mfplat: Read queue subscriber within the critical section.
[wine/zf.git] / dlls / d3dx9_36 / tests / mesh.c
blobe981f3623cec4cbece9e49c05f54de69f4de9089
1 /*
2 * Copyright 2008 David Adam
3 * Copyright 2008 Luis Busquets
4 * Copyright 2009 Henri Verbeet for CodeWeavers
5 * Copyright 2011 Michael Mc Donnell
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #define COBJMACROS
23 #include <stdio.h>
24 #include <float.h>
25 #include <limits.h>
26 #include "wine/test.h"
27 #include "d3dx9.h"
28 #include "initguid.h"
29 #include "rmxftmpl.h"
30 #include "rmxfguid.h"
32 /* Set the WINETEST_DEBUG environment variable to be greater than 1 for verbose
33 * function call traces of ID3DXAllocateHierarchy callbacks. */
34 #define TRACECALLBACK if(winetest_debug > 1) trace
36 #define admitted_error 0.0001f
38 #define compare_vertex_sizes(type, exp) \
39 got=D3DXGetFVFVertexSize(type); \
40 ok(got==exp, "Expected: %d, Got: %d\n", exp, got);
42 #define compare_float(got, exp) \
43 do { \
44 float _got = (got); \
45 float _exp = (exp); \
46 ok(_got == _exp, "Expected: %g, Got: %g\n", _exp, _got); \
47 } while (0)
49 static BOOL compare(FLOAT u, FLOAT v)
51 return (fabs(u-v) < admitted_error);
54 static BOOL compare_vec3(D3DXVECTOR3 u, D3DXVECTOR3 v)
56 return ( compare(u.x, v.x) && compare(u.y, v.y) && compare(u.z, v.z) );
59 static BOOL compare_vec4(D3DXVECTOR4 u, D3DXVECTOR4 v)
61 return compare(u.x, v.x) && compare(u.y, v.y) && compare(u.z, v.z) && compare(u.w, v.w);
64 #define check_floats(got, exp, dim) check_floats_(__LINE__, "", got, exp, dim)
65 static void check_floats_(int line, const char *prefix, const float *got, const float *exp, int dim)
67 int i;
68 char exp_buffer[256] = "";
69 char got_buffer[256] = "";
70 char *exp_buffer_ptr = exp_buffer;
71 char *got_buffer_ptr = got_buffer;
72 BOOL equal = TRUE;
74 for (i = 0; i < dim; i++) {
75 if (i) {
76 exp_buffer_ptr += sprintf(exp_buffer_ptr, ", ");
77 got_buffer_ptr += sprintf(got_buffer_ptr, ", ");
79 equal = equal && compare(*exp, *got);
80 exp_buffer_ptr += sprintf(exp_buffer_ptr, "%g", *exp);
81 got_buffer_ptr += sprintf(got_buffer_ptr, "%g", *got);
82 exp++; got++;
84 ok_(__FILE__,line)(equal, "%sExpected (%s), got (%s)", prefix, exp_buffer, got_buffer);
87 struct vertex
89 D3DXVECTOR3 position;
90 D3DXVECTOR3 normal;
93 typedef WORD face[3];
95 static BOOL compare_face(face a, face b)
97 return (a[0]==b[0] && a[1] == b[1] && a[2] == b[2]);
100 struct test_context
102 HWND hwnd;
103 IDirect3D9 *d3d;
104 IDirect3DDevice9 *device;
107 /* Initializes a test context struct. Use it to initialize DirectX.
109 * Returns NULL if an error occurred.
111 static struct test_context *new_test_context(void)
113 HRESULT hr;
114 HWND hwnd = NULL;
115 IDirect3D9 *d3d = NULL;
116 IDirect3DDevice9 *device = NULL;
117 D3DPRESENT_PARAMETERS d3dpp = {0};
118 struct test_context *test_context;
120 if (!(hwnd = CreateWindowA("static", "d3dx9_test", WS_OVERLAPPEDWINDOW, 0, 0,
121 640, 480, NULL, NULL, NULL, NULL)))
123 skip("Couldn't create application window\n");
124 goto error;
127 d3d = Direct3DCreate9(D3D_SDK_VERSION);
128 if (!d3d)
130 skip("Couldn't create IDirect3D9 object\n");
131 goto error;
134 memset(&d3dpp, 0, sizeof(d3dpp));
135 d3dpp.Windowed = TRUE;
136 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
137 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
138 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device);
139 if (FAILED(hr))
141 skip("Couldn't create IDirect3DDevice9 object %#x\n", hr);
142 goto error;
145 test_context = HeapAlloc(GetProcessHeap(), 0, sizeof(*test_context));
146 if (!test_context)
148 skip("Couldn't allocate memory for test_context\n");
149 goto error;
151 test_context->hwnd = hwnd;
152 test_context->d3d = d3d;
153 test_context->device = device;
155 return test_context;
157 error:
158 if (device)
159 IDirect3DDevice9_Release(device);
161 if (d3d)
162 IDirect3D9_Release(d3d);
164 if (hwnd)
165 DestroyWindow(hwnd);
167 return NULL;
170 static void free_test_context(struct test_context *test_context)
172 if (!test_context)
173 return;
175 if (test_context->device)
176 IDirect3DDevice9_Release(test_context->device);
178 if (test_context->d3d)
179 IDirect3D9_Release(test_context->d3d);
181 if (test_context->hwnd)
182 DestroyWindow(test_context->hwnd);
184 HeapFree(GetProcessHeap(), 0, test_context);
187 struct mesh
189 DWORD number_of_vertices;
190 struct vertex *vertices;
192 DWORD number_of_faces;
193 face *faces;
195 DWORD fvf;
196 UINT vertex_size;
199 static void free_mesh(struct mesh *mesh)
201 HeapFree(GetProcessHeap(), 0, mesh->faces);
202 HeapFree(GetProcessHeap(), 0, mesh->vertices);
205 static BOOL new_mesh(struct mesh *mesh, DWORD number_of_vertices, DWORD number_of_faces)
207 mesh->vertices = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, number_of_vertices * sizeof(*mesh->vertices));
208 if (!mesh->vertices)
210 return FALSE;
212 mesh->number_of_vertices = number_of_vertices;
214 mesh->faces = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, number_of_faces * sizeof(*mesh->faces));
215 if (!mesh->faces)
217 HeapFree(GetProcessHeap(), 0, mesh->vertices);
218 return FALSE;
220 mesh->number_of_faces = number_of_faces;
222 return TRUE;
225 static void compare_mesh(const char *name, ID3DXMesh *d3dxmesh, struct mesh *mesh)
227 HRESULT hr;
228 DWORD number_of_vertices, number_of_faces;
229 IDirect3DVertexBuffer9 *vertex_buffer;
230 IDirect3DIndexBuffer9 *index_buffer;
231 D3DVERTEXBUFFER_DESC vertex_buffer_description;
232 D3DINDEXBUFFER_DESC index_buffer_description;
233 struct vertex *vertices;
234 face *faces;
235 int expected, i;
237 number_of_vertices = d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh);
238 ok(number_of_vertices == mesh->number_of_vertices, "Test %s, result %u, expected %d\n",
239 name, number_of_vertices, mesh->number_of_vertices);
241 number_of_faces = d3dxmesh->lpVtbl->GetNumFaces(d3dxmesh);
242 ok(number_of_faces == mesh->number_of_faces, "Test %s, result %u, expected %d\n",
243 name, number_of_faces, mesh->number_of_faces);
245 /* vertex buffer */
246 hr = d3dxmesh->lpVtbl->GetVertexBuffer(d3dxmesh, &vertex_buffer);
247 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
249 if (hr != D3D_OK)
251 skip("Couldn't get vertex buffer\n");
253 else
255 hr = IDirect3DVertexBuffer9_GetDesc(vertex_buffer, &vertex_buffer_description);
256 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
258 if (hr != D3D_OK)
260 skip("Couldn't get vertex buffer description\n");
262 else
264 ok(vertex_buffer_description.Format == D3DFMT_VERTEXDATA, "Test %s, result %x, expected %x (D3DFMT_VERTEXDATA)\n",
265 name, vertex_buffer_description.Format, D3DFMT_VERTEXDATA);
266 ok(vertex_buffer_description.Type == D3DRTYPE_VERTEXBUFFER, "Test %s, result %x, expected %x (D3DRTYPE_VERTEXBUFFER)\n",
267 name, vertex_buffer_description.Type, D3DRTYPE_VERTEXBUFFER);
268 ok(vertex_buffer_description.Usage == 0, "Test %s, result %x, expected %x\n", name, vertex_buffer_description.Usage, 0);
269 ok(vertex_buffer_description.Pool == D3DPOOL_MANAGED, "Test %s, result %x, expected %x (D3DPOOL_MANAGED)\n",
270 name, vertex_buffer_description.Pool, D3DPOOL_MANAGED);
271 ok(vertex_buffer_description.FVF == mesh->fvf, "Test %s, result %x, expected %x\n",
272 name, vertex_buffer_description.FVF, mesh->fvf);
273 if (mesh->fvf == 0)
275 expected = number_of_vertices * mesh->vertex_size;
277 else
279 expected = number_of_vertices * D3DXGetFVFVertexSize(mesh->fvf);
281 ok(vertex_buffer_description.Size == expected, "Test %s, result %x, expected %x\n",
282 name, vertex_buffer_description.Size, expected);
285 /* specify offset and size to avoid potential overruns */
286 hr = IDirect3DVertexBuffer9_Lock(vertex_buffer, 0, number_of_vertices * sizeof(D3DXVECTOR3) * 2,
287 (void **)&vertices, D3DLOCK_DISCARD);
288 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
290 if (hr != D3D_OK)
292 skip("Couldn't lock vertex buffer\n");
294 else
296 for (i = 0; i < number_of_vertices; i++)
298 ok(compare_vec3(vertices[i].position, mesh->vertices[i].position),
299 "Test %s, vertex position %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i,
300 vertices[i].position.x, vertices[i].position.y, vertices[i].position.z,
301 mesh->vertices[i].position.x, mesh->vertices[i].position.y, mesh->vertices[i].position.z);
302 ok(compare_vec3(vertices[i].normal, mesh->vertices[i].normal),
303 "Test %s, vertex normal %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i,
304 vertices[i].normal.x, vertices[i].normal.y, vertices[i].normal.z,
305 mesh->vertices[i].normal.x, mesh->vertices[i].normal.y, mesh->vertices[i].normal.z);
308 IDirect3DVertexBuffer9_Unlock(vertex_buffer);
311 IDirect3DVertexBuffer9_Release(vertex_buffer);
314 /* index buffer */
315 hr = d3dxmesh->lpVtbl->GetIndexBuffer(d3dxmesh, &index_buffer);
316 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
318 if (!index_buffer)
320 skip("Couldn't get index buffer\n");
322 else
324 hr = IDirect3DIndexBuffer9_GetDesc(index_buffer, &index_buffer_description);
325 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
327 if (hr != D3D_OK)
329 skip("Couldn't get index buffer description\n");
331 else
333 ok(index_buffer_description.Format == D3DFMT_INDEX16, "Test %s, result %x, expected %x (D3DFMT_INDEX16)\n",
334 name, index_buffer_description.Format, D3DFMT_INDEX16);
335 ok(index_buffer_description.Type == D3DRTYPE_INDEXBUFFER, "Test %s, result %x, expected %x (D3DRTYPE_INDEXBUFFER)\n",
336 name, index_buffer_description.Type, D3DRTYPE_INDEXBUFFER);
337 ok(index_buffer_description.Usage == 0, "Test %s, result %#x, expected %#x.\n",
338 name, index_buffer_description.Usage, 0);
339 ok(index_buffer_description.Pool == D3DPOOL_MANAGED, "Test %s, result %x, expected %x (D3DPOOL_MANAGED)\n",
340 name, index_buffer_description.Pool, D3DPOOL_MANAGED);
341 expected = number_of_faces * sizeof(WORD) * 3;
342 ok(index_buffer_description.Size == expected, "Test %s, result %x, expected %x\n",
343 name, index_buffer_description.Size, expected);
346 /* specify offset and size to avoid potential overruns */
347 hr = IDirect3DIndexBuffer9_Lock(index_buffer, 0, number_of_faces * sizeof(WORD) * 3,
348 (void **)&faces, D3DLOCK_DISCARD);
349 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
351 if (hr != D3D_OK)
353 skip("Couldn't lock index buffer\n");
355 else
357 for (i = 0; i < number_of_faces; i++)
359 ok(compare_face(faces[i], mesh->faces[i]),
360 "Test %s, face %d, result (%u, %u, %u), expected (%u, %u, %u)\n", name, i,
361 faces[i][0], faces[i][1], faces[i][2],
362 mesh->faces[i][0], mesh->faces[i][1], mesh->faces[i][2]);
365 IDirect3DIndexBuffer9_Unlock(index_buffer);
368 IDirect3DIndexBuffer9_Release(index_buffer);
372 static void D3DXBoundProbeTest(void)
374 BOOL result;
375 D3DXVECTOR3 bottom_point, center, top_point, raydirection, rayposition;
376 FLOAT radius;
378 /*____________Test the Box case___________________________*/
379 bottom_point.x = -3.0f; bottom_point.y = -2.0f; bottom_point.z = -1.0f;
380 top_point.x = 7.0f; top_point.y = 8.0f; top_point.z = 9.0f;
382 raydirection.x = -4.0f; raydirection.y = -5.0f; raydirection.z = -6.0f;
383 rayposition.x = 5.0f; rayposition.y = 5.0f; rayposition.z = 11.0f;
384 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection);
385 ok(result == TRUE, "expected TRUE, received FALSE\n");
387 raydirection.x = 4.0f; raydirection.y = 5.0f; raydirection.z = 6.0f;
388 rayposition.x = 5.0f; rayposition.y = 5.0f; rayposition.z = 11.0f;
389 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection);
390 ok(result == FALSE, "expected FALSE, received TRUE\n");
392 rayposition.x = -4.0f; rayposition.y = 1.0f; rayposition.z = -2.0f;
393 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection);
394 ok(result == TRUE, "expected TRUE, received FALSE\n");
396 bottom_point.x = 1.0f; bottom_point.y = 0.0f; bottom_point.z = 0.0f;
397 top_point.x = 1.0f; top_point.y = 0.0f; top_point.z = 0.0f;
398 rayposition.x = 0.0f; rayposition.y = 1.0f; rayposition.z = 0.0f;
399 raydirection.x = 0.0f; raydirection.y = 3.0f; raydirection.z = 0.0f;
400 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection);
401 ok(result == FALSE, "expected FALSE, received TRUE\n");
403 bottom_point.x = 1.0f; bottom_point.y = 2.0f; bottom_point.z = 3.0f;
404 top_point.x = 10.0f; top_point.y = 15.0f; top_point.z = 20.0f;
406 raydirection.x = 7.0f; raydirection.y = 8.0f; raydirection.z = 9.0f;
407 rayposition.x = 3.0f; rayposition.y = 7.0f; rayposition.z = -6.0f;
408 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection);
409 ok(result == TRUE, "expected TRUE, received FALSE\n");
411 bottom_point.x = 0.0f; bottom_point.y = 0.0f; bottom_point.z = 0.0f;
412 top_point.x = 1.0f; top_point.y = 1.0f; top_point.z = 1.0f;
414 raydirection.x = 0.0f; raydirection.y = 1.0f; raydirection.z = .0f;
415 rayposition.x = -3.0f; rayposition.y = 0.0f; rayposition.z = 0.0f;
416 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection);
417 ok(result == FALSE, "expected FALSE, received TRUE\n");
419 raydirection.x = 1.0f; raydirection.y = 0.0f; raydirection.z = .0f;
420 rayposition.x = -3.0f; rayposition.y = 0.0f; rayposition.z = 0.0f;
421 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection);
422 ok(result == TRUE, "expected TRUE, received FALSE\n");
424 /*____________Test the Sphere case________________________*/
425 radius = sqrt(77.0f);
426 center.x = 1.0f; center.y = 2.0f; center.z = 3.0f;
427 raydirection.x = 2.0f; raydirection.y = -4.0f; raydirection.z = 2.0f;
428 rayposition.x = 5.0f; rayposition.y = 5.0f; rayposition.z = 9.0f;
429 result = D3DXSphereBoundProbe(&center, radius, &rayposition, &raydirection);
430 ok(result == TRUE, "Got unexpected result %#x.\n", result);
432 rayposition.x = 45.0f; rayposition.y = -75.0f; rayposition.z = 49.0f;
433 result = D3DXSphereBoundProbe(&center, radius, &rayposition, &raydirection);
434 ok(result == FALSE, "Got unexpected result %#x.\n", result);
436 raydirection.x = -2.0f; raydirection.y = 4.0f; raydirection.z = -2.0f;
437 result = D3DXSphereBoundProbe(&center, radius, &rayposition, &raydirection);
438 ok(result == TRUE, "Got unexpected result %#x.\n", result);
440 rayposition.x = 5.0f; rayposition.y = 11.0f; rayposition.z = 9.0f;
441 result = D3DXSphereBoundProbe(&center, radius, &rayposition, &raydirection);
442 ok(result == FALSE, "Got unexpected result %#x.\n", result);
444 raydirection.x = 2.0f; raydirection.y = -4.0f; raydirection.z = 2.0f;
445 result = D3DXSphereBoundProbe(&center, radius, &rayposition, &raydirection);
446 ok(result == FALSE, "Got unexpected result %#x.\n", result);
448 radius = 1.0f;
449 rayposition.x = 2.0f; rayposition.y = 2.0f; rayposition.z = 3.0f;
450 result = D3DXSphereBoundProbe(&center, radius, &rayposition, &raydirection);
451 ok(result == FALSE, "Got unexpected result %#x.\n", result);
453 raydirection.x = 0.0f; raydirection.y = 0.0f; raydirection.z = 1.0f;
454 result = D3DXSphereBoundProbe(&center, radius, &rayposition, &raydirection);
455 ok(result == TRUE, "Got unexpected result %#x.\n", result);
457 if (0)
459 /* All these crash on native. */
460 D3DXSphereBoundProbe(&center, radius, &rayposition, NULL);
461 D3DXSphereBoundProbe(&center, radius, NULL, &raydirection);
462 D3DXSphereBoundProbe(NULL, radius, &rayposition, &raydirection);
466 static void D3DXComputeBoundingBoxTest(void)
468 D3DXVECTOR3 exp_max, exp_min, got_max, got_min, vertex[5];
469 HRESULT hr;
471 vertex[0].x = 1.0f; vertex[0].y = 1.0f; vertex[0].z = 1.0f;
472 vertex[1].x = 1.0f; vertex[1].y = 1.0f; vertex[1].z = 1.0f;
473 vertex[2].x = 1.0f; vertex[2].y = 1.0f; vertex[2].z = 1.0f;
474 vertex[3].x = 1.0f; vertex[3].y = 1.0f; vertex[3].z = 1.0f;
475 vertex[4].x = 9.0f; vertex[4].y = 9.0f; vertex[4].z = 9.0f;
477 exp_min.x = 1.0f; exp_min.y = 1.0f; exp_min.z = 1.0f;
478 exp_max.x = 9.0f; exp_max.y = 9.0f; exp_max.z = 9.0f;
480 hr = D3DXComputeBoundingBox(&vertex[3],2,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_min,&got_max);
482 ok( hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
483 ok( compare_vec3(exp_min,got_min), "Expected min: (%f, %f, %f), got: (%f, %f, %f)\n", exp_min.x,exp_min.y,exp_min.z,got_min.x,got_min.y,got_min.z);
484 ok( compare_vec3(exp_max,got_max), "Expected max: (%f, %f, %f), got: (%f, %f, %f)\n", exp_max.x,exp_max.y,exp_max.z,got_max.x,got_max.y,got_max.z);
486 /*________________________*/
488 vertex[0].x = 2.0f; vertex[0].y = 5.9f; vertex[0].z = -1.2f;
489 vertex[1].x = -1.87f; vertex[1].y = 7.9f; vertex[1].z = 7.4f;
490 vertex[2].x = 7.43f; vertex[2].y = -0.9f; vertex[2].z = 11.9f;
491 vertex[3].x = -6.92f; vertex[3].y = 6.3f; vertex[3].z = -3.8f;
492 vertex[4].x = 11.4f; vertex[4].y = -8.1f; vertex[4].z = 4.5f;
494 exp_min.x = -6.92f; exp_min.y = -8.1f; exp_min.z = -3.80f;
495 exp_max.x = 11.4f; exp_max.y = 7.90f; exp_max.z = 11.9f;
497 hr = D3DXComputeBoundingBox(&vertex[0],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_min,&got_max);
499 ok( hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
500 ok( compare_vec3(exp_min,got_min), "Expected min: (%f, %f, %f), got: (%f, %f, %f)\n", exp_min.x,exp_min.y,exp_min.z,got_min.x,got_min.y,got_min.z);
501 ok( compare_vec3(exp_max,got_max), "Expected max: (%f, %f, %f), got: (%f, %f, %f)\n", exp_max.x,exp_max.y,exp_max.z,got_max.x,got_max.y,got_max.z);
503 /*________________________*/
505 vertex[0].x = 2.0f; vertex[0].y = 5.9f; vertex[0].z = -1.2f;
506 vertex[1].x = -1.87f; vertex[1].y = 7.9f; vertex[1].z = 7.4f;
507 vertex[2].x = 7.43f; vertex[2].y = -0.9f; vertex[2].z = 11.9f;
508 vertex[3].x = -6.92f; vertex[3].y = 6.3f; vertex[3].z = -3.8f;
509 vertex[4].x = 11.4f; vertex[4].y = -8.1f; vertex[4].z = 4.5f;
511 exp_min.x = -6.92f; exp_min.y = -0.9f; exp_min.z = -3.8f;
512 exp_max.x = 7.43f; exp_max.y = 7.90f; exp_max.z = 11.9f;
514 hr = D3DXComputeBoundingBox(&vertex[0],4,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_min,&got_max);
516 ok( hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
517 ok( compare_vec3(exp_min,got_min), "Expected min: (%f, %f, %f), got: (%f, %f, %f)\n", exp_min.x,exp_min.y,exp_min.z,got_min.x,got_min.y,got_min.z);
518 ok( compare_vec3(exp_max,got_max), "Expected max: (%f, %f, %f), got: (%f, %f, %f)\n", exp_max.x,exp_max.y,exp_max.z,got_max.x,got_max.y,got_max.z);
520 /*________________________*/
521 hr = D3DXComputeBoundingBox(NULL,5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_min,&got_max);
522 ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
524 /*________________________*/
525 hr = D3DXComputeBoundingBox(&vertex[3],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),NULL,&got_max);
526 ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
528 /*________________________*/
529 hr = D3DXComputeBoundingBox(&vertex[3],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_min,NULL);
530 ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
533 static void D3DXComputeBoundingSphereTest(void)
535 D3DXVECTOR3 exp_cen, got_cen, vertex[5];
536 FLOAT exp_rad, got_rad;
537 HRESULT hr;
539 vertex[0].x = 1.0f; vertex[0].y = 1.0f; vertex[0].z = 1.0f;
540 vertex[1].x = 1.0f; vertex[1].y = 1.0f; vertex[1].z = 1.0f;
541 vertex[2].x = 1.0f; vertex[2].y = 1.0f; vertex[2].z = 1.0f;
542 vertex[3].x = 1.0f; vertex[3].y = 1.0f; vertex[3].z = 1.0f;
543 vertex[4].x = 9.0f; vertex[4].y = 9.0f; vertex[4].z = 9.0f;
545 exp_rad = 6.928203f;
546 exp_cen.x = 5.0; exp_cen.y = 5.0; exp_cen.z = 5.0;
548 hr = D3DXComputeBoundingSphere(&vertex[3],2,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_cen,&got_rad);
550 ok( hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
551 ok( compare(exp_rad, got_rad), "Expected radius: %f, got radius: %f\n", exp_rad, got_rad);
552 ok( compare_vec3(exp_cen,got_cen), "Expected center: (%f, %f, %f), got center: (%f, %f, %f)\n", exp_cen.x,exp_cen.y,exp_cen.z,got_cen.x,got_cen.y,got_cen.z);
554 /*________________________*/
556 vertex[0].x = 2.0f; vertex[0].y = 5.9f; vertex[0].z = -1.2f;
557 vertex[1].x = -1.87f; vertex[1].y = 7.9f; vertex[1].z = 7.4f;
558 vertex[2].x = 7.43f; vertex[2].y = -0.9f; vertex[2].z = 11.9f;
559 vertex[3].x = -6.92f; vertex[3].y = 6.3f; vertex[3].z = -3.8f;
560 vertex[4].x = 11.4f; vertex[4].y = -8.1f; vertex[4].z = 4.5f;
562 exp_rad = 13.707883f;
563 exp_cen.x = 2.408f; exp_cen.y = 2.22f; exp_cen.z = 3.76f;
565 hr = D3DXComputeBoundingSphere(&vertex[0],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_cen,&got_rad);
567 ok( hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
568 ok( compare(exp_rad, got_rad), "Expected radius: %f, got radius: %f\n", exp_rad, got_rad);
569 ok( compare_vec3(exp_cen,got_cen), "Expected center: (%f, %f, %f), got center: (%f, %f, %f)\n", exp_cen.x,exp_cen.y,exp_cen.z,got_cen.x,got_cen.y,got_cen.z);
571 /*________________________*/
572 hr = D3DXComputeBoundingSphere(NULL,5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_cen,&got_rad);
573 ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
575 /*________________________*/
576 hr = D3DXComputeBoundingSphere(&vertex[3],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),NULL,&got_rad);
577 ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
579 /*________________________*/
580 hr = D3DXComputeBoundingSphere(&vertex[3],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_cen,NULL);
581 ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
584 static void print_elements(const D3DVERTEXELEMENT9 *elements)
586 D3DVERTEXELEMENT9 last = D3DDECL_END();
587 const D3DVERTEXELEMENT9 *ptr = elements;
588 int count = 0;
590 while (memcmp(ptr, &last, sizeof(D3DVERTEXELEMENT9)))
592 trace(
593 "[Element %d] Stream = %d, Offset = %d, Type = %d, Method = %d, Usage = %d, UsageIndex = %d\n",
594 count, ptr->Stream, ptr->Offset, ptr->Type, ptr->Method, ptr->Usage, ptr->UsageIndex);
595 ptr++;
596 count++;
600 static void compare_elements(const D3DVERTEXELEMENT9 *elements, const D3DVERTEXELEMENT9 *expected_elements,
601 unsigned int line, unsigned int test_id)
603 D3DVERTEXELEMENT9 last = D3DDECL_END();
604 unsigned int i;
606 for (i = 0; i < MAX_FVF_DECL_SIZE; i++)
608 int end1 = memcmp(&elements[i], &last, sizeof(last));
609 int end2 = memcmp(&expected_elements[i], &last, sizeof(last));
610 int status;
612 if (!end1 && !end2) break;
614 status = !end1 ^ !end2;
615 ok(!status, "Line %u, test %u: Mismatch in size, test declaration is %s than expected.\n",
616 line, test_id, end1 ? "shorter" : "longer");
617 if (status)
619 print_elements(elements);
620 break;
623 status = memcmp(&elements[i], &expected_elements[i], sizeof(D3DVERTEXELEMENT9));
624 ok(!status, "Line %u, test %u: Mismatch in element %u.\n", line, test_id, i);
625 if (status)
627 print_elements(elements);
628 break;
633 static void test_fvf_to_decl(DWORD test_fvf, const D3DVERTEXELEMENT9 expected_elements[],
634 HRESULT expected_hr, unsigned int line, unsigned int test_id)
636 HRESULT hr;
637 D3DVERTEXELEMENT9 decl[MAX_FVF_DECL_SIZE];
639 hr = D3DXDeclaratorFromFVF(test_fvf, decl);
640 ok(hr == expected_hr,
641 "Line %u, test %u: D3DXDeclaratorFromFVF returned %#x, expected %#x.\n",
642 line, test_id, hr, expected_hr);
643 if (SUCCEEDED(hr)) compare_elements(decl, expected_elements, line, test_id);
646 static void test_decl_to_fvf(const D3DVERTEXELEMENT9 *decl, DWORD expected_fvf,
647 HRESULT expected_hr, unsigned int line, unsigned int test_id)
649 HRESULT hr;
650 DWORD result_fvf = 0xdeadbeef;
652 hr = D3DXFVFFromDeclarator(decl, &result_fvf);
653 ok(hr == expected_hr,
654 "Line %u, test %u: D3DXFVFFromDeclarator returned %#x, expected %#x.\n",
655 line, test_id, hr, expected_hr);
656 if (SUCCEEDED(hr))
658 ok(expected_fvf == result_fvf, "Line %u, test %u: Got FVF %#x, expected %#x.\n",
659 line, test_id, result_fvf, expected_fvf);
663 static void test_fvf_decl_conversion(void)
665 static const struct
667 D3DVERTEXELEMENT9 decl[MAXD3DDECLLENGTH + 1];
668 DWORD fvf;
670 test_data[] =
673 D3DDECL_END(),
674 }, 0},
676 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
677 D3DDECL_END(),
678 }, D3DFVF_XYZ},
680 {0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITIONT, 0},
681 D3DDECL_END(),
682 }, D3DFVF_XYZRHW},
684 {0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITIONT, 0},
685 D3DDECL_END(),
686 }, D3DFVF_XYZRHW},
688 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
689 {0, 12, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
690 D3DDECL_END(),
691 }, D3DFVF_XYZB1},
693 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
694 {0, 12, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
695 D3DDECL_END(),
696 }, D3DFVF_XYZB1 | D3DFVF_LASTBETA_UBYTE4},
698 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
699 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
700 D3DDECL_END(),
701 }, D3DFVF_XYZB1 | D3DFVF_LASTBETA_D3DCOLOR},
703 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
704 {0, 12, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
705 D3DDECL_END(),
706 }, D3DFVF_XYZB2},
708 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
709 {0, 12, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
710 {0, 16, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
711 D3DDECL_END(),
712 }, D3DFVF_XYZB2 | D3DFVF_LASTBETA_UBYTE4},
714 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
715 {0, 12, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
716 {0, 16, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
717 D3DDECL_END(),
718 }, D3DFVF_XYZB2 | D3DFVF_LASTBETA_D3DCOLOR},
720 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
721 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
722 D3DDECL_END(),
723 }, D3DFVF_XYZB3},
725 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
726 {0, 12, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
727 {0, 20, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
728 D3DDECL_END(),
729 }, D3DFVF_XYZB3 | D3DFVF_LASTBETA_UBYTE4},
731 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
732 {0, 12, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
733 {0, 20, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
734 D3DDECL_END(),
735 }, D3DFVF_XYZB3 | D3DFVF_LASTBETA_D3DCOLOR},
737 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
738 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
739 D3DDECL_END(),
740 }, D3DFVF_XYZB4},
742 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
743 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
744 {0, 24, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
745 D3DDECL_END(),
746 }, D3DFVF_XYZB4 | D3DFVF_LASTBETA_UBYTE4},
748 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
749 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
750 {0, 24, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
751 D3DDECL_END(),
752 }, D3DFVF_XYZB4 | D3DFVF_LASTBETA_D3DCOLOR},
754 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
755 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
756 {0, 28, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
757 D3DDECL_END(),
758 }, D3DFVF_XYZB5 | D3DFVF_LASTBETA_UBYTE4},
760 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
761 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
762 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
763 D3DDECL_END(),
764 }, D3DFVF_XYZB5 | D3DFVF_LASTBETA_D3DCOLOR},
766 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
767 D3DDECL_END(),
768 }, D3DFVF_NORMAL},
770 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
771 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
772 D3DDECL_END(),
773 }, D3DFVF_NORMAL | D3DFVF_DIFFUSE},
775 {0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_PSIZE, 0},
776 D3DDECL_END(),
777 }, D3DFVF_PSIZE},
779 {0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
780 D3DDECL_END(),
781 }, D3DFVF_DIFFUSE},
783 {0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1},
784 D3DDECL_END(),
785 }, D3DFVF_SPECULAR},
786 /* Make sure textures of different sizes work. */
788 {0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
789 D3DDECL_END(),
790 }, D3DFVF_TEXCOORDSIZE1(0) | D3DFVF_TEX1},
792 {0, 0, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 0},
793 D3DDECL_END(),
794 }, D3DFVF_TEXCOORDSIZE2(0) | D3DFVF_TEX1},
796 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 0},
797 D3DDECL_END(),
798 }, D3DFVF_TEXCOORDSIZE3(0) | D3DFVF_TEX1},
800 {0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 0},
801 D3DDECL_END(),
802 }, D3DFVF_TEXCOORDSIZE4(0) | D3DFVF_TEX1},
803 /* Make sure the TEXCOORD index works correctly - try several textures. */
805 {0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
806 {0, 4, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 1},
807 {0, 16, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 2},
808 {0, 24, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 3},
809 D3DDECL_END(),
810 }, D3DFVF_TEX4 | D3DFVF_TEXCOORDSIZE1(0) | D3DFVF_TEXCOORDSIZE3(1)
811 | D3DFVF_TEXCOORDSIZE2(2) | D3DFVF_TEXCOORDSIZE4(3)},
812 /* Now try some combination tests. */
814 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
815 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
816 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
817 {0, 32, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1},
818 {0, 36, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 0},
819 {0, 44, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 1},
820 D3DDECL_END(),
821 }, D3DFVF_XYZB4 | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_TEX2
822 | D3DFVF_TEXCOORDSIZE2(0) | D3DFVF_TEXCOORDSIZE3(1)},
824 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
825 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
826 {0, 24, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_PSIZE, 0},
827 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1},
828 {0, 32, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
829 {0, 36, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 1},
830 D3DDECL_END(),
831 }, D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_PSIZE | D3DFVF_SPECULAR | D3DFVF_TEX2
832 | D3DFVF_TEXCOORDSIZE1(0) | D3DFVF_TEXCOORDSIZE4(1)},
834 unsigned int i;
836 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
838 test_decl_to_fvf(test_data[i].decl, test_data[i].fvf, D3D_OK, __LINE__, i);
839 test_fvf_to_decl(test_data[i].fvf, test_data[i].decl, D3D_OK, __LINE__, i);
842 /* Usage indices for position and normal are apparently ignored. */
844 const D3DVERTEXELEMENT9 decl[] =
846 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 1},
847 D3DDECL_END(),
849 test_decl_to_fvf(decl, D3DFVF_XYZ, D3D_OK, __LINE__, 0);
852 const D3DVERTEXELEMENT9 decl[] =
854 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 1},
855 D3DDECL_END(),
857 test_decl_to_fvf(decl, D3DFVF_NORMAL, D3D_OK, __LINE__, 0);
859 /* D3DFVF_LASTBETA_UBYTE4 and D3DFVF_LASTBETA_D3DCOLOR are ignored if
860 * there are no blend matrices. */
862 const D3DVERTEXELEMENT9 decl[] =
864 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
865 D3DDECL_END(),
867 test_fvf_to_decl(D3DFVF_XYZ | D3DFVF_LASTBETA_UBYTE4, decl, D3D_OK, __LINE__, 0);
870 const D3DVERTEXELEMENT9 decl[] =
872 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
873 D3DDECL_END(),
875 test_fvf_to_decl(D3DFVF_XYZ | D3DFVF_LASTBETA_D3DCOLOR, decl, D3D_OK, __LINE__, 0);
877 /* D3DFVF_LASTBETA_UBYTE4 takes precedence over D3DFVF_LASTBETA_D3DCOLOR. */
879 const D3DVERTEXELEMENT9 decl[] =
881 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
882 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
883 {0, 28, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
884 D3DDECL_END(),
886 test_fvf_to_decl(D3DFVF_XYZB5 | D3DFVF_LASTBETA_D3DCOLOR | D3DFVF_LASTBETA_UBYTE4,
887 decl, D3D_OK, __LINE__, 0);
889 /* These are supposed to fail, both ways. */
891 const D3DVERTEXELEMENT9 decl[] =
893 {0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITION, 0},
894 D3DDECL_END(),
896 test_decl_to_fvf(decl, D3DFVF_XYZW, D3DERR_INVALIDCALL, __LINE__, 0);
897 test_fvf_to_decl(D3DFVF_XYZW, decl, D3DERR_INVALIDCALL, __LINE__, 0);
900 const D3DVERTEXELEMENT9 decl[] =
902 {0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITION, 0},
903 {0, 16, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
904 D3DDECL_END(),
906 test_decl_to_fvf(decl, D3DFVF_XYZW | D3DFVF_NORMAL, D3DERR_INVALIDCALL, __LINE__, 0);
907 test_fvf_to_decl(D3DFVF_XYZW | D3DFVF_NORMAL, decl, D3DERR_INVALIDCALL, __LINE__, 0);
910 const D3DVERTEXELEMENT9 decl[] =
912 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
913 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
914 {0, 28, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDINDICES, 0},
915 D3DDECL_END(),
917 test_decl_to_fvf(decl, D3DFVF_XYZB5, D3DERR_INVALIDCALL, __LINE__, 0);
918 test_fvf_to_decl(D3DFVF_XYZB5, decl, D3DERR_INVALIDCALL, __LINE__, 0);
920 /* Test a declaration that can't be converted to an FVF. */
922 const D3DVERTEXELEMENT9 decl[] =
924 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
925 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
926 {0, 24, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_PSIZE, 0},
927 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1},
928 {0, 32, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
929 /* 8 bytes padding */
930 {0, 44, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 1},
931 D3DDECL_END(),
933 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0);
935 /* Elements must be ordered by offset. */
937 const D3DVERTEXELEMENT9 decl[] =
939 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
940 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
941 D3DDECL_END(),
943 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0);
945 /* Basic tests for element order. */
947 const D3DVERTEXELEMENT9 decl[] =
949 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
950 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
951 {0, 16, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
952 D3DDECL_END(),
954 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0);
957 const D3DVERTEXELEMENT9 decl[] =
959 {0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
960 {0, 4, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
961 D3DDECL_END(),
963 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0);
966 const D3DVERTEXELEMENT9 decl[] =
968 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
969 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
970 D3DDECL_END(),
972 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0);
974 /* Textures must be ordered by texcoords. */
976 const D3DVERTEXELEMENT9 decl[] =
978 {0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
979 {0, 4, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 2},
980 {0, 16, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 1},
981 {0, 24, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 3},
982 D3DDECL_END(),
984 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0);
986 /* Duplicate elements are not allowed. */
988 const D3DVERTEXELEMENT9 decl[] =
990 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
991 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
992 {0, 16, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
993 D3DDECL_END(),
995 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0);
997 /* Invalid FVFs cannot be converted to a declarator. */
998 test_fvf_to_decl(0xdeadbeef, NULL, D3DERR_INVALIDCALL, __LINE__, 0);
1001 static void D3DXGetFVFVertexSizeTest(void)
1003 UINT got;
1005 compare_vertex_sizes (D3DFVF_XYZ, 12);
1007 compare_vertex_sizes (D3DFVF_XYZB3, 24);
1009 compare_vertex_sizes (D3DFVF_XYZB5, 32);
1011 compare_vertex_sizes (D3DFVF_XYZ | D3DFVF_NORMAL, 24);
1013 compare_vertex_sizes (D3DFVF_XYZ | D3DFVF_DIFFUSE, 16);
1015 compare_vertex_sizes (
1016 D3DFVF_XYZ |
1017 D3DFVF_TEX1 |
1018 D3DFVF_TEXCOORDSIZE1(0), 16);
1019 compare_vertex_sizes (
1020 D3DFVF_XYZ |
1021 D3DFVF_TEX2 |
1022 D3DFVF_TEXCOORDSIZE1(0) |
1023 D3DFVF_TEXCOORDSIZE1(1), 20);
1025 compare_vertex_sizes (
1026 D3DFVF_XYZ |
1027 D3DFVF_TEX1 |
1028 D3DFVF_TEXCOORDSIZE2(0), 20);
1030 compare_vertex_sizes (
1031 D3DFVF_XYZ |
1032 D3DFVF_TEX2 |
1033 D3DFVF_TEXCOORDSIZE2(0) |
1034 D3DFVF_TEXCOORDSIZE2(1), 28);
1036 compare_vertex_sizes (
1037 D3DFVF_XYZ |
1038 D3DFVF_TEX6 |
1039 D3DFVF_TEXCOORDSIZE2(0) |
1040 D3DFVF_TEXCOORDSIZE2(1) |
1041 D3DFVF_TEXCOORDSIZE2(2) |
1042 D3DFVF_TEXCOORDSIZE2(3) |
1043 D3DFVF_TEXCOORDSIZE2(4) |
1044 D3DFVF_TEXCOORDSIZE2(5), 60);
1046 compare_vertex_sizes (
1047 D3DFVF_XYZ |
1048 D3DFVF_TEX8 |
1049 D3DFVF_TEXCOORDSIZE2(0) |
1050 D3DFVF_TEXCOORDSIZE2(1) |
1051 D3DFVF_TEXCOORDSIZE2(2) |
1052 D3DFVF_TEXCOORDSIZE2(3) |
1053 D3DFVF_TEXCOORDSIZE2(4) |
1054 D3DFVF_TEXCOORDSIZE2(5) |
1055 D3DFVF_TEXCOORDSIZE2(6) |
1056 D3DFVF_TEXCOORDSIZE2(7), 76);
1058 compare_vertex_sizes (
1059 D3DFVF_XYZ |
1060 D3DFVF_TEX1 |
1061 D3DFVF_TEXCOORDSIZE3(0), 24);
1063 compare_vertex_sizes (
1064 D3DFVF_XYZ |
1065 D3DFVF_TEX4 |
1066 D3DFVF_TEXCOORDSIZE3(0) |
1067 D3DFVF_TEXCOORDSIZE3(1) |
1068 D3DFVF_TEXCOORDSIZE3(2) |
1069 D3DFVF_TEXCOORDSIZE3(3), 60);
1071 compare_vertex_sizes (
1072 D3DFVF_XYZ |
1073 D3DFVF_TEX1 |
1074 D3DFVF_TEXCOORDSIZE4(0), 28);
1076 compare_vertex_sizes (
1077 D3DFVF_XYZ |
1078 D3DFVF_TEX2 |
1079 D3DFVF_TEXCOORDSIZE4(0) |
1080 D3DFVF_TEXCOORDSIZE4(1), 44);
1082 compare_vertex_sizes (
1083 D3DFVF_XYZ |
1084 D3DFVF_TEX3 |
1085 D3DFVF_TEXCOORDSIZE4(0) |
1086 D3DFVF_TEXCOORDSIZE4(1) |
1087 D3DFVF_TEXCOORDSIZE4(2), 60);
1089 compare_vertex_sizes (
1090 D3DFVF_XYZB5 |
1091 D3DFVF_NORMAL |
1092 D3DFVF_DIFFUSE |
1093 D3DFVF_SPECULAR |
1094 D3DFVF_TEX8 |
1095 D3DFVF_TEXCOORDSIZE4(0) |
1096 D3DFVF_TEXCOORDSIZE4(1) |
1097 D3DFVF_TEXCOORDSIZE4(2) |
1098 D3DFVF_TEXCOORDSIZE4(3) |
1099 D3DFVF_TEXCOORDSIZE4(4) |
1100 D3DFVF_TEXCOORDSIZE4(5) |
1101 D3DFVF_TEXCOORDSIZE4(6) |
1102 D3DFVF_TEXCOORDSIZE4(7), 180);
1105 static void D3DXIntersectTriTest(void)
1107 BOOL exp_res, got_res;
1108 D3DXVECTOR3 position, ray, vertex[3];
1109 FLOAT exp_dist, got_dist, exp_u, got_u, exp_v, got_v;
1111 vertex[0].x = 1.0f; vertex[0].y = 0.0f; vertex[0].z = 0.0f;
1112 vertex[1].x = 2.0f; vertex[1].y = 0.0f; vertex[1].z = 0.0f;
1113 vertex[2].x = 1.0f; vertex[2].y = 1.0f; vertex[2].z = 0.0f;
1115 position.x = -14.5f; position.y = -23.75f; position.z = -32.0f;
1117 ray.x = 2.0f; ray.y = 3.0f; ray.z = 4.0f;
1119 exp_res = TRUE; exp_u = 0.5f; exp_v = 0.25f; exp_dist = 8.0f;
1121 got_res = D3DXIntersectTri(&vertex[0], &vertex[1], &vertex[2], &position, &ray, &got_u, &got_v, &got_dist);
1122 ok(got_res == exp_res, "Expected result %d, got %d.\n", exp_res, got_res);
1123 ok(compare(exp_u, got_u), "Expected u %f, got %f.\n", exp_u, got_u);
1124 ok(compare(exp_v, got_v), "Expected v %f, got %f.\n", exp_v, got_v);
1125 ok(compare(exp_dist, got_dist), "Expected distance %f, got %f.\n", exp_dist, got_dist);
1127 got_res = D3DXIntersectTri(&vertex[0], &vertex[1], &vertex[2], &position, &ray, NULL, NULL, NULL);
1128 ok(got_res == exp_res, "Expected result %d, got %d.\n", exp_res, got_res);
1130 vertex[2].x = 1.0f; vertex[2].y = 0.0f; vertex[2].z = 0.0f;
1131 vertex[1].x = 2.0f; vertex[1].y = 0.0f; vertex[1].z = 0.0f;
1132 vertex[0].x = 1.0f; vertex[0].y = 1.0f; vertex[0].z = 0.0f;
1134 got_u = got_v = got_dist = 0.0f;
1135 got_res = D3DXIntersectTri(&vertex[0], &vertex[1], &vertex[2], &position, &ray, &got_u, &got_v, &got_dist);
1136 ok(got_res == exp_res, "Expected result %d, got %d.\n", exp_res, got_res);
1137 ok(compare(exp_u, got_u), "Expected u %f, got %f.\n", exp_u, got_u);
1138 ok(compare(exp_v, got_v), "Expected v %f, got %f.\n", exp_v, got_v);
1139 ok(compare(exp_dist, got_dist), "Expected distance %f, got %f.\n", exp_dist, got_dist);
1141 vertex[2].x = 1.0f; vertex[2].y = 0.0f; vertex[2].z = 0.0f;
1142 vertex[1].x = 2.0f; vertex[1].y = 0.0f; vertex[1].z = -0.5f;
1143 vertex[0].x = 1.0f; vertex[0].y = 1.0f; vertex[0].z = -1.0f;
1144 exp_u = 0.375f;
1145 exp_v = 0.5625f;
1146 exp_dist = 7.9375f;
1147 got_u = got_v = got_dist = 0.0f;
1148 got_res = D3DXIntersectTri(&vertex[0], &vertex[1], &vertex[2], &position, &ray, &got_u, &got_v, &got_dist);
1149 ok(got_res == exp_res, "Expected result %d, got %d.\n", exp_res, got_res);
1150 ok(compare(exp_u, got_u), "Expected u %f, got %f.\n", exp_u, got_u);
1151 ok(compare(exp_v, got_v), "Expected v %f, got %f.\n", exp_v, got_v);
1152 ok(compare(exp_dist, got_dist), "Expected distance %f, got %f.\n", exp_dist, got_dist);
1155 /*Only positive ray is taken in account*/
1157 vertex[0].x = 1.0f; vertex[0].y = 0.0f; vertex[0].z = 0.0f;
1158 vertex[1].x = 2.0f; vertex[1].y = 0.0f; vertex[1].z = 0.0f;
1159 vertex[2].x = 1.0f; vertex[2].y = 1.0f; vertex[2].z = 0.0f;
1161 position.x = 17.5f; position.y = 24.25f; position.z = 32.0f;
1163 ray.x = 2.0f; ray.y = 3.0f; ray.z = 4.0f;
1165 exp_res = FALSE;
1167 got_res = D3DXIntersectTri(&vertex[0],&vertex[1],&vertex[2],&position,&ray,&got_u,&got_v,&got_dist);
1168 ok( got_res == exp_res, "Expected result = %d, got %d\n",exp_res,got_res);
1170 got_res = D3DXIntersectTri(&vertex[0], &vertex[1], &vertex[2], &position, &ray, NULL, NULL, NULL);
1171 ok(got_res == exp_res, "Expected result = %d, got %d\n", exp_res, got_res);
1173 /*Intersection between ray and triangle in a same plane is considered as empty*/
1175 vertex[0].x = 4.0f; vertex[0].y = 0.0f; vertex[0].z = 0.0f;
1176 vertex[1].x = 6.0f; vertex[1].y = 0.0f; vertex[1].z = 0.0f;
1177 vertex[2].x = 4.0f; vertex[2].y = 2.0f; vertex[2].z = 0.0f;
1179 position.x = 1.0f; position.y = 1.0f; position.z = 0.0f;
1181 ray.x = 1.0f; ray.y = 0.0f; ray.z = 0.0f;
1183 exp_res = FALSE;
1185 got_res = D3DXIntersectTri(&vertex[0],&vertex[1],&vertex[2],&position,&ray,&got_u,&got_v,&got_dist);
1186 ok( got_res == exp_res, "Expected result = %d, got %d\n",exp_res,got_res);
1188 got_res = D3DXIntersectTri(&vertex[0], &vertex[1], &vertex[2], &position, &ray, NULL, NULL, NULL);
1189 ok(got_res == exp_res, "Expected result = %d, got %d\n", exp_res, got_res);
1192 static void D3DXCreateMeshTest(void)
1194 HRESULT hr;
1195 IDirect3DDevice9 *device, *test_device;
1196 ID3DXMesh *d3dxmesh;
1197 int i, size;
1198 D3DVERTEXELEMENT9 test_decl[MAX_FVF_DECL_SIZE];
1199 DWORD options;
1200 struct mesh mesh;
1201 struct test_context *test_context;
1203 static const D3DVERTEXELEMENT9 decl1[] =
1205 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1206 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
1207 D3DDECL_END(),
1210 static const D3DVERTEXELEMENT9 decl2[] =
1212 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1213 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
1214 {0, 24, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_PSIZE, 0},
1215 {0, 28, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 1},
1216 {0, 32, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
1217 /* 8 bytes padding */
1218 {0, 44, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
1219 D3DDECL_END(),
1222 static const D3DVERTEXELEMENT9 decl3[] =
1224 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1225 {1, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
1226 D3DDECL_END(),
1229 hr = D3DXCreateMesh(0, 0, 0, NULL, NULL, NULL);
1230 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1232 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl1, NULL, &d3dxmesh);
1233 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1235 test_context = new_test_context();
1236 if (!test_context)
1238 skip("Couldn't create test context\n");
1239 return;
1241 device = test_context->device;
1243 hr = D3DXCreateMesh(0, 3, D3DXMESH_MANAGED, decl1, device, &d3dxmesh);
1244 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1246 hr = D3DXCreateMesh(1, 0, D3DXMESH_MANAGED, decl1, device, &d3dxmesh);
1247 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1249 hr = D3DXCreateMesh(1, 3, 0, decl1, device, &d3dxmesh);
1250 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
1252 if (hr == D3D_OK)
1254 d3dxmesh->lpVtbl->Release(d3dxmesh);
1257 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, 0, device, &d3dxmesh);
1258 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1260 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl1, device, NULL);
1261 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1263 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl1, device, &d3dxmesh);
1264 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
1266 if (hr == D3D_OK)
1268 /* device */
1269 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, NULL);
1270 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1272 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, &test_device);
1273 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
1274 ok(test_device == device, "Got result %p, expected %p\n", test_device, device);
1276 if (hr == D3D_OK)
1278 IDirect3DDevice9_Release(device);
1281 /* declaration */
1282 hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, NULL);
1283 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1285 hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, test_decl);
1286 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
1288 if (hr == D3D_OK)
1290 size = ARRAY_SIZE(decl1);
1291 for (i = 0; i < size - 1; i++)
1293 ok(test_decl[i].Stream == decl1[i].Stream, "Returned stream %d, expected %d\n", test_decl[i].Stream, decl1[i].Stream);
1294 ok(test_decl[i].Type == decl1[i].Type, "Returned type %d, expected %d\n", test_decl[i].Type, decl1[i].Type);
1295 ok(test_decl[i].Method == decl1[i].Method, "Returned method %d, expected %d\n", test_decl[i].Method, decl1[i].Method);
1296 ok(test_decl[i].Usage == decl1[i].Usage, "Returned usage %d, expected %d\n", test_decl[i].Usage, decl1[i].Usage);
1297 ok(test_decl[i].UsageIndex == decl1[i].UsageIndex, "Returned usage index %d, expected %d\n", test_decl[i].UsageIndex, decl1[i].UsageIndex);
1298 ok(test_decl[i].Offset == decl1[i].Offset, "Returned offset %d, expected %d\n", test_decl[i].Offset, decl1[i].Offset);
1300 ok(decl1[size-1].Stream == 0xFF, "Returned too long vertex declaration\n"); /* end element */
1303 /* options */
1304 options = d3dxmesh->lpVtbl->GetOptions(d3dxmesh);
1305 ok(options == D3DXMESH_MANAGED, "Got result %x, expected %x (D3DXMESH_MANAGED)\n", options, D3DXMESH_MANAGED);
1307 /* rest */
1308 if (!new_mesh(&mesh, 3, 1))
1310 skip("Couldn't create mesh\n");
1312 else
1314 memset(mesh.vertices, 0, mesh.number_of_vertices * sizeof(*mesh.vertices));
1315 memset(mesh.faces, 0, mesh.number_of_faces * sizeof(*mesh.faces));
1316 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
1318 compare_mesh("createmesh1", d3dxmesh, &mesh);
1320 free_mesh(&mesh);
1323 d3dxmesh->lpVtbl->Release(d3dxmesh);
1326 /* Test a declaration that can't be converted to an FVF. */
1327 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl2, device, &d3dxmesh);
1328 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
1330 if (hr == D3D_OK)
1332 /* device */
1333 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, NULL);
1334 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1336 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, &test_device);
1337 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
1338 ok(test_device == device, "Got result %p, expected %p\n", test_device, device);
1340 if (hr == D3D_OK)
1342 IDirect3DDevice9_Release(device);
1345 /* declaration */
1346 hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, test_decl);
1347 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
1349 if (hr == D3D_OK)
1351 size = ARRAY_SIZE(decl2);
1352 for (i = 0; i < size - 1; i++)
1354 ok(test_decl[i].Stream == decl2[i].Stream, "Returned stream %d, expected %d\n", test_decl[i].Stream, decl2[i].Stream);
1355 ok(test_decl[i].Type == decl2[i].Type, "Returned type %d, expected %d\n", test_decl[i].Type, decl2[i].Type);
1356 ok(test_decl[i].Method == decl2[i].Method, "Returned method %d, expected %d\n", test_decl[i].Method, decl2[i].Method);
1357 ok(test_decl[i].Usage == decl2[i].Usage, "Returned usage %d, expected %d\n", test_decl[i].Usage, decl2[i].Usage);
1358 ok(test_decl[i].UsageIndex == decl2[i].UsageIndex, "Returned usage index %d, expected %d\n", test_decl[i].UsageIndex, decl2[i].UsageIndex);
1359 ok(test_decl[i].Offset == decl2[i].Offset, "Returned offset %d, expected %d\n", test_decl[i].Offset, decl2[i].Offset);
1361 ok(decl2[size-1].Stream == 0xFF, "Returned too long vertex declaration\n"); /* end element */
1364 /* options */
1365 options = d3dxmesh->lpVtbl->GetOptions(d3dxmesh);
1366 ok(options == D3DXMESH_MANAGED, "Got result %x, expected %x (D3DXMESH_MANAGED)\n", options, D3DXMESH_MANAGED);
1368 /* rest */
1369 if (!new_mesh(&mesh, 3, 1))
1371 skip("Couldn't create mesh\n");
1373 else
1375 memset(mesh.vertices, 0, mesh.number_of_vertices * sizeof(*mesh.vertices));
1376 memset(mesh.faces, 0, mesh.number_of_faces * sizeof(*mesh.faces));
1377 mesh.fvf = 0;
1378 mesh.vertex_size = 60;
1380 compare_mesh("createmesh2", d3dxmesh, &mesh);
1382 free_mesh(&mesh);
1385 mesh.vertex_size = d3dxmesh->lpVtbl->GetNumBytesPerVertex(d3dxmesh);
1386 ok(mesh.vertex_size == 60, "Got vertex size %u, expected %u\n", mesh.vertex_size, 60);
1388 d3dxmesh->lpVtbl->Release(d3dxmesh);
1391 /* Test a declaration with multiple streams. */
1392 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl3, device, &d3dxmesh);
1393 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1395 free_test_context(test_context);
1398 static void D3DXCreateMeshFVFTest(void)
1400 HRESULT hr;
1401 IDirect3DDevice9 *device, *test_device;
1402 ID3DXMesh *d3dxmesh;
1403 int i, size;
1404 D3DVERTEXELEMENT9 test_decl[MAX_FVF_DECL_SIZE];
1405 DWORD options;
1406 struct mesh mesh;
1407 struct test_context *test_context;
1409 static const D3DVERTEXELEMENT9 decl[] =
1411 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1412 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
1413 D3DDECL_END(),
1416 hr = D3DXCreateMeshFVF(0, 0, 0, 0, NULL, NULL);
1417 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1419 hr = D3DXCreateMeshFVF(1, 3, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, NULL, &d3dxmesh);
1420 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1422 test_context = new_test_context();
1423 if (!test_context)
1425 skip("Couldn't create test context\n");
1426 return;
1428 device = test_context->device;
1430 hr = D3DXCreateMeshFVF(0, 3, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, device, &d3dxmesh);
1431 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1433 hr = D3DXCreateMeshFVF(1, 0, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, device, &d3dxmesh);
1434 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1436 hr = D3DXCreateMeshFVF(1, 3, 0, D3DFVF_XYZ | D3DFVF_NORMAL, device, &d3dxmesh);
1437 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
1439 if (hr == D3D_OK)
1441 d3dxmesh->lpVtbl->Release(d3dxmesh);
1444 hr = D3DXCreateMeshFVF(1, 3, D3DXMESH_MANAGED, 0xdeadbeef, device, &d3dxmesh);
1445 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1447 hr = D3DXCreateMeshFVF(1, 3, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, device, NULL);
1448 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1450 hr = D3DXCreateMeshFVF(1, 3, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, device, &d3dxmesh);
1451 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
1453 if (hr == D3D_OK)
1455 /* device */
1456 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, NULL);
1457 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1459 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, &test_device);
1460 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
1461 ok(test_device == device, "Got result %p, expected %p\n", test_device, device);
1463 if (hr == D3D_OK)
1465 IDirect3DDevice9_Release(device);
1468 /* declaration */
1469 hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, NULL);
1470 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1472 hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, test_decl);
1473 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
1475 if (hr == D3D_OK)
1477 size = ARRAY_SIZE(decl);
1478 for (i = 0; i < size - 1; i++)
1480 ok(test_decl[i].Stream == decl[i].Stream, "Returned stream %d, expected %d\n", test_decl[i].Stream, decl[i].Stream);
1481 ok(test_decl[i].Type == decl[i].Type, "Returned type %d, expected %d\n", test_decl[i].Type, decl[i].Type);
1482 ok(test_decl[i].Method == decl[i].Method, "Returned method %d, expected %d\n", test_decl[i].Method, decl[i].Method);
1483 ok(test_decl[i].Usage == decl[i].Usage, "Returned usage %d, expected %d\n", test_decl[i].Usage, decl[i].Usage);
1484 ok(test_decl[i].UsageIndex == decl[i].UsageIndex, "Returned usage index %d, expected %d\n",
1485 test_decl[i].UsageIndex, decl[i].UsageIndex);
1486 ok(test_decl[i].Offset == decl[i].Offset, "Returned offset %d, expected %d\n", test_decl[i].Offset, decl[i].Offset);
1488 ok(decl[size-1].Stream == 0xFF, "Returned too long vertex declaration\n"); /* end element */
1491 /* options */
1492 options = d3dxmesh->lpVtbl->GetOptions(d3dxmesh);
1493 ok(options == D3DXMESH_MANAGED, "Got result %x, expected %x (D3DXMESH_MANAGED)\n", options, D3DXMESH_MANAGED);
1495 /* rest */
1496 if (!new_mesh(&mesh, 3, 1))
1498 skip("Couldn't create mesh\n");
1500 else
1502 memset(mesh.vertices, 0, mesh.number_of_vertices * sizeof(*mesh.vertices));
1503 memset(mesh.faces, 0, mesh.number_of_faces * sizeof(*mesh.faces));
1504 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
1506 compare_mesh("createmeshfvf", d3dxmesh, &mesh);
1508 free_mesh(&mesh);
1511 d3dxmesh->lpVtbl->Release(d3dxmesh);
1514 free_test_context(test_context);
1517 #define check_vertex_buffer(mesh, vertices, num_vertices, fvf) \
1518 check_vertex_buffer_(__LINE__, mesh, vertices, num_vertices, fvf)
1519 static void check_vertex_buffer_(int line, ID3DXMesh *mesh, const void *vertices, DWORD num_vertices, DWORD fvf)
1521 DWORD mesh_num_vertices = mesh->lpVtbl->GetNumVertices(mesh);
1522 DWORD mesh_fvf = mesh->lpVtbl->GetFVF(mesh);
1523 const void *mesh_vertices;
1524 HRESULT hr;
1526 ok_(__FILE__,line)(fvf == mesh_fvf, "expected FVF %x, got %x\n", fvf, mesh_fvf);
1527 ok_(__FILE__,line)(num_vertices == mesh_num_vertices,
1528 "Expected %u vertices, got %u\n", num_vertices, mesh_num_vertices);
1530 hr = mesh->lpVtbl->LockVertexBuffer(mesh, D3DLOCK_READONLY, (void**)&mesh_vertices);
1531 ok_(__FILE__,line)(hr == D3D_OK, "LockVertexBuffer returned %x, expected %x (D3D_OK)\n", hr, D3D_OK);
1532 if (FAILED(hr))
1533 return;
1535 if (mesh_fvf == fvf) {
1536 DWORD vertex_size = D3DXGetFVFVertexSize(fvf), i;
1538 for (i = 0; i < min(num_vertices, mesh_num_vertices); i++)
1540 const FLOAT *exp_float = vertices;
1541 const FLOAT *got_float = mesh_vertices;
1542 DWORD texcount;
1543 DWORD pos_dim = 0;
1544 int j;
1545 BOOL last_beta_dword = FALSE;
1546 char prefix[128];
1548 switch (fvf & D3DFVF_POSITION_MASK) {
1549 case D3DFVF_XYZ: pos_dim = 3; break;
1550 case D3DFVF_XYZRHW: pos_dim = 4; break;
1551 case D3DFVF_XYZB1:
1552 case D3DFVF_XYZB2:
1553 case D3DFVF_XYZB3:
1554 case D3DFVF_XYZB4:
1555 case D3DFVF_XYZB5:
1556 pos_dim = (fvf & D3DFVF_POSITION_MASK) - D3DFVF_XYZB1 + 1;
1557 if (fvf & (D3DFVF_LASTBETA_UBYTE4 | D3DFVF_LASTBETA_D3DCOLOR))
1559 pos_dim--;
1560 last_beta_dword = TRUE;
1562 break;
1563 case D3DFVF_XYZW: pos_dim = 4; break;
1565 sprintf(prefix, "vertex[%u] position, ", i);
1566 check_floats_(line, prefix, got_float, exp_float, pos_dim);
1567 exp_float += pos_dim;
1568 got_float += pos_dim;
1570 if (last_beta_dword) {
1571 ok_(__FILE__,line)(*(DWORD*)exp_float == *(DWORD*)got_float,
1572 "Vertex[%u]: Expected last beta %08x, got %08x\n", i, *(DWORD*)exp_float, *(DWORD*)got_float);
1573 exp_float++;
1574 got_float++;
1577 if (fvf & D3DFVF_NORMAL) {
1578 sprintf(prefix, "vertex[%u] normal, ", i);
1579 check_floats_(line, prefix, got_float, exp_float, 3);
1580 exp_float += 3;
1581 got_float += 3;
1583 if (fvf & D3DFVF_PSIZE) {
1584 ok_(__FILE__,line)(compare(*exp_float, *got_float),
1585 "Vertex[%u]: Expected psize %g, got %g\n", i, *exp_float, *got_float);
1586 exp_float++;
1587 got_float++;
1589 if (fvf & D3DFVF_DIFFUSE) {
1590 ok_(__FILE__,line)(*(DWORD*)exp_float == *(DWORD*)got_float,
1591 "Vertex[%u]: Expected diffuse %08x, got %08x\n", i, *(DWORD*)exp_float, *(DWORD*)got_float);
1592 exp_float++;
1593 got_float++;
1595 if (fvf & D3DFVF_SPECULAR) {
1596 ok_(__FILE__,line)(*(DWORD*)exp_float == *(DWORD*)got_float,
1597 "Vertex[%u]: Expected specular %08x, got %08x\n", i, *(DWORD*)exp_float, *(DWORD*)got_float);
1598 exp_float++;
1599 got_float++;
1602 texcount = (fvf & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
1603 for (j = 0; j < texcount; j++) {
1604 DWORD dim = (((fvf >> (16 + 2 * j)) + 1) & 0x03) + 1;
1605 sprintf(prefix, "vertex[%u] texture, ", i);
1606 check_floats_(line, prefix, got_float, exp_float, dim);
1607 exp_float += dim;
1608 got_float += dim;
1611 vertices = (BYTE*)vertices + vertex_size;
1612 mesh_vertices = (BYTE*)mesh_vertices + vertex_size;
1616 mesh->lpVtbl->UnlockVertexBuffer(mesh);
1619 #define check_index_buffer(mesh, indices, num_indices, index_size) \
1620 check_index_buffer_(__LINE__, mesh, indices, num_indices, index_size)
1621 static void check_index_buffer_(int line, ID3DXMesh *mesh, const void *indices, DWORD num_indices, DWORD index_size)
1623 DWORD mesh_index_size = (mesh->lpVtbl->GetOptions(mesh) & D3DXMESH_32BIT) ? 4 : 2;
1624 DWORD mesh_num_indices = mesh->lpVtbl->GetNumFaces(mesh) * 3;
1625 const void *mesh_indices;
1626 HRESULT hr;
1627 DWORD i;
1629 ok_(__FILE__,line)(index_size == mesh_index_size,
1630 "Expected index size %u, got %u\n", index_size, mesh_index_size);
1631 ok_(__FILE__,line)(num_indices == mesh_num_indices,
1632 "Expected %u indices, got %u\n", num_indices, mesh_num_indices);
1634 hr = mesh->lpVtbl->LockIndexBuffer(mesh, D3DLOCK_READONLY, (void**)&mesh_indices);
1635 ok_(__FILE__,line)(hr == D3D_OK, "LockIndexBuffer returned %x, expected %x (D3D_OK)\n", hr, D3D_OK);
1636 if (FAILED(hr))
1637 return;
1639 if (mesh_index_size == index_size) {
1640 for (i = 0; i < min(num_indices, mesh_num_indices); i++)
1642 if (index_size == 4)
1643 ok_(__FILE__,line)(*(DWORD*)indices == *(DWORD*)mesh_indices,
1644 "Index[%u]: expected %u, got %u\n", i, *(DWORD*)indices, *(DWORD*)mesh_indices);
1645 else
1646 ok_(__FILE__,line)(*(WORD*)indices == *(WORD*)mesh_indices,
1647 "Index[%u]: expected %u, got %u\n", i, *(WORD*)indices, *(WORD*)mesh_indices);
1648 indices = (BYTE*)indices + index_size;
1649 mesh_indices = (BYTE*)mesh_indices + index_size;
1652 mesh->lpVtbl->UnlockIndexBuffer(mesh);
1655 #define check_matrix(got, expected) check_matrix_(__LINE__, got, expected)
1656 static void check_matrix_(int line, const D3DXMATRIX *got, const D3DXMATRIX *expected)
1658 int i, j;
1659 for (i = 0; i < 4; i++) {
1660 for (j = 0; j < 4; j++) {
1661 ok_(__FILE__,line)(compare(U(*expected).m[i][j], U(*got).m[i][j]),
1662 "matrix[%u][%u]: expected %g, got %g\n",
1663 i, j, U(*expected).m[i][j], U(*got).m[i][j]);
1668 static void check_colorvalue_(int line, const char *prefix, const D3DCOLORVALUE got, const D3DCOLORVALUE expected)
1670 ok_(__FILE__,line)(expected.r == got.r && expected.g == got.g && expected.b == got.b && expected.a == got.a,
1671 "%sExpected (%g, %g, %g, %g), got (%g, %g, %g, %g)\n", prefix,
1672 expected.r, expected.g, expected.b, expected.a, got.r, got.g, got.b, got.a);
1675 #define check_materials(got, got_count, expected, expected_count) \
1676 check_materials_(__LINE__, got, got_count, expected, expected_count)
1677 static void check_materials_(int line, const D3DXMATERIAL *got, DWORD got_count, const D3DXMATERIAL *expected, DWORD expected_count)
1679 int i;
1680 ok_(__FILE__,line)(expected_count == got_count, "Expected %u materials, got %u\n", expected_count, got_count);
1681 if (!expected) {
1682 ok_(__FILE__,line)(got == NULL, "Expected NULL material ptr, got %p\n", got);
1683 return;
1685 for (i = 0; i < min(expected_count, got_count); i++)
1687 if (!expected[i].pTextureFilename)
1688 ok_(__FILE__,line)(got[i].pTextureFilename == NULL,
1689 "Expected NULL pTextureFilename, got %p\n", got[i].pTextureFilename);
1690 else
1691 ok_(__FILE__,line)(!strcmp(expected[i].pTextureFilename, got[i].pTextureFilename),
1692 "Expected '%s' for pTextureFilename, got '%s'\n", expected[i].pTextureFilename, got[i].pTextureFilename);
1693 check_colorvalue_(line, "Diffuse: ", got[i].MatD3D.Diffuse, expected[i].MatD3D.Diffuse);
1694 check_colorvalue_(line, "Ambient: ", got[i].MatD3D.Ambient, expected[i].MatD3D.Ambient);
1695 check_colorvalue_(line, "Specular: ", got[i].MatD3D.Specular, expected[i].MatD3D.Specular);
1696 check_colorvalue_(line, "Emissive: ", got[i].MatD3D.Emissive, expected[i].MatD3D.Emissive);
1697 ok_(__FILE__,line)(expected[i].MatD3D.Power == got[i].MatD3D.Power,
1698 "Power: Expected %g, got %g\n", expected[i].MatD3D.Power, got[i].MatD3D.Power);
1702 #define check_generated_adjacency(mesh, got, epsilon) check_generated_adjacency_(__LINE__, mesh, got, epsilon)
1703 static void check_generated_adjacency_(int line, ID3DXMesh *mesh, const DWORD *got, FLOAT epsilon)
1705 DWORD *expected;
1706 DWORD num_faces = mesh->lpVtbl->GetNumFaces(mesh);
1707 HRESULT hr;
1709 expected = HeapAlloc(GetProcessHeap(), 0, num_faces * sizeof(DWORD) * 3);
1710 if (!expected) {
1711 skip_(__FILE__, line)("Out of memory\n");
1712 return;
1714 hr = mesh->lpVtbl->GenerateAdjacency(mesh, epsilon, expected);
1715 ok_(__FILE__, line)(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
1716 if (SUCCEEDED(hr))
1718 int i;
1719 for (i = 0; i < num_faces; i++)
1721 ok_(__FILE__, line)(expected[i * 3] == got[i * 3] &&
1722 expected[i * 3 + 1] == got[i * 3 + 1] &&
1723 expected[i * 3 + 2] == got[i * 3 + 2],
1724 "Face %u adjacencies: Expected (%u, %u, %u), got (%u, %u, %u)\n", i,
1725 expected[i * 3], expected[i * 3 + 1], expected[i * 3 + 2],
1726 got[i * 3], got[i * 3 + 1], got[i * 3 + 2]);
1729 HeapFree(GetProcessHeap(), 0, expected);
1732 #define check_generated_effects(materials, num_materials, effects) \
1733 check_generated_effects_(__LINE__, materials, num_materials, effects)
1734 static void check_generated_effects_(int line, const D3DXMATERIAL *materials, DWORD num_materials, const D3DXEFFECTINSTANCE *effects)
1736 int i;
1737 static const struct {
1738 const char *name;
1739 DWORD name_size;
1740 DWORD num_bytes;
1741 DWORD value_offset;
1742 } params[] = {
1743 #define EFFECT_TABLE_ENTRY(str, field) \
1744 {str, sizeof(str), sizeof(materials->MatD3D.field), offsetof(D3DXMATERIAL, MatD3D.field)}
1745 EFFECT_TABLE_ENTRY("Diffuse", Diffuse),
1746 EFFECT_TABLE_ENTRY("Power", Power),
1747 EFFECT_TABLE_ENTRY("Specular", Specular),
1748 EFFECT_TABLE_ENTRY("Emissive", Emissive),
1749 EFFECT_TABLE_ENTRY("Ambient", Ambient),
1750 #undef EFFECT_TABLE_ENTRY
1753 if (!num_materials) {
1754 ok_(__FILE__, line)(effects == NULL, "Expected NULL effects, got %p\n", effects);
1755 return;
1757 for (i = 0; i < num_materials; i++)
1759 int j;
1760 DWORD expected_num_defaults = ARRAY_SIZE(params) + (materials[i].pTextureFilename ? 1 : 0);
1762 ok_(__FILE__,line)(expected_num_defaults == effects[i].NumDefaults,
1763 "effect[%u] NumDefaults: Expected %u, got %u\n", i,
1764 expected_num_defaults, effects[i].NumDefaults);
1765 for (j = 0; j < min(ARRAY_SIZE(params), effects[i].NumDefaults); j++)
1767 int k;
1768 D3DXEFFECTDEFAULT *got_param = &effects[i].pDefaults[j];
1769 ok_(__FILE__,line)(!strcmp(params[j].name, got_param->pParamName),
1770 "effect[%u].pDefaults[%u].pParamName: Expected '%s', got '%s'\n", i, j,
1771 params[j].name, got_param->pParamName);
1772 ok_(__FILE__,line)(D3DXEDT_FLOATS == got_param->Type,
1773 "effect[%u].pDefaults[%u].Type: Expected %u, got %u\n", i, j,
1774 D3DXEDT_FLOATS, got_param->Type);
1775 ok_(__FILE__,line)(params[j].num_bytes == got_param->NumBytes,
1776 "effect[%u].pDefaults[%u].NumBytes: Expected %u, got %u\n", i, j,
1777 params[j].num_bytes, got_param->NumBytes);
1778 for (k = 0; k < min(params[j].num_bytes, got_param->NumBytes) / 4; k++)
1780 FLOAT expected = ((FLOAT*)((BYTE*)&materials[i] + params[j].value_offset))[k];
1781 FLOAT got = ((FLOAT*)got_param->pValue)[k];
1782 ok_(__FILE__,line)(compare(expected, got),
1783 "effect[%u].pDefaults[%u] float value %u: Expected %g, got %g\n", i, j, k, expected, got);
1786 if (effects[i].NumDefaults > ARRAY_SIZE(params)) {
1787 D3DXEFFECTDEFAULT *got_param = &effects[i].pDefaults[j];
1788 static const char *expected_name = "Texture0@Name";
1790 ok_(__FILE__,line)(!strcmp(expected_name, got_param->pParamName),
1791 "effect[%u].pDefaults[%u].pParamName: Expected '%s', got '%s'\n", i, j,
1792 expected_name, got_param->pParamName);
1793 ok_(__FILE__,line)(D3DXEDT_STRING == got_param->Type,
1794 "effect[%u].pDefaults[%u].Type: Expected %u, got %u\n", i, j,
1795 D3DXEDT_STRING, got_param->Type);
1796 if (materials[i].pTextureFilename) {
1797 ok_(__FILE__,line)(strlen(materials[i].pTextureFilename) + 1 == got_param->NumBytes,
1798 "effect[%u] texture filename length: Expected %u, got %u\n", i,
1799 (DWORD)strlen(materials[i].pTextureFilename) + 1, got_param->NumBytes);
1800 ok_(__FILE__,line)(!strcmp(materials[i].pTextureFilename, got_param->pValue),
1801 "effect[%u] texture filename: Expected '%s', got '%s'\n", i,
1802 materials[i].pTextureFilename, (char*)got_param->pValue);
1808 static char *strdupA(const char *p)
1810 char *ret;
1811 if (!p) return NULL;
1812 ret = HeapAlloc(GetProcessHeap(), 0, strlen(p) + 1);
1813 if (ret) strcpy(ret, p);
1814 return ret;
1817 static HRESULT CALLBACK ID3DXAllocateHierarchyImpl_DestroyFrame(ID3DXAllocateHierarchy *iface, LPD3DXFRAME frame)
1819 TRACECALLBACK("ID3DXAllocateHierarchyImpl_DestroyFrame(%p, %p)\n", iface, frame);
1820 if (frame) {
1821 HeapFree(GetProcessHeap(), 0, frame->Name);
1822 HeapFree(GetProcessHeap(), 0, frame);
1824 return D3D_OK;
1827 static HRESULT CALLBACK ID3DXAllocateHierarchyImpl_CreateFrame(ID3DXAllocateHierarchy *iface,
1828 const char *name, D3DXFRAME **new_frame)
1830 D3DXFRAME *frame;
1832 TRACECALLBACK("ID3DXAllocateHierarchyImpl_CreateFrame(%p, '%s', %p)\n", iface, name, new_frame);
1833 frame = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*frame));
1834 if (!frame)
1835 return E_OUTOFMEMORY;
1836 if (name) {
1837 frame->Name = strdupA(name);
1838 if (!frame->Name) {
1839 HeapFree(GetProcessHeap(), 0, frame);
1840 return E_OUTOFMEMORY;
1843 *new_frame = frame;
1844 return D3D_OK;
1847 static HRESULT destroy_mesh_container(LPD3DXMESHCONTAINER mesh_container)
1849 int i;
1851 if (!mesh_container)
1852 return D3D_OK;
1853 HeapFree(GetProcessHeap(), 0, mesh_container->Name);
1854 if (U(mesh_container->MeshData).pMesh)
1855 IUnknown_Release(U(mesh_container->MeshData).pMesh);
1856 if (mesh_container->pMaterials) {
1857 for (i = 0; i < mesh_container->NumMaterials; i++)
1858 HeapFree(GetProcessHeap(), 0, mesh_container->pMaterials[i].pTextureFilename);
1859 HeapFree(GetProcessHeap(), 0, mesh_container->pMaterials);
1861 if (mesh_container->pEffects) {
1862 for (i = 0; i < mesh_container->NumMaterials; i++) {
1863 HeapFree(GetProcessHeap(), 0, mesh_container->pEffects[i].pEffectFilename);
1864 if (mesh_container->pEffects[i].pDefaults) {
1865 int j;
1866 for (j = 0; j < mesh_container->pEffects[i].NumDefaults; j++) {
1867 HeapFree(GetProcessHeap(), 0, mesh_container->pEffects[i].pDefaults[j].pParamName);
1868 HeapFree(GetProcessHeap(), 0, mesh_container->pEffects[i].pDefaults[j].pValue);
1870 HeapFree(GetProcessHeap(), 0, mesh_container->pEffects[i].pDefaults);
1873 HeapFree(GetProcessHeap(), 0, mesh_container->pEffects);
1875 HeapFree(GetProcessHeap(), 0, mesh_container->pAdjacency);
1876 if (mesh_container->pSkinInfo)
1877 IUnknown_Release(mesh_container->pSkinInfo);
1878 HeapFree(GetProcessHeap(), 0, mesh_container);
1879 return D3D_OK;
1882 static HRESULT CALLBACK ID3DXAllocateHierarchyImpl_DestroyMeshContainer(ID3DXAllocateHierarchy *iface, LPD3DXMESHCONTAINER mesh_container)
1884 TRACECALLBACK("ID3DXAllocateHierarchyImpl_DestroyMeshContainer(%p, %p)\n", iface, mesh_container);
1885 return destroy_mesh_container(mesh_container);
1888 static HRESULT CALLBACK ID3DXAllocateHierarchyImpl_CreateMeshContainer(ID3DXAllocateHierarchy *iface,
1889 const char *name, const D3DXMESHDATA *mesh_data, const D3DXMATERIAL *materials,
1890 const D3DXEFFECTINSTANCE *effects, DWORD num_materials, const DWORD *adjacency,
1891 ID3DXSkinInfo *skin_info, D3DXMESHCONTAINER **new_mesh_container)
1893 LPD3DXMESHCONTAINER mesh_container = NULL;
1894 int i;
1896 TRACECALLBACK("ID3DXAllocateHierarchyImpl_CreateMeshContainer(%p, '%s', %u, %p, %p, %p, %d, %p, %p, %p)\n",
1897 iface, name, mesh_data->Type, U(*mesh_data).pMesh, materials, effects,
1898 num_materials, adjacency, skin_info, *new_mesh_container);
1900 mesh_container = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*mesh_container));
1901 if (!mesh_container)
1902 return E_OUTOFMEMORY;
1904 if (name) {
1905 mesh_container->Name = strdupA(name);
1906 if (!mesh_container->Name)
1907 goto error;
1910 mesh_container->NumMaterials = num_materials;
1911 if (num_materials) {
1912 mesh_container->pMaterials = HeapAlloc(GetProcessHeap(), 0, num_materials * sizeof(*materials));
1913 if (!mesh_container->pMaterials)
1914 goto error;
1916 memcpy(mesh_container->pMaterials, materials, num_materials * sizeof(*materials));
1917 for (i = 0; i < num_materials; i++)
1918 mesh_container->pMaterials[i].pTextureFilename = NULL;
1919 for (i = 0; i < num_materials; i++) {
1920 if (materials[i].pTextureFilename) {
1921 mesh_container->pMaterials[i].pTextureFilename = strdupA(materials[i].pTextureFilename);
1922 if (!mesh_container->pMaterials[i].pTextureFilename)
1923 goto error;
1927 mesh_container->pEffects = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, num_materials * sizeof(*effects));
1928 if (!mesh_container->pEffects)
1929 goto error;
1930 for (i = 0; i < num_materials; i++) {
1931 int j;
1932 const D3DXEFFECTINSTANCE *effect_src = &effects[i];
1933 D3DXEFFECTINSTANCE *effect_dest = &mesh_container->pEffects[i];
1935 if (effect_src->pEffectFilename) {
1936 effect_dest->pEffectFilename = strdupA(effect_src->pEffectFilename);
1937 if (!effect_dest->pEffectFilename)
1938 goto error;
1940 effect_dest->pDefaults = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1941 effect_src->NumDefaults * sizeof(*effect_src->pDefaults));
1942 if (!effect_dest->pDefaults)
1943 goto error;
1944 effect_dest->NumDefaults = effect_src->NumDefaults;
1945 for (j = 0; j < effect_src->NumDefaults; j++) {
1946 const D3DXEFFECTDEFAULT *default_src = &effect_src->pDefaults[j];
1947 D3DXEFFECTDEFAULT *default_dest = &effect_dest->pDefaults[j];
1949 if (default_src->pParamName) {
1950 default_dest->pParamName = strdupA(default_src->pParamName);
1951 if (!default_dest->pParamName)
1952 goto error;
1954 default_dest->NumBytes = default_src->NumBytes;
1955 default_dest->Type = default_src->Type;
1956 default_dest->pValue = HeapAlloc(GetProcessHeap(), 0, default_src->NumBytes);
1957 memcpy(default_dest->pValue, default_src->pValue, default_src->NumBytes);
1962 ok(adjacency != NULL, "Expected non-NULL adjacency, got NULL\n");
1963 if (adjacency) {
1964 if (mesh_data->Type == D3DXMESHTYPE_MESH || mesh_data->Type == D3DXMESHTYPE_PMESH) {
1965 ID3DXBaseMesh *basemesh = (ID3DXBaseMesh*)U(*mesh_data).pMesh;
1966 DWORD num_faces = basemesh->lpVtbl->GetNumFaces(basemesh);
1967 size_t size = num_faces * sizeof(DWORD) * 3;
1968 mesh_container->pAdjacency = HeapAlloc(GetProcessHeap(), 0, size);
1969 if (!mesh_container->pAdjacency)
1970 goto error;
1971 memcpy(mesh_container->pAdjacency, adjacency, size);
1972 } else {
1973 ok(mesh_data->Type == D3DXMESHTYPE_PATCHMESH, "Unknown mesh type %u\n", mesh_data->Type);
1974 if (mesh_data->Type == D3DXMESHTYPE_PATCHMESH)
1975 trace("FIXME: copying adjacency data for patch mesh not implemented\n");
1979 memcpy(&mesh_container->MeshData, mesh_data, sizeof(*mesh_data));
1980 if (U(*mesh_data).pMesh)
1981 IUnknown_AddRef(U(*mesh_data).pMesh);
1982 if (skin_info) {
1983 mesh_container->pSkinInfo = skin_info;
1984 skin_info->lpVtbl->AddRef(skin_info);
1986 *new_mesh_container = mesh_container;
1988 return S_OK;
1989 error:
1990 destroy_mesh_container(mesh_container);
1991 return E_OUTOFMEMORY;
1994 static ID3DXAllocateHierarchyVtbl ID3DXAllocateHierarchyImpl_Vtbl = {
1995 ID3DXAllocateHierarchyImpl_CreateFrame,
1996 ID3DXAllocateHierarchyImpl_CreateMeshContainer,
1997 ID3DXAllocateHierarchyImpl_DestroyFrame,
1998 ID3DXAllocateHierarchyImpl_DestroyMeshContainer,
2000 static ID3DXAllocateHierarchy alloc_hier = { &ID3DXAllocateHierarchyImpl_Vtbl };
2002 #define test_LoadMeshFromX(device, xfile_str, vertex_array, fvf, index_array, materials_array, check_adjacency) \
2003 test_LoadMeshFromX_(__LINE__, device, xfile_str, sizeof(xfile_str) - 1, vertex_array, ARRAY_SIZE(vertex_array), fvf, \
2004 index_array, ARRAY_SIZE(index_array), sizeof(*index_array), materials_array, ARRAY_SIZE(materials_array), \
2005 check_adjacency);
2006 static void test_LoadMeshFromX_(int line, IDirect3DDevice9 *device, const char *xfile_str, size_t xfile_strlen,
2007 const void *vertices, DWORD num_vertices, DWORD fvf, const void *indices, DWORD num_indices, size_t index_size,
2008 const D3DXMATERIAL *expected_materials, DWORD expected_num_materials, BOOL check_adjacency)
2010 HRESULT hr;
2011 ID3DXBuffer *materials = NULL;
2012 ID3DXBuffer *effects = NULL;
2013 ID3DXBuffer *adjacency = NULL;
2014 ID3DXMesh *mesh = NULL;
2015 DWORD num_materials = 0;
2017 /* Adjacency is not checked when the X file contains multiple meshes,
2018 * since calling GenerateAdjacency on the merged mesh is not equivalent
2019 * to calling GenerateAdjacency on the individual meshes and then merging
2020 * the adjacency data. */
2021 hr = D3DXLoadMeshFromXInMemory(xfile_str, xfile_strlen, D3DXMESH_MANAGED, device,
2022 check_adjacency ? &adjacency : NULL, &materials, &effects, &num_materials, &mesh);
2023 ok_(__FILE__,line)(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2024 if (SUCCEEDED(hr)) {
2025 D3DXMATERIAL *materials_ptr = materials ? ID3DXBuffer_GetBufferPointer(materials) : NULL;
2026 D3DXEFFECTINSTANCE *effects_ptr = effects ? ID3DXBuffer_GetBufferPointer(effects) : NULL;
2027 DWORD *adjacency_ptr = check_adjacency ? ID3DXBuffer_GetBufferPointer(adjacency) : NULL;
2029 check_vertex_buffer_(line, mesh, vertices, num_vertices, fvf);
2030 check_index_buffer_(line, mesh, indices, num_indices, index_size);
2031 check_materials_(line, materials_ptr, num_materials, expected_materials, expected_num_materials);
2032 check_generated_effects_(line, materials_ptr, num_materials, effects_ptr);
2033 if (check_adjacency)
2034 check_generated_adjacency_(line, mesh, adjacency_ptr, 0.0f);
2036 if (materials) ID3DXBuffer_Release(materials);
2037 if (effects) ID3DXBuffer_Release(effects);
2038 if (adjacency) ID3DXBuffer_Release(adjacency);
2039 IUnknown_Release(mesh);
2043 static void D3DXLoadMeshTest(void)
2045 static const char empty_xfile[] = "xof 0303txt 0032";
2046 /*________________________*/
2047 static const char simple_xfile[] =
2048 "xof 0303txt 0032"
2049 "Mesh {"
2050 "3;"
2051 "0.0; 0.0; 0.0;,"
2052 "0.0; 1.0; 0.0;,"
2053 "1.0; 1.0; 0.0;;"
2054 "1;"
2055 "3; 0, 1, 2;;"
2056 "}";
2057 static const WORD simple_index_buffer[] = {0, 1, 2};
2058 static const D3DXVECTOR3 simple_vertex_buffer[] = {
2059 {0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {1.0, 1.0, 0.0}
2061 const DWORD simple_fvf = D3DFVF_XYZ;
2062 static const char framed_xfile[] =
2063 "xof 0303txt 0032"
2064 "Frame {"
2065 "Mesh { 3; 0.0; 0.0; 0.0;, 0.0; 1.0; 0.0;, 1.0; 1.0; 0.0;; 1; 3; 0, 1, 2;; }"
2066 "FrameTransformMatrix {" /* translation (0.0, 0.0, 2.0) */
2067 "1.0, 0.0, 0.0, 0.0,"
2068 "0.0, 1.0, 0.0, 0.0,"
2069 "0.0, 0.0, 1.0, 0.0,"
2070 "0.0, 0.0, 2.0, 1.0;;"
2072 "Mesh { 3; 0.0; 0.0; 0.0;, 0.0; 1.0; 0.0;, 2.0; 1.0; 0.0;; 1; 3; 0, 1, 2;; }"
2073 "FrameTransformMatrix {" /* translation (0.0, 0.0, 3.0) */
2074 "1.0, 0.0, 0.0, 0.0,"
2075 "0.0, 1.0, 0.0, 0.0,"
2076 "0.0, 0.0, 1.0, 0.0,"
2077 "0.0, 0.0, 3.0, 1.0;;"
2079 "Mesh { 3; 0.0; 0.0; 0.0;, 0.0; 1.0; 0.0;, 3.0; 1.0; 0.0;; 1; 3; 0, 1, 2;; }"
2080 "}";
2081 static const WORD framed_index_buffer[] = { 0, 1, 2 };
2082 static const D3DXVECTOR3 framed_vertex_buffers[3][3] = {
2083 {{0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {1.0, 1.0, 0.0}},
2084 {{0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {2.0, 1.0, 0.0}},
2085 {{0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {3.0, 1.0, 0.0}},
2087 static const WORD merged_index_buffer[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
2088 /* frame transforms accumulates for D3DXLoadMeshFromX */
2089 static const D3DXVECTOR3 merged_vertex_buffer[] = {
2090 {0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {1.0, 1.0, 0.0},
2091 {0.0, 0.0, 2.0}, {0.0, 1.0, 2.0}, {2.0, 1.0, 2.0},
2092 {0.0, 0.0, 5.0}, {0.0, 1.0, 5.0}, {3.0, 1.0, 5.0},
2094 const DWORD framed_fvf = D3DFVF_XYZ;
2095 /*________________________*/
2096 static const char box_xfile[] =
2097 "xof 0303txt 0032"
2098 "Mesh {"
2099 "8;" /* DWORD nVertices; */
2100 /* array Vector vertices[nVertices]; */
2101 "0.0; 0.0; 0.0;,"
2102 "0.0; 0.0; 1.0;,"
2103 "0.0; 1.0; 0.0;,"
2104 "0.0; 1.0; 1.0;,"
2105 "1.0; 0.0; 0.0;,"
2106 "1.0; 0.0; 1.0;,"
2107 "1.0; 1.0; 0.0;,"
2108 "1.0; 1.0; 1.0;;"
2109 "6;" /* DWORD nFaces; */
2110 /* array MeshFace faces[nFaces]; */
2111 "4; 0, 1, 3, 2;," /* (left side) */
2112 "4; 2, 3, 7, 6;," /* (top side) */
2113 "4; 6, 7, 5, 4;," /* (right side) */
2114 "4; 1, 0, 4, 5;," /* (bottom side) */
2115 "4; 1, 5, 7, 3;," /* (back side) */
2116 "4; 0, 2, 6, 4;;" /* (front side) */
2117 "MeshNormals {"
2118 "6;" /* DWORD nNormals; */
2119 /* array Vector normals[nNormals]; */
2120 "-1.0; 0.0; 0.0;,"
2121 "0.0; 1.0; 0.0;,"
2122 "1.0; 0.0; 0.0;,"
2123 "0.0; -1.0; 0.0;,"
2124 "0.0; 0.0; 1.0;,"
2125 "0.0; 0.0; -1.0;;"
2126 "6;" /* DWORD nFaceNormals; */
2127 /* array MeshFace faceNormals[nFaceNormals]; */
2128 "4; 0, 0, 0, 0;,"
2129 "4; 1, 1, 1, 1;,"
2130 "4; 2, 2, 2, 2;,"
2131 "4; 3, 3, 3, 3;,"
2132 "4; 4, 4, 4, 4;,"
2133 "4; 5, 5, 5, 5;;"
2135 "MeshMaterialList materials {"
2136 "2;" /* DWORD nMaterials; */
2137 "6;" /* DWORD nFaceIndexes; */
2138 /* array DWORD faceIndexes[nFaceIndexes]; */
2139 "0, 0, 0, 1, 1, 1;;"
2140 "Material {"
2141 /* ColorRGBA faceColor; */
2142 "0.0; 0.0; 1.0; 1.0;;"
2143 /* FLOAT power; */
2144 "0.5;"
2145 /* ColorRGB specularColor; */
2146 "1.0; 1.0; 1.0;;"
2147 /* ColorRGB emissiveColor; */
2148 "0.0; 0.0; 0.0;;"
2150 "Material {"
2151 /* ColorRGBA faceColor; */
2152 "1.0; 1.0; 1.0; 1.0;;"
2153 /* FLOAT power; */
2154 "1.0;"
2155 /* ColorRGB specularColor; */
2156 "1.0; 1.0; 1.0;;"
2157 /* ColorRGB emissiveColor; */
2158 "0.0; 0.0; 0.0;;"
2159 "TextureFilename { \"texture.jpg\"; }"
2162 "MeshVertexColors {"
2163 "8;" /* DWORD nVertexColors; */
2164 /* array IndexedColor vertexColors[nVertexColors]; */
2165 "0; 0.0; 0.0; 0.0; 0.0;;"
2166 "1; 0.0; 0.0; 1.0; 0.1;;"
2167 "2; 0.0; 1.0; 0.0; 0.2;;"
2168 "3; 0.0; 1.0; 1.0; 0.3;;"
2169 "4; 1.0; 0.0; 0.0; 0.4;;"
2170 "5; 1.0; 0.0; 1.0; 0.5;;"
2171 "6; 1.0; 1.0; 0.0; 0.6;;"
2172 "7; 1.0; 1.0; 1.0; 0.7;;"
2174 "MeshTextureCoords {"
2175 "8;" /* DWORD nTextureCoords; */
2176 /* array Coords2d textureCoords[nTextureCoords]; */
2177 "0.0; 1.0;,"
2178 "1.0; 1.0;,"
2179 "0.0; 0.0;,"
2180 "1.0; 0.0;,"
2181 "1.0; 1.0;,"
2182 "0.0; 1.0;,"
2183 "1.0; 0.0;,"
2184 "0.0; 0.0;;"
2186 "}";
2187 static const WORD box_index_buffer[] = {
2188 0, 1, 3,
2189 0, 3, 2,
2190 8, 9, 7,
2191 8, 7, 6,
2192 10, 11, 5,
2193 10, 5, 4,
2194 12, 13, 14,
2195 12, 14, 15,
2196 16, 17, 18,
2197 16, 18, 19,
2198 20, 21, 22,
2199 20, 22, 23,
2201 static const struct {
2202 D3DXVECTOR3 position;
2203 D3DXVECTOR3 normal;
2204 D3DCOLOR diffuse;
2205 D3DXVECTOR2 tex_coords;
2206 } box_vertex_buffer[] = {
2207 {{0.0, 0.0, 0.0}, {-1.0, 0.0, 0.0}, 0x00000000, {0.0, 1.0}},
2208 {{0.0, 0.0, 1.0}, {-1.0, 0.0, 0.0}, 0x1a0000ff, {1.0, 1.0}},
2209 {{0.0, 1.0, 0.0}, {-1.0, 0.0, 0.0}, 0x3300ff00, {0.0, 0.0}},
2210 {{0.0, 1.0, 1.0}, {-1.0, 0.0, 0.0}, 0x4d00ffff, {1.0, 0.0}},
2211 {{1.0, 0.0, 0.0}, {1.0, 0.0, 0.0}, 0x66ff0000, {1.0, 1.0}},
2212 {{1.0, 0.0, 1.0}, {1.0, 0.0, 0.0}, 0x80ff00ff, {0.0, 1.0}},
2213 {{1.0, 1.0, 0.0}, {0.0, 1.0, 0.0}, 0x99ffff00, {1.0, 0.0}},
2214 {{1.0, 1.0, 1.0}, {0.0, 1.0, 0.0}, 0xb3ffffff, {0.0, 0.0}},
2215 {{0.0, 1.0, 0.0}, {0.0, 1.0, 0.0}, 0x3300ff00, {0.0, 0.0}},
2216 {{0.0, 1.0, 1.0}, {0.0, 1.0, 0.0}, 0x4d00ffff, {1.0, 0.0}},
2217 {{1.0, 1.0, 0.0}, {1.0, 0.0, 0.0}, 0x99ffff00, {1.0, 0.0}},
2218 {{1.0, 1.0, 1.0}, {1.0, 0.0, 0.0}, 0xb3ffffff, {0.0, 0.0}},
2219 {{0.0, 0.0, 1.0}, {0.0, -1.0, 0.0}, 0x1a0000ff, {1.0, 1.0}},
2220 {{0.0, 0.0, 0.0}, {0.0, -1.0, 0.0}, 0x00000000, {0.0, 1.0}},
2221 {{1.0, 0.0, 0.0}, {0.0, -1.0, 0.0}, 0x66ff0000, {1.0, 1.0}},
2222 {{1.0, 0.0, 1.0}, {0.0, -1.0, 0.0}, 0x80ff00ff, {0.0, 1.0}},
2223 {{0.0, 0.0, 1.0}, {0.0, 0.0, 1.0}, 0x1a0000ff, {1.0, 1.0}},
2224 {{1.0, 0.0, 1.0}, {0.0, 0.0, 1.0}, 0x80ff00ff, {0.0, 1.0}},
2225 {{1.0, 1.0, 1.0}, {0.0, 0.0, 1.0}, 0xb3ffffff, {0.0, 0.0}},
2226 {{0.0, 1.0, 1.0}, {0.0, 0.0, 1.0}, 0x4d00ffff, {1.0, 0.0}},
2227 {{0.0, 0.0, 0.0}, {0.0, 0.0, -1.0}, 0x00000000, {0.0, 1.0}},
2228 {{0.0, 1.0, 0.0}, {0.0, 0.0, -1.0}, 0x3300ff00, {0.0, 0.0}},
2229 {{1.0, 1.0, 0.0}, {0.0, 0.0, -1.0}, 0x99ffff00, {1.0, 0.0}},
2230 {{1.0, 0.0, 0.0}, {0.0, 0.0, -1.0}, 0x66ff0000, {1.0, 1.0}},
2232 static const D3DXMATERIAL box_materials[] = {
2235 {0.0, 0.0, 1.0, 1.0}, /* Diffuse */
2236 {0.0, 0.0, 0.0, 1.0}, /* Ambient */
2237 {1.0, 1.0, 1.0, 1.0}, /* Specular */
2238 {0.0, 0.0, 0.0, 1.0}, /* Emissive */
2239 0.5, /* Power */
2241 NULL, /* pTextureFilename */
2245 {1.0, 1.0, 1.0, 1.0}, /* Diffuse */
2246 {0.0, 0.0, 0.0, 1.0}, /* Ambient */
2247 {1.0, 1.0, 1.0, 1.0}, /* Specular */
2248 {0.0, 0.0, 0.0, 1.0}, /* Emissive */
2249 1.0, /* Power */
2251 (char *)"texture.jpg", /* pTextureFilename */
2254 static const char box_anim_xfile[] =
2255 "xof 0303txt 0032"
2256 "Mesh CubeMesh {"
2257 "8;" /* DWORD nVertices; */
2258 /* array Vector vertices[nVertices]; */
2259 "0.0; 0.0; 0.0;,"
2260 "0.0; 0.0; 1.0;,"
2261 "0.0; 1.0; 0.0;,"
2262 "0.0; 1.0; 1.0;,"
2263 "1.0; 0.0; 0.0;,"
2264 "1.0; 0.0; 1.0;,"
2265 "1.0; 1.0; 0.0;,"
2266 "1.0; 1.0; 1.0;;"
2267 "6;" /* DWORD nFaces; */
2268 /* array MeshFace faces[nFaces]; */
2269 "4; 0, 1, 3, 2;," /* left side */
2270 "4; 2, 3, 7, 6;," /* top side */
2271 "4; 6, 7, 5, 4;," /* right side */
2272 "4; 1, 0, 4, 5;," /* bottom side */
2273 "4; 1, 5, 7, 3;," /* back side */
2274 "4; 0, 2, 6, 4;;" /* front side */
2275 "MeshNormals {"
2276 "6;" /* DWORD nNormals; */
2277 /* array Vector normals[nNormals]; */
2278 "-1.0; 0.0; 0.0;,"
2279 "0.0; 1.0; 0.0;,"
2280 "1.0; 0.0; 0.0;,"
2281 "0.0; -1.0; 0.0;,"
2282 "0.0; 0.0; 1.0;,"
2283 "0.0; 0.0; -1.0;;"
2284 "6;" /* DWORD nFaceNormals; */
2285 /* array MeshFace faceNormals[nFaceNormals]; */
2286 "4; 0, 0, 0, 0;,"
2287 "4; 1, 1, 1, 1;,"
2288 "4; 2, 2, 2, 2;,"
2289 "4; 3, 3, 3, 3;,"
2290 "4; 4, 4, 4, 4;,"
2291 "4; 5, 5, 5, 5;;"
2293 "MeshMaterialList materials {"
2294 "2;" /* DWORD nMaterials; */
2295 "6;" /* DWORD nFaceIndexes; */
2296 /* array DWORD faceIndexes[nFaceIndexes]; */
2297 "0, 0, 0, 1, 1, 1;;"
2298 "Material {"
2299 /* ColorRGBA faceColor; */
2300 "0.0; 0.0; 1.0; 1.0;;"
2301 /* FLOAT power; */
2302 "0.5;"
2303 /* ColorRGB specularColor; */
2304 "1.0; 1.0; 1.0;;"
2305 /* ColorRGB emissiveColor; */
2306 "0.0; 0.0; 0.0;;"
2308 "Material {"
2309 /* ColorRGBA faceColor; */
2310 "1.0; 1.0; 1.0; 1.0;;"
2311 /* FLOAT power; */
2312 "1.0;"
2313 /* ColorRGB specularColor; */
2314 "1.0; 1.0; 1.0;;"
2315 /* ColorRGB emissiveColor; */
2316 "0.0; 0.0; 0.0;;"
2317 "TextureFilename { \"texture.jpg\"; }"
2320 "MeshVertexColors {"
2321 "8;" /* DWORD nVertexColors; */
2322 /* array IndexedColor vertexColors[nVertexColors]; */
2323 "0; 0.0; 0.0; 0.0; 0.0;;"
2324 "1; 0.0; 0.0; 1.0; 0.1;;"
2325 "2; 0.0; 1.0; 0.0; 0.2;;"
2326 "3; 0.0; 1.0; 1.0; 0.3;;"
2327 "4; 1.0; 0.0; 0.0; 0.4;;"
2328 "5; 1.0; 0.0; 1.0; 0.5;;"
2329 "6; 1.0; 1.0; 0.0; 0.6;;"
2330 "7; 1.0; 1.0; 1.0; 0.7;;"
2332 "MeshTextureCoords {"
2333 "8;" /* DWORD nTextureCoords; */
2334 /* array Coords2d textureCoords[nTextureCoords]; */
2335 "0.0; 1.0;,"
2336 "1.0; 1.0;,"
2337 "0.0; 0.0;,"
2338 "1.0; 0.0;,"
2339 "1.0; 1.0;,"
2340 "0.0; 1.0;,"
2341 "1.0; 0.0;,"
2342 "0.0; 0.0;;"
2345 "Frame CubeFrame {"
2346 "FrameTransformMatrix {"
2347 /* Matrix4x4 frameMatrix; */
2348 "1.0, 0.0, 0.0, 0.0,"
2349 "0.0, 1.0, 0.0, 0.0,"
2350 "0.0, 0.0, 1.0, 0.0,"
2351 "0.0, 0.0, 0.0, 1.0;;"
2353 "{CubeMesh}"
2355 "AnimationSet AnimationSet0 {"
2356 "Animation Animation0 {"
2357 "{CubeFrame}"
2358 "AnimationKey {"
2359 "2;" /* DWORD keyType; */
2360 "9;" /* DWORD nKeys; */
2361 /* array TimedFloatKeys keys[nKeys]; */
2362 "10; 3; -100.0, 0.0, 0.0;;,"
2363 "20; 3; -75.0, 0.0, 0.0;;,"
2364 "30; 3; -50.0, 0.0, 0.0;;,"
2365 "40; 3; -25.5, 0.0, 0.0;;,"
2366 "50; 3; 0.0, 0.0, 0.0;;,"
2367 "60; 3; 25.5, 0.0, 0.0;;,"
2368 "70; 3; 50.0, 0.0, 0.0;;,"
2369 "80; 3; 75.5, 0.0, 0.0;;,"
2370 "90; 3; 100.0, 0.0, 0.0;;;"
2373 "}";
2375 const DWORD box_fvf = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_TEX1;
2376 /*________________________*/
2377 static const D3DXMATERIAL default_materials[] = {
2380 {0.5, 0.5, 0.5, 0.0}, /* Diffuse */
2381 {0.0, 0.0, 0.0, 0.0}, /* Ambient */
2382 {0.5, 0.5, 0.5, 0.0}, /* Specular */
2383 {0.0, 0.0, 0.0, 0.0}, /* Emissive */
2384 0.0, /* Power */
2386 NULL, /* pTextureFilename */
2389 HRESULT hr;
2390 IDirect3DDevice9 *device = NULL;
2391 ID3DXMesh *mesh = NULL;
2392 D3DXFRAME *frame_hier = NULL;
2393 D3DXMATRIX transform;
2394 struct test_context *test_context;
2395 ID3DXAnimationController *controller;
2397 if (!(test_context = new_test_context()))
2399 skip("Couldn't create test context\n");
2400 return;
2402 device = test_context->device;
2404 hr = D3DXLoadMeshHierarchyFromXInMemory(NULL, sizeof(simple_xfile) - 1,
2405 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
2406 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2408 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, 0,
2409 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
2410 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2412 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1,
2413 D3DXMESH_MANAGED, NULL, &alloc_hier, NULL, &frame_hier, NULL);
2414 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2416 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1,
2417 D3DXMESH_MANAGED, device, NULL, NULL, &frame_hier, NULL);
2418 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2420 hr = D3DXLoadMeshHierarchyFromXInMemory(empty_xfile, sizeof(empty_xfile) - 1,
2421 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
2422 ok(hr == E_FAIL, "Expected E_FAIL, got %#x\n", hr);
2424 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1,
2425 D3DXMESH_MANAGED, device, &alloc_hier, NULL, NULL, NULL);
2426 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2428 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1,
2429 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
2430 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2431 if (SUCCEEDED(hr)) {
2432 D3DXMESHCONTAINER *container = frame_hier->pMeshContainer;
2434 ok(frame_hier->Name == NULL, "Expected NULL, got '%s'\n", frame_hier->Name);
2435 D3DXMatrixIdentity(&transform);
2436 check_matrix(&frame_hier->TransformationMatrix, &transform);
2438 ok(!strcmp(container->Name, ""), "Expected '', got '%s'\n", container->Name);
2439 ok(container->MeshData.Type == D3DXMESHTYPE_MESH, "Expected %d, got %d\n",
2440 D3DXMESHTYPE_MESH, container->MeshData.Type);
2441 mesh = U(container->MeshData).pMesh;
2442 check_vertex_buffer(mesh, simple_vertex_buffer, ARRAY_SIZE(simple_vertex_buffer), simple_fvf);
2443 check_index_buffer(mesh, simple_index_buffer, ARRAY_SIZE(simple_index_buffer), sizeof(*simple_index_buffer));
2444 check_materials(container->pMaterials, container->NumMaterials, NULL, 0);
2445 check_generated_effects(container->pMaterials, container->NumMaterials, container->pEffects);
2446 check_generated_adjacency(mesh, container->pAdjacency, 0.0f);
2447 hr = D3DXFrameDestroy(frame_hier, &alloc_hier);
2448 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2449 frame_hier = NULL;
2452 controller = (ID3DXAnimationController *)0xdeadbeef;
2453 hr = D3DXLoadMeshHierarchyFromXInMemory(box_anim_xfile, sizeof(box_anim_xfile) - 1,
2454 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, &controller);
2455 todo_wine ok(hr == D3D_OK, "Expected D3D_OK, got %#x.\n", hr);
2456 if (SUCCEEDED(hr))
2458 ok(controller != NULL, "Animation Controller NULL.\n");
2460 hr = D3DXFrameDestroy(frame_hier, &alloc_hier);
2461 ok(hr == D3D_OK, "Expected D3D_OK, got %#x.\n", hr);
2462 if (controller)
2463 controller->lpVtbl->Release(controller);
2465 frame_hier = NULL;
2468 controller = (ID3DXAnimationController *)0xdeadbeef;
2469 hr = D3DXLoadMeshHierarchyFromXInMemory(box_xfile, sizeof(box_xfile) - 1,
2470 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, &controller);
2471 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2472 if (SUCCEEDED(hr))
2474 D3DXMESHCONTAINER *container = frame_hier->pMeshContainer;
2476 ok(!controller, "Animation Controller returned.\n");
2477 ok(frame_hier->Name == NULL, "Expected NULL, got '%s'\n", frame_hier->Name);
2478 D3DXMatrixIdentity(&transform);
2479 check_matrix(&frame_hier->TransformationMatrix, &transform);
2481 ok(!strcmp(container->Name, ""), "Expected '', got '%s'\n", container->Name);
2482 ok(container->MeshData.Type == D3DXMESHTYPE_MESH, "Expected %d, got %d\n",
2483 D3DXMESHTYPE_MESH, container->MeshData.Type);
2484 mesh = U(container->MeshData).pMesh;
2485 check_vertex_buffer(mesh, box_vertex_buffer, ARRAY_SIZE(box_vertex_buffer), box_fvf);
2486 check_index_buffer(mesh, box_index_buffer, ARRAY_SIZE(box_index_buffer), sizeof(*box_index_buffer));
2487 check_materials(container->pMaterials, container->NumMaterials, box_materials, ARRAY_SIZE(box_materials));
2488 check_generated_effects(container->pMaterials, container->NumMaterials, container->pEffects);
2489 check_generated_adjacency(mesh, container->pAdjacency, 0.0f);
2490 hr = D3DXFrameDestroy(frame_hier, &alloc_hier);
2491 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2492 frame_hier = NULL;
2495 hr = D3DXLoadMeshHierarchyFromXInMemory(framed_xfile, sizeof(framed_xfile) - 1,
2496 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
2497 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2498 if (SUCCEEDED(hr)) {
2499 D3DXMESHCONTAINER *container = frame_hier->pMeshContainer;
2500 int i;
2502 ok(!strcmp(frame_hier->Name, ""), "Expected '', got '%s'\n", frame_hier->Name);
2503 /* last frame transform replaces the first */
2504 D3DXMatrixIdentity(&transform);
2505 U(transform).m[3][2] = 3.0;
2506 check_matrix(&frame_hier->TransformationMatrix, &transform);
2508 for (i = 0; i < 3; i++) {
2509 ok(!strcmp(container->Name, ""), "Expected '', got '%s'\n", container->Name);
2510 ok(container->MeshData.Type == D3DXMESHTYPE_MESH, "Expected %d, got %d\n",
2511 D3DXMESHTYPE_MESH, container->MeshData.Type);
2512 mesh = U(container->MeshData).pMesh;
2513 check_vertex_buffer(mesh, framed_vertex_buffers[i], ARRAY_SIZE(framed_vertex_buffers[0]), framed_fvf);
2514 check_index_buffer(mesh, framed_index_buffer, ARRAY_SIZE(framed_index_buffer), sizeof(*framed_index_buffer));
2515 check_materials(container->pMaterials, container->NumMaterials, NULL, 0);
2516 check_generated_effects(container->pMaterials, container->NumMaterials, container->pEffects);
2517 check_generated_adjacency(mesh, container->pAdjacency, 0.0f);
2518 container = container->pNextMeshContainer;
2520 ok(container == NULL, "Expected NULL, got %p\n", container);
2521 hr = D3DXFrameDestroy(frame_hier, &alloc_hier);
2522 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2523 frame_hier = NULL;
2527 hr = D3DXLoadMeshFromXInMemory(NULL, 0, D3DXMESH_MANAGED,
2528 device, NULL, NULL, NULL, NULL, &mesh);
2529 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2531 hr = D3DXLoadMeshFromXInMemory(NULL, sizeof(simple_xfile) - 1, D3DXMESH_MANAGED,
2532 device, NULL, NULL, NULL, NULL, &mesh);
2533 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2535 hr = D3DXLoadMeshFromXInMemory(simple_xfile, 0, D3DXMESH_MANAGED,
2536 device, NULL, NULL, NULL, NULL, &mesh);
2537 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2539 hr = D3DXLoadMeshFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1, D3DXMESH_MANAGED,
2540 device, NULL, NULL, NULL, NULL, NULL);
2541 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2543 hr = D3DXLoadMeshFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1, D3DXMESH_MANAGED,
2544 NULL, NULL, NULL, NULL, NULL, &mesh);
2545 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2547 hr = D3DXLoadMeshFromXInMemory(empty_xfile, sizeof(empty_xfile) - 1, D3DXMESH_MANAGED,
2548 device, NULL, NULL, NULL, NULL, &mesh);
2549 ok(hr == E_FAIL, "Expected E_FAIL, got %#x\n", hr);
2551 hr = D3DXLoadMeshFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1, D3DXMESH_MANAGED,
2552 device, NULL, NULL, NULL, NULL, &mesh);
2553 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2554 if (SUCCEEDED(hr))
2555 IUnknown_Release(mesh);
2557 test_LoadMeshFromX(device, simple_xfile, simple_vertex_buffer, simple_fvf, simple_index_buffer, default_materials, TRUE);
2558 test_LoadMeshFromX(device, box_xfile, box_vertex_buffer, box_fvf, box_index_buffer, box_materials, TRUE);
2559 test_LoadMeshFromX(device, framed_xfile, merged_vertex_buffer, framed_fvf, merged_index_buffer, default_materials, FALSE);
2561 free_test_context(test_context);
2564 static BOOL compute_box(struct mesh *mesh, float width, float height, float depth)
2566 unsigned int i, face;
2567 static const D3DXVECTOR3 unit_box[] =
2569 {-1.0f, -1.0f, -1.0f}, {-1.0f, -1.0f, 1.0f}, {-1.0f, 1.0f, 1.0f}, {-1.0f, 1.0f, -1.0f},
2570 {-1.0f, 1.0f, -1.0f}, {-1.0f, 1.0f, 1.0f}, { 1.0f, 1.0f, 1.0f}, { 1.0f, 1.0f, -1.0f},
2571 { 1.0f, 1.0f, -1.0f}, { 1.0f, 1.0f, 1.0f}, { 1.0f, -1.0f, 1.0f}, { 1.0f, -1.0f, -1.0f},
2572 {-1.0f, -1.0f, 1.0f}, {-1.0f, -1.0f, -1.0f}, { 1.0f, -1.0f, -1.0f}, { 1.0f, -1.0f, 1.0f},
2573 {-1.0f, -1.0f, 1.0f}, { 1.0f, -1.0f, 1.0f}, { 1.0f, 1.0f, 1.0f}, {-1.0f, 1.0f, 1.0f},
2574 {-1.0f, -1.0f, -1.0f}, {-1.0f, 1.0f, -1.0f}, { 1.0f, 1.0f, -1.0f}, { 1.0f, -1.0f, -1.0f}
2576 static const D3DXVECTOR3 normals[] =
2578 {-1.0f, 0.0f, 0.0f}, { 0.0f, 1.0f, 0.0f}, { 1.0f, 0.0f, 0.0f},
2579 { 0.0f, -1.0f, 0.0f}, { 0.0f, 0.0f, 1.0f}, { 0.0f, 0.0f, -1.0f}
2582 if (!new_mesh(mesh, 24, 12))
2584 return FALSE;
2587 width /= 2.0f;
2588 height /= 2.0f;
2589 depth /= 2.0f;
2591 for (i = 0; i < 24; i++)
2593 mesh->vertices[i].position.x = width * unit_box[i].x;
2594 mesh->vertices[i].position.y = height * unit_box[i].y;
2595 mesh->vertices[i].position.z = depth * unit_box[i].z;
2596 mesh->vertices[i].normal.x = normals[i / 4].x;
2597 mesh->vertices[i].normal.y = normals[i / 4].y;
2598 mesh->vertices[i].normal.z = normals[i / 4].z;
2601 face = 0;
2602 for (i = 0; i < 12; i++)
2604 mesh->faces[i][0] = face++;
2605 mesh->faces[i][1] = face++;
2606 mesh->faces[i][2] = (i % 2) ? face - 4 : face;
2609 return TRUE;
2612 static void test_box(IDirect3DDevice9 *device, float width, float height, float depth)
2614 HRESULT hr;
2615 ID3DXMesh *box;
2616 struct mesh mesh;
2617 char name[256];
2619 hr = D3DXCreateBox(device, width, height, depth, &box, NULL);
2620 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
2621 if (hr != D3D_OK)
2623 skip("Couldn't create box\n");
2624 return;
2627 if (!compute_box(&mesh, width, height, depth))
2629 skip("Couldn't create mesh\n");
2630 box->lpVtbl->Release(box);
2631 return;
2634 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
2636 sprintf(name, "box (%g, %g, %g)", width, height, depth);
2637 compare_mesh(name, box, &mesh);
2639 free_mesh(&mesh);
2641 box->lpVtbl->Release(box);
2643 static void D3DXCreateBoxTest(void)
2645 HRESULT hr;
2646 IDirect3DDevice9* device;
2647 ID3DXMesh* box;
2648 ID3DXBuffer* ppBuffer;
2649 DWORD *buffer;
2650 static const DWORD adjacency[36]=
2651 {6, 9, 1, 2, 10, 0,
2652 1, 9, 3, 4, 10, 2,
2653 3, 8, 5, 7, 11, 4,
2654 0, 11, 7, 5, 8, 6,
2655 7, 4, 9, 2, 0, 8,
2656 1, 3, 11, 5, 6, 10};
2657 unsigned int i;
2658 struct test_context *test_context;
2660 if (!(test_context = new_test_context()))
2662 skip("Couldn't create test context\n");
2663 return;
2665 device = test_context->device;
2667 hr = D3DXCreateBox(device,2.0f,20.0f,4.9f,NULL, &ppBuffer);
2668 ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2670 hr = D3DXCreateBox(NULL,22.0f,20.0f,4.9f,&box, &ppBuffer);
2671 ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2673 hr = D3DXCreateBox(device,-2.0f,20.0f,4.9f,&box, &ppBuffer);
2674 ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2676 hr = D3DXCreateBox(device,22.0f,-20.0f,4.9f,&box, &ppBuffer);
2677 ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2679 hr = D3DXCreateBox(device,22.0f,20.0f,-4.9f,&box, &ppBuffer);
2680 ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2682 ppBuffer = NULL;
2683 hr = D3DXCreateBox(device,10.9f,20.0f,4.9f,&box, &ppBuffer);
2684 ok(hr==D3D_OK, "Expected D3D_OK, received %#x\n", hr);
2686 buffer = ID3DXBuffer_GetBufferPointer(ppBuffer);
2687 for(i=0; i<36; i++)
2688 ok(adjacency[i]==buffer[i], "expected adjacency %d: %#x, received %#x\n",i,adjacency[i], buffer[i]);
2690 box->lpVtbl->Release(box);
2691 ID3DXBuffer_Release(ppBuffer);
2693 test_box(device, 10.9f, 20.0f, 4.9f);
2695 free_test_context(test_context);
2698 static BOOL compute_polygon(struct mesh *mesh, float length, unsigned int sides)
2700 unsigned int i;
2701 float angle, scale;
2703 if (!new_mesh(mesh, sides + 1, sides))
2704 return FALSE;
2706 angle = D3DX_PI / sides;
2707 scale = 0.5f * length / sinf(angle);
2708 angle *= 2.0f;
2710 mesh->vertices[0].position.x = 0.0f;
2711 mesh->vertices[0].position.y = 0.0f;
2712 mesh->vertices[0].position.z = 0.0f;
2713 mesh->vertices[0].normal.x = 0.0f;
2714 mesh->vertices[0].normal.y = 0.0f;
2715 mesh->vertices[0].normal.z = 1.0f;
2717 for (i = 0; i < sides; ++i)
2719 mesh->vertices[i + 1].position.x = cosf(angle * i) * scale;
2720 mesh->vertices[i + 1].position.y = sinf(angle * i) * scale;
2721 mesh->vertices[i + 1].position.z = 0.0f;
2722 mesh->vertices[i + 1].normal.x = 0.0f;
2723 mesh->vertices[i + 1].normal.y = 0.0f;
2724 mesh->vertices[i + 1].normal.z = 1.0f;
2726 mesh->faces[i][0] = 0;
2727 mesh->faces[i][1] = i + 1;
2728 mesh->faces[i][2] = i + 2;
2731 mesh->faces[sides - 1][2] = 1;
2733 return TRUE;
2736 static void test_polygon(IDirect3DDevice9 *device, float length, unsigned int sides)
2738 HRESULT hr;
2739 ID3DXMesh *polygon;
2740 struct mesh mesh;
2741 char name[64];
2743 hr = D3DXCreatePolygon(device, length, sides, &polygon, NULL);
2744 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
2745 if (hr != D3D_OK)
2747 skip("Couldn't create polygon\n");
2748 return;
2751 if (!compute_polygon(&mesh, length, sides))
2753 skip("Couldn't create mesh\n");
2754 polygon->lpVtbl->Release(polygon);
2755 return;
2758 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
2760 sprintf(name, "polygon (%g, %u)", length, sides);
2761 compare_mesh(name, polygon, &mesh);
2763 free_mesh(&mesh);
2765 polygon->lpVtbl->Release(polygon);
2768 static void D3DXCreatePolygonTest(void)
2770 HRESULT hr;
2771 IDirect3DDevice9 *device;
2772 ID3DXMesh *polygon;
2773 ID3DXBuffer *adjacency;
2774 DWORD (*buffer)[3], buffer_size;
2775 unsigned int i;
2776 struct test_context *test_context;
2778 if (!(test_context = new_test_context()))
2780 skip("Couldn't create test context\n");
2781 return;
2783 device = test_context->device;
2785 hr = D3DXCreatePolygon(device, 2.0f, 11, NULL, &adjacency);
2786 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2788 hr = D3DXCreatePolygon(NULL, 2.0f, 11, &polygon, &adjacency);
2789 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2791 hr = D3DXCreatePolygon(device, -2.0f, 11, &polygon, &adjacency);
2792 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2794 polygon = (void *)0xdeadbeef;
2795 adjacency = (void *)0xdeadbeef;
2796 hr = D3DXCreatePolygon(device, 2.0f, 0, &polygon, &adjacency);
2797 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2798 ok(polygon == (void *)0xdeadbeef, "Polygon was changed to %p\n", polygon);
2799 ok(adjacency == (void *)0xdeadbeef, "Adjacency was changed to %p\n", adjacency);
2801 hr = D3DXCreatePolygon(device, 2.0f, 2, &polygon, &adjacency);
2802 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2804 adjacency = NULL;
2805 hr = D3DXCreatePolygon(device, 3.0f, 11, &polygon, &adjacency);
2806 ok(hr == D3D_OK, "Expected D3D_OK, received %#x\n", hr);
2808 buffer_size = ID3DXBuffer_GetBufferSize(adjacency);
2809 ok(buffer_size == 33 * sizeof(DWORD), "Wrong adjacency buffer size %u\n", buffer_size);
2811 buffer = ID3DXBuffer_GetBufferPointer(adjacency);
2812 for (i = 0; i < 11; ++i)
2814 ok(buffer[i][0] == (i + 10) % 11, "Wrong adjacency[%d][0] = %u\n", i, buffer[i][0]);
2815 ok(buffer[i][1] == ~0U, "Wrong adjacency[%d][1] = %u\n", i, buffer[i][1]);
2816 ok(buffer[i][2] == (i + 1) % 11, "Wrong adjacency[%d][2] = %u\n", i, buffer[i][2]);
2819 polygon->lpVtbl->Release(polygon);
2820 ID3DXBuffer_Release(adjacency);
2822 test_polygon(device, 2.0f, 3);
2823 test_polygon(device, 10.0f, 3);
2824 test_polygon(device, 10.0f, 5);
2825 test_polygon(device, 10.0f, 10);
2826 test_polygon(device, 20.0f, 10);
2827 test_polygon(device, 20.0f, 32000);
2829 free_test_context(test_context);
2832 struct sincos_table
2834 float *sin;
2835 float *cos;
2838 static void free_sincos_table(struct sincos_table *sincos_table)
2840 HeapFree(GetProcessHeap(), 0, sincos_table->cos);
2841 HeapFree(GetProcessHeap(), 0, sincos_table->sin);
2844 /* pre compute sine and cosine tables; caller must free */
2845 static BOOL compute_sincos_table(struct sincos_table *sincos_table, float angle_start, float angle_step, int n)
2847 float angle;
2848 int i;
2850 sincos_table->sin = HeapAlloc(GetProcessHeap(), 0, n * sizeof(*sincos_table->sin));
2851 if (!sincos_table->sin)
2853 return FALSE;
2855 sincos_table->cos = HeapAlloc(GetProcessHeap(), 0, n * sizeof(*sincos_table->cos));
2856 if (!sincos_table->cos)
2858 HeapFree(GetProcessHeap(), 0, sincos_table->sin);
2859 return FALSE;
2862 angle = angle_start;
2863 for (i = 0; i < n; i++)
2865 sincos_table->sin[i] = sin(angle);
2866 sincos_table->cos[i] = cos(angle);
2867 angle += angle_step;
2870 return TRUE;
2873 static WORD vertex_index(UINT slices, int slice, int stack)
2875 return stack*slices+slice+1;
2878 /* slices = subdivisions along xy plane, stacks = subdivisions along z axis */
2879 static BOOL compute_sphere(struct mesh *mesh, FLOAT radius, UINT slices, UINT stacks)
2881 float theta_step, theta_start;
2882 struct sincos_table theta;
2883 float phi_step, phi_start;
2884 struct sincos_table phi;
2885 DWORD number_of_vertices, number_of_faces;
2886 DWORD vertex, face;
2887 int slice, stack;
2889 /* theta = angle on xy plane wrt x axis */
2890 theta_step = D3DX_PI / stacks;
2891 theta_start = theta_step;
2893 /* phi = angle on xz plane wrt z axis */
2894 phi_step = -2 * D3DX_PI / slices;
2895 phi_start = D3DX_PI / 2;
2897 if (!compute_sincos_table(&theta, theta_start, theta_step, stacks))
2899 return FALSE;
2901 if (!compute_sincos_table(&phi, phi_start, phi_step, slices))
2903 free_sincos_table(&theta);
2904 return FALSE;
2907 number_of_vertices = 2 + slices * (stacks-1);
2908 number_of_faces = 2 * slices + (stacks - 2) * (2 * slices);
2910 if (!new_mesh(mesh, number_of_vertices, number_of_faces))
2912 free_sincos_table(&phi);
2913 free_sincos_table(&theta);
2914 return FALSE;
2917 vertex = 0;
2918 face = 0;
2920 mesh->vertices[vertex].normal.x = 0.0f;
2921 mesh->vertices[vertex].normal.y = 0.0f;
2922 mesh->vertices[vertex].normal.z = 1.0f;
2923 mesh->vertices[vertex].position.x = 0.0f;
2924 mesh->vertices[vertex].position.y = 0.0f;
2925 mesh->vertices[vertex].position.z = radius;
2926 vertex++;
2928 for (stack = 0; stack < stacks - 1; stack++)
2930 for (slice = 0; slice < slices; slice++)
2932 mesh->vertices[vertex].normal.x = theta.sin[stack] * phi.cos[slice];
2933 mesh->vertices[vertex].normal.y = theta.sin[stack] * phi.sin[slice];
2934 mesh->vertices[vertex].normal.z = theta.cos[stack];
2935 mesh->vertices[vertex].position.x = radius * theta.sin[stack] * phi.cos[slice];
2936 mesh->vertices[vertex].position.y = radius * theta.sin[stack] * phi.sin[slice];
2937 mesh->vertices[vertex].position.z = radius * theta.cos[stack];
2938 vertex++;
2940 if (slice > 0)
2942 if (stack == 0)
2944 /* top stack is triangle fan */
2945 mesh->faces[face][0] = 0;
2946 mesh->faces[face][1] = slice + 1;
2947 mesh->faces[face][2] = slice;
2948 face++;
2950 else
2952 /* stacks in between top and bottom are quad strips */
2953 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
2954 mesh->faces[face][1] = vertex_index(slices, slice, stack-1);
2955 mesh->faces[face][2] = vertex_index(slices, slice-1, stack);
2956 face++;
2958 mesh->faces[face][0] = vertex_index(slices, slice, stack-1);
2959 mesh->faces[face][1] = vertex_index(slices, slice, stack);
2960 mesh->faces[face][2] = vertex_index(slices, slice-1, stack);
2961 face++;
2966 if (stack == 0)
2968 mesh->faces[face][0] = 0;
2969 mesh->faces[face][1] = 1;
2970 mesh->faces[face][2] = slice;
2971 face++;
2973 else
2975 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
2976 mesh->faces[face][1] = vertex_index(slices, 0, stack-1);
2977 mesh->faces[face][2] = vertex_index(slices, slice-1, stack);
2978 face++;
2980 mesh->faces[face][0] = vertex_index(slices, 0, stack-1);
2981 mesh->faces[face][1] = vertex_index(slices, 0, stack);
2982 mesh->faces[face][2] = vertex_index(slices, slice-1, stack);
2983 face++;
2987 mesh->vertices[vertex].position.x = 0.0f;
2988 mesh->vertices[vertex].position.y = 0.0f;
2989 mesh->vertices[vertex].position.z = -radius;
2990 mesh->vertices[vertex].normal.x = 0.0f;
2991 mesh->vertices[vertex].normal.y = 0.0f;
2992 mesh->vertices[vertex].normal.z = -1.0f;
2994 /* bottom stack is triangle fan */
2995 for (slice = 1; slice < slices; slice++)
2997 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
2998 mesh->faces[face][1] = vertex_index(slices, slice, stack-1);
2999 mesh->faces[face][2] = vertex;
3000 face++;
3003 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
3004 mesh->faces[face][1] = vertex_index(slices, 0, stack-1);
3005 mesh->faces[face][2] = vertex;
3007 free_sincos_table(&phi);
3008 free_sincos_table(&theta);
3010 return TRUE;
3013 static void test_sphere(IDirect3DDevice9 *device, FLOAT radius, UINT slices, UINT stacks)
3015 HRESULT hr;
3016 ID3DXMesh *sphere;
3017 struct mesh mesh;
3018 char name[256];
3020 hr = D3DXCreateSphere(device, radius, slices, stacks, &sphere, NULL);
3021 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
3022 if (hr != D3D_OK)
3024 skip("Couldn't create sphere\n");
3025 return;
3028 if (!compute_sphere(&mesh, radius, slices, stacks))
3030 skip("Couldn't create mesh\n");
3031 sphere->lpVtbl->Release(sphere);
3032 return;
3035 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
3037 sprintf(name, "sphere (%g, %u, %u)", radius, slices, stacks);
3038 compare_mesh(name, sphere, &mesh);
3040 free_mesh(&mesh);
3042 sphere->lpVtbl->Release(sphere);
3045 static void D3DXCreateSphereTest(void)
3047 HRESULT hr;
3048 IDirect3DDevice9* device;
3049 ID3DXMesh* sphere = NULL;
3050 struct test_context *test_context;
3052 hr = D3DXCreateSphere(NULL, 0.0f, 0, 0, NULL, NULL);
3053 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3055 hr = D3DXCreateSphere(NULL, 0.1f, 0, 0, NULL, NULL);
3056 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3058 hr = D3DXCreateSphere(NULL, 0.0f, 1, 0, NULL, NULL);
3059 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3061 hr = D3DXCreateSphere(NULL, 0.0f, 0, 1, NULL, NULL);
3062 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3064 if (!(test_context = new_test_context()))
3066 skip("Couldn't create test context\n");
3067 return;
3069 device = test_context->device;
3071 hr = D3DXCreateSphere(device, 1.0f, 1, 1, &sphere, NULL);
3072 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3074 hr = D3DXCreateSphere(device, 1.0f, 2, 1, &sphere, NULL);
3075 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
3077 hr = D3DXCreateSphere(device, 1.0f, 1, 2, &sphere, NULL);
3078 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
3080 hr = D3DXCreateSphere(device, -0.1f, 1, 2, &sphere, NULL);
3081 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
3083 test_sphere(device, 0.0f, 2, 2);
3084 test_sphere(device, 1.0f, 2, 2);
3085 test_sphere(device, 1.0f, 3, 2);
3086 test_sphere(device, 1.0f, 4, 4);
3087 test_sphere(device, 1.0f, 3, 4);
3088 test_sphere(device, 5.0f, 6, 7);
3089 test_sphere(device, 10.0f, 11, 12);
3091 free_test_context(test_context);
3094 static BOOL compute_cylinder(struct mesh *mesh, FLOAT radius1, FLOAT radius2, FLOAT length, UINT slices, UINT stacks)
3096 float theta_step, theta_start;
3097 struct sincos_table theta;
3098 FLOAT delta_radius, radius, radius_step;
3099 FLOAT z, z_step, z_normal;
3100 DWORD number_of_vertices, number_of_faces;
3101 DWORD vertex, face;
3102 int slice, stack;
3104 /* theta = angle on xy plane wrt x axis */
3105 theta_step = -2 * D3DX_PI / slices;
3106 theta_start = D3DX_PI / 2;
3108 if (!compute_sincos_table(&theta, theta_start, theta_step, slices))
3110 return FALSE;
3113 number_of_vertices = 2 + (slices * (3 + stacks));
3114 number_of_faces = 2 * slices + stacks * (2 * slices);
3116 if (!new_mesh(mesh, number_of_vertices, number_of_faces))
3118 free_sincos_table(&theta);
3119 return FALSE;
3122 vertex = 0;
3123 face = 0;
3125 delta_radius = radius1 - radius2;
3126 radius = radius1;
3127 radius_step = delta_radius / stacks;
3129 z = -length / 2;
3130 z_step = length / stacks;
3131 z_normal = delta_radius / length;
3132 if (isnan(z_normal))
3134 z_normal = 0.0f;
3137 mesh->vertices[vertex].normal.x = 0.0f;
3138 mesh->vertices[vertex].normal.y = 0.0f;
3139 mesh->vertices[vertex].normal.z = -1.0f;
3140 mesh->vertices[vertex].position.x = 0.0f;
3141 mesh->vertices[vertex].position.y = 0.0f;
3142 mesh->vertices[vertex++].position.z = z;
3144 for (slice = 0; slice < slices; slice++, vertex++)
3146 mesh->vertices[vertex].normal.x = 0.0f;
3147 mesh->vertices[vertex].normal.y = 0.0f;
3148 mesh->vertices[vertex].normal.z = -1.0f;
3149 mesh->vertices[vertex].position.x = radius * theta.cos[slice];
3150 mesh->vertices[vertex].position.y = radius * theta.sin[slice];
3151 mesh->vertices[vertex].position.z = z;
3153 if (slice > 0)
3155 mesh->faces[face][0] = 0;
3156 mesh->faces[face][1] = slice;
3157 mesh->faces[face++][2] = slice + 1;
3161 mesh->faces[face][0] = 0;
3162 mesh->faces[face][1] = slice;
3163 mesh->faces[face++][2] = 1;
3165 for (stack = 1; stack <= stacks+1; stack++)
3167 for (slice = 0; slice < slices; slice++, vertex++)
3169 mesh->vertices[vertex].normal.x = theta.cos[slice];
3170 mesh->vertices[vertex].normal.y = theta.sin[slice];
3171 mesh->vertices[vertex].normal.z = z_normal;
3172 D3DXVec3Normalize(&mesh->vertices[vertex].normal, &mesh->vertices[vertex].normal);
3173 mesh->vertices[vertex].position.x = radius * theta.cos[slice];
3174 mesh->vertices[vertex].position.y = radius * theta.sin[slice];
3175 mesh->vertices[vertex].position.z = z;
3177 if (stack > 1 && slice > 0)
3179 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
3180 mesh->faces[face][1] = vertex_index(slices, slice-1, stack);
3181 mesh->faces[face++][2] = vertex_index(slices, slice, stack-1);
3183 mesh->faces[face][0] = vertex_index(slices, slice, stack-1);
3184 mesh->faces[face][1] = vertex_index(slices, slice-1, stack);
3185 mesh->faces[face++][2] = vertex_index(slices, slice, stack);
3189 if (stack > 1)
3191 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
3192 mesh->faces[face][1] = vertex_index(slices, slice-1, stack);
3193 mesh->faces[face++][2] = vertex_index(slices, 0, stack-1);
3195 mesh->faces[face][0] = vertex_index(slices, 0, stack-1);
3196 mesh->faces[face][1] = vertex_index(slices, slice-1, stack);
3197 mesh->faces[face++][2] = vertex_index(slices, 0, stack);
3200 if (stack < stacks + 1)
3202 z += z_step;
3203 radius -= radius_step;
3207 for (slice = 0; slice < slices; slice++, vertex++)
3209 mesh->vertices[vertex].normal.x = 0.0f;
3210 mesh->vertices[vertex].normal.y = 0.0f;
3211 mesh->vertices[vertex].normal.z = 1.0f;
3212 mesh->vertices[vertex].position.x = radius * theta.cos[slice];
3213 mesh->vertices[vertex].position.y = radius * theta.sin[slice];
3214 mesh->vertices[vertex].position.z = z;
3216 if (slice > 0)
3218 mesh->faces[face][0] = vertex_index(slices, slice-1, stack);
3219 mesh->faces[face][1] = number_of_vertices - 1;
3220 mesh->faces[face++][2] = vertex_index(slices, slice, stack);
3224 mesh->vertices[vertex].position.x = 0.0f;
3225 mesh->vertices[vertex].position.y = 0.0f;
3226 mesh->vertices[vertex].position.z = z;
3227 mesh->vertices[vertex].normal.x = 0.0f;
3228 mesh->vertices[vertex].normal.y = 0.0f;
3229 mesh->vertices[vertex].normal.z = 1.0f;
3231 mesh->faces[face][0] = vertex_index(slices, slice-1, stack);
3232 mesh->faces[face][1] = number_of_vertices - 1;
3233 mesh->faces[face][2] = vertex_index(slices, 0, stack);
3235 free_sincos_table(&theta);
3237 return TRUE;
3240 static void test_cylinder(IDirect3DDevice9 *device, FLOAT radius1, FLOAT radius2, FLOAT length, UINT slices, UINT stacks)
3242 HRESULT hr;
3243 ID3DXMesh *cylinder;
3244 struct mesh mesh;
3245 char name[256];
3247 hr = D3DXCreateCylinder(device, radius1, radius2, length, slices, stacks, &cylinder, NULL);
3248 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
3249 if (hr != D3D_OK)
3251 skip("Couldn't create cylinder\n");
3252 return;
3255 if (!compute_cylinder(&mesh, radius1, radius2, length, slices, stacks))
3257 skip("Couldn't create mesh\n");
3258 cylinder->lpVtbl->Release(cylinder);
3259 return;
3262 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
3264 sprintf(name, "cylinder (%g, %g, %g, %u, %u)", radius1, radius2, length, slices, stacks);
3265 compare_mesh(name, cylinder, &mesh);
3267 free_mesh(&mesh);
3269 cylinder->lpVtbl->Release(cylinder);
3272 static void D3DXCreateCylinderTest(void)
3274 HRESULT hr;
3275 IDirect3DDevice9* device;
3276 ID3DXMesh* cylinder = NULL;
3277 struct test_context *test_context;
3279 hr = D3DXCreateCylinder(NULL, 0.0f, 0.0f, 0.0f, 0, 0, NULL, NULL);
3280 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3282 hr = D3DXCreateCylinder(NULL, 1.0f, 1.0f, 1.0f, 2, 1, &cylinder, NULL);
3283 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3285 if (!(test_context = new_test_context()))
3287 skip("Couldn't create test context\n");
3288 return;
3290 device = test_context->device;
3292 hr = D3DXCreateCylinder(device, -0.1f, 1.0f, 1.0f, 2, 1, &cylinder, NULL);
3293 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3295 hr = D3DXCreateCylinder(device, 0.0f, 1.0f, 1.0f, 2, 1, &cylinder, NULL);
3296 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n",hr);
3298 if (SUCCEEDED(hr) && cylinder)
3300 cylinder->lpVtbl->Release(cylinder);
3303 hr = D3DXCreateCylinder(device, 1.0f, -0.1f, 1.0f, 2, 1, &cylinder, NULL);
3304 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3306 hr = D3DXCreateCylinder(device, 1.0f, 0.0f, 1.0f, 2, 1, &cylinder, NULL);
3307 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n",hr);
3309 if (SUCCEEDED(hr) && cylinder)
3311 cylinder->lpVtbl->Release(cylinder);
3314 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, -0.1f, 2, 1, &cylinder, NULL);
3315 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3317 /* Test with length == 0.0f succeeds */
3318 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, 0.0f, 2, 1, &cylinder, NULL);
3319 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n",hr);
3321 if (SUCCEEDED(hr) && cylinder)
3323 cylinder->lpVtbl->Release(cylinder);
3326 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, 1.0f, 1, 1, &cylinder, NULL);
3327 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3329 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, 1.0f, 2, 0, &cylinder, NULL);
3330 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3332 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, 1.0f, 2, 1, NULL, NULL);
3333 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3335 test_cylinder(device, 0.0f, 0.0f, 0.0f, 2, 1);
3336 test_cylinder(device, 1.0f, 1.0f, 1.0f, 2, 1);
3337 test_cylinder(device, 1.0f, 1.0f, 2.0f, 3, 4);
3338 test_cylinder(device, 3.0f, 2.0f, 4.0f, 3, 4);
3339 test_cylinder(device, 2.0f, 3.0f, 4.0f, 3, 4);
3340 test_cylinder(device, 3.0f, 4.0f, 5.0f, 11, 20);
3342 free_test_context(test_context);
3345 static BOOL compute_torus(struct mesh *mesh, float innerradius, float outerradius, UINT sides, UINT rings)
3347 float phi, phi_step, sin_phi, cos_phi;
3348 float theta, theta_step, sin_theta, cos_theta;
3349 unsigned int numvert, numfaces, i, j;
3351 numvert = sides * rings;
3352 numfaces = numvert * 2;
3354 if (!new_mesh(mesh, numvert, numfaces))
3355 return FALSE;
3357 phi_step = D3DX_PI / sides * 2.0f;
3358 theta_step = D3DX_PI / rings * -2.0f;
3360 theta = 0.0f;
3362 for (i = 0; i < rings; ++i)
3364 phi = 0.0f;
3366 cos_theta = cosf(theta);
3367 sin_theta = sinf(theta);
3369 for (j = 0; j < sides; ++j)
3371 sin_phi = sinf(phi);
3372 cos_phi = cosf(phi);
3374 mesh->vertices[i * sides + j].position.x = (innerradius * cos_phi + outerradius) * cos_theta;
3375 mesh->vertices[i * sides + j].position.y = (innerradius * cos_phi + outerradius) * sin_theta;
3376 mesh->vertices[i * sides + j].position.z = innerradius * sin_phi;
3377 mesh->vertices[i * sides + j].normal.x = cos_phi * cos_theta;
3378 mesh->vertices[i * sides + j].normal.y = cos_phi * sin_theta;
3379 mesh->vertices[i * sides + j].normal.z = sin_phi;
3381 phi += phi_step;
3384 theta += theta_step;
3387 for (i = 0; i < numfaces - sides * 2; ++i)
3389 mesh->faces[i][0] = i % 2 ? i / 2 + sides : i / 2;
3390 mesh->faces[i][1] = (i / 2 + 1) % sides ? i / 2 + 1 : i / 2 + 1 - sides;
3391 mesh->faces[i][2] = (i + 1) % (sides * 2) ? (i + 1) / 2 + sides : (i + 1) / 2;
3394 for (j = 0; i < numfaces; ++i, ++j)
3396 mesh->faces[i][0] = i % 2 ? j / 2 : i / 2;
3397 mesh->faces[i][1] = (i / 2 + 1) % sides ? i / 2 + 1 : i / 2 + 1 - sides;
3398 mesh->faces[i][2] = i == numfaces - 1 ? 0 : (j + 1) / 2;
3401 return TRUE;
3404 static void test_torus(IDirect3DDevice9 *device, float innerradius, float outerradius, UINT sides, UINT rings)
3406 HRESULT hr;
3407 ID3DXMesh *torus;
3408 struct mesh mesh;
3409 char name[256];
3411 hr = D3DXCreateTorus(device, innerradius, outerradius, sides, rings, &torus, NULL);
3412 ok(hr == D3D_OK, "Got result %#x, expected 0 (D3D_OK)\n", hr);
3413 if (hr != D3D_OK)
3415 skip("Couldn't create torus\n");
3416 return;
3419 if (!compute_torus(&mesh, innerradius, outerradius, sides, rings))
3421 skip("Couldn't create mesh\n");
3422 torus->lpVtbl->Release(torus);
3423 return;
3426 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
3428 sprintf(name, "torus (%g, %g, %u, %u)", innerradius, outerradius, sides, rings);
3429 compare_mesh(name, torus, &mesh);
3431 free_mesh(&mesh);
3433 torus->lpVtbl->Release(torus);
3436 static void D3DXCreateTorusTest(void)
3438 HRESULT hr;
3439 IDirect3DDevice9* device;
3440 ID3DXMesh* torus = NULL;
3441 struct test_context *test_context;
3443 if (!(test_context = new_test_context()))
3445 skip("Couldn't create test context\n");
3446 return;
3448 device = test_context->device;
3450 hr = D3DXCreateTorus(NULL, 0.0f, 0.0f, 3, 3, &torus, NULL);
3451 ok(hr == D3DERR_INVALIDCALL, "Got result %#x, expected %#x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
3453 hr = D3DXCreateTorus(device, -1.0f, 0.0f, 3, 3, &torus, NULL);
3454 ok(hr == D3DERR_INVALIDCALL, "Got result %#x, expected %#x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
3456 hr = D3DXCreateTorus(device, 0.0f, -1.0f, 3, 3, &torus, NULL);
3457 ok(hr == D3DERR_INVALIDCALL, "Got result %#x, expected %#x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
3459 hr = D3DXCreateTorus(device, 0.0f, 0.0f, 2, 3, &torus, NULL);
3460 ok(hr == D3DERR_INVALIDCALL, "Got result %#x, expected %#x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
3462 hr = D3DXCreateTorus(device, 0.0f, 0.0f, 3, 2, &torus, NULL);
3463 ok(hr == D3DERR_INVALIDCALL, "Got result %#x, expected %#x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
3465 hr = D3DXCreateTorus(device, 0.0f, 0.0f, 3, 3, NULL, NULL);
3466 ok(hr == D3DERR_INVALIDCALL, "Got result %#x, expected %#x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
3468 test_torus(device, 0.0f, 0.0f, 3, 3);
3469 test_torus(device, 1.0f, 1.0f, 3, 3);
3470 test_torus(device, 1.0f, 1.0f, 32, 64);
3471 test_torus(device, 0.0f, 1.0f, 5, 5);
3472 test_torus(device, 1.0f, 0.0f, 5, 5);
3473 test_torus(device, 5.0f, 0.2f, 8, 8);
3474 test_torus(device, 0.2f, 1.0f, 60, 3);
3475 test_torus(device, 0.2f, 1.0f, 8, 70);
3477 free_test_context(test_context);
3480 struct dynamic_array
3482 int count, capacity;
3483 void *items;
3486 enum pointtype {
3487 POINTTYPE_CURVE = 0,
3488 POINTTYPE_CORNER,
3489 POINTTYPE_CURVE_START,
3490 POINTTYPE_CURVE_END,
3491 POINTTYPE_CURVE_MIDDLE,
3494 struct point2d
3496 D3DXVECTOR2 pos;
3497 enum pointtype corner;
3500 /* is a dynamic_array */
3501 struct outline
3503 int count, capacity;
3504 struct point2d *items;
3507 /* is a dynamic_array */
3508 struct outline_array
3510 int count, capacity;
3511 struct outline *items;
3514 struct glyphinfo
3516 struct outline_array outlines;
3517 float offset_x;
3520 static BOOL reserve(struct dynamic_array *array, int count, int itemsize)
3522 if (count > array->capacity) {
3523 void *new_buffer;
3524 int new_capacity;
3525 if (array->items && array->capacity) {
3526 new_capacity = max(array->capacity * 2, count);
3527 new_buffer = HeapReAlloc(GetProcessHeap(), 0, array->items, new_capacity * itemsize);
3528 } else {
3529 new_capacity = max(16, count);
3530 new_buffer = HeapAlloc(GetProcessHeap(), 0, new_capacity * itemsize);
3532 if (!new_buffer)
3533 return FALSE;
3534 array->items = new_buffer;
3535 array->capacity = new_capacity;
3537 return TRUE;
3540 static struct point2d *add_point(struct outline *array)
3542 struct point2d *item;
3544 if (!reserve((struct dynamic_array *)array, array->count + 1, sizeof(array->items[0])))
3545 return NULL;
3547 item = &array->items[array->count++];
3548 ZeroMemory(item, sizeof(*item));
3549 return item;
3552 static struct outline *add_outline(struct outline_array *array)
3554 struct outline *item;
3556 if (!reserve((struct dynamic_array *)array, array->count + 1, sizeof(array->items[0])))
3557 return NULL;
3559 item = &array->items[array->count++];
3560 ZeroMemory(item, sizeof(*item));
3561 return item;
3564 static inline D3DXVECTOR2 *convert_fixed_to_float(POINTFX *pt, int count, float emsquare)
3566 D3DXVECTOR2 *ret = (D3DXVECTOR2*)pt;
3567 while (count--) {
3568 D3DXVECTOR2 *pt_flt = (D3DXVECTOR2*)pt;
3569 pt_flt->x = (pt->x.value + pt->x.fract / (float)0x10000) / emsquare;
3570 pt_flt->y = (pt->y.value + pt->y.fract / (float)0x10000) / emsquare;
3571 pt++;
3573 return ret;
3576 static HRESULT add_bezier_points(struct outline *outline, const D3DXVECTOR2 *p1,
3577 const D3DXVECTOR2 *p2, const D3DXVECTOR2 *p3,
3578 float max_deviation)
3580 D3DXVECTOR2 split1 = {0, 0}, split2 = {0, 0}, middle, vec;
3581 float deviation;
3583 D3DXVec2Scale(&split1, D3DXVec2Add(&split1, p1, p2), 0.5f);
3584 D3DXVec2Scale(&split2, D3DXVec2Add(&split2, p2, p3), 0.5f);
3585 D3DXVec2Scale(&middle, D3DXVec2Add(&middle, &split1, &split2), 0.5f);
3587 deviation = D3DXVec2Length(D3DXVec2Subtract(&vec, &middle, p2));
3588 if (deviation < max_deviation) {
3589 struct point2d *pt = add_point(outline);
3590 if (!pt) return E_OUTOFMEMORY;
3591 pt->pos = *p2;
3592 pt->corner = POINTTYPE_CURVE;
3593 /* the end point is omitted because the end line merges into the next segment of
3594 * the split bezier curve, and the end of the split bezier curve is added outside
3595 * this recursive function. */
3596 } else {
3597 HRESULT hr = add_bezier_points(outline, p1, &split1, &middle, max_deviation);
3598 if (hr != S_OK) return hr;
3599 hr = add_bezier_points(outline, &middle, &split2, p3, max_deviation);
3600 if (hr != S_OK) return hr;
3603 return S_OK;
3606 static inline BOOL is_direction_similar(D3DXVECTOR2 *dir1, D3DXVECTOR2 *dir2, float cos_theta)
3608 /* dot product = cos(theta) */
3609 return D3DXVec2Dot(dir1, dir2) > cos_theta;
3612 static inline D3DXVECTOR2 *unit_vec2(D3DXVECTOR2 *dir, const D3DXVECTOR2 *pt1, const D3DXVECTOR2 *pt2)
3614 return D3DXVec2Normalize(D3DXVec2Subtract(dir, pt2, pt1), dir);
3617 static BOOL attempt_line_merge(struct outline *outline,
3618 int pt_index,
3619 const D3DXVECTOR2 *nextpt,
3620 BOOL to_curve)
3622 D3DXVECTOR2 curdir, lastdir;
3623 struct point2d *prevpt, *pt;
3624 BOOL ret = FALSE;
3625 const float cos_half = cos(D3DXToRadian(0.5f));
3627 pt = &outline->items[pt_index];
3628 pt_index = (pt_index - 1 + outline->count) % outline->count;
3629 prevpt = &outline->items[pt_index];
3631 if (to_curve)
3632 pt->corner = pt->corner != POINTTYPE_CORNER ? POINTTYPE_CURVE_MIDDLE : POINTTYPE_CURVE_START;
3634 if (outline->count < 2)
3635 return FALSE;
3637 /* remove last point if the next line continues the last line */
3638 unit_vec2(&lastdir, &prevpt->pos, &pt->pos);
3639 unit_vec2(&curdir, &pt->pos, nextpt);
3640 if (is_direction_similar(&lastdir, &curdir, cos_half))
3642 outline->count--;
3643 if (pt->corner == POINTTYPE_CURVE_END)
3644 prevpt->corner = pt->corner;
3645 if (prevpt->corner == POINTTYPE_CURVE_END && to_curve)
3646 prevpt->corner = POINTTYPE_CURVE_MIDDLE;
3647 pt = prevpt;
3649 ret = TRUE;
3650 if (outline->count < 2)
3651 return ret;
3653 pt_index = (pt_index - 1 + outline->count) % outline->count;
3654 prevpt = &outline->items[pt_index];
3655 unit_vec2(&lastdir, &prevpt->pos, &pt->pos);
3656 unit_vec2(&curdir, &pt->pos, nextpt);
3658 return ret;
3661 static HRESULT create_outline(struct glyphinfo *glyph, void *raw_outline, int datasize,
3662 float max_deviation, float emsquare)
3664 const float cos_45 = cos(D3DXToRadian(45.0f));
3665 const float cos_90 = cos(D3DXToRadian(90.0f));
3666 TTPOLYGONHEADER *header = (TTPOLYGONHEADER *)raw_outline;
3668 while ((char *)header < (char *)raw_outline + datasize)
3670 TTPOLYCURVE *curve = (TTPOLYCURVE *)(header + 1);
3671 struct point2d *lastpt, *pt;
3672 D3DXVECTOR2 lastdir;
3673 D3DXVECTOR2 *pt_flt;
3674 int j;
3675 struct outline *outline = add_outline(&glyph->outlines);
3677 if (!outline)
3678 return E_OUTOFMEMORY;
3680 pt = add_point(outline);
3681 if (!pt)
3682 return E_OUTOFMEMORY;
3683 pt_flt = convert_fixed_to_float(&header->pfxStart, 1, emsquare);
3684 pt->pos = *pt_flt;
3685 pt->corner = POINTTYPE_CORNER;
3687 if (header->dwType != TT_POLYGON_TYPE)
3688 trace("Unknown header type %d\n", header->dwType);
3690 while ((char *)curve < (char *)header + header->cb)
3692 D3DXVECTOR2 bezier_start = outline->items[outline->count - 1].pos;
3693 BOOL to_curve = curve->wType != TT_PRIM_LINE && curve->cpfx > 1;
3695 if (!curve->cpfx) {
3696 curve = (TTPOLYCURVE *)&curve->apfx[curve->cpfx];
3697 continue;
3700 pt_flt = convert_fixed_to_float(curve->apfx, curve->cpfx, emsquare);
3702 attempt_line_merge(outline, outline->count - 1, &pt_flt[0], to_curve);
3704 if (to_curve)
3706 HRESULT hr;
3707 int count = curve->cpfx;
3708 j = 0;
3710 while (count > 2)
3712 D3DXVECTOR2 bezier_end;
3714 D3DXVec2Scale(&bezier_end, D3DXVec2Add(&bezier_end, &pt_flt[j], &pt_flt[j+1]), 0.5f);
3715 hr = add_bezier_points(outline, &bezier_start, &pt_flt[j], &bezier_end, max_deviation);
3716 if (hr != S_OK)
3717 return hr;
3718 bezier_start = bezier_end;
3719 count--;
3720 j++;
3722 hr = add_bezier_points(outline, &bezier_start, &pt_flt[j], &pt_flt[j+1], max_deviation);
3723 if (hr != S_OK)
3724 return hr;
3726 pt = add_point(outline);
3727 if (!pt)
3728 return E_OUTOFMEMORY;
3729 j++;
3730 pt->pos = pt_flt[j];
3731 pt->corner = POINTTYPE_CURVE_END;
3732 } else {
3733 for (j = 0; j < curve->cpfx; j++)
3735 pt = add_point(outline);
3736 if (!pt)
3737 return E_OUTOFMEMORY;
3738 pt->pos = pt_flt[j];
3739 pt->corner = POINTTYPE_CORNER;
3743 curve = (TTPOLYCURVE *)&curve->apfx[curve->cpfx];
3746 /* remove last point if the next line continues the last line */
3747 if (outline->count >= 3) {
3748 BOOL to_curve;
3750 lastpt = &outline->items[outline->count - 1];
3751 pt = &outline->items[0];
3752 if (pt->pos.x == lastpt->pos.x && pt->pos.y == lastpt->pos.y) {
3753 if (lastpt->corner == POINTTYPE_CURVE_END)
3755 if (pt->corner == POINTTYPE_CURVE_START)
3756 pt->corner = POINTTYPE_CURVE_MIDDLE;
3757 else
3758 pt->corner = POINTTYPE_CURVE_END;
3760 outline->count--;
3761 } else {
3762 /* outline closed with a line from end to start point */
3763 attempt_line_merge(outline, outline->count - 1, &pt->pos, FALSE);
3765 lastpt = &outline->items[0];
3766 to_curve = lastpt->corner != POINTTYPE_CORNER && lastpt->corner != POINTTYPE_CURVE_END;
3767 if (lastpt->corner == POINTTYPE_CURVE_START)
3768 lastpt->corner = POINTTYPE_CORNER;
3769 pt = &outline->items[1];
3770 if (attempt_line_merge(outline, 0, &pt->pos, to_curve))
3771 *lastpt = outline->items[outline->count];
3774 lastpt = &outline->items[outline->count - 1];
3775 pt = &outline->items[0];
3776 unit_vec2(&lastdir, &lastpt->pos, &pt->pos);
3777 for (j = 0; j < outline->count; j++)
3779 D3DXVECTOR2 curdir;
3781 lastpt = pt;
3782 pt = &outline->items[(j + 1) % outline->count];
3783 unit_vec2(&curdir, &lastpt->pos, &pt->pos);
3785 switch (lastpt->corner)
3787 case POINTTYPE_CURVE_START:
3788 case POINTTYPE_CURVE_END:
3789 if (!is_direction_similar(&lastdir, &curdir, cos_45))
3790 lastpt->corner = POINTTYPE_CORNER;
3791 break;
3792 case POINTTYPE_CURVE_MIDDLE:
3793 if (!is_direction_similar(&lastdir, &curdir, cos_90))
3794 lastpt->corner = POINTTYPE_CORNER;
3795 else
3796 lastpt->corner = POINTTYPE_CURVE;
3797 break;
3798 default:
3799 break;
3801 lastdir = curdir;
3804 header = (TTPOLYGONHEADER *)((char *)header + header->cb);
3806 return S_OK;
3809 static void free_outline(struct outline *outline)
3811 HeapFree(GetProcessHeap(), 0, outline->items);
3814 static void free_glyphinfo(struct glyphinfo *glyph)
3816 unsigned int i;
3818 for (i = 0; i < glyph->outlines.count; ++i)
3819 free_outline(&glyph->outlines.items[i]);
3820 HeapFree(GetProcessHeap(), 0, glyph->outlines.items);
3823 static void compute_text_mesh(struct mesh *mesh, const char *text,
3824 float deviation, float extrusion, float otmEMSquare, const struct glyphinfo *glyphs)
3826 DWORD nb_vertices, nb_faces;
3827 DWORD nb_corners, nb_outline_points;
3828 int textlen = 0;
3829 int i;
3830 struct vertex *vertex_ptr;
3831 face *face_ptr;
3833 textlen = strlen(text);
3835 /* corner points need an extra vertex for the different side faces normals */
3836 nb_corners = 0;
3837 nb_outline_points = 0;
3838 for (i = 0; i < textlen; i++)
3840 int j;
3841 for (j = 0; j < glyphs[i].outlines.count; j++)
3843 int k;
3844 struct outline *outline = &glyphs[i].outlines.items[j];
3845 nb_outline_points += outline->count;
3846 nb_corners++; /* first outline point always repeated as a corner */
3847 for (k = 1; k < outline->count; k++)
3848 if (outline->items[k].corner)
3849 nb_corners++;
3853 nb_vertices = (nb_outline_points + nb_corners) * 2 + textlen;
3854 nb_faces = nb_outline_points * 2;
3856 ok(new_mesh(mesh, nb_vertices, nb_faces), "Failed to create reference text mesh.\n");
3858 /* convert 2D vertices and faces into 3D mesh */
3859 vertex_ptr = mesh->vertices;
3860 face_ptr = mesh->faces;
3861 for (i = 0; i < textlen; i++)
3863 int j;
3865 /* side vertices and faces */
3866 for (j = 0; j < glyphs[i].outlines.count; j++)
3868 struct vertex *outline_vertices = vertex_ptr;
3869 struct outline *outline = &glyphs[i].outlines.items[j];
3870 int k;
3871 struct point2d *prevpt = &outline->items[outline->count - 1];
3872 struct point2d *pt = &outline->items[0];
3874 for (k = 1; k <= outline->count; k++)
3876 struct vertex vtx;
3877 struct point2d *nextpt = &outline->items[k % outline->count];
3878 WORD vtx_idx = vertex_ptr - mesh->vertices;
3879 D3DXVECTOR2 vec;
3881 if (pt->corner == POINTTYPE_CURVE_START)
3882 D3DXVec2Subtract(&vec, &pt->pos, &prevpt->pos);
3883 else if (pt->corner)
3884 D3DXVec2Subtract(&vec, &nextpt->pos, &pt->pos);
3885 else
3886 D3DXVec2Subtract(&vec, &nextpt->pos, &prevpt->pos);
3887 D3DXVec2Normalize(&vec, &vec);
3888 vtx.normal.x = -vec.y;
3889 vtx.normal.y = vec.x;
3890 vtx.normal.z = 0;
3892 vtx.position.x = pt->pos.x + glyphs[i].offset_x;
3893 vtx.position.y = pt->pos.y;
3894 vtx.position.z = 0;
3895 *vertex_ptr++ = vtx;
3897 vtx.position.z = -extrusion;
3898 *vertex_ptr++ = vtx;
3900 vtx.position.x = nextpt->pos.x + glyphs[i].offset_x;
3901 vtx.position.y = nextpt->pos.y;
3902 if (pt->corner && nextpt->corner && nextpt->corner != POINTTYPE_CURVE_END) {
3903 vtx.position.z = -extrusion;
3904 *vertex_ptr++ = vtx;
3905 vtx.position.z = 0;
3906 *vertex_ptr++ = vtx;
3908 (*face_ptr)[0] = vtx_idx;
3909 (*face_ptr)[1] = vtx_idx + 2;
3910 (*face_ptr)[2] = vtx_idx + 1;
3911 face_ptr++;
3913 (*face_ptr)[0] = vtx_idx;
3914 (*face_ptr)[1] = vtx_idx + 3;
3915 (*face_ptr)[2] = vtx_idx + 2;
3916 face_ptr++;
3917 } else {
3918 if (nextpt->corner) {
3919 if (nextpt->corner == POINTTYPE_CURVE_END) {
3920 struct point2d *nextpt2 = &outline->items[(k + 1) % outline->count];
3921 D3DXVec2Subtract(&vec, &nextpt2->pos, &nextpt->pos);
3922 } else {
3923 D3DXVec2Subtract(&vec, &nextpt->pos, &pt->pos);
3925 D3DXVec2Normalize(&vec, &vec);
3926 vtx.normal.x = -vec.y;
3927 vtx.normal.y = vec.x;
3929 vtx.position.z = 0;
3930 *vertex_ptr++ = vtx;
3931 vtx.position.z = -extrusion;
3932 *vertex_ptr++ = vtx;
3935 (*face_ptr)[0] = vtx_idx;
3936 (*face_ptr)[1] = vtx_idx + 3;
3937 (*face_ptr)[2] = vtx_idx + 1;
3938 face_ptr++;
3940 (*face_ptr)[0] = vtx_idx;
3941 (*face_ptr)[1] = vtx_idx + 2;
3942 (*face_ptr)[2] = vtx_idx + 3;
3943 face_ptr++;
3946 prevpt = pt;
3947 pt = nextpt;
3949 if (!pt->corner) {
3950 *vertex_ptr++ = *outline_vertices++;
3951 *vertex_ptr++ = *outline_vertices++;
3955 /* FIXME: compute expected faces */
3956 /* Add placeholder to separate glyph outlines */
3957 vertex_ptr->position.x = 0;
3958 vertex_ptr->position.y = 0;
3959 vertex_ptr->position.z = 0;
3960 vertex_ptr->normal.x = 0;
3961 vertex_ptr->normal.y = 0;
3962 vertex_ptr->normal.z = 1;
3963 vertex_ptr++;
3967 static void compare_text_outline_mesh(const char *name, ID3DXMesh *d3dxmesh, struct mesh *mesh,
3968 size_t textlen, float extrusion, const struct glyphinfo *glyphs)
3970 HRESULT hr;
3971 DWORD number_of_vertices, number_of_faces;
3972 IDirect3DVertexBuffer9 *vertex_buffer = NULL;
3973 IDirect3DIndexBuffer9 *index_buffer = NULL;
3974 D3DVERTEXBUFFER_DESC vertex_buffer_description;
3975 D3DINDEXBUFFER_DESC index_buffer_description;
3976 struct vertex *vertices = NULL;
3977 face *faces = NULL;
3978 int expected, i;
3979 int vtx_idx1, face_idx1, vtx_idx2, face_idx2;
3981 number_of_vertices = d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh);
3982 number_of_faces = d3dxmesh->lpVtbl->GetNumFaces(d3dxmesh);
3984 hr = d3dxmesh->lpVtbl->GetVertexBuffer(d3dxmesh, &vertex_buffer);
3985 ok(hr == D3D_OK, "Test %s, unexpected hr %#x.\n", name, hr);
3986 hr = IDirect3DVertexBuffer9_GetDesc(vertex_buffer, &vertex_buffer_description);
3987 ok(hr == D3D_OK, "Test %s, unexpected hr %#x.\n", name, hr);
3988 ok(vertex_buffer_description.Format == D3DFMT_VERTEXDATA, "Test %s, unexpected format %u.\n",
3989 name, vertex_buffer_description.Format);
3990 ok(vertex_buffer_description.Type == D3DRTYPE_VERTEXBUFFER, "Test %s, unexpected resource type %u.\n",
3991 name, vertex_buffer_description.Type);
3992 ok(!vertex_buffer_description.Usage, "Test %s, unexpected usage %#x.\n", name, vertex_buffer_description.Usage);
3993 ok(vertex_buffer_description.Pool == D3DPOOL_MANAGED, "Test %s, unexpected pool %u.\n",
3994 name, vertex_buffer_description.Pool);
3995 ok(vertex_buffer_description.FVF == mesh->fvf, "Test %s, unexpected FVF %#x (expected %#x).\n",
3996 name, vertex_buffer_description.FVF, mesh->fvf);
3997 if (!mesh->fvf)
3998 expected = number_of_vertices * mesh->vertex_size;
3999 else
4000 expected = number_of_vertices * D3DXGetFVFVertexSize(mesh->fvf);
4001 ok(vertex_buffer_description.Size == expected, "Test %s, unexpected size %u (expected %u).\n",
4002 name, vertex_buffer_description.Size, expected);
4004 hr = d3dxmesh->lpVtbl->GetIndexBuffer(d3dxmesh, &index_buffer);
4005 ok(hr == D3D_OK, "Test %s, unexpected hr %#x.\n", name, hr);
4006 hr = IDirect3DIndexBuffer9_GetDesc(index_buffer, &index_buffer_description);
4007 ok(hr == D3D_OK, "Test %s, unexpected hr %#x.\n", name, hr);
4008 ok(index_buffer_description.Format == D3DFMT_INDEX16, "Test %s, unexpected format %u.\n",
4009 name, index_buffer_description.Format);
4010 ok(index_buffer_description.Type == D3DRTYPE_INDEXBUFFER, "Test %s, unexpected resource type %u.\n",
4011 name, index_buffer_description.Type);
4012 ok(!index_buffer_description.Usage, "Test %s, unexpected usage %#x.\n",
4013 name, index_buffer_description.Usage);
4014 ok(index_buffer_description.Pool == D3DPOOL_MANAGED, "Test %s, unexpected pool %u.\n",
4015 name, index_buffer_description.Pool);
4016 expected = number_of_faces * sizeof(WORD) * 3;
4017 ok(index_buffer_description.Size == expected, "Test %s, unexpected size %u.\n",
4018 name, index_buffer_description.Size);
4020 hr = IDirect3DVertexBuffer9_Lock(vertex_buffer, 0, number_of_vertices * sizeof(D3DXVECTOR3) * 2,
4021 (void **)&vertices, D3DLOCK_DISCARD);
4022 ok(hr == D3D_OK, "Test %s, unexpected hr %#x.\n", name, hr);
4023 hr = IDirect3DIndexBuffer9_Lock(index_buffer, 0, number_of_faces * sizeof(WORD) * 3,
4024 (void **)&faces, D3DLOCK_DISCARD);
4025 ok(hr == D3D_OK, "Test %s, unexpected hr %#x.\n", name, hr);
4026 face_idx1 = 0;
4027 vtx_idx2 = 0;
4028 face_idx2 = 0;
4029 vtx_idx1 = 0;
4030 for (i = 0; i < textlen; i++)
4032 int nb_outline_vertices1, nb_outline_faces1;
4033 int nb_outline_vertices2, nb_outline_faces2;
4034 int nb_back_vertices, nb_back_faces;
4035 int first_vtx1, first_vtx2;
4036 int first_face1, first_face2;
4037 int j;
4039 first_vtx1 = vtx_idx1;
4040 first_vtx2 = vtx_idx2;
4041 /* Glyphs without outlines do not generate any vertices. */
4042 if (glyphs[i].outlines.count > 0)
4044 for (; vtx_idx1 < number_of_vertices; vtx_idx1++)
4046 if (vertices[vtx_idx1].normal.z != 0)
4047 break;
4050 for (; vtx_idx2 < mesh->number_of_vertices; vtx_idx2++)
4052 if (mesh->vertices[vtx_idx2].normal.z != 0)
4053 break;
4056 nb_outline_vertices1 = vtx_idx1 - first_vtx1;
4057 nb_outline_vertices2 = vtx_idx2 - first_vtx2;
4058 ok(nb_outline_vertices1 == nb_outline_vertices2,
4059 "Test %s, glyph %d, outline vertex count result %d, expected %d\n", name, i,
4060 nb_outline_vertices1, nb_outline_vertices2);
4062 for (j = 0; j < min(nb_outline_vertices1, nb_outline_vertices2); j++)
4064 vtx_idx1 = first_vtx1 + j;
4065 vtx_idx2 = first_vtx2 + j;
4066 ok(compare_vec3(vertices[vtx_idx1].position, mesh->vertices[vtx_idx2].position),
4067 "Test %s, glyph %d, vertex position %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1,
4068 vertices[vtx_idx1].position.x, vertices[vtx_idx1].position.y, vertices[vtx_idx1].position.z,
4069 mesh->vertices[vtx_idx2].position.x, mesh->vertices[vtx_idx2].position.y, mesh->vertices[vtx_idx2].position.z);
4070 ok(compare_vec3(vertices[vtx_idx1].normal, mesh->vertices[first_vtx2 + j].normal),
4071 "Test %s, glyph %d, vertex normal %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1,
4072 vertices[vtx_idx1].normal.x, vertices[vtx_idx1].normal.y, vertices[vtx_idx1].normal.z,
4073 mesh->vertices[vtx_idx2].normal.x, mesh->vertices[vtx_idx2].normal.y, mesh->vertices[vtx_idx2].normal.z);
4075 vtx_idx1 = first_vtx1 + nb_outline_vertices1;
4076 vtx_idx2 = first_vtx2 + nb_outline_vertices2;
4078 first_face1 = face_idx1;
4079 first_face2 = face_idx2;
4080 for (; face_idx1 < number_of_faces; face_idx1++)
4082 if (faces[face_idx1][0] >= vtx_idx1 ||
4083 faces[face_idx1][1] >= vtx_idx1 ||
4084 faces[face_idx1][2] >= vtx_idx1)
4085 break;
4087 for (; face_idx2 < mesh->number_of_faces; face_idx2++)
4089 if (mesh->faces[face_idx2][0] >= vtx_idx2 ||
4090 mesh->faces[face_idx2][1] >= vtx_idx2 ||
4091 mesh->faces[face_idx2][2] >= vtx_idx2)
4092 break;
4094 nb_outline_faces1 = face_idx1 - first_face1;
4095 nb_outline_faces2 = face_idx2 - first_face2;
4096 ok(nb_outline_faces1 == nb_outline_faces2,
4097 "Test %s, glyph %d, outline face count result %d, expected %d\n", name, i,
4098 nb_outline_faces1, nb_outline_faces2);
4100 for (j = 0; j < min(nb_outline_faces1, nb_outline_faces2); j++)
4102 face_idx1 = first_face1 + j;
4103 face_idx2 = first_face2 + j;
4104 ok(faces[face_idx1][0] - first_vtx1 == mesh->faces[face_idx2][0] - first_vtx2 &&
4105 faces[face_idx1][1] - first_vtx1 == mesh->faces[face_idx2][1] - first_vtx2 &&
4106 faces[face_idx1][2] - first_vtx1 == mesh->faces[face_idx2][2] - first_vtx2,
4107 "Test %s, glyph %d, face %d, result (%d, %d, %d), expected (%d, %d, %d)\n", name, i, face_idx1,
4108 faces[face_idx1][0], faces[face_idx1][1], faces[face_idx1][2],
4109 mesh->faces[face_idx2][0] - first_vtx2 + first_vtx1,
4110 mesh->faces[face_idx2][1] - first_vtx2 + first_vtx1,
4111 mesh->faces[face_idx2][2] - first_vtx2 + first_vtx1);
4113 face_idx1 = first_face1 + nb_outline_faces1;
4114 face_idx2 = first_face2 + nb_outline_faces2;
4116 /* partial test on back vertices and faces */
4117 first_vtx1 = vtx_idx1;
4118 for (; vtx_idx1 < number_of_vertices; vtx_idx1++) {
4119 struct vertex vtx;
4121 if (vertices[vtx_idx1].normal.z != 1.0f)
4122 break;
4124 vtx.position.z = 0.0f;
4125 vtx.normal.x = 0.0f;
4126 vtx.normal.y = 0.0f;
4127 vtx.normal.z = 1.0f;
4128 ok(compare(vertices[vtx_idx1].position.z, vtx.position.z),
4129 "Test %s, glyph %d, vertex position.z %d, result %g, expected %g\n", name, i, vtx_idx1,
4130 vertices[vtx_idx1].position.z, vtx.position.z);
4131 ok(compare_vec3(vertices[vtx_idx1].normal, vtx.normal),
4132 "Test %s, glyph %d, vertex normal %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1,
4133 vertices[vtx_idx1].normal.x, vertices[vtx_idx1].normal.y, vertices[vtx_idx1].normal.z,
4134 vtx.normal.x, vtx.normal.y, vtx.normal.z);
4136 nb_back_vertices = vtx_idx1 - first_vtx1;
4137 first_face1 = face_idx1;
4138 for (; face_idx1 < number_of_faces; face_idx1++)
4140 const D3DXVECTOR3 *vtx1, *vtx2, *vtx3;
4141 D3DXVECTOR3 normal;
4142 D3DXVECTOR3 v1 = {0, 0, 0};
4143 D3DXVECTOR3 v2 = {0, 0, 0};
4144 D3DXVECTOR3 forward = {0.0f, 0.0f, 1.0f};
4146 if (faces[face_idx1][0] >= vtx_idx1 ||
4147 faces[face_idx1][1] >= vtx_idx1 ||
4148 faces[face_idx1][2] >= vtx_idx1)
4149 break;
4151 vtx1 = &vertices[faces[face_idx1][0]].position;
4152 vtx2 = &vertices[faces[face_idx1][1]].position;
4153 vtx3 = &vertices[faces[face_idx1][2]].position;
4155 D3DXVec3Subtract(&v1, vtx2, vtx1);
4156 D3DXVec3Subtract(&v2, vtx3, vtx2);
4157 D3DXVec3Cross(&normal, &v1, &v2);
4158 D3DXVec3Normalize(&normal, &normal);
4159 ok(!D3DXVec3Length(&normal) || compare_vec3(normal, forward),
4160 "Test %s, glyph %d, face %d normal, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, face_idx1,
4161 normal.x, normal.y, normal.z, forward.x, forward.y, forward.z);
4163 nb_back_faces = face_idx1 - first_face1;
4165 /* compare front and back faces & vertices */
4166 if (extrusion == 0.0f) {
4167 /* Oddly there are only back faces in this case */
4168 nb_back_vertices /= 2;
4169 nb_back_faces /= 2;
4170 face_idx1 -= nb_back_faces;
4171 vtx_idx1 -= nb_back_vertices;
4173 for (j = 0; j < nb_back_vertices; j++)
4175 struct vertex vtx = vertices[first_vtx1];
4176 vtx.position.z = -extrusion;
4177 vtx.normal.x = 0.0f;
4178 vtx.normal.y = 0.0f;
4179 vtx.normal.z = extrusion == 0.0f ? 1.0f : -1.0f;
4180 ok(compare_vec3(vertices[vtx_idx1].position, vtx.position),
4181 "Test %s, glyph %d, vertex position %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1,
4182 vertices[vtx_idx1].position.x, vertices[vtx_idx1].position.y, vertices[vtx_idx1].position.z,
4183 vtx.position.x, vtx.position.y, vtx.position.z);
4184 ok(compare_vec3(vertices[vtx_idx1].normal, vtx.normal),
4185 "Test %s, glyph %d, vertex normal %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1,
4186 vertices[vtx_idx1].normal.x, vertices[vtx_idx1].normal.y, vertices[vtx_idx1].normal.z,
4187 vtx.normal.x, vtx.normal.y, vtx.normal.z);
4188 vtx_idx1++;
4189 first_vtx1++;
4191 for (j = 0; j < nb_back_faces; j++)
4193 int f1, f2;
4194 if (extrusion == 0.0f) {
4195 f1 = 1;
4196 f2 = 2;
4197 } else {
4198 f1 = 2;
4199 f2 = 1;
4201 ok(faces[face_idx1][0] == faces[first_face1][0] + nb_back_vertices &&
4202 faces[face_idx1][1] == faces[first_face1][f1] + nb_back_vertices &&
4203 faces[face_idx1][2] == faces[first_face1][f2] + nb_back_vertices,
4204 "Test %s, glyph %d, face %d, result (%d, %d, %d), expected (%d, %d, %d)\n", name, i, face_idx1,
4205 faces[face_idx1][0], faces[face_idx1][1], faces[face_idx1][2],
4206 faces[first_face1][0] - nb_back_faces,
4207 faces[first_face1][f1] - nb_back_faces,
4208 faces[first_face1][f2] - nb_back_faces);
4209 first_face1++;
4210 face_idx1++;
4213 /* skip to the outline for the next glyph */
4214 for (; vtx_idx2 < mesh->number_of_vertices; vtx_idx2++) {
4215 if (mesh->vertices[vtx_idx2].normal.z == 0)
4216 break;
4218 for (; face_idx2 < mesh->number_of_faces; face_idx2++)
4220 if (mesh->faces[face_idx2][0] >= vtx_idx2 ||
4221 mesh->faces[face_idx2][1] >= vtx_idx2 ||
4222 mesh->faces[face_idx2][2] >= vtx_idx2) break;
4226 IDirect3DIndexBuffer9_Unlock(index_buffer);
4227 IDirect3DVertexBuffer9_Unlock(vertex_buffer);
4228 IDirect3DIndexBuffer9_Release(index_buffer);
4229 IDirect3DVertexBuffer9_Release(vertex_buffer);
4232 static void test_createtext(IDirect3DDevice9 *device, HDC hdc, const char *text, float deviation, float extrusion)
4234 static const MAT2 identity = {{0, 1}, {0, 0}, {0, 0}, {0, 1}};
4235 HRESULT hr;
4236 ID3DXMesh *d3dxmesh = NULL;
4237 struct mesh mesh = {0};
4238 char name[256];
4239 OUTLINETEXTMETRICA otm;
4240 GLYPHMETRICS gm;
4241 struct glyphinfo *glyphs;
4242 GLYPHMETRICSFLOAT *glyphmetrics_float = HeapAlloc(GetProcessHeap(), 0, sizeof(GLYPHMETRICSFLOAT) * strlen(text));
4243 int i;
4244 LOGFONTA lf;
4245 float offset_x;
4246 size_t textlen;
4247 HFONT font = NULL, oldfont = NULL;
4248 char *raw_outline;
4250 sprintf(name, "text ('%s', %f, %f)", text, deviation, extrusion);
4252 hr = D3DXCreateTextA(device, hdc, text, deviation, extrusion, &d3dxmesh, NULL, glyphmetrics_float);
4253 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
4255 /* must select a modified font having lfHeight = otm.otmEMSquare before
4256 * calling GetGlyphOutline to get the expected values */
4257 ok(GetObjectA(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf), "Failed to get current DC font.\n");
4258 ok(GetOutlineTextMetricsA(hdc, sizeof(otm), &otm), "Failed to get DC font outline.\n");
4259 lf.lfHeight = otm.otmEMSquare;
4260 lf.lfWidth = 0;
4261 ok(!!(font = CreateFontIndirectA(&lf)), "Failed to create font.\n");
4263 textlen = strlen(text);
4264 glyphs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, textlen * sizeof(*glyphs));
4265 oldfont = SelectObject(hdc, font);
4267 for (i = 0; i < textlen; i++)
4269 GetGlyphOutlineA(hdc, text[i], GGO_NATIVE, &gm, 0, NULL, &identity);
4270 compare_float(glyphmetrics_float[i].gmfBlackBoxX, gm.gmBlackBoxX / (float)otm.otmEMSquare);
4271 compare_float(glyphmetrics_float[i].gmfBlackBoxY, gm.gmBlackBoxY / (float)otm.otmEMSquare);
4272 compare_float(glyphmetrics_float[i].gmfptGlyphOrigin.x, gm.gmptGlyphOrigin.x / (float)otm.otmEMSquare);
4273 compare_float(glyphmetrics_float[i].gmfptGlyphOrigin.y, gm.gmptGlyphOrigin.y / (float)otm.otmEMSquare);
4274 compare_float(glyphmetrics_float[i].gmfCellIncX, gm.gmCellIncX / (float)otm.otmEMSquare);
4275 compare_float(glyphmetrics_float[i].gmfCellIncY, gm.gmCellIncY / (float)otm.otmEMSquare);
4278 if (deviation == 0.0f)
4279 deviation = 1.0f / otm.otmEMSquare;
4281 offset_x = 0.0f;
4282 for (i = 0; i < textlen; i++)
4284 DWORD datasize;
4286 glyphs[i].offset_x = offset_x;
4288 datasize = GetGlyphOutlineA(hdc, text[i], GGO_NATIVE, &gm, 0, NULL, &identity);
4289 ok(datasize != GDI_ERROR, "Failed to retrieve GDI glyph outline size.\n");
4290 raw_outline = HeapAlloc(GetProcessHeap(), 0, datasize);
4291 datasize = GetGlyphOutlineA(hdc, text[i], GGO_NATIVE, &gm, datasize, raw_outline, &identity);
4292 ok(datasize != GDI_ERROR, "Failed to retrieve GDI glyph outline.\n");
4293 create_outline(&glyphs[i], raw_outline, datasize, deviation, otm.otmEMSquare);
4294 HeapFree(GetProcessHeap(), 0, raw_outline);
4296 offset_x += gm.gmCellIncX / (float)otm.otmEMSquare;
4299 SelectObject(hdc, oldfont);
4301 compute_text_mesh(&mesh, text, deviation, extrusion, otm.otmEMSquare, glyphs);
4302 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
4304 compare_text_outline_mesh(name, d3dxmesh, &mesh, textlen, extrusion, glyphs);
4306 free_mesh(&mesh);
4307 d3dxmesh->lpVtbl->Release(d3dxmesh);
4308 DeleteObject(font);
4309 HeapFree(GetProcessHeap(), 0, glyphmetrics_float);
4311 for (i = 0; i < textlen; i++)
4312 free_glyphinfo(&glyphs[i]);
4313 HeapFree(GetProcessHeap(), 0, glyphs);
4316 static void D3DXCreateTextTest(void)
4318 HRESULT hr;
4319 HDC hdc;
4320 IDirect3DDevice9* device;
4321 ID3DXMesh* d3dxmesh = NULL;
4322 HFONT hFont;
4323 OUTLINETEXTMETRICA otm;
4324 int number_of_vertices;
4325 int number_of_faces;
4326 struct test_context *test_context;
4328 if (!(test_context = new_test_context()))
4330 skip("Couldn't create test context\n");
4331 return;
4333 device = test_context->device;
4335 hdc = CreateCompatibleDC(NULL);
4337 hFont = CreateFontA(12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
4338 CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, "Arial");
4339 SelectObject(hdc, hFont);
4340 GetOutlineTextMetricsA(hdc, sizeof(otm), &otm);
4342 hr = D3DXCreateTextA(device, hdc, "wine", 0.001f, 0.4f, NULL, NULL, NULL);
4343 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4345 /* D3DXCreateTextA page faults from passing NULL text */
4347 hr = D3DXCreateTextW(device, hdc, NULL, 0.001f, 0.4f, &d3dxmesh, NULL, NULL);
4348 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4350 hr = D3DXCreateTextA(device, hdc, "", 0.001f, 0.4f, &d3dxmesh, NULL, NULL);
4351 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4353 hr = D3DXCreateTextA(device, hdc, " ", 0.001f, 0.4f, &d3dxmesh, NULL, NULL);
4354 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4356 hr = D3DXCreateTextA(NULL, hdc, "wine", 0.001f, 0.4f, &d3dxmesh, NULL, NULL);
4357 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4359 hr = D3DXCreateTextA(device, NULL, "wine", 0.001f, 0.4f, &d3dxmesh, NULL, NULL);
4360 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4362 hr = D3DXCreateTextA(device, hdc, "wine", -FLT_MIN, 0.4f, &d3dxmesh, NULL, NULL);
4363 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4365 hr = D3DXCreateTextA(device, hdc, "wine", 0.001f, -FLT_MIN, &d3dxmesh, NULL, NULL);
4366 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4368 /* deviation = 0.0f treated as if deviation = 1.0f / otm.otmEMSquare */
4369 hr = D3DXCreateTextA(device, hdc, "wine", 1.0f / otm.otmEMSquare, 0.4f, &d3dxmesh, NULL, NULL);
4370 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
4371 number_of_vertices = d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh);
4372 number_of_faces = d3dxmesh->lpVtbl->GetNumFaces(d3dxmesh);
4373 d3dxmesh->lpVtbl->Release(d3dxmesh);
4375 hr = D3DXCreateTextA(device, hdc, "wine", 0.0f, 0.4f, &d3dxmesh, NULL, NULL);
4376 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
4377 ok(number_of_vertices == d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh),
4378 "Got %d vertices, expected %d\n",
4379 d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh), number_of_vertices);
4380 ok(number_of_faces == d3dxmesh->lpVtbl->GetNumFaces(d3dxmesh),
4381 "Got %d faces, expected %d\n",
4382 d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh), number_of_faces);
4383 d3dxmesh->lpVtbl->Release(d3dxmesh);
4385 if (0)
4387 /* too much detail requested, so will appear to hang */
4388 trace("Waiting for D3DXCreateText to finish with deviation = FLT_MIN ...\n");
4389 hr = D3DXCreateTextA(device, hdc, "wine", FLT_MIN, 0.4f, &d3dxmesh, NULL, NULL);
4390 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
4391 if (SUCCEEDED(hr) && d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh);
4392 trace("D3DXCreateText finish with deviation = FLT_MIN\n");
4395 hr = D3DXCreateTextA(device, hdc, "wine", 0.001f, 0.4f, &d3dxmesh, NULL, NULL);
4396 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
4397 if (SUCCEEDED(hr) && d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh);
4399 test_createtext(device, hdc, "wine", FLT_MAX, 0.4f);
4400 test_createtext(device, hdc, "wine", 0.001f, FLT_MIN);
4401 test_createtext(device, hdc, "wine", 0.001f, 0.0f);
4402 test_createtext(device, hdc, "wine", 0.001f, FLT_MAX);
4403 test_createtext(device, hdc, "wine", 0.0f, 1.0f);
4404 test_createtext(device, hdc, " wine", 1.0f, 0.0f);
4405 test_createtext(device, hdc, "wine ", 1.0f, 0.0f);
4406 test_createtext(device, hdc, "wi ne", 1.0f, 0.0f);
4408 DeleteDC(hdc);
4409 DeleteObject(hFont);
4411 free_test_context(test_context);
4414 static void test_get_decl_length(void)
4416 static const D3DVERTEXELEMENT9 declaration1[] =
4418 {0, 0, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4419 {1, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4420 {2, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4421 {3, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4422 {4, 0, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4423 {5, 0, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4424 {6, 0, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4425 {7, 0, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4426 {8, 0, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4427 {9, 0, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4428 {10, 0, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4429 {11, 0, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4430 {12, 0, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4431 {13, 0, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4432 {14, 0, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4433 D3DDECL_END(),
4435 static const D3DVERTEXELEMENT9 declaration2[] =
4437 {0, 8, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4438 {1, 8, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4439 {2, 8, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4440 {3, 8, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4441 {4, 8, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4442 {5, 8, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4443 {6, 8, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4444 {7, 8, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4445 {0, 8, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4446 {1, 8, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4447 {2, 8, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4448 {3, 8, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4449 {4, 8, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4450 {5, 8, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4451 {6, 8, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4452 {7, 8, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4453 D3DDECL_END(),
4455 UINT size;
4457 size = D3DXGetDeclLength(declaration1);
4458 ok(size == 15, "Got size %u, expected 15.\n", size);
4460 size = D3DXGetDeclLength(declaration2);
4461 ok(size == 16, "Got size %u, expected 16.\n", size);
4464 static void test_get_decl_vertex_size(void)
4466 static const D3DVERTEXELEMENT9 declaration1[] =
4468 {0, 0, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4469 {1, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4470 {2, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4471 {3, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4472 {4, 0, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4473 {5, 0, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4474 {6, 0, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4475 {7, 0, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4476 {8, 0, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4477 {9, 0, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4478 {10, 0, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4479 {11, 0, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4480 {12, 0, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4481 {13, 0, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4482 {14, 0, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4483 D3DDECL_END(),
4485 static const D3DVERTEXELEMENT9 declaration2[] =
4487 {0, 8, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4488 {1, 8, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4489 {2, 8, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4490 {3, 8, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4491 {4, 8, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4492 {5, 8, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4493 {6, 8, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4494 {7, 8, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4495 {0, 8, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4496 {1, 8, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4497 {2, 8, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4498 {3, 8, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4499 {4, 8, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4500 {5, 8, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4501 {6, 8, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4502 {7, 8, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4503 D3DDECL_END(),
4505 static const UINT sizes1[] =
4507 4, 8, 12, 16,
4508 4, 4, 4, 8,
4509 4, 4, 8, 4,
4510 4, 4, 8, 0,
4512 static const UINT sizes2[] =
4514 12, 16, 20, 24,
4515 12, 12, 16, 16,
4517 unsigned int i;
4518 UINT size;
4520 size = D3DXGetDeclVertexSize(NULL, 0);
4521 ok(size == 0, "Got size %#x, expected 0.\n", size);
4523 for (i = 0; i < 16; ++i)
4525 size = D3DXGetDeclVertexSize(declaration1, i);
4526 ok(size == sizes1[i], "Got size %u for stream %u, expected %u.\n", size, i, sizes1[i]);
4529 for (i = 0; i < 8; ++i)
4531 size = D3DXGetDeclVertexSize(declaration2, i);
4532 ok(size == sizes2[i], "Got size %u for stream %u, expected %u.\n", size, i, sizes2[i]);
4536 static void D3DXGenerateAdjacencyTest(void)
4538 HRESULT hr;
4539 IDirect3DDevice9 *device;
4540 ID3DXMesh *d3dxmesh = NULL;
4541 D3DXVECTOR3 *vertices = NULL;
4542 WORD *indices = NULL;
4543 int i;
4544 struct {
4545 DWORD num_vertices;
4546 D3DXVECTOR3 vertices[6];
4547 DWORD num_faces;
4548 WORD indices[3 * 3];
4549 FLOAT epsilon;
4550 DWORD adjacency[3 * 3];
4551 } test_data[] = {
4552 { /* for epsilon < 0, indices must match for faces to be adjacent */
4553 4, {{0.0, 0.0, 0.0}, {1.0, 0.0, 0.0}, {1.0, 1.0, 0.0}, {0.0, 1.0, 0.0}},
4554 2, {0, 1, 2, 0, 2, 3},
4555 -1.0,
4556 {-1, -1, 1, 0, -1, -1},
4559 6, {{0.0, 0.0, 0.0}, {1.0, 0.0, 0.0}, {1.0, 1.0, 0.0}, {0.0, 0.0, 0.0}, {1.0, 1.0, 0.0}, {0.0, 1.0, 0.0}},
4560 2, {0, 1, 2, 3, 4, 5},
4561 -1.0,
4562 {-1, -1, -1, -1, -1, -1},
4564 { /* for epsilon == 0, indices or vertices must match for faces to be adjacent */
4565 6, {{0.0, 0.0, 0.0}, {1.0, 0.0, 0.0}, {1.0, 1.0, 0.0}, {0.0, 0.0, 0.0}, {1.0, 1.0, 0.0}, {0.0, 1.0, 0.0}},
4566 2, {0, 1, 2, 3, 4, 5},
4567 0.0,
4568 {-1, -1, 1, 0, -1, -1},
4570 { /* for epsilon > 0, vertices must be less than (but NOT equal to) epsilon distance away */
4571 6, {{0.0, 0.0, 0.0}, {1.0, 0.0, 0.0}, {1.0, 1.0, 0.0}, {0.0, 0.0, 0.25}, {1.0, 1.0, 0.25}, {0.0, 1.0, 0.25}},
4572 2, {0, 1, 2, 3, 4, 5},
4573 0.25,
4574 {-1, -1, -1, -1, -1, -1},
4576 { /* for epsilon > 0, vertices must be less than (but NOT equal to) epsilon distance away */
4577 6, {{0.0, 0.0, 0.0}, {1.0, 0.0, 0.0}, {1.0, 1.0, 0.0}, {0.0, 0.0, 0.25}, {1.0, 1.0, 0.25}, {0.0, 1.0, 0.25}},
4578 2, {0, 1, 2, 3, 4, 5},
4579 0.250001,
4580 {-1, -1, 1, 0, -1, -1},
4582 { /* length between vertices are compared to epsilon, not the individual dimension deltas */
4583 6, {{0.0, 0.0, 0.0}, {1.0, 0.0, 0.0}, {1.0, 1.0, 0.0}, {0.0, 0.25, 0.25}, {1.0, 1.25, 0.25}, {0.0, 1.25, 0.25}},
4584 2, {0, 1, 2, 3, 4, 5},
4585 0.353, /* < sqrt(0.25*0.25 + 0.25*0.25) */
4586 {-1, -1, -1, -1, -1, -1},
4589 6, {{0.0, 0.0, 0.0}, {1.0, 0.0, 0.0}, {1.0, 1.0, 0.0}, {0.0, 0.25, 0.25}, {1.0, 1.25, 0.25}, {0.0, 1.25, 0.25}},
4590 2, {0, 1, 2, 3, 4, 5},
4591 0.354, /* > sqrt(0.25*0.25 + 0.25*0.25) */
4592 {-1, -1, 1, 0, -1, -1},
4594 { /* adjacent faces must have opposite winding orders at the shared edge */
4595 4, {{0.0, 0.0, 0.0}, {1.0, 0.0, 0.0}, {1.0, 1.0, 0.0}, {0.0, 1.0, 0.0}},
4596 2, {0, 1, 2, 0, 3, 2},
4597 0.0,
4598 {-1, -1, -1, -1, -1, -1},
4601 struct test_context *test_context;
4603 if (!(test_context = new_test_context()))
4605 skip("Couldn't create test context\n");
4606 return;
4608 device = test_context->device;
4610 for (i = 0; i < ARRAY_SIZE(test_data); i++)
4612 DWORD adjacency[ARRAY_SIZE(test_data[0].adjacency)];
4613 int j;
4615 if (d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh);
4616 d3dxmesh = NULL;
4618 hr = D3DXCreateMeshFVF(test_data[i].num_faces, test_data[i].num_vertices, 0, D3DFVF_XYZ, device, &d3dxmesh);
4619 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
4621 hr = d3dxmesh->lpVtbl->LockVertexBuffer(d3dxmesh, D3DLOCK_DISCARD, (void**)&vertices);
4622 ok(hr == D3D_OK, "test %d: Got result %x, expected %x (D3D_OK)\n", i, hr, D3D_OK);
4623 if (FAILED(hr)) continue;
4624 CopyMemory(vertices, test_data[i].vertices, test_data[i].num_vertices * sizeof(test_data[0].vertices[0]));
4625 d3dxmesh->lpVtbl->UnlockVertexBuffer(d3dxmesh);
4627 hr = d3dxmesh->lpVtbl->LockIndexBuffer(d3dxmesh, D3DLOCK_DISCARD, (void**)&indices);
4628 ok(hr == D3D_OK, "test %d: Got result %x, expected %x (D3D_OK)\n", i, hr, D3D_OK);
4629 if (FAILED(hr)) continue;
4630 CopyMemory(indices, test_data[i].indices, test_data[i].num_faces * 3 * sizeof(test_data[0].indices[0]));
4631 d3dxmesh->lpVtbl->UnlockIndexBuffer(d3dxmesh);
4633 if (i == 0) {
4634 hr = d3dxmesh->lpVtbl->GenerateAdjacency(d3dxmesh, 0.0f, NULL);
4635 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4638 hr = d3dxmesh->lpVtbl->GenerateAdjacency(d3dxmesh, test_data[i].epsilon, adjacency);
4639 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
4640 if (FAILED(hr)) continue;
4642 for (j = 0; j < test_data[i].num_faces * 3; j++)
4643 ok(adjacency[j] == test_data[i].adjacency[j],
4644 "Test %d adjacency %d: Got result %u, expected %u\n", i, j,
4645 adjacency[j], test_data[i].adjacency[j]);
4647 if (d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh);
4649 free_test_context(test_context);
4652 static void test_update_semantics(void)
4654 HRESULT hr;
4655 struct test_context *test_context = NULL;
4656 ID3DXMesh *mesh = NULL;
4657 D3DVERTEXELEMENT9 declaration0[] =
4659 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4660 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4661 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4662 D3DDECL_END()
4664 D3DVERTEXELEMENT9 declaration_pos_type_color[] =
4666 {0, 0, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4667 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4668 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4669 D3DDECL_END()
4671 D3DVERTEXELEMENT9 declaration_smaller[] =
4673 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4674 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4675 D3DDECL_END()
4677 D3DVERTEXELEMENT9 declaration_larger[] =
4679 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4680 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4681 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4682 {0, 40, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT, 0},
4683 D3DDECL_END()
4685 D3DVERTEXELEMENT9 declaration_multiple_streams[] =
4687 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4688 {1, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT, 0},
4689 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4690 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4692 D3DDECL_END()
4694 D3DVERTEXELEMENT9 declaration_double_usage[] =
4696 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4697 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4698 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4699 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4700 D3DDECL_END()
4702 D3DVERTEXELEMENT9 declaration_undefined_type[] =
4704 {0, 0, D3DDECLTYPE_UNUSED+1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4705 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4706 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4707 D3DDECL_END()
4709 D3DVERTEXELEMENT9 declaration_not_4_byte_aligned_offset[] =
4711 {0, 3, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4712 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4713 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4714 D3DDECL_END()
4716 static const struct
4718 D3DXVECTOR3 position0;
4719 D3DXVECTOR3 position1;
4720 D3DXVECTOR3 normal;
4721 DWORD color;
4723 vertices[] =
4725 { { 0.0f, 1.0f, 0.f}, { 1.0f, 0.0f, 0.f}, {0.0f, 0.0f, 1.0f}, 0xffff0000 },
4726 { { 1.0f, -1.0f, 0.f}, {-1.0f, -1.0f, 0.f}, {0.0f, 0.0f, 1.0f}, 0xff00ff00 },
4727 { {-1.0f, -1.0f, 0.f}, {-1.0f, 1.0f, 0.f}, {0.0f, 0.0f, 1.0f}, 0xff0000ff },
4729 unsigned int faces[] = {0, 1, 2};
4730 unsigned int attributes[] = {0};
4731 unsigned int num_faces = ARRAY_SIZE(faces) / 3;
4732 unsigned int num_vertices = ARRAY_SIZE(vertices);
4733 int offset = sizeof(D3DXVECTOR3);
4734 DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
4735 void *vertex_buffer;
4736 void *index_buffer;
4737 DWORD *attributes_buffer;
4738 D3DVERTEXELEMENT9 declaration[MAX_FVF_DECL_SIZE];
4739 D3DVERTEXELEMENT9 *decl_ptr;
4740 DWORD exp_vertex_size = sizeof(*vertices);
4741 DWORD vertex_size = 0;
4742 int equal;
4743 int i = 0;
4744 int *decl_mem;
4745 int filler_a = 0xaaaaaaaa;
4746 int filler_b = 0xbbbbbbbb;
4748 test_context = new_test_context();
4749 if (!test_context)
4751 skip("Couldn't create a test_context\n");
4752 goto cleanup;
4755 hr = D3DXCreateMesh(num_faces, num_vertices, options, declaration0,
4756 test_context->device, &mesh);
4757 if (FAILED(hr))
4759 skip("Couldn't create test mesh %#x\n", hr);
4760 goto cleanup;
4763 mesh->lpVtbl->LockVertexBuffer(mesh, 0, &vertex_buffer);
4764 memcpy(vertex_buffer, vertices, sizeof(vertices));
4765 mesh->lpVtbl->UnlockVertexBuffer(mesh);
4767 mesh->lpVtbl->LockIndexBuffer(mesh, 0, &index_buffer);
4768 memcpy(index_buffer, faces, sizeof(faces));
4769 mesh->lpVtbl->UnlockIndexBuffer(mesh);
4771 mesh->lpVtbl->LockAttributeBuffer(mesh, 0, &attributes_buffer);
4772 memcpy(attributes_buffer, attributes, sizeof(attributes));
4773 mesh->lpVtbl->UnlockAttributeBuffer(mesh);
4775 /* Get the declaration and try to change it */
4776 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4777 if (FAILED(hr))
4779 skip("Couldn't get vertex declaration %#x\n", hr);
4780 goto cleanup;
4782 equal = memcmp(declaration, declaration0, sizeof(declaration0));
4783 ok(equal == 0, "Vertex declarations were not equal\n");
4785 for (decl_ptr = declaration; decl_ptr->Stream != 0xFF; decl_ptr++)
4787 if (decl_ptr->Usage == D3DDECLUSAGE_POSITION)
4789 /* Use second vertex position instead of first */
4790 decl_ptr->Offset = offset;
4794 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration);
4795 ok(hr == D3D_OK, "Test UpdateSemantics, got %#x expected %#x\n", hr, D3D_OK);
4797 /* Check that declaration was written by getting it again */
4798 memset(declaration, 0, sizeof(declaration));
4799 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4800 if (FAILED(hr))
4802 skip("Couldn't get vertex declaration %#x\n", hr);
4803 goto cleanup;
4806 for (decl_ptr = declaration; decl_ptr->Stream != 0xFF; decl_ptr++)
4808 if (decl_ptr->Usage == D3DDECLUSAGE_POSITION)
4810 ok(decl_ptr->Offset == offset, "Test UpdateSemantics, got offset %d expected %d\n",
4811 decl_ptr->Offset, offset);
4815 /* Check that GetDeclaration only writes up to the D3DDECL_END() marker and
4816 * not the full MAX_FVF_DECL_SIZE elements.
4818 memset(declaration, filler_a, sizeof(declaration));
4819 memcpy(declaration, declaration0, sizeof(declaration0));
4820 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration);
4821 ok(hr == D3D_OK, "Test UpdateSemantics, "
4822 "got %#x expected D3D_OK\n", hr);
4823 memset(declaration, filler_b, sizeof(declaration));
4824 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4825 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4826 decl_mem = (int*)declaration;
4827 for (i = sizeof(declaration0)/sizeof(*decl_mem); i < sizeof(declaration)/sizeof(*decl_mem); i++)
4829 equal = memcmp(&decl_mem[i], &filler_b, sizeof(filler_b));
4830 ok(equal == 0,
4831 "GetDeclaration wrote past the D3DDECL_END() marker. "
4832 "Got %#x, expected %#x\n", decl_mem[i], filler_b);
4833 if (equal != 0) break;
4836 /* UpdateSemantics does not check for overlapping fields */
4837 memset(declaration, 0, sizeof(declaration));
4838 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4839 if (FAILED(hr))
4841 skip("Couldn't get vertex declaration %#x\n", hr);
4842 goto cleanup;
4845 for (decl_ptr = declaration; decl_ptr->Stream != 0xFF; decl_ptr++)
4847 if (decl_ptr->Type == D3DDECLTYPE_FLOAT3)
4849 decl_ptr->Type = D3DDECLTYPE_FLOAT4;
4853 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration);
4854 ok(hr == D3D_OK, "Test UpdateSemantics for overlapping fields, "
4855 "got %#x expected D3D_OK\n", hr);
4857 /* Set the position type to color instead of float3 */
4858 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_pos_type_color);
4859 ok(hr == D3D_OK, "Test UpdateSemantics position type color, "
4860 "got %#x expected D3D_OK\n", hr);
4862 /* The following test cases show that NULL, smaller or larger declarations,
4863 * and declarations with non-zero Stream values are not accepted.
4864 * UpdateSemantics returns D3DERR_INVALIDCALL and the previously set
4865 * declaration will be used by DrawSubset, GetNumBytesPerVertex, and
4866 * GetDeclaration.
4869 /* Null declaration (invalid declaration) */
4870 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4871 hr = mesh->lpVtbl->UpdateSemantics(mesh, NULL);
4872 ok(hr == D3DERR_INVALIDCALL, "Test UpdateSemantics null pointer declaration, "
4873 "got %#x expected D3DERR_INVALIDCALL\n", hr);
4874 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4875 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4876 vertex_size, exp_vertex_size);
4877 memset(declaration, 0, sizeof(declaration));
4878 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4879 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4880 equal = memcmp(declaration, declaration0, sizeof(declaration0));
4881 ok(equal == 0, "Vertex declarations were not equal\n");
4883 /* Smaller vertex declaration (invalid declaration) */
4884 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4885 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_smaller);
4886 ok(hr == D3DERR_INVALIDCALL, "Test UpdateSemantics for smaller vertex declaration, "
4887 "got %#x expected D3DERR_INVALIDCALL\n", hr);
4888 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4889 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4890 vertex_size, exp_vertex_size);
4891 memset(declaration, 0, sizeof(declaration));
4892 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4893 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4894 equal = memcmp(declaration, declaration0, sizeof(declaration0));
4895 ok(equal == 0, "Vertex declarations were not equal\n");
4897 /* Larger vertex declaration (invalid declaration) */
4898 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4899 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_larger);
4900 ok(hr == D3DERR_INVALIDCALL, "Test UpdateSemantics for larger vertex declaration, "
4901 "got %#x expected D3DERR_INVALIDCALL\n", hr);
4902 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4903 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4904 vertex_size, exp_vertex_size);
4905 memset(declaration, 0, sizeof(declaration));
4906 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4907 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4908 equal = memcmp(declaration, declaration0, sizeof(declaration0));
4909 ok(equal == 0, "Vertex declarations were not equal\n");
4911 /* Use multiple streams and keep the same vertex size (invalid declaration) */
4912 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4913 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_multiple_streams);
4914 ok(hr == D3DERR_INVALIDCALL, "Test UpdateSemantics using multiple streams, "
4915 "got %#x expected D3DERR_INVALIDCALL\n", hr);
4916 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4917 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4918 vertex_size, exp_vertex_size);
4919 memset(declaration, 0, sizeof(declaration));
4920 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4921 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4922 equal = memcmp(declaration, declaration0, sizeof(declaration0));
4923 ok(equal == 0, "Vertex declarations were not equal\n");
4925 /* The next following test cases show that some invalid declarations are
4926 * accepted with a D3D_OK. An access violation is thrown on Windows if
4927 * DrawSubset is called. The methods GetNumBytesPerVertex and GetDeclaration
4928 * are not affected, which indicates that the declaration is cached.
4931 /* Double usage (invalid declaration) */
4932 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4933 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_double_usage);
4934 ok(hr == D3D_OK, "Test UpdateSemantics double usage, "
4935 "got %#x expected D3D_OK\n", hr);
4936 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4937 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4938 vertex_size, exp_vertex_size);
4939 memset(declaration, 0, sizeof(declaration));
4940 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4941 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4942 equal = memcmp(declaration, declaration_double_usage, sizeof(declaration_double_usage));
4943 ok(equal == 0, "Vertex declarations were not equal\n");
4945 /* Set the position to an undefined type (invalid declaration) */
4946 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4947 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_undefined_type);
4948 ok(hr == D3D_OK, "Test UpdateSemantics undefined type, "
4949 "got %#x expected D3D_OK\n", hr);
4950 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4951 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4952 vertex_size, exp_vertex_size);
4953 memset(declaration, 0, sizeof(declaration));
4954 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4955 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4956 equal = memcmp(declaration, declaration_undefined_type, sizeof(declaration_undefined_type));
4957 ok(equal == 0, "Vertex declarations were not equal\n");
4959 /* Use a not 4 byte aligned offset (invalid declaration) */
4960 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4961 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_not_4_byte_aligned_offset);
4962 ok(hr == D3D_OK, "Test UpdateSemantics not 4 byte aligned offset, "
4963 "got %#x expected D3D_OK\n", hr);
4964 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4965 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4966 vertex_size, exp_vertex_size);
4967 memset(declaration, 0, sizeof(declaration));
4968 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4969 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4970 equal = memcmp(declaration, declaration_not_4_byte_aligned_offset,
4971 sizeof(declaration_not_4_byte_aligned_offset));
4972 ok(equal == 0, "Vertex declarations were not equal\n");
4974 cleanup:
4975 if (mesh)
4976 mesh->lpVtbl->Release(mesh);
4978 free_test_context(test_context);
4981 static void test_create_skin_info(void)
4983 D3DVERTEXELEMENT9 empty_declaration[] = { D3DDECL_END() };
4984 D3DVERTEXELEMENT9 declaration_out[MAX_FVF_DECL_SIZE];
4985 const D3DVERTEXELEMENT9 declaration_with_nonzero_stream[] = {
4986 {1, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
4987 D3DDECL_END()
4989 D3DVERTEXELEMENT9 declaration[MAX_FVF_DECL_SIZE];
4990 DWORD exp_vertices[2], vertices[2];
4991 float exp_weights[2], weights[2];
4992 const char *exp_string, *string;
4993 ID3DXSkinInfo *skininfo = NULL;
4994 DWORD exp_fvf, fvf;
4995 unsigned int i;
4996 HRESULT hr;
4998 hr = D3DXCreateSkinInfo(0, empty_declaration, 0, &skininfo);
4999 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5000 if (skininfo) IUnknown_Release(skininfo);
5001 skininfo = NULL;
5003 hr = D3DXCreateSkinInfo(1, NULL, 1, &skininfo);
5004 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5006 hr = D3DXCreateSkinInfo(1, declaration_with_nonzero_stream, 1, &skininfo);
5007 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5009 hr = D3DXCreateSkinInfoFVF(1, 0, 1, &skininfo);
5010 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5011 if (skininfo)
5013 ID3DXSkinInfo *clone = NULL;
5014 DWORD dword_result;
5015 float flt_result;
5016 const char *string_result;
5017 D3DXMATRIX *transform;
5018 D3DXMATRIX identity_matrix;
5020 /* test initial values */
5021 hr = skininfo->lpVtbl->GetDeclaration(skininfo, declaration_out);
5022 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5023 if (SUCCEEDED(hr))
5024 compare_elements(declaration_out, empty_declaration, __LINE__, 0);
5026 dword_result = skininfo->lpVtbl->GetNumBones(skininfo);
5027 ok(dword_result == 1, "Expected 1, got %u\n", dword_result);
5029 flt_result = skininfo->lpVtbl->GetMinBoneInfluence(skininfo);
5030 ok(flt_result == 0.0f, "Expected 0.0, got %g\n", flt_result);
5032 string_result = skininfo->lpVtbl->GetBoneName(skininfo, 0);
5033 ok(string_result == NULL, "Expected NULL, got %p\n", string_result);
5035 dword_result = skininfo->lpVtbl->GetFVF(skininfo);
5036 ok(dword_result == 0, "Expected 0, got %u\n", dword_result);
5038 dword_result = skininfo->lpVtbl->GetNumBoneInfluences(skininfo, 0);
5039 ok(dword_result == 0, "Expected 0, got %u\n", dword_result);
5041 dword_result = skininfo->lpVtbl->GetNumBoneInfluences(skininfo, 1);
5042 ok(dword_result == 0, "Expected 0, got %u\n", dword_result);
5044 transform = skininfo->lpVtbl->GetBoneOffsetMatrix(skininfo, -1);
5045 ok(transform == NULL, "Expected NULL, got %p\n", transform);
5047 hr = skininfo->lpVtbl->Clone(skininfo, &clone);
5048 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5049 IUnknown_Release(clone);
5052 /* test [GS]etBoneOffsetMatrix */
5053 hr = skininfo->lpVtbl->SetBoneOffsetMatrix(skininfo, 1, &identity_matrix);
5054 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5056 hr = skininfo->lpVtbl->SetBoneOffsetMatrix(skininfo, 0, NULL);
5057 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5059 D3DXMatrixIdentity(&identity_matrix);
5060 hr = skininfo->lpVtbl->SetBoneOffsetMatrix(skininfo, 0, &identity_matrix);
5061 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5063 transform = skininfo->lpVtbl->GetBoneOffsetMatrix(skininfo, 0);
5064 check_matrix(transform, &identity_matrix);
5068 /* test [GS]etBoneName */
5069 const char *name_in = "testBoneName";
5070 const char *string_result2;
5072 hr = skininfo->lpVtbl->SetBoneName(skininfo, 1, name_in);
5073 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5075 hr = skininfo->lpVtbl->SetBoneName(skininfo, 0, NULL);
5076 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5078 hr = skininfo->lpVtbl->SetBoneName(skininfo, 0, name_in);
5079 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5081 string_result = skininfo->lpVtbl->GetBoneName(skininfo, 0);
5082 ok(string_result != NULL, "Expected non-NULL string, got %p\n", string_result);
5083 ok(!strcmp(string_result, name_in), "Expected '%s', got '%s'\n", name_in, string_result);
5085 string_result2 = skininfo->lpVtbl->GetBoneName(skininfo, 0);
5086 ok(string_result == string_result2, "Expected %p, got %p\n", string_result, string_result2);
5088 string_result = skininfo->lpVtbl->GetBoneName(skininfo, 1);
5089 ok(string_result == NULL, "Expected NULL, got %p\n", string_result);
5093 /* test [GS]etBoneInfluence */
5094 DWORD num_influences;
5096 /* vertex and weight arrays untouched when num_influences is 0 */
5097 vertices[0] = 0xdeadbeef;
5098 weights[0] = FLT_MAX;
5099 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, vertices, weights);
5100 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5101 ok(vertices[0] == 0xdeadbeef, "expected 0xdeadbeef, got %#x\n", vertices[0]);
5102 ok(weights[0] == FLT_MAX, "expected %g, got %g\n", FLT_MAX, weights[0]);
5104 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 1, vertices, weights);
5105 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5107 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, NULL, NULL);
5108 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5110 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, vertices, NULL);
5111 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5113 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, NULL, weights);
5114 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5117 /* no vertex or weight value checking */
5118 exp_vertices[0] = 0;
5119 exp_vertices[1] = 0x87654321;
5120 exp_weights[0] = 0.5;
5121 exp_weights[1] = NAN;
5122 num_influences = 2;
5124 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 1, num_influences, vertices, weights);
5125 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5127 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, num_influences, NULL, weights);
5128 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5130 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, num_influences, vertices, NULL);
5131 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5133 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, num_influences, NULL, NULL);
5134 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5136 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, num_influences, exp_vertices, exp_weights);
5137 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5139 memset(vertices, 0, sizeof(vertices));
5140 memset(weights, 0, sizeof(weights));
5141 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, vertices, weights);
5142 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5143 for (i = 0; i < num_influences; i++) {
5144 ok(exp_vertices[i] == vertices[i],
5145 "influence[%d]: expected vertex %u, got %u\n", i, exp_vertices[i], vertices[i]);
5146 ok((isnan(exp_weights[i]) && isnan(weights[i])) || exp_weights[i] == weights[i],
5147 "influence[%d]: expected weights %g, got %g\n", i, exp_weights[i], weights[i]);
5150 /* vertices and weights aren't returned after setting num_influences to 0 */
5151 memset(vertices, 0, sizeof(vertices));
5152 memset(weights, 0, sizeof(weights));
5153 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, 0, vertices, weights);
5154 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5156 vertices[0] = 0xdeadbeef;
5157 weights[0] = FLT_MAX;
5158 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, vertices, weights);
5159 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5160 ok(vertices[0] == 0xdeadbeef, "expected vertex 0xdeadbeef, got %u\n", vertices[0]);
5161 ok(weights[0] == FLT_MAX, "expected weight %g, got %g\n", FLT_MAX, weights[0]);
5163 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, num_influences, exp_vertices, exp_weights);
5164 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5168 /* test [GS]etFVF and [GS]etDeclaration */
5169 D3DVERTEXELEMENT9 declaration_in[MAX_FVF_DECL_SIZE];
5170 DWORD got_fvf;
5172 fvf = D3DFVF_XYZ;
5173 hr = skininfo->lpVtbl->SetDeclaration(skininfo, NULL);
5174 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5176 hr = skininfo->lpVtbl->SetDeclaration(skininfo, declaration_with_nonzero_stream);
5177 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5179 hr = skininfo->lpVtbl->SetFVF(skininfo, 0);
5180 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5182 hr = D3DXDeclaratorFromFVF(fvf, declaration_in);
5183 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5184 hr = skininfo->lpVtbl->SetDeclaration(skininfo, declaration_in);
5185 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5186 got_fvf = skininfo->lpVtbl->GetFVF(skininfo);
5187 ok(fvf == got_fvf, "Expected %#x, got %#x\n", fvf, got_fvf);
5188 hr = skininfo->lpVtbl->GetDeclaration(skininfo, declaration_out);
5189 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5190 compare_elements(declaration_out, declaration_in, __LINE__, 0);
5192 hr = skininfo->lpVtbl->SetDeclaration(skininfo, empty_declaration);
5193 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5194 got_fvf = skininfo->lpVtbl->GetFVF(skininfo);
5195 ok(got_fvf == 0, "Expected 0, got %#x\n", got_fvf);
5196 hr = skininfo->lpVtbl->GetDeclaration(skininfo, declaration_out);
5197 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5198 compare_elements(declaration_out, empty_declaration, __LINE__, 0);
5200 hr = skininfo->lpVtbl->SetFVF(skininfo, fvf);
5201 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5202 got_fvf = skininfo->lpVtbl->GetFVF(skininfo);
5203 ok(fvf == got_fvf, "Expected %#x, got %#x\n", fvf, got_fvf);
5204 hr = skininfo->lpVtbl->GetDeclaration(skininfo, declaration_out);
5205 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5206 compare_elements(declaration_out, declaration_in, __LINE__, 0);
5209 /* Test Clone() */
5210 hr = skininfo->lpVtbl->Clone(skininfo, NULL);
5211 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5213 clone = NULL;
5214 hr = skininfo->lpVtbl->Clone(skininfo, &clone);
5215 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5217 hr = clone->lpVtbl->GetDeclaration(clone, declaration);
5218 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5219 compare_elements(declaration, declaration_out, __LINE__, 0);
5221 hr = D3DXFVFFromDeclarator(declaration_out, &exp_fvf);
5222 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5223 fvf = clone->lpVtbl->GetFVF(clone);
5224 ok(fvf == exp_fvf, "Got unexpected fvf %#x.\n", fvf);
5226 exp_string = skininfo->lpVtbl->GetBoneName(skininfo, 0);
5227 string = clone->lpVtbl->GetBoneName(clone, 0);
5228 ok(!strcmp(string, exp_string), "Got unexpected bone 0 name %s.\n", debugstr_a(string));
5230 transform = clone->lpVtbl->GetBoneOffsetMatrix(clone, 0);
5231 check_matrix(transform, &identity_matrix);
5233 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, exp_vertices, exp_weights);
5234 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5235 hr = clone->lpVtbl->GetBoneInfluence(clone, 0, vertices, weights);
5236 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5238 for (i = 0; i < ARRAY_SIZE(vertices); ++i)
5240 ok(vertices[i] == exp_vertices[i], "influence[%u]: got unexpected vertex %u, expected %u.\n",
5241 i, vertices[i], exp_vertices[i]);
5242 ok(((DWORD *)weights)[i] == ((DWORD *)exp_weights)[i],
5243 "influence[%u]: got unexpected weight %.8e, expected %.8e.\n", i, weights[i], exp_weights[i]);
5246 IUnknown_Release(clone);
5248 if (skininfo) IUnknown_Release(skininfo);
5249 skininfo = NULL;
5251 hr = D3DXCreateSkinInfoFVF(1, D3DFVF_XYZ, 1, NULL);
5252 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5254 hr = D3DXCreateSkinInfo(1, NULL, 1, &skininfo);
5255 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5258 static void test_convert_adjacency_to_point_reps(void)
5260 HRESULT hr;
5261 struct test_context *test_context = NULL;
5262 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
5263 const DWORD options_16bit = D3DXMESH_SYSTEMMEM;
5264 const D3DVERTEXELEMENT9 declaration[] =
5266 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
5267 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
5268 {0, 24, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
5269 D3DDECL_END()
5271 const unsigned int VERTS_PER_FACE = 3;
5272 void *vertex_buffer;
5273 void *index_buffer;
5274 DWORD *attributes_buffer;
5275 int i, j;
5276 enum color { RED = 0xffff0000, GREEN = 0xff00ff00, BLUE = 0xff0000ff};
5277 struct vertex_pnc
5279 D3DXVECTOR3 position;
5280 D3DXVECTOR3 normal;
5281 enum color color; /* In case of manual visual inspection */
5283 D3DXVECTOR3 up = {0.0f, 0.0f, 1.0f};
5284 /* mesh0 (one face)
5286 * 0--1
5287 * | /
5288 * |/
5291 const struct vertex_pnc vertices0[] =
5293 {{ 0.0f, 3.0f, 0.f}, up, RED},
5294 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5295 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5297 const DWORD indices0[] = {0, 1, 2};
5298 const unsigned int num_vertices0 = ARRAY_SIZE(vertices0);
5299 const unsigned int num_faces0 = ARRAY_SIZE(indices0) / VERTS_PER_FACE;
5300 const DWORD adjacency0[] = {-1, -1, -1};
5301 const DWORD exp_point_rep0[] = {0, 1, 2};
5302 /* mesh1 (right)
5304 * 0--1 3
5305 * | / /|
5306 * |/ / |
5307 * 2 5--4
5309 const struct vertex_pnc vertices1[] =
5311 {{ 0.0f, 3.0f, 0.f}, up, RED},
5312 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5313 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5315 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5316 {{ 3.0f, 0.0f, 0.f}, up, RED},
5317 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5319 const DWORD indices1[] = {0, 1, 2, 3, 4, 5};
5320 const unsigned int num_vertices1 = ARRAY_SIZE(vertices1);
5321 const unsigned int num_faces1 = ARRAY_SIZE(indices1) / VERTS_PER_FACE;
5322 const DWORD adjacency1[] = {-1, 1, -1, -1, -1, 0};
5323 const DWORD exp_point_rep1[] = {0, 1, 2, 1, 4, 2};
5324 /* mesh2 (left)
5326 * 3 0--1
5327 * /| | /
5328 * / | |/
5329 * 5--4 2
5331 const struct vertex_pnc vertices2[] =
5333 {{ 0.0f, 3.0f, 0.f}, up, RED},
5334 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5335 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5337 {{-1.0f, 3.0f, 0.f}, up, RED},
5338 {{-1.0f, 0.0f, 0.f}, up, GREEN},
5339 {{-3.0f, 0.0f, 0.f}, up, BLUE},
5341 const DWORD indices2[] = {0, 1, 2, 3, 4, 5};
5342 const unsigned int num_vertices2 = ARRAY_SIZE(vertices2);
5343 const unsigned int num_faces2 = ARRAY_SIZE(indices2) / VERTS_PER_FACE;
5344 const DWORD adjacency2[] = {-1, -1, 1, 0, -1, -1};
5345 const DWORD exp_point_rep2[] = {0, 1, 2, 0, 2, 5};
5346 /* mesh3 (above)
5349 * /|
5350 * / |
5351 * 5--4
5352 * 0--1
5353 * | /
5354 * |/
5357 struct vertex_pnc vertices3[] =
5359 {{ 0.0f, 3.0f, 0.f}, up, RED},
5360 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5361 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5363 {{ 2.0f, 7.0f, 0.f}, up, BLUE},
5364 {{ 2.0f, 4.0f, 0.f}, up, GREEN},
5365 {{ 0.0f, 4.0f, 0.f}, up, RED},
5367 const DWORD indices3[] = {0, 1, 2, 3, 4, 5};
5368 const unsigned int num_vertices3 = ARRAY_SIZE(vertices3);
5369 const unsigned int num_faces3 = ARRAY_SIZE(indices3) / VERTS_PER_FACE;
5370 const DWORD adjacency3[] = {1, -1, -1, -1, 0, -1};
5371 const DWORD exp_point_rep3[] = {0, 1, 2, 3, 1, 0};
5372 /* mesh4 (below, tip against tip)
5374 * 0--1
5375 * | /
5376 * |/
5379 * |\
5380 * | \
5381 * 5--4
5383 struct vertex_pnc vertices4[] =
5385 {{ 0.0f, 3.0f, 0.f}, up, RED},
5386 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5387 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5389 {{ 0.0f, -4.0f, 0.f}, up, BLUE},
5390 {{ 2.0f, -7.0f, 0.f}, up, GREEN},
5391 {{ 0.0f, -7.0f, 0.f}, up, RED},
5393 const DWORD indices4[] = {0, 1, 2, 3, 4, 5};
5394 const unsigned int num_vertices4 = ARRAY_SIZE(vertices4);
5395 const unsigned int num_faces4 = ARRAY_SIZE(indices4) / VERTS_PER_FACE;
5396 const DWORD adjacency4[] = {-1, -1, -1, -1, -1, -1};
5397 const DWORD exp_point_rep4[] = {0, 1, 2, 3, 4, 5};
5398 /* mesh5 (gap in mesh)
5400 * 0 3-----4 15
5401 * / \ \ / / \
5402 * / \ \ / / \
5403 * 2-----1 5 17-----16
5404 * 6-----7 9 12-----13
5405 * \ / / \ \ /
5406 * \ / / \ \ /
5407 * 8 10-----11 14
5410 const struct vertex_pnc vertices5[] =
5412 {{ 0.0f, 1.0f, 0.f}, up, RED},
5413 {{ 1.0f, -1.0f, 0.f}, up, GREEN},
5414 {{-1.0f, -1.0f, 0.f}, up, BLUE},
5416 {{ 0.1f, 1.0f, 0.f}, up, RED},
5417 {{ 2.1f, 1.0f, 0.f}, up, BLUE},
5418 {{ 1.1f, -1.0f, 0.f}, up, GREEN},
5420 {{-1.0f, -1.1f, 0.f}, up, BLUE},
5421 {{ 1.0f, -1.1f, 0.f}, up, GREEN},
5422 {{ 0.0f, -3.1f, 0.f}, up, RED},
5424 {{ 1.1f, -1.1f, 0.f}, up, GREEN},
5425 {{ 2.1f, -3.1f, 0.f}, up, BLUE},
5426 {{ 0.1f, -3.1f, 0.f}, up, RED},
5428 {{ 1.2f, -1.1f, 0.f}, up, GREEN},
5429 {{ 3.2f, -1.1f, 0.f}, up, RED},
5430 {{ 2.2f, -3.1f, 0.f}, up, BLUE},
5432 {{ 2.2f, 1.0f, 0.f}, up, BLUE},
5433 {{ 3.2f, -1.0f, 0.f}, up, RED},
5434 {{ 1.2f, -1.0f, 0.f}, up, GREEN},
5436 const DWORD indices5[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17};
5437 const unsigned int num_vertices5 = ARRAY_SIZE(vertices5);
5438 const unsigned int num_faces5 = ARRAY_SIZE(indices5) / VERTS_PER_FACE;
5439 const DWORD adjacency5[] = {-1, 2, -1, -1, 5, -1, 0, -1, -1, 4, -1, -1, 5, -1, 3, -1, 4, 1};
5440 const DWORD exp_point_rep5[] = {0, 1, 2, 3, 4, 5, 2, 1, 8, 5, 10, 11, 5, 13, 10, 4, 13, 5};
5441 const WORD indices5_16bit[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17};
5442 /* mesh6 (indices re-ordering)
5444 * 0--1 6 3
5445 * | / /| |\
5446 * |/ / | | \
5447 * 2 8--7 5--4
5449 const struct vertex_pnc vertices6[] =
5451 {{ 0.0f, 3.0f, 0.f}, up, RED},
5452 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5453 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5455 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5456 {{ 3.0f, 0.0f, 0.f}, up, RED},
5457 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5459 {{ 4.0f, 3.0f, 0.f}, up, GREEN},
5460 {{ 6.0f, 0.0f, 0.f}, up, BLUE},
5461 {{ 4.0f, 0.0f, 0.f}, up, RED},
5463 const DWORD indices6[] = {0, 1, 2, 6, 7, 8, 3, 4, 5};
5464 const unsigned int num_vertices6 = ARRAY_SIZE(vertices6);
5465 const unsigned int num_faces6 = ARRAY_SIZE(indices6) / VERTS_PER_FACE;
5466 const DWORD adjacency6[] = {-1, 1, -1, 2, -1, 0, -1, -1, 1};
5467 const DWORD exp_point_rep6[] = {0, 1, 2, 1, 4, 5, 1, 5, 2};
5468 /* mesh7 (expands collapsed triangle)
5470 * 0--1 3
5471 * | / /|
5472 * |/ / |
5473 * 2 5--4
5475 const struct vertex_pnc vertices7[] =
5477 {{ 0.0f, 3.0f, 0.f}, up, RED},
5478 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5479 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5481 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5482 {{ 3.0f, 0.0f, 0.f}, up, RED},
5483 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5485 const DWORD indices7[] = {0, 1, 2, 3, 3, 3}; /* Face 1 is collapsed*/
5486 const unsigned int num_vertices7 = ARRAY_SIZE(vertices7);
5487 const unsigned int num_faces7 = ARRAY_SIZE(indices7) / VERTS_PER_FACE;
5488 const DWORD adjacency7[] = {-1, -1, -1, -1, -1, -1};
5489 const DWORD exp_point_rep7[] = {0, 1, 2, 3, 4, 5};
5490 /* mesh8 (indices re-ordering and double replacement)
5492 * 0--1 9 6
5493 * | / /| |\
5494 * |/ / | | \
5495 * 2 11-10 8--7
5496 * 3--4
5497 * | /
5498 * |/
5501 const struct vertex_pnc vertices8[] =
5503 {{ 0.0f, 3.0f, 0.f}, up, RED},
5504 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5505 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5507 {{ 4.0, -4.0, 0.f}, up, RED},
5508 {{ 6.0, -4.0, 0.f}, up, BLUE},
5509 {{ 4.0, -7.0, 0.f}, up, GREEN},
5511 {{ 4.0f, 3.0f, 0.f}, up, GREEN},
5512 {{ 6.0f, 0.0f, 0.f}, up, BLUE},
5513 {{ 4.0f, 0.0f, 0.f}, up, RED},
5515 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5516 {{ 3.0f, 0.0f, 0.f}, up, RED},
5517 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5519 const DWORD indices8[] = {0, 1, 2, 9, 10, 11, 6, 7, 8, 3, 4, 5};
5520 const unsigned int num_vertices8 = ARRAY_SIZE(vertices8);
5521 const unsigned int num_faces8 = ARRAY_SIZE(indices8) / VERTS_PER_FACE;
5522 const DWORD adjacency8[] = {-1, 1, -1, 2, -1, 0, -1, 3, 1, 2, -1, -1};
5523 const DWORD exp_point_rep8[] = {0, 1, 2, 3, 4, 5, 1, 4, 3, 1, 3, 2};
5524 /* mesh9 (right, shared vertices)
5526 * 0--1
5527 * | /|
5528 * |/ |
5529 * 2--3
5531 const struct vertex_pnc vertices9[] =
5533 {{ 0.0f, 3.0f, 0.f}, up, RED},
5534 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5535 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5537 {{ 2.0f, 0.0f, 0.f}, up, RED},
5539 const DWORD indices9[] = {0, 1, 2, 1, 3, 2};
5540 const unsigned int num_vertices9 = ARRAY_SIZE(vertices9);
5541 const unsigned int num_faces9 = ARRAY_SIZE(indices9) / VERTS_PER_FACE;
5542 const DWORD adjacency9[] = {-1, 1, -1, -1, -1, 0};
5543 const DWORD exp_point_rep9[] = {0, 1, 2, 3};
5544 /* All mesh data */
5545 ID3DXMesh *mesh = NULL;
5546 ID3DXMesh *mesh_null_check = NULL;
5547 unsigned int attributes[] = {0};
5548 struct
5550 const struct vertex_pnc *vertices;
5551 const DWORD *indices;
5552 const DWORD num_vertices;
5553 const DWORD num_faces;
5554 const DWORD *adjacency;
5555 const DWORD *exp_point_reps;
5556 const DWORD options;
5558 tc[] =
5561 vertices0,
5562 indices0,
5563 num_vertices0,
5564 num_faces0,
5565 adjacency0,
5566 exp_point_rep0,
5567 options
5570 vertices1,
5571 indices1,
5572 num_vertices1,
5573 num_faces1,
5574 adjacency1,
5575 exp_point_rep1,
5576 options
5579 vertices2,
5580 indices2,
5581 num_vertices2,
5582 num_faces2,
5583 adjacency2,
5584 exp_point_rep2,
5585 options
5588 vertices3,
5589 indices3,
5590 num_vertices3,
5591 num_faces3,
5592 adjacency3,
5593 exp_point_rep3,
5594 options
5597 vertices4,
5598 indices4,
5599 num_vertices4,
5600 num_faces4,
5601 adjacency4,
5602 exp_point_rep4,
5603 options
5606 vertices5,
5607 indices5,
5608 num_vertices5,
5609 num_faces5,
5610 adjacency5,
5611 exp_point_rep5,
5612 options
5615 vertices6,
5616 indices6,
5617 num_vertices6,
5618 num_faces6,
5619 adjacency6,
5620 exp_point_rep6,
5621 options
5624 vertices7,
5625 indices7,
5626 num_vertices7,
5627 num_faces7,
5628 adjacency7,
5629 exp_point_rep7,
5630 options
5633 vertices8,
5634 indices8,
5635 num_vertices8,
5636 num_faces8,
5637 adjacency8,
5638 exp_point_rep8,
5639 options
5642 vertices9,
5643 indices9,
5644 num_vertices9,
5645 num_faces9,
5646 adjacency9,
5647 exp_point_rep9,
5648 options
5651 vertices5,
5652 (DWORD*)indices5_16bit,
5653 num_vertices5,
5654 num_faces5,
5655 adjacency5,
5656 exp_point_rep5,
5657 options_16bit
5660 DWORD *point_reps = NULL;
5662 test_context = new_test_context();
5663 if (!test_context)
5665 skip("Couldn't create test context\n");
5666 goto cleanup;
5669 for (i = 0; i < ARRAY_SIZE(tc); i++)
5671 hr = D3DXCreateMesh(tc[i].num_faces, tc[i].num_vertices, tc[i].options, declaration,
5672 test_context->device, &mesh);
5673 if (FAILED(hr))
5675 skip("Couldn't create mesh %d. Got %x expected D3D_OK\n", i, hr);
5676 goto cleanup;
5679 if (i == 0) /* Save first mesh for later NULL checks */
5680 mesh_null_check = mesh;
5682 point_reps = HeapAlloc(GetProcessHeap(), 0, tc[i].num_vertices * sizeof(*point_reps));
5683 if (!point_reps)
5685 skip("Couldn't allocate point reps array.\n");
5686 goto cleanup;
5689 hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, &vertex_buffer);
5690 if (FAILED(hr))
5692 skip("Couldn't lock vertex buffer.\n");
5693 goto cleanup;
5695 memcpy(vertex_buffer, tc[i].vertices, tc[i].num_vertices * sizeof(*tc[i].vertices));
5696 hr = mesh->lpVtbl->UnlockVertexBuffer(mesh);
5697 if (FAILED(hr))
5699 skip("Couldn't unlock vertex buffer.\n");
5700 goto cleanup;
5703 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, &index_buffer);
5704 if (FAILED(hr))
5706 skip("Couldn't lock index buffer.\n");
5707 goto cleanup;
5709 if (tc[i].options & D3DXMESH_32BIT)
5711 memcpy(index_buffer, tc[i].indices, VERTS_PER_FACE * tc[i].num_faces * sizeof(DWORD));
5713 else
5715 memcpy(index_buffer, tc[i].indices, VERTS_PER_FACE * tc[i].num_faces * sizeof(WORD));
5717 hr = mesh->lpVtbl->UnlockIndexBuffer(mesh);
5718 if (FAILED(hr)) {
5719 skip("Couldn't unlock index buffer.\n");
5720 goto cleanup;
5723 hr = mesh->lpVtbl->LockAttributeBuffer(mesh, 0, &attributes_buffer);
5724 if (FAILED(hr))
5726 skip("Couldn't lock attributes buffer.\n");
5727 goto cleanup;
5729 memcpy(attributes_buffer, attributes, sizeof(attributes));
5730 hr = mesh->lpVtbl->UnlockAttributeBuffer(mesh);
5731 if (FAILED(hr))
5733 skip("Couldn't unlock attributes buffer.\n");
5734 goto cleanup;
5737 /* Convert adjacency to point representation */
5738 for (j = 0; j < tc[i].num_vertices; j++) point_reps[j] = -1;
5739 hr = mesh->lpVtbl->ConvertAdjacencyToPointReps(mesh, tc[i].adjacency, point_reps);
5740 ok(hr == D3D_OK, "ConvertAdjacencyToPointReps failed case %d. "
5741 "Got %x expected D3D_OK\n", i, hr);
5743 /* Check point representation */
5744 for (j = 0; j < tc[i].num_vertices; j++)
5746 ok(point_reps[j] == tc[i].exp_point_reps[j],
5747 "Unexpected point representation at (%d, %d)."
5748 " Got %d expected %d\n",
5749 i, j, point_reps[j], tc[i].exp_point_reps[j]);
5752 HeapFree(GetProcessHeap(), 0, point_reps);
5753 point_reps = NULL;
5755 if (i != 0) /* First mesh will be freed during cleanup */
5756 mesh->lpVtbl->Release(mesh);
5759 /* NULL checks */
5760 hr = mesh_null_check->lpVtbl->ConvertAdjacencyToPointReps(mesh_null_check, tc[0].adjacency, NULL);
5761 ok(hr == D3DERR_INVALIDCALL, "ConvertAdjacencyToPointReps point_reps NULL. "
5762 "Got %x expected D3DERR_INVALIDCALL\n", hr);
5763 hr = mesh_null_check->lpVtbl->ConvertAdjacencyToPointReps(mesh_null_check, NULL, NULL);
5764 ok(hr == D3DERR_INVALIDCALL, "ConvertAdjacencyToPointReps adjacency and point_reps NULL. "
5765 "Got %x expected D3DERR_INVALIDCALL\n", hr);
5767 cleanup:
5768 if (mesh_null_check)
5769 mesh_null_check->lpVtbl->Release(mesh_null_check);
5770 HeapFree(GetProcessHeap(), 0, point_reps);
5771 free_test_context(test_context);
5774 static void test_convert_point_reps_to_adjacency(void)
5776 HRESULT hr;
5777 struct test_context *test_context = NULL;
5778 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
5779 const DWORD options_16bit = D3DXMESH_SYSTEMMEM;
5780 const D3DVERTEXELEMENT9 declaration[] =
5782 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
5783 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
5784 {0, 24, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
5785 D3DDECL_END()
5787 const unsigned int VERTS_PER_FACE = 3;
5788 void *vertex_buffer;
5789 void *index_buffer;
5790 DWORD *attributes_buffer;
5791 int i, j;
5792 enum color { RED = 0xffff0000, GREEN = 0xff00ff00, BLUE = 0xff0000ff};
5793 struct vertex_pnc
5795 D3DXVECTOR3 position;
5796 D3DXVECTOR3 normal;
5797 enum color color; /* In case of manual visual inspection */
5799 D3DXVECTOR3 up = {0.0f, 0.0f, 1.0f};
5800 /* mesh0 (one face)
5802 * 0--1
5803 * | /
5804 * |/
5807 const struct vertex_pnc vertices0[] =
5809 {{ 0.0f, 3.0f, 0.f}, up, RED},
5810 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5811 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5813 const DWORD indices0[] = {0, 1, 2};
5814 const unsigned int num_vertices0 = ARRAY_SIZE(vertices0);
5815 const unsigned int num_faces0 = num_vertices0 / VERTS_PER_FACE;
5816 const DWORD exp_adjacency0[] = {-1, -1, -1};
5817 const DWORD exp_id_adjacency0[] = {-1, -1, -1};
5818 const DWORD point_rep0[] = {0, 1, 2};
5819 /* mesh1 (right)
5821 * 0--1 3
5822 * | / /|
5823 * |/ / |
5824 * 2 5--4
5826 const struct vertex_pnc vertices1[] =
5828 {{ 0.0f, 3.0f, 0.f}, up, RED},
5829 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5830 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5832 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5833 {{ 3.0f, 0.0f, 0.f}, up, RED},
5834 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5836 const DWORD indices1[] = {0, 1, 2, 3, 4, 5};
5837 const unsigned int num_vertices1 = ARRAY_SIZE(vertices1);
5838 const unsigned int num_faces1 = num_vertices1 / VERTS_PER_FACE;
5839 const DWORD exp_adjacency1[] = {-1, 1, -1, -1, -1, 0};
5840 const DWORD exp_id_adjacency1[] = {-1, -1, -1, -1, -1, -1};
5841 const DWORD point_rep1[] = {0, 1, 2, 1, 4, 2};
5842 /* mesh2 (left)
5844 * 3 0--1
5845 * /| | /
5846 * / | |/
5847 * 5--4 2
5849 const struct vertex_pnc vertices2[] =
5851 {{ 0.0f, 3.0f, 0.f}, up, RED},
5852 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5853 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5855 {{-1.0f, 3.0f, 0.f}, up, RED},
5856 {{-1.0f, 0.0f, 0.f}, up, GREEN},
5857 {{-3.0f, 0.0f, 0.f}, up, BLUE},
5859 const DWORD indices2[] = {0, 1, 2, 3, 4, 5};
5860 const unsigned int num_vertices2 = ARRAY_SIZE(vertices2);
5861 const unsigned int num_faces2 = num_vertices2 / VERTS_PER_FACE;
5862 const DWORD exp_adjacency2[] = {-1, -1, 1, 0, -1, -1};
5863 const DWORD exp_id_adjacency2[] = {-1, -1, -1, -1, -1, -1};
5864 const DWORD point_rep2[] = {0, 1, 2, 0, 2, 5};
5865 /* mesh3 (above)
5868 * /|
5869 * / |
5870 * 5--4
5871 * 0--1
5872 * | /
5873 * |/
5876 struct vertex_pnc vertices3[] =
5878 {{ 0.0f, 3.0f, 0.f}, up, RED},
5879 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5880 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5882 {{ 2.0f, 7.0f, 0.f}, up, BLUE},
5883 {{ 2.0f, 4.0f, 0.f}, up, GREEN},
5884 {{ 0.0f, 4.0f, 0.f}, up, RED},
5886 const DWORD indices3[] = {0, 1, 2, 3, 4, 5};
5887 const unsigned int num_vertices3 = ARRAY_SIZE(vertices3);
5888 const unsigned int num_faces3 = num_vertices3 / VERTS_PER_FACE;
5889 const DWORD exp_adjacency3[] = {1, -1, -1, -1, 0, -1};
5890 const DWORD exp_id_adjacency3[] = {-1, -1, -1, -1, -1, -1};
5891 const DWORD point_rep3[] = {0, 1, 2, 3, 1, 0};
5892 /* mesh4 (below, tip against tip)
5894 * 0--1
5895 * | /
5896 * |/
5899 * |\
5900 * | \
5901 * 5--4
5903 struct vertex_pnc vertices4[] =
5905 {{ 0.0f, 3.0f, 0.f}, up, RED},
5906 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5907 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5909 {{ 0.0f, -4.0f, 0.f}, up, BLUE},
5910 {{ 2.0f, -7.0f, 0.f}, up, GREEN},
5911 {{ 0.0f, -7.0f, 0.f}, up, RED},
5913 const DWORD indices4[] = {0, 1, 2, 3, 4, 5};
5914 const unsigned int num_vertices4 = ARRAY_SIZE(vertices4);
5915 const unsigned int num_faces4 = num_vertices4 / VERTS_PER_FACE;
5916 const DWORD exp_adjacency4[] = {-1, -1, -1, -1, -1, -1};
5917 const DWORD exp_id_adjacency4[] = {-1, -1, -1, -1, -1, -1};
5918 const DWORD point_rep4[] = {0, 1, 2, 3, 4, 5};
5919 /* mesh5 (gap in mesh)
5921 * 0 3-----4 15
5922 * / \ \ / / \
5923 * / \ \ / / \
5924 * 2-----1 5 17-----16
5925 * 6-----7 9 12-----13
5926 * \ / / \ \ /
5927 * \ / / \ \ /
5928 * 8 10-----11 14
5931 const struct vertex_pnc vertices5[] =
5933 {{ 0.0f, 1.0f, 0.f}, up, RED},
5934 {{ 1.0f, -1.0f, 0.f}, up, GREEN},
5935 {{-1.0f, -1.0f, 0.f}, up, BLUE},
5937 {{ 0.1f, 1.0f, 0.f}, up, RED},
5938 {{ 2.1f, 1.0f, 0.f}, up, BLUE},
5939 {{ 1.1f, -1.0f, 0.f}, up, GREEN},
5941 {{-1.0f, -1.1f, 0.f}, up, BLUE},
5942 {{ 1.0f, -1.1f, 0.f}, up, GREEN},
5943 {{ 0.0f, -3.1f, 0.f}, up, RED},
5945 {{ 1.1f, -1.1f, 0.f}, up, GREEN},
5946 {{ 2.1f, -3.1f, 0.f}, up, BLUE},
5947 {{ 0.1f, -3.1f, 0.f}, up, RED},
5949 {{ 1.2f, -1.1f, 0.f}, up, GREEN},
5950 {{ 3.2f, -1.1f, 0.f}, up, RED},
5951 {{ 2.2f, -3.1f, 0.f}, up, BLUE},
5953 {{ 2.2f, 1.0f, 0.f}, up, BLUE},
5954 {{ 3.2f, -1.0f, 0.f}, up, RED},
5955 {{ 1.2f, -1.0f, 0.f}, up, GREEN},
5957 const DWORD indices5[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17};
5958 const unsigned int num_vertices5 = ARRAY_SIZE(vertices5);
5959 const unsigned int num_faces5 = num_vertices5 / VERTS_PER_FACE;
5960 const DWORD exp_adjacency5[] = {-1, 2, -1, -1, 5, -1, 0, -1, -1, 4, -1, -1, 5, -1, 3, -1, 4, 1};
5961 const DWORD exp_id_adjacency5[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
5962 const DWORD point_rep5[] = {0, 1, 2, 3, 4, 5, 2, 1, 8, 5, 10, 11, 5, 13, 10, 4, 13, 5};
5963 /* mesh6 (indices re-ordering)
5965 * 0--1 6 3
5966 * | / /| |\
5967 * |/ / | | \
5968 * 2 8--7 5--4
5970 const struct vertex_pnc vertices6[] =
5972 {{ 0.0f, 3.0f, 0.f}, up, RED},
5973 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5974 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5976 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5977 {{ 3.0f, 0.0f, 0.f}, up, RED},
5978 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5980 {{ 4.0f, 3.0f, 0.f}, up, GREEN},
5981 {{ 6.0f, 0.0f, 0.f}, up, BLUE},
5982 {{ 4.0f, 0.0f, 0.f}, up, RED},
5984 const DWORD indices6[] = {0, 1, 2, 6, 7, 8, 3, 4, 5};
5985 const unsigned int num_vertices6 = ARRAY_SIZE(vertices6);
5986 const unsigned int num_faces6 = num_vertices6 / VERTS_PER_FACE;
5987 const DWORD exp_adjacency6[] = {-1, 1, -1, 2, -1, 0, -1, -1, 1};
5988 const DWORD exp_id_adjacency6[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1};
5989 const DWORD point_rep6[] = {0, 1, 2, 1, 4, 5, 1, 5, 2};
5990 /* mesh7 (expands collapsed triangle)
5992 * 0--1 3
5993 * | / /|
5994 * |/ / |
5995 * 2 5--4
5997 const struct vertex_pnc vertices7[] =
5999 {{ 0.0f, 3.0f, 0.f}, up, RED},
6000 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
6001 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
6003 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
6004 {{ 3.0f, 0.0f, 0.f}, up, RED},
6005 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
6007 const DWORD indices7[] = {0, 1, 2, 3, 3, 3}; /* Face 1 is collapsed*/
6008 const unsigned int num_vertices7 = ARRAY_SIZE(vertices7);
6009 const unsigned int num_faces7 = num_vertices7 / VERTS_PER_FACE;
6010 const DWORD exp_adjacency7[] = {-1, -1, -1, -1, -1, -1};
6011 const DWORD exp_id_adjacency7[] = {-1, -1, -1, -1, -1, -1};
6012 const DWORD point_rep7[] = {0, 1, 2, 3, 4, 5};
6013 /* mesh8 (indices re-ordering and double replacement)
6015 * 0--1 9 6
6016 * | / /| |\
6017 * |/ / | | \
6018 * 2 11-10 8--7
6019 * 3--4
6020 * | /
6021 * |/
6024 const struct vertex_pnc vertices8[] =
6026 {{ 0.0f, 3.0f, 0.f}, up, RED},
6027 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
6028 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
6030 {{ 4.0, -4.0, 0.f}, up, RED},
6031 {{ 6.0, -4.0, 0.f}, up, BLUE},
6032 {{ 4.0, -7.0, 0.f}, up, GREEN},
6034 {{ 4.0f, 3.0f, 0.f}, up, GREEN},
6035 {{ 6.0f, 0.0f, 0.f}, up, BLUE},
6036 {{ 4.0f, 0.0f, 0.f}, up, RED},
6038 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
6039 {{ 3.0f, 0.0f, 0.f}, up, RED},
6040 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
6042 const DWORD indices8[] = {0, 1, 2, 9, 10, 11, 6, 7, 8, 3, 4, 5};
6043 const WORD indices8_16bit[] = {0, 1, 2, 9, 10, 11, 6, 7, 8, 3, 4, 5};
6044 const unsigned int num_vertices8 = ARRAY_SIZE(vertices8);
6045 const unsigned int num_faces8 = num_vertices8 / VERTS_PER_FACE;
6046 const DWORD exp_adjacency8[] = {-1, 1, -1, 2, -1, 0, -1, 3, 1, 2, -1, -1};
6047 const DWORD exp_id_adjacency8[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
6048 const DWORD point_rep8[] = {0, 1, 2, 3, 4, 5, 1, 4, 3, 1, 3, 2};
6049 /* mesh9 (right, shared vertices)
6051 * 0--1
6052 * | /|
6053 * |/ |
6054 * 2--3
6056 const struct vertex_pnc vertices9[] =
6058 {{ 0.0f, 3.0f, 0.f}, up, RED},
6059 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
6060 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
6062 {{ 2.0f, 0.0f, 0.f}, up, RED},
6064 const DWORD indices9[] = {0, 1, 2, 1, 3, 2};
6065 const unsigned int num_vertices9 = ARRAY_SIZE(vertices9);
6066 const unsigned int num_faces9 = 2;
6067 const DWORD exp_adjacency9[] = {-1, 1, -1, -1, -1, 0};
6068 const DWORD exp_id_adjacency9[] = {-1, 1, -1, -1, -1, 0};
6069 const DWORD point_rep9[] = {0, 1, 2, 3};
6070 /* All mesh data */
6071 ID3DXMesh *mesh = NULL;
6072 ID3DXMesh *mesh_null_check = NULL;
6073 unsigned int attributes[] = {0};
6074 struct
6076 const struct vertex_pnc *vertices;
6077 const DWORD *indices;
6078 const DWORD num_vertices;
6079 const DWORD num_faces;
6080 const DWORD *point_reps;
6081 const DWORD *exp_adjacency;
6082 const DWORD *exp_id_adjacency;
6083 const DWORD options;
6085 tc[] =
6088 vertices0,
6089 indices0,
6090 num_vertices0,
6091 num_faces0,
6092 point_rep0,
6093 exp_adjacency0,
6094 exp_id_adjacency0,
6095 options
6098 vertices1,
6099 indices1,
6100 num_vertices1,
6101 num_faces1,
6102 point_rep1,
6103 exp_adjacency1,
6104 exp_id_adjacency1,
6105 options
6108 vertices2,
6109 indices2,
6110 num_vertices2,
6111 num_faces2,
6112 point_rep2,
6113 exp_adjacency2,
6114 exp_id_adjacency2,
6115 options
6118 vertices3,
6119 indices3,
6120 num_vertices3,
6121 num_faces3,
6122 point_rep3,
6123 exp_adjacency3,
6124 exp_id_adjacency3,
6125 options
6128 vertices4,
6129 indices4,
6130 num_vertices4,
6131 num_faces4,
6132 point_rep4,
6133 exp_adjacency4,
6134 exp_id_adjacency4,
6135 options
6138 vertices5,
6139 indices5,
6140 num_vertices5,
6141 num_faces5,
6142 point_rep5,
6143 exp_adjacency5,
6144 exp_id_adjacency5,
6145 options
6148 vertices6,
6149 indices6,
6150 num_vertices6,
6151 num_faces6,
6152 point_rep6,
6153 exp_adjacency6,
6154 exp_id_adjacency6,
6155 options
6158 vertices7,
6159 indices7,
6160 num_vertices7,
6161 num_faces7,
6162 point_rep7,
6163 exp_adjacency7,
6164 exp_id_adjacency7,
6165 options
6168 vertices8,
6169 indices8,
6170 num_vertices8,
6171 num_faces8,
6172 point_rep8,
6173 exp_adjacency8,
6174 exp_id_adjacency8,
6175 options
6178 vertices9,
6179 indices9,
6180 num_vertices9,
6181 num_faces9,
6182 point_rep9,
6183 exp_adjacency9,
6184 exp_id_adjacency9,
6185 options
6188 vertices8,
6189 (DWORD*)indices8_16bit,
6190 num_vertices8,
6191 num_faces8,
6192 point_rep8,
6193 exp_adjacency8,
6194 exp_id_adjacency8,
6195 options_16bit
6198 DWORD *adjacency = NULL;
6200 test_context = new_test_context();
6201 if (!test_context)
6203 skip("Couldn't create test context\n");
6204 goto cleanup;
6207 for (i = 0; i < ARRAY_SIZE(tc); i++)
6209 hr = D3DXCreateMesh(tc[i].num_faces, tc[i].num_vertices, tc[i].options,
6210 declaration, test_context->device, &mesh);
6211 if (FAILED(hr))
6213 skip("Couldn't create mesh %d. Got %x expected D3D_OK\n", i, hr);
6214 goto cleanup;
6217 if (i == 0) /* Save first mesh for later NULL checks */
6218 mesh_null_check = mesh;
6220 adjacency = HeapAlloc(GetProcessHeap(), 0, VERTS_PER_FACE * tc[i].num_faces * sizeof(*adjacency));
6221 if (!adjacency)
6223 skip("Couldn't allocate adjacency array.\n");
6224 goto cleanup;
6227 hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, &vertex_buffer);
6228 if (FAILED(hr))
6230 skip("Couldn't lock vertex buffer.\n");
6231 goto cleanup;
6233 memcpy(vertex_buffer, tc[i].vertices, tc[i].num_vertices * sizeof(*tc[i].vertices));
6234 hr = mesh->lpVtbl->UnlockVertexBuffer(mesh);
6235 if (FAILED(hr))
6237 skip("Couldn't unlock vertex buffer.\n");
6238 goto cleanup;
6240 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, &index_buffer);
6241 if (FAILED(hr))
6243 skip("Couldn't lock index buffer.\n");
6244 goto cleanup;
6246 if (tc[i].options & D3DXMESH_32BIT)
6248 memcpy(index_buffer, tc[i].indices, VERTS_PER_FACE * tc[i].num_faces * sizeof(DWORD));
6250 else
6252 memcpy(index_buffer, tc[i].indices, VERTS_PER_FACE * tc[i].num_faces * sizeof(WORD));
6254 hr = mesh->lpVtbl->UnlockIndexBuffer(mesh);
6255 if (FAILED(hr)) {
6256 skip("Couldn't unlock index buffer.\n");
6257 goto cleanup;
6260 hr = mesh->lpVtbl->LockAttributeBuffer(mesh, 0, &attributes_buffer);
6261 if (FAILED(hr))
6263 skip("Couldn't lock attributes buffer.\n");
6264 goto cleanup;
6266 memcpy(attributes_buffer, attributes, sizeof(attributes));
6267 hr = mesh->lpVtbl->UnlockAttributeBuffer(mesh);
6268 if (FAILED(hr))
6270 skip("Couldn't unlock attributes buffer.\n");
6271 goto cleanup;
6274 /* Convert point representation to adjacency*/
6275 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++) adjacency[j] = -2;
6277 hr = mesh->lpVtbl->ConvertPointRepsToAdjacency(mesh, tc[i].point_reps, adjacency);
6278 ok(hr == D3D_OK, "ConvertPointRepsToAdjacency failed case %d. "
6279 "Got %x expected D3D_OK\n", i, hr);
6280 /* Check adjacency */
6281 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
6283 ok(adjacency[j] == tc[i].exp_adjacency[j],
6284 "Unexpected adjacency information at (%d, %d)."
6285 " Got %d expected %d\n",
6286 i, j, adjacency[j], tc[i].exp_adjacency[j]);
6289 /* NULL point representation is considered identity. */
6290 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++) adjacency[j] = -2;
6291 hr = mesh_null_check->lpVtbl->ConvertPointRepsToAdjacency(mesh, NULL, adjacency);
6292 ok(hr == D3D_OK, "ConvertPointRepsToAdjacency NULL point_reps. "
6293 "Got %x expected D3D_OK\n", hr);
6294 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
6296 ok(adjacency[j] == tc[i].exp_id_adjacency[j],
6297 "Unexpected adjacency information (id) at (%d, %d)."
6298 " Got %d expected %d\n",
6299 i, j, adjacency[j], tc[i].exp_id_adjacency[j]);
6302 HeapFree(GetProcessHeap(), 0, adjacency);
6303 adjacency = NULL;
6304 if (i != 0) /* First mesh will be freed during cleanup */
6305 mesh->lpVtbl->Release(mesh);
6308 /* NULL checks */
6309 hr = mesh_null_check->lpVtbl->ConvertPointRepsToAdjacency(mesh_null_check, tc[0].point_reps, NULL);
6310 ok(hr == D3DERR_INVALIDCALL, "ConvertPointRepsToAdjacency NULL adjacency. "
6311 "Got %x expected D3DERR_INVALIDCALL\n", hr);
6312 hr = mesh_null_check->lpVtbl->ConvertPointRepsToAdjacency(mesh_null_check, NULL, NULL);
6313 ok(hr == D3DERR_INVALIDCALL, "ConvertPointRepsToAdjacency NULL point_reps and adjacency. "
6314 "Got %x expected D3DERR_INVALIDCALL\n", hr);
6316 cleanup:
6317 if (mesh_null_check)
6318 mesh_null_check->lpVtbl->Release(mesh_null_check);
6319 HeapFree(GetProcessHeap(), 0, adjacency);
6320 free_test_context(test_context);
6323 static HRESULT init_test_mesh(const DWORD num_faces, const DWORD num_vertices,
6324 const DWORD options,
6325 const D3DVERTEXELEMENT9 *declaration,
6326 IDirect3DDevice9 *device, ID3DXMesh **mesh_ptr,
6327 const void *vertices, const DWORD vertex_size,
6328 const DWORD *indices, const DWORD *attributes)
6330 HRESULT hr;
6331 void *vertex_buffer;
6332 void *index_buffer;
6333 DWORD *attributes_buffer;
6334 ID3DXMesh *mesh = NULL;
6336 hr = D3DXCreateMesh(num_faces, num_vertices, options, declaration, device, mesh_ptr);
6337 if (FAILED(hr))
6339 skip("Couldn't create mesh. Got %x expected D3D_OK\n", hr);
6340 goto cleanup;
6342 mesh = *mesh_ptr;
6344 hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, &vertex_buffer);
6345 if (FAILED(hr))
6347 skip("Couldn't lock vertex buffer.\n");
6348 goto cleanup;
6350 memcpy(vertex_buffer, vertices, num_vertices * vertex_size);
6351 hr = mesh->lpVtbl->UnlockVertexBuffer(mesh);
6352 if (FAILED(hr))
6354 skip("Couldn't unlock vertex buffer.\n");
6355 goto cleanup;
6358 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, &index_buffer);
6359 if (FAILED(hr))
6361 skip("Couldn't lock index buffer.\n");
6362 goto cleanup;
6364 if (options & D3DXMESH_32BIT)
6366 if (indices)
6367 memcpy(index_buffer, indices, 3 * num_faces * sizeof(DWORD));
6368 else
6370 /* Fill index buffer with 0, 1, 2, ...*/
6371 DWORD *indices_32bit = (DWORD*)index_buffer;
6372 UINT i;
6373 for (i = 0; i < 3 * num_faces; i++)
6374 indices_32bit[i] = i;
6377 else
6379 if (indices)
6380 memcpy(index_buffer, indices, 3 * num_faces * sizeof(WORD));
6381 else
6383 /* Fill index buffer with 0, 1, 2, ...*/
6384 WORD *indices_16bit = (WORD*)index_buffer;
6385 UINT i;
6386 for (i = 0; i < 3 * num_faces; i++)
6387 indices_16bit[i] = i;
6390 hr = mesh->lpVtbl->UnlockIndexBuffer(mesh);
6391 if (FAILED(hr)) {
6392 skip("Couldn't unlock index buffer.\n");
6393 goto cleanup;
6396 hr = mesh->lpVtbl->LockAttributeBuffer(mesh, 0, &attributes_buffer);
6397 if (FAILED(hr))
6399 skip("Couldn't lock attributes buffer.\n");
6400 goto cleanup;
6403 if (attributes)
6404 memcpy(attributes_buffer, attributes, num_faces * sizeof(*attributes));
6405 else
6406 memset(attributes_buffer, 0, num_faces * sizeof(*attributes));
6408 hr = mesh->lpVtbl->UnlockAttributeBuffer(mesh);
6409 if (FAILED(hr))
6411 skip("Couldn't unlock attributes buffer.\n");
6412 goto cleanup;
6415 hr = D3D_OK;
6416 cleanup:
6417 return hr;
6420 /* Using structs instead of bit-fields in order to avoid compiler issues. */
6421 struct udec3
6423 UINT x;
6424 UINT y;
6425 UINT z;
6426 UINT w;
6429 struct dec3n
6431 INT x;
6432 INT y;
6433 INT z;
6434 INT w;
6437 static DWORD init_udec3_dword(UINT x, UINT y, UINT z, UINT w)
6439 DWORD d = 0;
6441 d |= x & 0x3ff;
6442 d |= (y << 10) & 0xffc00;
6443 d |= (z << 20) & 0x3ff00000;
6444 d |= (w << 30) & 0xc0000000;
6446 return d;
6449 static DWORD init_dec3n_dword(INT x, INT y, INT z, INT w)
6451 DWORD d = 0;
6453 d |= x & 0x3ff;
6454 d |= (y << 10) & 0xffc00;
6455 d |= (z << 20) & 0x3ff00000;
6456 d |= (w << 30) & 0xc0000000;
6458 return d;
6461 static struct udec3 dword_to_udec3(DWORD d)
6463 struct udec3 v;
6465 v.x = d & 0x3ff;
6466 v.y = (d & 0xffc00) >> 10;
6467 v.z = (d & 0x3ff00000) >> 20;
6468 v.w = (d & 0xc0000000) >> 30;
6470 return v;
6473 static struct dec3n dword_to_dec3n(DWORD d)
6475 struct dec3n v;
6477 v.x = d & 0x3ff;
6478 v.y = (d & 0xffc00) >> 10;
6479 v.z = (d & 0x3ff00000) >> 20;
6480 v.w = (d & 0xc0000000) >> 30;
6482 return v;
6485 static void check_vertex_components(int line, int mesh_number, int vertex_number, BYTE *got_ptr, const BYTE *exp_ptr, D3DVERTEXELEMENT9 *declaration)
6487 const char *usage_strings[] =
6489 "position",
6490 "blend weight",
6491 "blend indices",
6492 "normal",
6493 "point size",
6494 "texture coordinates",
6495 "tangent",
6496 "binormal",
6497 "tessellation factor",
6498 "position transformed",
6499 "color",
6500 "fog",
6501 "depth",
6502 "sample"
6504 D3DVERTEXELEMENT9 *decl_ptr;
6505 const float PRECISION = 1e-5f;
6507 for (decl_ptr = declaration; decl_ptr->Stream != 0xFF; decl_ptr++)
6509 switch (decl_ptr->Type)
6511 case D3DDECLTYPE_FLOAT1:
6513 FLOAT *got = (FLOAT*)(got_ptr + decl_ptr->Offset);
6514 FLOAT *exp = (FLOAT*)(exp_ptr + decl_ptr->Offset);
6515 FLOAT diff = fabsf(*got - *exp);
6516 ok_(__FILE__,line)(diff <= PRECISION, "Mesh %d: Got %f for vertex %d %s, expected %f.\n",
6517 mesh_number, *got, vertex_number, usage_strings[decl_ptr->Usage], *exp);
6518 break;
6520 case D3DDECLTYPE_FLOAT2:
6522 D3DXVECTOR2 *got = (D3DXVECTOR2*)(got_ptr + decl_ptr->Offset);
6523 D3DXVECTOR2 *exp = (D3DXVECTOR2*)(exp_ptr + decl_ptr->Offset);
6524 FLOAT diff = max(fabsf(got->x - exp->x), fabsf(got->y - exp->y));
6525 ok_(__FILE__,line)(diff <= PRECISION, "Mesh %d: Got (%f, %f) for vertex %d %s, expected (%f, %f).\n",
6526 mesh_number, got->x, got->y, vertex_number, usage_strings[decl_ptr->Usage], exp->x, exp->y);
6527 break;
6529 case D3DDECLTYPE_FLOAT3:
6531 D3DXVECTOR3 *got = (D3DXVECTOR3*)(got_ptr + decl_ptr->Offset);
6532 D3DXVECTOR3 *exp = (D3DXVECTOR3*)(exp_ptr + decl_ptr->Offset);
6533 FLOAT diff = max(fabsf(got->x - exp->x), fabsf(got->y - exp->y));
6534 diff = max(diff, fabsf(got->z - exp->z));
6535 ok_(__FILE__,line)(diff <= PRECISION, "Mesh %d: Got (%f, %f, %f) for vertex %d %s, expected (%f, %f, %f).\n",
6536 mesh_number, got->x, got->y, got->z, vertex_number, usage_strings[decl_ptr->Usage], exp->x, exp->y, exp->z);
6537 break;
6539 case D3DDECLTYPE_FLOAT4:
6541 D3DXVECTOR4 *got = (D3DXVECTOR4*)(got_ptr + decl_ptr->Offset);
6542 D3DXVECTOR4 *exp = (D3DXVECTOR4*)(exp_ptr + decl_ptr->Offset);
6543 FLOAT diff = max(fabsf(got->x - exp->x), fabsf(got->y - exp->y));
6544 diff = max(diff, fabsf(got->z - exp->z));
6545 diff = max(diff, fabsf(got->w - exp->w));
6546 ok_(__FILE__,line)(diff <= PRECISION, "Mesh %d: Got (%f, %f, %f, %f) for vertex %d %s, expected (%f, %f, %f, %f).\n",
6547 mesh_number, got->x, got->y, got->z, got->w, vertex_number, usage_strings[decl_ptr->Usage], exp->x, exp->y, exp->z, got->w);
6548 break;
6550 case D3DDECLTYPE_D3DCOLOR:
6552 BYTE *got = got_ptr + decl_ptr->Offset;
6553 const BYTE *exp = exp_ptr + decl_ptr->Offset;
6554 BOOL same_color = got[0] == exp[0] && got[1] == exp[1]
6555 && got[2] == exp[2] && got[3] == exp[3];
6556 const char *color_types[] = {"diffuse", "specular", "undefined color"};
6557 BYTE usage_index = decl_ptr->UsageIndex;
6558 if (usage_index > 1) usage_index = 2;
6559 ok_(__FILE__,line)(same_color, "Mesh %d: Got (%u, %u, %u, %u) for vertex %d %s, expected (%u, %u, %u, %u).\n",
6560 mesh_number, got[0], got[1], got[2], got[3], vertex_number, color_types[usage_index], exp[0], exp[1], exp[2], exp[3]);
6561 break;
6563 case D3DDECLTYPE_UBYTE4:
6564 case D3DDECLTYPE_UBYTE4N:
6566 BYTE *got = got_ptr + decl_ptr->Offset;
6567 const BYTE *exp = exp_ptr + decl_ptr->Offset;
6568 BOOL same = got[0] == exp[0] && got[1] == exp[1]
6569 && got[2] == exp[2] && got[3] == exp[3];
6570 ok_(__FILE__,line)(same, "Mesh %d: Got (%u, %u, %u, %u) for vertex %d %s, expected (%u, %u, %u, %u).\n",
6571 mesh_number, got[0], got[1], got[2], got[3], vertex_number, usage_strings[decl_ptr->Usage], exp[0], exp[1], exp[2], exp[3]);
6572 break;
6574 case D3DDECLTYPE_SHORT2:
6575 case D3DDECLTYPE_SHORT2N:
6577 SHORT *got = (SHORT*)(got_ptr + decl_ptr->Offset);
6578 SHORT *exp = (SHORT*)(exp_ptr + decl_ptr->Offset);
6579 BOOL same = got[0] == exp[0] && got[1] == exp[1];
6580 ok_(__FILE__,line)(same, "Mesh %d: Got (%hd, %hd) for vertex %d %s, expected (%hd, %hd).\n",
6581 mesh_number, got[0], got[1], vertex_number, usage_strings[decl_ptr->Usage], exp[0], exp[1]);
6582 break;
6584 case D3DDECLTYPE_SHORT4:
6585 case D3DDECLTYPE_SHORT4N:
6587 SHORT *got = (SHORT*)(got_ptr + decl_ptr->Offset);
6588 SHORT *exp = (SHORT*)(exp_ptr + decl_ptr->Offset);
6589 BOOL same = got[0] == exp[0] && got[1] == exp[1]
6590 && got[2] == exp[2] && got[3] == exp[3];
6591 ok_(__FILE__,line)(same, "Mesh %d: Got (%hd, %hd, %hd, %hd) for vertex %d %s, expected (%hd, %hd, %hd, %hd).\n",
6592 mesh_number, got[0], got[1], got[2], got[3], vertex_number, usage_strings[decl_ptr->Usage], exp[0], exp[1], exp[2], exp[3]);
6593 break;
6595 case D3DDECLTYPE_USHORT2N:
6597 USHORT *got = (USHORT*)(got_ptr + decl_ptr->Offset);
6598 USHORT *exp = (USHORT*)(exp_ptr + decl_ptr->Offset);
6599 BOOL same = got[0] == exp[0] && got[1] == exp[1];
6600 ok_(__FILE__,line)(same, "Mesh %d: Got (%hu, %hu) for vertex %d %s, expected (%hu, %hu).\n",
6601 mesh_number, got[0], got[1], vertex_number, usage_strings[decl_ptr->Usage], exp[0], exp[1]);
6602 break;
6604 case D3DDECLTYPE_USHORT4N:
6606 USHORT *got = (USHORT*)(got_ptr + decl_ptr->Offset);
6607 USHORT *exp = (USHORT*)(exp_ptr + decl_ptr->Offset);
6608 BOOL same = got[0] == exp[0] && got[1] == exp[1]
6609 && got[2] == exp[2] && got[3] == exp[3];
6610 ok_(__FILE__,line)(same, "Mesh %d: Got (%hu, %hu, %hu, %hu) for vertex %d %s, expected (%hu, %hu, %hu, %hu).\n",
6611 mesh_number, got[0], got[1], got[2], got[3], vertex_number, usage_strings[decl_ptr->Usage], exp[0], exp[1], exp[2], exp[3]);
6612 break;
6614 case D3DDECLTYPE_UDEC3:
6616 DWORD *got = (DWORD*)(got_ptr + decl_ptr->Offset);
6617 DWORD *exp = (DWORD*)(exp_ptr + decl_ptr->Offset);
6618 BOOL same = memcmp(got, exp, sizeof(*got)) == 0;
6619 struct udec3 got_udec3 = dword_to_udec3(*got);
6620 struct udec3 exp_udec3 = dword_to_udec3(*exp);
6621 ok_(__FILE__,line)(same, "Mesh %d: Got (%u, %u, %u, %u) for vertex %d %s, expected (%u, %u, %u, %u).\n",
6622 mesh_number, got_udec3.x, got_udec3.y, got_udec3.z, got_udec3.w, vertex_number, usage_strings[decl_ptr->Usage], exp_udec3.x, exp_udec3.y, exp_udec3.z, exp_udec3.w);
6624 break;
6626 case D3DDECLTYPE_DEC3N:
6628 DWORD *got = (DWORD*)(got_ptr + decl_ptr->Offset);
6629 DWORD *exp = (DWORD*)(exp_ptr + decl_ptr->Offset);
6630 BOOL same = memcmp(got, exp, sizeof(*got)) == 0;
6631 struct dec3n got_dec3n = dword_to_dec3n(*got);
6632 struct dec3n exp_dec3n = dword_to_dec3n(*exp);
6633 ok_(__FILE__,line)(same, "Mesh %d: Got (%d, %d, %d, %d) for vertex %d %s, expected (%d, %d, %d, %d).\n",
6634 mesh_number, got_dec3n.x, got_dec3n.y, got_dec3n.z, got_dec3n.w, vertex_number, usage_strings[decl_ptr->Usage], exp_dec3n.x, exp_dec3n.y, exp_dec3n.z, exp_dec3n.w);
6635 break;
6637 case D3DDECLTYPE_FLOAT16_2:
6639 WORD *got = (WORD*)(got_ptr + decl_ptr->Offset);
6640 WORD *exp = (WORD*)(exp_ptr + decl_ptr->Offset);
6641 BOOL same = got[0] == exp[0] && got[1] == exp[1];
6642 ok_(__FILE__,line)(same, "Mesh %d: Got (%hx, %hx) for vertex %d %s, expected (%hx, %hx).\n",
6643 mesh_number, got[0], got[1], vertex_number, usage_strings[decl_ptr->Usage], exp[0], exp[1]);
6644 break;
6646 case D3DDECLTYPE_FLOAT16_4:
6648 WORD *got = (WORD*)(got_ptr + decl_ptr->Offset);
6649 WORD *exp = (WORD*)(exp_ptr + decl_ptr->Offset);
6650 BOOL same = got[0] == exp[0] && got[1] == exp[1]
6651 && got[2] == exp[2] && got[3] == exp[3];
6652 ok_(__FILE__,line)(same, "Mesh %d: Got (%hx, %hx, %hx, %hx) for vertex %d %s, expected (%hx, %hx, %hx, %hx).\n",
6653 mesh_number, got[0], got[1], got[2], got[3], vertex_number, usage_strings[decl_ptr->Usage], exp[0], exp[1], exp[3], exp[4]);
6654 break;
6656 default:
6657 break;
6662 static void test_weld_vertices(void)
6664 HRESULT hr;
6665 struct test_context *test_context = NULL;
6666 DWORD i;
6667 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
6668 const DWORD options_16bit = D3DXMESH_SYSTEMMEM;
6669 BYTE *vertices = NULL;
6670 DWORD *indices = NULL;
6671 WORD *indices_16bit = NULL;
6672 const UINT VERTS_PER_FACE = 3;
6673 const D3DXVECTOR3 up = {0.0f, 0.0f, 1.0f};
6674 struct vertex_normal
6676 D3DXVECTOR3 position;
6677 D3DXVECTOR3 normal;
6679 struct vertex_blendweight
6681 D3DXVECTOR3 position;
6682 FLOAT blendweight;
6684 struct vertex_texcoord
6686 D3DXVECTOR3 position;
6687 D3DXVECTOR2 texcoord;
6689 struct vertex_color
6691 D3DXVECTOR3 position;
6692 DWORD color;
6694 struct vertex_color_ubyte4
6696 D3DXVECTOR3 position;
6697 BYTE color[4];
6699 struct vertex_texcoord_short2
6701 D3DXVECTOR3 position;
6702 SHORT texcoord[2];
6704 struct vertex_texcoord_ushort2n
6706 D3DXVECTOR3 position;
6707 USHORT texcoord[2];
6709 struct vertex_normal_short4
6711 D3DXVECTOR3 position;
6712 SHORT normal[4];
6714 struct vertex_texcoord_float16_2
6716 D3DXVECTOR3 position;
6717 WORD texcoord[2];
6719 struct vertex_texcoord_float16_4
6721 D3DXVECTOR3 position;
6722 WORD texcoord[4];
6724 struct vertex_normal_udec3
6726 D3DXVECTOR3 position;
6727 DWORD normal;
6729 struct vertex_normal_dec3n
6731 D3DXVECTOR3 position;
6732 DWORD normal;
6734 UINT vertex_size_normal = sizeof(struct vertex_normal);
6735 UINT vertex_size_blendweight = sizeof(struct vertex_blendweight);
6736 UINT vertex_size_texcoord = sizeof(struct vertex_texcoord);
6737 UINT vertex_size_color = sizeof(struct vertex_color);
6738 UINT vertex_size_color_ubyte4 = sizeof(struct vertex_color_ubyte4);
6739 UINT vertex_size_texcoord_short2 = sizeof(struct vertex_texcoord_short2);
6740 UINT vertex_size_normal_short4 = sizeof(struct vertex_normal_short4);
6741 UINT vertex_size_texcoord_float16_2 = sizeof(struct vertex_texcoord_float16_2);
6742 UINT vertex_size_texcoord_float16_4 = sizeof(struct vertex_texcoord_float16_4);
6743 UINT vertex_size_normal_udec3 = sizeof(struct vertex_normal_udec3);
6744 UINT vertex_size_normal_dec3n = sizeof(struct vertex_normal_dec3n);
6745 D3DVERTEXELEMENT9 declaration_normal[] =
6747 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6748 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6749 D3DDECL_END()
6751 D3DVERTEXELEMENT9 declaration_normal3[] =
6753 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 3},
6754 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6755 D3DDECL_END()
6757 D3DVERTEXELEMENT9 declaration_blendweight[] =
6759 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6760 {0, 12, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BLENDWEIGHT, 0},
6761 D3DDECL_END()
6763 D3DVERTEXELEMENT9 declaration_texcoord[] =
6765 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6766 {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6767 D3DDECL_END()
6769 D3DVERTEXELEMENT9 declaration_color[] =
6771 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6772 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
6773 D3DDECL_END()
6775 D3DVERTEXELEMENT9 declaration_color_ubyte4n[] =
6777 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6778 {0, 12, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
6779 D3DDECL_END()
6781 D3DVERTEXELEMENT9 declaration_color_ubyte4[] =
6783 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6784 {0, 12, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
6785 D3DDECL_END()
6787 D3DVERTEXELEMENT9 declaration_texcoord_short2[] =
6789 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6790 {0, 12, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6791 D3DDECL_END()
6793 D3DVERTEXELEMENT9 declaration_texcoord_short2n[] =
6795 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6796 {0, 12, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6797 D3DDECL_END()
6799 D3DVERTEXELEMENT9 declaration_texcoord_ushort2n[] =
6801 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6802 {0, 12, D3DDECLTYPE_USHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6803 D3DDECL_END()
6805 D3DVERTEXELEMENT9 declaration_normal_short4[] =
6807 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6808 {0, 12, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6809 D3DDECL_END()
6811 D3DVERTEXELEMENT9 declaration_normal_short4n[] =
6813 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6814 {0, 12, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6815 D3DDECL_END()
6817 D3DVERTEXELEMENT9 declaration_normal_ushort4n[] =
6819 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6820 {0, 12, D3DDECLTYPE_USHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6821 D3DDECL_END()
6823 D3DVERTEXELEMENT9 declaration_texcoord10[] =
6825 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6826 {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 10},
6827 D3DDECL_END()
6829 D3DVERTEXELEMENT9 declaration_color2[] =
6831 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6832 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 2},
6833 D3DDECL_END()
6835 D3DVERTEXELEMENT9 declaration_color1[] =
6837 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6838 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 1},
6839 D3DDECL_END()
6841 D3DVERTEXELEMENT9 declaration_texcoord_float16_2[] =
6843 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6844 {0, 12, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6845 D3DDECL_END()
6847 D3DVERTEXELEMENT9 declaration_texcoord_float16_4[] =
6849 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6850 {0, 12, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6851 D3DDECL_END()
6853 D3DVERTEXELEMENT9 declaration_normal_udec3[] =
6855 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6856 {0, 12, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6857 D3DDECL_END()
6859 D3DVERTEXELEMENT9 declaration_normal_dec3n[] =
6861 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6862 {0, 12, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6863 D3DDECL_END()
6865 /* Test 0. One face and no welding.
6867 * 0--1
6868 * | /
6869 * |/
6872 const struct vertex vertices0[] =
6874 {{ 0.0f, 3.0f, 0.f}, up},
6875 {{ 2.0f, 3.0f, 0.f}, up},
6876 {{ 0.0f, 0.0f, 0.f}, up},
6878 const DWORD indices0[] = {0, 1, 2};
6879 const DWORD attributes0[] = {0};
6880 const DWORD exp_indices0[] = {0, 1, 2};
6881 const UINT num_vertices0 = ARRAY_SIZE(vertices0);
6882 const UINT num_faces0 = ARRAY_SIZE(indices0) / VERTS_PER_FACE;
6883 const DWORD flags0 = D3DXWELDEPSILONS_WELDALL;
6884 /* epsilons0 is NULL */
6885 const DWORD adjacency0[] = {-1, -1, -1};
6886 const struct vertex exp_vertices0[] =
6888 {{ 0.0f, 3.0f, 0.f}, up},
6889 {{ 2.0f, 3.0f, 0.f}, up},
6890 {{ 0.0f, 0.0f, 0.f}, up},
6892 const DWORD exp_face_remap0[] = {0};
6893 const DWORD exp_vertex_remap0[] = {0, 1, 2};
6894 const DWORD exp_new_num_vertices0 = ARRAY_SIZE(exp_vertices0);
6895 /* Test 1. Two vertices should be removed without regard to epsilon.
6897 * 0--1 3
6898 * | / /|
6899 * |/ / |
6900 * 2 5--4
6902 const struct vertex_normal vertices1[] =
6904 {{ 0.0f, 3.0f, 0.f}, up},
6905 {{ 2.0f, 3.0f, 0.f}, up},
6906 {{ 0.0f, 0.0f, 0.f}, up},
6908 {{ 3.0f, 3.0f, 0.f}, up},
6909 {{ 3.0f, 0.0f, 0.f}, up},
6910 {{ 1.0f, 0.0f, 0.f}, up},
6912 const DWORD indices1[] = {0, 1, 2, 3, 4, 5};
6913 const DWORD attributes1[] = {0, 0};
6914 const UINT num_vertices1 = ARRAY_SIZE(vertices1);
6915 const UINT num_faces1 = ARRAY_SIZE(indices1) / VERTS_PER_FACE;
6916 const DWORD flags1 = D3DXWELDEPSILONS_WELDALL;
6917 /* epsilons1 is NULL */
6918 const DWORD adjacency1[] = {-1, 1, -1, -1, -1, 0};
6919 const struct vertex_normal exp_vertices1[] =
6921 {{ 0.0f, 3.0f, 0.f}, up},
6922 {{ 2.0f, 3.0f, 0.f}, up},
6923 {{ 0.0f, 0.0f, 0.f}, up},
6925 {{ 3.0f, 0.0f, 0.f}, up}
6927 const DWORD exp_indices1[] = {0, 1, 2, 1, 3, 2};
6928 const DWORD exp_face_remap1[] = {0, 1};
6929 const DWORD exp_vertex_remap1[] = {0, 1, 2, 4, -1, -1};
6930 const DWORD exp_new_num_vertices1 = ARRAY_SIZE(exp_vertices1);
6931 /* Test 2. Two faces. No vertices should be removed because of normal
6932 * epsilon, but the positions should be replaced. */
6933 const struct vertex_normal vertices2[] =
6935 {{ 0.0f, 3.0f, 0.f}, up},
6936 {{ 2.0f, 3.0f, 0.f}, up},
6937 {{ 0.0f, 0.0f, 0.f}, up},
6939 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
6940 {{ 3.0f, 0.0f, 0.f}, up},
6941 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6943 const DWORD indices2[] = {0, 1, 2, 3, 4, 5};
6944 const DWORD attributes2[] = {0, 0};
6945 const UINT num_vertices2 = ARRAY_SIZE(vertices2);
6946 const UINT num_faces2 = ARRAY_SIZE(indices2) / VERTS_PER_FACE;
6947 DWORD flags2 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
6948 const D3DXWELDEPSILONS epsilons2 = {1.0f, 0.0f, 0.499999f, 0.0f, 0.0f, 0.0f, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, 0.0f, 0.0f, 0.0f};
6949 const DWORD adjacency2[] = {-1, 1, -1, -1, -1, 0};
6950 const struct vertex_normal exp_vertices2[] =
6952 {{ 0.0f, 3.0f, 0.f}, up},
6953 {{ 2.0f, 3.0f, 0.f}, up},
6954 {{ 0.0f, 0.0f, 0.f}, up},
6956 {{ 2.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
6957 {{ 3.0f, 0.0f, 0.f}, up},
6958 {{ 0.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6960 const DWORD exp_indices2[] = {0, 1, 2, 3, 4, 5};
6961 const DWORD exp_face_remap2[] = {0, 1};
6962 const DWORD exp_vertex_remap2[] = {0, 1, 2, 3, 4, 5};
6963 const DWORD exp_new_num_vertices2 = ARRAY_SIZE(exp_vertices2);
6964 /* Test 3. Two faces. One vertex should be removed because of normal epsilon. */
6965 const struct vertex_normal vertices3[] =
6967 {{ 0.0f, 3.0f, 0.f}, up},
6968 {{ 2.0f, 3.0f, 0.f}, up},
6969 {{ 0.0f, 0.0f, 0.f}, up},
6971 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
6972 {{ 3.0f, 0.0f, 0.f}, up},
6973 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6975 const DWORD indices3[] = {0, 1, 2, 3, 4, 5};
6976 const DWORD attributes3[] = {0, 0};
6977 const UINT num_vertices3 = ARRAY_SIZE(vertices3);
6978 const UINT num_faces3 = ARRAY_SIZE(indices3) / VERTS_PER_FACE;
6979 DWORD flags3 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
6980 const D3DXWELDEPSILONS epsilons3 = {1.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, 0.0f, 0.0f, 0.0f};
6981 const DWORD adjacency3[] = {-1, 1, -1, -1, -1, 0};
6982 const struct vertex_normal exp_vertices3[] =
6984 {{ 0.0f, 3.0f, 0.f}, up},
6985 {{ 2.0f, 3.0f, 0.f}, up},
6986 {{ 0.0f, 0.0f, 0.f}, up},
6988 {{ 3.0f, 0.0f, 0.f}, up},
6989 {{ 0.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6991 const DWORD exp_indices3[] = {0, 1, 2, 1, 3, 4};
6992 const DWORD exp_face_remap3[] = {0, 1};
6993 const DWORD exp_vertex_remap3[] = {0, 1, 2, 4, 5, -1};
6994 const DWORD exp_new_num_vertices3 = ARRAY_SIZE(exp_vertices3);
6995 /* Test 4 Two faces. Two vertices should be removed. */
6996 const struct vertex_normal vertices4[] =
6998 {{ 0.0f, 3.0f, 0.f}, up},
6999 {{ 2.0f, 3.0f, 0.f}, up},
7000 {{ 0.0f, 0.0f, 0.f}, up},
7002 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
7003 {{ 3.0f, 0.0f, 0.f}, up},
7004 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
7006 const DWORD indices4[] = {0, 1, 2, 3, 4, 5};
7007 const DWORD attributes4[] = {0, 0};
7008 const UINT num_vertices4 = ARRAY_SIZE(vertices4);
7009 const UINT num_faces4 = ARRAY_SIZE(indices4) / VERTS_PER_FACE;
7010 DWORD flags4 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7011 const D3DXWELDEPSILONS epsilons4 = {1.0f, 0.0f, 0.6f, 0.0f, 0.0f, 0.0f, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, 0.0f, 0.0f, 0.0f};
7012 const DWORD adjacency4[] = {-1, 1, -1, -1, -1, 0};
7013 const struct vertex_normal exp_vertices4[] =
7015 {{ 0.0f, 3.0f, 0.f}, up},
7016 {{ 2.0f, 3.0f, 0.f}, up},
7017 {{ 0.0f, 0.0f, 0.f}, up},
7019 {{ 3.0f, 0.0f, 0.f}, up},
7021 const DWORD exp_indices4[] = {0, 1, 2, 1, 3, 2};
7022 const DWORD exp_face_remap4[] = {0, 1};
7023 const DWORD exp_vertex_remap4[] = {0, 1, 2, 4, -1, -1};
7024 const DWORD exp_new_num_vertices4 = ARRAY_SIZE(exp_vertices4);
7025 /* Test 5. Odd face ordering.
7027 * 0--1 6 3
7028 * | / /| |\
7029 * |/ / | | \
7030 * 2 8--7 5--4
7032 const struct vertex_normal vertices5[] =
7034 {{ 0.0f, 3.0f, 0.f}, up},
7035 {{ 2.0f, 3.0f, 0.f}, up},
7036 {{ 0.0f, 0.0f, 0.f}, up},
7038 {{ 3.0f, 3.0f, 0.f}, up},
7039 {{ 3.0f, 0.0f, 0.f}, up},
7040 {{ 1.0f, 0.0f, 0.f}, up},
7042 {{ 4.0f, 3.0f, 0.f}, up},
7043 {{ 6.0f, 0.0f, 0.f}, up},
7044 {{ 4.0f, 0.0f, 0.f}, up},
7046 const DWORD indices5[] = {0, 1, 2, 6, 7, 8, 3, 4, 5};
7047 const DWORD exp_indices5[] = {0, 1, 2, 1, 4, 2, 1, 3, 4};
7048 const DWORD attributes5[] = {0, 0, 0};
7049 const UINT num_vertices5 = ARRAY_SIZE(vertices5);
7050 const UINT num_faces5 = ARRAY_SIZE(indices5) / VERTS_PER_FACE;
7051 DWORD flags5 = D3DXWELDEPSILONS_WELDALL;
7052 const DWORD adjacency5[] = {-1, 1, -1, 2, -1, 0, -1, -1, 1};
7053 const struct vertex_normal exp_vertices5[] =
7055 {{ 0.0f, 3.0f, 0.f}, up},
7056 {{ 2.0f, 3.0f, 0.f}, up},
7057 {{ 0.0f, 0.0f, 0.f}, up},
7059 {{ 3.0f, 0.0f, 0.f}, up},
7060 {{ 1.0f, 0.0f, 0.f}, up},
7062 const DWORD exp_face_remap5[] = {0, 1, 2};
7063 const DWORD exp_vertex_remap5[] = {0, 1, 2, 4, 5, -1, -1, -1, -1};
7064 const DWORD exp_new_num_vertices5 = ARRAY_SIZE(exp_vertices5);
7065 /* Test 6. Two faces. Do not remove flag is used, so no vertices should be
7066 * removed. */
7067 const struct vertex_normal vertices6[] =
7069 {{ 0.0f, 3.0f, 0.f}, up},
7070 {{ 2.0f, 3.0f, 0.f}, up},
7071 {{ 0.0f, 0.0f, 0.f}, up},
7073 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
7074 {{ 3.0f, 0.0f, 0.f}, up},
7075 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
7077 const DWORD indices6[] = {0, 1, 2, 3, 4, 5};
7078 const DWORD attributes6[] = {0, 0};
7079 const UINT num_vertices6 = ARRAY_SIZE(vertices6);
7080 const UINT num_faces6 = ARRAY_SIZE(indices6) / VERTS_PER_FACE;
7081 DWORD flags6 = D3DXWELDEPSILONS_WELDPARTIALMATCHES | D3DXWELDEPSILONS_DONOTREMOVEVERTICES;
7082 const D3DXWELDEPSILONS epsilons6 = {1.0f, 0.0f, 0.6f, 0.0f, 0.0f, 0.0f, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, 0.0f, 0.0f, 0.0f};
7083 const DWORD adjacency6[] = {-1, 1, -1, -1, -1, 0};
7084 const struct vertex_normal exp_vertices6[] =
7086 {{ 0.0f, 3.0f, 0.f}, up},
7087 {{ 2.0f, 3.0f, 0.f}, up},
7088 {{ 0.0f, 0.0f, 0.f}, up},
7090 {{ 2.0f, 3.0f, 0.f}, up},
7091 {{ 3.0f, 0.0f, 0.f}, up},
7092 {{ 0.0f, 0.0f, 0.f}, up},
7095 const DWORD exp_indices6[] = {0, 1, 2, 3, 4, 5};
7096 const DWORD exp_face_remap6[] = {0, 1};
7097 const DWORD exp_vertex_remap6[] = {0, 1, 2, 3, 4, 5};
7098 const DWORD exp_new_num_vertices6 = ARRAY_SIZE(exp_vertices6);
7099 /* Test 7. Same as test 6 but with 16 bit indices. */
7100 const WORD indices6_16bit[] = {0, 1, 2, 3, 4, 5};
7101 /* Test 8. No flags. Same result as D3DXWELDEPSILONS_WELDPARTIALMATCHES. */
7102 const struct vertex_normal vertices8[] =
7104 {{ 0.0f, 3.0f, 0.f}, up},
7105 {{ 2.0f, 3.0f, 0.f}, up},
7106 {{ 0.0f, 0.0f, 0.f}, up},
7108 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
7109 {{ 3.0f, 0.0f, 0.f}, up},
7110 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
7112 const DWORD indices8[] = {0, 1, 2, 1, 3, 4};
7113 const DWORD attributes8[] = {0, 0};
7114 const UINT num_vertices8 = ARRAY_SIZE(vertices8);
7115 const UINT num_faces8 = ARRAY_SIZE(indices8) / VERTS_PER_FACE;
7116 DWORD flags8 = 0;
7117 const D3DXWELDEPSILONS epsilons8 = {1.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, 0.0f, 0.0f, 0.0f};
7118 const DWORD adjacency8[] = {-1, 1, -1, -1, -1, 0};
7119 const struct vertex_normal exp_vertices8[] =
7121 {{ 0.0f, 3.0f, 0.f}, up},
7122 {{ 2.0f, 3.0f, 0.f}, up},
7123 {{ 0.0f, 0.0f, 0.f}, up},
7125 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
7126 {{ 3.0f, 0.0f, 0.f}, up},
7128 const DWORD exp_indices8[] = {0, 1, 2, 1, 3, 4};
7129 const DWORD exp_face_remap8[] = {0, 1};
7130 const DWORD exp_vertex_remap8[] = {0, 1, 2, 3, 4, -1};
7131 const DWORD exp_new_num_vertices8 = ARRAY_SIZE(exp_vertices8);
7132 /* Test 9. Vertices are removed even though they belong to separate
7133 * attribute groups if D3DXWELDEPSILONS_DONOTSPLIT is set. */
7134 const struct vertex_normal vertices9[] =
7136 {{ 0.0f, 3.0f, 0.f}, up},
7137 {{ 2.0f, 3.0f, 0.f}, up},
7138 {{ 0.0f, 0.0f, 0.f}, up},
7140 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
7141 {{ 3.0f, 0.0f, 0.f}, up},
7142 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
7144 const DWORD indices9[] = {0, 1, 2, 3, 4, 5};
7145 const DWORD attributes9[] = {0, 1};
7146 const UINT num_vertices9 = ARRAY_SIZE(vertices9);
7147 const UINT num_faces9 = ARRAY_SIZE(indices9) / VERTS_PER_FACE;
7148 DWORD flags9 = D3DXWELDEPSILONS_WELDPARTIALMATCHES | D3DXWELDEPSILONS_DONOTSPLIT;
7149 const D3DXWELDEPSILONS epsilons9 = {1.0f, 0.0f, 0.6f, 0.0f, 0.0f, 0.0f, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, 0.0f, 0.0f, 0.0f};
7150 const DWORD adjacency9[] = {-1, 1, -1, -1, -1, 0};
7151 const struct vertex_normal exp_vertices9[] =
7153 {{ 0.0f, 3.0f, 0.f}, up},
7154 {{ 2.0f, 3.0f, 0.f}, up},
7155 {{ 0.0f, 0.0f, 0.f}, up},
7157 {{ 3.0f, 0.0f, 0.f}, up},
7159 const DWORD exp_indices9[] = {0, 1, 2, 1, 3, 2};
7160 const DWORD exp_face_remap9[] = {0, 1};
7161 const DWORD exp_vertex_remap9[] = {0, 1, 2, 4, -1, -1};
7162 const DWORD exp_new_num_vertices9 = ARRAY_SIZE(exp_vertices9);
7163 /* Test 10. Weld blendweight (FLOAT1). */
7164 const struct vertex_blendweight vertices10[] =
7166 {{ 0.0f, 3.0f, 0.f}, 1.0f},
7167 {{ 2.0f, 3.0f, 0.f}, 1.0f},
7168 {{ 0.0f, 0.0f, 0.f}, 1.0f},
7170 {{ 3.0f, 3.0f, 0.f}, 0.9},
7171 {{ 3.0f, 0.0f, 0.f}, 1.0},
7172 {{ 1.0f, 0.0f, 0.f}, 0.4},
7174 const DWORD indices10[] = {0, 1, 2, 3, 4, 5};
7175 const DWORD attributes10[] = {0, 0};
7176 const UINT num_vertices10 = ARRAY_SIZE(vertices10);
7177 const UINT num_faces10 = ARRAY_SIZE(indices10) / VERTS_PER_FACE;
7178 DWORD flags10 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7179 const D3DXWELDEPSILONS epsilons10 = {1.0f, 0.1f + FLT_EPSILON, 0.0f, 0.0f, 0.0f, 0.0f, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, 0.0f, 0.0f, 0.0f};
7180 const DWORD adjacency10[] = {-1, 1, -1, -1, -1, 0};
7181 const struct vertex_blendweight exp_vertices10[] =
7183 {{ 0.0f, 3.0f, 0.f}, 1.0f},
7184 {{ 2.0f, 3.0f, 0.f}, 1.0f},
7185 {{ 0.0f, 0.0f, 0.f}, 1.0f},
7187 {{ 3.0f, 0.0f, 0.f}, 1.0},
7188 {{ 0.0f, 0.0f, 0.f}, 0.4},
7190 const DWORD exp_indices10[] = {0, 1, 2, 1, 3, 4};
7191 const DWORD exp_face_remap10[] = {0, 1};
7192 const DWORD exp_vertex_remap10[] = {0, 1, 2, 4, 5, -1};
7193 const DWORD exp_new_num_vertices10 = ARRAY_SIZE(exp_vertices10);
7194 /* Test 11. Weld texture coordinates. */
7195 const struct vertex_texcoord vertices11[] =
7197 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f}},
7198 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.7f}},
7199 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
7201 {{ 3.0f, 3.0f, 0.f}, {0.2f, 0.3f}},
7202 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f}},
7203 {{ 1.0f, 0.0f, 0.f}, {0.1f, 0.2f}}
7205 const DWORD indices11[] = {0, 1, 2, 3, 4, 5};
7206 const DWORD attributes11[] = {0, 0};
7207 const UINT num_vertices11 = ARRAY_SIZE(vertices11);
7208 const UINT num_faces11 = ARRAY_SIZE(indices11) / VERTS_PER_FACE;
7209 DWORD flags11 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7210 const D3DXWELDEPSILONS epsilons11 = {1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, {0.4f + FLT_EPSILON, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, 0.0f, 0.0f, 0.0f};
7211 const DWORD adjacency11[] = {-1, 1, -1, -1, -1, 0};
7212 const struct vertex_texcoord exp_vertices11[] =
7214 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f}},
7215 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.7f}},
7216 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
7218 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f}},
7219 {{ 0.0f, 0.0f, 0.f}, {0.1f, 0.2f}},
7221 const DWORD exp_indices11[] = {0, 1, 2, 1, 3, 4};
7222 const DWORD exp_face_remap11[] = {0, 1};
7223 const DWORD exp_vertex_remap11[] = {0, 1, 2, 4, 5, -1};
7224 const DWORD exp_new_num_vertices11 = ARRAY_SIZE(exp_vertices11);
7225 /* Test 12. Weld with color. */
7226 const struct vertex_color vertices12[] =
7228 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7229 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7230 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7232 {{ 3.0f, 3.0f, 0.f}, 0x00000000},
7233 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7234 {{ 1.0f, 0.0f, 0.f}, 0x88888888},
7236 const DWORD indices12[] = {0, 1, 2, 3, 4, 5};
7237 const DWORD attributes12[] = {0, 0};
7238 const UINT num_vertices12 = ARRAY_SIZE(vertices12);
7239 const UINT num_faces12 = ARRAY_SIZE(indices12) / VERTS_PER_FACE;
7240 DWORD flags12 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7241 const D3DXWELDEPSILONS epsilons12 = {1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, 0.0f, 0.0f, 0.0f};
7242 const DWORD adjacency12[] = {-1, 1, -1, -1, -1, 0};
7243 const struct vertex_color exp_vertices12[] =
7245 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7246 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7247 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7249 {{ 2.0f, 3.0f, 0.f}, 0x00000000},
7250 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7252 const DWORD exp_indices12[] = {0, 1, 2, 3, 4, 2};
7253 const DWORD exp_face_remap12[] = {0, 1};
7254 const DWORD exp_vertex_remap12[] = {0, 1, 2, 3, 4, -1};
7255 const DWORD exp_new_num_vertices12 = ARRAY_SIZE(exp_vertices12);
7256 /* Test 13. Two faces. One vertex should be removed because of normal epsilon.
7257 * This is similar to test 3, but the declaration has been changed to NORMAL3.
7259 const struct vertex_normal vertices13[] =
7261 {{ 0.0f, 3.0f, 0.f}, up},
7262 {{ 2.0f, 3.0f, 0.f}, up},
7263 {{ 0.0f, 0.0f, 0.f}, up},
7265 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
7266 {{ 3.0f, 0.0f, 0.f}, up},
7267 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
7269 const DWORD indices13[] = {0, 1, 2, 3, 4, 5};
7270 const DWORD attributes13[] = {0, 0};
7271 const UINT num_vertices13 = ARRAY_SIZE(vertices3);
7272 const UINT num_faces13 = ARRAY_SIZE(indices3) / VERTS_PER_FACE;
7273 DWORD flags13 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7274 const D3DXWELDEPSILONS epsilons13 = {1.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, 0.0f, 0.0f, 0.0f};
7275 const DWORD adjacency13[] = {-1, 1, -1, -1, -1, 0};
7276 const struct vertex_normal exp_vertices13[] =
7278 {{ 0.0f, 3.0f, 0.f}, up},
7279 {{ 2.0f, 3.0f, 0.f}, up},
7280 {{ 0.0f, 0.0f, 0.f}, up},
7282 {{ 3.0f, 0.0f, 0.f}, up},
7283 {{ 0.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
7285 const DWORD exp_indices13[] = {0, 1, 2, 1, 3, 4};
7286 const DWORD exp_face_remap13[] = {0, 1};
7287 const DWORD exp_vertex_remap13[] = {0, 1, 2, 4, 5, -1};
7288 const DWORD exp_new_num_vertices13 = ARRAY_SIZE(exp_vertices13);
7289 /* Test 14. Another test for welding with color. */
7290 const struct vertex_color vertices14[] =
7292 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7293 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7294 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7296 {{ 3.0f, 3.0f, 0.f}, 0x00000000},
7297 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7298 {{ 1.0f, 0.0f, 0.f}, 0x01010101},
7300 const DWORD indices14[] = {0, 1, 2, 3, 4, 5};
7301 const DWORD attributes14[] = {0, 0};
7302 const UINT num_vertices14 = ARRAY_SIZE(vertices14);
7303 const UINT num_faces14 = ARRAY_SIZE(indices14) / VERTS_PER_FACE;
7304 DWORD flags14 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7305 const D3DXWELDEPSILONS epsilons14 = {1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 254.0f/255.0f, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, 0.0f, 0.0f, 0.0f};
7306 const DWORD adjacency14[] = {-1, 1, -1, -1, -1, 0};
7307 const struct vertex_color exp_vertices14[] =
7309 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7310 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7311 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7313 {{ 2.0f, 3.0f, 0.f}, 0x00000000},
7314 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7316 const DWORD exp_indices14[] = {0, 1, 2, 3, 4, 2};
7317 const DWORD exp_face_remap14[] = {0, 1};
7318 const DWORD exp_vertex_remap14[] = {0, 1, 2, 3, 4, -1};
7319 const DWORD exp_new_num_vertices14 = ARRAY_SIZE(exp_vertices14);
7320 /* Test 15. Weld with color, but as UBYTE4N instead of D3DCOLOR. It shows
7321 * that UBYTE4N and D3DCOLOR are compared the same way.
7323 const struct vertex_color_ubyte4 vertices15[] =
7325 {{ 0.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7326 {{ 2.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7327 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7329 {{ 3.0f, 3.0f, 0.f}, { 0, 0, 0, 0}},
7330 {{ 3.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7331 {{ 1.0f, 0.0f, 0.f}, { 1, 1, 1, 1}},
7333 const DWORD indices15[] = {0, 1, 2, 3, 4, 5};
7334 const DWORD attributes15[] = {0, 0};
7335 const UINT num_vertices15 = ARRAY_SIZE(vertices15);
7336 const UINT num_faces15 = ARRAY_SIZE(indices15) / VERTS_PER_FACE;
7337 DWORD flags15 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7338 const D3DXWELDEPSILONS epsilons15 = {1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 254.0f/255.0f, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, 0.0f, 0.0f, 0.0f};
7339 const DWORD adjacency15[] = {-1, 1, -1, -1, -1, 0};
7340 const struct vertex_color_ubyte4 exp_vertices15[] =
7342 {{ 0.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7343 {{ 2.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7344 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7346 {{ 2.0f, 3.0f, 0.f}, { 0, 0, 0, 0}},
7347 {{ 3.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7349 const DWORD exp_indices15[] = {0, 1, 2, 3, 4, 2};
7350 const DWORD exp_face_remap15[] = {0, 1};
7351 const DWORD exp_vertex_remap15[] = {0, 1, 2, 3, 4, -1};
7352 const DWORD exp_new_num_vertices15 = ARRAY_SIZE(exp_vertices15);
7353 /* Test 16. Weld with color, but as UBYTE4 instead of D3DCOLOR. It shows
7354 * that UBYTE4 is not normalized and that epsilon is truncated and compared
7355 * directly to each of the four bytes.
7357 const struct vertex_color_ubyte4 vertices16[] =
7359 {{ 0.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7360 {{ 2.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7361 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7363 {{ 3.0f, 3.0f, 0.f}, { 0, 0, 0, 0}},
7364 {{ 3.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7365 {{ 1.0f, 0.0f, 0.f}, { 1, 1, 1, 1}},
7367 const DWORD indices16[] = {0, 1, 2, 3, 4, 5};
7368 const DWORD attributes16[] = {0, 0};
7369 const UINT num_vertices16 = ARRAY_SIZE(vertices16);
7370 const UINT num_faces16 = ARRAY_SIZE(indices16) / VERTS_PER_FACE;
7371 DWORD flags16 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7372 const D3DXWELDEPSILONS epsilons16 = {1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 254.9f, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, 0.0f, 0.0f, 0.0f};
7373 const DWORD adjacency16[] = {-1, 1, -1, -1, -1, 0};
7374 const struct vertex_color_ubyte4 exp_vertices16[] =
7376 {{ 0.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7377 {{ 2.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7378 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7380 {{ 2.0f, 3.0f, 0.f}, { 0, 0, 0, 0}},
7381 {{ 3.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7383 const DWORD exp_indices16[] = {0, 1, 2, 3, 4, 2};
7384 const DWORD exp_face_remap16[] = {0, 1};
7385 const DWORD exp_vertex_remap16[] = {0, 1, 2, 3, 4, -1};
7386 const DWORD exp_new_num_vertices16 = ARRAY_SIZE(exp_vertices16);
7387 /* Test 17. Weld texture coordinates but as SHORT2 instead of D3DXVECTOR2.*/
7388 const struct vertex_texcoord_short2 vertices17[] =
7390 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7391 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7392 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7394 {{ 3.0f, 3.0f, 0.f}, {32767, 32767}},
7395 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7396 {{ 1.0f, 0.0f, 0.f}, {32766, 32766}},
7398 const DWORD indices17[] = {0, 1, 2, 3, 4, 5};
7399 const DWORD attributes17[] = {0, 0};
7400 const UINT num_vertices17 = ARRAY_SIZE(vertices17);
7401 const UINT num_faces17 = ARRAY_SIZE(indices17) / VERTS_PER_FACE;
7402 DWORD flags17 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7403 const D3DXWELDEPSILONS epsilons17 = {1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, {32766.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, 0.0f, 0.0f, 0.0f};
7404 const DWORD adjacency17[] = {-1, 1, -1, -1, -1, 0};
7405 const struct vertex_texcoord_short2 exp_vertices17[] =
7407 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7408 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7409 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7411 {{ 2.0f, 3.0f, 0.f}, {32767, 32767}},
7412 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7414 const DWORD exp_indices17[] = {0, 1, 2, 3, 4, 2};
7415 const DWORD exp_face_remap17[] = {0, 1};
7416 const DWORD exp_vertex_remap17[] = {0, 1, 2, 3, 4, -1};
7417 const DWORD exp_new_num_vertices17 = ARRAY_SIZE(exp_vertices17);
7418 /* Test 18. Weld texture coordinates but as SHORT2N instead of D3DXVECTOR2. */
7419 const struct vertex_texcoord_short2 vertices18[] =
7421 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7422 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7423 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7425 {{ 3.0f, 3.0f, 0.f}, {32767, 32767}},
7426 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7427 {{ 1.0f, 0.0f, 0.f}, {32766, 32766}},
7429 const DWORD indices18[] = {0, 1, 2, 3, 4, 5};
7430 const DWORD attributes18[] = {0, 0};
7431 const UINT num_vertices18 = ARRAY_SIZE(vertices18);
7432 const UINT num_faces18 = ARRAY_SIZE(indices18) / VERTS_PER_FACE;
7433 DWORD flags18 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7434 const D3DXWELDEPSILONS epsilons18 = {1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, {32766.0f/32767.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, 0.0f, 0.0f, 0.0f};
7435 const DWORD adjacency18[] = {-1, 1, -1, -1, -1, 0};
7436 const struct vertex_texcoord_short2 exp_vertices18[] =
7438 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7439 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7440 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7442 {{ 2.0f, 3.0f, 0.f}, {32767, 32767}},
7443 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7445 const DWORD exp_indices18[] = {0, 1, 2, 3, 4, 2};
7446 const DWORD exp_face_remap18[] = {0, 1};
7447 const DWORD exp_vertex_remap18[] = {0, 1, 2, 3, 4, -1};
7448 const DWORD exp_new_num_vertices18 = ARRAY_SIZE(exp_vertices18);
7449 /* Test 19. Weld texture coordinates but as USHORT2N instead of D3DXVECTOR2. */
7450 const struct vertex_texcoord_ushort2n vertices19[] =
7452 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7453 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7454 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7456 {{ 3.0f, 3.0f, 0.f}, {65535, 65535}},
7457 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7458 {{ 1.0f, 0.0f, 0.f}, {65534, 65534}},
7460 const DWORD indices19[] = {0, 1, 2, 3, 4, 5};
7461 const DWORD attributes19[] = {0, 0};
7462 const UINT num_vertices19 = ARRAY_SIZE(vertices19);
7463 const UINT num_faces19 = ARRAY_SIZE(indices19) / VERTS_PER_FACE;
7464 DWORD flags19 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7465 const D3DXWELDEPSILONS epsilons19 = {1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, {65534.0f/65535.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, 0.0f, 0.0f, 0.0f};
7466 const DWORD adjacency19[] = {-1, 1, -1, -1, -1, 0};
7467 const struct vertex_texcoord_ushort2n exp_vertices19[] =
7469 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7470 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7471 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7473 {{ 2.0f, 3.0f, 0.f}, {65535, 65535}},
7474 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7476 const DWORD exp_indices19[] = {0, 1, 2, 3, 4, 2};
7477 const DWORD exp_face_remap19[] = {0, 1};
7478 const DWORD exp_vertex_remap19[] = {0, 1, 2, 3, 4, -1};
7479 const DWORD exp_new_num_vertices19 = ARRAY_SIZE(exp_vertices19);
7480 /* Test 20. Weld normal as SHORT4 instead of D3DXVECTOR3. */
7481 const struct vertex_normal_short4 vertices20[] =
7483 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7484 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7485 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7487 {{ 3.0f, 3.0f, 0.f}, {32767, 32767, 32767, 32767}},
7488 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7489 {{ 1.0f, 0.0f, 0.f}, {32766, 32766, 32766, 32766}},
7491 const DWORD indices20[] = {0, 1, 2, 3, 4, 5};
7492 const DWORD attributes20[] = {0, 0};
7493 const UINT num_vertices20 = ARRAY_SIZE(vertices20);
7494 const UINT num_faces20 = ARRAY_SIZE(indices20) / VERTS_PER_FACE;
7495 DWORD flags20 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7496 const D3DXWELDEPSILONS epsilons20 = {1.0f, 0.0f, 32766.0f, 0.0f, 0.0f, 0.0f, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, 0.0f, 0.0f, 0.0f};
7497 const DWORD adjacency20[] = {-1, 1, -1, -1, -1, 0};
7498 const struct vertex_normal_short4 exp_vertices20[] =
7500 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7501 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7502 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7504 {{ 2.0f, 3.0f, 0.f}, {32767, 32767, 32767, 32767}},
7505 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7507 const DWORD exp_indices20[] = {0, 1, 2, 3, 4, 2};
7508 const DWORD exp_face_remap20[] = {0, 1};
7509 const DWORD exp_vertex_remap20[] = {0, 1, 2, 3, 4, -1};
7510 const DWORD exp_new_num_vertices20 = ARRAY_SIZE(exp_vertices20);
7511 /* Test 21. Weld normal as SHORT4N instead of D3DXVECTOR3. */
7512 const struct vertex_normal_short4 vertices21[] =
7514 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7515 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7516 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7518 {{ 3.0f, 3.0f, 0.f}, {32767, 32767, 32767, 32767}},
7519 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7520 {{ 1.0f, 0.0f, 0.f}, {32766, 32766, 32766, 32766}},
7522 const DWORD indices21[] = {0, 1, 2, 3, 4, 5};
7523 const DWORD attributes21[] = {0, 0};
7524 const UINT num_vertices21 = ARRAY_SIZE(vertices21);
7525 const UINT num_faces21 = ARRAY_SIZE(indices21) / VERTS_PER_FACE;
7526 DWORD flags21 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7527 const D3DXWELDEPSILONS epsilons21 = {1.0f, 0.0f, 32766.0f/32767.0f, 0.0f, 0.0f, 0.0f, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, 0.0f, 0.0f, 0.0f};
7528 const DWORD adjacency21[] = {-1, 1, -1, -1, -1, 0};
7529 const struct vertex_normal_short4 exp_vertices21[] =
7531 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7532 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7533 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7535 {{ 2.0f, 3.0f, 0.f}, {32767, 32767, 32767, 32767}},
7536 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7538 const DWORD exp_indices21[] = {0, 1, 2, 3, 4, 2};
7539 const DWORD exp_face_remap21[] = {0, 1};
7540 const DWORD exp_vertex_remap21[] = {0, 1, 2, 3, 4, -1};
7541 const DWORD exp_new_num_vertices21 = ARRAY_SIZE(exp_vertices21);
7542 /* Test 22. Weld normal as USHORT4N instead of D3DXVECTOR3. */
7543 const struct vertex_normal_short4 vertices22[] =
7545 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7546 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7547 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7549 {{ 3.0f, 3.0f, 0.f}, {-1, -1, -1, -1}},
7550 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7551 {{ 1.0f, 0.0f, 0.f}, {-2, -2, -2, -2}},
7553 const DWORD indices22[] = {0, 1, 2, 3, 4, 5};
7554 const DWORD attributes22[] = {0, 0};
7555 const UINT num_vertices22 = ARRAY_SIZE(vertices22);
7556 const UINT num_faces22 = ARRAY_SIZE(indices22) / VERTS_PER_FACE;
7557 DWORD flags22 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7558 const D3DXWELDEPSILONS epsilons22 = {1.0f, 0.0f, 65534.0f/65535.0f, 0.0f, 0.0f, 0.0f, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, 0.0f, 0.0f, 0.0f};
7559 const DWORD adjacency22[] = {-1, 1, -1, -1, -1, 0};
7560 const struct vertex_normal_short4 exp_vertices22[] =
7562 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7563 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7564 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7566 {{ 2.0f, 3.0f, 0.f}, {-1, -1, -1, -1}},
7567 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7569 const DWORD exp_indices22[] = {0, 1, 2, 3, 4, 2};
7570 const DWORD exp_face_remap22[] = {0, 1};
7571 const DWORD exp_vertex_remap22[] = {0, 1, 2, 3, 4, -1};
7572 const DWORD exp_new_num_vertices22 = ARRAY_SIZE(exp_vertices22);
7573 /* Test 23. Weld texture coordinates as FLOAT16_2. Similar to test 11, but
7574 * with texture coordinates converted to float16 in hex. */
7575 const struct vertex_texcoord_float16_2 vertices23[] =
7577 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
7578 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */
7579 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */
7581 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd}}, /* {0.2f, 0.3f} */
7582 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
7583 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */
7585 const DWORD indices23[] = {0, 1, 2, 3, 4, 5};
7586 const DWORD attributes23[] = {0, 0};
7587 const UINT num_vertices23 = ARRAY_SIZE(vertices23);
7588 const UINT num_faces23 = ARRAY_SIZE(indices23) / VERTS_PER_FACE;
7589 DWORD flags23 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7590 const D3DXWELDEPSILONS epsilons23 = {1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, {0.41f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, 0.0f, 0.0f, 0.0f};
7591 const DWORD adjacency23[] = {-1, 1, -1, -1, -1, 0};
7592 const struct vertex_texcoord_float16_2 exp_vertices23[] =
7594 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
7595 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */
7596 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */
7598 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
7599 {{ 0.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */
7601 const DWORD exp_indices23[] = {0, 1, 2, 1, 3, 4};
7602 const DWORD exp_face_remap23[] = {0, 1};
7603 const DWORD exp_vertex_remap23[] = {0, 1, 2, 4, 5, -1};
7604 const DWORD exp_new_num_vertices23 = ARRAY_SIZE(exp_vertices23);
7605 /* Test 24. Weld texture coordinates as FLOAT16_4. Similar to test 24. */
7606 const struct vertex_texcoord_float16_4 vertices24[] =
7608 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}},
7609 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a, 0x3800, 0x399a}},
7610 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd, 0xb266, 0xb4cd}},
7612 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd, 0x3266, 0x34cd}},
7613 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}},
7614 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266, 0x2e66, 0x3266}},
7616 const DWORD indices24[] = {0, 1, 2, 3, 4, 5};
7617 const DWORD attributes24[] = {0, 0};
7618 const UINT num_vertices24 = ARRAY_SIZE(vertices24);
7619 const UINT num_faces24 = ARRAY_SIZE(indices24) / VERTS_PER_FACE;
7620 DWORD flags24 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7621 const D3DXWELDEPSILONS epsilons24 = {1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, {0.41f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, 0.0f, 0.0f, 0.0f};
7622 const DWORD adjacency24[] = {-1, 1, -1, -1, -1, 0};
7623 const struct vertex_texcoord_float16_4 exp_vertices24[] =
7625 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}},
7626 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a, 0x3800, 0x399a}},
7627 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd, 0xb266, 0xb4cd}},
7629 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}},
7630 {{ 0.0f, 0.0f, 0.f}, {0x2e66, 0x3266, 0x2e66, 0x3266}},
7632 const DWORD exp_indices24[] = {0, 1, 2, 1, 3, 4};
7633 const DWORD exp_face_remap24[] = {0, 1};
7634 const DWORD exp_vertex_remap24[] = {0, 1, 2, 4, 5, -1};
7635 const DWORD exp_new_num_vertices24 = ARRAY_SIZE(exp_vertices24);
7636 /* Test 25. Weld texture coordinates with usage index 10 (TEXCOORD10). The
7637 * usage index is capped at 7, so the epsilon for TEXCOORD7 is used instead.
7639 const struct vertex_texcoord vertices25[] =
7641 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f}},
7642 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.7f}},
7643 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
7645 {{ 3.0f, 3.0f, 0.f}, {0.2f, 0.3f}},
7646 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f}},
7647 {{ 1.0f, 0.0f, 0.f}, {0.1f, 0.2f}}
7649 const DWORD indices25[] = {0, 1, 2, 3, 4, 5};
7650 const DWORD attributes25[] = {0, 0};
7651 const UINT num_vertices25 = ARRAY_SIZE(vertices25);
7652 const UINT num_faces25 = ARRAY_SIZE(indices25) / VERTS_PER_FACE;
7653 DWORD flags25 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7654 const D3DXWELDEPSILONS epsilons25 = {1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.4f + FLT_EPSILON}, 0.0f, 0.0f, 0.0f};
7655 const DWORD adjacency25[] = {-1, 1, -1, -1, -1, 0};
7656 const struct vertex_texcoord exp_vertices25[] =
7658 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f}},
7659 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.7f}},
7660 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
7662 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f}},
7663 {{ 0.0f, 0.0f, 0.f}, {0.1f, 0.2f}},
7665 const DWORD exp_indices25[] = {0, 1, 2, 1, 3, 4};
7666 const DWORD exp_face_remap25[] = {0, 1};
7667 const DWORD exp_vertex_remap25[] = {0, 1, 2, 4, 5, -1};
7668 const DWORD exp_new_num_vertices25 = ARRAY_SIZE(exp_vertices25);
7669 /* Test 26. Weld color with usage index larger than 1. Shows that none of
7670 * the epsilon values are used. */
7671 const struct vertex_color vertices26[] =
7673 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7674 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7675 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7677 {{ 3.0f, 3.0f, 0.f}, 0x00000000},
7678 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7679 {{ 1.0f, 0.0f, 0.f}, 0x01010101},
7681 const DWORD indices26[] = {0, 1, 2, 3, 4, 5};
7682 const DWORD attributes26[] = {0, 0};
7683 const UINT num_vertices26 = ARRAY_SIZE(vertices26);
7684 const UINT num_faces26 = ARRAY_SIZE(indices26) / VERTS_PER_FACE;
7685 DWORD flags26 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7686 const D3DXWELDEPSILONS epsilons26 = {1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, {1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f}, 1.0f, 1.0f, 1.0f};
7687 const DWORD adjacency26[] = {-1, 1, -1, -1, -1, 0};
7688 const struct vertex_color exp_vertices26[] =
7690 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7691 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7692 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7694 {{ 2.0f, 3.0f, 0.f}, 0x00000000},
7695 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7696 {{ 0.0f, 0.0f, 0.f}, 0x01010101},
7698 const DWORD exp_indices26[] = {0, 1, 2, 3, 4, 5};
7699 const DWORD exp_face_remap26[] = {0, 1};
7700 const DWORD exp_vertex_remap26[] = {0, 1, 2, 3, 4, 5};
7701 const DWORD exp_new_num_vertices26 = ARRAY_SIZE(exp_vertices26);
7702 /* Test 27. Weld color with usage index 1 (specular). */
7703 /* Previously this test used float color values and index > 1 but that case
7704 * appears to be effectively unhandled in native so the test gave
7705 * inconsistent results. */
7706 const struct vertex_color vertices27[] =
7708 {{ 0.0f, 3.0f, 0.0f}, 0x00000000},
7709 {{ 2.0f, 3.0f, 0.0f}, 0x10203040},
7710 {{ 0.0f, 0.0f, 0.0f}, 0x50607080},
7712 {{ 3.0f, 3.0f, 0.0f}, 0x11213141},
7713 {{ 3.0f, 0.0f, 0.0f}, 0xffffffff},
7714 {{ 1.0f, 0.0f, 0.0f}, 0x51617181},
7716 const DWORD indices27[] = {0, 1, 2, 3, 4, 5};
7717 const DWORD attributes27[] = {0, 0};
7718 const UINT num_vertices27 = ARRAY_SIZE(vertices27);
7719 const UINT num_faces27 = ARRAY_SIZE(indices27) / VERTS_PER_FACE;
7720 DWORD flags27 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7721 const D3DXWELDEPSILONS epsilons27 =
7723 1.1f, 0.0f, 0.0f, 0.0f, 2.0f / 255.0f, 0.0f,
7724 {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, 0.0f, 0.0f, 0.0f
7726 const DWORD adjacency27[] = {-1, 1, -1, -1, -1, 0};
7727 const struct vertex_color exp_vertices27[] =
7729 {{ 0.0f, 3.0f, 0.0f}, 0x00000000},
7730 {{ 2.0f, 3.0f, 0.0f}, 0x10203040},
7731 {{ 0.0f, 0.0f, 0.0f}, 0x50607080},
7733 {{ 3.0f, 0.0f, 0.0f}, 0xffffffff},
7735 const DWORD exp_indices27[] = {0, 1, 2, 1, 3, 2};
7736 const DWORD exp_face_remap27[] = {0, 1};
7737 const DWORD exp_vertex_remap27[] = {0, 1, 2, 4, -1, -1};
7738 const DWORD exp_new_num_vertices27 = ARRAY_SIZE(exp_vertices27);
7739 /* Test 28. Weld one normal with UDEC3. */
7740 const DWORD dword_udec3_zero = init_udec3_dword(0, 0, 0, 1);
7741 const DWORD dword_udec3_1023 = init_udec3_dword(1023, 1023, 1023, 1);
7742 const DWORD dword_udec3_1022 = init_udec3_dword(1022, 1022, 1022, 1);
7743 const struct vertex_normal_udec3 vertices28[] =
7745 {{ 0.0f, 3.0f, 0.f}, dword_udec3_zero},
7746 {{ 2.0f, 3.0f, 0.f}, dword_udec3_zero},
7747 {{ 0.0f, 0.0f, 0.f}, dword_udec3_zero},
7749 {{ 3.0f, 3.0f, 0.f}, dword_udec3_1023},
7750 {{ 3.0f, 0.0f, 0.f}, dword_udec3_zero},
7751 {{ 1.0f, 0.0f, 0.f}, dword_udec3_1022},
7753 const DWORD indices28[] = {0, 1, 2, 3, 4, 5};
7754 const DWORD attributes28[] = {0, 0};
7755 const UINT num_vertices28 = ARRAY_SIZE(vertices28);
7756 const UINT num_faces28 = ARRAY_SIZE(indices28) / VERTS_PER_FACE;
7757 DWORD flags28 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7758 const D3DXWELDEPSILONS epsilons28 = {1.0f, 0.0f, 1022.0f, 0.0f, 0.0f, 0.0f, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, 0.0f, 0.0f, 0.0f};
7759 const DWORD adjacency28[] = {-1, 1, -1, -1, -1, 0};
7760 const struct vertex_normal_udec3 exp_vertices28[] =
7762 {{ 0.0f, 3.0f, 0.f}, dword_udec3_zero},
7763 {{ 2.0f, 3.0f, 0.f}, dword_udec3_zero},
7764 {{ 0.0f, 0.0f, 0.f}, dword_udec3_zero},
7766 {{ 2.0f, 3.0f, 0.f}, dword_udec3_1023},
7767 {{ 3.0f, 0.0f, 0.f}, dword_udec3_zero},
7769 const DWORD exp_indices28[] = {0, 1, 2, 3, 4, 2};
7770 const DWORD exp_face_remap28[] = {0, 1};
7771 const DWORD exp_vertex_remap28[] = {0, 1, 2, 3, 4, -1};
7772 const DWORD exp_new_num_vertices28 = ARRAY_SIZE(exp_vertices28);
7773 /* Test 29. Weld one normal with DEC3N. */
7774 const DWORD dword_dec3n_zero = init_dec3n_dword(0, 0, 0, 1);
7775 const DWORD dword_dec3n_511 = init_dec3n_dword(511, 511, 511, 1);
7776 const DWORD dword_dec3n_510 = init_dec3n_dword(510, 510, 510, 1);
7777 const struct vertex_normal_dec3n vertices29[] =
7779 {{ 0.0f, 3.0f, 0.f}, dword_dec3n_zero},
7780 {{ 2.0f, 3.0f, 0.f}, dword_dec3n_zero},
7781 {{ 0.0f, 0.0f, 0.f}, dword_dec3n_zero},
7783 {{ 3.0f, 3.0f, 0.f}, dword_dec3n_511},
7784 {{ 3.0f, 0.0f, 0.f}, dword_dec3n_zero},
7785 {{ 1.0f, 0.0f, 0.f}, dword_dec3n_510},
7787 const DWORD indices29[] = {0, 1, 2, 3, 4, 5};
7788 const DWORD attributes29[] = {0, 0};
7789 const UINT num_vertices29 = ARRAY_SIZE(vertices29);
7790 const UINT num_faces29 = ARRAY_SIZE(indices29) / VERTS_PER_FACE;
7791 DWORD flags29 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7792 const D3DXWELDEPSILONS epsilons29 = {1.0f, 0.0f, 510.0f/511.0f, 0.0f, 0.0f, 0.0f, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, .0f}, 0.0f, 0.0f, 0.0f};
7793 const DWORD adjacency29[] = {-1, 1, -1, -1, -1, 0};
7794 const struct vertex_normal_dec3n exp_vertices29[] =
7796 {{ 0.0f, 3.0f, 0.f}, dword_dec3n_zero},
7797 {{ 2.0f, 3.0f, 0.f}, dword_dec3n_zero},
7798 {{ 0.0f, 0.0f, 0.f}, dword_dec3n_zero},
7800 {{ 2.0f, 3.0f, 0.f}, dword_dec3n_511},
7801 {{ 3.0f, 0.0f, 0.f}, dword_dec3n_zero},
7803 const DWORD exp_indices29[] = {0, 1, 2, 3, 4, 2};
7804 const DWORD exp_face_remap29[] = {0, 1};
7805 const DWORD exp_vertex_remap29[] = {0, 1, 2, 3, 4, -1};
7806 const DWORD exp_new_num_vertices29 = ARRAY_SIZE(exp_vertices29);
7807 /* All mesh data */
7808 DWORD *adjacency_out = NULL;
7809 DWORD *face_remap = NULL;
7810 ID3DXMesh *mesh = NULL;
7811 ID3DXBuffer *vertex_remap = NULL;
7812 struct
7814 const BYTE *vertices;
7815 const DWORD *indices;
7816 const DWORD *attributes;
7817 const DWORD num_vertices;
7818 const DWORD num_faces;
7819 const DWORD options;
7820 D3DVERTEXELEMENT9 *declaration;
7821 const UINT vertex_size;
7822 const DWORD flags;
7823 const D3DXWELDEPSILONS *epsilons;
7824 const DWORD *adjacency;
7825 const BYTE *exp_vertices;
7826 const DWORD *exp_indices;
7827 const DWORD *exp_face_remap;
7828 const DWORD *exp_vertex_remap;
7829 const DWORD exp_new_num_vertices;
7831 tc[] =
7834 (BYTE*)vertices0,
7835 indices0,
7836 attributes0,
7837 num_vertices0,
7838 num_faces0,
7839 options,
7840 declaration_normal,
7841 vertex_size_normal,
7842 flags0,
7843 NULL,
7844 adjacency0,
7845 (BYTE*)exp_vertices0,
7846 exp_indices0,
7847 exp_face_remap0,
7848 exp_vertex_remap0,
7849 exp_new_num_vertices0
7852 (BYTE*)vertices1,
7853 indices1,
7854 attributes1,
7855 num_vertices1,
7856 num_faces1,
7857 options,
7858 declaration_normal,
7859 vertex_size_normal,
7860 flags1,
7861 NULL,
7862 adjacency1,
7863 (BYTE*)exp_vertices1,
7864 exp_indices1,
7865 exp_face_remap1,
7866 exp_vertex_remap1,
7867 exp_new_num_vertices1
7870 (BYTE*)vertices2,
7871 indices2,
7872 attributes2,
7873 num_vertices2,
7874 num_faces2,
7875 options,
7876 declaration_normal,
7877 vertex_size_normal,
7878 flags2,
7879 &epsilons2,
7880 adjacency2,
7881 (BYTE*)exp_vertices2,
7882 exp_indices2,
7883 exp_face_remap2,
7884 exp_vertex_remap2,
7885 exp_new_num_vertices2
7888 (BYTE*)vertices3,
7889 indices3,
7890 attributes3,
7891 num_vertices3,
7892 num_faces3,
7893 options,
7894 declaration_normal,
7895 vertex_size_normal,
7896 flags3,
7897 &epsilons3,
7898 adjacency3,
7899 (BYTE*)exp_vertices3,
7900 exp_indices3,
7901 exp_face_remap3,
7902 exp_vertex_remap3,
7903 exp_new_num_vertices3
7906 (BYTE*)vertices4,
7907 indices4,
7908 attributes4,
7909 num_vertices4,
7910 num_faces4,
7911 options,
7912 declaration_normal,
7913 vertex_size_normal,
7914 flags4,
7915 &epsilons4,
7916 adjacency4,
7917 (BYTE*)exp_vertices4,
7918 exp_indices4,
7919 exp_face_remap4,
7920 exp_vertex_remap4,
7921 exp_new_num_vertices4
7923 /* Unusual ordering. */
7925 (BYTE*)vertices5,
7926 indices5,
7927 attributes5,
7928 num_vertices5,
7929 num_faces5,
7930 options,
7931 declaration_normal,
7932 vertex_size_normal,
7933 flags5,
7934 NULL,
7935 adjacency5,
7936 (BYTE*)exp_vertices5,
7937 exp_indices5,
7938 exp_face_remap5,
7939 exp_vertex_remap5,
7940 exp_new_num_vertices5
7943 (BYTE*)vertices6,
7944 indices6,
7945 attributes6,
7946 num_vertices6,
7947 num_faces6,
7948 options,
7949 declaration_normal,
7950 vertex_size_normal,
7951 flags6,
7952 &epsilons6,
7953 adjacency6,
7954 (BYTE*)exp_vertices6,
7955 exp_indices6,
7956 exp_face_remap6,
7957 exp_vertex_remap6,
7958 exp_new_num_vertices6
7961 (BYTE*)vertices6,
7962 (DWORD*)indices6_16bit,
7963 attributes6,
7964 num_vertices6,
7965 num_faces6,
7966 options_16bit,
7967 declaration_normal,
7968 vertex_size_normal,
7969 flags6,
7970 &epsilons6,
7971 adjacency6,
7972 (BYTE*)exp_vertices6,
7973 exp_indices6,
7974 exp_face_remap6,
7975 exp_vertex_remap6,
7976 exp_new_num_vertices6
7979 (BYTE*)vertices8,
7980 indices8,
7981 attributes8,
7982 num_vertices8,
7983 num_faces8,
7984 options,
7985 declaration_normal,
7986 vertex_size_normal,
7987 flags8,
7988 &epsilons8,
7989 adjacency8,
7990 (BYTE*)exp_vertices8,
7991 exp_indices8,
7992 exp_face_remap8,
7993 exp_vertex_remap8,
7994 exp_new_num_vertices8
7997 (BYTE*)vertices9,
7998 indices9,
7999 attributes9,
8000 num_vertices9,
8001 num_faces9,
8002 options,
8003 declaration_normal,
8004 vertex_size_normal,
8005 flags9,
8006 &epsilons9,
8007 adjacency9,
8008 (BYTE*)exp_vertices9,
8009 exp_indices9,
8010 exp_face_remap9,
8011 exp_vertex_remap9,
8012 exp_new_num_vertices9
8015 (BYTE*)vertices10,
8016 indices10,
8017 attributes10,
8018 num_vertices10,
8019 num_faces10,
8020 options,
8021 declaration_blendweight,
8022 vertex_size_blendweight,
8023 flags10,
8024 &epsilons10,
8025 adjacency10,
8026 (BYTE*)exp_vertices10,
8027 exp_indices10,
8028 exp_face_remap10,
8029 exp_vertex_remap10,
8030 exp_new_num_vertices10
8033 (BYTE*)vertices11,
8034 indices11,
8035 attributes11,
8036 num_vertices11,
8037 num_faces11,
8038 options,
8039 declaration_texcoord,
8040 vertex_size_texcoord,
8041 flags11,
8042 &epsilons11,
8043 adjacency11,
8044 (BYTE*)exp_vertices11,
8045 exp_indices11,
8046 exp_face_remap11,
8047 exp_vertex_remap11,
8048 exp_new_num_vertices11
8051 (BYTE*)vertices12,
8052 indices12,
8053 attributes12,
8054 num_vertices12,
8055 num_faces12,
8056 options,
8057 declaration_color,
8058 vertex_size_color,
8059 flags12,
8060 &epsilons12,
8061 adjacency12,
8062 (BYTE*)exp_vertices12,
8063 exp_indices12,
8064 exp_face_remap12,
8065 exp_vertex_remap12,
8066 exp_new_num_vertices12
8069 (BYTE*)vertices13,
8070 indices13,
8071 attributes13,
8072 num_vertices13,
8073 num_faces13,
8074 options,
8075 declaration_normal3,
8076 vertex_size_normal,
8077 flags13,
8078 &epsilons13,
8079 adjacency13,
8080 (BYTE*)exp_vertices13,
8081 exp_indices13,
8082 exp_face_remap13,
8083 exp_vertex_remap13,
8084 exp_new_num_vertices13
8087 (BYTE*)vertices14,
8088 indices14,
8089 attributes14,
8090 num_vertices14,
8091 num_faces14,
8092 options,
8093 declaration_color,
8094 vertex_size_color,
8095 flags14,
8096 &epsilons14,
8097 adjacency14,
8098 (BYTE*)exp_vertices14,
8099 exp_indices14,
8100 exp_face_remap14,
8101 exp_vertex_remap14,
8102 exp_new_num_vertices14
8105 (BYTE*)vertices15,
8106 indices15,
8107 attributes15,
8108 num_vertices15,
8109 num_faces15,
8110 options,
8111 declaration_color_ubyte4n,
8112 vertex_size_color_ubyte4, /* UBYTE4 same size as UBYTE4N */
8113 flags15,
8114 &epsilons15,
8115 adjacency15,
8116 (BYTE*)exp_vertices15,
8117 exp_indices15,
8118 exp_face_remap15,
8119 exp_vertex_remap15,
8120 exp_new_num_vertices15
8123 (BYTE*)vertices16,
8124 indices16,
8125 attributes16,
8126 num_vertices16,
8127 num_faces16,
8128 options,
8129 declaration_color_ubyte4,
8130 vertex_size_color_ubyte4,
8131 flags16,
8132 &epsilons16,
8133 adjacency16,
8134 (BYTE*)exp_vertices16,
8135 exp_indices16,
8136 exp_face_remap16,
8137 exp_vertex_remap16,
8138 exp_new_num_vertices16
8141 (BYTE*)vertices17,
8142 indices17,
8143 attributes17,
8144 num_vertices17,
8145 num_faces17,
8146 options,
8147 declaration_texcoord_short2,
8148 vertex_size_texcoord_short2,
8149 flags17,
8150 &epsilons17,
8151 adjacency17,
8152 (BYTE*)exp_vertices17,
8153 exp_indices17,
8154 exp_face_remap17,
8155 exp_vertex_remap17,
8156 exp_new_num_vertices17
8159 (BYTE*)vertices18,
8160 indices18,
8161 attributes18,
8162 num_vertices18,
8163 num_faces18,
8164 options,
8165 declaration_texcoord_short2n,
8166 vertex_size_texcoord_short2, /* SHORT2 same size as SHORT2N */
8167 flags18,
8168 &epsilons18,
8169 adjacency18,
8170 (BYTE*)exp_vertices18,
8171 exp_indices18,
8172 exp_face_remap18,
8173 exp_vertex_remap18,
8174 exp_new_num_vertices18
8177 (BYTE*)vertices19,
8178 indices19,
8179 attributes19,
8180 num_vertices19,
8181 num_faces19,
8182 options,
8183 declaration_texcoord_ushort2n,
8184 vertex_size_texcoord_short2, /* SHORT2 same size as USHORT2N */
8185 flags19,
8186 &epsilons19,
8187 adjacency19,
8188 (BYTE*)exp_vertices19,
8189 exp_indices19,
8190 exp_face_remap19,
8191 exp_vertex_remap19,
8192 exp_new_num_vertices19
8195 (BYTE*)vertices20,
8196 indices20,
8197 attributes20,
8198 num_vertices20,
8199 num_faces20,
8200 options,
8201 declaration_normal_short4,
8202 vertex_size_normal_short4,
8203 flags20,
8204 &epsilons20,
8205 adjacency20,
8206 (BYTE*)exp_vertices20,
8207 exp_indices20,
8208 exp_face_remap20,
8209 exp_vertex_remap20,
8210 exp_new_num_vertices20
8213 (BYTE*)vertices21,
8214 indices21,
8215 attributes21,
8216 num_vertices21,
8217 num_faces21,
8218 options,
8219 declaration_normal_short4n,
8220 vertex_size_normal_short4, /* SHORT4 same size as SHORT4N */
8221 flags21,
8222 &epsilons21,
8223 adjacency21,
8224 (BYTE*)exp_vertices21,
8225 exp_indices21,
8226 exp_face_remap21,
8227 exp_vertex_remap21,
8228 exp_new_num_vertices21
8231 (BYTE*)vertices22,
8232 indices22,
8233 attributes22,
8234 num_vertices22,
8235 num_faces22,
8236 options,
8237 declaration_normal_ushort4n,
8238 vertex_size_normal_short4, /* SHORT4 same size as USHORT4N */
8239 flags22,
8240 &epsilons22,
8241 adjacency22,
8242 (BYTE*)exp_vertices22,
8243 exp_indices22,
8244 exp_face_remap22,
8245 exp_vertex_remap22,
8246 exp_new_num_vertices22
8249 (BYTE*)vertices23,
8250 indices23,
8251 attributes23,
8252 num_vertices23,
8253 num_faces23,
8254 options,
8255 declaration_texcoord_float16_2,
8256 vertex_size_texcoord_float16_2,
8257 flags23,
8258 &epsilons23,
8259 adjacency23,
8260 (BYTE*)exp_vertices23,
8261 exp_indices23,
8262 exp_face_remap23,
8263 exp_vertex_remap23,
8264 exp_new_num_vertices23
8267 (BYTE*)vertices24,
8268 indices24,
8269 attributes24,
8270 num_vertices24,
8271 num_faces24,
8272 options,
8273 declaration_texcoord_float16_4,
8274 vertex_size_texcoord_float16_4,
8275 flags24,
8276 &epsilons24,
8277 adjacency24,
8278 (BYTE*)exp_vertices24,
8279 exp_indices24,
8280 exp_face_remap24,
8281 exp_vertex_remap24,
8282 exp_new_num_vertices24
8285 (BYTE*)vertices25,
8286 indices25,
8287 attributes25,
8288 num_vertices25,
8289 num_faces25,
8290 options,
8291 declaration_texcoord10,
8292 vertex_size_texcoord,
8293 flags25,
8294 &epsilons25,
8295 adjacency25,
8296 (BYTE*)exp_vertices25,
8297 exp_indices25,
8298 exp_face_remap25,
8299 exp_vertex_remap25,
8300 exp_new_num_vertices25
8303 (BYTE*)vertices26,
8304 indices26,
8305 attributes26,
8306 num_vertices26,
8307 num_faces26,
8308 options,
8309 declaration_color2,
8310 vertex_size_color,
8311 flags26,
8312 &epsilons26,
8313 adjacency26,
8314 (BYTE*)exp_vertices26,
8315 exp_indices26,
8316 exp_face_remap26,
8317 exp_vertex_remap26,
8318 exp_new_num_vertices26
8321 (BYTE*)vertices27,
8322 indices27,
8323 attributes27,
8324 num_vertices27,
8325 num_faces27,
8326 options,
8327 declaration_color1,
8328 vertex_size_color,
8329 flags27,
8330 &epsilons27,
8331 adjacency27,
8332 (BYTE*)exp_vertices27,
8333 exp_indices27,
8334 exp_face_remap27,
8335 exp_vertex_remap27,
8336 exp_new_num_vertices27
8339 (BYTE*)vertices28,
8340 indices28,
8341 attributes28,
8342 num_vertices28,
8343 num_faces28,
8344 options,
8345 declaration_normal_udec3,
8346 vertex_size_normal_udec3,
8347 flags28,
8348 &epsilons28,
8349 adjacency28,
8350 (BYTE*)exp_vertices28,
8351 exp_indices28,
8352 exp_face_remap28,
8353 exp_vertex_remap28,
8354 exp_new_num_vertices28
8357 (BYTE*)vertices29,
8358 indices29,
8359 attributes29,
8360 num_vertices29,
8361 num_faces29,
8362 options,
8363 declaration_normal_dec3n,
8364 vertex_size_normal_dec3n,
8365 flags29,
8366 &epsilons29,
8367 adjacency29,
8368 (BYTE*)exp_vertices29,
8369 exp_indices29,
8370 exp_face_remap29,
8371 exp_vertex_remap29,
8372 exp_new_num_vertices29
8376 test_context = new_test_context();
8377 if (!test_context)
8379 skip("Couldn't create test context\n");
8380 goto cleanup;
8383 for (i = 0; i < ARRAY_SIZE(tc); i++)
8385 DWORD j;
8386 DWORD *vertex_remap_ptr;
8387 DWORD new_num_vertices;
8389 hr = init_test_mesh(tc[i].num_faces, tc[i].num_vertices, tc[i].options,
8390 tc[i].declaration, test_context->device, &mesh,
8391 tc[i].vertices, tc[i].vertex_size,
8392 tc[i].indices, tc[i].attributes);
8393 if (FAILED(hr))
8395 skip("Couldn't initialize test mesh %d.\n", i);
8396 goto cleanup;
8399 /* Allocate out parameters */
8400 adjacency_out = HeapAlloc(GetProcessHeap(), 0, VERTS_PER_FACE * tc[i].num_faces * sizeof(*adjacency_out));
8401 if (!adjacency_out)
8403 skip("Couldn't allocate adjacency_out array.\n");
8404 goto cleanup;
8406 face_remap = HeapAlloc(GetProcessHeap(), 0, tc[i].num_faces * sizeof(*face_remap));
8407 if (!face_remap)
8409 skip("Couldn't allocate face_remap array.\n");
8410 goto cleanup;
8413 hr = D3DXWeldVertices(mesh, tc[i].flags, tc[i].epsilons, tc[i].adjacency,
8414 adjacency_out, face_remap, &vertex_remap);
8415 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
8416 /* Check number of vertices*/
8417 new_num_vertices = mesh->lpVtbl->GetNumVertices(mesh);
8418 ok(new_num_vertices == tc[i].exp_new_num_vertices,
8419 "Mesh %d: new_num_vertices == %d, expected %d.\n",
8420 i, new_num_vertices, tc[i].exp_new_num_vertices);
8421 /* Check index buffer */
8422 if (tc[i].options & D3DXMESH_32BIT)
8424 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, (void**)&indices);
8425 if (FAILED(hr))
8427 skip("Couldn't lock index buffer.\n");
8428 goto cleanup;
8430 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
8432 ok(indices[j] == tc[i].exp_indices[j],
8433 "Mesh %d: indices[%d] == %d, expected %d\n",
8434 i, j, indices[j], tc[i].exp_indices[j]);
8437 else
8439 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, (void**)&indices_16bit);
8440 if (FAILED(hr))
8442 skip("Couldn't lock index buffer.\n");
8443 goto cleanup;
8445 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
8447 ok(indices_16bit[j] == tc[i].exp_indices[j],
8448 "Mesh %d: indices_16bit[%d] == %d, expected %d\n",
8449 i, j, indices_16bit[j], tc[i].exp_indices[j]);
8452 mesh->lpVtbl->UnlockIndexBuffer(mesh);
8453 indices = NULL;
8454 indices_16bit = NULL;
8455 /* Check adjacency_out */
8456 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
8458 ok(adjacency_out[j] == tc[i].adjacency[j],
8459 "Mesh %d: adjacency_out[%d] == %d, expected %d\n",
8460 i, j, adjacency_out[j], tc[i].adjacency[j]);
8462 /* Check face_remap */
8463 for (j = 0; j < tc[i].num_faces; j++)
8465 ok(face_remap[j] == tc[i].exp_face_remap[j],
8466 "Mesh %d: face_remap[%d] == %d, expected %d\n",
8467 i, j, face_remap[j], tc[i].exp_face_remap[j]);
8469 /* Check vertex_remap */
8470 vertex_remap_ptr = vertex_remap->lpVtbl->GetBufferPointer(vertex_remap);
8471 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
8473 ok(vertex_remap_ptr[j] == tc[i].exp_vertex_remap[j],
8474 "Mesh %d: vertex_remap_ptr[%d] == %d, expected %d\n",
8475 i, j, vertex_remap_ptr[j], tc[i].exp_vertex_remap[j]);
8477 /* Check vertex buffer */
8478 hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, (void*)&vertices);
8479 if (FAILED(hr))
8481 skip("Couldn't lock vertex buffer.\n");
8482 goto cleanup;
8484 /* Check contents of re-ordered vertex buffer */
8485 for (j = 0; j < tc[i].exp_new_num_vertices; j++)
8487 int index = tc[i].vertex_size*j;
8488 check_vertex_components(__LINE__, i, j, &vertices[index], &tc[i].exp_vertices[index], tc[i].declaration);
8490 mesh->lpVtbl->UnlockVertexBuffer(mesh);
8491 vertices = NULL;
8493 /* Free mesh and output data */
8494 HeapFree(GetProcessHeap(), 0, adjacency_out);
8495 adjacency_out = NULL;
8496 HeapFree(GetProcessHeap(), 0, face_remap);
8497 face_remap = NULL;
8498 vertex_remap->lpVtbl->Release(vertex_remap);
8499 vertex_remap = NULL;
8500 mesh->lpVtbl->Release(mesh);
8501 mesh = NULL;
8504 cleanup:
8505 HeapFree(GetProcessHeap(), 0, adjacency_out);
8506 HeapFree(GetProcessHeap(), 0, face_remap);
8507 if (indices) mesh->lpVtbl->UnlockIndexBuffer(mesh);
8508 if (indices_16bit) mesh->lpVtbl->UnlockIndexBuffer(mesh);
8509 if (mesh) mesh->lpVtbl->Release(mesh);
8510 if (vertex_remap) vertex_remap->lpVtbl->Release(vertex_remap);
8511 if (vertices) mesh->lpVtbl->UnlockVertexBuffer(mesh);
8512 free_test_context(test_context);
8515 static void test_clone_mesh(void)
8517 HRESULT hr;
8518 struct test_context *test_context = NULL;
8519 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
8520 D3DVERTEXELEMENT9 declaration_pn[] =
8522 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8523 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
8524 D3DDECL_END()
8526 D3DVERTEXELEMENT9 declaration_pntc[] =
8528 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8529 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
8530 {0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8531 D3DDECL_END()
8533 D3DVERTEXELEMENT9 declaration_ptcn[] =
8535 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8536 {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8537 {0, 20, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
8538 D3DDECL_END()
8540 D3DVERTEXELEMENT9 declaration_ptc[] =
8542 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8543 {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8544 D3DDECL_END()
8546 D3DVERTEXELEMENT9 declaration_ptc_float16_2[] =
8548 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8549 {0, 12, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8550 D3DDECL_END()
8552 D3DVERTEXELEMENT9 declaration_ptc_float16_4[] =
8554 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8555 {0, 12, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8556 D3DDECL_END()
8558 D3DVERTEXELEMENT9 declaration_ptc_float1[] =
8560 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8561 {0, 12, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8562 D3DDECL_END()
8564 D3DVERTEXELEMENT9 declaration_ptc_float3[] =
8566 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8567 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8568 D3DDECL_END()
8570 D3DVERTEXELEMENT9 declaration_ptc_float4[] =
8572 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8573 {0, 12, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8574 D3DDECL_END()
8576 D3DVERTEXELEMENT9 declaration_ptc_d3dcolor[] =
8578 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8579 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8580 D3DDECL_END()
8582 D3DVERTEXELEMENT9 declaration_ptc_ubyte4[] =
8584 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8585 {0, 12, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8586 D3DDECL_END()
8588 D3DVERTEXELEMENT9 declaration_ptc_ubyte4n[] =
8590 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8591 {0, 12, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8592 D3DDECL_END()
8594 D3DVERTEXELEMENT9 declaration_ptc_short2[] =
8596 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8597 {0, 12, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8598 D3DDECL_END()
8600 D3DVERTEXELEMENT9 declaration_ptc_short4[] =
8602 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8603 {0, 12, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8604 D3DDECL_END()
8606 D3DVERTEXELEMENT9 declaration_ptc_short2n[] =
8608 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8609 {0, 12, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8610 D3DDECL_END()
8612 D3DVERTEXELEMENT9 declaration_ptc_short4n[] =
8614 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8615 {0, 12, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8616 D3DDECL_END()
8618 D3DVERTEXELEMENT9 declaration_ptc_ushort2n[] =
8620 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8621 {0, 12, D3DDECLTYPE_USHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8622 D3DDECL_END()
8624 D3DVERTEXELEMENT9 declaration_ptc_ushort4n[] =
8626 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8627 {0, 12, D3DDECLTYPE_USHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8628 D3DDECL_END()
8630 D3DVERTEXELEMENT9 declaration_ptc_float16_2_partialu[] =
8632 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8633 {0, 12, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_PARTIALU, D3DDECLUSAGE_TEXCOORD, 0},
8634 D3DDECL_END()
8636 D3DVERTEXELEMENT9 declaration_pntc1[] =
8638 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8639 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
8640 {0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
8641 D3DDECL_END()
8643 const unsigned int VERTS_PER_FACE = 3;
8644 BYTE *vertices = NULL;
8645 INT i;
8646 struct vertex_pn
8648 D3DXVECTOR3 position;
8649 D3DXVECTOR3 normal;
8651 struct vertex_pntc
8653 D3DXVECTOR3 position;
8654 D3DXVECTOR3 normal;
8655 D3DXVECTOR2 texcoords;
8657 struct vertex_ptcn
8659 D3DXVECTOR3 position;
8660 D3DXVECTOR2 texcoords;
8661 D3DXVECTOR3 normal;
8663 struct vertex_ptc
8665 D3DXVECTOR3 position;
8666 D3DXVECTOR2 texcoords;
8668 struct vertex_ptc_float16_2
8670 D3DXVECTOR3 position;
8671 WORD texcoords[2]; /* float16_2 */
8673 struct vertex_ptc_float16_4
8675 D3DXVECTOR3 position;
8676 WORD texcoords[4]; /* float16_4 */
8678 struct vertex_ptc_float1
8680 D3DXVECTOR3 position;
8681 FLOAT texcoords;
8683 struct vertex_ptc_float3
8685 D3DXVECTOR3 position;
8686 FLOAT texcoords[3];
8688 struct vertex_ptc_float4
8690 D3DXVECTOR3 position;
8691 FLOAT texcoords[4];
8693 struct vertex_ptc_d3dcolor
8695 D3DXVECTOR3 position;
8696 BYTE texcoords[4];
8698 struct vertex_ptc_ubyte4
8700 D3DXVECTOR3 position;
8701 BYTE texcoords[4];
8703 struct vertex_ptc_ubyte4n
8705 D3DXVECTOR3 position;
8706 BYTE texcoords[4];
8708 struct vertex_ptc_short2
8710 D3DXVECTOR3 position;
8711 SHORT texcoords[2];
8713 struct vertex_ptc_short4
8715 D3DXVECTOR3 position;
8716 SHORT texcoords[4];
8718 struct vertex_ptc_ushort2n
8720 D3DXVECTOR3 position;
8721 USHORT texcoords[2];
8723 struct vertex_ptc_ushort4n
8725 D3DXVECTOR3 position;
8726 USHORT texcoords[4];
8728 struct vertex_ptc_udec3
8730 D3DXVECTOR3 position;
8731 DWORD texcoords;
8733 struct vertex_ptc_dec3n
8735 D3DXVECTOR3 position;
8736 DWORD texcoords;
8738 D3DXVECTOR3 up = {0.0f, 0.0f, 1.0f};
8739 D3DXVECTOR2 zero_vec2 = {0.0f, 0.0f};
8740 /* Test 0. Check that a mesh can be cloned if the new declaration is the
8741 * same as the one used to create the mesh.
8743 * 0--1 3
8744 * | / /|
8745 * |/ / |
8746 * 2 5--4
8748 const struct vertex_pn vertices0[] =
8750 {{ 0.0f, 3.0f, 0.f}, up},
8751 {{ 2.0f, 3.0f, 0.f}, up},
8752 {{ 0.0f, 0.0f, 0.f}, up},
8754 {{ 3.0f, 3.0f, 0.f}, up},
8755 {{ 3.0f, 0.0f, 0.f}, up},
8756 {{ 1.0f, 0.0f, 0.f}, up},
8758 const UINT num_vertices0 = ARRAY_SIZE(vertices0);
8759 const UINT num_faces0 = ARRAY_SIZE(vertices0) / VERTS_PER_FACE;
8760 const UINT vertex_size0 = sizeof(*vertices0);
8761 /* Test 1. Check that 16-bit indices are handled. */
8762 const DWORD options_16bit = D3DXMESH_SYSTEMMEM;
8763 /* Test 2. Check that the size of each vertex is increased and the data
8764 * moved if the new declaration adds an element after the original elements.
8766 const struct vertex_pntc exp_vertices2[] =
8768 {{ 0.0f, 3.0f, 0.f}, up, zero_vec2},
8769 {{ 2.0f, 3.0f, 0.f}, up, zero_vec2},
8770 {{ 0.0f, 0.0f, 0.f}, up, zero_vec2},
8772 {{ 3.0f, 3.0f, 0.f}, up, zero_vec2},
8773 {{ 3.0f, 0.0f, 0.f}, up, zero_vec2},
8774 {{ 1.0f, 0.0f, 0.f}, up, zero_vec2},
8776 const UINT exp_vertex_size2 = sizeof(*exp_vertices2);
8777 /* Test 3. Check that the size of each vertex is increased and the data
8778 * moved if the new declaration adds an element between the original
8779 * elements.
8781 const struct vertex_ptcn exp_vertices3[] =
8783 {{ 0.0f, 3.0f, 0.f}, zero_vec2, up},
8784 {{ 2.0f, 3.0f, 0.f}, zero_vec2, up},
8785 {{ 0.0f, 0.0f, 0.f}, zero_vec2, up},
8787 {{ 3.0f, 3.0f, 0.f}, zero_vec2, up},
8788 {{ 3.0f, 0.0f, 0.f}, zero_vec2, up},
8789 {{ 1.0f, 0.0f, 0.f}, zero_vec2, up},
8791 const UINT exp_vertex_size3 = sizeof(*exp_vertices3);
8792 /* Test 4. Test that data types can be converted, e.g. FLOAT2 to FLOAT16_2. */
8793 const struct vertex_ptc vertices4[] =
8795 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8796 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8797 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
8799 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8800 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
8801 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
8803 const UINT num_vertices4 = ARRAY_SIZE(vertices4);
8804 const UINT num_faces4 = ARRAY_SIZE(vertices4) / VERTS_PER_FACE;
8805 const UINT vertex_size4 = sizeof(*vertices4);
8806 const struct vertex_ptc_float16_2 exp_vertices4[] =
8808 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
8809 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */
8810 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */
8812 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd}}, /* {0.2f, 0.3f} */
8813 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
8814 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */
8816 const UINT exp_vertex_size4 = sizeof(*exp_vertices4);
8817 /* Test 5. Convert FLOAT2 to FLOAT16_4. */
8818 const struct vertex_ptc vertices5[] =
8820 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8821 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8822 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
8824 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8825 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
8826 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
8828 const UINT num_vertices5 = ARRAY_SIZE(vertices5);
8829 const UINT num_faces5 = ARRAY_SIZE(vertices5) / VERTS_PER_FACE;
8830 const UINT vertex_size5 = sizeof(*vertices5);
8831 const struct vertex_ptc_float16_4 exp_vertices5[] =
8833 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00, 0, 0x3c00}}, /* {1.0f, 1.0f, 0.0f, 1.0f} */
8834 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a, 0, 0x3c00}}, /* {0.5f, 0.7f, 0.0f, 1.0f} */
8835 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd, 0, 0x3c00}}, /* {-0.2f, -0.3f, 0.0f, 1.0f} */
8837 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd, 0, 0x3c00}}, /* {0.2f, 0.3f, 0.0f, 1.0f} */
8838 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00, 0, 0x3c00}}, /* {1.0f, 1.0f, 0.0f, 1.0f} */
8839 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266, 0, 0x3c00}}, /* {0.1f, 0.2f, 0.0f, 1.0f} */
8841 const UINT exp_vertex_size5 = sizeof(*exp_vertices5);
8842 /* Test 6. Convert FLOAT2 to FLOAT1. */
8843 const struct vertex_ptc vertices6[] =
8845 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8846 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8847 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
8849 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8850 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
8851 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
8853 const UINT num_vertices6 = ARRAY_SIZE(vertices6);
8854 const UINT num_faces6 = ARRAY_SIZE(vertices6) / VERTS_PER_FACE;
8855 const UINT vertex_size6 = sizeof(*vertices6);
8856 const struct vertex_ptc_float1 exp_vertices6[] =
8858 {{ 0.0f, 3.0f, 0.f}, 1.0f},
8859 {{ 2.0f, 3.0f, 0.f}, 0.5f},
8860 {{ 0.0f, 0.0f, 0.f}, -0.2f},
8862 {{ 3.0f, 3.0f, 0.f}, 0.2f},
8863 {{ 3.0f, 0.0f, 0.f}, 1.0f},
8864 {{ 1.0f, 0.0f, 0.f}, 0.1f},
8866 const UINT exp_vertex_size6 = sizeof(*exp_vertices6);
8867 /* Test 7. Convert FLOAT2 to FLOAT3. */
8868 const struct vertex_ptc vertices7[] =
8870 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8871 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8872 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
8874 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8875 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
8876 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
8878 const UINT num_vertices7 = ARRAY_SIZE(vertices7);
8879 const UINT num_faces7 = ARRAY_SIZE(vertices7) / VERTS_PER_FACE;
8880 const UINT vertex_size7 = sizeof(*vertices7);
8881 const struct vertex_ptc_float3 exp_vertices7[] =
8883 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f, 0.0f}},
8884 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f, 0.0f}},
8885 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f, 0.0f}},
8887 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f, 0.0f}},
8888 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f, 0.0f}},
8889 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f, 0.0f}},
8891 const UINT exp_vertex_size7 = sizeof(*exp_vertices7);
8892 /* Test 8. Convert FLOAT2 to FLOAT4. */
8893 const struct vertex_ptc vertices8[] =
8895 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8896 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8897 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
8899 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8900 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
8901 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
8903 const UINT num_vertices8 = ARRAY_SIZE(vertices8);
8904 const UINT num_faces8 = ARRAY_SIZE(vertices8) / VERTS_PER_FACE;
8905 const UINT vertex_size8 = sizeof(*vertices8);
8906 const struct vertex_ptc_float4 exp_vertices8[] =
8908 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f, 0.0f, 1.0f}},
8909 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f, 0.0f, 1.0f}},
8910 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f, 0.0f, 1.0f}},
8912 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f, 0.0f, 1.0f}},
8913 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f, 0.0f, 1.0f}},
8914 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f, 0.0f, 1.0f}},
8916 const UINT exp_vertex_size8 = sizeof(*exp_vertices8);
8917 /* Test 9. Convert FLOAT2 to D3DCOLOR. */
8918 const struct vertex_ptc vertices9[] =
8920 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8921 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8922 {{ 0.0f, 0.0f, 0.f}, {-0.4f, -0.6f}},
8924 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8925 {{ 3.0f, 0.0f, 0.f}, { 2.0f, 256.0f}},
8926 {{ 1.0f, 0.0f, 0.f}, { 0.11f, 0.2f}},
8928 const UINT num_vertices9 = ARRAY_SIZE(vertices9);
8929 const UINT num_faces9 = ARRAY_SIZE(vertices9) / VERTS_PER_FACE;
8930 const UINT vertex_size9 = sizeof(*vertices9);
8931 const struct vertex_ptc_d3dcolor exp_vertices9[] =
8933 {{ 0.0f, 3.0f, 0.f}, {0, 255, 255, 255}},
8934 {{ 2.0f, 3.0f, 0.f}, {0, 179, 128, 255}},
8935 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 255}},
8937 {{ 3.0f, 3.0f, 0.f}, {0, 77, 51, 255}},
8938 {{ 3.0f, 0.0f, 0.f}, {0, 255, 255, 255}},
8939 {{ 1.0f, 0.0f, 0.f}, {0, 51, 28, 255}},
8941 const UINT exp_vertex_size9 = sizeof(*exp_vertices9);
8942 /* Test 10. Convert FLOAT2 to UBYTE4. */
8943 const struct vertex_ptc vertices10[] =
8945 {{ 0.0f, 3.0f, 0.f}, { 0.0f, 1.0f}},
8946 {{ 2.0f, 3.0f, 0.f}, { 2.0f, 3.0f}},
8947 {{ 0.0f, 0.0f, 0.f}, { 254.0f, 255.0f}},
8949 {{ 3.0f, 3.0f, 0.f}, { 256.0f, 257.0f}},
8950 {{ 3.0f, 0.0f, 0.f}, { 1.4f, 1.5f}},
8951 {{ 1.0f, 0.0f, 0.f}, {-4.0f, -5.0f}},
8953 const UINT num_vertices10 = ARRAY_SIZE(vertices10);
8954 const UINT num_faces10 = ARRAY_SIZE(vertices10) / VERTS_PER_FACE;
8955 const UINT vertex_size10 = sizeof(*vertices10);
8956 const struct vertex_ptc_ubyte4 exp_vertices10[] =
8958 {{ 0.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
8959 {{ 2.0f, 3.0f, 0.f}, {2, 3, 0, 1}},
8960 {{ 0.0f, 0.0f, 0.f}, {254, 255, 0, 1}},
8962 {{ 3.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
8963 {{ 3.0f, 0.0f, 0.f}, {1, 2, 0, 1}},
8964 {{ 1.0f, 0.0f, 0.f}, {0, 0, 0, 1}},
8966 const UINT exp_vertex_size10 = sizeof(*exp_vertices10);
8967 /* Test 11. Convert FLOAT2 to SHORT2. */
8968 const struct vertex_ptc vertices11[] =
8970 {{ 0.0f, 3.0f, 0.f}, { 1.0f, -1.0f}},
8971 {{ 2.0f, 3.0f, 0.f}, { 0.4f, 0.5f}},
8972 {{ 0.0f, 0.0f, 0.f}, {-0.5f, -5.0f}},
8974 {{ 3.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MIN}},
8975 {{ 3.0f, 0.0f, 0.f}, {SHRT_MAX + 1.0f, SHRT_MIN - 1.0f}},
8976 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX + 2.0f, SHRT_MIN - 2.0f}},
8978 {{ 4.0f, 3.0f, 0.f}, {2 * SHRT_MAX, 2 * SHRT_MIN}},
8979 {{ 6.0f, 0.0f, 0.f}, {3 * SHRT_MAX, 3 * SHRT_MIN}},
8980 {{ 4.0f, 0.0f, 0.f}, {4 * SHRT_MAX, 4 * SHRT_MIN}},
8982 const UINT num_vertices11 = ARRAY_SIZE(vertices11);
8983 const UINT num_faces11 = ARRAY_SIZE(vertices11) / VERTS_PER_FACE;
8984 const UINT vertex_size11 = sizeof(*vertices11);
8985 const struct vertex_ptc_short2 exp_vertices11[] =
8987 {{ 0.0f, 3.0f, 0.f}, {1, 0}},
8988 {{ 2.0f, 3.0f, 0.f}, {0, 1}},
8989 {{ 0.0f, 0.0f, 0.f}, {0, -4}},
8991 {{ 3.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MIN + 1}},
8992 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MIN}},
8993 {{ 1.0f, 0.0f, 0.f}, {SHRT_MIN + 1, SHRT_MAX}},
8995 {{ 4.0f, 3.0f, 0.f}, {-2, 1}},
8996 {{ 6.0f, 0.0f, 0.f}, {32765, -32767}},
8997 {{ 4.0f, 0.0f, 0.f}, {-4, 1}},
8999 const UINT exp_vertex_size11 = sizeof(*exp_vertices11);
9000 /* Test 12. Convert FLOAT2 to SHORT4. */
9001 const struct vertex_ptc vertices12[] =
9003 {{ 0.0f, 3.0f, 0.f}, { 1.0f, -1.0f}},
9004 {{ 2.0f, 3.0f, 0.f}, { 0.4f, 0.5f}},
9005 {{ 0.0f, 0.0f, 0.f}, {-0.5f, -5.0f}},
9007 {{ 3.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MIN}},
9008 {{ 3.0f, 0.0f, 0.f}, {SHRT_MAX + 1.0f, SHRT_MIN - 1.0f}},
9009 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX + 2.0f, SHRT_MIN - 2.0f}},
9011 {{ 4.0f, 3.0f, 0.f}, {2 * SHRT_MAX, 2 * SHRT_MIN}},
9012 {{ 6.0f, 0.0f, 0.f}, {3 * SHRT_MAX, 3 * SHRT_MIN}},
9013 {{ 4.0f, 0.0f, 0.f}, {4 * SHRT_MAX, 4 * SHRT_MIN}},
9015 const UINT num_vertices12 = ARRAY_SIZE(vertices12);
9016 const UINT num_faces12 = ARRAY_SIZE(vertices12) / VERTS_PER_FACE;
9017 const UINT vertex_size12 = sizeof(*vertices12);
9018 const struct vertex_ptc_short4 exp_vertices12[] =
9020 {{ 0.0f, 3.0f, 0.f}, {1, 0, 0, 1}},
9021 {{ 2.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
9022 {{ 0.0f, 0.0f, 0.f}, {0, -4, 0, 1}},
9024 {{ 3.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MIN + 1, 0, 1}},
9025 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MIN, 0, 1}},
9026 {{ 1.0f, 0.0f, 0.f}, {SHRT_MIN + 1, SHRT_MAX, 0, 1}},
9028 {{ 4.0f, 3.0f, 0.f}, {-2, 1, 0, 1}},
9029 {{ 6.0f, 0.0f, 0.f}, {32765, -32767, 0, 1}},
9030 {{ 4.0f, 0.0f, 0.f}, {-4, 1, 0, 1}},
9032 const UINT exp_vertex_size12 = sizeof(*exp_vertices12);
9033 /* Test 13. Convert FLOAT2 to UBYTE4N. */
9034 const struct vertex_ptc vertices13[] =
9036 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 2.0f}},
9037 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
9038 {{ 0.0f, 0.0f, 0.f}, {-0.4f, -0.5f}},
9040 {{ 3.0f, 3.0f, 0.f}, {-0.6f, -1.0f}},
9041 {{ 3.0f, 0.0f, 0.f}, {UCHAR_MAX, UCHAR_MAX + 1}},
9042 {{ 1.0f, 0.0f, 0.f}, {2 * UCHAR_MAX, -UCHAR_MAX}},
9044 const UINT num_vertices13 = ARRAY_SIZE(vertices13);
9045 const UINT num_faces13 = ARRAY_SIZE(vertices13) / VERTS_PER_FACE;
9046 const UINT vertex_size13 = sizeof(*vertices13);
9047 const struct vertex_ptc_ubyte4n exp_vertices13[] =
9049 {{ 0.0f, 3.0f, 0.f}, {255, 255, 0, 255}},
9050 {{ 2.0f, 3.0f, 0.f}, {128, 179, 0, 255}},
9051 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 255}},
9053 {{ 3.0f, 3.0f, 0.f}, {0, 0, 0, 255}},
9054 {{ 3.0f, 0.0f, 0.f}, {255, 255, 0, 255}},
9055 {{ 1.0f, 0.0f, 0.f}, {255, 0, 0, 255}},
9057 const UINT exp_vertex_size13 = sizeof(*exp_vertices13);
9058 /* Test 14. Convert FLOAT2 to SHORT2N. */
9059 const struct vertex_ptc vertices14[] =
9061 {{ 0.0f, 3.0f, 0.f}, {1.0f, 2.0f}},
9062 {{ 2.0f, 3.0f, 0.f}, {0.4f, 0.5f}},
9063 {{ 0.0f, 0.0f, 0.f}, {0.6f, -1.0f}},
9065 {{ 3.0f, 3.0f, 0.f}, {-0.4f, -0.5f}},
9066 {{ 3.0f, 0.0f, 0.f}, {-0.9f, -0.99997}},
9067 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX, SHRT_MIN}},
9069 const UINT num_vertices14 = ARRAY_SIZE(vertices14);
9070 const UINT num_faces14 = ARRAY_SIZE(vertices14) / VERTS_PER_FACE;
9071 const UINT vertex_size14 = sizeof(*vertices14);
9072 const struct vertex_ptc_short2 exp_vertices14[] =
9074 {{ 0.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MAX}},
9075 {{ 2.0f, 3.0f, 0.f}, {13107, 16384}},
9076 {{ 0.0f, 0.0f, 0.f}, {19660, SHRT_MIN + 2}},
9078 {{ 3.0f, 3.0f, 0.f}, {-13106, -16383}},
9079 {{ 3.0f, 0.0f, 0.f}, {-29489, SHRT_MIN + 3}},
9080 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX, SHRT_MIN + 2}},
9082 const UINT exp_vertex_size14 = sizeof(*exp_vertices14);
9083 /* Test 15. Convert FLOAT2 to SHORT4N. */
9084 const struct vertex_ptc vertices15[] =
9086 {{ 0.0f, 3.0f, 0.f}, {1.0f, 2.0f}},
9087 {{ 2.0f, 3.0f, 0.f}, {0.4f, 0.5f}},
9088 {{ 0.0f, 0.0f, 0.f}, {0.6f, -1.0f}},
9090 {{ 3.0f, 3.0f, 0.f}, {-0.4f, -0.5f}},
9091 {{ 3.0f, 0.0f, 0.f}, {-0.9f, -0.99997}},
9092 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX, SHRT_MIN}},
9094 const UINT num_vertices15 = ARRAY_SIZE(vertices15);
9095 const UINT num_faces15 = ARRAY_SIZE(vertices15) / VERTS_PER_FACE;
9096 const UINT vertex_size15 = sizeof(*vertices15);
9097 const struct vertex_ptc_short4 exp_vertices15[] =
9099 {{ 0.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MAX, 0, SHRT_MAX}},
9100 {{ 2.0f, 3.0f, 0.f}, {13107, 16384, 0, SHRT_MAX}},
9101 {{ 0.0f, 0.0f, 0.f}, {19660, SHRT_MIN + 2, 0, SHRT_MAX}},
9103 {{ 3.0f, 3.0f, 0.f}, {-13106, -16383, 0, SHRT_MAX}},
9104 {{ 3.0f, 0.0f, 0.f}, {-29489, SHRT_MIN + 3, 0, SHRT_MAX}},
9105 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX, SHRT_MIN + 2, 0, SHRT_MAX}},
9107 const UINT exp_vertex_size15 = sizeof(*exp_vertices15);
9108 /* Test 16. Convert FLOAT2 to USHORT2N. */
9109 const struct vertex_ptc vertices16[] =
9111 {{ 0.0f, 3.0f, 0.f}, {1.0f, 2.0f}},
9112 {{ 2.0f, 3.0f, 0.f}, {0.4f, 0.5f}},
9113 {{ 0.0f, 0.0f, 0.f}, {0.6f, -1.0f}},
9115 {{ 3.0f, 3.0f, 0.f}, {-0.4f, -0.5f}},
9116 {{ 3.0f, 0.0f, 0.f}, {-0.9f, 0.99998f}},
9117 {{ 1.0f, 0.0f, 0.f}, {USHRT_MAX, 0.0f}},
9119 const UINT num_vertices16 = ARRAY_SIZE(vertices16);
9120 const UINT num_faces16 = ARRAY_SIZE(vertices16) / VERTS_PER_FACE;
9121 const UINT vertex_size16 = sizeof(*vertices16);
9122 const struct vertex_ptc_ushort2n exp_vertices16[] =
9124 {{ 0.0f, 3.0f, 0.f}, {USHRT_MAX, USHRT_MAX}},
9125 {{ 2.0f, 3.0f, 0.f}, {26214, 32768}},
9126 {{ 0.0f, 0.0f, 0.f}, {39321, 0}},
9128 {{ 3.0f, 3.0f, 0.f}, {0, 0}},
9129 {{ 3.0f, 0.0f, 0.f}, {0, USHRT_MAX - 1}},
9130 {{ 1.0f, 0.0f, 0.f}, {USHRT_MAX, 0}},
9132 const UINT exp_vertex_size16 = sizeof(*exp_vertices16);
9133 /* Test 17. Convert FLOAT2 to USHORT4N. */
9134 const struct vertex_ptc vertices17[] =
9136 {{ 0.0f, 3.0f, 0.f}, {1.0f, 2.0f}},
9137 {{ 2.0f, 3.0f, 0.f}, {0.4f, 0.5f}},
9138 {{ 0.0f, 0.0f, 0.f}, {0.6f, -1.0f}},
9140 {{ 3.0f, 3.0f, 0.f}, {-0.4f, -0.5f}},
9141 {{ 3.0f, 0.0f, 0.f}, {-0.9f, 0.99998f}},
9142 {{ 1.0f, 0.0f, 0.f}, {USHRT_MAX, 0.0f}},
9144 const UINT num_vertices17 = ARRAY_SIZE(vertices17);
9145 const UINT num_faces17 = ARRAY_SIZE(vertices17) / VERTS_PER_FACE;
9146 const UINT vertex_size17 = sizeof(*vertices17);
9147 const struct vertex_ptc_ushort4n exp_vertices17[] =
9149 {{ 0.0f, 3.0f, 0.f}, {USHRT_MAX, USHRT_MAX, 0, USHRT_MAX}},
9150 {{ 2.0f, 3.0f, 0.f}, {26214, 32768, 0, USHRT_MAX}},
9151 {{ 0.0f, 0.0f, 0.f}, {39321, 0, 0, USHRT_MAX}},
9153 {{ 3.0f, 3.0f, 0.f}, {0, 0, 0, USHRT_MAX}},
9154 {{ 3.0f, 0.0f, 0.f}, {0, USHRT_MAX - 1, 0, USHRT_MAX}},
9155 {{ 1.0f, 0.0f, 0.f}, {USHRT_MAX, 0, 0, USHRT_MAX}},
9157 const UINT exp_vertex_size17 = sizeof(*exp_vertices17);
9158 /* Test 18. Test that the method field is compared by converting a FLOAT2 to
9159 * FLOAT16_2. where the method field has been change from
9160 * D3DDECLMETHOD_DEFAULT to D3DDECLMETHOD_PARTIALU. */
9161 const struct vertex_ptc vertices18[] =
9163 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
9164 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
9165 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
9167 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
9168 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
9169 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
9171 const UINT num_vertices18 = ARRAY_SIZE(vertices18);
9172 const UINT num_faces18 = ARRAY_SIZE(vertices18) / VERTS_PER_FACE;
9173 const UINT vertex_size18 = sizeof(*vertices18);
9174 const struct vertex_ptc_float16_2 exp_vertices18[] =
9176 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
9177 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */
9178 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */
9180 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd}}, /* {0.2f, 0.3f} */
9181 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
9182 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */
9184 const UINT exp_vertex_size18 = sizeof(*exp_vertices18);
9185 /* Test 19. Test that data is lost if usage index changes, e.g. TEXCOORD0
9186 * TEXCOORD1. */
9187 const struct vertex_pntc vertices19[] =
9189 {{ 0.0f, 3.0f, 0.f}, up, { 1.0f, 1.0f}},
9190 {{ 2.0f, 3.0f, 0.f}, up, { 0.5f, 0.7f}},
9191 {{ 0.0f, 0.0f, 0.f}, up, {-0.2f, -0.3f}},
9193 {{ 3.0f, 3.0f, 0.f}, up, { 0.2f, 0.3f}},
9194 {{ 3.0f, 0.0f, 0.f}, up, { 1.0f, 1.0f}},
9195 {{ 1.0f, 0.0f, 0.f}, up, { 0.1f, 0.2f}},
9197 const UINT num_vertices19 = ARRAY_SIZE(vertices19);
9198 const UINT num_faces19 = ARRAY_SIZE(vertices19) / VERTS_PER_FACE;
9199 const UINT vertex_size19 = sizeof(*vertices19);
9200 const struct vertex_pntc exp_vertices19[] =
9202 {{ 0.0f, 3.0f, 0.f}, up, zero_vec2},
9203 {{ 2.0f, 3.0f, 0.f}, up, zero_vec2},
9204 {{ 0.0f, 0.0f, 0.f}, up, zero_vec2},
9206 {{ 3.0f, 3.0f, 0.f}, up, zero_vec2},
9207 {{ 3.0f, 0.0f, 0.f}, up, zero_vec2},
9208 {{ 1.0f, 0.0f, 0.f}, up, zero_vec2},
9210 const UINT exp_vertex_size19 = sizeof(*exp_vertices19);
9211 /* Test 20. Another test that data is lost if usage index changes, e.g.
9212 * TEXCOORD1 to TEXCOORD0. */
9213 const struct vertex_pntc vertices20[] =
9215 {{ 0.0f, 3.0f, 0.f}, up, { 1.0f, 1.0f}},
9216 {{ 2.0f, 3.0f, 0.f}, up, { 0.5f, 0.7f}},
9217 {{ 0.0f, 0.0f, 0.f}, up, {-0.2f, -0.3f}},
9219 {{ 3.0f, 3.0f, 0.f}, up, { 0.2f, 0.3f}},
9220 {{ 3.0f, 0.0f, 0.f}, up, { 1.0f, 1.0f}},
9221 {{ 1.0f, 0.0f, 0.f}, up, { 0.1f, 0.2f}},
9223 const UINT num_vertices20 = ARRAY_SIZE(vertices20);
9224 const UINT num_faces20 = ARRAY_SIZE(vertices20) / VERTS_PER_FACE;
9225 const UINT vertex_size20 = sizeof(*vertices20);
9226 const struct vertex_pntc exp_vertices20[] =
9228 {{ 0.0f, 3.0f, 0.f}, up, zero_vec2},
9229 {{ 2.0f, 3.0f, 0.f}, up, zero_vec2},
9230 {{ 0.0f, 0.0f, 0.f}, up, zero_vec2},
9232 {{ 3.0f, 3.0f, 0.f}, up, zero_vec2},
9233 {{ 3.0f, 0.0f, 0.f}, up, zero_vec2},
9234 {{ 1.0f, 0.0f, 0.f}, up, zero_vec2},
9236 const UINT exp_vertex_size20 = sizeof(*exp_vertices20);
9237 /* Test 21. Convert FLOAT1 to FLOAT2. */
9238 const struct vertex_ptc_float1 vertices21[] =
9240 {{ 0.0f, 3.0f, 0.f}, 1.0f},
9241 {{ 2.0f, 3.0f, 0.f}, 0.5f},
9242 {{ 0.0f, 0.0f, 0.f}, -0.2f},
9244 {{ 3.0f, 3.0f, 0.f}, 0.2f},
9245 {{ 3.0f, 0.0f, 0.f}, 1.0f},
9246 {{ 1.0f, 0.0f, 0.f}, 0.1f},
9248 const UINT num_vertices21 = ARRAY_SIZE(vertices21);
9249 const UINT num_faces21 = ARRAY_SIZE(vertices21) / VERTS_PER_FACE;
9250 const UINT vertex_size21 = sizeof(*vertices21);
9251 const struct vertex_ptc exp_vertices21[] =
9253 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 0.0f}},
9254 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.0f}},
9255 {{ 0.0f, 0.0f, 0.f}, {-0.2f, 0.0f}},
9257 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.0f}},
9258 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 0.0f}},
9259 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.0f}},
9261 const UINT exp_vertex_size21 = sizeof(*exp_vertices21);
9262 /* Test 22. Convert FLOAT1 to FLOAT3. */
9263 const struct vertex_ptc_float1 vertices22[] =
9265 {{ 0.0f, 3.0f, 0.f}, 1.0f},
9266 {{ 2.0f, 3.0f, 0.f}, 0.5f},
9267 {{ 0.0f, 0.0f, 0.f}, -0.2f},
9269 {{ 3.0f, 3.0f, 0.f}, 0.2f},
9270 {{ 3.0f, 0.0f, 0.f}, 1.0f},
9271 {{ 1.0f, 0.0f, 0.f}, 0.1f},
9273 const UINT num_vertices22 = ARRAY_SIZE(vertices22);
9274 const UINT num_faces22 = ARRAY_SIZE(vertices22) / VERTS_PER_FACE;
9275 const UINT vertex_size22 = sizeof(*vertices22);
9276 const struct vertex_ptc_float3 exp_vertices22[] =
9278 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 0.0f, 0.0f}},
9279 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.0f, 0.0f}},
9280 {{ 0.0f, 0.0f, 0.f}, {-0.2f, 0.0f, 0.0f}},
9282 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.0f, 0.0f}},
9283 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 0.0f, 0.0f}},
9284 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.0f, 0.0f}},
9286 const UINT exp_vertex_size22 = sizeof(*exp_vertices22);
9287 /* Test 23. Convert FLOAT1 to FLOAT4. */
9288 const struct vertex_ptc_float1 vertices23[] =
9290 {{ 0.0f, 3.0f, 0.f}, 1.0f},
9291 {{ 2.0f, 3.0f, 0.f}, 0.5f},
9292 {{ 0.0f, 0.0f, 0.f}, -0.2f},
9294 {{ 3.0f, 3.0f, 0.f}, 0.2f},
9295 {{ 3.0f, 0.0f, 0.f}, 1.0f},
9296 {{ 1.0f, 0.0f, 0.f}, 0.1f},
9298 const UINT num_vertices23 = ARRAY_SIZE(vertices23);
9299 const UINT num_faces23 = ARRAY_SIZE(vertices23) / VERTS_PER_FACE;
9300 const UINT vertex_size23 = sizeof(*vertices23);
9301 const struct vertex_ptc_float4 exp_vertices23[] =
9303 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 0.0f, 0.0f, 1.0f}},
9304 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.0f, 0.0f, 1.0f}},
9305 {{ 0.0f, 0.0f, 0.f}, {-0.2f, 0.0f, 0.0f, 1.0f}},
9307 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.0f, 0.0f, 1.0f}},
9308 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 0.0f, 0.0f, 1.0f}},
9309 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.0f, 0.0f, 1.0f}},
9311 const UINT exp_vertex_size23 = sizeof(*exp_vertices23);
9312 /* Test 24. Convert FLOAT1 to D3DCOLOR. */
9313 const struct vertex_ptc_float1 vertices24[] =
9315 {{ 0.0f, 3.0f, 0.f}, 1.0f},
9316 {{ 2.0f, 3.0f, 0.f}, 0.5f},
9317 {{ 0.0f, 0.0f, 0.f}, -0.2f},
9319 {{ 3.0f, 3.0f, 0.f}, 0.2f},
9320 {{ 3.0f, 0.0f, 0.f}, 1.0f},
9321 {{ 1.0f, 0.0f, 0.f}, 0.11f},
9323 const UINT num_vertices24 = ARRAY_SIZE(vertices24);
9324 const UINT num_faces24 = ARRAY_SIZE(vertices24) / VERTS_PER_FACE;
9325 const UINT vertex_size24 = sizeof(*vertices24);
9326 const struct vertex_ptc_d3dcolor exp_vertices24[] =
9328 {{ 0.0f, 3.0f, 0.f}, {0, 0, 255, 255}},
9329 {{ 2.0f, 3.0f, 0.f}, {0, 0, 128, 255}},
9330 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 255}},
9332 {{ 3.0f, 3.0f, 0.f}, {0, 0, 51, 255}},
9333 {{ 3.0f, 0.0f, 0.f}, {0, 0, 255, 255}},
9334 {{ 1.0f, 0.0f, 0.f}, {0, 0, 28, 255}},
9336 const UINT exp_vertex_size24 = sizeof(*exp_vertices24);
9337 /* Test 25. Convert FLOAT1 to ubyte4. */
9338 const struct vertex_ptc_float1 vertices25[] =
9340 {{ 0.0f, 3.0f, 0.f}, 0.0f},
9341 {{ 2.0f, 3.0f, 0.f}, 1.4f},
9342 {{ 0.0f, 0.0f, 0.f}, 1.5f},
9344 {{ 3.0f, 3.0f, 0.f}, 255.0f},
9345 {{ 3.0f, 0.0f, 0.f}, 256.0f},
9346 {{ 1.0f, 0.0f, 0.f}, -1.0f},
9348 const UINT num_vertices25 = ARRAY_SIZE(vertices25);
9349 const UINT num_faces25 = ARRAY_SIZE(vertices25) / VERTS_PER_FACE;
9350 const UINT vertex_size25 = sizeof(*vertices25);
9351 const struct vertex_ptc_ubyte4 exp_vertices25[] =
9353 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 1}},
9354 {{ 2.0f, 3.0f, 0.f}, {1, 0, 0, 1}},
9355 {{ 0.0f, 0.0f, 0.f}, {2, 0, 0, 1}},
9357 {{ 3.0f, 3.0f, 0.f}, {255, 0, 0, 1}},
9358 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 1}},
9359 {{ 1.0f, 0.0f, 0.f}, {0, 0, 0, 1}},
9361 const UINT exp_vertex_size25 = sizeof(*exp_vertices25);
9362 /* Test 26. Convert FLOAT4 to D3DCOLOR. */
9363 const struct vertex_ptc_float4 vertices26[] =
9365 {{ 0.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.4f, 0.5f}},
9366 {{ 2.0f, 3.0f, 0.f}, {-0.4f, -0.5f, -1.0f, -2.0f}},
9367 {{ 0.0f, 0.0f, 0.f}, {254.0f, 255.0f, 256.0f, 257.0f}},
9369 {{ 3.0f, 3.0f, 0.f}, {0.1f, 0.2f, 0.3f, 0.4f}},
9370 {{ 3.0f, 0.0f, 0.f}, {0.5f, 0.6f, 0.7f, 0.8f}},
9371 {{ 1.0f, 0.0f, 0.f}, {0.9f, 0.99f, 0.995f, 0.999f}},
9373 const UINT num_vertices26 = ARRAY_SIZE(vertices26);
9374 const UINT num_faces26 = ARRAY_SIZE(vertices26) / VERTS_PER_FACE;
9375 const UINT vertex_size26 = sizeof(*vertices26);
9376 const struct vertex_ptc_d3dcolor exp_vertices26[] =
9378 {{ 0.0f, 3.0f, 0.f}, {102, 255, 0, 128}},
9379 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9380 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
9382 {{ 3.0f, 3.0f, 0.f}, {77, 51, 26, 102}},
9383 {{ 3.0f, 0.0f, 0.f}, {179, 153, 128, 204}},
9384 {{ 1.0f, 0.0f, 0.f}, {254, 252, 230, 255}},
9386 const UINT exp_vertex_size26 = sizeof(*exp_vertices26);
9387 /* Test 27. Convert D3DCOLOR to FLOAT4. */
9388 const struct vertex_ptc_d3dcolor vertices27[] =
9390 {{ 0.0f, 3.0f, 0.f}, {102, 255, 0, 128}},
9391 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9392 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
9394 {{ 3.0f, 3.0f, 0.f}, {77, 51, 26, 102}},
9395 {{ 3.0f, 0.0f, 0.f}, {179, 153, 128, 204}},
9396 {{ 1.0f, 0.0f, 0.f}, {254, 252, 230, 255}},
9398 const UINT num_vertices27 = ARRAY_SIZE(vertices27);
9399 const UINT num_faces27 = ARRAY_SIZE(vertices27) / VERTS_PER_FACE;
9400 const UINT vertex_size27 = sizeof(*vertices27);
9401 const struct vertex_ptc_float4 exp_vertices27[] =
9403 {{ 0.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.4f, 0.501961f}},
9404 {{ 2.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9405 {{ 0.0f, 0.0f, 0.f}, {1.0f, 1.0f, 1.0f, 1.0f}},
9407 {{ 3.0f, 3.0f, 0.f}, {0.101961f, 0.2f, 0.301961f, 0.4f}},
9408 {{ 3.0f, 0.0f, 0.f}, {0.501961f, 0.6f, 0.701961f, 0.8f}},
9409 {{ 1.0f, 0.0f, 0.f}, {0.901961f, 0.988235f, 0.996078f, 1.0f}},
9411 const UINT exp_vertex_size27 = sizeof(*exp_vertices27);
9412 /* Test 28. Convert UBYTE4 to FLOAT4. */
9413 const struct vertex_ptc_ubyte4 vertices28[] =
9415 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9416 {{ 2.0f, 3.0f, 0.f}, {1, 1, 1, 1}},
9417 {{ 0.0f, 0.0f, 0.f}, {1, 0, 1, 0}},
9419 {{ 3.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
9420 {{ 3.0f, 0.0f, 0.f}, {10, 20, 30, 40}},
9421 {{ 1.0f, 0.0f, 0.f}, {50, 60, 127, 255}},
9423 const UINT num_vertices28 = ARRAY_SIZE(vertices28);
9424 const UINT num_faces28 = ARRAY_SIZE(vertices28) / VERTS_PER_FACE;
9425 const UINT vertex_size28 = sizeof(*vertices28);
9426 const struct vertex_ptc_float4 exp_vertices28[] =
9428 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9429 {{ 2.0f, 3.0f, 0.f}, {1.0f, 1.0f, 1.0f, 1.0f}},
9430 {{ 0.0f, 0.0f, 0.f}, {1.0f, 0.0f, 1.0f, 0.0f}},
9432 {{ 3.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.0f, 1.0f}},
9433 {{ 3.0f, 0.0f, 0.f}, {10.0f, 20.0f, 30.0f, 40.0f}},
9434 {{ 1.0f, 0.0f, 0.f}, {50.0f, 60.0f, 127.0f, 255.0f}},
9436 const UINT exp_vertex_size28 = sizeof(*exp_vertices28);
9437 /* Test 29. Convert SHORT2 to FLOAT4. */
9438 const struct vertex_ptc_short2 vertices29[] =
9440 {{ 0.0f, 3.0f, 0.f}, {0, 0}},
9441 {{ 2.0f, 3.0f, 0.f}, {0, 1}},
9442 {{ 0.0f, 0.0f, 0.f}, {1, 0}},
9444 {{ 3.0f, 3.0f, 0.f}, {1, 1}},
9445 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MAX}},
9446 {{ 1.0f, 0.0f, 0.f}, {-42, 42}},
9448 const UINT num_vertices29 = ARRAY_SIZE(vertices29);
9449 const UINT num_faces29 = ARRAY_SIZE(vertices29) / VERTS_PER_FACE;
9450 const UINT vertex_size29 = sizeof(*vertices29);
9451 const struct vertex_ptc_float4 exp_vertices29[] =
9453 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 1.0f}},
9454 {{ 2.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.0f, 1.0f }},
9455 {{ 0.0f, 0.0f, 0.f}, {1.0f, 0.0f, 0.0f, 1.0f}},
9457 {{ 3.0f, 3.0f, 0.f}, {1.0f, 1.0f, 0.0f, 1.0f}},
9458 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MAX, 0.0f, 1.0f}},
9459 {{ 1.0f, 0.0f, 0.f}, {-42.0f, 42.0f, 0.0f, 1.0f}},
9461 const UINT exp_vertex_size29 = sizeof(*exp_vertices29);
9462 /* Test 29. Convert SHORT4 to FLOAT4. */
9463 const struct vertex_ptc_short4 vertices30[] =
9465 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9466 {{ 2.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
9467 {{ 0.0f, 0.0f, 0.f}, {1, 0, 1, 0}},
9469 {{ 3.0f, 3.0f, 0.f}, {1, 1, 1, 1}},
9470 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MAX, 1, 0}},
9471 {{ 1.0f, 0.0f, 0.f}, {-42, 42, SHRT_MAX, SHRT_MIN}},
9473 const UINT num_vertices30 = ARRAY_SIZE(vertices30);
9474 const UINT num_faces30 = ARRAY_SIZE(vertices30) / VERTS_PER_FACE;
9475 const UINT vertex_size30 = sizeof(*vertices30);
9476 const struct vertex_ptc_float4 exp_vertices30[] =
9478 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9479 {{ 2.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.0f, 1.0f }},
9480 {{ 0.0f, 0.0f, 0.f}, {1.0f, 0.0f, 1.0f, 0.0f}},
9482 {{ 3.0f, 3.0f, 0.f}, {1.0f, 1.0f, 1.0f, 1.0f}},
9483 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MAX, 1.0f, 0.0f}},
9484 {{ 1.0f, 0.0f, 0.f}, {-42.0f, 42.0f, SHRT_MAX, SHRT_MIN}},
9486 const UINT exp_vertex_size30 = sizeof(*exp_vertices30);
9487 /* Test 31. Convert UBYTE4N to FLOAT4. */
9488 const struct vertex_ptc_ubyte4n vertices31[] =
9490 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9491 {{ 2.0f, 3.0f, 0.f}, {1, 1, 1, 1}},
9492 {{ 0.0f, 0.0f, 0.f}, {1, 0, 1, 0}},
9494 {{ 3.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
9495 {{ 3.0f, 0.0f, 0.f}, {10, 20, 30, 40}},
9496 {{ 1.0f, 0.0f, 0.f}, {50, 60, 70, UCHAR_MAX}},
9498 const UINT num_vertices31 = ARRAY_SIZE(vertices31);
9499 const UINT num_faces31 = ARRAY_SIZE(vertices31) / VERTS_PER_FACE;
9500 const UINT vertex_size31 = sizeof(*vertices31);
9501 const struct vertex_ptc_float4 exp_vertices31[] =
9503 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9504 {{ 2.0f, 3.0f, 0.f}, {(FLOAT)1/UCHAR_MAX, (FLOAT)1/UCHAR_MAX, (FLOAT)1/UCHAR_MAX, (FLOAT)1/UCHAR_MAX}},
9505 {{ 0.0f, 0.0f, 0.f}, {(FLOAT)1/UCHAR_MAX, 0.0f, (FLOAT)1/UCHAR_MAX, 0.0f}},
9507 {{ 3.0f, 3.0f, 0.f}, {0.0f, (FLOAT)1/UCHAR_MAX, 0.0f, (FLOAT)1/UCHAR_MAX}},
9508 {{ 3.0f, 0.0f, 0.f}, {(FLOAT)10/UCHAR_MAX, (FLOAT)20/UCHAR_MAX, (FLOAT)30/UCHAR_MAX, (FLOAT)40/UCHAR_MAX}},
9509 {{ 1.0f, 0.0f, 0.f}, {(FLOAT)50/UCHAR_MAX, (FLOAT)60/UCHAR_MAX, (FLOAT)70/UCHAR_MAX, 1.0f}},
9511 const UINT exp_vertex_size31 = sizeof(*exp_vertices31);
9512 /* Test 32. Convert SHORT2N to FLOAT4. */
9513 const struct vertex_ptc_short2 vertices32[] =
9515 {{ 0.0f, 3.0f, 0.f}, {0, 0}},
9516 {{ 2.0f, 3.0f, 0.f}, {0, 1}},
9517 {{ 0.0f, 0.0f, 0.f}, {1, 0}},
9519 {{ 3.0f, 3.0f, 0.f}, {1, 1}},
9520 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN + 1, SHRT_MAX}},
9521 {{ 1.0f, 0.0f, 0.f}, {-42, 42}},
9523 const UINT num_vertices32 = ARRAY_SIZE(vertices32);
9524 const UINT num_faces32 = ARRAY_SIZE(vertices32) / VERTS_PER_FACE;
9525 const UINT vertex_size32 = sizeof(*vertices32);
9526 const struct vertex_ptc_float4 exp_vertices32[] =
9528 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 1.0f}},
9529 {{ 2.0f, 3.0f, 0.f}, {0.0f, 1.0f/SHRT_MAX, 0.0f, 1.0f}},
9530 {{ 0.0f, 0.0f, 0.f}, {1.0f/SHRT_MAX, 0.0f, 0.0f, 1.0f}},
9532 {{ 3.0f, 3.0f, 0.f}, {1.0f/SHRT_MAX, 1.0f/SHRT_MAX, 0.0f, 1.0f}},
9533 {{ 3.0f, 0.0f, 0.f}, {-1.0f, 1.0f, 0.0f, 1.0f}},
9534 {{ 1.0f, 0.0f, 0.f}, {-42.0f/SHRT_MAX, 42.0f/SHRT_MAX, 0.0f, 1.0f}},
9536 const UINT exp_vertex_size32 = sizeof(*exp_vertices32);
9537 /* Test 33. Convert SHORT4N to FLOAT4. */
9538 const struct vertex_ptc_short4 vertices33[] =
9540 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9541 {{ 2.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
9542 {{ 0.0f, 0.0f, 0.f}, {1, 0, 1, 0}},
9544 {{ 3.0f, 3.0f, 0.f}, {1, 1, 1, 1}},
9545 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN + 1, SHRT_MAX, SHRT_MIN + 1, SHRT_MAX}},
9546 {{ 1.0f, 0.0f, 0.f}, {-42, 42, 1, 1}},
9548 const UINT num_vertices33 = ARRAY_SIZE(vertices33);
9549 const UINT num_faces33 = ARRAY_SIZE(vertices33) / VERTS_PER_FACE;
9550 const UINT vertex_size33 = sizeof(*vertices33);
9551 const struct vertex_ptc_float4 exp_vertices33[] =
9553 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9554 {{ 2.0f, 3.0f, 0.f}, {0.0f, 1.0f/SHRT_MAX, 0.0f, 1.0f/SHRT_MAX}},
9555 {{ 0.0f, 0.0f, 0.f}, {1.0f/SHRT_MAX, 0.0f, 1.0f/SHRT_MAX, 0.0f}},
9557 {{ 3.0f, 3.0f, 0.f}, {1.0f/SHRT_MAX, 1.0f/SHRT_MAX, 1.0f/SHRT_MAX, 1.0f/SHRT_MAX}},
9558 {{ 3.0f, 0.0f, 0.f}, {-1.0f, 1.0f, -1.0f, 1.0f}},
9559 {{ 1.0f, 0.0f, 0.f}, {-42.0f/SHRT_MAX, 42.0f/SHRT_MAX, 1.0f/SHRT_MAX, 1.0f/SHRT_MAX}},
9561 const UINT exp_vertex_size33 = sizeof(*exp_vertices33);
9562 /* Test 34. Convert FLOAT16_2 to FLOAT4. */
9563 const struct vertex_ptc_float16_2 vertices34[] =
9565 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
9566 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */
9567 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */
9569 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd}}, /* {0.2f, 0.3f} */
9570 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
9571 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */
9573 const UINT num_vertices34 = ARRAY_SIZE(vertices34);
9574 const UINT num_faces34 = ARRAY_SIZE(vertices34) / VERTS_PER_FACE;
9575 const UINT vertex_size34 = sizeof(*vertices34);
9576 const struct vertex_ptc_float4 exp_vertices34[] =
9578 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f, 0.0f, 1.0f}},
9579 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.700195f, 0.0f, 1.0f}},
9580 {{ 0.0f, 0.0f, 0.f}, {-0.199951f, -0.300049f, 0.0f, 1.0f}},
9582 {{ 3.0f, 3.0f, 0.f}, {0.199951f, 0.300049f, 0.0f, 1.0f}},
9583 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f, 0.0f, 1.0f}},
9584 {{ 1.0f, 0.0f, 0.f}, {0.099976f, 0.199951f, 0.0f, 1.0f}},
9586 const UINT exp_vertex_size34 = sizeof(*exp_vertices34);
9587 /* Test 35. Convert FLOAT16_4 to FLOAT4. */
9588 const struct vertex_ptc_float16_4 vertices35[] =
9590 {{ 0.0f, 3.0f, 0.f}, {0x0000, 0x0000, 0x0000, 0x0000}},
9591 {{ 2.0f, 3.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}},
9592 {{ 0.0f, 0.0f, 0.f}, {0x3c00, 0x0000, 0x3c00, 0x0000}},
9594 {{ 3.0f, 3.0f, 0.f}, {0x0000, 0x3c00, 0x0000, 0x3c00}},
9595 {{ 3.0f, 0.0f, 0.f}, {0x3800, 0x399a, 0xb266, 0xb4cd}},
9596 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266, 0x2e66, 0x3266}},
9598 const UINT num_vertices35 = ARRAY_SIZE(vertices35);
9599 const UINT num_faces35 = ARRAY_SIZE(vertices35) / VERTS_PER_FACE;
9600 const UINT vertex_size35 = sizeof(*vertices35);
9601 const struct vertex_ptc_float4 exp_vertices35[] =
9603 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9604 {{ 2.0f, 3.0f, 0.f}, {1.0f, 1.0f, 1.0f, 1.0f}},
9605 {{ 0.0f, 0.0f, 0.f}, {1.0f, 0.0f, 1.0f, 0.0f}},
9607 {{ 3.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.0f, 1.0f}},
9608 {{ 3.0f, 0.0f, 0.f}, {0.5f, 0.700195f, -0.199951f, -0.300049f}},
9609 {{ 1.0f, 0.0f, 0.f}, {0.099976f, 0.199951f, 0.099976f, 0.199951f}},
9611 const UINT exp_vertex_size35 = sizeof(*exp_vertices35);
9612 /* Test 36. Check that vertex buffer sharing is ok. */
9613 const struct vertex_pn vertices36[] =
9615 {{ 0.0f, 3.0f, 0.f}, up},
9616 {{ 2.0f, 3.0f, 0.f}, up},
9617 {{ 0.0f, 0.0f, 0.f}, up},
9619 const UINT num_vertices36 = ARRAY_SIZE(vertices36);
9620 const UINT num_faces36 = ARRAY_SIZE(vertices36) / VERTS_PER_FACE;
9621 const UINT vertex_size36 = sizeof(*vertices36);
9622 const DWORD clone_options36 = options | D3DXMESH_VB_SHARE;
9623 /* Common mesh data */
9624 ID3DXMesh *mesh = NULL;
9625 ID3DXMesh *mesh_clone = NULL;
9626 struct
9628 const BYTE *vertices;
9629 const DWORD *indices;
9630 const DWORD *attributes;
9631 const UINT num_vertices;
9632 const UINT num_faces;
9633 const UINT vertex_size;
9634 const DWORD create_options;
9635 const DWORD clone_options;
9636 D3DVERTEXELEMENT9 *declaration;
9637 D3DVERTEXELEMENT9 *new_declaration;
9638 const BYTE *exp_vertices;
9639 const UINT exp_vertex_size;
9641 tc[] =
9644 (BYTE*)vertices0,
9645 NULL,
9646 NULL,
9647 num_vertices0,
9648 num_faces0,
9649 vertex_size0,
9650 options,
9651 options,
9652 declaration_pn,
9653 declaration_pn,
9654 (BYTE*)vertices0,
9655 vertex_size0
9658 (BYTE*)vertices0,
9659 NULL,
9660 NULL,
9661 num_vertices0,
9662 num_faces0,
9663 vertex_size0,
9664 options_16bit,
9665 options_16bit,
9666 declaration_pn,
9667 declaration_pn,
9668 (BYTE*)vertices0,
9669 vertex_size0
9672 (BYTE*)vertices0,
9673 NULL,
9674 NULL,
9675 num_vertices0,
9676 num_faces0,
9677 vertex_size0,
9678 options,
9679 options,
9680 declaration_pn,
9681 declaration_pntc,
9682 (BYTE*)exp_vertices2,
9683 exp_vertex_size2
9686 (BYTE*)vertices0,
9687 NULL,
9688 NULL,
9689 num_vertices0,
9690 num_faces0,
9691 vertex_size0,
9692 options,
9693 options,
9694 declaration_pn,
9695 declaration_ptcn,
9696 (BYTE*)exp_vertices3,
9697 exp_vertex_size3
9700 (BYTE*)vertices4,
9701 NULL,
9702 NULL,
9703 num_vertices4,
9704 num_faces4,
9705 vertex_size4,
9706 options,
9707 options,
9708 declaration_ptc,
9709 declaration_ptc_float16_2,
9710 (BYTE*)exp_vertices4,
9711 exp_vertex_size4
9714 (BYTE*)vertices5,
9715 NULL,
9716 NULL,
9717 num_vertices5,
9718 num_faces5,
9719 vertex_size5,
9720 options,
9721 options,
9722 declaration_ptc,
9723 declaration_ptc_float16_4,
9724 (BYTE*)exp_vertices5,
9725 exp_vertex_size5
9728 (BYTE*)vertices6,
9729 NULL,
9730 NULL,
9731 num_vertices6,
9732 num_faces6,
9733 vertex_size6,
9734 options,
9735 options,
9736 declaration_ptc,
9737 declaration_ptc_float1,
9738 (BYTE*)exp_vertices6,
9739 exp_vertex_size6
9742 (BYTE*)vertices7,
9743 NULL,
9744 NULL,
9745 num_vertices7,
9746 num_faces7,
9747 vertex_size7,
9748 options,
9749 options,
9750 declaration_ptc,
9751 declaration_ptc_float3,
9752 (BYTE*)exp_vertices7,
9753 exp_vertex_size7
9756 (BYTE*)vertices8,
9757 NULL,
9758 NULL,
9759 num_vertices8,
9760 num_faces8,
9761 vertex_size8,
9762 options,
9763 options,
9764 declaration_ptc,
9765 declaration_ptc_float4,
9766 (BYTE*)exp_vertices8,
9767 exp_vertex_size8
9770 (BYTE*)vertices9,
9771 NULL,
9772 NULL,
9773 num_vertices9,
9774 num_faces9,
9775 vertex_size9,
9776 options,
9777 options,
9778 declaration_ptc,
9779 declaration_ptc_d3dcolor,
9780 (BYTE*)exp_vertices9,
9781 exp_vertex_size9
9784 (BYTE*)vertices10,
9785 NULL,
9786 NULL,
9787 num_vertices10,
9788 num_faces10,
9789 vertex_size10,
9790 options,
9791 options,
9792 declaration_ptc,
9793 declaration_ptc_ubyte4,
9794 (BYTE*)exp_vertices10,
9795 exp_vertex_size10
9798 (BYTE*)vertices11,
9799 NULL,
9800 NULL,
9801 num_vertices11,
9802 num_faces11,
9803 vertex_size11,
9804 options,
9805 options,
9806 declaration_ptc,
9807 declaration_ptc_short2,
9808 (BYTE*)exp_vertices11,
9809 exp_vertex_size11
9812 (BYTE*)vertices12,
9813 NULL,
9814 NULL,
9815 num_vertices12,
9816 num_faces12,
9817 vertex_size12,
9818 options,
9819 options,
9820 declaration_ptc,
9821 declaration_ptc_short4,
9822 (BYTE*)exp_vertices12,
9823 exp_vertex_size12
9826 (BYTE*)vertices13,
9827 NULL,
9828 NULL,
9829 num_vertices13,
9830 num_faces13,
9831 vertex_size13,
9832 options,
9833 options,
9834 declaration_ptc,
9835 declaration_ptc_ubyte4n,
9836 (BYTE*)exp_vertices13,
9837 exp_vertex_size13
9840 (BYTE*)vertices14,
9841 NULL,
9842 NULL,
9843 num_vertices14,
9844 num_faces14,
9845 vertex_size14,
9846 options,
9847 options,
9848 declaration_ptc,
9849 declaration_ptc_short2n,
9850 (BYTE*)exp_vertices14,
9851 exp_vertex_size14
9854 (BYTE*)vertices15,
9855 NULL,
9856 NULL,
9857 num_vertices15,
9858 num_faces15,
9859 vertex_size15,
9860 options,
9861 options,
9862 declaration_ptc,
9863 declaration_ptc_short4n,
9864 (BYTE*)exp_vertices15,
9865 exp_vertex_size15
9868 (BYTE*)vertices16,
9869 NULL,
9870 NULL,
9871 num_vertices16,
9872 num_faces16,
9873 vertex_size16,
9874 options,
9875 options,
9876 declaration_ptc,
9877 declaration_ptc_ushort2n,
9878 (BYTE*)exp_vertices16,
9879 exp_vertex_size16
9882 (BYTE*)vertices17,
9883 NULL,
9884 NULL,
9885 num_vertices17,
9886 num_faces17,
9887 vertex_size17,
9888 options,
9889 options,
9890 declaration_ptc,
9891 declaration_ptc_ushort4n,
9892 (BYTE*)exp_vertices17,
9893 exp_vertex_size17
9896 (BYTE*)vertices18,
9897 NULL,
9898 NULL,
9899 num_vertices18,
9900 num_faces18,
9901 vertex_size18,
9902 options,
9903 options,
9904 declaration_ptc,
9905 declaration_ptc_float16_2_partialu,
9906 (BYTE*)exp_vertices18,
9907 exp_vertex_size18
9910 (BYTE*)vertices19,
9911 NULL,
9912 NULL,
9913 num_vertices19,
9914 num_faces19,
9915 vertex_size19,
9916 options,
9917 options,
9918 declaration_pntc,
9919 declaration_pntc1,
9920 (BYTE*)exp_vertices19,
9921 exp_vertex_size19
9924 (BYTE*)vertices20,
9925 NULL,
9926 NULL,
9927 num_vertices20,
9928 num_faces20,
9929 vertex_size20,
9930 options,
9931 options,
9932 declaration_pntc1,
9933 declaration_pntc,
9934 (BYTE*)exp_vertices20,
9935 exp_vertex_size20
9938 (BYTE*)vertices21,
9939 NULL,
9940 NULL,
9941 num_vertices21,
9942 num_faces21,
9943 vertex_size21,
9944 options,
9945 options,
9946 declaration_ptc_float1,
9947 declaration_ptc,
9948 (BYTE*)exp_vertices21,
9949 exp_vertex_size21
9952 (BYTE*)vertices22,
9953 NULL,
9954 NULL,
9955 num_vertices22,
9956 num_faces22,
9957 vertex_size22,
9958 options,
9959 options,
9960 declaration_ptc_float1,
9961 declaration_ptc_float3,
9962 (BYTE*)exp_vertices22,
9963 exp_vertex_size22
9966 (BYTE*)vertices23,
9967 NULL,
9968 NULL,
9969 num_vertices23,
9970 num_faces23,
9971 vertex_size23,
9972 options,
9973 options,
9974 declaration_ptc_float1,
9975 declaration_ptc_float4,
9976 (BYTE*)exp_vertices23,
9977 exp_vertex_size23
9980 (BYTE*)vertices24,
9981 NULL,
9982 NULL,
9983 num_vertices24,
9984 num_faces24,
9985 vertex_size24,
9986 options,
9987 options,
9988 declaration_ptc_float1,
9989 declaration_ptc_d3dcolor,
9990 (BYTE*)exp_vertices24,
9991 exp_vertex_size24
9994 (BYTE*)vertices25,
9995 NULL,
9996 NULL,
9997 num_vertices25,
9998 num_faces25,
9999 vertex_size25,
10000 options,
10001 options,
10002 declaration_ptc_float1,
10003 declaration_ptc_ubyte4,
10004 (BYTE*)exp_vertices25,
10005 exp_vertex_size25
10008 (BYTE*)vertices26,
10009 NULL,
10010 NULL,
10011 num_vertices26,
10012 num_faces26,
10013 vertex_size26,
10014 options,
10015 options,
10016 declaration_ptc_float4,
10017 declaration_ptc_d3dcolor,
10018 (BYTE*)exp_vertices26,
10019 exp_vertex_size26
10022 (BYTE*)vertices27,
10023 NULL,
10024 NULL,
10025 num_vertices27,
10026 num_faces27,
10027 vertex_size27,
10028 options,
10029 options,
10030 declaration_ptc_d3dcolor,
10031 declaration_ptc_float4,
10032 (BYTE*)exp_vertices27,
10033 exp_vertex_size27
10036 (BYTE*)vertices28,
10037 NULL,
10038 NULL,
10039 num_vertices28,
10040 num_faces28,
10041 vertex_size28,
10042 options,
10043 options,
10044 declaration_ptc_ubyte4,
10045 declaration_ptc_float4,
10046 (BYTE*)exp_vertices28,
10047 exp_vertex_size28
10050 (BYTE*)vertices29,
10051 NULL,
10052 NULL,
10053 num_vertices29,
10054 num_faces29,
10055 vertex_size29,
10056 options,
10057 options,
10058 declaration_ptc_short2,
10059 declaration_ptc_float4,
10060 (BYTE*)exp_vertices29,
10061 exp_vertex_size29
10064 (BYTE*)vertices30,
10065 NULL,
10066 NULL,
10067 num_vertices30,
10068 num_faces30,
10069 vertex_size30,
10070 options,
10071 options,
10072 declaration_ptc_short4,
10073 declaration_ptc_float4,
10074 (BYTE*)exp_vertices30,
10075 exp_vertex_size30
10078 (BYTE*)vertices31,
10079 NULL,
10080 NULL,
10081 num_vertices31,
10082 num_faces31,
10083 vertex_size31,
10084 options,
10085 options,
10086 declaration_ptc_ubyte4n,
10087 declaration_ptc_float4,
10088 (BYTE*)exp_vertices31,
10089 exp_vertex_size31
10092 (BYTE*)vertices32,
10093 NULL,
10094 NULL,
10095 num_vertices32,
10096 num_faces32,
10097 vertex_size32,
10098 options,
10099 options,
10100 declaration_ptc_short2n,
10101 declaration_ptc_float4,
10102 (BYTE*)exp_vertices32,
10103 exp_vertex_size32
10106 (BYTE*)vertices33,
10107 NULL,
10108 NULL,
10109 num_vertices33,
10110 num_faces33,
10111 vertex_size33,
10112 options,
10113 options,
10114 declaration_ptc_short4n,
10115 declaration_ptc_float4,
10116 (BYTE*)exp_vertices33,
10117 exp_vertex_size33
10120 (BYTE*)vertices34,
10121 NULL,
10122 NULL,
10123 num_vertices34,
10124 num_faces34,
10125 vertex_size34,
10126 options,
10127 options,
10128 declaration_ptc_float16_2,
10129 declaration_ptc_float4,
10130 (BYTE*)exp_vertices34,
10131 exp_vertex_size34
10134 (BYTE*)vertices35,
10135 NULL,
10136 NULL,
10137 num_vertices35,
10138 num_faces35,
10139 vertex_size35,
10140 options,
10141 options,
10142 declaration_ptc_float16_4,
10143 declaration_ptc_float4,
10144 (BYTE*)exp_vertices35,
10145 exp_vertex_size35
10148 (BYTE*)vertices36,
10149 NULL,
10150 NULL,
10151 num_vertices36,
10152 num_faces36,
10153 vertex_size36,
10154 options,
10155 clone_options36,
10156 declaration_pn,
10157 declaration_pn,
10158 (BYTE*)vertices36,
10159 vertex_size36
10163 test_context = new_test_context();
10164 if (!test_context)
10166 skip("Couldn't create test context\n");
10167 goto cleanup;
10170 for (i = 0; i < ARRAY_SIZE(tc); i++)
10172 UINT j;
10173 D3DVERTEXELEMENT9 new_declaration[MAX_FVF_DECL_SIZE];
10174 UINT exp_new_decl_length, new_decl_length;
10175 UINT exp_new_decl_size, new_decl_size;
10177 hr = init_test_mesh(tc[i].num_faces, tc[i].num_vertices,
10178 tc[i].create_options,
10179 tc[i].declaration,
10180 test_context->device, &mesh,
10181 tc[i].vertices, tc[i].vertex_size,
10182 tc[i].indices, tc[i].attributes);
10183 if (FAILED(hr))
10185 skip("Couldn't initialize test mesh %d. Got %x expected D3D_OK\n", i, hr);
10186 goto cleanup;
10189 hr = mesh->lpVtbl->CloneMesh(mesh, tc[i].clone_options, tc[i].new_declaration,
10190 test_context->device, &mesh_clone);
10191 ok(hr == D3D_OK, "Test %u, got unexpected hr %#x.\n", i, hr);
10193 hr = mesh_clone->lpVtbl->GetDeclaration(mesh_clone, new_declaration);
10194 ok(hr == D3D_OK, "Test %u, got unexpected hr %#x.\n", i, hr);
10195 /* Check declaration elements */
10196 for (j = 0; tc[i].new_declaration[j].Stream != 0xFF; j++)
10198 ok(memcmp(&tc[i].new_declaration[j], &new_declaration[j], sizeof(*new_declaration)) == 0,
10199 "Test case %d failed. Declaration element %d did not match.\n", i, j);
10202 /* Check declaration length */
10203 exp_new_decl_length = D3DXGetDeclLength(tc[i].new_declaration);
10204 new_decl_length = D3DXGetDeclLength(new_declaration);
10205 ok(new_decl_length == exp_new_decl_length,
10206 "Test case %d failed. Got new declaration length %d, expected %d\n",
10207 i, new_decl_length, exp_new_decl_length);
10209 /* Check declaration size */
10210 exp_new_decl_size = D3DXGetDeclVertexSize(tc[i].new_declaration, 0);
10211 new_decl_size = D3DXGetDeclVertexSize(new_declaration, 0);
10212 ok(new_decl_size == exp_new_decl_size,
10213 "Test case %d failed. Got new declaration size %d, expected %d\n",
10214 i, new_decl_size, exp_new_decl_size);
10216 /* Check vertex data in cloned mesh */
10217 hr = mesh_clone->lpVtbl->LockVertexBuffer(mesh_clone, 0, (void**)&vertices);
10218 if (FAILED(hr))
10220 skip("Couldn't lock cloned vertex buffer.\n");
10221 goto cleanup;
10223 for (j = 0; j < tc[i].num_vertices; j++)
10225 UINT index = tc[i].exp_vertex_size * j;
10226 check_vertex_components(__LINE__, i, j, &vertices[index], &tc[i].exp_vertices[index], tc[i].new_declaration);
10228 hr = mesh_clone->lpVtbl->UnlockVertexBuffer(mesh_clone);
10229 if (FAILED(hr))
10231 skip("Couldn't unlock vertex buffer.\n");
10232 goto cleanup;
10234 vertices = NULL;
10235 mesh->lpVtbl->Release(mesh);
10236 mesh = NULL;
10237 mesh_clone->lpVtbl->Release(mesh_clone);
10238 mesh_clone = NULL;
10241 /* The following test shows that it is not possible to share a vertex buffer
10242 * with D3DXMESH_VB_SHARE and change the vertex declaration at the same
10243 * time. It reuses the test data from test 2.
10245 hr = init_test_mesh(tc[2].num_faces, tc[2].num_vertices,
10246 tc[2].create_options,
10247 tc[2].declaration,
10248 test_context->device, &mesh,
10249 tc[2].vertices, tc[2].vertex_size,
10250 tc[2].indices, tc[2].attributes);
10251 if (FAILED(hr))
10253 skip("Couldn't initialize test mesh for D3DXMESH_VB_SHARE case."
10254 " Got %x expected D3D_OK\n", hr);
10255 goto cleanup;
10258 hr = mesh->lpVtbl->CloneMesh(mesh, tc[2].create_options | D3DXMESH_VB_SHARE,
10259 tc[2].new_declaration, test_context->device,
10260 &mesh_clone);
10261 ok(hr == D3DERR_INVALIDCALL, "CloneMesh D3DXMESH_VB_SHARE with new"
10262 " declaration. Got %x, expected D3DERR_INVALIDCALL\n",
10263 hr);
10264 mesh->lpVtbl->Release(mesh);
10265 mesh = NULL;
10266 mesh_clone = NULL;
10268 cleanup:
10269 if (vertices) mesh->lpVtbl->UnlockVertexBuffer(mesh);
10270 if (mesh) mesh->lpVtbl->Release(mesh);
10271 if (mesh_clone) mesh_clone->lpVtbl->Release(mesh_clone);
10272 free_test_context(test_context);
10275 static void test_valid_mesh(void)
10277 HRESULT hr;
10278 struct test_context *test_context = NULL;
10279 UINT i;
10280 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
10281 const D3DVERTEXELEMENT9 declaration[] =
10283 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
10284 D3DDECL_END()
10286 const unsigned int VERTS_PER_FACE = 3;
10287 /* mesh0 (one face)
10289 * 0--1
10290 * | /
10291 * |/
10294 const D3DXVECTOR3 vertices0[] =
10296 { 0.0f, 3.0f, 0.f},
10297 { 2.0f, 3.0f, 0.f},
10298 { 0.0f, 0.0f, 0.f},
10300 const DWORD indices0[] = {0, 1, 2};
10301 const unsigned int num_vertices0 = ARRAY_SIZE(vertices0);
10302 const unsigned int num_faces0 = ARRAY_SIZE(indices0) / VERTS_PER_FACE;
10303 const DWORD adjacency0[] = {-1, -1, -1};
10304 const HRESULT exp_hr0 = D3D_OK;
10305 /* mesh1 (Simple bow-tie)
10307 * 0--1 1--3
10308 * | / \ |
10309 * |/ \|
10310 * 2 4
10312 const D3DXVECTOR3 vertices1[] =
10314 { 0.0f, 3.0f, 0.f},
10315 { 2.0f, 3.0f, 0.f},
10316 { 0.0f, 0.0f, 0.f},
10318 { 4.0f, 3.0f, 0.f},
10319 { 4.0f, 0.0f, 0.f},
10321 const DWORD indices1[] = {0, 1, 2, 1, 3, 4};
10322 const unsigned int num_vertices1 = ARRAY_SIZE(vertices1);
10323 const unsigned int num_faces1 = ARRAY_SIZE(indices1) / VERTS_PER_FACE;
10324 const DWORD adjacency1[] = {-1, -1, -1, -1, -1, -1};
10325 const HRESULT exp_hr1 = D3DXERR_INVALIDMESH;
10326 /* Common mesh data */
10327 ID3DXMesh *mesh = NULL;
10328 UINT vertex_size = sizeof(D3DXVECTOR3);
10329 ID3DXBuffer *errors_and_warnings = NULL;
10330 struct
10332 const D3DXVECTOR3 *vertices;
10333 const DWORD *indices;
10334 const UINT num_vertices;
10335 const UINT num_faces;
10336 const DWORD *adjacency;
10337 const HRESULT exp_hr;
10339 tc[] =
10342 vertices0,
10343 indices0,
10344 num_vertices0,
10345 num_faces0,
10346 adjacency0,
10347 exp_hr0,
10350 vertices1,
10351 indices1,
10352 num_vertices1,
10353 num_faces1,
10354 adjacency1,
10355 exp_hr1,
10359 test_context = new_test_context();
10360 if (!test_context)
10362 skip("Couldn't create test context\n");
10363 goto cleanup;
10366 for (i = 0; i < ARRAY_SIZE(tc); i++)
10368 hr = init_test_mesh(tc[i].num_faces, tc[i].num_vertices,
10369 options, declaration,
10370 test_context->device, &mesh,
10371 tc[i].vertices, vertex_size,
10372 tc[i].indices, NULL);
10373 if (FAILED(hr))
10375 skip("Couldn't initialize test mesh %d. Got %x expected D3D_OK\n", i, hr);
10376 goto cleanup;
10379 hr = D3DXValidMesh(mesh, tc[i].adjacency, &errors_and_warnings);
10380 todo_wine ok(hr == tc[i].exp_hr, "Test %u, got unexpected hr %#x, expected %#x.\n", i, hr, tc[i].exp_hr);
10382 /* Note errors_and_warnings is deliberately not checked because that
10383 * would require copying wast amounts of the text output. */
10384 if (errors_and_warnings)
10386 ID3DXBuffer_Release(errors_and_warnings);
10387 errors_and_warnings = NULL;
10389 mesh->lpVtbl->Release(mesh);
10390 mesh = NULL;
10393 cleanup:
10394 if (mesh) mesh->lpVtbl->Release(mesh);
10395 free_test_context(test_context);
10398 static void test_optimize_faces(void)
10400 HRESULT hr;
10401 UINT i;
10402 DWORD smallest_face_remap;
10403 /* mesh0
10405 * 0--1
10406 * | /
10407 * |/
10410 const DWORD indices0[] = {0, 1, 2};
10411 const UINT num_faces0 = 1;
10412 const UINT num_vertices0 = 3;
10413 const DWORD exp_face_remap0[] = {0};
10414 /* mesh1
10416 * 0--1 3
10417 * | / /|
10418 * |/ / |
10419 * 2 5--4
10421 const DWORD indices1[] = {0, 1, 2, 3, 4, 5};
10422 const UINT num_faces1 = 2;
10423 const UINT num_vertices1 = 6;
10424 const DWORD exp_face_remap1[] = {1, 0};
10425 /* mesh2
10427 * 0--1
10428 * | /|
10429 * |/ |
10430 * 2--3
10432 const DWORD indices2[] = {0, 1, 2, 1, 3, 2};
10433 const UINT num_faces2 = 2;
10434 const UINT num_vertices2 = 4;
10435 const DWORD exp_face_remap2[] = {1, 0};
10436 /* mesh3
10438 * 0--1
10439 * | /|
10440 * |/ |
10441 * 2--3
10442 * | /|
10443 * |/ |
10444 * 4--5
10446 const DWORD indices3[] = {0, 1, 2, 1, 3, 2, 2, 3, 4, 3, 4, 5};
10447 const UINT num_faces3 = 4;
10448 const UINT num_vertices3 = 6;
10449 const DWORD exp_face_remap3[] = {3, 2, 1, 0};
10450 /* mesh4
10452 * 0--1
10453 * | /|
10454 * |/ |
10455 * 2--3
10456 * | /|
10457 * |/ |
10458 * 4--5
10460 const WORD indices4[] = {0, 1, 2, 1, 3, 2, 2, 3, 4, 3, 4, 5};
10461 const UINT num_faces4 = 4;
10462 const UINT num_vertices4 = 6;
10463 const DWORD exp_face_remap4[] = {3, 2, 1, 0};
10464 /* Test cases are stored in the tc array */
10465 struct
10467 const VOID *indices;
10468 const UINT num_faces;
10469 const UINT num_vertices;
10470 const BOOL indices_are_32bit;
10471 const DWORD *exp_face_remap;
10473 tc[] =
10476 indices0,
10477 num_faces0,
10478 num_vertices0,
10479 TRUE,
10480 exp_face_remap0
10483 indices1,
10484 num_faces1,
10485 num_vertices1,
10486 TRUE,
10487 exp_face_remap1
10490 indices2,
10491 num_faces2,
10492 num_vertices2,
10493 TRUE,
10494 exp_face_remap2
10497 indices3,
10498 num_faces3,
10499 num_vertices3,
10500 TRUE,
10501 exp_face_remap3
10504 indices4,
10505 num_faces4,
10506 num_vertices4,
10507 FALSE,
10508 exp_face_remap4
10512 /* Go through all test cases */
10513 for (i = 0; i < ARRAY_SIZE(tc); i++)
10515 DWORD j;
10516 DWORD *face_remap;
10517 face_remap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
10518 tc[i].num_faces*sizeof(*face_remap));
10520 hr = D3DXOptimizeFaces(tc[i].indices, tc[i].num_faces,
10521 tc[i].num_vertices, tc[i].indices_are_32bit,
10522 face_remap);
10523 ok(hr == D3D_OK, "Test %u, got unexpected hr %#x.\n", i, hr);
10525 /* Compare face remap with expected face remap */
10526 for (j = 0; j < tc[i].num_faces; j++)
10528 ok(tc[i].exp_face_remap[j] == face_remap[j],
10529 "Test case %d: Got face %d at %d, expected %d\n", i,
10530 face_remap[j], j, tc[i].exp_face_remap[j]);
10533 HeapFree(GetProcessHeap(), 0, face_remap);
10536 /* face_remap must not be NULL */
10537 hr = D3DXOptimizeFaces(tc[0].indices, tc[0].num_faces,
10538 tc[0].num_vertices, tc[0].indices_are_32bit,
10539 NULL);
10540 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
10542 /* Number of faces must be smaller than 2^15 */
10543 hr = D3DXOptimizeFaces(tc[0].indices, 2 << 15,
10544 tc[0].num_vertices, FALSE,
10545 &smallest_face_remap);
10546 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
10549 static HRESULT clear_normals(ID3DXMesh *mesh)
10551 HRESULT hr;
10552 BYTE *vertices;
10553 size_t normal_size;
10554 DWORD i, num_vertices, vertex_stride;
10555 const D3DXVECTOR4 normal = {NAN, NAN, NAN, NAN};
10556 D3DVERTEXELEMENT9 *normal_declaration = NULL;
10557 D3DVERTEXELEMENT9 declaration[MAX_FVF_DECL_SIZE] = {D3DDECL_END()};
10559 if (FAILED(hr = mesh->lpVtbl->GetDeclaration(mesh, declaration)))
10560 return hr;
10562 for (i = 0; declaration[i].Stream != 0xff; i++)
10564 if (declaration[i].Usage == D3DDECLUSAGE_NORMAL && !declaration[i].UsageIndex)
10566 normal_declaration = &declaration[i];
10567 break;
10571 if (!normal_declaration)
10572 return D3DERR_INVALIDCALL;
10574 if (normal_declaration->Type == D3DDECLTYPE_FLOAT3)
10576 normal_size = sizeof(D3DXVECTOR3);
10578 else if (normal_declaration->Type == D3DDECLTYPE_FLOAT4)
10580 normal_size = sizeof(D3DXVECTOR4);
10582 else
10584 trace("Cannot clear normals\n");
10585 return E_NOTIMPL;
10588 num_vertices = mesh->lpVtbl->GetNumVertices(mesh);
10589 vertex_stride = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
10591 if (FAILED(hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, (void **)&vertices)))
10592 return hr;
10594 vertices += normal_declaration->Offset;
10596 for (i = 0; i < num_vertices; i++, vertices += vertex_stride)
10597 memcpy(vertices, &normal, normal_size);
10599 return mesh->lpVtbl->UnlockVertexBuffer(mesh);
10602 static void compare_normals(unsigned int line, const char *test_name,
10603 ID3DXMesh *mesh, const D3DXVECTOR3 *normals, unsigned int num_normals)
10605 unsigned int i;
10606 BYTE *vertices;
10607 DWORD num_vertices, vertex_stride;
10608 D3DVERTEXELEMENT9 *normal_declaration = NULL;
10609 D3DVERTEXELEMENT9 declaration[MAX_FVF_DECL_SIZE] = {D3DDECL_END()};
10611 if (FAILED(mesh->lpVtbl->GetDeclaration(mesh, declaration)))
10613 ok_(__FILE__, line)(0, "%s: Failed to get declaration\n", test_name);
10614 return;
10617 for (i = 0; declaration[i].Stream != 0xff; i++)
10619 if (declaration[i].Usage == D3DDECLUSAGE_NORMAL && !declaration[i].UsageIndex)
10621 normal_declaration = &declaration[i];
10622 break;
10626 if (!normal_declaration)
10628 ok_(__FILE__, line)(0, "%s: Mesh has no normals\n", test_name);
10629 return;
10632 if (normal_declaration->Type != D3DDECLTYPE_FLOAT3 && normal_declaration->Type != D3DDECLTYPE_FLOAT4)
10634 ok_(__FILE__, line)(0, "%s: Mesh has invalid normals type\n", test_name);
10635 return;
10638 num_vertices = mesh->lpVtbl->GetNumVertices(mesh);
10639 vertex_stride = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
10641 ok_(__FILE__, line)(num_vertices == num_normals, "%s: Expected %u vertices, got %u\n", test_name,
10642 num_normals, num_vertices);
10644 if (FAILED(mesh->lpVtbl->LockVertexBuffer(mesh, 0, (void **)&vertices)))
10646 ok_(__FILE__, line)(0, "%s: Failed to compare normals\n", test_name);
10647 return;
10650 vertices += normal_declaration->Offset;
10652 for (i = 0; i < min(num_vertices, num_normals); i++, vertices += vertex_stride)
10654 if (normal_declaration->Type == D3DDECLTYPE_FLOAT3)
10656 const D3DXVECTOR3 *n = (D3DXVECTOR3 *)vertices;
10657 ok_(__FILE__, line)(compare_vec3(*n, normals[i]),
10658 "%s: normal %2u, expected (%f, %f, %f), got (%f, %f, %f)\n",
10659 test_name, i, normals[i].x, normals[i].y, normals[i].z, n->x, n->y, n->z);
10661 else
10663 const D3DXVECTOR4 *n = (D3DXVECTOR4 *)vertices;
10664 const D3DXVECTOR4 normal = {normals[i].x, normals[i].y, normals[i].z, 1.0f};
10665 ok_(__FILE__, line)(compare_vec4(*n, normal),
10666 "%s: normal %2u, expected (%f, %f, %f, %f), got (%f, %f, %f, %f)\n",
10667 test_name, i, normals[i].x, normals[i].y, normals[i].z, 1.0f,
10668 n->x, n->y, n->z, n->w);
10672 mesh->lpVtbl->UnlockVertexBuffer(mesh);
10675 static HRESULT compute_normals_D3DXComputeNormals(ID3DXMesh *mesh, const DWORD *adjacency)
10677 return D3DXComputeNormals((ID3DXBaseMesh *)mesh, adjacency);
10680 static HRESULT compute_normals_D3DXComputeTangentFrameEx(ID3DXMesh *mesh, const DWORD *adjacency)
10682 return D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
10683 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS,
10684 adjacency, -1.01f, -0.01f, -1.01f, NULL, NULL);
10687 static void test_compute_normals(void)
10689 HRESULT hr;
10690 ULONG refcount;
10691 ID3DXMesh *mesh, *cloned_mesh;
10692 ID3DXBuffer *adjacency;
10693 IDirect3DDevice9 *device;
10694 struct test_context *test_context;
10695 unsigned int i;
10697 static const struct compute_normals_func
10699 const char *name;
10700 HRESULT (*apply)(ID3DXMesh *mesh, const DWORD *adjacency);
10702 compute_normals_funcs[] =
10704 {"D3DXComputeNormals", compute_normals_D3DXComputeNormals },
10705 {"D3DXComputeTangentFrameEx", compute_normals_D3DXComputeTangentFrameEx}
10708 static const D3DXVECTOR3 box_normals[24] =
10710 {-1.0f, 0.0f, 0.0f}, {-1.0f, 0.0f, 0.0f}, {-1.0f, 0.0f, 0.0f}, {-1.0f, 0.0f, 0.0f},
10711 { 0.0f, 1.0f, 0.0f}, { 0.0f, 1.0f, 0.0f}, { 0.0f, 1.0f, 0.0f}, { 0.0f, 1.0f, 0.0f},
10712 { 1.0f, 0.0f, 0.0f}, { 1.0f, 0.0f, 0.0f}, { 1.0f, 0.0f, 0.0f}, { 1.0f, 0.0f, 0.0f},
10713 { 0.0f,-1.0f, 0.0f}, { 0.0f,-1.0f, 0.0f}, { 0.0f,-1.0f, 0.0f}, { 0.0f,-1.0f, 0.0f},
10714 { 0.0f, 0.0f, 1.0f}, { 0.0f, 0.0f, 1.0f}, { 0.0f, 0.0f, 1.0f}, { 0.0f, 0.0f, 1.0f},
10715 { 0.0f, 0.0f,-1.0f}, { 0.0f, 0.0f,-1.0f}, { 0.0f, 0.0f,-1.0f}, { 0.0f, 0.0f,-1.0f}
10717 const float box_normal_component = 1.0f / sqrtf(3.0f);
10718 const D3DXVECTOR3 box_normals_adjacency[24] =
10720 {-box_normal_component, -box_normal_component, -box_normal_component},
10721 {-box_normal_component, -box_normal_component, box_normal_component},
10722 {-box_normal_component, box_normal_component, box_normal_component},
10723 {-box_normal_component, box_normal_component, -box_normal_component},
10724 {-box_normal_component, box_normal_component, -box_normal_component},
10725 {-box_normal_component, box_normal_component, box_normal_component},
10726 { box_normal_component, box_normal_component, box_normal_component},
10727 { box_normal_component, box_normal_component, -box_normal_component},
10728 { box_normal_component, box_normal_component, -box_normal_component},
10729 { box_normal_component, box_normal_component, box_normal_component},
10730 { box_normal_component, -box_normal_component, box_normal_component},
10731 { box_normal_component, -box_normal_component, -box_normal_component},
10732 {-box_normal_component, -box_normal_component, box_normal_component},
10733 {-box_normal_component, -box_normal_component, -box_normal_component},
10734 { box_normal_component, -box_normal_component, -box_normal_component},
10735 { box_normal_component, -box_normal_component, box_normal_component},
10736 {-box_normal_component, -box_normal_component, box_normal_component},
10737 { box_normal_component, -box_normal_component, box_normal_component},
10738 { box_normal_component, box_normal_component, box_normal_component},
10739 {-box_normal_component, box_normal_component, box_normal_component},
10740 {-box_normal_component, -box_normal_component, -box_normal_component},
10741 {-box_normal_component, box_normal_component, -box_normal_component},
10742 { box_normal_component, box_normal_component, -box_normal_component},
10743 { box_normal_component, -box_normal_component, -box_normal_component}
10745 static const D3DXVECTOR3 box_normals_adjacency_area[24] =
10747 {-0.666667f, -0.333333f, -0.666667f}, {-0.333333f, -0.666667f, 0.666667f},
10748 {-0.816496f, 0.408248f, 0.408248f}, {-0.408248f, 0.816496f, -0.408248f},
10749 {-0.408248f, 0.816496f, -0.408248f}, {-0.816496f, 0.408248f, 0.408248f},
10750 { 0.333333f, 0.666667f, 0.666667f}, { 0.666667f, 0.333333f, -0.666667f},
10751 { 0.666667f, 0.333333f, -0.666667f}, { 0.333333f, 0.666667f, 0.666667f},
10752 { 0.816496f, -0.408248f, 0.408248f}, { 0.408248f, -0.816496f, -0.408248f},
10753 {-0.333333f, -0.666667f, 0.666667f}, {-0.666667f, -0.333333f, -0.666667f},
10754 { 0.408248f, -0.816496f, -0.408248f}, { 0.816496f, -0.408248f, 0.408248f},
10755 {-0.333333f, -0.666667f, 0.666667f}, { 0.816497f, -0.408248f, 0.408248f},
10756 { 0.333333f, 0.666667f, 0.666667f}, {-0.816497f, 0.408248f, 0.408248f},
10757 {-0.666667f, -0.333333f, -0.666667f}, {-0.408248f, 0.816497f, -0.408248f},
10758 { 0.666667f, 0.333333f, -0.666667f}, { 0.408248f, -0.816496f, -0.408248f}
10760 static const D3DXVECTOR3 box_normals_position1f[24] = {{0}};
10761 static const D3DXVECTOR3 box_normals_position2f[24] =
10763 {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f},
10764 {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, 1.0f},
10765 {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, -1.0f},
10766 {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f},
10767 {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, -1.0f},
10768 {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f},
10769 {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f},
10770 {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, -1.0f}
10773 static const D3DXVECTOR3 sphere_normals[22] =
10775 { 0.000000f, -0.000000f, 1.000000f}, { 0.000000f, 0.582244f, 0.813014f},
10776 { 0.582244f, -0.000000f, 0.813014f}, {-0.000000f, -0.582244f, 0.813014f},
10777 {-0.582244f, 0.000000f, 0.813014f}, {-0.000000f, 0.890608f, 0.454772f},
10778 { 0.890608f, 0.000000f, 0.454772f}, { 0.000000f, -0.890608f, 0.454772f},
10779 {-0.890608f, -0.000000f, 0.454772f}, { 0.000000f, 1.000000f, -0.000000f},
10780 { 1.000000f, -0.000000f, -0.000000f}, {-0.000000f, -1.000000f, -0.000000f},
10781 {-1.000000f, 0.000000f, -0.000000f}, { 0.000000f, 0.890608f, -0.454773f},
10782 { 0.890608f, -0.000000f, -0.454772f}, {-0.000000f, -0.890608f, -0.454773f},
10783 {-0.890608f, 0.000000f, -0.454773f}, { 0.000000f, 0.582244f, -0.813015f},
10784 { 0.582244f, -0.000000f, -0.813015f}, { 0.000000f, -0.582244f, -0.813015f},
10785 {-0.582243f, 0.000000f, -0.813015f}, { 0.000000f, 0.000000f, -1.000000f}
10787 static const D3DXVECTOR3 sphere_normals_area[22] =
10789 { 0.000000f, -0.000000f, 1.000000f}, {-0.215311f, 0.554931f, 0.803550f},
10790 { 0.554931f, 0.215311f, 0.803550f}, { 0.215311f, -0.554931f, 0.803550f},
10791 {-0.554931f, -0.215311f, 0.803550f}, {-0.126638f, 0.872121f, 0.472618f},
10792 { 0.872121f, 0.126638f, 0.472618f}, { 0.126638f, -0.872121f, 0.472618f},
10793 {-0.872121f, -0.126637f, 0.472618f}, { 0.000000f, 1.000000f, -0.000000f},
10794 { 1.000000f, -0.000000f, -0.000000f}, {-0.000000f, -1.000000f, -0.000000f},
10795 {-1.000000f, 0.000000f, -0.000000f}, { 0.126638f, 0.872121f, -0.472618f},
10796 { 0.872121f, -0.126638f, -0.472618f}, {-0.126638f, -0.872121f, -0.472618f},
10797 {-0.872121f, 0.126638f, -0.472618f}, { 0.215311f, 0.554931f, -0.803550f},
10798 { 0.554931f, -0.215311f, -0.803550f}, {-0.215311f, -0.554931f, -0.803550f},
10799 {-0.554931f, 0.215311f, -0.803550f}, { 0.000000f, 0.000000f, -1.000000f}
10801 static const D3DXVECTOR3 sphere_normals_equal[22] =
10803 { 0.000000f, -0.000000f, 1.000000f}, {-0.134974f, 0.522078f, 0.842150f},
10804 { 0.522078f, 0.134974f, 0.842150f}, { 0.134974f, -0.522078f, 0.842150f},
10805 {-0.522078f, -0.134974f, 0.842150f}, {-0.026367f, 0.857121f, 0.514440f},
10806 { 0.857121f, 0.026367f, 0.514440f}, { 0.026367f, -0.857121f, 0.514440f},
10807 {-0.857121f, -0.026367f, 0.514440f}, { 0.000000f, 1.000000f, -0.000000f},
10808 { 1.000000f, -0.000000f, -0.000000f}, {-0.000000f, -1.000000f, -0.000000f},
10809 {-1.000000f, 0.000000f, -0.000000f}, { 0.026367f, 0.857121f, -0.514440f},
10810 { 0.857121f, -0.026367f, -0.514440f}, {-0.026367f, -0.857121f, -0.514440f},
10811 {-0.857121f, 0.026367f, -0.514440f}, { 0.134975f, 0.522078f, -0.842150f},
10812 { 0.522078f, -0.134975f, -0.842150f}, {-0.134974f, -0.522078f, -0.842150f},
10813 {-0.522078f, 0.134974f, -0.842150f}, { 0.000000f, 0.000000f, -1.000000f}
10816 static const D3DVERTEXELEMENT9 position3f_normal1f_declaration[] =
10818 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
10819 {0, sizeof(D3DXVECTOR3), D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
10820 D3DDECL_END()
10822 static const D3DVERTEXELEMENT9 position3f_normal2f_declaration[] =
10824 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
10825 {0, sizeof(D3DXVECTOR3), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
10826 D3DDECL_END()
10828 static const D3DVERTEXELEMENT9 normal4f_position3f_declaration[] =
10830 {0, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
10831 {0, sizeof(D3DXVECTOR4), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
10832 D3DDECL_END()
10834 static const D3DVERTEXELEMENT9 position1f_normal3f_declaration[] =
10836 {0, 0, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
10837 {0, sizeof(float), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
10838 D3DDECL_END()
10840 static const D3DVERTEXELEMENT9 position2f_normal3f_declaration[] =
10842 {0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
10843 {0, sizeof(D3DXVECTOR2), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
10844 D3DDECL_END()
10846 static const D3DVERTEXELEMENT9 position4f_normal3f_declaration[] =
10848 {0, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
10849 {0, sizeof(D3DXVECTOR4), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
10850 D3DDECL_END()
10853 for (i = 0; i < ARRAY_SIZE(compute_normals_funcs); i++)
10855 hr = compute_normals_funcs[i].apply(NULL, NULL);
10856 ok(hr == D3DERR_INVALIDCALL, "%s returned %#x, expected D3DERR_INVALIDCALL\n", compute_normals_funcs[i].name, hr);
10859 if (!(test_context = new_test_context()))
10861 skip("Couldn't create test context\n");
10862 return;
10864 device = test_context->device;
10866 hr = D3DXCreateBox(device, 1.0f, 1.0f, 1.0f, &mesh, &adjacency);
10867 ok(SUCCEEDED(hr), "D3DXCreateBox failed %#x\n", hr);
10869 /* Check wrong input */
10870 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
10871 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE, NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
10872 todo_wine ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr);
10874 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DDECLUSAGE_NORMAL, 0,
10875 D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_BY_AREA | D3DXTANGENT_WEIGHT_EQUAL,
10876 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
10877 ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr);
10879 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
10880 D3DDECLUSAGE_NORMAL, 0, 0, NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
10881 todo_wine ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr);
10883 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
10884 D3DDECLUSAGE_NORMAL, 1, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS,
10885 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
10886 ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr);
10888 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
10889 D3DX_DEFAULT, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS,
10890 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
10891 ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr);
10893 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
10894 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_CALCULATE_NORMALS,
10895 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
10896 todo_wine ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr);
10898 for (i = 0; i < ARRAY_SIZE(compute_normals_funcs); i++)
10900 const struct compute_normals_func *func = &compute_normals_funcs[i];
10902 /* Mesh without normals */
10903 hr = mesh->lpVtbl->CloneMeshFVF(mesh, 0, D3DFVF_XYZ, device, &cloned_mesh);
10904 ok(SUCCEEDED(hr), "CloneMeshFVF failed %#x\n", hr);
10906 hr = func->apply(cloned_mesh, NULL);
10907 ok(hr == D3DERR_INVALIDCALL, "%s returned %#x, expected D3DERR_INVALIDCALL\n", func->name, hr);
10909 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh);
10910 ok(!refcount, "Mesh has %u references left\n", refcount);
10912 /* Mesh without positions */
10913 hr = mesh->lpVtbl->CloneMeshFVF(mesh, 0, D3DFVF_NORMAL, device, &cloned_mesh);
10914 ok(SUCCEEDED(hr), "CloneMeshFVF failed %#x\n", hr);
10916 hr = func->apply(cloned_mesh, NULL);
10917 ok(hr == D3DERR_INVALIDCALL, "%s returned %#x, expected D3DERR_INVALIDCALL\n", func->name, hr);
10919 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh);
10920 ok(!refcount, "Mesh has %u references left\n", refcount);
10922 /* Mesh with D3DDECLTYPE_FLOAT1 normals */
10923 hr = mesh->lpVtbl->CloneMesh(mesh, 0, position3f_normal1f_declaration, device, &cloned_mesh);
10924 ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr);
10926 hr = func->apply(cloned_mesh, NULL);
10927 ok(hr == D3DERR_INVALIDCALL, "%s returned %#x, expected D3DERR_INVALIDCALL\n", func->name, hr);
10929 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh);
10930 ok(!refcount, "Mesh has %u references left\n", refcount);
10932 /* Mesh with D3DDECLTYPE_FLOAT2 normals */
10933 hr = mesh->lpVtbl->CloneMesh(mesh, 0, position3f_normal2f_declaration, device, &cloned_mesh);
10934 ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr);
10936 hr = func->apply(cloned_mesh, NULL);
10937 ok(hr == D3DERR_INVALIDCALL, "%s returned %#x, expected D3DERR_INVALIDCALL\n", func->name, hr);
10939 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh);
10940 ok(!refcount, "Mesh has %u references left\n", refcount);
10942 /* Mesh without adjacency data */
10943 hr = clear_normals(mesh);
10944 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr);
10946 hr = func->apply(mesh, NULL);
10947 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr);
10949 compare_normals(__LINE__, func->name, mesh, box_normals, ARRAY_SIZE(box_normals));
10951 /* Mesh with adjacency data */
10952 hr = clear_normals(mesh);
10953 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr);
10955 hr = func->apply(mesh, ID3DXBuffer_GetBufferPointer(adjacency));
10956 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr);
10958 compare_normals(__LINE__, func->name, mesh, box_normals_adjacency, ARRAY_SIZE(box_normals_adjacency));
10960 /* Mesh with custom vertex format, D3DDECLTYPE_FLOAT4 normals and adjacency */
10961 hr = mesh->lpVtbl->CloneMesh(mesh, 0, normal4f_position3f_declaration, device, &cloned_mesh);
10962 ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr);
10964 hr = clear_normals(cloned_mesh);
10965 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr);
10967 hr = func->apply(cloned_mesh, ID3DXBuffer_GetBufferPointer(adjacency));
10968 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr);
10970 compare_normals(__LINE__, func->name, cloned_mesh, box_normals_adjacency, ARRAY_SIZE(box_normals_adjacency));
10972 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh);
10973 ok(!refcount, "Mesh has %u references left\n", refcount);
10975 /* Mesh with D3DDECLTYPE_FLOAT1 positions and D3DDECLTYPE_FLOAT3 normals */
10976 hr = mesh->lpVtbl->CloneMesh(mesh, 0, position1f_normal3f_declaration, device, &cloned_mesh);
10977 ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr);
10979 hr = clear_normals(cloned_mesh);
10980 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr);
10982 hr = func->apply(cloned_mesh, ID3DXBuffer_GetBufferPointer(adjacency));
10983 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr);
10985 compare_normals(__LINE__, func->name, cloned_mesh, box_normals_position1f, ARRAY_SIZE(box_normals_position1f));
10987 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh);
10988 ok(!refcount, "Mesh has %u references left\n", refcount);
10990 /* Mesh with D3DDECLTYPE_FLOAT2 positions and D3DDECLTYPE_FLOAT3 normals */
10991 hr = mesh->lpVtbl->CloneMesh(mesh, 0, position2f_normal3f_declaration, device, &cloned_mesh);
10992 ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr);
10994 hr = clear_normals(cloned_mesh);
10995 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr);
10997 hr = func->apply(cloned_mesh, ID3DXBuffer_GetBufferPointer(adjacency));
10998 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr);
11000 compare_normals(__LINE__, func->name, cloned_mesh, box_normals_position2f, ARRAY_SIZE(box_normals_position2f));
11002 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh);
11003 ok(!refcount, "Mesh has %u references left\n", refcount);
11005 /* Mesh with D3DDECLTYPE_FLOAT4 positions and D3DDECLTYPE_FLOAT3 normals */
11006 hr = mesh->lpVtbl->CloneMesh(mesh, 0, position4f_normal3f_declaration, device, &cloned_mesh);
11007 ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr);
11009 hr = clear_normals(cloned_mesh);
11010 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr);
11012 hr = func->apply(cloned_mesh, ID3DXBuffer_GetBufferPointer(adjacency));
11013 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr);
11015 compare_normals(__LINE__, func->name, cloned_mesh, box_normals_adjacency, ARRAY_SIZE(box_normals_adjacency));
11017 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh);
11018 ok(!refcount, "Mesh has %u references left\n", refcount);
11021 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
11022 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_BY_AREA,
11023 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
11024 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr);
11026 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, box_normals, ARRAY_SIZE(box_normals));
11028 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
11029 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_BY_AREA,
11030 ID3DXBuffer_GetBufferPointer(adjacency), -1.01f, -0.01f, -1.01f, NULL, NULL);
11031 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr);
11033 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, box_normals_adjacency_area, ARRAY_SIZE(box_normals_adjacency_area));
11035 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
11036 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_EQUAL,
11037 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
11038 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr);
11040 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, box_normals, ARRAY_SIZE(box_normals));
11042 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
11043 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_EQUAL,
11044 ID3DXBuffer_GetBufferPointer(adjacency), -1.01f, -0.01f, -1.01f, NULL, NULL);
11045 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr);
11047 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, box_normals_adjacency_area, ARRAY_SIZE(box_normals_adjacency_area));
11049 refcount = mesh->lpVtbl->Release(mesh);
11050 ok(!refcount, "Mesh has %u references left\n", refcount);
11051 refcount = ID3DXBuffer_Release(adjacency);
11052 ok(!refcount, "Buffer has %u references left\n", refcount);
11054 hr = D3DXCreateSphere(device, 1.0f, 4, 6, &mesh, &adjacency);
11055 ok(SUCCEEDED(hr), "D3DXCreateSphere failed %#x\n", hr);
11057 for (i = 0; i < ARRAY_SIZE(compute_normals_funcs); i++)
11059 const struct compute_normals_func *func = &compute_normals_funcs[i];
11061 /* Sphere without adjacency data */
11062 hr = clear_normals(mesh);
11063 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr);
11065 hr = func->apply(mesh, NULL);
11066 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr);
11068 compare_normals(__LINE__, func->name, mesh, sphere_normals, ARRAY_SIZE(sphere_normals));
11070 /* Sphere with adjacency data */
11071 hr = clear_normals(mesh);
11072 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr);
11074 hr = func->apply(mesh, ID3DXBuffer_GetBufferPointer(adjacency));
11075 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr);
11077 compare_normals(__LINE__, func->name, mesh, sphere_normals, ARRAY_SIZE(sphere_normals));
11080 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
11081 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_BY_AREA,
11082 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
11083 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr);
11085 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, sphere_normals_area, ARRAY_SIZE(sphere_normals_area));
11087 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
11088 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_BY_AREA,
11089 ID3DXBuffer_GetBufferPointer(adjacency), -1.01f, -0.01f, -1.01f, NULL, NULL);
11090 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr);
11092 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, sphere_normals_area, ARRAY_SIZE(sphere_normals_area));
11094 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
11095 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_EQUAL,
11096 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
11097 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr);
11099 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, sphere_normals_equal, ARRAY_SIZE(sphere_normals_equal));
11101 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
11102 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_EQUAL,
11103 ID3DXBuffer_GetBufferPointer(adjacency), -1.01f, -0.01f, -1.01f, NULL, NULL);
11104 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr);
11106 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, sphere_normals_equal, ARRAY_SIZE(sphere_normals_equal));
11108 refcount = mesh->lpVtbl->Release(mesh);
11109 ok(!refcount, "Mesh has %u references left\n", refcount);
11110 refcount = ID3DXBuffer_Release(adjacency);
11111 ok(!refcount, "Buffer has %u references left\n", refcount);
11113 free_test_context(test_context);
11116 static void D3DXCreateAnimationControllerTest(void)
11118 HRESULT hr;
11119 ID3DXAnimationController *animation;
11120 UINT value;
11122 hr = D3DXCreateAnimationController(0, 0, 0, 0, NULL);
11123 ok(hr == D3D_OK, "Got unexpected hr returned %#x.\n", hr);
11125 animation = (void*)0xdeadbeef;
11126 hr = D3DXCreateAnimationController(0, 1, 1, 1, &animation);
11127 ok(hr == D3D_OK, "Got unexpected hr returned %#x.\n", hr);
11128 ok(animation == (void*)0xdeadbeef, "Got unexpected animation %p.\n", animation);
11130 animation = (void*)0xdeadbeef;
11131 hr = D3DXCreateAnimationController(1, 0, 1, 1, &animation);
11132 ok(hr == D3D_OK, "Got unexpected hr returned %#x.\n", hr);
11133 ok(animation == (void*)0xdeadbeef, "Got unexpected animation %p.\n", animation);
11135 animation = (void*)0xdeadbeef;
11136 hr = D3DXCreateAnimationController(1, 1, 0, 1, &animation);
11137 ok(hr == D3D_OK, "Got unexpected hr returned %#x.\n", hr);
11138 ok(animation == (void*)0xdeadbeef, "Got unexpected animation %p.\n", animation);
11140 animation = (void*)0xdeadbeef;
11141 hr = D3DXCreateAnimationController(1, 1, 1, 0, &animation);
11142 ok(hr == D3D_OK, "Got unexpected hr returned %#x.\n", hr);
11143 ok(animation == (void*)0xdeadbeef, "Got unexpected animation %p.\n", animation);
11145 hr = D3DXCreateAnimationController(1, 1, 1, 1, &animation);
11146 ok(hr == D3D_OK, "Got unexpected hr returned %#x.\n", hr);
11148 value = animation->lpVtbl->GetMaxNumAnimationOutputs(animation);
11149 ok(value == 1, "Got unexpected value %u.\n", value);
11151 value = animation->lpVtbl->GetMaxNumAnimationSets(animation);
11152 ok(value == 1, "Got unexpected value %u.\n", value);
11154 value = animation->lpVtbl->GetMaxNumTracks(animation);
11155 ok(value == 1, "Got unexpected value %u.\n", value);
11157 value = animation->lpVtbl->GetMaxNumEvents(animation);
11158 ok(value == 1, "Got unexpected value %u.\n", value);
11160 animation->lpVtbl->Release(animation);
11162 hr = D3DXCreateAnimationController(100, 101, 102, 103, &animation);
11163 ok(hr == D3D_OK, "Got unexpected hr returned %#x.\n", hr);
11165 value = animation->lpVtbl->GetMaxNumAnimationOutputs(animation);
11166 ok(value == 100, "Got unexpected value %u.\n", value);
11168 value = animation->lpVtbl->GetMaxNumAnimationSets(animation);
11169 ok(value == 101, "Got unexpected value %u.\n", value);
11171 value = animation->lpVtbl->GetMaxNumTracks(animation);
11172 ok(value == 102, "Got unexpected value %u.\n", value);
11174 value = animation->lpVtbl->GetMaxNumEvents(animation);
11175 ok(value == 103, "Got unexpected value %u.\n", value);
11177 animation->lpVtbl->Release(animation);
11180 static void D3DXCreateKeyframedAnimationSetTest(void)
11182 ID3DXKeyframedAnimationSet *set;
11183 D3DXPLAYBACK_TYPE type;
11184 unsigned int count;
11185 const char *name;
11186 HRESULT hr;
11188 hr = D3DXCreateKeyframedAnimationSet("wine_bottle", 5.0, D3DXPLAY_LOOP, 0, 0, NULL, &set);
11189 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11191 hr = D3DXCreateKeyframedAnimationSet("wine_bottle", 5.0, D3DXPLAY_LOOP, 10, 0, NULL, &set);
11192 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11194 name = set->lpVtbl->GetName(set);
11195 ok(!strcmp(name, "wine_bottle"), "Got unexpected name %s.\n", debugstr_a(name));
11197 type = set->lpVtbl->GetPlaybackType(set);
11198 ok(type == D3DXPLAY_LOOP, "Got unexpected value %u.\n", type);
11200 count = set->lpVtbl->GetNumAnimations(set);
11201 ok(!count, "Got unexpected value %u.\n", count);
11203 set->lpVtbl->Release(set);
11206 static void test_D3DXFrameFind(void)
11208 static char n1[] = "name1";
11209 static char n2[] = "name2";
11210 static char n3[] = "name3";
11211 static char n4[] = "name4";
11212 static char n5[] = "name5";
11213 static char n6[] = "name6";
11214 static char N1[] = "Name1";
11215 D3DXFRAME root, sibling, sibling2, child, *ret;
11216 D3DXFRAME child2, child3;
11218 ret = D3DXFrameFind(NULL, NULL);
11219 ok(ret == NULL, "Unexpected frame, %p.\n", ret);
11221 ret = D3DXFrameFind(NULL, "test");
11222 ok(ret == NULL, "Unexpected frame, %p.\n", ret);
11224 memset(&root, 0, sizeof(root));
11226 ret = D3DXFrameFind(&root, NULL);
11227 ok(ret == &root, "Unexpected frame, %p.\n", ret);
11229 root.Name = n1;
11230 ret = D3DXFrameFind(&root, NULL);
11231 ok(ret == NULL, "Unexpected frame, %p.\n", ret);
11233 ret = D3DXFrameFind(&root, n1);
11234 ok(ret == &root, "Unexpected frame, %p.\n", ret);
11236 ret = D3DXFrameFind(&root, N1);
11237 ok(ret == NULL, "Unexpected frame, %p.\n", ret);
11239 /* Test siblings order traversal. */
11240 memset(&sibling, 0, sizeof(sibling));
11241 sibling.Name = n2;
11242 root.pFrameSibling = &sibling;
11243 ret = D3DXFrameFind(&root, n2);
11244 ok(ret == &sibling, "Unexpected frame, %p.\n", ret);
11246 memset(&sibling2, 0, sizeof(sibling2));
11247 sibling2.Name = n2;
11248 sibling.pFrameSibling = &sibling2;
11249 ret = D3DXFrameFind(&root, n2);
11250 ok(ret == &sibling, "Unexpected frame, %p.\n", ret);
11252 sibling2.Name = n3;
11253 ret = D3DXFrameFind(&root, n3);
11254 ok(ret == &sibling2, "Unexpected frame, %p.\n", ret);
11256 /* Siblings first. */
11257 memset(&child, 0, sizeof(child));
11258 child.Name = n2;
11259 root.pFrameFirstChild = &child;
11260 ret = D3DXFrameFind(&root, n2);
11261 ok(ret == &sibling, "Unexpected frame, %p.\n", ret);
11263 child.Name = n4;
11264 ret = D3DXFrameFind(&root, n4);
11265 ok(ret == &child, "Unexpected frame, %p.\n", ret);
11267 /* Link a grandchild and another one for sibling. */
11268 memset(&child2, 0, sizeof(child2));
11269 memset(&child3, 0, sizeof(child3));
11270 child2.Name = child3.Name = n5;
11271 sibling.pFrameFirstChild = &child2;
11272 child.pFrameFirstChild = &child3;
11273 ret = D3DXFrameFind(&root, n5);
11274 ok(ret == &child2, "Unexpected frame, %p.\n", ret);
11276 child3.Name = n6;
11277 ret = D3DXFrameFind(&root, n6);
11278 ok(ret == &child3, "Unexpected frame, %p.\n", ret);
11281 static ID3DXFileData *get_mesh_data(const void *memory, SIZE_T length)
11283 ID3DXFileData *file_data, *ret = NULL;
11284 ID3DXFileEnumObject *enum_obj = NULL;
11285 D3DXF_FILELOADMEMORY source;
11286 ID3DXFile *file;
11287 SIZE_T i, count;
11288 GUID guid;
11290 if (FAILED(D3DXFileCreate(&file)))
11291 return NULL;
11293 if (FAILED(file->lpVtbl->RegisterTemplates(file, D3DRM_XTEMPLATES, D3DRM_XTEMPLATE_BYTES)))
11294 goto cleanup;
11296 source.lpMemory = memory;
11297 source.dSize = length;
11298 if (FAILED(file->lpVtbl->CreateEnumObject(file, &source, D3DXF_FILELOAD_FROMMEMORY, &enum_obj)))
11299 goto cleanup;
11301 if (FAILED(enum_obj->lpVtbl->GetChildren(enum_obj, &count)))
11302 goto cleanup;
11304 for (i = 0; i < count; ++i)
11306 if (FAILED(enum_obj->lpVtbl->GetChild(enum_obj, i, &file_data)))
11307 goto cleanup;
11309 if (SUCCEEDED(file_data->lpVtbl->GetType(file_data, &guid))
11310 && IsEqualGUID(&guid, &TID_D3DRMMesh))
11312 ret = file_data;
11313 break;
11315 else
11317 file_data->lpVtbl->Release(file_data);
11321 cleanup:
11322 if (enum_obj)
11323 enum_obj->lpVtbl->Release(enum_obj);
11324 file->lpVtbl->Release(file);
11326 return ret;
11329 static void test_load_skin_mesh_from_xof(void)
11331 static const char simple_xfile[] =
11332 "xof 0303txt 0032"
11333 "Mesh {"
11334 "3;"
11335 "0.0; 0.0; 0.0;,"
11336 "0.0; 1.0; 0.0;,"
11337 "1.0; 1.0; 0.0;;"
11338 "1;"
11339 "3; 0, 1, 2;;"
11340 "}";
11341 static const D3DVERTEXELEMENT9 expected_declaration[] =
11343 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
11344 D3DDECL_END(),
11346 D3DVERTEXELEMENT9 declaration[MAX_FVF_DECL_SIZE];
11347 ID3DXBuffer *adjacency, *materials, *effects;
11348 DWORD max_influences[3], count, fvf;
11349 D3DPRESENT_PARAMETERS d3dpp;
11350 IDirect3DDevice9 *device;
11351 ID3DXSkinInfo *skin_info;
11352 ID3DXFileData *file_data;
11353 const char *bone_name;
11354 D3DXMATRIX *matrix;
11355 float influence;
11356 ID3DXMesh *mesh;
11357 IDirect3D9 *d3d;
11358 ULONG refcount;
11359 HRESULT hr;
11360 HWND hwnd;
11362 if (!(hwnd = CreateWindowA("static", "d3dx9_test", WS_OVERLAPPEDWINDOW, 0, 0,
11363 640, 480, NULL, NULL, NULL, NULL)))
11365 skip("Failed to create application window.\n");
11366 return;
11369 d3d = Direct3DCreate9(D3D_SDK_VERSION);
11370 if (!d3d)
11372 skip("Failed to create d3d object.\n");
11373 DestroyWindow(hwnd);
11374 return;
11377 memset(&d3dpp, 0, sizeof(d3dpp));
11378 d3dpp.Windowed = TRUE;
11379 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
11381 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
11382 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device);
11383 IDirect3D9_Release(d3d);
11384 if (FAILED(hr))
11386 skip("Failed to create device, hr %#x.\n", hr);
11387 DestroyWindow(hwnd);
11388 return;
11391 file_data = get_mesh_data(simple_xfile, sizeof(simple_xfile) - 1);
11392 ok(!!file_data, "Failed to load mesh data.\n");
11394 adjacency = materials = effects = (void *)0xdeadbeef;
11395 count = ~0u;
11396 skin_info = (void *)0xdeadbeef;
11397 mesh = (void *)0xdeadbeef;
11399 hr = D3DXLoadSkinMeshFromXof(file_data, 0, device, &adjacency, &materials, &effects, &count,
11400 &skin_info, &mesh);
11401 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11402 ok(!!adjacency, "Got unexpected value %p.\n", adjacency);
11403 ok(!materials, "Got unexpected value %p.\n", materials);
11404 ok(!effects, "Got unexpected value %p.\n", effects);
11405 ok(!count, "Got unexpected value %u.\n", count);
11406 ok(!!skin_info, "Got unexpected value %p.\n", skin_info);
11407 ok(!!mesh, "Got unexpected value %p.\n", mesh);
11408 count = mesh->lpVtbl->GetNumVertices(mesh);
11409 ok(count == 3, "Got unexpected value %u.\n", count);
11410 count = mesh->lpVtbl->GetNumFaces(mesh);
11411 ok(count == 1, "Got unexpected value %u.\n", count);
11413 hr = skin_info->lpVtbl->GetDeclaration(skin_info, declaration);
11414 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11415 compare_elements(declaration, expected_declaration, __LINE__, 0);
11417 fvf = skin_info->lpVtbl->GetFVF(skin_info);
11418 ok(fvf == D3DFVF_XYZ, "Got unexpected value %u.\n", fvf);
11420 count = skin_info->lpVtbl->GetNumBones(skin_info);
11421 ok(!count, "Got unexpected value %u.\n", count);
11423 influence = skin_info->lpVtbl->GetMinBoneInfluence(skin_info);
11424 ok(!influence, "Got unexpected value %.8e.\n", influence);
11426 memset(max_influences, 0x55, sizeof(max_influences));
11427 hr = skin_info->lpVtbl->GetMaxVertexInfluences(skin_info, max_influences);
11428 todo_wine ok(hr == D3D_OK, "Got unexpected value %#x.\n", hr);
11429 todo_wine ok(!max_influences[0], "Got unexpected value %u.\n", max_influences[0]);
11430 ok(max_influences[1] == 0x55555555, "Got unexpected value %u.\n", max_influences[1]);
11431 ok(max_influences[2] == 0x55555555, "Got unexpected value %u.\n", max_influences[2]);
11433 bone_name = skin_info->lpVtbl->GetBoneName(skin_info, 0);
11434 ok(!bone_name, "Got unexpected value %p.\n", bone_name);
11436 count = skin_info->lpVtbl->GetNumBoneInfluences(skin_info, 0);
11437 ok(!count, "Got unexpected value %u.\n", count);
11439 count = skin_info->lpVtbl->GetNumBoneInfluences(skin_info, 1);
11440 ok(!count, "Got unexpected value %u.\n", count);
11442 matrix = skin_info->lpVtbl->GetBoneOffsetMatrix(skin_info, -1);
11443 ok(!matrix, "Got unexpected value %p.\n", matrix);
11445 matrix = skin_info->lpVtbl->GetBoneOffsetMatrix(skin_info, 0);
11446 ok(!matrix, "Got unexpected value %p.\n", matrix);
11448 skin_info->lpVtbl->Release(skin_info);
11449 mesh->lpVtbl->Release(mesh);
11450 adjacency->lpVtbl->Release(adjacency);
11451 file_data->lpVtbl->Release(file_data);
11452 refcount = IDirect3DDevice9_Release(device);
11453 ok(!refcount, "Device has %u references left.\n", refcount);
11454 DestroyWindow(hwnd);
11457 START_TEST(mesh)
11459 D3DXBoundProbeTest();
11460 D3DXComputeBoundingBoxTest();
11461 D3DXComputeBoundingSphereTest();
11462 D3DXGetFVFVertexSizeTest();
11463 D3DXIntersectTriTest();
11464 D3DXCreateMeshTest();
11465 D3DXCreateMeshFVFTest();
11466 D3DXLoadMeshTest();
11467 D3DXCreateBoxTest();
11468 D3DXCreatePolygonTest();
11469 D3DXCreateSphereTest();
11470 D3DXCreateCylinderTest();
11471 D3DXCreateTextTest();
11472 D3DXCreateTorusTest();
11473 D3DXCreateAnimationControllerTest();
11474 D3DXCreateKeyframedAnimationSetTest();
11475 test_get_decl_length();
11476 test_get_decl_vertex_size();
11477 test_fvf_decl_conversion();
11478 D3DXGenerateAdjacencyTest();
11479 test_update_semantics();
11480 test_create_skin_info();
11481 test_convert_adjacency_to_point_reps();
11482 test_convert_point_reps_to_adjacency();
11483 test_weld_vertices();
11484 test_clone_mesh();
11485 test_valid_mesh();
11486 test_optimize_faces();
11487 test_compute_normals();
11488 test_D3DXFrameFind();
11489 test_load_skin_mesh_from_xof();