include/mscvpdb.h: Use flexible array members for the rest of structures.
[wine.git] / dlls / d3dx9_36 / tests / mesh.c
blob1af4532790a9bac4420bdd553cc8d72283f1fd78
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 <assert.h>
27 #include "wine/test.h"
28 #include "d3dx9.h"
29 #include "initguid.h"
30 #include "rmxftmpl.h"
31 #include "rmxfguid.h"
33 /* Set the WINETEST_DEBUG environment variable to be greater than 1 for verbose
34 * function call traces of ID3DXAllocateHierarchy callbacks. */
35 #define TRACECALLBACK if(winetest_debug > 1) trace
37 #define admitted_error 0.0001f
39 #define compare_vertex_sizes(type, exp) \
40 got=D3DXGetFVFVertexSize(type); \
41 ok(got==exp, "Expected: %d, Got: %d\n", exp, got);
43 #define compare_float(got, exp) \
44 do { \
45 float _got = (got); \
46 float _exp = (exp); \
47 ok(_got == _exp, "Expected: %g, Got: %g\n", _exp, _got); \
48 } while (0)
50 static BOOL compare(FLOAT u, FLOAT v)
52 return (fabs(u-v) < admitted_error);
55 static BOOL compare_vec3(D3DXVECTOR3 u, D3DXVECTOR3 v)
57 return ( compare(u.x, v.x) && compare(u.y, v.y) && compare(u.z, v.z) );
60 static BOOL compare_vec4(D3DXVECTOR4 u, D3DXVECTOR4 v)
62 return compare(u.x, v.x) && compare(u.y, v.y) && compare(u.z, v.z) && compare(u.w, v.w);
65 #define check_floats(got, exp, dim) check_floats_(__LINE__, "", got, exp, dim)
66 static void check_floats_(int line, const char *prefix, const float *got, const float *exp, int dim)
68 int i;
69 char exp_buffer[256] = "";
70 char got_buffer[256] = "";
71 char *exp_buffer_ptr = exp_buffer;
72 char *got_buffer_ptr = got_buffer;
73 BOOL equal = TRUE;
75 for (i = 0; i < dim; i++) {
76 if (i) {
77 exp_buffer_ptr += sprintf(exp_buffer_ptr, ", ");
78 got_buffer_ptr += sprintf(got_buffer_ptr, ", ");
80 equal = equal && compare(*exp, *got);
81 exp_buffer_ptr += sprintf(exp_buffer_ptr, "%g", *exp);
82 got_buffer_ptr += sprintf(got_buffer_ptr, "%g", *got);
83 exp++; got++;
85 ok_(__FILE__,line)(equal, "%sExpected (%s), got (%s)", prefix, exp_buffer, got_buffer);
88 struct vertex
90 D3DXVECTOR3 position;
91 D3DXVECTOR3 normal;
94 typedef WORD face[3];
96 static BOOL compare_face(face a, face b)
98 return (a[0]==b[0] && a[1] == b[1] && a[2] == b[2]);
101 struct test_context
103 HWND hwnd;
104 IDirect3D9 *d3d;
105 IDirect3DDevice9 *device;
108 /* Initializes a test context struct. Use it to initialize DirectX.
110 * Returns NULL if an error occurred.
112 static struct test_context *new_test_context(void)
114 HRESULT hr;
115 HWND hwnd = NULL;
116 IDirect3D9 *d3d = NULL;
117 IDirect3DDevice9 *device = NULL;
118 D3DPRESENT_PARAMETERS d3dpp = {0};
119 struct test_context *test_context;
121 if (!(hwnd = CreateWindowA("static", "d3dx9_test", WS_OVERLAPPEDWINDOW, 0, 0,
122 640, 480, NULL, NULL, NULL, NULL)))
124 skip("Couldn't create application window\n");
125 goto error;
128 d3d = Direct3DCreate9(D3D_SDK_VERSION);
129 if (!d3d)
131 skip("Couldn't create IDirect3D9 object\n");
132 goto error;
135 memset(&d3dpp, 0, sizeof(d3dpp));
136 d3dpp.Windowed = TRUE;
137 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
138 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
139 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device);
140 if (FAILED(hr))
142 skip("Couldn't create IDirect3DDevice9 object %#lx\n", hr);
143 goto error;
146 test_context = malloc(sizeof(*test_context));
147 if (!test_context)
149 skip("Couldn't allocate memory for test_context\n");
150 goto error;
152 test_context->hwnd = hwnd;
153 test_context->d3d = d3d;
154 test_context->device = device;
156 return test_context;
158 error:
159 if (device)
160 IDirect3DDevice9_Release(device);
162 if (d3d)
163 IDirect3D9_Release(d3d);
165 if (hwnd)
166 DestroyWindow(hwnd);
168 return NULL;
171 static void free_test_context(struct test_context *test_context)
173 if (!test_context)
174 return;
176 if (test_context->device)
177 IDirect3DDevice9_Release(test_context->device);
179 if (test_context->d3d)
180 IDirect3D9_Release(test_context->d3d);
182 if (test_context->hwnd)
183 DestroyWindow(test_context->hwnd);
185 free(test_context);
188 struct mesh
190 DWORD number_of_vertices;
191 struct vertex *vertices;
193 DWORD number_of_faces;
194 face *faces;
196 DWORD fvf;
197 UINT vertex_size;
200 static void free_mesh(struct mesh *mesh)
202 free(mesh->faces);
203 free(mesh->vertices);
206 static BOOL new_mesh(struct mesh *mesh, DWORD number_of_vertices, DWORD number_of_faces)
208 mesh->vertices = calloc(number_of_vertices, sizeof(*mesh->vertices));
209 if (!mesh->vertices)
211 return FALSE;
213 mesh->number_of_vertices = number_of_vertices;
215 mesh->faces = calloc(number_of_faces, sizeof(*mesh->faces));
216 if (!mesh->faces)
218 free(mesh->vertices);
219 return FALSE;
221 mesh->number_of_faces = number_of_faces;
223 return TRUE;
226 static void compare_mesh(const char *name, ID3DXMesh *d3dxmesh, struct mesh *mesh)
228 HRESULT hr;
229 DWORD number_of_vertices, number_of_faces;
230 IDirect3DVertexBuffer9 *vertex_buffer;
231 IDirect3DIndexBuffer9 *index_buffer;
232 D3DVERTEXBUFFER_DESC vertex_buffer_description;
233 D3DINDEXBUFFER_DESC index_buffer_description;
234 struct vertex *vertices;
235 face *faces;
236 int expected, i;
238 number_of_vertices = d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh);
239 ok(number_of_vertices == mesh->number_of_vertices, "Test %s, result %lu, expected %ld\n",
240 name, number_of_vertices, mesh->number_of_vertices);
242 number_of_faces = d3dxmesh->lpVtbl->GetNumFaces(d3dxmesh);
243 ok(number_of_faces == mesh->number_of_faces, "Test %s, result %lu, expected %ld\n",
244 name, number_of_faces, mesh->number_of_faces);
246 /* vertex buffer */
247 hr = d3dxmesh->lpVtbl->GetVertexBuffer(d3dxmesh, &vertex_buffer);
248 ok(hr == D3D_OK, "Test %s, result %lx, expected 0 (D3D_OK)\n", name, hr);
250 if (hr != D3D_OK)
252 skip("Couldn't get vertex buffer\n");
254 else
256 hr = IDirect3DVertexBuffer9_GetDesc(vertex_buffer, &vertex_buffer_description);
257 ok(hr == D3D_OK, "Test %s, result %lx, expected 0 (D3D_OK)\n", name, hr);
259 if (hr != D3D_OK)
261 skip("Couldn't get vertex buffer description\n");
263 else
265 ok(vertex_buffer_description.Format == D3DFMT_VERTEXDATA, "Test %s, result %x, expected %x (D3DFMT_VERTEXDATA)\n",
266 name, vertex_buffer_description.Format, D3DFMT_VERTEXDATA);
267 ok(vertex_buffer_description.Type == D3DRTYPE_VERTEXBUFFER, "Test %s, result %x, expected %x (D3DRTYPE_VERTEXBUFFER)\n",
268 name, vertex_buffer_description.Type, D3DRTYPE_VERTEXBUFFER);
269 ok(vertex_buffer_description.Usage == 0, "Test %s, result %lx, expected %x\n", name, vertex_buffer_description.Usage, 0);
270 ok(vertex_buffer_description.Pool == D3DPOOL_MANAGED, "Test %s, result %x, expected %x (D3DPOOL_MANAGED)\n",
271 name, vertex_buffer_description.Pool, D3DPOOL_MANAGED);
272 ok(vertex_buffer_description.FVF == mesh->fvf, "Test %s, result %lx, expected %lx\n",
273 name, vertex_buffer_description.FVF, mesh->fvf);
274 if (mesh->fvf == 0)
276 expected = number_of_vertices * mesh->vertex_size;
278 else
280 expected = number_of_vertices * D3DXGetFVFVertexSize(mesh->fvf);
282 ok(vertex_buffer_description.Size == expected, "Test %s, result %x, expected %x\n",
283 name, vertex_buffer_description.Size, expected);
286 /* specify offset and size to avoid potential overruns */
287 hr = IDirect3DVertexBuffer9_Lock(vertex_buffer, 0, number_of_vertices * sizeof(D3DXVECTOR3) * 2,
288 (void **)&vertices, D3DLOCK_DISCARD);
289 ok(hr == D3D_OK, "Test %s, result %lx, expected 0 (D3D_OK)\n", name, hr);
291 if (hr != D3D_OK)
293 skip("Couldn't lock vertex buffer\n");
295 else
297 for (i = 0; i < number_of_vertices; i++)
299 ok(compare_vec3(vertices[i].position, mesh->vertices[i].position),
300 "Test %s, vertex position %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i,
301 vertices[i].position.x, vertices[i].position.y, vertices[i].position.z,
302 mesh->vertices[i].position.x, mesh->vertices[i].position.y, mesh->vertices[i].position.z);
303 ok(compare_vec3(vertices[i].normal, mesh->vertices[i].normal),
304 "Test %s, vertex normal %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i,
305 vertices[i].normal.x, vertices[i].normal.y, vertices[i].normal.z,
306 mesh->vertices[i].normal.x, mesh->vertices[i].normal.y, mesh->vertices[i].normal.z);
309 IDirect3DVertexBuffer9_Unlock(vertex_buffer);
312 IDirect3DVertexBuffer9_Release(vertex_buffer);
315 /* index buffer */
316 hr = d3dxmesh->lpVtbl->GetIndexBuffer(d3dxmesh, &index_buffer);
317 ok(hr == D3D_OK, "Test %s, result %lx, expected 0 (D3D_OK)\n", name, hr);
319 if (!index_buffer)
321 skip("Couldn't get index buffer\n");
323 else
325 hr = IDirect3DIndexBuffer9_GetDesc(index_buffer, &index_buffer_description);
326 ok(hr == D3D_OK, "Test %s, result %lx, expected 0 (D3D_OK)\n", name, hr);
328 if (hr != D3D_OK)
330 skip("Couldn't get index buffer description\n");
332 else
334 ok(index_buffer_description.Format == D3DFMT_INDEX16, "Test %s, result %x, expected %x (D3DFMT_INDEX16)\n",
335 name, index_buffer_description.Format, D3DFMT_INDEX16);
336 ok(index_buffer_description.Type == D3DRTYPE_INDEXBUFFER, "Test %s, result %x, expected %x (D3DRTYPE_INDEXBUFFER)\n",
337 name, index_buffer_description.Type, D3DRTYPE_INDEXBUFFER);
338 ok(index_buffer_description.Usage == 0, "Test %s, result %#lx, expected %#x.\n",
339 name, index_buffer_description.Usage, 0);
340 ok(index_buffer_description.Pool == D3DPOOL_MANAGED, "Test %s, result %x, expected %x (D3DPOOL_MANAGED)\n",
341 name, index_buffer_description.Pool, D3DPOOL_MANAGED);
342 expected = number_of_faces * sizeof(WORD) * 3;
343 ok(index_buffer_description.Size == expected, "Test %s, result %x, expected %x\n",
344 name, index_buffer_description.Size, expected);
347 /* specify offset and size to avoid potential overruns */
348 hr = IDirect3DIndexBuffer9_Lock(index_buffer, 0, number_of_faces * sizeof(WORD) * 3,
349 (void **)&faces, D3DLOCK_DISCARD);
350 ok(hr == D3D_OK, "Test %s, result %lx, expected 0 (D3D_OK)\n", name, hr);
352 if (hr != D3D_OK)
354 skip("Couldn't lock index buffer\n");
356 else
358 for (i = 0; i < number_of_faces; i++)
360 ok(compare_face(faces[i], mesh->faces[i]),
361 "Test %s, face %d, result (%u, %u, %u), expected (%u, %u, %u)\n", name, i,
362 faces[i][0], faces[i][1], faces[i][2],
363 mesh->faces[i][0], mesh->faces[i][1], mesh->faces[i][2]);
366 IDirect3DIndexBuffer9_Unlock(index_buffer);
369 IDirect3DIndexBuffer9_Release(index_buffer);
373 static void D3DXBoundProbeTest(void)
375 BOOL result;
376 D3DXVECTOR3 bottom_point, center, top_point, raydirection, rayposition;
377 FLOAT radius;
379 /*____________Test the Box case___________________________*/
380 bottom_point.x = -3.0f; bottom_point.y = -2.0f; bottom_point.z = -1.0f;
381 top_point.x = 7.0f; top_point.y = 8.0f; top_point.z = 9.0f;
383 raydirection.x = -4.0f; raydirection.y = -5.0f; raydirection.z = -6.0f;
384 rayposition.x = 5.0f; rayposition.y = 5.0f; rayposition.z = 11.0f;
385 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection);
386 ok(result == TRUE, "expected TRUE, received FALSE\n");
388 raydirection.x = 4.0f; raydirection.y = 5.0f; raydirection.z = 6.0f;
389 rayposition.x = 5.0f; rayposition.y = 5.0f; rayposition.z = 11.0f;
390 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection);
391 ok(result == FALSE, "expected FALSE, received TRUE\n");
393 rayposition.x = -4.0f; rayposition.y = 1.0f; rayposition.z = -2.0f;
394 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection);
395 ok(result == TRUE, "expected TRUE, received FALSE\n");
397 bottom_point.x = 1.0f; bottom_point.y = 0.0f; bottom_point.z = 0.0f;
398 top_point.x = 1.0f; top_point.y = 0.0f; top_point.z = 0.0f;
399 rayposition.x = 0.0f; rayposition.y = 1.0f; rayposition.z = 0.0f;
400 raydirection.x = 0.0f; raydirection.y = 3.0f; raydirection.z = 0.0f;
401 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection);
402 ok(result == FALSE, "expected FALSE, received TRUE\n");
404 bottom_point.x = 1.0f; bottom_point.y = 2.0f; bottom_point.z = 3.0f;
405 top_point.x = 10.0f; top_point.y = 15.0f; top_point.z = 20.0f;
407 raydirection.x = 7.0f; raydirection.y = 8.0f; raydirection.z = 9.0f;
408 rayposition.x = 3.0f; rayposition.y = 7.0f; rayposition.z = -6.0f;
409 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection);
410 ok(result == TRUE, "expected TRUE, received FALSE\n");
412 bottom_point.x = 0.0f; bottom_point.y = 0.0f; bottom_point.z = 0.0f;
413 top_point.x = 1.0f; top_point.y = 1.0f; top_point.z = 1.0f;
415 raydirection.x = 0.0f; raydirection.y = 1.0f; raydirection.z = .0f;
416 rayposition.x = -3.0f; rayposition.y = 0.0f; rayposition.z = 0.0f;
417 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection);
418 ok(result == FALSE, "expected FALSE, received TRUE\n");
420 raydirection.x = 1.0f; raydirection.y = 0.0f; raydirection.z = .0f;
421 rayposition.x = -3.0f; rayposition.y = 0.0f; rayposition.z = 0.0f;
422 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection);
423 ok(result == TRUE, "expected TRUE, received FALSE\n");
425 /*____________Test the Sphere case________________________*/
426 radius = sqrt(77.0f);
427 center.x = 1.0f; center.y = 2.0f; center.z = 3.0f;
428 raydirection.x = 2.0f; raydirection.y = -4.0f; raydirection.z = 2.0f;
429 rayposition.x = 5.0f; rayposition.y = 5.0f; rayposition.z = 9.0f;
430 result = D3DXSphereBoundProbe(&center, radius, &rayposition, &raydirection);
431 ok(result == TRUE, "Got unexpected result %#x.\n", result);
433 rayposition.x = 45.0f; rayposition.y = -75.0f; rayposition.z = 49.0f;
434 result = D3DXSphereBoundProbe(&center, radius, &rayposition, &raydirection);
435 ok(result == FALSE, "Got unexpected result %#x.\n", result);
437 raydirection.x = -2.0f; raydirection.y = 4.0f; raydirection.z = -2.0f;
438 result = D3DXSphereBoundProbe(&center, radius, &rayposition, &raydirection);
439 ok(result == TRUE, "Got unexpected result %#x.\n", result);
441 rayposition.x = 5.0f; rayposition.y = 11.0f; rayposition.z = 9.0f;
442 result = D3DXSphereBoundProbe(&center, radius, &rayposition, &raydirection);
443 ok(result == FALSE, "Got unexpected result %#x.\n", result);
445 raydirection.x = 2.0f; raydirection.y = -4.0f; raydirection.z = 2.0f;
446 result = D3DXSphereBoundProbe(&center, radius, &rayposition, &raydirection);
447 ok(result == FALSE, "Got unexpected result %#x.\n", result);
449 radius = 1.0f;
450 rayposition.x = 2.0f; rayposition.y = 2.0f; rayposition.z = 3.0f;
451 result = D3DXSphereBoundProbe(&center, radius, &rayposition, &raydirection);
452 ok(result == FALSE, "Got unexpected result %#x.\n", result);
454 raydirection.x = 0.0f; raydirection.y = 0.0f; raydirection.z = 1.0f;
455 result = D3DXSphereBoundProbe(&center, radius, &rayposition, &raydirection);
456 ok(result == TRUE, "Got unexpected result %#x.\n", result);
458 if (0)
460 /* All these crash on native. */
461 D3DXSphereBoundProbe(&center, radius, &rayposition, NULL);
462 D3DXSphereBoundProbe(&center, radius, NULL, &raydirection);
463 D3DXSphereBoundProbe(NULL, radius, &rayposition, &raydirection);
467 static void D3DXComputeBoundingBoxTest(void)
469 D3DXVECTOR3 exp_max, exp_min, got_max, got_min, vertex[5];
470 HRESULT hr;
472 vertex[0].x = 1.0f; vertex[0].y = 1.0f; vertex[0].z = 1.0f;
473 vertex[1].x = 1.0f; vertex[1].y = 1.0f; vertex[1].z = 1.0f;
474 vertex[2].x = 1.0f; vertex[2].y = 1.0f; vertex[2].z = 1.0f;
475 vertex[3].x = 1.0f; vertex[3].y = 1.0f; vertex[3].z = 1.0f;
476 vertex[4].x = 9.0f; vertex[4].y = 9.0f; vertex[4].z = 9.0f;
478 exp_min.x = 1.0f; exp_min.y = 1.0f; exp_min.z = 1.0f;
479 exp_max.x = 9.0f; exp_max.y = 9.0f; exp_max.z = 9.0f;
481 hr = D3DXComputeBoundingBox(&vertex[3],2,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_min,&got_max);
483 ok( hr == D3D_OK, "Expected D3D_OK, got %#lx\n", hr);
484 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);
485 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);
487 /*________________________*/
489 vertex[0].x = 2.0f; vertex[0].y = 5.9f; vertex[0].z = -1.2f;
490 vertex[1].x = -1.87f; vertex[1].y = 7.9f; vertex[1].z = 7.4f;
491 vertex[2].x = 7.43f; vertex[2].y = -0.9f; vertex[2].z = 11.9f;
492 vertex[3].x = -6.92f; vertex[3].y = 6.3f; vertex[3].z = -3.8f;
493 vertex[4].x = 11.4f; vertex[4].y = -8.1f; vertex[4].z = 4.5f;
495 exp_min.x = -6.92f; exp_min.y = -8.1f; exp_min.z = -3.80f;
496 exp_max.x = 11.4f; exp_max.y = 7.90f; exp_max.z = 11.9f;
498 hr = D3DXComputeBoundingBox(&vertex[0],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_min,&got_max);
500 ok( hr == D3D_OK, "Expected D3D_OK, got %#lx\n", hr);
501 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);
502 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);
504 /*________________________*/
506 vertex[0].x = 2.0f; vertex[0].y = 5.9f; vertex[0].z = -1.2f;
507 vertex[1].x = -1.87f; vertex[1].y = 7.9f; vertex[1].z = 7.4f;
508 vertex[2].x = 7.43f; vertex[2].y = -0.9f; vertex[2].z = 11.9f;
509 vertex[3].x = -6.92f; vertex[3].y = 6.3f; vertex[3].z = -3.8f;
510 vertex[4].x = 11.4f; vertex[4].y = -8.1f; vertex[4].z = 4.5f;
512 exp_min.x = -6.92f; exp_min.y = -0.9f; exp_min.z = -3.8f;
513 exp_max.x = 7.43f; exp_max.y = 7.90f; exp_max.z = 11.9f;
515 hr = D3DXComputeBoundingBox(&vertex[0],4,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_min,&got_max);
517 ok( hr == D3D_OK, "Expected D3D_OK, got %#lx\n", hr);
518 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);
519 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);
521 /*________________________*/
522 hr = D3DXComputeBoundingBox(NULL,5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_min,&got_max);
523 ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#lx\n", hr);
525 /*________________________*/
526 hr = D3DXComputeBoundingBox(&vertex[3],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),NULL,&got_max);
527 ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#lx\n", hr);
529 /*________________________*/
530 hr = D3DXComputeBoundingBox(&vertex[3],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_min,NULL);
531 ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#lx\n", hr);
534 static void D3DXComputeBoundingSphereTest(void)
536 D3DXVECTOR3 exp_cen, got_cen, vertex[5];
537 FLOAT exp_rad, got_rad;
538 HRESULT hr;
540 vertex[0].x = 1.0f; vertex[0].y = 1.0f; vertex[0].z = 1.0f;
541 vertex[1].x = 1.0f; vertex[1].y = 1.0f; vertex[1].z = 1.0f;
542 vertex[2].x = 1.0f; vertex[2].y = 1.0f; vertex[2].z = 1.0f;
543 vertex[3].x = 1.0f; vertex[3].y = 1.0f; vertex[3].z = 1.0f;
544 vertex[4].x = 9.0f; vertex[4].y = 9.0f; vertex[4].z = 9.0f;
546 exp_rad = 6.928203f;
547 exp_cen.x = 5.0; exp_cen.y = 5.0; exp_cen.z = 5.0;
549 hr = D3DXComputeBoundingSphere(&vertex[3],2,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_cen,&got_rad);
551 ok( hr == D3D_OK, "Expected D3D_OK, got %#lx\n", hr);
552 ok( compare(exp_rad, got_rad), "Expected radius: %f, got radius: %f\n", exp_rad, got_rad);
553 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);
555 /*________________________*/
557 vertex[0].x = 2.0f; vertex[0].y = 5.9f; vertex[0].z = -1.2f;
558 vertex[1].x = -1.87f; vertex[1].y = 7.9f; vertex[1].z = 7.4f;
559 vertex[2].x = 7.43f; vertex[2].y = -0.9f; vertex[2].z = 11.9f;
560 vertex[3].x = -6.92f; vertex[3].y = 6.3f; vertex[3].z = -3.8f;
561 vertex[4].x = 11.4f; vertex[4].y = -8.1f; vertex[4].z = 4.5f;
563 exp_rad = 13.707883f;
564 exp_cen.x = 2.408f; exp_cen.y = 2.22f; exp_cen.z = 3.76f;
566 hr = D3DXComputeBoundingSphere(&vertex[0],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_cen,&got_rad);
568 ok( hr == D3D_OK, "Expected D3D_OK, got %#lx\n", hr);
569 ok( compare(exp_rad, got_rad), "Expected radius: %f, got radius: %f\n", exp_rad, got_rad);
570 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);
572 /*________________________*/
573 hr = D3DXComputeBoundingSphere(NULL,5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_cen,&got_rad);
574 ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#lx\n", hr);
576 /*________________________*/
577 hr = D3DXComputeBoundingSphere(&vertex[3],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),NULL,&got_rad);
578 ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#lx\n", hr);
580 /*________________________*/
581 hr = D3DXComputeBoundingSphere(&vertex[3],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_cen,NULL);
582 ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#lx\n", hr);
585 static void print_elements(const D3DVERTEXELEMENT9 *elements)
587 D3DVERTEXELEMENT9 last = D3DDECL_END();
588 const D3DVERTEXELEMENT9 *ptr = elements;
589 int count = 0;
591 while (memcmp(ptr, &last, sizeof(D3DVERTEXELEMENT9)))
593 trace(
594 "[Element %d] Stream = %d, Offset = %d, Type = %d, Method = %d, Usage = %d, UsageIndex = %d\n",
595 count, ptr->Stream, ptr->Offset, ptr->Type, ptr->Method, ptr->Usage, ptr->UsageIndex);
596 ptr++;
597 count++;
601 static void compare_elements(const D3DVERTEXELEMENT9 *elements, const D3DVERTEXELEMENT9 *expected_elements,
602 unsigned int line, unsigned int test_id)
604 D3DVERTEXELEMENT9 last = D3DDECL_END();
605 unsigned int i;
607 for (i = 0; i < MAX_FVF_DECL_SIZE; i++)
609 int end1 = memcmp(&elements[i], &last, sizeof(last));
610 int end2 = memcmp(&expected_elements[i], &last, sizeof(last));
611 int status;
613 if (!end1 && !end2) break;
615 status = !end1 ^ !end2;
616 ok(!status, "Line %u, test %u: Mismatch in size, test declaration is %s than expected.\n",
617 line, test_id, end1 ? "shorter" : "longer");
618 if (status)
620 print_elements(elements);
621 break;
624 status = memcmp(&elements[i], &expected_elements[i], sizeof(D3DVERTEXELEMENT9));
625 ok(!status, "Line %u, test %u: Mismatch in element %u.\n", line, test_id, i);
626 if (status)
628 print_elements(elements);
629 break;
634 static void test_fvf_to_decl(DWORD test_fvf, const D3DVERTEXELEMENT9 expected_elements[],
635 HRESULT expected_hr, unsigned int line, unsigned int test_id)
637 HRESULT hr;
638 D3DVERTEXELEMENT9 decl[MAX_FVF_DECL_SIZE];
640 hr = D3DXDeclaratorFromFVF(test_fvf, decl);
641 ok(hr == expected_hr,
642 "Line %u, test %u: D3DXDeclaratorFromFVF returned %#lx, expected %#lx.\n",
643 line, test_id, hr, expected_hr);
644 if (SUCCEEDED(hr)) compare_elements(decl, expected_elements, line, test_id);
647 static void test_decl_to_fvf(const D3DVERTEXELEMENT9 *decl, DWORD expected_fvf,
648 HRESULT expected_hr, unsigned int line, unsigned int test_id)
650 HRESULT hr;
651 DWORD result_fvf = 0xdeadbeef;
653 hr = D3DXFVFFromDeclarator(decl, &result_fvf);
654 ok(hr == expected_hr,
655 "Line %u, test %u: D3DXFVFFromDeclarator returned %#lx, expected %#lx.\n",
656 line, test_id, hr, expected_hr);
657 if (SUCCEEDED(hr))
659 ok(expected_fvf == result_fvf, "Line %u, test %u: Got FVF %#lx, expected %#lx.\n",
660 line, test_id, result_fvf, expected_fvf);
664 static void test_fvf_decl_conversion(void)
666 static const struct
668 D3DVERTEXELEMENT9 decl[MAXD3DDECLLENGTH + 1];
669 DWORD fvf;
671 test_data[] =
674 D3DDECL_END(),
675 }, 0},
677 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
678 D3DDECL_END(),
679 }, D3DFVF_XYZ},
681 {0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITIONT, 0},
682 D3DDECL_END(),
683 }, D3DFVF_XYZRHW},
685 {0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITIONT, 0},
686 D3DDECL_END(),
687 }, D3DFVF_XYZRHW},
689 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
690 {0, 12, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
691 D3DDECL_END(),
692 }, D3DFVF_XYZB1},
694 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
695 {0, 12, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
696 D3DDECL_END(),
697 }, D3DFVF_XYZB1 | D3DFVF_LASTBETA_UBYTE4},
699 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
700 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
701 D3DDECL_END(),
702 }, D3DFVF_XYZB1 | D3DFVF_LASTBETA_D3DCOLOR},
704 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
705 {0, 12, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
706 D3DDECL_END(),
707 }, D3DFVF_XYZB2},
709 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
710 {0, 12, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
711 {0, 16, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
712 D3DDECL_END(),
713 }, D3DFVF_XYZB2 | D3DFVF_LASTBETA_UBYTE4},
715 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
716 {0, 12, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
717 {0, 16, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
718 D3DDECL_END(),
719 }, D3DFVF_XYZB2 | D3DFVF_LASTBETA_D3DCOLOR},
721 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
722 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
723 D3DDECL_END(),
724 }, D3DFVF_XYZB3},
726 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
727 {0, 12, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
728 {0, 20, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
729 D3DDECL_END(),
730 }, D3DFVF_XYZB3 | D3DFVF_LASTBETA_UBYTE4},
732 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
733 {0, 12, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
734 {0, 20, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
735 D3DDECL_END(),
736 }, D3DFVF_XYZB3 | D3DFVF_LASTBETA_D3DCOLOR},
738 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
739 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
740 D3DDECL_END(),
741 }, D3DFVF_XYZB4},
743 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
744 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
745 {0, 24, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
746 D3DDECL_END(),
747 }, D3DFVF_XYZB4 | D3DFVF_LASTBETA_UBYTE4},
749 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
750 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
751 {0, 24, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
752 D3DDECL_END(),
753 }, D3DFVF_XYZB4 | D3DFVF_LASTBETA_D3DCOLOR},
755 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
756 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
757 {0, 28, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
758 D3DDECL_END(),
759 }, D3DFVF_XYZB5 | D3DFVF_LASTBETA_UBYTE4},
761 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
762 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
763 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
764 D3DDECL_END(),
765 }, D3DFVF_XYZB5 | D3DFVF_LASTBETA_D3DCOLOR},
767 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
768 D3DDECL_END(),
769 }, D3DFVF_NORMAL},
771 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
772 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
773 D3DDECL_END(),
774 }, D3DFVF_NORMAL | D3DFVF_DIFFUSE},
776 {0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_PSIZE, 0},
777 D3DDECL_END(),
778 }, D3DFVF_PSIZE},
780 {0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
781 D3DDECL_END(),
782 }, D3DFVF_DIFFUSE},
784 {0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1},
785 D3DDECL_END(),
786 }, D3DFVF_SPECULAR},
787 /* Make sure textures of different sizes work. */
789 {0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
790 D3DDECL_END(),
791 }, D3DFVF_TEXCOORDSIZE1(0) | D3DFVF_TEX1},
793 {0, 0, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 0},
794 D3DDECL_END(),
795 }, D3DFVF_TEXCOORDSIZE2(0) | D3DFVF_TEX1},
797 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 0},
798 D3DDECL_END(),
799 }, D3DFVF_TEXCOORDSIZE3(0) | D3DFVF_TEX1},
801 {0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 0},
802 D3DDECL_END(),
803 }, D3DFVF_TEXCOORDSIZE4(0) | D3DFVF_TEX1},
804 /* Make sure the TEXCOORD index works correctly - try several textures. */
806 {0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
807 {0, 4, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 1},
808 {0, 16, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 2},
809 {0, 24, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 3},
810 D3DDECL_END(),
811 }, D3DFVF_TEX4 | D3DFVF_TEXCOORDSIZE1(0) | D3DFVF_TEXCOORDSIZE3(1)
812 | D3DFVF_TEXCOORDSIZE2(2) | D3DFVF_TEXCOORDSIZE4(3)},
813 /* Now try some combination tests. */
815 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
816 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
817 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
818 {0, 32, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1},
819 {0, 36, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 0},
820 {0, 44, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 1},
821 D3DDECL_END(),
822 }, D3DFVF_XYZB4 | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_TEX2
823 | D3DFVF_TEXCOORDSIZE2(0) | D3DFVF_TEXCOORDSIZE3(1)},
825 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
826 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
827 {0, 24, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_PSIZE, 0},
828 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1},
829 {0, 32, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
830 {0, 36, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 1},
831 D3DDECL_END(),
832 }, D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_PSIZE | D3DFVF_SPECULAR | D3DFVF_TEX2
833 | D3DFVF_TEXCOORDSIZE1(0) | D3DFVF_TEXCOORDSIZE4(1)},
835 unsigned int i;
837 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
839 test_decl_to_fvf(test_data[i].decl, test_data[i].fvf, D3D_OK, __LINE__, i);
840 test_fvf_to_decl(test_data[i].fvf, test_data[i].decl, D3D_OK, __LINE__, i);
843 /* Usage indices for position and normal are apparently ignored. */
845 const D3DVERTEXELEMENT9 decl[] =
847 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 1},
848 D3DDECL_END(),
850 test_decl_to_fvf(decl, D3DFVF_XYZ, D3D_OK, __LINE__, 0);
853 const D3DVERTEXELEMENT9 decl[] =
855 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 1},
856 D3DDECL_END(),
858 test_decl_to_fvf(decl, D3DFVF_NORMAL, D3D_OK, __LINE__, 0);
860 /* D3DFVF_LASTBETA_UBYTE4 and D3DFVF_LASTBETA_D3DCOLOR are ignored if
861 * there are no blend matrices. */
863 const D3DVERTEXELEMENT9 decl[] =
865 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
866 D3DDECL_END(),
868 test_fvf_to_decl(D3DFVF_XYZ | D3DFVF_LASTBETA_UBYTE4, decl, D3D_OK, __LINE__, 0);
871 const D3DVERTEXELEMENT9 decl[] =
873 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
874 D3DDECL_END(),
876 test_fvf_to_decl(D3DFVF_XYZ | D3DFVF_LASTBETA_D3DCOLOR, decl, D3D_OK, __LINE__, 0);
878 /* D3DFVF_LASTBETA_UBYTE4 takes precedence over D3DFVF_LASTBETA_D3DCOLOR. */
880 const D3DVERTEXELEMENT9 decl[] =
882 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
883 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
884 {0, 28, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
885 D3DDECL_END(),
887 test_fvf_to_decl(D3DFVF_XYZB5 | D3DFVF_LASTBETA_D3DCOLOR | D3DFVF_LASTBETA_UBYTE4,
888 decl, D3D_OK, __LINE__, 0);
890 /* These are supposed to fail, both ways. */
892 const D3DVERTEXELEMENT9 decl[] =
894 {0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITION, 0},
895 D3DDECL_END(),
897 test_decl_to_fvf(decl, D3DFVF_XYZW, D3DERR_INVALIDCALL, __LINE__, 0);
898 test_fvf_to_decl(D3DFVF_XYZW, decl, D3DERR_INVALIDCALL, __LINE__, 0);
901 const D3DVERTEXELEMENT9 decl[] =
903 {0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITION, 0},
904 {0, 16, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
905 D3DDECL_END(),
907 test_decl_to_fvf(decl, D3DFVF_XYZW | D3DFVF_NORMAL, D3DERR_INVALIDCALL, __LINE__, 0);
908 test_fvf_to_decl(D3DFVF_XYZW | D3DFVF_NORMAL, decl, D3DERR_INVALIDCALL, __LINE__, 0);
911 const D3DVERTEXELEMENT9 decl[] =
913 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
914 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
915 {0, 28, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDINDICES, 0},
916 D3DDECL_END(),
918 test_decl_to_fvf(decl, D3DFVF_XYZB5, D3DERR_INVALIDCALL, __LINE__, 0);
919 test_fvf_to_decl(D3DFVF_XYZB5, decl, D3DERR_INVALIDCALL, __LINE__, 0);
921 /* Test a declaration that can't be converted to an FVF. */
923 const D3DVERTEXELEMENT9 decl[] =
925 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
926 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
927 {0, 24, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_PSIZE, 0},
928 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1},
929 {0, 32, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
930 /* 8 bytes padding */
931 {0, 44, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 1},
932 D3DDECL_END(),
934 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0);
936 /* Elements must be ordered by offset. */
938 const D3DVERTEXELEMENT9 decl[] =
940 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
941 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
942 D3DDECL_END(),
944 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0);
946 /* Basic tests for element order. */
948 const D3DVERTEXELEMENT9 decl[] =
950 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
951 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
952 {0, 16, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
953 D3DDECL_END(),
955 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0);
958 const D3DVERTEXELEMENT9 decl[] =
960 {0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
961 {0, 4, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
962 D3DDECL_END(),
964 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0);
967 const D3DVERTEXELEMENT9 decl[] =
969 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
970 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
971 D3DDECL_END(),
973 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0);
975 /* Textures must be ordered by texcoords. */
977 const D3DVERTEXELEMENT9 decl[] =
979 {0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
980 {0, 4, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 2},
981 {0, 16, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 1},
982 {0, 24, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 3},
983 D3DDECL_END(),
985 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0);
987 /* Duplicate elements are not allowed. */
989 const D3DVERTEXELEMENT9 decl[] =
991 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
992 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
993 {0, 16, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
994 D3DDECL_END(),
996 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0);
998 /* Invalid FVFs cannot be converted to a declarator. */
999 test_fvf_to_decl(0xdeadbeef, NULL, D3DERR_INVALIDCALL, __LINE__, 0);
1002 static void D3DXGetFVFVertexSizeTest(void)
1004 UINT got;
1006 compare_vertex_sizes (D3DFVF_XYZ, 12);
1008 compare_vertex_sizes (D3DFVF_XYZB3, 24);
1010 compare_vertex_sizes (D3DFVF_XYZB5, 32);
1012 compare_vertex_sizes (D3DFVF_XYZ | D3DFVF_NORMAL, 24);
1014 compare_vertex_sizes (D3DFVF_XYZ | D3DFVF_DIFFUSE, 16);
1016 compare_vertex_sizes (
1017 D3DFVF_XYZ |
1018 D3DFVF_TEX1 |
1019 D3DFVF_TEXCOORDSIZE1(0), 16);
1020 compare_vertex_sizes (
1021 D3DFVF_XYZ |
1022 D3DFVF_TEX2 |
1023 D3DFVF_TEXCOORDSIZE1(0) |
1024 D3DFVF_TEXCOORDSIZE1(1), 20);
1026 compare_vertex_sizes (
1027 D3DFVF_XYZ |
1028 D3DFVF_TEX1 |
1029 D3DFVF_TEXCOORDSIZE2(0), 20);
1031 compare_vertex_sizes (
1032 D3DFVF_XYZ |
1033 D3DFVF_TEX2 |
1034 D3DFVF_TEXCOORDSIZE2(0) |
1035 D3DFVF_TEXCOORDSIZE2(1), 28);
1037 compare_vertex_sizes (
1038 D3DFVF_XYZ |
1039 D3DFVF_TEX6 |
1040 D3DFVF_TEXCOORDSIZE2(0) |
1041 D3DFVF_TEXCOORDSIZE2(1) |
1042 D3DFVF_TEXCOORDSIZE2(2) |
1043 D3DFVF_TEXCOORDSIZE2(3) |
1044 D3DFVF_TEXCOORDSIZE2(4) |
1045 D3DFVF_TEXCOORDSIZE2(5), 60);
1047 compare_vertex_sizes (
1048 D3DFVF_XYZ |
1049 D3DFVF_TEX8 |
1050 D3DFVF_TEXCOORDSIZE2(0) |
1051 D3DFVF_TEXCOORDSIZE2(1) |
1052 D3DFVF_TEXCOORDSIZE2(2) |
1053 D3DFVF_TEXCOORDSIZE2(3) |
1054 D3DFVF_TEXCOORDSIZE2(4) |
1055 D3DFVF_TEXCOORDSIZE2(5) |
1056 D3DFVF_TEXCOORDSIZE2(6) |
1057 D3DFVF_TEXCOORDSIZE2(7), 76);
1059 compare_vertex_sizes (
1060 D3DFVF_XYZ |
1061 D3DFVF_TEX1 |
1062 D3DFVF_TEXCOORDSIZE3(0), 24);
1064 compare_vertex_sizes (
1065 D3DFVF_XYZ |
1066 D3DFVF_TEX4 |
1067 D3DFVF_TEXCOORDSIZE3(0) |
1068 D3DFVF_TEXCOORDSIZE3(1) |
1069 D3DFVF_TEXCOORDSIZE3(2) |
1070 D3DFVF_TEXCOORDSIZE3(3), 60);
1072 compare_vertex_sizes (
1073 D3DFVF_XYZ |
1074 D3DFVF_TEX1 |
1075 D3DFVF_TEXCOORDSIZE4(0), 28);
1077 compare_vertex_sizes (
1078 D3DFVF_XYZ |
1079 D3DFVF_TEX2 |
1080 D3DFVF_TEXCOORDSIZE4(0) |
1081 D3DFVF_TEXCOORDSIZE4(1), 44);
1083 compare_vertex_sizes (
1084 D3DFVF_XYZ |
1085 D3DFVF_TEX3 |
1086 D3DFVF_TEXCOORDSIZE4(0) |
1087 D3DFVF_TEXCOORDSIZE4(1) |
1088 D3DFVF_TEXCOORDSIZE4(2), 60);
1090 compare_vertex_sizes (
1091 D3DFVF_XYZB5 |
1092 D3DFVF_NORMAL |
1093 D3DFVF_DIFFUSE |
1094 D3DFVF_SPECULAR |
1095 D3DFVF_TEX8 |
1096 D3DFVF_TEXCOORDSIZE4(0) |
1097 D3DFVF_TEXCOORDSIZE4(1) |
1098 D3DFVF_TEXCOORDSIZE4(2) |
1099 D3DFVF_TEXCOORDSIZE4(3) |
1100 D3DFVF_TEXCOORDSIZE4(4) |
1101 D3DFVF_TEXCOORDSIZE4(5) |
1102 D3DFVF_TEXCOORDSIZE4(6) |
1103 D3DFVF_TEXCOORDSIZE4(7), 180);
1106 static void D3DXIntersectTriTest(void)
1108 BOOL exp_res, got_res;
1109 D3DXVECTOR3 position, ray, vertex[3];
1110 FLOAT exp_dist, got_dist, exp_u, got_u, exp_v, got_v;
1112 vertex[0].x = 1.0f; vertex[0].y = 0.0f; vertex[0].z = 0.0f;
1113 vertex[1].x = 2.0f; vertex[1].y = 0.0f; vertex[1].z = 0.0f;
1114 vertex[2].x = 1.0f; vertex[2].y = 1.0f; vertex[2].z = 0.0f;
1116 position.x = -14.5f; position.y = -23.75f; position.z = -32.0f;
1118 ray.x = 2.0f; ray.y = 3.0f; ray.z = 4.0f;
1120 exp_res = TRUE; exp_u = 0.5f; exp_v = 0.25f; exp_dist = 8.0f;
1122 got_res = D3DXIntersectTri(&vertex[0], &vertex[1], &vertex[2], &position, &ray, &got_u, &got_v, &got_dist);
1123 ok(got_res == exp_res, "Expected result %d, got %d.\n", exp_res, got_res);
1124 ok(compare(exp_u, got_u), "Expected u %f, got %f.\n", exp_u, got_u);
1125 ok(compare(exp_v, got_v), "Expected v %f, got %f.\n", exp_v, got_v);
1126 ok(compare(exp_dist, got_dist), "Expected distance %f, got %f.\n", exp_dist, got_dist);
1128 got_res = D3DXIntersectTri(&vertex[0], &vertex[1], &vertex[2], &position, &ray, NULL, NULL, NULL);
1129 ok(got_res == exp_res, "Expected result %d, got %d.\n", exp_res, got_res);
1131 vertex[2].x = 1.0f; vertex[2].y = 0.0f; vertex[2].z = 0.0f;
1132 vertex[1].x = 2.0f; vertex[1].y = 0.0f; vertex[1].z = 0.0f;
1133 vertex[0].x = 1.0f; vertex[0].y = 1.0f; vertex[0].z = 0.0f;
1135 got_u = got_v = got_dist = 0.0f;
1136 got_res = D3DXIntersectTri(&vertex[0], &vertex[1], &vertex[2], &position, &ray, &got_u, &got_v, &got_dist);
1137 ok(got_res == exp_res, "Expected result %d, got %d.\n", exp_res, got_res);
1138 ok(compare(exp_u, got_u), "Expected u %f, got %f.\n", exp_u, got_u);
1139 ok(compare(exp_v, got_v), "Expected v %f, got %f.\n", exp_v, got_v);
1140 ok(compare(exp_dist, got_dist), "Expected distance %f, got %f.\n", exp_dist, got_dist);
1142 vertex[2].x = 1.0f; vertex[2].y = 0.0f; vertex[2].z = 0.0f;
1143 vertex[1].x = 2.0f; vertex[1].y = 0.0f; vertex[1].z = -0.5f;
1144 vertex[0].x = 1.0f; vertex[0].y = 1.0f; vertex[0].z = -1.0f;
1145 exp_u = 0.375f;
1146 exp_v = 0.5625f;
1147 exp_dist = 7.9375f;
1148 got_u = got_v = got_dist = 0.0f;
1149 got_res = D3DXIntersectTri(&vertex[0], &vertex[1], &vertex[2], &position, &ray, &got_u, &got_v, &got_dist);
1150 ok(got_res == exp_res, "Expected result %d, got %d.\n", exp_res, got_res);
1151 ok(compare(exp_u, got_u), "Expected u %f, got %f.\n", exp_u, got_u);
1152 ok(compare(exp_v, got_v), "Expected v %f, got %f.\n", exp_v, got_v);
1153 ok(compare(exp_dist, got_dist), "Expected distance %f, got %f.\n", exp_dist, got_dist);
1156 /*Only positive ray is taken in account*/
1158 vertex[0].x = 1.0f; vertex[0].y = 0.0f; vertex[0].z = 0.0f;
1159 vertex[1].x = 2.0f; vertex[1].y = 0.0f; vertex[1].z = 0.0f;
1160 vertex[2].x = 1.0f; vertex[2].y = 1.0f; vertex[2].z = 0.0f;
1162 position.x = 17.5f; position.y = 24.25f; position.z = 32.0f;
1164 ray.x = 2.0f; ray.y = 3.0f; ray.z = 4.0f;
1166 exp_res = FALSE;
1168 got_res = D3DXIntersectTri(&vertex[0],&vertex[1],&vertex[2],&position,&ray,&got_u,&got_v,&got_dist);
1169 ok( got_res == exp_res, "Expected result = %d, got %d\n",exp_res,got_res);
1171 got_res = D3DXIntersectTri(&vertex[0], &vertex[1], &vertex[2], &position, &ray, NULL, NULL, NULL);
1172 ok(got_res == exp_res, "Expected result = %d, got %d\n", exp_res, got_res);
1174 /*Intersection between ray and triangle in a same plane is considered as empty*/
1176 vertex[0].x = 4.0f; vertex[0].y = 0.0f; vertex[0].z = 0.0f;
1177 vertex[1].x = 6.0f; vertex[1].y = 0.0f; vertex[1].z = 0.0f;
1178 vertex[2].x = 4.0f; vertex[2].y = 2.0f; vertex[2].z = 0.0f;
1180 position.x = 1.0f; position.y = 1.0f; position.z = 0.0f;
1182 ray.x = 1.0f; ray.y = 0.0f; ray.z = 0.0f;
1184 exp_res = FALSE;
1186 got_res = D3DXIntersectTri(&vertex[0],&vertex[1],&vertex[2],&position,&ray,&got_u,&got_v,&got_dist);
1187 ok( got_res == exp_res, "Expected result = %d, got %d\n",exp_res,got_res);
1189 got_res = D3DXIntersectTri(&vertex[0], &vertex[1], &vertex[2], &position, &ray, NULL, NULL, NULL);
1190 ok(got_res == exp_res, "Expected result = %d, got %d\n", exp_res, got_res);
1193 static void D3DXCreateMeshTest(void)
1195 HRESULT hr;
1196 IDirect3DDevice9 *device, *test_device;
1197 ID3DXMesh *d3dxmesh;
1198 int i, size;
1199 D3DVERTEXELEMENT9 test_decl[MAX_FVF_DECL_SIZE];
1200 DWORD options;
1201 struct mesh mesh;
1202 struct test_context *test_context;
1204 static const D3DVERTEXELEMENT9 decl1[] =
1206 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1207 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
1208 D3DDECL_END(),
1211 static const D3DVERTEXELEMENT9 decl2[] =
1213 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1214 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
1215 {0, 24, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_PSIZE, 0},
1216 {0, 28, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 1},
1217 {0, 32, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
1218 /* 8 bytes padding */
1219 {0, 44, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
1220 D3DDECL_END(),
1223 static const D3DVERTEXELEMENT9 decl3[] =
1225 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1226 {1, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
1227 D3DDECL_END(),
1230 hr = D3DXCreateMesh(0, 0, 0, NULL, NULL, NULL);
1231 ok(hr == D3DERR_INVALIDCALL, "Got result %lx, expected %lx (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1233 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl1, NULL, &d3dxmesh);
1234 ok(hr == D3DERR_INVALIDCALL, "Got result %lx, expected %lx (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1236 test_context = new_test_context();
1237 if (!test_context)
1239 skip("Couldn't create test context\n");
1240 return;
1242 device = test_context->device;
1244 hr = D3DXCreateMesh(0, 3, D3DXMESH_MANAGED, decl1, device, &d3dxmesh);
1245 ok(hr == D3DERR_INVALIDCALL, "Got result %lx, expected %lx (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1247 hr = D3DXCreateMesh(1, 0, D3DXMESH_MANAGED, decl1, device, &d3dxmesh);
1248 ok(hr == D3DERR_INVALIDCALL, "Got result %lx, expected %lx (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1250 hr = D3DXCreateMesh(1, 3, 0, decl1, device, &d3dxmesh);
1251 ok(hr == D3D_OK, "Got result %lx, expected %lx (D3D_OK)\n", hr, D3D_OK);
1253 if (hr == D3D_OK)
1255 d3dxmesh->lpVtbl->Release(d3dxmesh);
1258 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, 0, device, &d3dxmesh);
1259 ok(hr == D3DERR_INVALIDCALL, "Got result %lx, expected %lx (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1261 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl1, device, NULL);
1262 ok(hr == D3DERR_INVALIDCALL, "Got result %lx, expected %lx (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1264 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl1, device, &d3dxmesh);
1265 ok(hr == D3D_OK, "Got result %lx, expected 0 (D3D_OK)\n", hr);
1267 if (hr == D3D_OK)
1269 /* device */
1270 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, NULL);
1271 ok(hr == D3DERR_INVALIDCALL, "Got result %lx, expected %lx (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1273 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, &test_device);
1274 ok(hr == D3D_OK, "Got result %lx, expected %lx (D3D_OK)\n", hr, D3D_OK);
1275 ok(test_device == device, "Got result %p, expected %p\n", test_device, device);
1277 if (hr == D3D_OK)
1279 IDirect3DDevice9_Release(device);
1282 /* declaration */
1283 hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, NULL);
1284 ok(hr == D3DERR_INVALIDCALL, "Got result %lx, expected %lx (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1286 hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, test_decl);
1287 ok(hr == D3D_OK, "Got result %lx, expected 0 (D3D_OK)\n", hr);
1289 if (hr == D3D_OK)
1291 size = ARRAY_SIZE(decl1);
1292 for (i = 0; i < size - 1; i++)
1294 ok(test_decl[i].Stream == decl1[i].Stream, "Returned stream %d, expected %d\n", test_decl[i].Stream, decl1[i].Stream);
1295 ok(test_decl[i].Type == decl1[i].Type, "Returned type %d, expected %d\n", test_decl[i].Type, decl1[i].Type);
1296 ok(test_decl[i].Method == decl1[i].Method, "Returned method %d, expected %d\n", test_decl[i].Method, decl1[i].Method);
1297 ok(test_decl[i].Usage == decl1[i].Usage, "Returned usage %d, expected %d\n", test_decl[i].Usage, decl1[i].Usage);
1298 ok(test_decl[i].UsageIndex == decl1[i].UsageIndex, "Returned usage index %d, expected %d\n", test_decl[i].UsageIndex, decl1[i].UsageIndex);
1299 ok(test_decl[i].Offset == decl1[i].Offset, "Returned offset %d, expected %d\n", test_decl[i].Offset, decl1[i].Offset);
1301 ok(decl1[size-1].Stream == 0xFF, "Returned too long vertex declaration\n"); /* end element */
1304 /* options */
1305 options = d3dxmesh->lpVtbl->GetOptions(d3dxmesh);
1306 ok(options == D3DXMESH_MANAGED, "Got result %lx, expected %x (D3DXMESH_MANAGED)\n", options, D3DXMESH_MANAGED);
1308 /* rest */
1309 if (!new_mesh(&mesh, 3, 1))
1311 skip("Couldn't create mesh\n");
1313 else
1315 memset(mesh.vertices, 0, mesh.number_of_vertices * sizeof(*mesh.vertices));
1316 memset(mesh.faces, 0, mesh.number_of_faces * sizeof(*mesh.faces));
1317 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
1319 compare_mesh("createmesh1", d3dxmesh, &mesh);
1321 free_mesh(&mesh);
1324 d3dxmesh->lpVtbl->Release(d3dxmesh);
1327 /* Test a declaration that can't be converted to an FVF. */
1328 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl2, device, &d3dxmesh);
1329 ok(hr == D3D_OK, "Got result %lx, expected 0 (D3D_OK)\n", hr);
1331 if (hr == D3D_OK)
1333 /* device */
1334 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, NULL);
1335 ok(hr == D3DERR_INVALIDCALL, "Got result %lx, expected %lx (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1337 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, &test_device);
1338 ok(hr == D3D_OK, "Got result %lx, expected %lx (D3D_OK)\n", hr, D3D_OK);
1339 ok(test_device == device, "Got result %p, expected %p\n", test_device, device);
1341 if (hr == D3D_OK)
1343 IDirect3DDevice9_Release(device);
1346 /* declaration */
1347 hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, test_decl);
1348 ok(hr == D3D_OK, "Got result %lx, expected 0 (D3D_OK)\n", hr);
1350 if (hr == D3D_OK)
1352 size = ARRAY_SIZE(decl2);
1353 for (i = 0; i < size - 1; i++)
1355 ok(test_decl[i].Stream == decl2[i].Stream, "Returned stream %d, expected %d\n", test_decl[i].Stream, decl2[i].Stream);
1356 ok(test_decl[i].Type == decl2[i].Type, "Returned type %d, expected %d\n", test_decl[i].Type, decl2[i].Type);
1357 ok(test_decl[i].Method == decl2[i].Method, "Returned method %d, expected %d\n", test_decl[i].Method, decl2[i].Method);
1358 ok(test_decl[i].Usage == decl2[i].Usage, "Returned usage %d, expected %d\n", test_decl[i].Usage, decl2[i].Usage);
1359 ok(test_decl[i].UsageIndex == decl2[i].UsageIndex, "Returned usage index %d, expected %d\n", test_decl[i].UsageIndex, decl2[i].UsageIndex);
1360 ok(test_decl[i].Offset == decl2[i].Offset, "Returned offset %d, expected %d\n", test_decl[i].Offset, decl2[i].Offset);
1362 ok(decl2[size-1].Stream == 0xFF, "Returned too long vertex declaration\n"); /* end element */
1365 /* options */
1366 options = d3dxmesh->lpVtbl->GetOptions(d3dxmesh);
1367 ok(options == D3DXMESH_MANAGED, "Got result %lx, expected %x (D3DXMESH_MANAGED)\n", options, D3DXMESH_MANAGED);
1369 /* rest */
1370 if (!new_mesh(&mesh, 3, 1))
1372 skip("Couldn't create mesh\n");
1374 else
1376 memset(mesh.vertices, 0, mesh.number_of_vertices * sizeof(*mesh.vertices));
1377 memset(mesh.faces, 0, mesh.number_of_faces * sizeof(*mesh.faces));
1378 mesh.fvf = 0;
1379 mesh.vertex_size = 60;
1381 compare_mesh("createmesh2", d3dxmesh, &mesh);
1383 free_mesh(&mesh);
1386 mesh.vertex_size = d3dxmesh->lpVtbl->GetNumBytesPerVertex(d3dxmesh);
1387 ok(mesh.vertex_size == 60, "Got vertex size %u, expected %u\n", mesh.vertex_size, 60);
1389 d3dxmesh->lpVtbl->Release(d3dxmesh);
1392 /* Test a declaration with multiple streams. */
1393 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl3, device, &d3dxmesh);
1394 ok(hr == D3DERR_INVALIDCALL, "Got result %lx, expected %lx (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1396 free_test_context(test_context);
1399 static void D3DXCreateMeshFVFTest(void)
1401 HRESULT hr;
1402 IDirect3DDevice9 *device, *test_device;
1403 ID3DXMesh *d3dxmesh;
1404 int i, size;
1405 D3DVERTEXELEMENT9 test_decl[MAX_FVF_DECL_SIZE];
1406 DWORD options;
1407 struct mesh mesh;
1408 struct test_context *test_context;
1410 static const D3DVERTEXELEMENT9 decl[] =
1412 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1413 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
1414 D3DDECL_END(),
1417 hr = D3DXCreateMeshFVF(0, 0, 0, 0, NULL, NULL);
1418 ok(hr == D3DERR_INVALIDCALL, "Got result %lx, expected %lx (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1420 hr = D3DXCreateMeshFVF(1, 3, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, NULL, &d3dxmesh);
1421 ok(hr == D3DERR_INVALIDCALL, "Got result %lx, expected %lx (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1423 test_context = new_test_context();
1424 if (!test_context)
1426 skip("Couldn't create test context\n");
1427 return;
1429 device = test_context->device;
1431 hr = D3DXCreateMeshFVF(0, 3, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, device, &d3dxmesh);
1432 ok(hr == D3DERR_INVALIDCALL, "Got result %lx, expected %lx (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1434 hr = D3DXCreateMeshFVF(1, 0, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, device, &d3dxmesh);
1435 ok(hr == D3DERR_INVALIDCALL, "Got result %lx, expected %lx (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1437 hr = D3DXCreateMeshFVF(1, 3, 0, D3DFVF_XYZ | D3DFVF_NORMAL, device, &d3dxmesh);
1438 ok(hr == D3D_OK, "Got result %lx, expected %lx (D3D_OK)\n", hr, D3D_OK);
1440 if (hr == D3D_OK)
1442 d3dxmesh->lpVtbl->Release(d3dxmesh);
1445 hr = D3DXCreateMeshFVF(1, 3, D3DXMESH_MANAGED, 0xdeadbeef, device, &d3dxmesh);
1446 ok(hr == D3DERR_INVALIDCALL, "Got result %lx, expected %lx (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1448 hr = D3DXCreateMeshFVF(1, 3, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, device, NULL);
1449 ok(hr == D3DERR_INVALIDCALL, "Got result %lx, expected %lx (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1451 hr = D3DXCreateMeshFVF(1, 3, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, device, &d3dxmesh);
1452 ok(hr == D3D_OK, "Got result %lx, expected 0 (D3D_OK)\n", hr);
1454 if (hr == D3D_OK)
1456 /* device */
1457 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, NULL);
1458 ok(hr == D3DERR_INVALIDCALL, "Got result %lx, expected %lx (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1460 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, &test_device);
1461 ok(hr == D3D_OK, "Got result %lx, expected %lx (D3D_OK)\n", hr, D3D_OK);
1462 ok(test_device == device, "Got result %p, expected %p\n", test_device, device);
1464 if (hr == D3D_OK)
1466 IDirect3DDevice9_Release(device);
1469 /* declaration */
1470 hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, NULL);
1471 ok(hr == D3DERR_INVALIDCALL, "Got result %lx, expected %lx (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1473 hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, test_decl);
1474 ok(hr == D3D_OK, "Got result %lx, expected 0 (D3D_OK)\n", hr);
1476 if (hr == D3D_OK)
1478 size = ARRAY_SIZE(decl);
1479 for (i = 0; i < size - 1; i++)
1481 ok(test_decl[i].Stream == decl[i].Stream, "Returned stream %d, expected %d\n", test_decl[i].Stream, decl[i].Stream);
1482 ok(test_decl[i].Type == decl[i].Type, "Returned type %d, expected %d\n", test_decl[i].Type, decl[i].Type);
1483 ok(test_decl[i].Method == decl[i].Method, "Returned method %d, expected %d\n", test_decl[i].Method, decl[i].Method);
1484 ok(test_decl[i].Usage == decl[i].Usage, "Returned usage %d, expected %d\n", test_decl[i].Usage, decl[i].Usage);
1485 ok(test_decl[i].UsageIndex == decl[i].UsageIndex, "Returned usage index %d, expected %d\n",
1486 test_decl[i].UsageIndex, decl[i].UsageIndex);
1487 ok(test_decl[i].Offset == decl[i].Offset, "Returned offset %d, expected %d\n", test_decl[i].Offset, decl[i].Offset);
1489 ok(decl[size-1].Stream == 0xFF, "Returned too long vertex declaration\n"); /* end element */
1492 /* options */
1493 options = d3dxmesh->lpVtbl->GetOptions(d3dxmesh);
1494 ok(options == D3DXMESH_MANAGED, "Got result %lx, expected %x (D3DXMESH_MANAGED)\n", options, D3DXMESH_MANAGED);
1496 /* rest */
1497 if (!new_mesh(&mesh, 3, 1))
1499 skip("Couldn't create mesh\n");
1501 else
1503 memset(mesh.vertices, 0, mesh.number_of_vertices * sizeof(*mesh.vertices));
1504 memset(mesh.faces, 0, mesh.number_of_faces * sizeof(*mesh.faces));
1505 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
1507 compare_mesh("createmeshfvf", d3dxmesh, &mesh);
1509 free_mesh(&mesh);
1512 d3dxmesh->lpVtbl->Release(d3dxmesh);
1515 free_test_context(test_context);
1518 #define check_vertex_buffer(mesh, vertices, num_vertices, fvf) \
1519 check_vertex_buffer_(__LINE__, mesh, vertices, num_vertices, fvf)
1520 static void check_vertex_buffer_(int line, ID3DXMesh *mesh, const void *vertices, DWORD num_vertices, DWORD fvf)
1522 DWORD mesh_num_vertices = mesh->lpVtbl->GetNumVertices(mesh);
1523 DWORD mesh_fvf = mesh->lpVtbl->GetFVF(mesh);
1524 const void *mesh_vertices;
1525 HRESULT hr;
1527 ok_(__FILE__,line)(fvf == mesh_fvf, "expected FVF %lx, got %lx\n", fvf, mesh_fvf);
1528 ok_(__FILE__,line)(num_vertices == mesh_num_vertices,
1529 "Expected %lu vertices, got %lu\n", num_vertices, mesh_num_vertices);
1531 hr = mesh->lpVtbl->LockVertexBuffer(mesh, D3DLOCK_READONLY, (void**)&mesh_vertices);
1532 ok_(__FILE__,line)(hr == D3D_OK, "LockVertexBuffer returned %lx, expected %lx (D3D_OK)\n", hr, D3D_OK);
1533 if (FAILED(hr))
1534 return;
1536 if (mesh_fvf == fvf) {
1537 DWORD vertex_size = D3DXGetFVFVertexSize(fvf), i;
1539 for (i = 0; i < min(num_vertices, mesh_num_vertices); i++)
1541 const FLOAT *exp_float = vertices;
1542 const FLOAT *got_float = mesh_vertices;
1543 DWORD texcount;
1544 DWORD pos_dim = 0;
1545 int j;
1546 BOOL last_beta_dword = FALSE;
1547 char prefix[128];
1549 switch (fvf & D3DFVF_POSITION_MASK) {
1550 case D3DFVF_XYZ: pos_dim = 3; break;
1551 case D3DFVF_XYZRHW: pos_dim = 4; break;
1552 case D3DFVF_XYZB1:
1553 case D3DFVF_XYZB2:
1554 case D3DFVF_XYZB3:
1555 case D3DFVF_XYZB4:
1556 case D3DFVF_XYZB5:
1557 pos_dim = (fvf & D3DFVF_POSITION_MASK) - D3DFVF_XYZB1 + 1;
1558 if (fvf & (D3DFVF_LASTBETA_UBYTE4 | D3DFVF_LASTBETA_D3DCOLOR))
1560 pos_dim--;
1561 last_beta_dword = TRUE;
1563 break;
1564 case D3DFVF_XYZW: pos_dim = 4; break;
1566 sprintf(prefix, "vertex[%lu] position, ", i);
1567 check_floats_(line, prefix, got_float, exp_float, pos_dim);
1568 exp_float += pos_dim;
1569 got_float += pos_dim;
1571 if (last_beta_dword) {
1572 ok_(__FILE__,line)(*(DWORD*)exp_float == *(DWORD*)got_float,
1573 "Vertex[%lu]: Expected last beta %08lx, got %08lx\n", i, *(DWORD*)exp_float, *(DWORD*)got_float);
1574 exp_float++;
1575 got_float++;
1578 if (fvf & D3DFVF_NORMAL) {
1579 sprintf(prefix, "vertex[%lu] normal, ", i);
1580 check_floats_(line, prefix, got_float, exp_float, 3);
1581 exp_float += 3;
1582 got_float += 3;
1584 if (fvf & D3DFVF_PSIZE) {
1585 ok_(__FILE__,line)(compare(*exp_float, *got_float),
1586 "Vertex[%lu]: Expected psize %g, got %g\n", i, *exp_float, *got_float);
1587 exp_float++;
1588 got_float++;
1590 if (fvf & D3DFVF_DIFFUSE) {
1591 ok_(__FILE__,line)(*(DWORD*)exp_float == *(DWORD*)got_float,
1592 "Vertex[%lu]: Expected diffuse %08lx, got %08lx\n", i, *(DWORD*)exp_float, *(DWORD*)got_float);
1593 exp_float++;
1594 got_float++;
1596 if (fvf & D3DFVF_SPECULAR) {
1597 ok_(__FILE__,line)(*(DWORD*)exp_float == *(DWORD*)got_float,
1598 "Vertex[%lu]: Expected specular %08lx, got %08lx\n", i, *(DWORD*)exp_float, *(DWORD*)got_float);
1599 exp_float++;
1600 got_float++;
1603 texcount = (fvf & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
1604 for (j = 0; j < texcount; j++) {
1605 DWORD dim = (((fvf >> (16 + 2 * j)) + 1) & 0x03) + 1;
1606 sprintf(prefix, "vertex[%lu] texture, ", i);
1607 check_floats_(line, prefix, got_float, exp_float, dim);
1608 exp_float += dim;
1609 got_float += dim;
1612 vertices = (BYTE*)vertices + vertex_size;
1613 mesh_vertices = (BYTE*)mesh_vertices + vertex_size;
1617 mesh->lpVtbl->UnlockVertexBuffer(mesh);
1620 #define check_index_buffer(mesh, indices, num_indices, index_size) \
1621 check_index_buffer_(__LINE__, mesh, indices, num_indices, index_size)
1622 static void check_index_buffer_(int line, ID3DXMesh *mesh, const void *indices, DWORD num_indices, DWORD index_size)
1624 DWORD mesh_index_size = (mesh->lpVtbl->GetOptions(mesh) & D3DXMESH_32BIT) ? 4 : 2;
1625 DWORD mesh_num_indices = mesh->lpVtbl->GetNumFaces(mesh) * 3;
1626 const void *mesh_indices;
1627 HRESULT hr;
1628 DWORD i;
1630 ok_(__FILE__,line)(index_size == mesh_index_size,
1631 "Expected index size %lu, got %lu\n", index_size, mesh_index_size);
1632 ok_(__FILE__,line)(num_indices == mesh_num_indices,
1633 "Expected %lu indices, got %lu\n", num_indices, mesh_num_indices);
1635 hr = mesh->lpVtbl->LockIndexBuffer(mesh, D3DLOCK_READONLY, (void**)&mesh_indices);
1636 ok_(__FILE__,line)(hr == D3D_OK, "LockIndexBuffer returned %lx, expected %lx (D3D_OK)\n", hr, D3D_OK);
1637 if (FAILED(hr))
1638 return;
1640 if (mesh_index_size == index_size) {
1641 for (i = 0; i < min(num_indices, mesh_num_indices); i++)
1643 if (index_size == 4)
1644 ok_(__FILE__,line)(*(DWORD*)indices == *(DWORD*)mesh_indices,
1645 "Index[%lu]: expected %lu, got %lu\n", i, *(DWORD*)indices, *(DWORD*)mesh_indices);
1646 else
1647 ok_(__FILE__,line)(*(WORD*)indices == *(WORD*)mesh_indices,
1648 "Index[%lu]: expected %u, got %u\n", i, *(WORD*)indices, *(WORD*)mesh_indices);
1649 indices = (BYTE*)indices + index_size;
1650 mesh_indices = (BYTE*)mesh_indices + index_size;
1653 mesh->lpVtbl->UnlockIndexBuffer(mesh);
1656 #define check_matrix(got, expected) check_matrix_(__LINE__, got, expected)
1657 static void check_matrix_(int line, const D3DXMATRIX *got, const D3DXMATRIX *expected)
1659 int i, j;
1660 for (i = 0; i < 4; i++) {
1661 for (j = 0; j < 4; j++) {
1662 ok_(__FILE__,line)(compare(expected->m[i][j], got->m[i][j]),
1663 "matrix[%u][%u]: expected %g, got %g\n",
1664 i, j, expected->m[i][j], got->m[i][j]);
1669 static void check_colorvalue_(int line, const char *prefix, const D3DCOLORVALUE got, const D3DCOLORVALUE expected)
1671 ok_(__FILE__,line)(expected.r == got.r && expected.g == got.g && expected.b == got.b && expected.a == got.a,
1672 "%sExpected (%g, %g, %g, %g), got (%g, %g, %g, %g)\n", prefix,
1673 expected.r, expected.g, expected.b, expected.a, got.r, got.g, got.b, got.a);
1676 #define check_materials(got, got_count, expected, expected_count) \
1677 check_materials_(__LINE__, got, got_count, expected, expected_count)
1678 static void check_materials_(int line, const D3DXMATERIAL *got, DWORD got_count, const D3DXMATERIAL *expected, DWORD expected_count)
1680 int i;
1681 ok_(__FILE__,line)(expected_count == got_count, "Expected %lu materials, got %lu\n", expected_count, got_count);
1682 if (!expected) {
1683 ok_(__FILE__,line)(got == NULL, "Expected NULL material ptr, got %p\n", got);
1684 return;
1686 for (i = 0; i < min(expected_count, got_count); i++)
1688 if (!expected[i].pTextureFilename)
1689 ok_(__FILE__,line)(got[i].pTextureFilename == NULL,
1690 "Expected NULL pTextureFilename, got %p\n", got[i].pTextureFilename);
1691 else
1692 ok_(__FILE__,line)(!strcmp(expected[i].pTextureFilename, got[i].pTextureFilename),
1693 "Expected '%s' for pTextureFilename, got '%s'\n", expected[i].pTextureFilename, got[i].pTextureFilename);
1694 check_colorvalue_(line, "Diffuse: ", got[i].MatD3D.Diffuse, expected[i].MatD3D.Diffuse);
1695 check_colorvalue_(line, "Ambient: ", got[i].MatD3D.Ambient, expected[i].MatD3D.Ambient);
1696 check_colorvalue_(line, "Specular: ", got[i].MatD3D.Specular, expected[i].MatD3D.Specular);
1697 check_colorvalue_(line, "Emissive: ", got[i].MatD3D.Emissive, expected[i].MatD3D.Emissive);
1698 ok_(__FILE__,line)(expected[i].MatD3D.Power == got[i].MatD3D.Power,
1699 "Power: Expected %g, got %g\n", expected[i].MatD3D.Power, got[i].MatD3D.Power);
1703 #define check_generated_adjacency(mesh, got, epsilon) check_generated_adjacency_(__LINE__, mesh, got, epsilon)
1704 static void check_generated_adjacency_(int line, ID3DXMesh *mesh, const DWORD *got, FLOAT epsilon)
1706 DWORD *expected;
1707 DWORD num_faces = mesh->lpVtbl->GetNumFaces(mesh);
1708 HRESULT hr;
1710 expected = malloc(num_faces * sizeof(DWORD) * 3);
1711 if (!expected) {
1712 skip_(__FILE__, line)("Out of memory\n");
1713 return;
1715 hr = mesh->lpVtbl->GenerateAdjacency(mesh, epsilon, expected);
1716 ok_(__FILE__, line)(hr == D3D_OK, "Expected D3D_OK, got %#lx\n", hr);
1717 if (SUCCEEDED(hr))
1719 int i;
1720 for (i = 0; i < num_faces; i++)
1722 ok_(__FILE__, line)(expected[i * 3] == got[i * 3] &&
1723 expected[i * 3 + 1] == got[i * 3 + 1] &&
1724 expected[i * 3 + 2] == got[i * 3 + 2],
1725 "Face %u adjacencies: Expected (%lu, %lu, %lu), got (%lu, %lu, %lu)\n", i,
1726 expected[i * 3], expected[i * 3 + 1], expected[i * 3 + 2],
1727 got[i * 3], got[i * 3 + 1], got[i * 3 + 2]);
1730 free(expected);
1733 #define check_generated_effects(materials, num_materials, effects) \
1734 check_generated_effects_(__LINE__, materials, num_materials, effects)
1735 static void check_generated_effects_(int line, const D3DXMATERIAL *materials, DWORD num_materials, const D3DXEFFECTINSTANCE *effects)
1737 int i;
1738 static const struct {
1739 const char *name;
1740 DWORD name_size;
1741 DWORD num_bytes;
1742 DWORD value_offset;
1743 } params[] = {
1744 #define EFFECT_TABLE_ENTRY(str, field) \
1745 {str, sizeof(str), sizeof(materials->MatD3D.field), offsetof(D3DXMATERIAL, MatD3D.field)}
1746 EFFECT_TABLE_ENTRY("Diffuse", Diffuse),
1747 EFFECT_TABLE_ENTRY("Power", Power),
1748 EFFECT_TABLE_ENTRY("Specular", Specular),
1749 EFFECT_TABLE_ENTRY("Emissive", Emissive),
1750 EFFECT_TABLE_ENTRY("Ambient", Ambient),
1751 #undef EFFECT_TABLE_ENTRY
1754 if (!num_materials) {
1755 ok_(__FILE__, line)(effects == NULL, "Expected NULL effects, got %p\n", effects);
1756 return;
1758 for (i = 0; i < num_materials; i++)
1760 int j;
1761 DWORD expected_num_defaults = ARRAY_SIZE(params) + (materials[i].pTextureFilename ? 1 : 0);
1763 ok_(__FILE__,line)(expected_num_defaults == effects[i].NumDefaults,
1764 "effect[%u] NumDefaults: Expected %lu, got %lu\n", i,
1765 expected_num_defaults, effects[i].NumDefaults);
1766 for (j = 0; j < min(ARRAY_SIZE(params), effects[i].NumDefaults); j++)
1768 int k;
1769 D3DXEFFECTDEFAULT *got_param = &effects[i].pDefaults[j];
1770 ok_(__FILE__,line)(!strcmp(params[j].name, got_param->pParamName),
1771 "effect[%u].pDefaults[%u].pParamName: Expected '%s', got '%s'\n", i, j,
1772 params[j].name, got_param->pParamName);
1773 ok_(__FILE__,line)(D3DXEDT_FLOATS == got_param->Type,
1774 "effect[%u].pDefaults[%u].Type: Expected %u, got %u\n", i, j,
1775 D3DXEDT_FLOATS, got_param->Type);
1776 ok_(__FILE__,line)(params[j].num_bytes == got_param->NumBytes,
1777 "effect[%u].pDefaults[%u].NumBytes: Expected %lu, got %lu\n", i, j,
1778 params[j].num_bytes, got_param->NumBytes);
1779 for (k = 0; k < min(params[j].num_bytes, got_param->NumBytes) / 4; k++)
1781 FLOAT expected = ((FLOAT*)((BYTE*)&materials[i] + params[j].value_offset))[k];
1782 FLOAT got = ((FLOAT*)got_param->pValue)[k];
1783 ok_(__FILE__,line)(compare(expected, got),
1784 "effect[%u].pDefaults[%u] float value %u: Expected %g, got %g\n", i, j, k, expected, got);
1787 if (effects[i].NumDefaults > ARRAY_SIZE(params)) {
1788 D3DXEFFECTDEFAULT *got_param = &effects[i].pDefaults[j];
1789 static const char *expected_name = "Texture0@Name";
1791 ok_(__FILE__,line)(!strcmp(expected_name, got_param->pParamName),
1792 "effect[%u].pDefaults[%u].pParamName: Expected '%s', got '%s'\n", i, j,
1793 expected_name, got_param->pParamName);
1794 ok_(__FILE__,line)(D3DXEDT_STRING == got_param->Type,
1795 "effect[%u].pDefaults[%u].Type: Expected %u, got %u\n", i, j,
1796 D3DXEDT_STRING, got_param->Type);
1797 if (materials[i].pTextureFilename) {
1798 ok_(__FILE__,line)(strlen(materials[i].pTextureFilename) + 1 == got_param->NumBytes,
1799 "effect[%u] texture filename length: Expected %lu, got %lu\n", i,
1800 (DWORD)strlen(materials[i].pTextureFilename) + 1, got_param->NumBytes);
1801 ok_(__FILE__,line)(!strcmp(materials[i].pTextureFilename, got_param->pValue),
1802 "effect[%u] texture filename: Expected '%s', got '%s'\n", i,
1803 materials[i].pTextureFilename, (char*)got_param->pValue);
1809 static HRESULT CALLBACK ID3DXAllocateHierarchyImpl_DestroyFrame(ID3DXAllocateHierarchy *iface, LPD3DXFRAME frame)
1811 TRACECALLBACK("ID3DXAllocateHierarchyImpl_DestroyFrame(%p, %p)\n", iface, frame);
1812 if (frame) {
1813 free(frame->Name);
1814 free(frame);
1816 return D3D_OK;
1819 static HRESULT CALLBACK ID3DXAllocateHierarchyImpl_CreateFrame(ID3DXAllocateHierarchy *iface,
1820 const char *name, D3DXFRAME **new_frame)
1822 D3DXFRAME *frame;
1824 TRACECALLBACK("ID3DXAllocateHierarchyImpl_CreateFrame(%p, '%s', %p)\n", iface, name, new_frame);
1825 frame = calloc(1, sizeof(*frame));
1826 if (!frame)
1827 return E_OUTOFMEMORY;
1828 if (name) {
1829 frame->Name = strdup(name);
1830 if (!frame->Name) {
1831 free(frame);
1832 return E_OUTOFMEMORY;
1835 *new_frame = frame;
1836 return D3D_OK;
1839 static HRESULT destroy_mesh_container(LPD3DXMESHCONTAINER mesh_container)
1841 int i;
1843 if (!mesh_container)
1844 return D3D_OK;
1845 free(mesh_container->Name);
1846 if (mesh_container->MeshData.pMesh)
1847 IUnknown_Release(mesh_container->MeshData.pMesh);
1848 if (mesh_container->pMaterials) {
1849 for (i = 0; i < mesh_container->NumMaterials; i++)
1850 free(mesh_container->pMaterials[i].pTextureFilename);
1851 free(mesh_container->pMaterials);
1853 if (mesh_container->pEffects) {
1854 for (i = 0; i < mesh_container->NumMaterials; i++) {
1855 free(mesh_container->pEffects[i].pEffectFilename);
1856 if (mesh_container->pEffects[i].pDefaults) {
1857 int j;
1858 for (j = 0; j < mesh_container->pEffects[i].NumDefaults; j++) {
1859 free(mesh_container->pEffects[i].pDefaults[j].pParamName);
1860 free(mesh_container->pEffects[i].pDefaults[j].pValue);
1862 free(mesh_container->pEffects[i].pDefaults);
1865 free(mesh_container->pEffects);
1867 free(mesh_container->pAdjacency);
1868 if (mesh_container->pSkinInfo)
1869 IUnknown_Release(mesh_container->pSkinInfo);
1870 free(mesh_container);
1871 return D3D_OK;
1874 static HRESULT CALLBACK ID3DXAllocateHierarchyImpl_DestroyMeshContainer(ID3DXAllocateHierarchy *iface, LPD3DXMESHCONTAINER mesh_container)
1876 TRACECALLBACK("ID3DXAllocateHierarchyImpl_DestroyMeshContainer(%p, %p)\n", iface, mesh_container);
1877 return destroy_mesh_container(mesh_container);
1880 static HRESULT CALLBACK ID3DXAllocateHierarchyImpl_CreateMeshContainer(ID3DXAllocateHierarchy *iface,
1881 const char *name, const D3DXMESHDATA *mesh_data, const D3DXMATERIAL *materials,
1882 const D3DXEFFECTINSTANCE *effects, DWORD num_materials, const DWORD *adjacency,
1883 ID3DXSkinInfo *skin_info, D3DXMESHCONTAINER **new_mesh_container)
1885 LPD3DXMESHCONTAINER mesh_container = NULL;
1886 int i;
1888 TRACECALLBACK("ID3DXAllocateHierarchyImpl_CreateMeshContainer(%p, '%s', %u, %p, %p, %p, %ld, %p, %p, %p)\n",
1889 iface, name, mesh_data->Type, mesh_data->pMesh, materials, effects,
1890 num_materials, adjacency, skin_info, *new_mesh_container);
1892 mesh_container = calloc(1, sizeof(*mesh_container));
1893 if (!mesh_container)
1894 return E_OUTOFMEMORY;
1896 if (name) {
1897 mesh_container->Name = strdup(name);
1898 if (!mesh_container->Name)
1899 goto error;
1902 mesh_container->NumMaterials = num_materials;
1903 if (num_materials) {
1904 mesh_container->pMaterials = malloc(num_materials * sizeof(*materials));
1905 if (!mesh_container->pMaterials)
1906 goto error;
1908 memcpy(mesh_container->pMaterials, materials, num_materials * sizeof(*materials));
1909 for (i = 0; i < num_materials; i++)
1910 mesh_container->pMaterials[i].pTextureFilename = NULL;
1911 for (i = 0; i < num_materials; i++) {
1912 if (materials[i].pTextureFilename) {
1913 mesh_container->pMaterials[i].pTextureFilename = strdup(materials[i].pTextureFilename);
1914 if (!mesh_container->pMaterials[i].pTextureFilename)
1915 goto error;
1919 mesh_container->pEffects = calloc(num_materials, sizeof(*effects));
1920 if (!mesh_container->pEffects)
1921 goto error;
1922 for (i = 0; i < num_materials; i++) {
1923 int j;
1924 const D3DXEFFECTINSTANCE *effect_src = &effects[i];
1925 D3DXEFFECTINSTANCE *effect_dest = &mesh_container->pEffects[i];
1927 if (effect_src->pEffectFilename) {
1928 effect_dest->pEffectFilename = strdup(effect_src->pEffectFilename);
1929 if (!effect_dest->pEffectFilename)
1930 goto error;
1932 effect_dest->pDefaults = calloc(effect_src->NumDefaults, sizeof(*effect_src->pDefaults));
1933 if (!effect_dest->pDefaults)
1934 goto error;
1935 effect_dest->NumDefaults = effect_src->NumDefaults;
1936 for (j = 0; j < effect_src->NumDefaults; j++) {
1937 const D3DXEFFECTDEFAULT *default_src = &effect_src->pDefaults[j];
1938 D3DXEFFECTDEFAULT *default_dest = &effect_dest->pDefaults[j];
1940 if (default_src->pParamName) {
1941 default_dest->pParamName = strdup(default_src->pParamName);
1942 if (!default_dest->pParamName)
1943 goto error;
1945 default_dest->NumBytes = default_src->NumBytes;
1946 default_dest->Type = default_src->Type;
1947 default_dest->pValue = malloc(default_src->NumBytes);
1948 memcpy(default_dest->pValue, default_src->pValue, default_src->NumBytes);
1953 ok(adjacency != NULL, "Expected non-NULL adjacency, got NULL\n");
1954 if (adjacency) {
1955 if (mesh_data->Type == D3DXMESHTYPE_MESH || mesh_data->Type == D3DXMESHTYPE_PMESH) {
1956 ID3DXBaseMesh *basemesh = (ID3DXBaseMesh*)mesh_data->pMesh;
1957 DWORD num_faces = basemesh->lpVtbl->GetNumFaces(basemesh);
1958 size_t size = num_faces * sizeof(DWORD) * 3;
1959 mesh_container->pAdjacency = malloc(size);
1960 if (!mesh_container->pAdjacency)
1961 goto error;
1962 memcpy(mesh_container->pAdjacency, adjacency, size);
1963 } else {
1964 ok(mesh_data->Type == D3DXMESHTYPE_PATCHMESH, "Unknown mesh type %u\n", mesh_data->Type);
1965 if (mesh_data->Type == D3DXMESHTYPE_PATCHMESH)
1966 trace("FIXME: copying adjacency data for patch mesh not implemented\n");
1970 memcpy(&mesh_container->MeshData, mesh_data, sizeof(*mesh_data));
1971 if (mesh_data->pMesh)
1972 IUnknown_AddRef(mesh_data->pMesh);
1973 if (skin_info) {
1974 mesh_container->pSkinInfo = skin_info;
1975 skin_info->lpVtbl->AddRef(skin_info);
1977 *new_mesh_container = mesh_container;
1979 return S_OK;
1980 error:
1981 destroy_mesh_container(mesh_container);
1982 return E_OUTOFMEMORY;
1985 static ID3DXAllocateHierarchyVtbl ID3DXAllocateHierarchyImpl_Vtbl = {
1986 ID3DXAllocateHierarchyImpl_CreateFrame,
1987 ID3DXAllocateHierarchyImpl_CreateMeshContainer,
1988 ID3DXAllocateHierarchyImpl_DestroyFrame,
1989 ID3DXAllocateHierarchyImpl_DestroyMeshContainer,
1991 static ID3DXAllocateHierarchy alloc_hier = { &ID3DXAllocateHierarchyImpl_Vtbl };
1993 #define test_LoadMeshFromX(device, xfile_str, vertex_array, fvf, index_array, materials_array, check_adjacency) \
1994 test_LoadMeshFromX_(__LINE__, device, xfile_str, sizeof(xfile_str) - 1, vertex_array, ARRAY_SIZE(vertex_array), fvf, \
1995 index_array, ARRAY_SIZE(index_array), sizeof(*index_array), materials_array, ARRAY_SIZE(materials_array), \
1996 check_adjacency);
1997 static void test_LoadMeshFromX_(int line, IDirect3DDevice9 *device, const char *xfile_str, size_t xfile_strlen,
1998 const void *vertices, DWORD num_vertices, DWORD fvf, const void *indices, DWORD num_indices, size_t index_size,
1999 const D3DXMATERIAL *expected_materials, DWORD expected_num_materials, BOOL check_adjacency)
2001 HRESULT hr;
2002 ID3DXBuffer *materials = NULL;
2003 ID3DXBuffer *effects = NULL;
2004 ID3DXBuffer *adjacency = NULL;
2005 ID3DXMesh *mesh = NULL;
2006 DWORD num_materials = 0;
2008 /* Adjacency is not checked when the X file contains multiple meshes,
2009 * since calling GenerateAdjacency on the merged mesh is not equivalent
2010 * to calling GenerateAdjacency on the individual meshes and then merging
2011 * the adjacency data. */
2012 hr = D3DXLoadMeshFromXInMemory(xfile_str, xfile_strlen, D3DXMESH_MANAGED, device,
2013 check_adjacency ? &adjacency : NULL, &materials, &effects, &num_materials, &mesh);
2014 ok_(__FILE__,line)(hr == D3D_OK, "Expected D3D_OK, got %#lx\n", hr);
2015 if (SUCCEEDED(hr)) {
2016 D3DXMATERIAL *materials_ptr = materials ? ID3DXBuffer_GetBufferPointer(materials) : NULL;
2017 D3DXEFFECTINSTANCE *effects_ptr = effects ? ID3DXBuffer_GetBufferPointer(effects) : NULL;
2018 DWORD *adjacency_ptr = check_adjacency ? ID3DXBuffer_GetBufferPointer(adjacency) : NULL;
2020 check_vertex_buffer_(line, mesh, vertices, num_vertices, fvf);
2021 check_index_buffer_(line, mesh, indices, num_indices, index_size);
2022 check_materials_(line, materials_ptr, num_materials, expected_materials, expected_num_materials);
2023 check_generated_effects_(line, materials_ptr, num_materials, effects_ptr);
2024 if (check_adjacency)
2025 check_generated_adjacency_(line, mesh, adjacency_ptr, 0.0f);
2027 if (materials) ID3DXBuffer_Release(materials);
2028 if (effects) ID3DXBuffer_Release(effects);
2029 if (adjacency) ID3DXBuffer_Release(adjacency);
2030 IUnknown_Release(mesh);
2034 #define MAX_USER_DATA_COUNT 32
2035 enum user_data_type
2037 USER_DATA_TYPE_TOP,
2038 USER_DATA_TYPE_FRAME_CHILD,
2039 USER_DATA_TYPE_MESH_CHILD,
2042 struct test_user_data
2044 enum user_data_type data_type;
2045 const GUID *type;
2046 SIZE_T size;
2047 unsigned int value;
2048 BOOL mesh_container;
2049 unsigned int num_materials;
2052 struct test_load_user_data
2054 ID3DXLoadUserData iface;
2056 unsigned int data_count;
2057 struct test_user_data data[MAX_USER_DATA_COUNT];
2058 GUID guids[MAX_USER_DATA_COUNT];
2061 static void record_common_user_data(struct test_load_user_data *data, ID3DXFileData *filedata,
2062 enum user_data_type data_type)
2064 struct test_user_data *d = &data->data[data->data_count];
2065 const void *ptr;
2066 HRESULT hr;
2067 SIZE_T sz;
2069 assert(data->data_count < MAX_USER_DATA_COUNT);
2071 d->data_type = data_type;
2072 hr = filedata->lpVtbl->GetType(filedata, &data->guids[data->data_count]);
2073 ok(hr == S_OK, "got %#lx.\n", hr);
2074 hr = filedata->lpVtbl->Lock(filedata, &sz, &ptr);
2075 ok(hr == S_OK, "got %#lx.\n", hr);
2076 d->size = sz;
2077 ok(sz >= sizeof(int), "got %Iu.\n", sz);
2078 d->value = *(unsigned int *)ptr;
2079 hr = filedata->lpVtbl->Unlock(filedata);
2080 ok(hr == S_OK, "got %#lx.\n", hr);
2081 ++data->data_count;
2084 static struct test_load_user_data *impl_from_ID3DXLoadUserData(ID3DXLoadUserData *iface)
2086 return CONTAINING_RECORD(iface, struct test_load_user_data, iface);
2089 static HRESULT STDMETHODCALLTYPE load_top_level_data(ID3DXLoadUserData *iface, ID3DXFileData *filedata)
2091 struct test_load_user_data *user_data = impl_from_ID3DXLoadUserData(iface);
2093 record_common_user_data(user_data, filedata, USER_DATA_TYPE_TOP);
2094 return S_OK;
2097 static HRESULT STDMETHODCALLTYPE load_frame_child_data(ID3DXLoadUserData *iface, D3DXFRAME *frame,
2098 ID3DXFileData *filedata)
2100 struct test_load_user_data *user_data = impl_from_ID3DXLoadUserData(iface);
2102 ok(!frame->pFrameSibling, "got %p.\n", frame->pFrameSibling);
2103 ok(!frame->pFrameFirstChild, "got %p.\n", frame->pFrameFirstChild);
2105 user_data->data[user_data->data_count].mesh_container = !!frame->pMeshContainer;
2106 record_common_user_data(user_data, filedata, USER_DATA_TYPE_FRAME_CHILD);
2107 return S_OK;
2110 static HRESULT STDMETHODCALLTYPE load_mesh_child_data(ID3DXLoadUserData *iface, D3DXMESHCONTAINER *mesh_container,
2111 ID3DXFileData *filedata)
2113 struct test_load_user_data *user_data = impl_from_ID3DXLoadUserData(iface);
2115 user_data->data[user_data->data_count].num_materials = mesh_container->NumMaterials;
2117 record_common_user_data(user_data, filedata, USER_DATA_TYPE_MESH_CHILD);
2118 return S_OK;
2121 static const struct ID3DXLoadUserDataVtbl load_user_data_vtbl =
2123 load_top_level_data,
2124 load_frame_child_data,
2125 load_mesh_child_data,
2128 static void init_load_user_data(struct test_load_user_data *data)
2130 memset(data, 0, sizeof(*data));
2131 data->iface.lpVtbl = &load_user_data_vtbl;
2134 static void check_user_data(struct test_load_user_data *user_data, unsigned int expected_count,
2135 const struct test_user_data *expected)
2137 unsigned int i;
2139 ok(user_data->data_count == expected_count, "got %u, expected %u.\n", user_data->data_count, expected_count);
2140 for (i = 0; i < expected_count; ++i)
2142 winetest_push_context("i %u", i);
2143 ok(user_data->data[i].data_type == expected[i].data_type, "got %u, expected %u.\n",
2144 user_data->data[i].data_type, expected[i].data_type);
2145 ok(IsEqualGUID(&user_data->guids[i], expected[i].type), "got %s, expected %s.\n",
2146 debugstr_guid(&user_data->guids[i]), debugstr_guid(expected[i].type));
2147 ok(user_data->data[i].size == expected[i].size, "got %Iu, expected %Iu.\n",
2148 user_data->data[i].size, expected[i].size);
2149 ok(user_data->data[i].value == expected[i].value, "got %u, expected %u.\n",
2150 user_data->data[i].value, expected[i].value);
2151 ok(user_data->data[i].mesh_container == expected[i].mesh_container, "got %u, expected %u.\n",
2152 user_data->data[i].mesh_container, expected[i].mesh_container);
2153 ok(user_data->data[i].num_materials == expected[i].num_materials, "got %u, expected %u.\n",
2154 user_data->data[i].num_materials, expected[i].num_materials);
2155 winetest_pop_context();
2159 DEFINE_GUID(TID_TestDataGuid, 0x12345678, 0x1234, 0x1234, 0x12, 0x34, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11);
2161 static void D3DXLoadMeshTest(void)
2163 static const char empty_xfile[] = "xof 0303txt 0032";
2164 /*________________________*/
2165 static const char simple_xfile[] =
2166 "xof 0303txt 0032"
2167 "Mesh {"
2168 "3;"
2169 "0.0; 0.0; 0.0;,"
2170 "0.0; 1.0; 0.0;,"
2171 "1.0; 1.0; 0.0;;"
2172 "1;"
2173 "3; 0, 1, 2;;"
2174 "}";
2175 static const WORD simple_index_buffer[] = {0, 1, 2};
2176 static const D3DXVECTOR3 simple_vertex_buffer[] = {
2177 {0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {1.0, 1.0, 0.0}
2179 const DWORD simple_fvf = D3DFVF_XYZ;
2180 static const char framed_xfile[] =
2181 "xof 0303txt 0032"
2182 "template TestData {"
2183 "<12345678-1234-1234-1234-111111111111>"
2184 "DWORD value;"
2186 "TestData {"
2187 "1;;"
2189 "Material {"
2190 /* ColorRGBA faceColor; */
2191 "0.0; 0.0; 1.0; 1.0;;"
2192 /* FLOAT power; */
2193 "0.5;"
2194 /* ColorRGB specularColor; */
2195 "1.0; 1.0; 1.0;;"
2196 /* ColorRGB emissiveColor; */
2197 "0.0; 0.0; 0.0;;"
2200 "Frame {"
2201 "TestData {"
2202 "2;;"
2204 "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;;"
2205 "TestData {"
2206 "3;;"
2209 "FrameTransformMatrix {" /* translation (0.0, 0.0, 2.0) */
2210 "1.0, 0.0, 0.0, 0.0,"
2211 "0.0, 1.0, 0.0, 0.0,"
2212 "0.0, 0.0, 1.0, 0.0,"
2213 "0.0, 0.0, 2.0, 1.0;;"
2215 "TestData {"
2216 "4;;"
2218 "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;; }"
2219 "FrameTransformMatrix {" /* translation (0.0, 0.0, 3.0) */
2220 "1.0, 0.0, 0.0, 0.0,"
2221 "0.0, 1.0, 0.0, 0.0,"
2222 "0.0, 0.0, 1.0, 0.0,"
2223 "0.0, 0.0, 3.0, 1.0;;"
2225 "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;; }"
2226 "}";
2228 static const struct test_user_data framed_xfile_expected_user_data[] =
2230 { USER_DATA_TYPE_TOP, &TID_TestDataGuid, 4, 1, 0, 0},
2231 { USER_DATA_TYPE_TOP, &TID_D3DRMMaterial, 44, 0, 0, 0},
2232 { USER_DATA_TYPE_FRAME_CHILD, &TID_TestDataGuid, 4, 2, 0, 0},
2233 { USER_DATA_TYPE_MESH_CHILD, &TID_TestDataGuid, 4, 3, 0, 0},
2234 { USER_DATA_TYPE_FRAME_CHILD, &TID_TestDataGuid, 4, 4, 1, 0},
2237 static const char framed_xfile_empty[] =
2238 "xof 0303txt 0032"
2239 "Frame Box01 {"
2240 " Mesh { 0;; 0;;"
2241 " MeshNormals { 0;; 0;; }"
2242 " }"
2243 "}";
2245 static const WORD framed_index_buffer[] = { 0, 1, 2 };
2246 static const D3DXVECTOR3 framed_vertex_buffers[3][3] = {
2247 {{0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {1.0, 1.0, 0.0}},
2248 {{0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {2.0, 1.0, 0.0}},
2249 {{0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {3.0, 1.0, 0.0}},
2251 static const WORD merged_index_buffer[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
2252 /* frame transforms accumulates for D3DXLoadMeshFromX */
2253 static const D3DXVECTOR3 merged_vertex_buffer[] = {
2254 {0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {1.0, 1.0, 0.0},
2255 {0.0, 0.0, 2.0}, {0.0, 1.0, 2.0}, {2.0, 1.0, 2.0},
2256 {0.0, 0.0, 5.0}, {0.0, 1.0, 5.0}, {3.0, 1.0, 5.0},
2258 const DWORD framed_fvf = D3DFVF_XYZ;
2259 /*________________________*/
2260 static const char box_xfile[] =
2261 "xof 0303txt 0032"
2262 "template TestData {"
2263 "<12345678-1234-1234-1234-111111111111>"
2264 "DWORD value;"
2266 "Mesh {"
2267 "8;" /* DWORD nVertices; */
2268 /* array Vector vertices[nVertices]; */
2269 "0.0; 0.0; 0.0;,"
2270 "0.0; 0.0; 1.0;,"
2271 "0.0; 1.0; 0.0;,"
2272 "0.0; 1.0; 1.0;,"
2273 "1.0; 0.0; 0.0;,"
2274 "1.0; 0.0; 1.0;,"
2275 "1.0; 1.0; 0.0;,"
2276 "1.0; 1.0; 1.0;;"
2277 "6;" /* DWORD nFaces; */
2278 /* array MeshFace faces[nFaces]; */
2279 "4; 0, 1, 3, 2;," /* (left side) */
2280 "4; 2, 3, 7, 6;," /* (top side) */
2281 "4; 6, 7, 5, 4;," /* (right side) */
2282 "4; 1, 0, 4, 5;," /* (bottom side) */
2283 "4; 1, 5, 7, 3;," /* (back side) */
2284 "4; 0, 2, 6, 4;;" /* (front side) */
2285 "MeshNormals {"
2286 "6;" /* DWORD nNormals; */
2287 /* array Vector normals[nNormals]; */
2288 "-1.0; 0.0; 0.0;,"
2289 "0.0; 1.0; 0.0;,"
2290 "1.0; 0.0; 0.0;,"
2291 "0.0; -1.0; 0.0;,"
2292 "0.0; 0.0; 1.0;,"
2293 "0.0; 0.0; -1.0;;"
2294 "6;" /* DWORD nFaceNormals; */
2295 /* array MeshFace faceNormals[nFaceNormals]; */
2296 "4; 0, 0, 0, 0;,"
2297 "4; 1, 1, 1, 1;,"
2298 "4; 2, 2, 2, 2;,"
2299 "4; 3, 3, 3, 3;,"
2300 "4; 4, 4, 4, 4;,"
2301 "4; 5, 5, 5, 5;;"
2303 "TestData {"
2304 "1;;"
2306 "MeshMaterialList materials {"
2307 "2;" /* DWORD nMaterials; */
2308 "6;" /* DWORD nFaceIndexes; */
2309 /* array DWORD faceIndexes[nFaceIndexes]; */
2310 "0, 0, 0, 1, 1, 1;;"
2311 "Material {"
2312 /* ColorRGBA faceColor; */
2313 "0.0; 0.0; 1.0; 1.0;;"
2314 /* FLOAT power; */
2315 "0.5;"
2316 /* ColorRGB specularColor; */
2317 "1.0; 1.0; 1.0;;"
2318 /* ColorRGB emissiveColor; */
2319 "0.0; 0.0; 0.0;;"
2321 "Material {"
2322 /* ColorRGBA faceColor; */
2323 "1.0; 1.0; 1.0; 1.0;;"
2324 /* FLOAT power; */
2325 "1.0;"
2326 /* ColorRGB specularColor; */
2327 "1.0; 1.0; 1.0;;"
2328 /* ColorRGB emissiveColor; */
2329 "0.0; 0.0; 0.0;;"
2330 "TextureFilename { \"texture.jpg\"; }"
2333 "TestData {"
2334 "2;;"
2337 "MeshVertexColors {"
2338 "8;" /* DWORD nVertexColors; */
2339 /* array IndexedColor vertexColors[nVertexColors]; */
2340 "0; 0.0; 0.0; 0.0; 0.0;;"
2341 "1; 0.0; 0.0; 1.0; 0.1;;"
2342 "2; 0.0; 1.0; 0.0; 0.2;;"
2343 "3; 0.0; 1.0; 1.0; 0.3;;"
2344 "4; 1.0; 0.0; 0.0; 0.4;;"
2345 "5; 1.0; 0.0; 1.0; 0.5;;"
2346 "6; 1.0; 1.0; 0.0; 0.6;;"
2347 "7; 1.0; 1.0; 1.0; 0.7;;"
2349 "MeshTextureCoords {"
2350 "8;" /* DWORD nTextureCoords; */
2351 /* array Coords2d textureCoords[nTextureCoords]; */
2352 "0.0; 1.0;,"
2353 "1.0; 1.0;,"
2354 "0.0; 0.0;,"
2355 "1.0; 0.0;,"
2356 "1.0; 1.0;,"
2357 "0.0; 1.0;,"
2358 "1.0; 0.0;,"
2359 "0.0; 0.0;;"
2361 "}";
2362 static const struct test_user_data box_xfile_expected_user_data[] =
2364 { USER_DATA_TYPE_MESH_CHILD, &TID_TestDataGuid, 4, 1, 0, 2},
2365 { USER_DATA_TYPE_MESH_CHILD, &TID_TestDataGuid, 4, 2, 0, 2},
2368 static const WORD box_index_buffer[] = {
2369 0, 1, 3,
2370 0, 3, 2,
2371 8, 9, 7,
2372 8, 7, 6,
2373 10, 11, 5,
2374 10, 5, 4,
2375 12, 13, 14,
2376 12, 14, 15,
2377 16, 17, 18,
2378 16, 18, 19,
2379 20, 21, 22,
2380 20, 22, 23,
2382 static const struct {
2383 D3DXVECTOR3 position;
2384 D3DXVECTOR3 normal;
2385 D3DCOLOR diffuse;
2386 D3DXVECTOR2 tex_coords;
2387 } box_vertex_buffer[] = {
2388 {{0.0, 0.0, 0.0}, {-1.0, 0.0, 0.0}, 0x00000000, {0.0, 1.0}},
2389 {{0.0, 0.0, 1.0}, {-1.0, 0.0, 0.0}, 0x1a0000ff, {1.0, 1.0}},
2390 {{0.0, 1.0, 0.0}, {-1.0, 0.0, 0.0}, 0x3300ff00, {0.0, 0.0}},
2391 {{0.0, 1.0, 1.0}, {-1.0, 0.0, 0.0}, 0x4d00ffff, {1.0, 0.0}},
2392 {{1.0, 0.0, 0.0}, {1.0, 0.0, 0.0}, 0x66ff0000, {1.0, 1.0}},
2393 {{1.0, 0.0, 1.0}, {1.0, 0.0, 0.0}, 0x80ff00ff, {0.0, 1.0}},
2394 {{1.0, 1.0, 0.0}, {0.0, 1.0, 0.0}, 0x99ffff00, {1.0, 0.0}},
2395 {{1.0, 1.0, 1.0}, {0.0, 1.0, 0.0}, 0xb3ffffff, {0.0, 0.0}},
2396 {{0.0, 1.0, 0.0}, {0.0, 1.0, 0.0}, 0x3300ff00, {0.0, 0.0}},
2397 {{0.0, 1.0, 1.0}, {0.0, 1.0, 0.0}, 0x4d00ffff, {1.0, 0.0}},
2398 {{1.0, 1.0, 0.0}, {1.0, 0.0, 0.0}, 0x99ffff00, {1.0, 0.0}},
2399 {{1.0, 1.0, 1.0}, {1.0, 0.0, 0.0}, 0xb3ffffff, {0.0, 0.0}},
2400 {{0.0, 0.0, 1.0}, {0.0, -1.0, 0.0}, 0x1a0000ff, {1.0, 1.0}},
2401 {{0.0, 0.0, 0.0}, {0.0, -1.0, 0.0}, 0x00000000, {0.0, 1.0}},
2402 {{1.0, 0.0, 0.0}, {0.0, -1.0, 0.0}, 0x66ff0000, {1.0, 1.0}},
2403 {{1.0, 0.0, 1.0}, {0.0, -1.0, 0.0}, 0x80ff00ff, {0.0, 1.0}},
2404 {{0.0, 0.0, 1.0}, {0.0, 0.0, 1.0}, 0x1a0000ff, {1.0, 1.0}},
2405 {{1.0, 0.0, 1.0}, {0.0, 0.0, 1.0}, 0x80ff00ff, {0.0, 1.0}},
2406 {{1.0, 1.0, 1.0}, {0.0, 0.0, 1.0}, 0xb3ffffff, {0.0, 0.0}},
2407 {{0.0, 1.0, 1.0}, {0.0, 0.0, 1.0}, 0x4d00ffff, {1.0, 0.0}},
2408 {{0.0, 0.0, 0.0}, {0.0, 0.0, -1.0}, 0x00000000, {0.0, 1.0}},
2409 {{0.0, 1.0, 0.0}, {0.0, 0.0, -1.0}, 0x3300ff00, {0.0, 0.0}},
2410 {{1.0, 1.0, 0.0}, {0.0, 0.0, -1.0}, 0x99ffff00, {1.0, 0.0}},
2411 {{1.0, 0.0, 0.0}, {0.0, 0.0, -1.0}, 0x66ff0000, {1.0, 1.0}},
2413 static const D3DXMATERIAL box_materials[] = {
2416 {0.0, 0.0, 1.0, 1.0}, /* Diffuse */
2417 {0.0, 0.0, 0.0, 1.0}, /* Ambient */
2418 {1.0, 1.0, 1.0, 1.0}, /* Specular */
2419 {0.0, 0.0, 0.0, 1.0}, /* Emissive */
2420 0.5, /* Power */
2422 NULL, /* pTextureFilename */
2426 {1.0, 1.0, 1.0, 1.0}, /* Diffuse */
2427 {0.0, 0.0, 0.0, 1.0}, /* Ambient */
2428 {1.0, 1.0, 1.0, 1.0}, /* Specular */
2429 {0.0, 0.0, 0.0, 1.0}, /* Emissive */
2430 1.0, /* Power */
2432 (char *)"texture.jpg", /* pTextureFilename */
2435 static const char box_anim_xfile[] =
2436 "xof 0303txt 0032"
2437 "Mesh CubeMesh {"
2438 "8;" /* DWORD nVertices; */
2439 /* array Vector vertices[nVertices]; */
2440 "0.0; 0.0; 0.0;,"
2441 "0.0; 0.0; 1.0;,"
2442 "0.0; 1.0; 0.0;,"
2443 "0.0; 1.0; 1.0;,"
2444 "1.0; 0.0; 0.0;,"
2445 "1.0; 0.0; 1.0;,"
2446 "1.0; 1.0; 0.0;,"
2447 "1.0; 1.0; 1.0;;"
2448 "6;" /* DWORD nFaces; */
2449 /* array MeshFace faces[nFaces]; */
2450 "4; 0, 1, 3, 2;," /* left side */
2451 "4; 2, 3, 7, 6;," /* top side */
2452 "4; 6, 7, 5, 4;," /* right side */
2453 "4; 1, 0, 4, 5;," /* bottom side */
2454 "4; 1, 5, 7, 3;," /* back side */
2455 "4; 0, 2, 6, 4;;" /* front side */
2456 "MeshNormals {"
2457 "6;" /* DWORD nNormals; */
2458 /* array Vector normals[nNormals]; */
2459 "-1.0; 0.0; 0.0;,"
2460 "0.0; 1.0; 0.0;,"
2461 "1.0; 0.0; 0.0;,"
2462 "0.0; -1.0; 0.0;,"
2463 "0.0; 0.0; 1.0;,"
2464 "0.0; 0.0; -1.0;;"
2465 "6;" /* DWORD nFaceNormals; */
2466 /* array MeshFace faceNormals[nFaceNormals]; */
2467 "4; 0, 0, 0, 0;,"
2468 "4; 1, 1, 1, 1;,"
2469 "4; 2, 2, 2, 2;,"
2470 "4; 3, 3, 3, 3;,"
2471 "4; 4, 4, 4, 4;,"
2472 "4; 5, 5, 5, 5;;"
2474 "MeshMaterialList materials {"
2475 "2;" /* DWORD nMaterials; */
2476 "6;" /* DWORD nFaceIndexes; */
2477 /* array DWORD faceIndexes[nFaceIndexes]; */
2478 "0, 0, 0, 1, 1, 1;;"
2479 "Material {"
2480 /* ColorRGBA faceColor; */
2481 "0.0; 0.0; 1.0; 1.0;;"
2482 /* FLOAT power; */
2483 "0.5;"
2484 /* ColorRGB specularColor; */
2485 "1.0; 1.0; 1.0;;"
2486 /* ColorRGB emissiveColor; */
2487 "0.0; 0.0; 0.0;;"
2489 "Material {"
2490 /* ColorRGBA faceColor; */
2491 "1.0; 1.0; 1.0; 1.0;;"
2492 /* FLOAT power; */
2493 "1.0;"
2494 /* ColorRGB specularColor; */
2495 "1.0; 1.0; 1.0;;"
2496 /* ColorRGB emissiveColor; */
2497 "0.0; 0.0; 0.0;;"
2498 "TextureFilename { \"texture.jpg\"; }"
2501 "MeshVertexColors {"
2502 "8;" /* DWORD nVertexColors; */
2503 /* array IndexedColor vertexColors[nVertexColors]; */
2504 "0; 0.0; 0.0; 0.0; 0.0;;"
2505 "1; 0.0; 0.0; 1.0; 0.1;;"
2506 "2; 0.0; 1.0; 0.0; 0.2;;"
2507 "3; 0.0; 1.0; 1.0; 0.3;;"
2508 "4; 1.0; 0.0; 0.0; 0.4;;"
2509 "5; 1.0; 0.0; 1.0; 0.5;;"
2510 "6; 1.0; 1.0; 0.0; 0.6;;"
2511 "7; 1.0; 1.0; 1.0; 0.7;;"
2513 "MeshTextureCoords {"
2514 "8;" /* DWORD nTextureCoords; */
2515 /* array Coords2d textureCoords[nTextureCoords]; */
2516 "0.0; 1.0;,"
2517 "1.0; 1.0;,"
2518 "0.0; 0.0;,"
2519 "1.0; 0.0;,"
2520 "1.0; 1.0;,"
2521 "0.0; 1.0;,"
2522 "1.0; 0.0;,"
2523 "0.0; 0.0;;"
2526 "Frame CubeFrame {"
2527 "FrameTransformMatrix {"
2528 /* Matrix4x4 frameMatrix; */
2529 "1.0, 0.0, 0.0, 0.0,"
2530 "0.0, 1.0, 0.0, 0.0,"
2531 "0.0, 0.0, 1.0, 0.0,"
2532 "0.0, 0.0, 0.0, 1.0;;"
2534 "{CubeMesh}"
2536 "AnimationSet AnimationSet0 {"
2537 "Animation Animation0 {"
2538 "{CubeFrame}"
2539 "AnimationKey {"
2540 "2;" /* DWORD keyType; */
2541 "9;" /* DWORD nKeys; */
2542 /* array TimedFloatKeys keys[nKeys]; */
2543 "10; 3; -100.0, 0.0, 0.0;;,"
2544 "20; 3; -75.0, 0.0, 0.0;;,"
2545 "30; 3; -50.0, 0.0, 0.0;;,"
2546 "40; 3; -25.5, 0.0, 0.0;;,"
2547 "50; 3; 0.0, 0.0, 0.0;;,"
2548 "60; 3; 25.5, 0.0, 0.0;;,"
2549 "70; 3; 50.0, 0.0, 0.0;;,"
2550 "80; 3; 75.5, 0.0, 0.0;;,"
2551 "90; 3; 100.0, 0.0, 0.0;;;"
2554 "}";
2556 const DWORD box_fvf = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_TEX1;
2557 /*________________________*/
2558 static const D3DXMATERIAL default_materials[] = {
2561 {0.5, 0.5, 0.5, 0.0}, /* Diffuse */
2562 {0.0, 0.0, 0.0, 0.0}, /* Ambient */
2563 {0.5, 0.5, 0.5, 0.0}, /* Specular */
2564 {0.0, 0.0, 0.0, 0.0}, /* Emissive */
2565 0.0, /* Power */
2567 NULL, /* pTextureFilename */
2570 HRESULT hr;
2571 IDirect3DDevice9 *device = NULL;
2572 ID3DXMesh *mesh = NULL;
2573 D3DXFRAME *frame_hier = NULL;
2574 D3DXMATRIX transform;
2575 struct test_context *test_context;
2576 ID3DXAnimationController *controller;
2577 D3DXMESHCONTAINER *container;
2578 unsigned int i;
2579 struct test_load_user_data load_user_data;
2581 if (!(test_context = new_test_context()))
2583 skip("Couldn't create test context\n");
2584 return;
2586 device = test_context->device;
2588 hr = D3DXLoadMeshHierarchyFromXInMemory(NULL, sizeof(simple_xfile) - 1,
2589 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
2590 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#lx\n", hr);
2592 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, 0,
2593 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
2594 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#lx\n", hr);
2596 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1,
2597 D3DXMESH_MANAGED, NULL, &alloc_hier, NULL, &frame_hier, NULL);
2598 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#lx\n", hr);
2600 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1,
2601 D3DXMESH_MANAGED, device, NULL, NULL, &frame_hier, NULL);
2602 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#lx\n", hr);
2604 hr = D3DXLoadMeshHierarchyFromXInMemory(empty_xfile, sizeof(empty_xfile) - 1,
2605 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
2606 ok(hr == E_FAIL, "Expected E_FAIL, got %#lx\n", hr);
2608 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1,
2609 D3DXMESH_MANAGED, device, &alloc_hier, NULL, NULL, NULL);
2610 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#lx\n", hr);
2612 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1,
2613 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
2614 ok(hr == D3D_OK, "Expected D3D_OK, got %#lx\n", hr);
2615 container = frame_hier->pMeshContainer;
2617 ok(frame_hier->Name == NULL, "Expected NULL, got '%s'\n", frame_hier->Name);
2618 D3DXMatrixIdentity(&transform);
2619 check_matrix(&frame_hier->TransformationMatrix, &transform);
2621 ok(!strcmp(container->Name, ""), "Expected '', got '%s'\n", container->Name);
2622 ok(container->MeshData.Type == D3DXMESHTYPE_MESH, "Expected %d, got %d\n",
2623 D3DXMESHTYPE_MESH, container->MeshData.Type);
2624 mesh = container->MeshData.pMesh;
2625 check_vertex_buffer(mesh, simple_vertex_buffer, ARRAY_SIZE(simple_vertex_buffer), simple_fvf);
2626 check_index_buffer(mesh, simple_index_buffer, ARRAY_SIZE(simple_index_buffer), sizeof(*simple_index_buffer));
2627 check_materials(container->pMaterials, container->NumMaterials, NULL, 0);
2628 check_generated_effects(container->pMaterials, container->NumMaterials, container->pEffects);
2629 check_generated_adjacency(mesh, container->pAdjacency, 0.0f);
2630 hr = D3DXFrameDestroy(frame_hier, &alloc_hier);
2631 ok(hr == D3D_OK, "Expected D3D_OK, got %#lx\n", hr);
2632 frame_hier = NULL;
2634 controller = (ID3DXAnimationController *)0xdeadbeef;
2635 hr = D3DXLoadMeshHierarchyFromXInMemory(box_anim_xfile, sizeof(box_anim_xfile) - 1,
2636 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, &controller);
2637 todo_wine ok(hr == D3D_OK, "Expected D3D_OK, got %#lx.\n", hr);
2638 if (SUCCEEDED(hr))
2640 ok(controller != NULL, "Animation Controller NULL.\n");
2642 hr = D3DXFrameDestroy(frame_hier, &alloc_hier);
2643 ok(hr == D3D_OK, "Expected D3D_OK, got %#lx.\n", hr);
2644 if (controller)
2645 controller->lpVtbl->Release(controller);
2647 frame_hier = NULL;
2650 controller = (ID3DXAnimationController *)0xdeadbeef;
2651 hr = D3DXLoadMeshHierarchyFromXInMemory(box_xfile, sizeof(box_xfile) - 1,
2652 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, &controller);
2653 ok(hr == D3D_OK, "Expected D3D_OK, got %#lx\n", hr);
2654 container = frame_hier->pMeshContainer;
2656 ok(!controller, "Animation Controller returned.\n");
2657 ok(frame_hier->Name == NULL, "Expected NULL, got '%s'\n", frame_hier->Name);
2658 D3DXMatrixIdentity(&transform);
2659 check_matrix(&frame_hier->TransformationMatrix, &transform);
2661 ok(!strcmp(container->Name, ""), "Expected '', got '%s'\n", container->Name);
2662 ok(container->MeshData.Type == D3DXMESHTYPE_MESH, "Expected %d, got %d\n",
2663 D3DXMESHTYPE_MESH, container->MeshData.Type);
2664 mesh = container->MeshData.pMesh;
2665 check_vertex_buffer(mesh, box_vertex_buffer, ARRAY_SIZE(box_vertex_buffer), box_fvf);
2666 check_index_buffer(mesh, box_index_buffer, ARRAY_SIZE(box_index_buffer), sizeof(*box_index_buffer));
2667 check_materials(container->pMaterials, container->NumMaterials, box_materials, ARRAY_SIZE(box_materials));
2668 check_generated_effects(container->pMaterials, container->NumMaterials, container->pEffects);
2669 check_generated_adjacency(mesh, container->pAdjacency, 0.0f);
2670 hr = D3DXFrameDestroy(frame_hier, &alloc_hier);
2671 ok(hr == D3D_OK, "Expected D3D_OK, got %#lx\n", hr);
2672 frame_hier = NULL;
2674 init_load_user_data(&load_user_data);
2675 hr = D3DXLoadMeshHierarchyFromXInMemory(box_xfile, sizeof(box_xfile) - 1,
2676 D3DXMESH_MANAGED, device, &alloc_hier, &load_user_data.iface, &frame_hier, &controller);
2677 ok(hr == D3D_OK, "Expected D3D_OK, got %#lx\n", hr);
2678 winetest_push_context("box_xfile");
2679 check_user_data(&load_user_data, ARRAY_SIZE(box_xfile_expected_user_data), box_xfile_expected_user_data);
2680 winetest_pop_context();
2681 hr = D3DXFrameDestroy(frame_hier, &alloc_hier);
2682 ok(hr == D3D_OK, "Expected D3D_OK, got %#lx\n", hr);
2683 frame_hier = NULL;
2685 hr = D3DXLoadMeshHierarchyFromXInMemory(framed_xfile, sizeof(framed_xfile) - 1,
2686 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
2687 ok(hr == D3D_OK, "Expected D3D_OK, got %#lx\n", hr);
2688 container = frame_hier->pMeshContainer;
2690 ok(!strcmp(frame_hier->Name, ""), "Expected '', got '%s'\n", frame_hier->Name);
2691 /* last frame transform replaces the first */
2692 D3DXMatrixIdentity(&transform);
2693 transform.m[3][2] = 3.0;
2694 check_matrix(&frame_hier->TransformationMatrix, &transform);
2696 for (i = 0; i < 3; ++i)
2698 ok(!strcmp(container->Name, ""), "Expected '', got '%s'\n", container->Name);
2699 ok(container->MeshData.Type == D3DXMESHTYPE_MESH, "Expected %d, got %d\n",
2700 D3DXMESHTYPE_MESH, container->MeshData.Type);
2701 mesh = container->MeshData.pMesh;
2702 check_vertex_buffer(mesh, framed_vertex_buffers[i], ARRAY_SIZE(framed_vertex_buffers[0]), framed_fvf);
2703 check_index_buffer(mesh, framed_index_buffer, ARRAY_SIZE(framed_index_buffer), sizeof(*framed_index_buffer));
2704 check_materials(container->pMaterials, container->NumMaterials, NULL, 0);
2705 check_generated_effects(container->pMaterials, container->NumMaterials, container->pEffects);
2706 check_generated_adjacency(mesh, container->pAdjacency, 0.0f);
2707 container = container->pNextMeshContainer;
2709 ok(container == NULL, "Expected NULL, got %p\n", container);
2710 hr = D3DXFrameDestroy(frame_hier, &alloc_hier);
2711 ok(hr == D3D_OK, "Expected D3D_OK, got %#lx\n", hr);
2712 frame_hier = NULL;
2714 init_load_user_data(&load_user_data);
2715 hr = D3DXLoadMeshHierarchyFromXInMemory(framed_xfile, sizeof(framed_xfile) - 1,
2716 D3DXMESH_MANAGED, device, &alloc_hier, &load_user_data.iface, &frame_hier, NULL);
2717 ok(hr == D3D_OK, "Expected D3D_OK, got %#lx\n", hr);
2718 hr = D3DXFrameDestroy(frame_hier, &alloc_hier);
2719 ok(hr == D3D_OK, "Expected D3D_OK, got %#lx\n", hr);
2720 winetest_push_context("framed_xfile");
2721 check_user_data(&load_user_data, ARRAY_SIZE(framed_xfile_expected_user_data), framed_xfile_expected_user_data);
2722 winetest_pop_context();
2723 frame_hier = NULL;
2725 hr = D3DXLoadMeshHierarchyFromXInMemory(framed_xfile_empty, sizeof(framed_xfile_empty) - 1,
2726 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
2727 ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr);
2728 container = frame_hier->pMeshContainer;
2729 ok(!strcmp(frame_hier->Name, "Box01"), "Unexpected name %s.\n", debugstr_a(frame_hier->Name));
2730 ok(!container, "Unexpected container %p.\n", container);
2732 hr = D3DXFrameDestroy(frame_hier, &alloc_hier);
2733 ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr);
2734 frame_hier = NULL;
2736 hr = D3DXLoadMeshFromXInMemory(NULL, 0, D3DXMESH_MANAGED,
2737 device, NULL, NULL, NULL, NULL, &mesh);
2738 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#lx\n", hr);
2740 hr = D3DXLoadMeshFromXInMemory(NULL, sizeof(simple_xfile) - 1, D3DXMESH_MANAGED,
2741 device, NULL, NULL, NULL, NULL, &mesh);
2742 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#lx\n", hr);
2744 hr = D3DXLoadMeshFromXInMemory(simple_xfile, 0, D3DXMESH_MANAGED,
2745 device, NULL, NULL, NULL, NULL, &mesh);
2746 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#lx\n", hr);
2748 hr = D3DXLoadMeshFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1, D3DXMESH_MANAGED,
2749 device, NULL, NULL, NULL, NULL, NULL);
2750 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#lx\n", hr);
2752 hr = D3DXLoadMeshFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1, D3DXMESH_MANAGED,
2753 NULL, NULL, NULL, NULL, NULL, &mesh);
2754 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#lx\n", hr);
2756 hr = D3DXLoadMeshFromXInMemory(empty_xfile, sizeof(empty_xfile) - 1, D3DXMESH_MANAGED,
2757 device, NULL, NULL, NULL, NULL, &mesh);
2758 ok(hr == E_FAIL, "Expected E_FAIL, got %#lx\n", hr);
2760 hr = D3DXLoadMeshFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1, D3DXMESH_MANAGED,
2761 device, NULL, NULL, NULL, NULL, &mesh);
2762 ok(hr == D3D_OK, "Expected D3D_OK, got %#lx\n", hr);
2763 IUnknown_Release(mesh);
2765 test_LoadMeshFromX(device, simple_xfile, simple_vertex_buffer, simple_fvf, simple_index_buffer, default_materials, TRUE);
2766 test_LoadMeshFromX(device, box_xfile, box_vertex_buffer, box_fvf, box_index_buffer, box_materials, TRUE);
2767 test_LoadMeshFromX(device, framed_xfile, merged_vertex_buffer, framed_fvf, merged_index_buffer, default_materials, FALSE);
2769 free_test_context(test_context);
2772 static BOOL compute_box(struct mesh *mesh, float width, float height, float depth)
2774 unsigned int i, face;
2775 static const D3DXVECTOR3 unit_box[] =
2777 {-1.0f, -1.0f, -1.0f}, {-1.0f, -1.0f, 1.0f}, {-1.0f, 1.0f, 1.0f}, {-1.0f, 1.0f, -1.0f},
2778 {-1.0f, 1.0f, -1.0f}, {-1.0f, 1.0f, 1.0f}, { 1.0f, 1.0f, 1.0f}, { 1.0f, 1.0f, -1.0f},
2779 { 1.0f, 1.0f, -1.0f}, { 1.0f, 1.0f, 1.0f}, { 1.0f, -1.0f, 1.0f}, { 1.0f, -1.0f, -1.0f},
2780 {-1.0f, -1.0f, 1.0f}, {-1.0f, -1.0f, -1.0f}, { 1.0f, -1.0f, -1.0f}, { 1.0f, -1.0f, 1.0f},
2781 {-1.0f, -1.0f, 1.0f}, { 1.0f, -1.0f, 1.0f}, { 1.0f, 1.0f, 1.0f}, {-1.0f, 1.0f, 1.0f},
2782 {-1.0f, -1.0f, -1.0f}, {-1.0f, 1.0f, -1.0f}, { 1.0f, 1.0f, -1.0f}, { 1.0f, -1.0f, -1.0f}
2784 static const D3DXVECTOR3 normals[] =
2786 {-1.0f, 0.0f, 0.0f}, { 0.0f, 1.0f, 0.0f}, { 1.0f, 0.0f, 0.0f},
2787 { 0.0f, -1.0f, 0.0f}, { 0.0f, 0.0f, 1.0f}, { 0.0f, 0.0f, -1.0f}
2790 if (!new_mesh(mesh, 24, 12))
2792 return FALSE;
2795 width /= 2.0f;
2796 height /= 2.0f;
2797 depth /= 2.0f;
2799 for (i = 0; i < 24; i++)
2801 mesh->vertices[i].position.x = width * unit_box[i].x;
2802 mesh->vertices[i].position.y = height * unit_box[i].y;
2803 mesh->vertices[i].position.z = depth * unit_box[i].z;
2804 mesh->vertices[i].normal.x = normals[i / 4].x;
2805 mesh->vertices[i].normal.y = normals[i / 4].y;
2806 mesh->vertices[i].normal.z = normals[i / 4].z;
2809 face = 0;
2810 for (i = 0; i < 12; i++)
2812 mesh->faces[i][0] = face++;
2813 mesh->faces[i][1] = face++;
2814 mesh->faces[i][2] = (i % 2) ? face - 4 : face;
2817 return TRUE;
2820 static void test_box(IDirect3DDevice9 *device, float width, float height, float depth)
2822 HRESULT hr;
2823 ID3DXMesh *box;
2824 struct mesh mesh;
2825 char name[256];
2827 hr = D3DXCreateBox(device, width, height, depth, &box, NULL);
2828 ok(hr == D3D_OK, "Got result %lx, expected 0 (D3D_OK)\n", hr);
2829 if (hr != D3D_OK)
2831 skip("Couldn't create box\n");
2832 return;
2835 if (!compute_box(&mesh, width, height, depth))
2837 skip("Couldn't create mesh\n");
2838 box->lpVtbl->Release(box);
2839 return;
2842 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
2844 sprintf(name, "box (%g, %g, %g)", width, height, depth);
2845 compare_mesh(name, box, &mesh);
2847 free_mesh(&mesh);
2849 box->lpVtbl->Release(box);
2851 static void D3DXCreateBoxTest(void)
2853 HRESULT hr;
2854 IDirect3DDevice9* device;
2855 ID3DXMesh* box;
2856 ID3DXBuffer* ppBuffer;
2857 DWORD *buffer;
2858 static const DWORD adjacency[36]=
2859 {6, 9, 1, 2, 10, 0,
2860 1, 9, 3, 4, 10, 2,
2861 3, 8, 5, 7, 11, 4,
2862 0, 11, 7, 5, 8, 6,
2863 7, 4, 9, 2, 0, 8,
2864 1, 3, 11, 5, 6, 10};
2865 unsigned int i;
2866 struct test_context *test_context;
2868 if (!(test_context = new_test_context()))
2870 skip("Couldn't create test context\n");
2871 return;
2873 device = test_context->device;
2875 hr = D3DXCreateBox(device,2.0f,20.0f,4.9f,NULL, &ppBuffer);
2876 ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#lx\n", hr);
2878 hr = D3DXCreateBox(NULL,22.0f,20.0f,4.9f,&box, &ppBuffer);
2879 ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#lx\n", hr);
2881 hr = D3DXCreateBox(device,-2.0f,20.0f,4.9f,&box, &ppBuffer);
2882 ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#lx\n", hr);
2884 hr = D3DXCreateBox(device,22.0f,-20.0f,4.9f,&box, &ppBuffer);
2885 ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#lx\n", hr);
2887 hr = D3DXCreateBox(device,22.0f,20.0f,-4.9f,&box, &ppBuffer);
2888 ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#lx\n", hr);
2890 ppBuffer = NULL;
2891 hr = D3DXCreateBox(device,10.9f,20.0f,4.9f,&box, &ppBuffer);
2892 ok(hr==D3D_OK, "Expected D3D_OK, received %#lx\n", hr);
2894 buffer = ID3DXBuffer_GetBufferPointer(ppBuffer);
2895 for(i=0; i<36; i++)
2896 ok(adjacency[i]==buffer[i], "expected adjacency %d: %#lx, received %#lx\n",i,adjacency[i], buffer[i]);
2898 box->lpVtbl->Release(box);
2899 ID3DXBuffer_Release(ppBuffer);
2901 test_box(device, 10.9f, 20.0f, 4.9f);
2903 free_test_context(test_context);
2906 static BOOL compute_polygon(struct mesh *mesh, float length, unsigned int sides)
2908 unsigned int i;
2909 float angle, scale;
2911 if (!new_mesh(mesh, sides + 1, sides))
2912 return FALSE;
2914 angle = D3DX_PI / sides;
2915 scale = 0.5f * length / sinf(angle);
2916 angle *= 2.0f;
2918 mesh->vertices[0].position.x = 0.0f;
2919 mesh->vertices[0].position.y = 0.0f;
2920 mesh->vertices[0].position.z = 0.0f;
2921 mesh->vertices[0].normal.x = 0.0f;
2922 mesh->vertices[0].normal.y = 0.0f;
2923 mesh->vertices[0].normal.z = 1.0f;
2925 for (i = 0; i < sides; ++i)
2927 mesh->vertices[i + 1].position.x = cosf(angle * i) * scale;
2928 mesh->vertices[i + 1].position.y = sinf(angle * i) * scale;
2929 mesh->vertices[i + 1].position.z = 0.0f;
2930 mesh->vertices[i + 1].normal.x = 0.0f;
2931 mesh->vertices[i + 1].normal.y = 0.0f;
2932 mesh->vertices[i + 1].normal.z = 1.0f;
2934 mesh->faces[i][0] = 0;
2935 mesh->faces[i][1] = i + 1;
2936 mesh->faces[i][2] = i + 2;
2939 mesh->faces[sides - 1][2] = 1;
2941 return TRUE;
2944 static void test_polygon(IDirect3DDevice9 *device, float length, unsigned int sides)
2946 HRESULT hr;
2947 ID3DXMesh *polygon;
2948 struct mesh mesh;
2949 char name[64];
2951 hr = D3DXCreatePolygon(device, length, sides, &polygon, NULL);
2952 ok(hr == D3D_OK, "Got result %lx, expected 0 (D3D_OK)\n", hr);
2953 if (hr != D3D_OK)
2955 skip("Couldn't create polygon\n");
2956 return;
2959 if (!compute_polygon(&mesh, length, sides))
2961 skip("Couldn't create mesh\n");
2962 polygon->lpVtbl->Release(polygon);
2963 return;
2966 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
2968 sprintf(name, "polygon (%g, %u)", length, sides);
2969 compare_mesh(name, polygon, &mesh);
2971 free_mesh(&mesh);
2973 polygon->lpVtbl->Release(polygon);
2976 static void D3DXCreatePolygonTest(void)
2978 HRESULT hr;
2979 IDirect3DDevice9 *device;
2980 ID3DXMesh *polygon;
2981 ID3DXBuffer *adjacency;
2982 DWORD (*buffer)[3], buffer_size;
2983 unsigned int i;
2984 struct test_context *test_context;
2986 if (!(test_context = new_test_context()))
2988 skip("Couldn't create test context\n");
2989 return;
2991 device = test_context->device;
2993 hr = D3DXCreatePolygon(device, 2.0f, 11, NULL, &adjacency);
2994 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#lx\n", hr);
2996 hr = D3DXCreatePolygon(NULL, 2.0f, 11, &polygon, &adjacency);
2997 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#lx\n", hr);
2999 hr = D3DXCreatePolygon(device, -2.0f, 11, &polygon, &adjacency);
3000 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#lx\n", hr);
3002 polygon = (void *)0xdeadbeef;
3003 adjacency = (void *)0xdeadbeef;
3004 hr = D3DXCreatePolygon(device, 2.0f, 0, &polygon, &adjacency);
3005 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#lx\n", hr);
3006 ok(polygon == (void *)0xdeadbeef, "Polygon was changed to %p\n", polygon);
3007 ok(adjacency == (void *)0xdeadbeef, "Adjacency was changed to %p\n", adjacency);
3009 hr = D3DXCreatePolygon(device, 2.0f, 2, &polygon, &adjacency);
3010 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#lx\n", hr);
3012 adjacency = NULL;
3013 hr = D3DXCreatePolygon(device, 3.0f, 11, &polygon, &adjacency);
3014 ok(hr == D3D_OK, "Expected D3D_OK, received %#lx\n", hr);
3016 buffer_size = ID3DXBuffer_GetBufferSize(adjacency);
3017 ok(buffer_size == 33 * sizeof(DWORD), "Wrong adjacency buffer size %lu\n", buffer_size);
3019 buffer = ID3DXBuffer_GetBufferPointer(adjacency);
3020 for (i = 0; i < 11; ++i)
3022 ok(buffer[i][0] == (i + 10) % 11, "Wrong adjacency[%d][0] = %lu\n", i, buffer[i][0]);
3023 ok(buffer[i][1] == ~0U, "Wrong adjacency[%d][1] = %lu\n", i, buffer[i][1]);
3024 ok(buffer[i][2] == (i + 1) % 11, "Wrong adjacency[%d][2] = %lu\n", i, buffer[i][2]);
3027 polygon->lpVtbl->Release(polygon);
3028 ID3DXBuffer_Release(adjacency);
3030 test_polygon(device, 2.0f, 3);
3031 test_polygon(device, 10.0f, 3);
3032 test_polygon(device, 10.0f, 5);
3033 test_polygon(device, 10.0f, 10);
3034 test_polygon(device, 20.0f, 10);
3035 test_polygon(device, 20.0f, 32000);
3037 free_test_context(test_context);
3040 struct sincos_table
3042 float *sin;
3043 float *cos;
3046 static void free_sincos_table(struct sincos_table *sincos_table)
3048 free(sincos_table->cos);
3049 free(sincos_table->sin);
3052 /* pre compute sine and cosine tables; caller must free */
3053 static BOOL compute_sincos_table(struct sincos_table *sincos_table, float angle_start, float angle_step, int n)
3055 float angle;
3056 int i;
3058 sincos_table->sin = malloc(n * sizeof(*sincos_table->sin));
3059 if (!sincos_table->sin)
3061 return FALSE;
3063 sincos_table->cos = malloc(n * sizeof(*sincos_table->cos));
3064 if (!sincos_table->cos)
3066 free(sincos_table->sin);
3067 return FALSE;
3070 angle = angle_start;
3071 for (i = 0; i < n; i++)
3073 sincos_table->sin[i] = sin(angle);
3074 sincos_table->cos[i] = cos(angle);
3075 angle += angle_step;
3078 return TRUE;
3081 static WORD vertex_index(UINT slices, int slice, int stack)
3083 return stack*slices+slice+1;
3086 /* slices = subdivisions along xy plane, stacks = subdivisions along z axis */
3087 static BOOL compute_sphere(struct mesh *mesh, FLOAT radius, UINT slices, UINT stacks)
3089 float theta_step, theta_start;
3090 struct sincos_table theta;
3091 float phi_step, phi_start;
3092 struct sincos_table phi;
3093 DWORD number_of_vertices, number_of_faces;
3094 DWORD vertex, face;
3095 int slice, stack;
3097 /* theta = angle on xy plane wrt x axis */
3098 theta_step = D3DX_PI / stacks;
3099 theta_start = theta_step;
3101 /* phi = angle on xz plane wrt z axis */
3102 phi_step = -2 * D3DX_PI / slices;
3103 phi_start = D3DX_PI / 2;
3105 if (!compute_sincos_table(&theta, theta_start, theta_step, stacks))
3107 return FALSE;
3109 if (!compute_sincos_table(&phi, phi_start, phi_step, slices))
3111 free_sincos_table(&theta);
3112 return FALSE;
3115 number_of_vertices = 2 + slices * (stacks-1);
3116 number_of_faces = 2 * slices + (stacks - 2) * (2 * slices);
3118 if (!new_mesh(mesh, number_of_vertices, number_of_faces))
3120 free_sincos_table(&phi);
3121 free_sincos_table(&theta);
3122 return FALSE;
3125 vertex = 0;
3126 face = 0;
3128 mesh->vertices[vertex].normal.x = 0.0f;
3129 mesh->vertices[vertex].normal.y = 0.0f;
3130 mesh->vertices[vertex].normal.z = 1.0f;
3131 mesh->vertices[vertex].position.x = 0.0f;
3132 mesh->vertices[vertex].position.y = 0.0f;
3133 mesh->vertices[vertex].position.z = radius;
3134 vertex++;
3136 for (stack = 0; stack < stacks - 1; stack++)
3138 for (slice = 0; slice < slices; slice++)
3140 mesh->vertices[vertex].normal.x = theta.sin[stack] * phi.cos[slice];
3141 mesh->vertices[vertex].normal.y = theta.sin[stack] * phi.sin[slice];
3142 mesh->vertices[vertex].normal.z = theta.cos[stack];
3143 mesh->vertices[vertex].position.x = radius * theta.sin[stack] * phi.cos[slice];
3144 mesh->vertices[vertex].position.y = radius * theta.sin[stack] * phi.sin[slice];
3145 mesh->vertices[vertex].position.z = radius * theta.cos[stack];
3146 vertex++;
3148 if (slice > 0)
3150 if (stack == 0)
3152 /* top stack is triangle fan */
3153 mesh->faces[face][0] = 0;
3154 mesh->faces[face][1] = slice + 1;
3155 mesh->faces[face][2] = slice;
3156 face++;
3158 else
3160 /* stacks in between top and bottom are quad strips */
3161 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
3162 mesh->faces[face][1] = vertex_index(slices, slice, stack-1);
3163 mesh->faces[face][2] = vertex_index(slices, slice-1, stack);
3164 face++;
3166 mesh->faces[face][0] = vertex_index(slices, slice, stack-1);
3167 mesh->faces[face][1] = vertex_index(slices, slice, stack);
3168 mesh->faces[face][2] = vertex_index(slices, slice-1, stack);
3169 face++;
3174 if (stack == 0)
3176 mesh->faces[face][0] = 0;
3177 mesh->faces[face][1] = 1;
3178 mesh->faces[face][2] = slice;
3179 face++;
3181 else
3183 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
3184 mesh->faces[face][1] = vertex_index(slices, 0, stack-1);
3185 mesh->faces[face][2] = vertex_index(slices, slice-1, stack);
3186 face++;
3188 mesh->faces[face][0] = vertex_index(slices, 0, stack-1);
3189 mesh->faces[face][1] = vertex_index(slices, 0, stack);
3190 mesh->faces[face][2] = vertex_index(slices, slice-1, stack);
3191 face++;
3195 mesh->vertices[vertex].position.x = 0.0f;
3196 mesh->vertices[vertex].position.y = 0.0f;
3197 mesh->vertices[vertex].position.z = -radius;
3198 mesh->vertices[vertex].normal.x = 0.0f;
3199 mesh->vertices[vertex].normal.y = 0.0f;
3200 mesh->vertices[vertex].normal.z = -1.0f;
3202 /* bottom stack is triangle fan */
3203 for (slice = 1; slice < slices; slice++)
3205 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
3206 mesh->faces[face][1] = vertex_index(slices, slice, stack-1);
3207 mesh->faces[face][2] = vertex;
3208 face++;
3211 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
3212 mesh->faces[face][1] = vertex_index(slices, 0, stack-1);
3213 mesh->faces[face][2] = vertex;
3215 free_sincos_table(&phi);
3216 free_sincos_table(&theta);
3218 return TRUE;
3221 static void test_sphere(IDirect3DDevice9 *device, FLOAT radius, UINT slices, UINT stacks)
3223 HRESULT hr;
3224 ID3DXMesh *sphere;
3225 struct mesh mesh;
3226 char name[256];
3228 hr = D3DXCreateSphere(device, radius, slices, stacks, &sphere, NULL);
3229 ok(hr == D3D_OK, "Got result %lx, expected 0 (D3D_OK)\n", hr);
3230 if (hr != D3D_OK)
3232 skip("Couldn't create sphere\n");
3233 return;
3236 if (!compute_sphere(&mesh, radius, slices, stacks))
3238 skip("Couldn't create mesh\n");
3239 sphere->lpVtbl->Release(sphere);
3240 return;
3243 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
3245 sprintf(name, "sphere (%g, %u, %u)", radius, slices, stacks);
3246 compare_mesh(name, sphere, &mesh);
3248 free_mesh(&mesh);
3250 sphere->lpVtbl->Release(sphere);
3253 static void D3DXCreateSphereTest(void)
3255 HRESULT hr;
3256 IDirect3DDevice9* device;
3257 ID3DXMesh* sphere = NULL;
3258 struct test_context *test_context;
3260 hr = D3DXCreateSphere(NULL, 0.0f, 0, 0, NULL, NULL);
3261 ok(hr == D3DERR_INVALIDCALL, "Got result %lx, expected %lx (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3263 hr = D3DXCreateSphere(NULL, 0.1f, 0, 0, NULL, NULL);
3264 ok(hr == D3DERR_INVALIDCALL, "Got result %lx, expected %lx (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3266 hr = D3DXCreateSphere(NULL, 0.0f, 1, 0, NULL, NULL);
3267 ok(hr == D3DERR_INVALIDCALL, "Got result %lx, expected %lx (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3269 hr = D3DXCreateSphere(NULL, 0.0f, 0, 1, NULL, NULL);
3270 ok(hr == D3DERR_INVALIDCALL, "Got result %lx, expected %lx (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3272 if (!(test_context = new_test_context()))
3274 skip("Couldn't create test context\n");
3275 return;
3277 device = test_context->device;
3279 hr = D3DXCreateSphere(device, 1.0f, 1, 1, &sphere, NULL);
3280 ok(hr == D3DERR_INVALIDCALL, "Got result %lx, expected %lx (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3282 hr = D3DXCreateSphere(device, 1.0f, 2, 1, &sphere, NULL);
3283 ok(hr == D3DERR_INVALIDCALL, "Got result %lx, expected %lx (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
3285 hr = D3DXCreateSphere(device, 1.0f, 1, 2, &sphere, NULL);
3286 ok(hr == D3DERR_INVALIDCALL, "Got result %lx, expected %lx (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
3288 hr = D3DXCreateSphere(device, -0.1f, 1, 2, &sphere, NULL);
3289 ok(hr == D3DERR_INVALIDCALL, "Got result %lx, expected %lx (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
3291 test_sphere(device, 0.0f, 2, 2);
3292 test_sphere(device, 1.0f, 2, 2);
3293 test_sphere(device, 1.0f, 3, 2);
3294 test_sphere(device, 1.0f, 4, 4);
3295 test_sphere(device, 1.0f, 3, 4);
3296 test_sphere(device, 5.0f, 6, 7);
3297 test_sphere(device, 10.0f, 11, 12);
3299 free_test_context(test_context);
3302 static BOOL compute_cylinder(struct mesh *mesh, FLOAT radius1, FLOAT radius2, FLOAT length, UINT slices, UINT stacks)
3304 float theta_step, theta_start;
3305 struct sincos_table theta;
3306 FLOAT delta_radius, radius, radius_step;
3307 FLOAT z, z_step, z_normal;
3308 DWORD number_of_vertices, number_of_faces;
3309 DWORD vertex, face;
3310 int slice, stack;
3312 /* theta = angle on xy plane wrt x axis */
3313 theta_step = -2 * D3DX_PI / slices;
3314 theta_start = D3DX_PI / 2;
3316 if (!compute_sincos_table(&theta, theta_start, theta_step, slices))
3318 return FALSE;
3321 number_of_vertices = 2 + (slices * (3 + stacks));
3322 number_of_faces = 2 * slices + stacks * (2 * slices);
3324 if (!new_mesh(mesh, number_of_vertices, number_of_faces))
3326 free_sincos_table(&theta);
3327 return FALSE;
3330 vertex = 0;
3331 face = 0;
3333 delta_radius = radius1 - radius2;
3334 radius = radius1;
3335 radius_step = delta_radius / stacks;
3337 z = -length / 2;
3338 z_step = length / stacks;
3339 z_normal = delta_radius / length;
3340 if (isnan(z_normal))
3342 z_normal = 0.0f;
3345 mesh->vertices[vertex].normal.x = 0.0f;
3346 mesh->vertices[vertex].normal.y = 0.0f;
3347 mesh->vertices[vertex].normal.z = -1.0f;
3348 mesh->vertices[vertex].position.x = 0.0f;
3349 mesh->vertices[vertex].position.y = 0.0f;
3350 mesh->vertices[vertex++].position.z = z;
3352 for (slice = 0; slice < slices; slice++, vertex++)
3354 mesh->vertices[vertex].normal.x = 0.0f;
3355 mesh->vertices[vertex].normal.y = 0.0f;
3356 mesh->vertices[vertex].normal.z = -1.0f;
3357 mesh->vertices[vertex].position.x = radius * theta.cos[slice];
3358 mesh->vertices[vertex].position.y = radius * theta.sin[slice];
3359 mesh->vertices[vertex].position.z = z;
3361 if (slice > 0)
3363 mesh->faces[face][0] = 0;
3364 mesh->faces[face][1] = slice;
3365 mesh->faces[face++][2] = slice + 1;
3369 mesh->faces[face][0] = 0;
3370 mesh->faces[face][1] = slice;
3371 mesh->faces[face++][2] = 1;
3373 for (stack = 1; stack <= stacks+1; stack++)
3375 for (slice = 0; slice < slices; slice++, vertex++)
3377 mesh->vertices[vertex].normal.x = theta.cos[slice];
3378 mesh->vertices[vertex].normal.y = theta.sin[slice];
3379 mesh->vertices[vertex].normal.z = z_normal;
3380 D3DXVec3Normalize(&mesh->vertices[vertex].normal, &mesh->vertices[vertex].normal);
3381 mesh->vertices[vertex].position.x = radius * theta.cos[slice];
3382 mesh->vertices[vertex].position.y = radius * theta.sin[slice];
3383 mesh->vertices[vertex].position.z = z;
3385 if (stack > 1 && slice > 0)
3387 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
3388 mesh->faces[face][1] = vertex_index(slices, slice-1, stack);
3389 mesh->faces[face++][2] = vertex_index(slices, slice, stack-1);
3391 mesh->faces[face][0] = vertex_index(slices, slice, stack-1);
3392 mesh->faces[face][1] = vertex_index(slices, slice-1, stack);
3393 mesh->faces[face++][2] = vertex_index(slices, slice, stack);
3397 if (stack > 1)
3399 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
3400 mesh->faces[face][1] = vertex_index(slices, slice-1, stack);
3401 mesh->faces[face++][2] = vertex_index(slices, 0, stack-1);
3403 mesh->faces[face][0] = vertex_index(slices, 0, stack-1);
3404 mesh->faces[face][1] = vertex_index(slices, slice-1, stack);
3405 mesh->faces[face++][2] = vertex_index(slices, 0, stack);
3408 if (stack < stacks + 1)
3410 z += z_step;
3411 radius -= radius_step;
3415 for (slice = 0; slice < slices; slice++, vertex++)
3417 mesh->vertices[vertex].normal.x = 0.0f;
3418 mesh->vertices[vertex].normal.y = 0.0f;
3419 mesh->vertices[vertex].normal.z = 1.0f;
3420 mesh->vertices[vertex].position.x = radius * theta.cos[slice];
3421 mesh->vertices[vertex].position.y = radius * theta.sin[slice];
3422 mesh->vertices[vertex].position.z = z;
3424 if (slice > 0)
3426 mesh->faces[face][0] = vertex_index(slices, slice-1, stack);
3427 mesh->faces[face][1] = number_of_vertices - 1;
3428 mesh->faces[face++][2] = vertex_index(slices, slice, stack);
3432 mesh->vertices[vertex].position.x = 0.0f;
3433 mesh->vertices[vertex].position.y = 0.0f;
3434 mesh->vertices[vertex].position.z = z;
3435 mesh->vertices[vertex].normal.x = 0.0f;
3436 mesh->vertices[vertex].normal.y = 0.0f;
3437 mesh->vertices[vertex].normal.z = 1.0f;
3439 mesh->faces[face][0] = vertex_index(slices, slice-1, stack);
3440 mesh->faces[face][1] = number_of_vertices - 1;
3441 mesh->faces[face][2] = vertex_index(slices, 0, stack);
3443 free_sincos_table(&theta);
3445 return TRUE;
3448 static void test_cylinder(IDirect3DDevice9 *device, FLOAT radius1, FLOAT radius2, FLOAT length, UINT slices, UINT stacks)
3450 HRESULT hr;
3451 ID3DXMesh *cylinder;
3452 struct mesh mesh;
3453 char name[256];
3455 hr = D3DXCreateCylinder(device, radius1, radius2, length, slices, stacks, &cylinder, NULL);
3456 ok(hr == D3D_OK, "Got result %lx, expected 0 (D3D_OK)\n", hr);
3457 if (hr != D3D_OK)
3459 skip("Couldn't create cylinder\n");
3460 return;
3463 if (!compute_cylinder(&mesh, radius1, radius2, length, slices, stacks))
3465 skip("Couldn't create mesh\n");
3466 cylinder->lpVtbl->Release(cylinder);
3467 return;
3470 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
3472 sprintf(name, "cylinder (%g, %g, %g, %u, %u)", radius1, radius2, length, slices, stacks);
3473 compare_mesh(name, cylinder, &mesh);
3475 free_mesh(&mesh);
3477 cylinder->lpVtbl->Release(cylinder);
3480 static void D3DXCreateCylinderTest(void)
3482 HRESULT hr;
3483 IDirect3DDevice9* device;
3484 ID3DXMesh* cylinder = NULL;
3485 struct test_context *test_context;
3487 hr = D3DXCreateCylinder(NULL, 0.0f, 0.0f, 0.0f, 0, 0, NULL, NULL);
3488 ok(hr == D3DERR_INVALIDCALL, "Got result %lx, expected %lx (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3490 hr = D3DXCreateCylinder(NULL, 1.0f, 1.0f, 1.0f, 2, 1, &cylinder, NULL);
3491 ok(hr == D3DERR_INVALIDCALL, "Got result %lx, expected %lx (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3493 if (!(test_context = new_test_context()))
3495 skip("Couldn't create test context\n");
3496 return;
3498 device = test_context->device;
3500 hr = D3DXCreateCylinder(device, -0.1f, 1.0f, 1.0f, 2, 1, &cylinder, NULL);
3501 ok(hr == D3DERR_INVALIDCALL, "Got result %lx, expected %lx (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3503 hr = D3DXCreateCylinder(device, 0.0f, 1.0f, 1.0f, 2, 1, &cylinder, NULL);
3504 ok(hr == D3D_OK, "Got result %lx, expected 0 (D3D_OK)\n",hr);
3506 if (SUCCEEDED(hr) && cylinder)
3508 cylinder->lpVtbl->Release(cylinder);
3511 hr = D3DXCreateCylinder(device, 1.0f, -0.1f, 1.0f, 2, 1, &cylinder, NULL);
3512 ok(hr == D3DERR_INVALIDCALL, "Got result %lx, expected %lx (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3514 hr = D3DXCreateCylinder(device, 1.0f, 0.0f, 1.0f, 2, 1, &cylinder, NULL);
3515 ok(hr == D3D_OK, "Got result %lx, expected 0 (D3D_OK)\n",hr);
3517 if (SUCCEEDED(hr) && cylinder)
3519 cylinder->lpVtbl->Release(cylinder);
3522 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, -0.1f, 2, 1, &cylinder, NULL);
3523 ok(hr == D3DERR_INVALIDCALL, "Got result %lx, expected %lx (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3525 /* Test with length == 0.0f succeeds */
3526 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, 0.0f, 2, 1, &cylinder, NULL);
3527 ok(hr == D3D_OK, "Got result %lx, expected 0 (D3D_OK)\n",hr);
3529 if (SUCCEEDED(hr) && cylinder)
3531 cylinder->lpVtbl->Release(cylinder);
3534 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, 1.0f, 1, 1, &cylinder, NULL);
3535 ok(hr == D3DERR_INVALIDCALL, "Got result %lx, expected %lx (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3537 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, 1.0f, 2, 0, &cylinder, NULL);
3538 ok(hr == D3DERR_INVALIDCALL, "Got result %lx, expected %lx (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3540 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, 1.0f, 2, 1, NULL, NULL);
3541 ok(hr == D3DERR_INVALIDCALL, "Got result %lx, expected %lx (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3543 test_cylinder(device, 0.0f, 0.0f, 0.0f, 2, 1);
3544 test_cylinder(device, 1.0f, 1.0f, 1.0f, 2, 1);
3545 test_cylinder(device, 1.0f, 1.0f, 2.0f, 3, 4);
3546 test_cylinder(device, 3.0f, 2.0f, 4.0f, 3, 4);
3547 test_cylinder(device, 2.0f, 3.0f, 4.0f, 3, 4);
3548 test_cylinder(device, 3.0f, 4.0f, 5.0f, 11, 20);
3550 free_test_context(test_context);
3553 static BOOL compute_torus(struct mesh *mesh, float innerradius, float outerradius, UINT sides, UINT rings)
3555 float phi, phi_step, sin_phi, cos_phi;
3556 float theta, theta_step, sin_theta, cos_theta;
3557 unsigned int numvert, numfaces, i, j;
3559 numvert = sides * rings;
3560 numfaces = numvert * 2;
3562 if (!new_mesh(mesh, numvert, numfaces))
3563 return FALSE;
3565 phi_step = D3DX_PI / sides * 2.0f;
3566 theta_step = D3DX_PI / rings * -2.0f;
3568 theta = 0.0f;
3570 for (i = 0; i < rings; ++i)
3572 phi = 0.0f;
3574 cos_theta = cosf(theta);
3575 sin_theta = sinf(theta);
3577 for (j = 0; j < sides; ++j)
3579 sin_phi = sinf(phi);
3580 cos_phi = cosf(phi);
3582 mesh->vertices[i * sides + j].position.x = (innerradius * cos_phi + outerradius) * cos_theta;
3583 mesh->vertices[i * sides + j].position.y = (innerradius * cos_phi + outerradius) * sin_theta;
3584 mesh->vertices[i * sides + j].position.z = innerradius * sin_phi;
3585 mesh->vertices[i * sides + j].normal.x = cos_phi * cos_theta;
3586 mesh->vertices[i * sides + j].normal.y = cos_phi * sin_theta;
3587 mesh->vertices[i * sides + j].normal.z = sin_phi;
3589 phi += phi_step;
3592 theta += theta_step;
3595 for (i = 0; i < numfaces - sides * 2; ++i)
3597 mesh->faces[i][0] = i % 2 ? i / 2 + sides : i / 2;
3598 mesh->faces[i][1] = (i / 2 + 1) % sides ? i / 2 + 1 : i / 2 + 1 - sides;
3599 mesh->faces[i][2] = (i + 1) % (sides * 2) ? (i + 1) / 2 + sides : (i + 1) / 2;
3602 for (j = 0; i < numfaces; ++i, ++j)
3604 mesh->faces[i][0] = i % 2 ? j / 2 : i / 2;
3605 mesh->faces[i][1] = (i / 2 + 1) % sides ? i / 2 + 1 : i / 2 + 1 - sides;
3606 mesh->faces[i][2] = i == numfaces - 1 ? 0 : (j + 1) / 2;
3609 return TRUE;
3612 static void test_torus(IDirect3DDevice9 *device, float innerradius, float outerradius, UINT sides, UINT rings)
3614 HRESULT hr;
3615 ID3DXMesh *torus;
3616 struct mesh mesh;
3617 char name[256];
3619 hr = D3DXCreateTorus(device, innerradius, outerradius, sides, rings, &torus, NULL);
3620 ok(hr == D3D_OK, "Got result %#lx, expected 0 (D3D_OK)\n", hr);
3621 if (hr != D3D_OK)
3623 skip("Couldn't create torus\n");
3624 return;
3627 if (!compute_torus(&mesh, innerradius, outerradius, sides, rings))
3629 skip("Couldn't create mesh\n");
3630 torus->lpVtbl->Release(torus);
3631 return;
3634 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
3636 sprintf(name, "torus (%g, %g, %u, %u)", innerradius, outerradius, sides, rings);
3637 compare_mesh(name, torus, &mesh);
3639 free_mesh(&mesh);
3641 torus->lpVtbl->Release(torus);
3644 static void D3DXCreateTorusTest(void)
3646 HRESULT hr;
3647 IDirect3DDevice9* device;
3648 ID3DXMesh* torus = NULL;
3649 struct test_context *test_context;
3651 if (!(test_context = new_test_context()))
3653 skip("Couldn't create test context\n");
3654 return;
3656 device = test_context->device;
3658 hr = D3DXCreateTorus(NULL, 0.0f, 0.0f, 3, 3, &torus, NULL);
3659 ok(hr == D3DERR_INVALIDCALL, "Got result %#lx, expected %#lx (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
3661 hr = D3DXCreateTorus(device, -1.0f, 0.0f, 3, 3, &torus, NULL);
3662 ok(hr == D3DERR_INVALIDCALL, "Got result %#lx, expected %#lx (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
3664 hr = D3DXCreateTorus(device, 0.0f, -1.0f, 3, 3, &torus, NULL);
3665 ok(hr == D3DERR_INVALIDCALL, "Got result %#lx, expected %#lx (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
3667 hr = D3DXCreateTorus(device, 0.0f, 0.0f, 2, 3, &torus, NULL);
3668 ok(hr == D3DERR_INVALIDCALL, "Got result %#lx, expected %#lx (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
3670 hr = D3DXCreateTorus(device, 0.0f, 0.0f, 3, 2, &torus, NULL);
3671 ok(hr == D3DERR_INVALIDCALL, "Got result %#lx, expected %#lx (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
3673 hr = D3DXCreateTorus(device, 0.0f, 0.0f, 3, 3, NULL, NULL);
3674 ok(hr == D3DERR_INVALIDCALL, "Got result %#lx, expected %#lx (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
3676 test_torus(device, 0.0f, 0.0f, 3, 3);
3677 test_torus(device, 1.0f, 1.0f, 3, 3);
3678 test_torus(device, 1.0f, 1.0f, 32, 64);
3679 test_torus(device, 0.0f, 1.0f, 5, 5);
3680 test_torus(device, 1.0f, 0.0f, 5, 5);
3681 test_torus(device, 5.0f, 0.2f, 8, 8);
3682 test_torus(device, 0.2f, 1.0f, 60, 3);
3683 test_torus(device, 0.2f, 1.0f, 8, 70);
3685 free_test_context(test_context);
3688 struct dynamic_array
3690 int count, capacity;
3691 void *items;
3694 enum pointtype {
3695 POINTTYPE_CURVE = 0,
3696 POINTTYPE_CORNER,
3697 POINTTYPE_CURVE_START,
3698 POINTTYPE_CURVE_END,
3699 POINTTYPE_CURVE_MIDDLE,
3702 struct point2d
3704 D3DXVECTOR2 pos;
3705 enum pointtype corner;
3708 /* is a dynamic_array */
3709 struct outline
3711 int count, capacity;
3712 struct point2d *items;
3715 /* is a dynamic_array */
3716 struct outline_array
3718 int count, capacity;
3719 struct outline *items;
3722 struct glyphinfo
3724 struct outline_array outlines;
3725 float offset_x;
3728 static BOOL reserve(struct dynamic_array *array, int count, int itemsize)
3730 if (count > array->capacity) {
3731 void *new_buffer;
3732 int new_capacity;
3733 if (array->items && array->capacity) {
3734 new_capacity = max(array->capacity * 2, count);
3735 new_buffer = realloc(array->items, new_capacity * itemsize);
3736 } else {
3737 new_capacity = max(16, count);
3738 new_buffer = malloc(new_capacity * itemsize);
3740 if (!new_buffer)
3741 return FALSE;
3742 array->items = new_buffer;
3743 array->capacity = new_capacity;
3745 return TRUE;
3748 static struct point2d *add_point(struct outline *array)
3750 struct point2d *item;
3752 if (!reserve((struct dynamic_array *)array, array->count + 1, sizeof(array->items[0])))
3753 return NULL;
3755 item = &array->items[array->count++];
3756 ZeroMemory(item, sizeof(*item));
3757 return item;
3760 static struct outline *add_outline(struct outline_array *array)
3762 struct outline *item;
3764 if (!reserve((struct dynamic_array *)array, array->count + 1, sizeof(array->items[0])))
3765 return NULL;
3767 item = &array->items[array->count++];
3768 ZeroMemory(item, sizeof(*item));
3769 return item;
3772 static inline D3DXVECTOR2 *convert_fixed_to_float(POINTFX *pt, int count, float emsquare)
3774 D3DXVECTOR2 *ret = (D3DXVECTOR2*)pt;
3775 while (count--) {
3776 D3DXVECTOR2 *pt_flt = (D3DXVECTOR2*)pt;
3777 pt_flt->x = (pt->x.value + pt->x.fract / (float)0x10000) / emsquare;
3778 pt_flt->y = (pt->y.value + pt->y.fract / (float)0x10000) / emsquare;
3779 pt++;
3781 return ret;
3784 static HRESULT add_bezier_points(struct outline *outline, const D3DXVECTOR2 *p1,
3785 const D3DXVECTOR2 *p2, const D3DXVECTOR2 *p3,
3786 float max_deviation)
3788 D3DXVECTOR2 split1 = {0, 0}, split2 = {0, 0}, middle, vec;
3789 float deviation;
3791 D3DXVec2Scale(&split1, D3DXVec2Add(&split1, p1, p2), 0.5f);
3792 D3DXVec2Scale(&split2, D3DXVec2Add(&split2, p2, p3), 0.5f);
3793 D3DXVec2Scale(&middle, D3DXVec2Add(&middle, &split1, &split2), 0.5f);
3795 deviation = D3DXVec2Length(D3DXVec2Subtract(&vec, &middle, p2));
3796 if (deviation < max_deviation) {
3797 struct point2d *pt = add_point(outline);
3798 if (!pt) return E_OUTOFMEMORY;
3799 pt->pos = *p2;
3800 pt->corner = POINTTYPE_CURVE;
3801 /* the end point is omitted because the end line merges into the next segment of
3802 * the split bezier curve, and the end of the split bezier curve is added outside
3803 * this recursive function. */
3804 } else {
3805 HRESULT hr = add_bezier_points(outline, p1, &split1, &middle, max_deviation);
3806 if (hr != S_OK) return hr;
3807 hr = add_bezier_points(outline, &middle, &split2, p3, max_deviation);
3808 if (hr != S_OK) return hr;
3811 return S_OK;
3814 static inline BOOL is_direction_similar(D3DXVECTOR2 *dir1, D3DXVECTOR2 *dir2, float cos_theta)
3816 /* dot product = cos(theta) */
3817 return D3DXVec2Dot(dir1, dir2) > cos_theta;
3820 static inline D3DXVECTOR2 *unit_vec2(D3DXVECTOR2 *dir, const D3DXVECTOR2 *pt1, const D3DXVECTOR2 *pt2)
3822 return D3DXVec2Normalize(dir, D3DXVec2Subtract(dir, pt2, pt1));
3825 static BOOL attempt_line_merge(struct outline *outline,
3826 int pt_index,
3827 const D3DXVECTOR2 *nextpt,
3828 BOOL to_curve)
3830 D3DXVECTOR2 curdir, lastdir;
3831 struct point2d *prevpt, *pt;
3832 BOOL ret = FALSE;
3833 const float cos_half = cos(D3DXToRadian(0.5f));
3835 pt = &outline->items[pt_index];
3836 pt_index = (pt_index - 1 + outline->count) % outline->count;
3837 prevpt = &outline->items[pt_index];
3839 if (to_curve)
3840 pt->corner = pt->corner != POINTTYPE_CORNER ? POINTTYPE_CURVE_MIDDLE : POINTTYPE_CURVE_START;
3842 if (outline->count < 2)
3843 return FALSE;
3845 /* remove last point if the next line continues the last line */
3846 unit_vec2(&lastdir, &prevpt->pos, &pt->pos);
3847 unit_vec2(&curdir, &pt->pos, nextpt);
3848 if (is_direction_similar(&lastdir, &curdir, cos_half))
3850 outline->count--;
3851 if (pt->corner == POINTTYPE_CURVE_END)
3852 prevpt->corner = pt->corner;
3853 if (prevpt->corner == POINTTYPE_CURVE_END && to_curve)
3854 prevpt->corner = POINTTYPE_CURVE_MIDDLE;
3855 pt = prevpt;
3857 ret = TRUE;
3858 if (outline->count < 2)
3859 return ret;
3861 pt_index = (pt_index - 1 + outline->count) % outline->count;
3862 prevpt = &outline->items[pt_index];
3863 unit_vec2(&lastdir, &prevpt->pos, &pt->pos);
3864 unit_vec2(&curdir, &pt->pos, nextpt);
3866 return ret;
3869 static HRESULT create_outline(struct glyphinfo *glyph, void *raw_outline, int datasize,
3870 float max_deviation, float emsquare)
3872 const float cos_45 = cos(D3DXToRadian(45.0f));
3873 const float cos_90 = cos(D3DXToRadian(90.0f));
3874 TTPOLYGONHEADER *header = (TTPOLYGONHEADER *)raw_outline;
3876 while ((char *)header < (char *)raw_outline + datasize)
3878 TTPOLYCURVE *curve = (TTPOLYCURVE *)(header + 1);
3879 struct point2d *lastpt, *pt;
3880 D3DXVECTOR2 lastdir;
3881 D3DXVECTOR2 *pt_flt;
3882 int j;
3883 struct outline *outline = add_outline(&glyph->outlines);
3885 if (!outline)
3886 return E_OUTOFMEMORY;
3888 pt = add_point(outline);
3889 if (!pt)
3890 return E_OUTOFMEMORY;
3891 pt_flt = convert_fixed_to_float(&header->pfxStart, 1, emsquare);
3892 pt->pos = *pt_flt;
3893 pt->corner = POINTTYPE_CORNER;
3895 if (header->dwType != TT_POLYGON_TYPE)
3896 trace("Unknown header type %ld\n", header->dwType);
3898 while ((char *)curve < (char *)header + header->cb)
3900 D3DXVECTOR2 bezier_start = outline->items[outline->count - 1].pos;
3901 BOOL to_curve = curve->wType != TT_PRIM_LINE && curve->cpfx > 1;
3903 if (!curve->cpfx) {
3904 curve = (TTPOLYCURVE *)&curve->apfx[curve->cpfx];
3905 continue;
3908 pt_flt = convert_fixed_to_float(curve->apfx, curve->cpfx, emsquare);
3910 attempt_line_merge(outline, outline->count - 1, &pt_flt[0], to_curve);
3912 if (to_curve)
3914 HRESULT hr;
3915 int count = curve->cpfx;
3916 j = 0;
3918 while (count > 2)
3920 D3DXVECTOR2 bezier_end;
3922 D3DXVec2Scale(&bezier_end, D3DXVec2Add(&bezier_end, &pt_flt[j], &pt_flt[j+1]), 0.5f);
3923 hr = add_bezier_points(outline, &bezier_start, &pt_flt[j], &bezier_end, max_deviation);
3924 if (hr != S_OK)
3925 return hr;
3926 bezier_start = bezier_end;
3927 count--;
3928 j++;
3930 hr = add_bezier_points(outline, &bezier_start, &pt_flt[j], &pt_flt[j+1], max_deviation);
3931 if (hr != S_OK)
3932 return hr;
3934 pt = add_point(outline);
3935 if (!pt)
3936 return E_OUTOFMEMORY;
3937 j++;
3938 pt->pos = pt_flt[j];
3939 pt->corner = POINTTYPE_CURVE_END;
3940 } else {
3941 for (j = 0; j < curve->cpfx; j++)
3943 pt = add_point(outline);
3944 if (!pt)
3945 return E_OUTOFMEMORY;
3946 pt->pos = pt_flt[j];
3947 pt->corner = POINTTYPE_CORNER;
3951 curve = (TTPOLYCURVE *)&curve->apfx[curve->cpfx];
3954 /* remove last point if the next line continues the last line */
3955 if (outline->count >= 3) {
3956 BOOL to_curve;
3958 lastpt = &outline->items[outline->count - 1];
3959 pt = &outline->items[0];
3960 if (pt->pos.x == lastpt->pos.x && pt->pos.y == lastpt->pos.y) {
3961 if (lastpt->corner == POINTTYPE_CURVE_END)
3963 if (pt->corner == POINTTYPE_CURVE_START)
3964 pt->corner = POINTTYPE_CURVE_MIDDLE;
3965 else
3966 pt->corner = POINTTYPE_CURVE_END;
3968 outline->count--;
3969 } else {
3970 /* outline closed with a line from end to start point */
3971 attempt_line_merge(outline, outline->count - 1, &pt->pos, FALSE);
3973 lastpt = &outline->items[0];
3974 to_curve = lastpt->corner != POINTTYPE_CORNER && lastpt->corner != POINTTYPE_CURVE_END;
3975 if (lastpt->corner == POINTTYPE_CURVE_START)
3976 lastpt->corner = POINTTYPE_CORNER;
3977 pt = &outline->items[1];
3978 if (attempt_line_merge(outline, 0, &pt->pos, to_curve))
3979 *lastpt = outline->items[outline->count];
3982 lastpt = &outline->items[outline->count - 1];
3983 pt = &outline->items[0];
3984 unit_vec2(&lastdir, &lastpt->pos, &pt->pos);
3985 for (j = 0; j < outline->count; j++)
3987 D3DXVECTOR2 curdir;
3989 lastpt = pt;
3990 pt = &outline->items[(j + 1) % outline->count];
3991 unit_vec2(&curdir, &lastpt->pos, &pt->pos);
3993 switch (lastpt->corner)
3995 case POINTTYPE_CURVE_START:
3996 case POINTTYPE_CURVE_END:
3997 if (!is_direction_similar(&lastdir, &curdir, cos_45))
3998 lastpt->corner = POINTTYPE_CORNER;
3999 break;
4000 case POINTTYPE_CURVE_MIDDLE:
4001 if (!is_direction_similar(&lastdir, &curdir, cos_90))
4002 lastpt->corner = POINTTYPE_CORNER;
4003 else
4004 lastpt->corner = POINTTYPE_CURVE;
4005 break;
4006 default:
4007 break;
4009 lastdir = curdir;
4012 header = (TTPOLYGONHEADER *)((char *)header + header->cb);
4014 return S_OK;
4017 static void free_outline(struct outline *outline)
4019 free(outline->items);
4022 static void free_glyphinfo(struct glyphinfo *glyph)
4024 unsigned int i;
4026 for (i = 0; i < glyph->outlines.count; ++i)
4027 free_outline(&glyph->outlines.items[i]);
4028 free(glyph->outlines.items);
4031 static void compute_text_mesh(struct mesh *mesh, const char *text,
4032 float deviation, float extrusion, float otmEMSquare, const struct glyphinfo *glyphs)
4034 DWORD nb_vertices, nb_faces;
4035 DWORD nb_corners, nb_outline_points;
4036 int textlen = 0;
4037 int i;
4038 struct vertex *vertex_ptr;
4039 face *face_ptr;
4041 textlen = strlen(text);
4043 /* corner points need an extra vertex for the different side faces normals */
4044 nb_corners = 0;
4045 nb_outline_points = 0;
4046 for (i = 0; i < textlen; i++)
4048 int j;
4049 for (j = 0; j < glyphs[i].outlines.count; j++)
4051 int k;
4052 struct outline *outline = &glyphs[i].outlines.items[j];
4053 nb_outline_points += outline->count;
4054 nb_corners++; /* first outline point always repeated as a corner */
4055 for (k = 1; k < outline->count; k++)
4056 if (outline->items[k].corner)
4057 nb_corners++;
4061 nb_vertices = (nb_outline_points + nb_corners) * 2 + textlen;
4062 nb_faces = nb_outline_points * 2;
4064 ok(new_mesh(mesh, nb_vertices, nb_faces), "Failed to create reference text mesh.\n");
4066 /* convert 2D vertices and faces into 3D mesh */
4067 vertex_ptr = mesh->vertices;
4068 face_ptr = mesh->faces;
4069 for (i = 0; i < textlen; i++)
4071 int j;
4073 /* side vertices and faces */
4074 for (j = 0; j < glyphs[i].outlines.count; j++)
4076 struct vertex *outline_vertices = vertex_ptr;
4077 struct outline *outline = &glyphs[i].outlines.items[j];
4078 int k;
4079 struct point2d *prevpt = &outline->items[outline->count - 1];
4080 struct point2d *pt = &outline->items[0];
4082 for (k = 1; k <= outline->count; k++)
4084 struct vertex vtx;
4085 struct point2d *nextpt = &outline->items[k % outline->count];
4086 WORD vtx_idx = vertex_ptr - mesh->vertices;
4087 D3DXVECTOR2 vec;
4089 if (pt->corner == POINTTYPE_CURVE_START)
4090 D3DXVec2Subtract(&vec, &pt->pos, &prevpt->pos);
4091 else if (pt->corner)
4092 D3DXVec2Subtract(&vec, &nextpt->pos, &pt->pos);
4093 else
4094 D3DXVec2Subtract(&vec, &nextpt->pos, &prevpt->pos);
4095 D3DXVec2Normalize(&vec, &vec);
4096 vtx.normal.x = -vec.y;
4097 vtx.normal.y = vec.x;
4098 vtx.normal.z = 0;
4100 vtx.position.x = pt->pos.x + glyphs[i].offset_x;
4101 vtx.position.y = pt->pos.y;
4102 vtx.position.z = 0;
4103 *vertex_ptr++ = vtx;
4105 vtx.position.z = -extrusion;
4106 *vertex_ptr++ = vtx;
4108 vtx.position.x = nextpt->pos.x + glyphs[i].offset_x;
4109 vtx.position.y = nextpt->pos.y;
4110 if (pt->corner && nextpt->corner && nextpt->corner != POINTTYPE_CURVE_END) {
4111 vtx.position.z = -extrusion;
4112 *vertex_ptr++ = vtx;
4113 vtx.position.z = 0;
4114 *vertex_ptr++ = vtx;
4116 (*face_ptr)[0] = vtx_idx;
4117 (*face_ptr)[1] = vtx_idx + 2;
4118 (*face_ptr)[2] = vtx_idx + 1;
4119 face_ptr++;
4121 (*face_ptr)[0] = vtx_idx;
4122 (*face_ptr)[1] = vtx_idx + 3;
4123 (*face_ptr)[2] = vtx_idx + 2;
4124 face_ptr++;
4125 } else {
4126 if (nextpt->corner) {
4127 if (nextpt->corner == POINTTYPE_CURVE_END) {
4128 struct point2d *nextpt2 = &outline->items[(k + 1) % outline->count];
4129 D3DXVec2Subtract(&vec, &nextpt2->pos, &nextpt->pos);
4130 } else {
4131 D3DXVec2Subtract(&vec, &nextpt->pos, &pt->pos);
4133 D3DXVec2Normalize(&vec, &vec);
4134 vtx.normal.x = -vec.y;
4135 vtx.normal.y = vec.x;
4137 vtx.position.z = 0;
4138 *vertex_ptr++ = vtx;
4139 vtx.position.z = -extrusion;
4140 *vertex_ptr++ = vtx;
4143 (*face_ptr)[0] = vtx_idx;
4144 (*face_ptr)[1] = vtx_idx + 3;
4145 (*face_ptr)[2] = vtx_idx + 1;
4146 face_ptr++;
4148 (*face_ptr)[0] = vtx_idx;
4149 (*face_ptr)[1] = vtx_idx + 2;
4150 (*face_ptr)[2] = vtx_idx + 3;
4151 face_ptr++;
4154 prevpt = pt;
4155 pt = nextpt;
4157 if (!pt->corner) {
4158 *vertex_ptr++ = *outline_vertices++;
4159 *vertex_ptr++ = *outline_vertices++;
4163 /* FIXME: compute expected faces */
4164 /* Add placeholder to separate glyph outlines */
4165 vertex_ptr->position.x = 0;
4166 vertex_ptr->position.y = 0;
4167 vertex_ptr->position.z = 0;
4168 vertex_ptr->normal.x = 0;
4169 vertex_ptr->normal.y = 0;
4170 vertex_ptr->normal.z = 1;
4171 vertex_ptr++;
4175 static void compare_text_outline_mesh(const char *name, ID3DXMesh *d3dxmesh, struct mesh *mesh,
4176 size_t textlen, float extrusion, const struct glyphinfo *glyphs)
4178 HRESULT hr;
4179 DWORD number_of_vertices, number_of_faces;
4180 IDirect3DVertexBuffer9 *vertex_buffer = NULL;
4181 IDirect3DIndexBuffer9 *index_buffer = NULL;
4182 D3DVERTEXBUFFER_DESC vertex_buffer_description;
4183 D3DINDEXBUFFER_DESC index_buffer_description;
4184 struct vertex *vertices = NULL;
4185 face *faces = NULL;
4186 int expected, i;
4187 int vtx_idx1, face_idx1, vtx_idx2, face_idx2;
4189 number_of_vertices = d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh);
4190 number_of_faces = d3dxmesh->lpVtbl->GetNumFaces(d3dxmesh);
4192 hr = d3dxmesh->lpVtbl->GetVertexBuffer(d3dxmesh, &vertex_buffer);
4193 ok(hr == D3D_OK, "Test %s, unexpected hr %#lx.\n", name, hr);
4194 hr = IDirect3DVertexBuffer9_GetDesc(vertex_buffer, &vertex_buffer_description);
4195 ok(hr == D3D_OK, "Test %s, unexpected hr %#lx.\n", name, hr);
4196 ok(vertex_buffer_description.Format == D3DFMT_VERTEXDATA, "Test %s, unexpected format %u.\n",
4197 name, vertex_buffer_description.Format);
4198 ok(vertex_buffer_description.Type == D3DRTYPE_VERTEXBUFFER, "Test %s, unexpected resource type %u.\n",
4199 name, vertex_buffer_description.Type);
4200 ok(!vertex_buffer_description.Usage, "Test %s, unexpected usage %#lx.\n", name, vertex_buffer_description.Usage);
4201 ok(vertex_buffer_description.Pool == D3DPOOL_MANAGED, "Test %s, unexpected pool %u.\n",
4202 name, vertex_buffer_description.Pool);
4203 ok(vertex_buffer_description.FVF == mesh->fvf, "Test %s, unexpected FVF %#lx (expected %#lx).\n",
4204 name, vertex_buffer_description.FVF, mesh->fvf);
4205 if (!mesh->fvf)
4206 expected = number_of_vertices * mesh->vertex_size;
4207 else
4208 expected = number_of_vertices * D3DXGetFVFVertexSize(mesh->fvf);
4209 ok(vertex_buffer_description.Size == expected, "Test %s, unexpected size %u (expected %u).\n",
4210 name, vertex_buffer_description.Size, expected);
4212 hr = d3dxmesh->lpVtbl->GetIndexBuffer(d3dxmesh, &index_buffer);
4213 ok(hr == D3D_OK, "Test %s, unexpected hr %#lx.\n", name, hr);
4214 hr = IDirect3DIndexBuffer9_GetDesc(index_buffer, &index_buffer_description);
4215 ok(hr == D3D_OK, "Test %s, unexpected hr %#lx.\n", name, hr);
4216 ok(index_buffer_description.Format == D3DFMT_INDEX16, "Test %s, unexpected format %u.\n",
4217 name, index_buffer_description.Format);
4218 ok(index_buffer_description.Type == D3DRTYPE_INDEXBUFFER, "Test %s, unexpected resource type %u.\n",
4219 name, index_buffer_description.Type);
4220 ok(!index_buffer_description.Usage, "Test %s, unexpected usage %#lx.\n",
4221 name, index_buffer_description.Usage);
4222 ok(index_buffer_description.Pool == D3DPOOL_MANAGED, "Test %s, unexpected pool %u.\n",
4223 name, index_buffer_description.Pool);
4224 expected = number_of_faces * sizeof(WORD) * 3;
4225 ok(index_buffer_description.Size == expected, "Test %s, unexpected size %u.\n",
4226 name, index_buffer_description.Size);
4228 hr = IDirect3DVertexBuffer9_Lock(vertex_buffer, 0, number_of_vertices * sizeof(D3DXVECTOR3) * 2,
4229 (void **)&vertices, D3DLOCK_DISCARD);
4230 ok(hr == D3D_OK, "Test %s, unexpected hr %#lx.\n", name, hr);
4231 hr = IDirect3DIndexBuffer9_Lock(index_buffer, 0, number_of_faces * sizeof(WORD) * 3,
4232 (void **)&faces, D3DLOCK_DISCARD);
4233 ok(hr == D3D_OK, "Test %s, unexpected hr %#lx.\n", name, hr);
4234 face_idx1 = 0;
4235 vtx_idx2 = 0;
4236 face_idx2 = 0;
4237 vtx_idx1 = 0;
4238 for (i = 0; i < textlen; i++)
4240 int nb_outline_vertices1, nb_outline_faces1;
4241 int nb_outline_vertices2, nb_outline_faces2;
4242 int nb_back_vertices, nb_back_faces;
4243 int first_vtx1, first_vtx2;
4244 int first_face1, first_face2;
4245 int j;
4247 first_vtx1 = vtx_idx1;
4248 first_vtx2 = vtx_idx2;
4249 /* Glyphs without outlines do not generate any vertices. */
4250 if (glyphs[i].outlines.count > 0)
4252 for (; vtx_idx1 < number_of_vertices; vtx_idx1++)
4254 if (vertices[vtx_idx1].normal.z != 0)
4255 break;
4258 for (; vtx_idx2 < mesh->number_of_vertices; vtx_idx2++)
4260 if (mesh->vertices[vtx_idx2].normal.z != 0)
4261 break;
4264 nb_outline_vertices1 = vtx_idx1 - first_vtx1;
4265 nb_outline_vertices2 = vtx_idx2 - first_vtx2;
4266 ok(nb_outline_vertices1 == nb_outline_vertices2,
4267 "Test %s, glyph %d, outline vertex count result %d, expected %d\n", name, i,
4268 nb_outline_vertices1, nb_outline_vertices2);
4270 for (j = 0; j < min(nb_outline_vertices1, nb_outline_vertices2); j++)
4272 vtx_idx1 = first_vtx1 + j;
4273 vtx_idx2 = first_vtx2 + j;
4274 ok(compare_vec3(vertices[vtx_idx1].position, mesh->vertices[vtx_idx2].position),
4275 "Test %s, glyph %d, vertex position %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1,
4276 vertices[vtx_idx1].position.x, vertices[vtx_idx1].position.y, vertices[vtx_idx1].position.z,
4277 mesh->vertices[vtx_idx2].position.x, mesh->vertices[vtx_idx2].position.y, mesh->vertices[vtx_idx2].position.z);
4278 ok(compare_vec3(vertices[vtx_idx1].normal, mesh->vertices[first_vtx2 + j].normal),
4279 "Test %s, glyph %d, vertex normal %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1,
4280 vertices[vtx_idx1].normal.x, vertices[vtx_idx1].normal.y, vertices[vtx_idx1].normal.z,
4281 mesh->vertices[vtx_idx2].normal.x, mesh->vertices[vtx_idx2].normal.y, mesh->vertices[vtx_idx2].normal.z);
4283 vtx_idx1 = first_vtx1 + nb_outline_vertices1;
4284 vtx_idx2 = first_vtx2 + nb_outline_vertices2;
4286 first_face1 = face_idx1;
4287 first_face2 = face_idx2;
4288 for (; face_idx1 < number_of_faces; face_idx1++)
4290 if (faces[face_idx1][0] >= vtx_idx1 ||
4291 faces[face_idx1][1] >= vtx_idx1 ||
4292 faces[face_idx1][2] >= vtx_idx1)
4293 break;
4295 for (; face_idx2 < mesh->number_of_faces; face_idx2++)
4297 if (mesh->faces[face_idx2][0] >= vtx_idx2 ||
4298 mesh->faces[face_idx2][1] >= vtx_idx2 ||
4299 mesh->faces[face_idx2][2] >= vtx_idx2)
4300 break;
4302 nb_outline_faces1 = face_idx1 - first_face1;
4303 nb_outline_faces2 = face_idx2 - first_face2;
4304 ok(nb_outline_faces1 == nb_outline_faces2,
4305 "Test %s, glyph %d, outline face count result %d, expected %d\n", name, i,
4306 nb_outline_faces1, nb_outline_faces2);
4308 for (j = 0; j < min(nb_outline_faces1, nb_outline_faces2); j++)
4310 face_idx1 = first_face1 + j;
4311 face_idx2 = first_face2 + j;
4312 ok(faces[face_idx1][0] - first_vtx1 == mesh->faces[face_idx2][0] - first_vtx2 &&
4313 faces[face_idx1][1] - first_vtx1 == mesh->faces[face_idx2][1] - first_vtx2 &&
4314 faces[face_idx1][2] - first_vtx1 == mesh->faces[face_idx2][2] - first_vtx2,
4315 "Test %s, glyph %d, face %d, result (%d, %d, %d), expected (%d, %d, %d)\n", name, i, face_idx1,
4316 faces[face_idx1][0], faces[face_idx1][1], faces[face_idx1][2],
4317 mesh->faces[face_idx2][0] - first_vtx2 + first_vtx1,
4318 mesh->faces[face_idx2][1] - first_vtx2 + first_vtx1,
4319 mesh->faces[face_idx2][2] - first_vtx2 + first_vtx1);
4321 face_idx1 = first_face1 + nb_outline_faces1;
4322 face_idx2 = first_face2 + nb_outline_faces2;
4324 /* partial test on back vertices and faces */
4325 first_vtx1 = vtx_idx1;
4326 for (; vtx_idx1 < number_of_vertices; vtx_idx1++) {
4327 struct vertex vtx;
4329 if (vertices[vtx_idx1].normal.z != 1.0f)
4330 break;
4332 vtx.position.z = 0.0f;
4333 vtx.normal.x = 0.0f;
4334 vtx.normal.y = 0.0f;
4335 vtx.normal.z = 1.0f;
4336 ok(compare(vertices[vtx_idx1].position.z, vtx.position.z),
4337 "Test %s, glyph %d, vertex position.z %d, result %g, expected %g\n", name, i, vtx_idx1,
4338 vertices[vtx_idx1].position.z, vtx.position.z);
4339 ok(compare_vec3(vertices[vtx_idx1].normal, vtx.normal),
4340 "Test %s, glyph %d, vertex normal %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1,
4341 vertices[vtx_idx1].normal.x, vertices[vtx_idx1].normal.y, vertices[vtx_idx1].normal.z,
4342 vtx.normal.x, vtx.normal.y, vtx.normal.z);
4344 nb_back_vertices = vtx_idx1 - first_vtx1;
4345 first_face1 = face_idx1;
4346 for (; face_idx1 < number_of_faces; face_idx1++)
4348 const D3DXVECTOR3 *vtx1, *vtx2, *vtx3;
4349 D3DXVECTOR3 normal;
4350 D3DXVECTOR3 v1 = {0, 0, 0};
4351 D3DXVECTOR3 v2 = {0, 0, 0};
4352 D3DXVECTOR3 forward = {0.0f, 0.0f, 1.0f};
4354 if (faces[face_idx1][0] >= vtx_idx1 ||
4355 faces[face_idx1][1] >= vtx_idx1 ||
4356 faces[face_idx1][2] >= vtx_idx1)
4357 break;
4359 vtx1 = &vertices[faces[face_idx1][0]].position;
4360 vtx2 = &vertices[faces[face_idx1][1]].position;
4361 vtx3 = &vertices[faces[face_idx1][2]].position;
4363 D3DXVec3Subtract(&v1, vtx2, vtx1);
4364 D3DXVec3Subtract(&v2, vtx3, vtx2);
4365 D3DXVec3Cross(&normal, &v1, &v2);
4366 D3DXVec3Normalize(&normal, &normal);
4367 ok(!D3DXVec3Length(&normal) || compare_vec3(normal, forward),
4368 "Test %s, glyph %d, face %d normal, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, face_idx1,
4369 normal.x, normal.y, normal.z, forward.x, forward.y, forward.z);
4371 nb_back_faces = face_idx1 - first_face1;
4373 /* compare front and back faces & vertices */
4374 if (extrusion == 0.0f) {
4375 /* Oddly there are only back faces in this case */
4376 nb_back_vertices /= 2;
4377 nb_back_faces /= 2;
4378 face_idx1 -= nb_back_faces;
4379 vtx_idx1 -= nb_back_vertices;
4381 for (j = 0; j < nb_back_vertices; j++)
4383 struct vertex vtx = vertices[first_vtx1];
4384 vtx.position.z = -extrusion;
4385 vtx.normal.x = 0.0f;
4386 vtx.normal.y = 0.0f;
4387 vtx.normal.z = extrusion == 0.0f ? 1.0f : -1.0f;
4388 ok(compare_vec3(vertices[vtx_idx1].position, vtx.position),
4389 "Test %s, glyph %d, vertex position %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1,
4390 vertices[vtx_idx1].position.x, vertices[vtx_idx1].position.y, vertices[vtx_idx1].position.z,
4391 vtx.position.x, vtx.position.y, vtx.position.z);
4392 ok(compare_vec3(vertices[vtx_idx1].normal, vtx.normal),
4393 "Test %s, glyph %d, vertex normal %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1,
4394 vertices[vtx_idx1].normal.x, vertices[vtx_idx1].normal.y, vertices[vtx_idx1].normal.z,
4395 vtx.normal.x, vtx.normal.y, vtx.normal.z);
4396 vtx_idx1++;
4397 first_vtx1++;
4399 for (j = 0; j < nb_back_faces; j++)
4401 int f1, f2;
4402 if (extrusion == 0.0f) {
4403 f1 = 1;
4404 f2 = 2;
4405 } else {
4406 f1 = 2;
4407 f2 = 1;
4409 ok(faces[face_idx1][0] == faces[first_face1][0] + nb_back_vertices &&
4410 faces[face_idx1][1] == faces[first_face1][f1] + nb_back_vertices &&
4411 faces[face_idx1][2] == faces[first_face1][f2] + nb_back_vertices,
4412 "Test %s, glyph %d, face %d, result (%d, %d, %d), expected (%d, %d, %d)\n", name, i, face_idx1,
4413 faces[face_idx1][0], faces[face_idx1][1], faces[face_idx1][2],
4414 faces[first_face1][0] - nb_back_faces,
4415 faces[first_face1][f1] - nb_back_faces,
4416 faces[first_face1][f2] - nb_back_faces);
4417 first_face1++;
4418 face_idx1++;
4421 /* skip to the outline for the next glyph */
4422 for (; vtx_idx2 < mesh->number_of_vertices; vtx_idx2++) {
4423 if (mesh->vertices[vtx_idx2].normal.z == 0)
4424 break;
4426 for (; face_idx2 < mesh->number_of_faces; face_idx2++)
4428 if (mesh->faces[face_idx2][0] >= vtx_idx2 ||
4429 mesh->faces[face_idx2][1] >= vtx_idx2 ||
4430 mesh->faces[face_idx2][2] >= vtx_idx2) break;
4434 IDirect3DIndexBuffer9_Unlock(index_buffer);
4435 IDirect3DVertexBuffer9_Unlock(vertex_buffer);
4436 IDirect3DIndexBuffer9_Release(index_buffer);
4437 IDirect3DVertexBuffer9_Release(vertex_buffer);
4440 static void test_createtext(IDirect3DDevice9 *device, HDC hdc, const char *text, float deviation, float extrusion)
4442 static const MAT2 identity = {{0, 1}, {0, 0}, {0, 0}, {0, 1}};
4443 HRESULT hr;
4444 ID3DXMesh *d3dxmesh = NULL;
4445 struct mesh mesh = {0};
4446 char name[256];
4447 OUTLINETEXTMETRICA otm;
4448 GLYPHMETRICS gm;
4449 struct glyphinfo *glyphs;
4450 GLYPHMETRICSFLOAT *glyphmetrics_float = malloc(sizeof(GLYPHMETRICSFLOAT) * strlen(text));
4451 int i;
4452 LOGFONTA lf;
4453 float offset_x;
4454 size_t textlen;
4455 HFONT font = NULL, oldfont = NULL;
4456 char *raw_outline;
4458 sprintf(name, "text ('%s', %f, %f)", text, deviation, extrusion);
4460 hr = D3DXCreateTextA(device, hdc, text, deviation, extrusion, &d3dxmesh, NULL, glyphmetrics_float);
4461 ok(hr == D3D_OK, "Got result %lx, expected 0 (D3D_OK)\n", hr);
4463 /* must select a modified font having lfHeight = otm.otmEMSquare before
4464 * calling GetGlyphOutline to get the expected values */
4465 ok(GetObjectA(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf), "Failed to get current DC font.\n");
4466 ok(GetOutlineTextMetricsA(hdc, sizeof(otm), &otm), "Failed to get DC font outline.\n");
4467 lf.lfHeight = otm.otmEMSquare;
4468 lf.lfWidth = 0;
4469 ok(!!(font = CreateFontIndirectA(&lf)), "Failed to create font.\n");
4471 textlen = strlen(text);
4472 glyphs = calloc(textlen, sizeof(*glyphs));
4473 oldfont = SelectObject(hdc, font);
4475 for (i = 0; i < textlen; i++)
4477 GetGlyphOutlineA(hdc, text[i], GGO_NATIVE, &gm, 0, NULL, &identity);
4478 compare_float(glyphmetrics_float[i].gmfBlackBoxX, gm.gmBlackBoxX / (float)otm.otmEMSquare);
4479 compare_float(glyphmetrics_float[i].gmfBlackBoxY, gm.gmBlackBoxY / (float)otm.otmEMSquare);
4480 compare_float(glyphmetrics_float[i].gmfptGlyphOrigin.x, gm.gmptGlyphOrigin.x / (float)otm.otmEMSquare);
4481 compare_float(glyphmetrics_float[i].gmfptGlyphOrigin.y, gm.gmptGlyphOrigin.y / (float)otm.otmEMSquare);
4482 compare_float(glyphmetrics_float[i].gmfCellIncX, gm.gmCellIncX / (float)otm.otmEMSquare);
4483 compare_float(glyphmetrics_float[i].gmfCellIncY, gm.gmCellIncY / (float)otm.otmEMSquare);
4486 if (deviation == 0.0f)
4487 deviation = 1.0f / otm.otmEMSquare;
4489 offset_x = 0.0f;
4490 for (i = 0; i < textlen; i++)
4492 DWORD datasize;
4494 glyphs[i].offset_x = offset_x;
4496 datasize = GetGlyphOutlineA(hdc, text[i], GGO_NATIVE, &gm, 0, NULL, &identity);
4497 ok(datasize != GDI_ERROR, "Failed to retrieve GDI glyph outline size.\n");
4498 raw_outline = malloc(datasize);
4499 datasize = GetGlyphOutlineA(hdc, text[i], GGO_NATIVE, &gm, datasize, raw_outline, &identity);
4500 ok(datasize != GDI_ERROR, "Failed to retrieve GDI glyph outline.\n");
4501 create_outline(&glyphs[i], raw_outline, datasize, deviation, otm.otmEMSquare);
4502 free(raw_outline);
4504 offset_x += gm.gmCellIncX / (float)otm.otmEMSquare;
4507 SelectObject(hdc, oldfont);
4509 compute_text_mesh(&mesh, text, deviation, extrusion, otm.otmEMSquare, glyphs);
4510 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
4512 compare_text_outline_mesh(name, d3dxmesh, &mesh, textlen, extrusion, glyphs);
4514 free_mesh(&mesh);
4515 d3dxmesh->lpVtbl->Release(d3dxmesh);
4516 DeleteObject(font);
4517 free(glyphmetrics_float);
4519 for (i = 0; i < textlen; i++)
4520 free_glyphinfo(&glyphs[i]);
4521 free(glyphs);
4524 static void D3DXCreateTextTest(void)
4526 HRESULT hr;
4527 HDC hdc;
4528 IDirect3DDevice9* device;
4529 ID3DXMesh* d3dxmesh = NULL;
4530 HFONT hFont;
4531 OUTLINETEXTMETRICA otm;
4532 int number_of_vertices;
4533 int number_of_faces;
4534 struct test_context *test_context;
4536 if (!(test_context = new_test_context()))
4538 skip("Couldn't create test context\n");
4539 return;
4541 device = test_context->device;
4543 hdc = CreateCompatibleDC(NULL);
4545 hFont = CreateFontA(12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
4546 CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, "Arial");
4547 SelectObject(hdc, hFont);
4548 GetOutlineTextMetricsA(hdc, sizeof(otm), &otm);
4550 hr = D3DXCreateTextA(device, hdc, "wine", 0.001f, 0.4f, NULL, NULL, NULL);
4551 ok(hr == D3DERR_INVALIDCALL, "Got result %lx, expected %lx (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4553 /* D3DXCreateTextA page faults from passing NULL text */
4555 hr = D3DXCreateTextW(device, hdc, NULL, 0.001f, 0.4f, &d3dxmesh, NULL, NULL);
4556 ok(hr == D3DERR_INVALIDCALL, "Got result %lx, expected %lx (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4558 hr = D3DXCreateTextA(device, hdc, "", 0.001f, 0.4f, &d3dxmesh, NULL, NULL);
4559 ok(hr == D3DERR_INVALIDCALL, "Got result %lx, expected %lx (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4561 hr = D3DXCreateTextA(device, hdc, " ", 0.001f, 0.4f, &d3dxmesh, NULL, NULL);
4562 ok(hr == D3DERR_INVALIDCALL, "Got result %lx, expected %lx (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4564 hr = D3DXCreateTextA(NULL, hdc, "wine", 0.001f, 0.4f, &d3dxmesh, NULL, NULL);
4565 ok(hr == D3DERR_INVALIDCALL, "Got result %lx, expected %lx (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4567 hr = D3DXCreateTextA(device, NULL, "wine", 0.001f, 0.4f, &d3dxmesh, NULL, NULL);
4568 ok(hr == D3DERR_INVALIDCALL, "Got result %lx, expected %lx (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4570 hr = D3DXCreateTextA(device, hdc, "wine", -FLT_MIN, 0.4f, &d3dxmesh, NULL, NULL);
4571 ok(hr == D3DERR_INVALIDCALL, "Got result %lx, expected %lx (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4573 hr = D3DXCreateTextA(device, hdc, "wine", 0.001f, -FLT_MIN, &d3dxmesh, NULL, NULL);
4574 ok(hr == D3DERR_INVALIDCALL, "Got result %lx, expected %lx (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4576 /* deviation = 0.0f treated as if deviation = 1.0f / otm.otmEMSquare */
4577 hr = D3DXCreateTextA(device, hdc, "wine", 1.0f / otm.otmEMSquare, 0.4f, &d3dxmesh, NULL, NULL);
4578 ok(hr == D3D_OK, "Got result %lx, expected %lx (D3D_OK)\n", hr, D3D_OK);
4579 number_of_vertices = d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh);
4580 number_of_faces = d3dxmesh->lpVtbl->GetNumFaces(d3dxmesh);
4581 d3dxmesh->lpVtbl->Release(d3dxmesh);
4583 hr = D3DXCreateTextA(device, hdc, "wine", 0.0f, 0.4f, &d3dxmesh, NULL, NULL);
4584 ok(hr == D3D_OK, "Got result %lx, expected %lx (D3D_OK)\n", hr, D3D_OK);
4585 ok(number_of_vertices == d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh),
4586 "Got %ld vertices, expected %d\n",
4587 d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh), number_of_vertices);
4588 ok(number_of_faces == d3dxmesh->lpVtbl->GetNumFaces(d3dxmesh),
4589 "Got %ld faces, expected %d\n",
4590 d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh), number_of_faces);
4591 d3dxmesh->lpVtbl->Release(d3dxmesh);
4593 if (0)
4595 /* too much detail requested, so will appear to hang */
4596 trace("Waiting for D3DXCreateText to finish with deviation = FLT_MIN ...\n");
4597 hr = D3DXCreateTextA(device, hdc, "wine", FLT_MIN, 0.4f, &d3dxmesh, NULL, NULL);
4598 ok(hr == D3D_OK, "Got result %lx, expected %lx (D3D_OK)\n", hr, D3D_OK);
4599 if (SUCCEEDED(hr) && d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh);
4600 trace("D3DXCreateText finish with deviation = FLT_MIN\n");
4603 hr = D3DXCreateTextA(device, hdc, "wine", 0.001f, 0.4f, &d3dxmesh, NULL, NULL);
4604 ok(hr == D3D_OK, "Got result %lx, expected %lx (D3D_OK)\n", hr, D3D_OK);
4605 if (SUCCEEDED(hr) && d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh);
4607 test_createtext(device, hdc, "wine", FLT_MAX, 0.4f);
4608 test_createtext(device, hdc, "wine", 0.001f, FLT_MIN);
4609 test_createtext(device, hdc, "wine", 0.001f, 0.0f);
4610 test_createtext(device, hdc, "wine", 0.001f, FLT_MAX);
4611 test_createtext(device, hdc, "wine", 0.0f, 1.0f);
4612 test_createtext(device, hdc, " wine", 1.0f, 0.0f);
4613 test_createtext(device, hdc, "wine ", 1.0f, 0.0f);
4614 test_createtext(device, hdc, "wi ne", 1.0f, 0.0f);
4616 DeleteDC(hdc);
4617 DeleteObject(hFont);
4619 free_test_context(test_context);
4622 static void test_get_decl_length(void)
4624 static const D3DVERTEXELEMENT9 declaration1[] =
4626 {0, 0, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4627 {1, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4628 {2, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4629 {3, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4630 {4, 0, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4631 {5, 0, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4632 {6, 0, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4633 {7, 0, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4634 {8, 0, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4635 {9, 0, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4636 {10, 0, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4637 {11, 0, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4638 {12, 0, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4639 {13, 0, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4640 {14, 0, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4641 D3DDECL_END(),
4643 static const D3DVERTEXELEMENT9 declaration2[] =
4645 {0, 8, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4646 {1, 8, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4647 {2, 8, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4648 {3, 8, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4649 {4, 8, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4650 {5, 8, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4651 {6, 8, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4652 {7, 8, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4653 {0, 8, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4654 {1, 8, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4655 {2, 8, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4656 {3, 8, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4657 {4, 8, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4658 {5, 8, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4659 {6, 8, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4660 {7, 8, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4661 D3DDECL_END(),
4663 UINT size;
4665 size = D3DXGetDeclLength(declaration1);
4666 ok(size == 15, "Got size %u, expected 15.\n", size);
4668 size = D3DXGetDeclLength(declaration2);
4669 ok(size == 16, "Got size %u, expected 16.\n", size);
4672 static void test_get_decl_vertex_size(void)
4674 static const D3DVERTEXELEMENT9 declaration1[] =
4676 {0, 0, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4677 {1, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4678 {2, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4679 {3, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4680 {4, 0, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4681 {5, 0, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4682 {6, 0, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4683 {7, 0, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4684 {8, 0, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4685 {9, 0, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4686 {10, 0, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4687 {11, 0, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4688 {12, 0, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4689 {13, 0, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4690 {14, 0, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4691 D3DDECL_END(),
4693 static const D3DVERTEXELEMENT9 declaration2[] =
4695 {0, 8, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4696 {1, 8, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4697 {2, 8, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4698 {3, 8, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4699 {4, 8, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4700 {5, 8, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4701 {6, 8, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4702 {7, 8, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4703 {0, 8, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4704 {1, 8, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4705 {2, 8, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4706 {3, 8, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4707 {4, 8, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4708 {5, 8, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4709 {6, 8, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4710 {7, 8, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4711 D3DDECL_END(),
4713 static const UINT sizes1[] =
4715 4, 8, 12, 16,
4716 4, 4, 4, 8,
4717 4, 4, 8, 4,
4718 4, 4, 8, 0,
4720 static const UINT sizes2[] =
4722 12, 16, 20, 24,
4723 12, 12, 16, 16,
4725 unsigned int i;
4726 UINT size;
4728 size = D3DXGetDeclVertexSize(NULL, 0);
4729 ok(size == 0, "Got size %#x, expected 0.\n", size);
4731 for (i = 0; i < 16; ++i)
4733 size = D3DXGetDeclVertexSize(declaration1, i);
4734 ok(size == sizes1[i], "Got size %u for stream %u, expected %u.\n", size, i, sizes1[i]);
4737 for (i = 0; i < 8; ++i)
4739 size = D3DXGetDeclVertexSize(declaration2, i);
4740 ok(size == sizes2[i], "Got size %u for stream %u, expected %u.\n", size, i, sizes2[i]);
4744 static void D3DXGenerateAdjacencyTest(void)
4746 HRESULT hr;
4747 IDirect3DDevice9 *device;
4748 ID3DXMesh *d3dxmesh = NULL;
4749 D3DXVECTOR3 *vertices = NULL;
4750 WORD *indices = NULL;
4751 int i;
4752 struct {
4753 DWORD num_vertices;
4754 D3DXVECTOR3 vertices[6];
4755 DWORD num_faces;
4756 WORD indices[3 * 3];
4757 FLOAT epsilon;
4758 DWORD adjacency[3 * 3];
4759 } test_data[] = {
4760 { /* for epsilon < 0, indices must match for faces to be adjacent */
4761 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}},
4762 2, {0, 1, 2, 0, 2, 3},
4763 -1.0,
4764 {-1, -1, 1, 0, -1, -1},
4767 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}},
4768 2, {0, 1, 2, 3, 4, 5},
4769 -1.0,
4770 {-1, -1, -1, -1, -1, -1},
4772 { /* for epsilon == 0, indices or vertices must match for faces to be adjacent */
4773 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}},
4774 2, {0, 1, 2, 3, 4, 5},
4775 0.0,
4776 {-1, -1, 1, 0, -1, -1},
4778 { /* for epsilon > 0, vertices must be less than (but NOT equal to) epsilon distance away */
4779 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}},
4780 2, {0, 1, 2, 3, 4, 5},
4781 0.25,
4782 {-1, -1, -1, -1, -1, -1},
4784 { /* for epsilon > 0, vertices must be less than (but NOT equal to) epsilon distance away */
4785 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}},
4786 2, {0, 1, 2, 3, 4, 5},
4787 0.250001,
4788 {-1, -1, 1, 0, -1, -1},
4790 { /* length between vertices are compared to epsilon, not the individual dimension deltas */
4791 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}},
4792 2, {0, 1, 2, 3, 4, 5},
4793 0.353, /* < sqrt(0.25*0.25 + 0.25*0.25) */
4794 {-1, -1, -1, -1, -1, -1},
4797 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}},
4798 2, {0, 1, 2, 3, 4, 5},
4799 0.354, /* > sqrt(0.25*0.25 + 0.25*0.25) */
4800 {-1, -1, 1, 0, -1, -1},
4802 { /* adjacent faces must have opposite winding orders at the shared edge */
4803 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}},
4804 2, {0, 1, 2, 0, 3, 2},
4805 0.0,
4806 {-1, -1, -1, -1, -1, -1},
4809 struct test_context *test_context;
4811 if (!(test_context = new_test_context()))
4813 skip("Couldn't create test context\n");
4814 return;
4816 device = test_context->device;
4818 for (i = 0; i < ARRAY_SIZE(test_data); i++)
4820 DWORD adjacency[ARRAY_SIZE(test_data[0].adjacency)];
4821 int j;
4823 if (d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh);
4824 d3dxmesh = NULL;
4826 hr = D3DXCreateMeshFVF(test_data[i].num_faces, test_data[i].num_vertices, 0, D3DFVF_XYZ, device, &d3dxmesh);
4827 ok(hr == D3D_OK, "Got result %lx, expected %lx (D3D_OK)\n", hr, D3D_OK);
4829 hr = d3dxmesh->lpVtbl->LockVertexBuffer(d3dxmesh, D3DLOCK_DISCARD, (void**)&vertices);
4830 ok(hr == D3D_OK, "test %d: Got result %lx, expected %lx (D3D_OK)\n", i, hr, D3D_OK);
4831 if (FAILED(hr)) continue;
4832 CopyMemory(vertices, test_data[i].vertices, test_data[i].num_vertices * sizeof(test_data[0].vertices[0]));
4833 d3dxmesh->lpVtbl->UnlockVertexBuffer(d3dxmesh);
4835 hr = d3dxmesh->lpVtbl->LockIndexBuffer(d3dxmesh, D3DLOCK_DISCARD, (void**)&indices);
4836 ok(hr == D3D_OK, "test %d: Got result %lx, expected %lx (D3D_OK)\n", i, hr, D3D_OK);
4837 if (FAILED(hr)) continue;
4838 CopyMemory(indices, test_data[i].indices, test_data[i].num_faces * 3 * sizeof(test_data[0].indices[0]));
4839 d3dxmesh->lpVtbl->UnlockIndexBuffer(d3dxmesh);
4841 if (i == 0) {
4842 hr = d3dxmesh->lpVtbl->GenerateAdjacency(d3dxmesh, 0.0f, NULL);
4843 ok(hr == D3DERR_INVALIDCALL, "Got result %lx, expected %lx (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4846 hr = d3dxmesh->lpVtbl->GenerateAdjacency(d3dxmesh, test_data[i].epsilon, adjacency);
4847 ok(hr == D3D_OK, "Got result %lx, expected %lx (D3D_OK)\n", hr, D3D_OK);
4848 if (FAILED(hr)) continue;
4850 for (j = 0; j < test_data[i].num_faces * 3; j++)
4851 ok(adjacency[j] == test_data[i].adjacency[j],
4852 "Test %d adjacency %d: Got result %lu, expected %lu\n", i, j,
4853 adjacency[j], test_data[i].adjacency[j]);
4855 if (d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh);
4857 free_test_context(test_context);
4860 static void test_update_semantics(void)
4862 HRESULT hr;
4863 struct test_context *test_context = NULL;
4864 ID3DXMesh *mesh = NULL;
4865 D3DVERTEXELEMENT9 declaration0[] =
4867 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4868 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4869 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4870 D3DDECL_END()
4872 D3DVERTEXELEMENT9 declaration_pos_type_color[] =
4874 {0, 0, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4875 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4876 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4877 D3DDECL_END()
4879 D3DVERTEXELEMENT9 declaration_smaller[] =
4881 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4882 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4883 D3DDECL_END()
4885 D3DVERTEXELEMENT9 declaration_larger[] =
4887 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4888 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4889 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4890 {0, 40, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT, 0},
4891 D3DDECL_END()
4893 D3DVERTEXELEMENT9 declaration_multiple_streams[] =
4895 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4896 {1, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT, 0},
4897 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4898 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4900 D3DDECL_END()
4902 D3DVERTEXELEMENT9 declaration_double_usage[] =
4904 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4905 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4906 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4907 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4908 D3DDECL_END()
4910 D3DVERTEXELEMENT9 declaration_undefined_type[] =
4912 {0, 0, D3DDECLTYPE_UNUSED+1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4913 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4914 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4915 D3DDECL_END()
4917 D3DVERTEXELEMENT9 declaration_not_4_byte_aligned_offset[] =
4919 {0, 3, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4920 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4921 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4922 D3DDECL_END()
4924 static const struct
4926 D3DXVECTOR3 position0;
4927 D3DXVECTOR3 position1;
4928 D3DXVECTOR3 normal;
4929 DWORD color;
4931 vertices[] =
4933 { { 0.0f, 1.0f, 0.f}, { 1.0f, 0.0f, 0.f}, {0.0f, 0.0f, 1.0f}, 0xffff0000 },
4934 { { 1.0f, -1.0f, 0.f}, {-1.0f, -1.0f, 0.f}, {0.0f, 0.0f, 1.0f}, 0xff00ff00 },
4935 { {-1.0f, -1.0f, 0.f}, {-1.0f, 1.0f, 0.f}, {0.0f, 0.0f, 1.0f}, 0xff0000ff },
4937 unsigned int faces[] = {0, 1, 2};
4938 unsigned int attributes[] = {0};
4939 unsigned int num_faces = ARRAY_SIZE(faces) / 3;
4940 unsigned int num_vertices = ARRAY_SIZE(vertices);
4941 int offset = sizeof(D3DXVECTOR3);
4942 DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
4943 void *vertex_buffer;
4944 void *index_buffer;
4945 DWORD *attributes_buffer;
4946 D3DVERTEXELEMENT9 declaration[MAX_FVF_DECL_SIZE];
4947 D3DVERTEXELEMENT9 *decl_ptr;
4948 DWORD exp_vertex_size = sizeof(*vertices);
4949 DWORD vertex_size = 0;
4950 BYTE *decl_mem;
4951 int equal;
4952 int i = 0;
4954 test_context = new_test_context();
4955 if (!test_context)
4957 skip("Couldn't create a test_context\n");
4958 goto cleanup;
4961 hr = D3DXCreateMesh(num_faces, num_vertices, options, declaration0,
4962 test_context->device, &mesh);
4963 if (FAILED(hr))
4965 skip("Couldn't create test mesh %#lx\n", hr);
4966 goto cleanup;
4969 mesh->lpVtbl->LockVertexBuffer(mesh, 0, &vertex_buffer);
4970 memcpy(vertex_buffer, vertices, sizeof(vertices));
4971 mesh->lpVtbl->UnlockVertexBuffer(mesh);
4973 mesh->lpVtbl->LockIndexBuffer(mesh, 0, &index_buffer);
4974 memcpy(index_buffer, faces, sizeof(faces));
4975 mesh->lpVtbl->UnlockIndexBuffer(mesh);
4977 mesh->lpVtbl->LockAttributeBuffer(mesh, 0, &attributes_buffer);
4978 memcpy(attributes_buffer, attributes, sizeof(attributes));
4979 mesh->lpVtbl->UnlockAttributeBuffer(mesh);
4981 /* Get the declaration and try to change it */
4982 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4983 if (FAILED(hr))
4985 skip("Couldn't get vertex declaration %#lx\n", hr);
4986 goto cleanup;
4988 equal = memcmp(declaration, declaration0, sizeof(declaration0));
4989 ok(equal == 0, "Vertex declarations were not equal\n");
4991 for (decl_ptr = declaration; decl_ptr->Stream != 0xFF; decl_ptr++)
4993 if (decl_ptr->Usage == D3DDECLUSAGE_POSITION)
4995 /* Use second vertex position instead of first */
4996 decl_ptr->Offset = offset;
5000 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration);
5001 ok(hr == D3D_OK, "Test UpdateSemantics, got %#lx expected %#lx\n", hr, D3D_OK);
5003 /* Check that declaration was written by getting it again */
5004 memset(declaration, 0, sizeof(declaration));
5005 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
5006 if (FAILED(hr))
5008 skip("Couldn't get vertex declaration %#lx\n", hr);
5009 goto cleanup;
5012 for (decl_ptr = declaration; decl_ptr->Stream != 0xFF; decl_ptr++)
5014 if (decl_ptr->Usage == D3DDECLUSAGE_POSITION)
5016 ok(decl_ptr->Offset == offset, "Test UpdateSemantics, got offset %d expected %d\n",
5017 decl_ptr->Offset, offset);
5021 /* Check that GetDeclaration only writes up to the D3DDECL_END() marker and
5022 * not the full MAX_FVF_DECL_SIZE elements.
5024 memset(declaration, 0xaa, sizeof(declaration));
5025 memcpy(declaration, declaration0, sizeof(declaration0));
5026 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration);
5027 ok(hr == D3D_OK, "Test UpdateSemantics, "
5028 "got %#lx expected D3D_OK\n", hr);
5029 memset(declaration, 0xbb, sizeof(declaration));
5030 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
5031 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#lx, expected D3D_OK\n", hr);
5032 decl_mem = (BYTE *)declaration;
5033 for (i = sizeof(declaration0); i < sizeof(declaration); ++i)
5035 ok(decl_mem[i] == 0xbb, "Unexpected %#x.\n", decl_mem[i]);
5036 if (equal != 0)
5037 break;
5040 /* UpdateSemantics does not check for overlapping fields */
5041 memset(declaration, 0, sizeof(declaration));
5042 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
5043 if (FAILED(hr))
5045 skip("Couldn't get vertex declaration %#lx\n", hr);
5046 goto cleanup;
5049 for (decl_ptr = declaration; decl_ptr->Stream != 0xFF; decl_ptr++)
5051 if (decl_ptr->Type == D3DDECLTYPE_FLOAT3)
5053 decl_ptr->Type = D3DDECLTYPE_FLOAT4;
5057 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration);
5058 ok(hr == D3D_OK, "Test UpdateSemantics for overlapping fields, "
5059 "got %#lx expected D3D_OK\n", hr);
5061 /* Set the position type to color instead of float3 */
5062 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_pos_type_color);
5063 ok(hr == D3D_OK, "Test UpdateSemantics position type color, "
5064 "got %#lx expected D3D_OK\n", hr);
5066 /* The following test cases show that NULL, smaller or larger declarations,
5067 * and declarations with non-zero Stream values are not accepted.
5068 * UpdateSemantics returns D3DERR_INVALIDCALL and the previously set
5069 * declaration will be used by DrawSubset, GetNumBytesPerVertex, and
5070 * GetDeclaration.
5073 /* Null declaration (invalid declaration) */
5074 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
5075 hr = mesh->lpVtbl->UpdateSemantics(mesh, NULL);
5076 ok(hr == D3DERR_INVALIDCALL, "Test UpdateSemantics null pointer declaration, "
5077 "got %#lx expected D3DERR_INVALIDCALL\n", hr);
5078 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
5079 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %lu, expected %lu\n",
5080 vertex_size, exp_vertex_size);
5081 memset(declaration, 0, sizeof(declaration));
5082 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
5083 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#lx, expected D3D_OK\n", hr);
5084 equal = memcmp(declaration, declaration0, sizeof(declaration0));
5085 ok(equal == 0, "Vertex declarations were not equal\n");
5087 /* Smaller vertex declaration (invalid declaration) */
5088 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
5089 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_smaller);
5090 ok(hr == D3DERR_INVALIDCALL, "Test UpdateSemantics for smaller vertex declaration, "
5091 "got %#lx expected D3DERR_INVALIDCALL\n", hr);
5092 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
5093 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %lu, expected %lu\n",
5094 vertex_size, exp_vertex_size);
5095 memset(declaration, 0, sizeof(declaration));
5096 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
5097 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#lx, expected D3D_OK\n", hr);
5098 equal = memcmp(declaration, declaration0, sizeof(declaration0));
5099 ok(equal == 0, "Vertex declarations were not equal\n");
5101 /* Larger vertex declaration (invalid declaration) */
5102 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
5103 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_larger);
5104 ok(hr == D3DERR_INVALIDCALL, "Test UpdateSemantics for larger vertex declaration, "
5105 "got %#lx expected D3DERR_INVALIDCALL\n", hr);
5106 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
5107 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %lu, expected %lu\n",
5108 vertex_size, exp_vertex_size);
5109 memset(declaration, 0, sizeof(declaration));
5110 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
5111 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#lx, expected D3D_OK\n", hr);
5112 equal = memcmp(declaration, declaration0, sizeof(declaration0));
5113 ok(equal == 0, "Vertex declarations were not equal\n");
5115 /* Use multiple streams and keep the same vertex size (invalid declaration) */
5116 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
5117 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_multiple_streams);
5118 ok(hr == D3DERR_INVALIDCALL, "Test UpdateSemantics using multiple streams, "
5119 "got %#lx expected D3DERR_INVALIDCALL\n", hr);
5120 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
5121 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %lu, expected %lu\n",
5122 vertex_size, exp_vertex_size);
5123 memset(declaration, 0, sizeof(declaration));
5124 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
5125 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#lx, expected D3D_OK\n", hr);
5126 equal = memcmp(declaration, declaration0, sizeof(declaration0));
5127 ok(equal == 0, "Vertex declarations were not equal\n");
5129 /* The next following test cases show that some invalid declarations are
5130 * accepted with a D3D_OK. An access violation is thrown on Windows if
5131 * DrawSubset is called. The methods GetNumBytesPerVertex and GetDeclaration
5132 * are not affected, which indicates that the declaration is cached.
5135 /* Double usage (invalid declaration) */
5136 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
5137 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_double_usage);
5138 ok(hr == D3D_OK, "Test UpdateSemantics double usage, "
5139 "got %#lx expected D3D_OK\n", hr);
5140 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
5141 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %lu, expected %lu\n",
5142 vertex_size, exp_vertex_size);
5143 memset(declaration, 0, sizeof(declaration));
5144 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
5145 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#lx, expected D3D_OK\n", hr);
5146 equal = memcmp(declaration, declaration_double_usage, sizeof(declaration_double_usage));
5147 ok(equal == 0, "Vertex declarations were not equal\n");
5149 /* Set the position to an undefined type (invalid declaration) */
5150 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
5151 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_undefined_type);
5152 ok(hr == D3D_OK, "Test UpdateSemantics undefined type, "
5153 "got %#lx expected D3D_OK\n", hr);
5154 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
5155 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %lu, expected %lu\n",
5156 vertex_size, exp_vertex_size);
5157 memset(declaration, 0, sizeof(declaration));
5158 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
5159 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#lx, expected D3D_OK\n", hr);
5160 equal = memcmp(declaration, declaration_undefined_type, sizeof(declaration_undefined_type));
5161 ok(equal == 0, "Vertex declarations were not equal\n");
5163 /* Use a not 4 byte aligned offset (invalid declaration) */
5164 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
5165 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_not_4_byte_aligned_offset);
5166 ok(hr == D3D_OK, "Test UpdateSemantics not 4 byte aligned offset, "
5167 "got %#lx expected D3D_OK\n", hr);
5168 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
5169 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %lu, expected %lu\n",
5170 vertex_size, exp_vertex_size);
5171 memset(declaration, 0, sizeof(declaration));
5172 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
5173 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#lx, expected D3D_OK\n", hr);
5174 equal = memcmp(declaration, declaration_not_4_byte_aligned_offset,
5175 sizeof(declaration_not_4_byte_aligned_offset));
5176 ok(equal == 0, "Vertex declarations were not equal\n");
5178 cleanup:
5179 if (mesh)
5180 mesh->lpVtbl->Release(mesh);
5182 free_test_context(test_context);
5185 static void test_create_skin_info(void)
5187 D3DVERTEXELEMENT9 empty_declaration[] = { D3DDECL_END() };
5188 D3DVERTEXELEMENT9 declaration_out[MAX_FVF_DECL_SIZE];
5189 const D3DVERTEXELEMENT9 declaration_with_nonzero_stream[] = {
5190 {1, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
5191 D3DDECL_END()
5193 D3DVERTEXELEMENT9 declaration[MAX_FVF_DECL_SIZE];
5194 DWORD exp_vertices[2], vertices[2];
5195 float exp_weights[2], weights[2];
5196 const char *exp_string, *string;
5197 ID3DXSkinInfo *skininfo = NULL;
5198 DWORD exp_fvf, fvf;
5199 unsigned int i;
5200 HRESULT hr;
5202 hr = D3DXCreateSkinInfo(0, empty_declaration, 0, &skininfo);
5203 ok(hr == D3D_OK, "Expected D3D_OK, got %#lx\n", hr);
5204 if (skininfo) IUnknown_Release(skininfo);
5205 skininfo = NULL;
5207 hr = D3DXCreateSkinInfo(1, NULL, 1, &skininfo);
5208 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#lx\n", hr);
5210 hr = D3DXCreateSkinInfo(1, declaration_with_nonzero_stream, 1, &skininfo);
5211 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#lx\n", hr);
5213 hr = D3DXCreateSkinInfoFVF(1, 0, 1, &skininfo);
5214 ok(hr == D3D_OK, "Expected D3D_OK, got %#lx\n", hr);
5215 if (skininfo)
5217 ID3DXSkinInfo *clone = NULL;
5218 DWORD dword_result;
5219 float flt_result;
5220 const char *string_result;
5221 D3DXMATRIX *transform;
5222 D3DXMATRIX identity_matrix;
5224 /* test initial values */
5225 hr = skininfo->lpVtbl->GetDeclaration(skininfo, declaration_out);
5226 ok(hr == D3D_OK, "Expected D3D_OK, got %#lx\n", hr);
5227 if (SUCCEEDED(hr))
5228 compare_elements(declaration_out, empty_declaration, __LINE__, 0);
5230 dword_result = skininfo->lpVtbl->GetNumBones(skininfo);
5231 ok(dword_result == 1, "Expected 1, got %lu\n", dword_result);
5233 flt_result = skininfo->lpVtbl->GetMinBoneInfluence(skininfo);
5234 ok(flt_result == 0.0f, "Expected 0.0, got %g\n", flt_result);
5236 string_result = skininfo->lpVtbl->GetBoneName(skininfo, 0);
5237 ok(string_result == NULL, "Expected NULL, got %p\n", string_result);
5239 dword_result = skininfo->lpVtbl->GetFVF(skininfo);
5240 ok(dword_result == 0, "Expected 0, got %lu\n", dword_result);
5242 dword_result = skininfo->lpVtbl->GetNumBoneInfluences(skininfo, 0);
5243 ok(dword_result == 0, "Expected 0, got %lu\n", dword_result);
5245 dword_result = skininfo->lpVtbl->GetNumBoneInfluences(skininfo, 1);
5246 ok(dword_result == 0, "Expected 0, got %lu\n", dword_result);
5248 transform = skininfo->lpVtbl->GetBoneOffsetMatrix(skininfo, -1);
5249 ok(transform == NULL, "Expected NULL, got %p\n", transform);
5251 hr = skininfo->lpVtbl->Clone(skininfo, &clone);
5252 ok(hr == D3D_OK, "Expected D3D_OK, got %#lx\n", hr);
5253 IUnknown_Release(clone);
5256 /* test [GS]etBoneOffsetMatrix */
5257 hr = skininfo->lpVtbl->SetBoneOffsetMatrix(skininfo, 1, &identity_matrix);
5258 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#lx\n", hr);
5260 hr = skininfo->lpVtbl->SetBoneOffsetMatrix(skininfo, 0, NULL);
5261 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#lx\n", hr);
5263 D3DXMatrixIdentity(&identity_matrix);
5264 hr = skininfo->lpVtbl->SetBoneOffsetMatrix(skininfo, 0, &identity_matrix);
5265 ok(hr == D3D_OK, "Expected D3D_OK, got %#lx\n", hr);
5267 transform = skininfo->lpVtbl->GetBoneOffsetMatrix(skininfo, 0);
5268 check_matrix(transform, &identity_matrix);
5272 /* test [GS]etBoneName */
5273 const char *name_in = "testBoneName";
5274 const char *string_result2;
5276 hr = skininfo->lpVtbl->SetBoneName(skininfo, 1, name_in);
5277 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#lx\n", hr);
5279 hr = skininfo->lpVtbl->SetBoneName(skininfo, 0, NULL);
5280 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#lx\n", hr);
5282 hr = skininfo->lpVtbl->SetBoneName(skininfo, 0, name_in);
5283 ok(hr == D3D_OK, "Expected D3D_OK, got %#lx\n", hr);
5285 string_result = skininfo->lpVtbl->GetBoneName(skininfo, 0);
5286 ok(string_result != NULL, "Expected non-NULL string, got %p\n", string_result);
5287 ok(!strcmp(string_result, name_in), "Expected '%s', got '%s'\n", name_in, string_result);
5289 string_result2 = skininfo->lpVtbl->GetBoneName(skininfo, 0);
5290 ok(string_result == string_result2, "Expected %p, got %p\n", string_result, string_result2);
5292 string_result = skininfo->lpVtbl->GetBoneName(skininfo, 1);
5293 ok(string_result == NULL, "Expected NULL, got %p\n", string_result);
5297 /* test [GS]etBoneInfluence */
5298 DWORD num_influences;
5300 /* vertex and weight arrays untouched when num_influences is 0 */
5301 vertices[0] = 0xdeadbeef;
5302 weights[0] = FLT_MAX;
5303 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, vertices, weights);
5304 ok(hr == D3D_OK, "Expected D3D_OK, got %#lx\n", hr);
5305 ok(vertices[0] == 0xdeadbeef, "expected 0xdeadbeef, got %#lx\n", vertices[0]);
5306 ok(weights[0] == FLT_MAX, "expected %g, got %g\n", FLT_MAX, weights[0]);
5308 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 1, vertices, weights);
5309 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#lx\n", hr);
5311 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, NULL, NULL);
5312 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#lx\n", hr);
5314 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, vertices, NULL);
5315 ok(hr == D3D_OK, "Expected D3D_OK, got %#lx\n", hr);
5317 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, NULL, weights);
5318 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#lx\n", hr);
5321 /* no vertex or weight value checking */
5322 exp_vertices[0] = 0;
5323 exp_vertices[1] = 0x87654321;
5324 exp_weights[0] = 0.5;
5325 exp_weights[1] = NAN;
5326 num_influences = 2;
5328 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 1, num_influences, vertices, weights);
5329 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#lx\n", hr);
5331 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, num_influences, NULL, weights);
5332 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#lx\n", hr);
5334 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, num_influences, vertices, NULL);
5335 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#lx\n", hr);
5337 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, num_influences, NULL, NULL);
5338 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#lx\n", hr);
5340 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, num_influences, exp_vertices, exp_weights);
5341 ok(hr == D3D_OK, "Expected D3D_OK, got %#lx\n", hr);
5343 memset(vertices, 0, sizeof(vertices));
5344 memset(weights, 0, sizeof(weights));
5345 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, vertices, weights);
5346 ok(hr == D3D_OK, "Expected D3D_OK, got %#lx\n", hr);
5347 for (i = 0; i < num_influences; i++) {
5348 ok(exp_vertices[i] == vertices[i],
5349 "influence[%d]: expected vertex %lu, got %lu\n", i, exp_vertices[i], vertices[i]);
5350 ok((isnan(exp_weights[i]) && isnan(weights[i])) || exp_weights[i] == weights[i],
5351 "influence[%d]: expected weights %g, got %g\n", i, exp_weights[i], weights[i]);
5354 /* vertices and weights aren't returned after setting num_influences to 0 */
5355 memset(vertices, 0, sizeof(vertices));
5356 memset(weights, 0, sizeof(weights));
5357 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, 0, vertices, weights);
5358 ok(hr == D3D_OK, "Expected D3D_OK, got %#lx\n", hr);
5360 vertices[0] = 0xdeadbeef;
5361 weights[0] = FLT_MAX;
5362 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, vertices, weights);
5363 ok(hr == D3D_OK, "Expected D3D_OK, got %#lx\n", hr);
5364 ok(vertices[0] == 0xdeadbeef, "expected vertex 0xdeadbeef, got %lu\n", vertices[0]);
5365 ok(weights[0] == FLT_MAX, "expected weight %g, got %g\n", FLT_MAX, weights[0]);
5367 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, num_influences, exp_vertices, exp_weights);
5368 ok(hr == D3D_OK, "Expected D3D_OK, got %#lx\n", hr);
5372 /* test [GS]etFVF and [GS]etDeclaration */
5373 D3DVERTEXELEMENT9 declaration_in[MAX_FVF_DECL_SIZE];
5374 DWORD got_fvf;
5376 fvf = D3DFVF_XYZ;
5377 hr = skininfo->lpVtbl->SetDeclaration(skininfo, NULL);
5378 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#lx\n", hr);
5380 hr = skininfo->lpVtbl->SetDeclaration(skininfo, declaration_with_nonzero_stream);
5381 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#lx\n", hr);
5383 hr = skininfo->lpVtbl->SetFVF(skininfo, 0);
5384 ok(hr == D3D_OK, "Expected D3D_OK, got %#lx\n", hr);
5386 hr = D3DXDeclaratorFromFVF(fvf, declaration_in);
5387 ok(hr == D3D_OK, "Expected D3D_OK, got %#lx\n", hr);
5388 hr = skininfo->lpVtbl->SetDeclaration(skininfo, declaration_in);
5389 ok(hr == D3D_OK, "Expected D3D_OK, got %#lx\n", hr);
5390 got_fvf = skininfo->lpVtbl->GetFVF(skininfo);
5391 ok(fvf == got_fvf, "Expected %#lx, got %#lx\n", fvf, got_fvf);
5392 hr = skininfo->lpVtbl->GetDeclaration(skininfo, declaration_out);
5393 ok(hr == D3D_OK, "Expected D3D_OK, got %#lx\n", hr);
5394 compare_elements(declaration_out, declaration_in, __LINE__, 0);
5396 hr = skininfo->lpVtbl->SetDeclaration(skininfo, empty_declaration);
5397 ok(hr == D3D_OK, "Expected D3D_OK, got %#lx\n", hr);
5398 got_fvf = skininfo->lpVtbl->GetFVF(skininfo);
5399 ok(got_fvf == 0, "Expected 0, got %#lx\n", got_fvf);
5400 hr = skininfo->lpVtbl->GetDeclaration(skininfo, declaration_out);
5401 ok(hr == D3D_OK, "Expected D3D_OK, got %#lx\n", hr);
5402 compare_elements(declaration_out, empty_declaration, __LINE__, 0);
5404 hr = skininfo->lpVtbl->SetFVF(skininfo, fvf);
5405 ok(hr == D3D_OK, "Expected D3D_OK, got %#lx\n", hr);
5406 got_fvf = skininfo->lpVtbl->GetFVF(skininfo);
5407 ok(fvf == got_fvf, "Expected %#lx, got %#lx\n", fvf, got_fvf);
5408 hr = skininfo->lpVtbl->GetDeclaration(skininfo, declaration_out);
5409 ok(hr == D3D_OK, "Expected D3D_OK, got %#lx\n", hr);
5410 compare_elements(declaration_out, declaration_in, __LINE__, 0);
5413 /* Test Clone() */
5414 hr = skininfo->lpVtbl->Clone(skininfo, NULL);
5415 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
5417 clone = NULL;
5418 hr = skininfo->lpVtbl->Clone(skininfo, &clone);
5419 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
5421 hr = clone->lpVtbl->GetDeclaration(clone, declaration);
5422 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
5423 compare_elements(declaration, declaration_out, __LINE__, 0);
5425 hr = D3DXFVFFromDeclarator(declaration_out, &exp_fvf);
5426 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
5427 fvf = clone->lpVtbl->GetFVF(clone);
5428 ok(fvf == exp_fvf, "Got unexpected fvf %#lx.\n", fvf);
5430 exp_string = skininfo->lpVtbl->GetBoneName(skininfo, 0);
5431 string = clone->lpVtbl->GetBoneName(clone, 0);
5432 ok(!strcmp(string, exp_string), "Got unexpected bone 0 name %s.\n", debugstr_a(string));
5434 transform = clone->lpVtbl->GetBoneOffsetMatrix(clone, 0);
5435 check_matrix(transform, &identity_matrix);
5437 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, exp_vertices, exp_weights);
5438 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
5439 hr = clone->lpVtbl->GetBoneInfluence(clone, 0, vertices, weights);
5440 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
5442 for (i = 0; i < ARRAY_SIZE(vertices); ++i)
5444 ok(vertices[i] == exp_vertices[i], "influence[%u]: got unexpected vertex %lu, expected %lu.\n",
5445 i, vertices[i], exp_vertices[i]);
5446 ok(((DWORD *)weights)[i] == ((DWORD *)exp_weights)[i],
5447 "influence[%u]: got unexpected weight %.8e, expected %.8e.\n", i, weights[i], exp_weights[i]);
5450 IUnknown_Release(clone);
5452 if (skininfo) IUnknown_Release(skininfo);
5453 skininfo = NULL;
5455 hr = D3DXCreateSkinInfoFVF(1, D3DFVF_XYZ, 1, NULL);
5456 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#lx\n", hr);
5458 hr = D3DXCreateSkinInfo(1, NULL, 1, &skininfo);
5459 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#lx\n", hr);
5462 static void test_convert_adjacency_to_point_reps(void)
5464 HRESULT hr;
5465 struct test_context *test_context = NULL;
5466 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
5467 const DWORD options_16bit = D3DXMESH_SYSTEMMEM;
5468 const D3DVERTEXELEMENT9 declaration[] =
5470 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
5471 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
5472 {0, 24, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
5473 D3DDECL_END()
5475 const unsigned int VERTS_PER_FACE = 3;
5476 void *vertex_buffer;
5477 void *index_buffer;
5478 DWORD *attributes_buffer;
5479 int i, j;
5480 enum color { RED = 0xffff0000, GREEN = 0xff00ff00, BLUE = 0xff0000ff};
5481 struct vertex_pnc
5483 D3DXVECTOR3 position;
5484 D3DXVECTOR3 normal;
5485 enum color color; /* In case of manual visual inspection */
5487 D3DXVECTOR3 up = {0.0f, 0.0f, 1.0f};
5488 /* mesh0 (one face)
5490 * 0--1
5491 * | /
5492 * |/
5495 const struct vertex_pnc vertices0[] =
5497 {{ 0.0f, 3.0f, 0.f}, up, RED},
5498 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5499 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5501 const DWORD indices0[] = {0, 1, 2};
5502 const unsigned int num_vertices0 = ARRAY_SIZE(vertices0);
5503 const unsigned int num_faces0 = ARRAY_SIZE(indices0) / VERTS_PER_FACE;
5504 const DWORD adjacency0[] = {-1, -1, -1};
5505 const DWORD exp_point_rep0[] = {0, 1, 2};
5506 /* mesh1 (right)
5508 * 0--1 3
5509 * | / /|
5510 * |/ / |
5511 * 2 5--4
5513 const struct vertex_pnc vertices1[] =
5515 {{ 0.0f, 3.0f, 0.f}, up, RED},
5516 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5517 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5519 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5520 {{ 3.0f, 0.0f, 0.f}, up, RED},
5521 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5523 const DWORD indices1[] = {0, 1, 2, 3, 4, 5};
5524 const unsigned int num_vertices1 = ARRAY_SIZE(vertices1);
5525 const unsigned int num_faces1 = ARRAY_SIZE(indices1) / VERTS_PER_FACE;
5526 const DWORD adjacency1[] = {-1, 1, -1, -1, -1, 0};
5527 const DWORD exp_point_rep1[] = {0, 1, 2, 1, 4, 2};
5528 /* mesh2 (left)
5530 * 3 0--1
5531 * /| | /
5532 * / | |/
5533 * 5--4 2
5535 const struct vertex_pnc vertices2[] =
5537 {{ 0.0f, 3.0f, 0.f}, up, RED},
5538 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5539 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5541 {{-1.0f, 3.0f, 0.f}, up, RED},
5542 {{-1.0f, 0.0f, 0.f}, up, GREEN},
5543 {{-3.0f, 0.0f, 0.f}, up, BLUE},
5545 const DWORD indices2[] = {0, 1, 2, 3, 4, 5};
5546 const unsigned int num_vertices2 = ARRAY_SIZE(vertices2);
5547 const unsigned int num_faces2 = ARRAY_SIZE(indices2) / VERTS_PER_FACE;
5548 const DWORD adjacency2[] = {-1, -1, 1, 0, -1, -1};
5549 const DWORD exp_point_rep2[] = {0, 1, 2, 0, 2, 5};
5550 /* mesh3 (above)
5553 * /|
5554 * / |
5555 * 5--4
5556 * 0--1
5557 * | /
5558 * |/
5561 struct vertex_pnc vertices3[] =
5563 {{ 0.0f, 3.0f, 0.f}, up, RED},
5564 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5565 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5567 {{ 2.0f, 7.0f, 0.f}, up, BLUE},
5568 {{ 2.0f, 4.0f, 0.f}, up, GREEN},
5569 {{ 0.0f, 4.0f, 0.f}, up, RED},
5571 const DWORD indices3[] = {0, 1, 2, 3, 4, 5};
5572 const unsigned int num_vertices3 = ARRAY_SIZE(vertices3);
5573 const unsigned int num_faces3 = ARRAY_SIZE(indices3) / VERTS_PER_FACE;
5574 const DWORD adjacency3[] = {1, -1, -1, -1, 0, -1};
5575 const DWORD exp_point_rep3[] = {0, 1, 2, 3, 1, 0};
5576 /* mesh4 (below, tip against tip)
5578 * 0--1
5579 * | /
5580 * |/
5583 * |\
5584 * | \
5585 * 5--4
5587 struct vertex_pnc vertices4[] =
5589 {{ 0.0f, 3.0f, 0.f}, up, RED},
5590 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5591 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5593 {{ 0.0f, -4.0f, 0.f}, up, BLUE},
5594 {{ 2.0f, -7.0f, 0.f}, up, GREEN},
5595 {{ 0.0f, -7.0f, 0.f}, up, RED},
5597 const DWORD indices4[] = {0, 1, 2, 3, 4, 5};
5598 const unsigned int num_vertices4 = ARRAY_SIZE(vertices4);
5599 const unsigned int num_faces4 = ARRAY_SIZE(indices4) / VERTS_PER_FACE;
5600 const DWORD adjacency4[] = {-1, -1, -1, -1, -1, -1};
5601 const DWORD exp_point_rep4[] = {0, 1, 2, 3, 4, 5};
5602 /* mesh5 (gap in mesh)
5604 * 0 3-----4 15
5605 * / \ \ / / \
5606 * / \ \ / / \
5607 * 2-----1 5 17-----16
5608 * 6-----7 9 12-----13
5609 * \ / / \ \ /
5610 * \ / / \ \ /
5611 * 8 10-----11 14
5614 const struct vertex_pnc vertices5[] =
5616 {{ 0.0f, 1.0f, 0.f}, up, RED},
5617 {{ 1.0f, -1.0f, 0.f}, up, GREEN},
5618 {{-1.0f, -1.0f, 0.f}, up, BLUE},
5620 {{ 0.1f, 1.0f, 0.f}, up, RED},
5621 {{ 2.1f, 1.0f, 0.f}, up, BLUE},
5622 {{ 1.1f, -1.0f, 0.f}, up, GREEN},
5624 {{-1.0f, -1.1f, 0.f}, up, BLUE},
5625 {{ 1.0f, -1.1f, 0.f}, up, GREEN},
5626 {{ 0.0f, -3.1f, 0.f}, up, RED},
5628 {{ 1.1f, -1.1f, 0.f}, up, GREEN},
5629 {{ 2.1f, -3.1f, 0.f}, up, BLUE},
5630 {{ 0.1f, -3.1f, 0.f}, up, RED},
5632 {{ 1.2f, -1.1f, 0.f}, up, GREEN},
5633 {{ 3.2f, -1.1f, 0.f}, up, RED},
5634 {{ 2.2f, -3.1f, 0.f}, up, BLUE},
5636 {{ 2.2f, 1.0f, 0.f}, up, BLUE},
5637 {{ 3.2f, -1.0f, 0.f}, up, RED},
5638 {{ 1.2f, -1.0f, 0.f}, up, GREEN},
5640 const DWORD indices5[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17};
5641 const unsigned int num_vertices5 = ARRAY_SIZE(vertices5);
5642 const unsigned int num_faces5 = ARRAY_SIZE(indices5) / VERTS_PER_FACE;
5643 const DWORD adjacency5[] = {-1, 2, -1, -1, 5, -1, 0, -1, -1, 4, -1, -1, 5, -1, 3, -1, 4, 1};
5644 const DWORD exp_point_rep5[] = {0, 1, 2, 3, 4, 5, 2, 1, 8, 5, 10, 11, 5, 13, 10, 4, 13, 5};
5645 const WORD indices5_16bit[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17};
5646 /* mesh6 (indices re-ordering)
5648 * 0--1 6 3
5649 * | / /| |\
5650 * |/ / | | \
5651 * 2 8--7 5--4
5653 const struct vertex_pnc vertices6[] =
5655 {{ 0.0f, 3.0f, 0.f}, up, RED},
5656 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5657 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5659 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5660 {{ 3.0f, 0.0f, 0.f}, up, RED},
5661 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5663 {{ 4.0f, 3.0f, 0.f}, up, GREEN},
5664 {{ 6.0f, 0.0f, 0.f}, up, BLUE},
5665 {{ 4.0f, 0.0f, 0.f}, up, RED},
5667 const DWORD indices6[] = {0, 1, 2, 6, 7, 8, 3, 4, 5};
5668 const unsigned int num_vertices6 = ARRAY_SIZE(vertices6);
5669 const unsigned int num_faces6 = ARRAY_SIZE(indices6) / VERTS_PER_FACE;
5670 const DWORD adjacency6[] = {-1, 1, -1, 2, -1, 0, -1, -1, 1};
5671 const DWORD exp_point_rep6[] = {0, 1, 2, 1, 4, 5, 1, 5, 2};
5672 /* mesh7 (expands collapsed triangle)
5674 * 0--1 3
5675 * | / /|
5676 * |/ / |
5677 * 2 5--4
5679 const struct vertex_pnc vertices7[] =
5681 {{ 0.0f, 3.0f, 0.f}, up, RED},
5682 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5683 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5685 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5686 {{ 3.0f, 0.0f, 0.f}, up, RED},
5687 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5689 const DWORD indices7[] = {0, 1, 2, 3, 3, 3}; /* Face 1 is collapsed*/
5690 const unsigned int num_vertices7 = ARRAY_SIZE(vertices7);
5691 const unsigned int num_faces7 = ARRAY_SIZE(indices7) / VERTS_PER_FACE;
5692 const DWORD adjacency7[] = {-1, -1, -1, -1, -1, -1};
5693 const DWORD exp_point_rep7[] = {0, 1, 2, 3, 4, 5};
5694 /* mesh8 (indices re-ordering and double replacement)
5696 * 0--1 9 6
5697 * | / /| |\
5698 * |/ / | | \
5699 * 2 11-10 8--7
5700 * 3--4
5701 * | /
5702 * |/
5705 const struct vertex_pnc vertices8[] =
5707 {{ 0.0f, 3.0f, 0.f}, up, RED},
5708 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5709 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5711 {{ 4.0, -4.0, 0.f}, up, RED},
5712 {{ 6.0, -4.0, 0.f}, up, BLUE},
5713 {{ 4.0, -7.0, 0.f}, up, GREEN},
5715 {{ 4.0f, 3.0f, 0.f}, up, GREEN},
5716 {{ 6.0f, 0.0f, 0.f}, up, BLUE},
5717 {{ 4.0f, 0.0f, 0.f}, up, RED},
5719 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5720 {{ 3.0f, 0.0f, 0.f}, up, RED},
5721 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5723 const DWORD indices8[] = {0, 1, 2, 9, 10, 11, 6, 7, 8, 3, 4, 5};
5724 const unsigned int num_vertices8 = ARRAY_SIZE(vertices8);
5725 const unsigned int num_faces8 = ARRAY_SIZE(indices8) / VERTS_PER_FACE;
5726 const DWORD adjacency8[] = {-1, 1, -1, 2, -1, 0, -1, 3, 1, 2, -1, -1};
5727 const DWORD exp_point_rep8[] = {0, 1, 2, 3, 4, 5, 1, 4, 3, 1, 3, 2};
5728 /* mesh9 (right, shared vertices)
5730 * 0--1
5731 * | /|
5732 * |/ |
5733 * 2--3
5735 const struct vertex_pnc vertices9[] =
5737 {{ 0.0f, 3.0f, 0.f}, up, RED},
5738 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5739 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5741 {{ 2.0f, 0.0f, 0.f}, up, RED},
5743 const DWORD indices9[] = {0, 1, 2, 1, 3, 2};
5744 const unsigned int num_vertices9 = ARRAY_SIZE(vertices9);
5745 const unsigned int num_faces9 = ARRAY_SIZE(indices9) / VERTS_PER_FACE;
5746 const DWORD adjacency9[] = {-1, 1, -1, -1, -1, 0};
5747 const DWORD exp_point_rep9[] = {0, 1, 2, 3};
5748 /* All mesh data */
5749 ID3DXMesh *mesh = NULL;
5750 ID3DXMesh *mesh_null_check = NULL;
5751 unsigned int attributes[] = {0};
5752 struct
5754 const struct vertex_pnc *vertices;
5755 const DWORD *indices;
5756 const DWORD num_vertices;
5757 const DWORD num_faces;
5758 const DWORD *adjacency;
5759 const DWORD *exp_point_reps;
5760 const DWORD options;
5762 tc[] =
5765 vertices0,
5766 indices0,
5767 num_vertices0,
5768 num_faces0,
5769 adjacency0,
5770 exp_point_rep0,
5771 options
5774 vertices1,
5775 indices1,
5776 num_vertices1,
5777 num_faces1,
5778 adjacency1,
5779 exp_point_rep1,
5780 options
5783 vertices2,
5784 indices2,
5785 num_vertices2,
5786 num_faces2,
5787 adjacency2,
5788 exp_point_rep2,
5789 options
5792 vertices3,
5793 indices3,
5794 num_vertices3,
5795 num_faces3,
5796 adjacency3,
5797 exp_point_rep3,
5798 options
5801 vertices4,
5802 indices4,
5803 num_vertices4,
5804 num_faces4,
5805 adjacency4,
5806 exp_point_rep4,
5807 options
5810 vertices5,
5811 indices5,
5812 num_vertices5,
5813 num_faces5,
5814 adjacency5,
5815 exp_point_rep5,
5816 options
5819 vertices6,
5820 indices6,
5821 num_vertices6,
5822 num_faces6,
5823 adjacency6,
5824 exp_point_rep6,
5825 options
5828 vertices7,
5829 indices7,
5830 num_vertices7,
5831 num_faces7,
5832 adjacency7,
5833 exp_point_rep7,
5834 options
5837 vertices8,
5838 indices8,
5839 num_vertices8,
5840 num_faces8,
5841 adjacency8,
5842 exp_point_rep8,
5843 options
5846 vertices9,
5847 indices9,
5848 num_vertices9,
5849 num_faces9,
5850 adjacency9,
5851 exp_point_rep9,
5852 options
5855 vertices5,
5856 (DWORD*)indices5_16bit,
5857 num_vertices5,
5858 num_faces5,
5859 adjacency5,
5860 exp_point_rep5,
5861 options_16bit
5864 DWORD *point_reps = NULL;
5866 test_context = new_test_context();
5867 if (!test_context)
5869 skip("Couldn't create test context\n");
5870 goto cleanup;
5873 for (i = 0; i < ARRAY_SIZE(tc); i++)
5875 hr = D3DXCreateMesh(tc[i].num_faces, tc[i].num_vertices, tc[i].options, declaration,
5876 test_context->device, &mesh);
5877 if (FAILED(hr))
5879 skip("Couldn't create mesh %d. Got %lx expected D3D_OK\n", i, hr);
5880 goto cleanup;
5883 if (i == 0) /* Save first mesh for later NULL checks */
5884 mesh_null_check = mesh;
5886 point_reps = malloc(tc[i].num_vertices * sizeof(*point_reps));
5887 if (!point_reps)
5889 skip("Couldn't allocate point reps array.\n");
5890 goto cleanup;
5893 hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, &vertex_buffer);
5894 if (FAILED(hr))
5896 skip("Couldn't lock vertex buffer.\n");
5897 goto cleanup;
5899 memcpy(vertex_buffer, tc[i].vertices, tc[i].num_vertices * sizeof(*tc[i].vertices));
5900 hr = mesh->lpVtbl->UnlockVertexBuffer(mesh);
5901 if (FAILED(hr))
5903 skip("Couldn't unlock vertex buffer.\n");
5904 goto cleanup;
5907 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, &index_buffer);
5908 if (FAILED(hr))
5910 skip("Couldn't lock index buffer.\n");
5911 goto cleanup;
5913 if (tc[i].options & D3DXMESH_32BIT)
5915 memcpy(index_buffer, tc[i].indices, VERTS_PER_FACE * tc[i].num_faces * sizeof(DWORD));
5917 else
5919 memcpy(index_buffer, tc[i].indices, VERTS_PER_FACE * tc[i].num_faces * sizeof(WORD));
5921 hr = mesh->lpVtbl->UnlockIndexBuffer(mesh);
5922 if (FAILED(hr)) {
5923 skip("Couldn't unlock index buffer.\n");
5924 goto cleanup;
5927 hr = mesh->lpVtbl->LockAttributeBuffer(mesh, 0, &attributes_buffer);
5928 if (FAILED(hr))
5930 skip("Couldn't lock attributes buffer.\n");
5931 goto cleanup;
5933 memcpy(attributes_buffer, attributes, sizeof(attributes));
5934 hr = mesh->lpVtbl->UnlockAttributeBuffer(mesh);
5935 if (FAILED(hr))
5937 skip("Couldn't unlock attributes buffer.\n");
5938 goto cleanup;
5941 /* Convert adjacency to point representation */
5942 for (j = 0; j < tc[i].num_vertices; j++) point_reps[j] = -1;
5943 hr = mesh->lpVtbl->ConvertAdjacencyToPointReps(mesh, tc[i].adjacency, point_reps);
5944 ok(hr == D3D_OK, "ConvertAdjacencyToPointReps failed case %d. "
5945 "Got %lx expected D3D_OK\n", i, hr);
5947 /* Check point representation */
5948 for (j = 0; j < tc[i].num_vertices; j++)
5950 ok(point_reps[j] == tc[i].exp_point_reps[j],
5951 "Unexpected point representation at (%d, %d)."
5952 " Got %ld expected %ld\n",
5953 i, j, point_reps[j], tc[i].exp_point_reps[j]);
5956 free(point_reps);
5957 point_reps = NULL;
5959 if (i != 0) /* First mesh will be freed during cleanup */
5960 mesh->lpVtbl->Release(mesh);
5963 /* NULL checks */
5964 hr = mesh_null_check->lpVtbl->ConvertAdjacencyToPointReps(mesh_null_check, tc[0].adjacency, NULL);
5965 ok(hr == D3DERR_INVALIDCALL, "ConvertAdjacencyToPointReps point_reps NULL. "
5966 "Got %lx expected D3DERR_INVALIDCALL\n", hr);
5967 hr = mesh_null_check->lpVtbl->ConvertAdjacencyToPointReps(mesh_null_check, NULL, NULL);
5968 ok(hr == D3DERR_INVALIDCALL, "ConvertAdjacencyToPointReps adjacency and point_reps NULL. "
5969 "Got %lx expected D3DERR_INVALIDCALL\n", hr);
5971 cleanup:
5972 if (mesh_null_check)
5973 mesh_null_check->lpVtbl->Release(mesh_null_check);
5974 free(point_reps);
5975 free_test_context(test_context);
5978 static void test_convert_point_reps_to_adjacency(void)
5980 HRESULT hr;
5981 struct test_context *test_context = NULL;
5982 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
5983 const DWORD options_16bit = D3DXMESH_SYSTEMMEM;
5984 const D3DVERTEXELEMENT9 declaration[] =
5986 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
5987 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
5988 {0, 24, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
5989 D3DDECL_END()
5991 const unsigned int VERTS_PER_FACE = 3;
5992 void *vertex_buffer;
5993 void *index_buffer;
5994 DWORD *attributes_buffer;
5995 int i, j;
5996 enum color { RED = 0xffff0000, GREEN = 0xff00ff00, BLUE = 0xff0000ff};
5997 struct vertex_pnc
5999 D3DXVECTOR3 position;
6000 D3DXVECTOR3 normal;
6001 enum color color; /* In case of manual visual inspection */
6003 D3DXVECTOR3 up = {0.0f, 0.0f, 1.0f};
6004 /* mesh0 (one face)
6006 * 0--1
6007 * | /
6008 * |/
6011 const struct vertex_pnc vertices0[] =
6013 {{ 0.0f, 3.0f, 0.f}, up, RED},
6014 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
6015 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
6017 const DWORD indices0[] = {0, 1, 2};
6018 const unsigned int num_vertices0 = ARRAY_SIZE(vertices0);
6019 const unsigned int num_faces0 = num_vertices0 / VERTS_PER_FACE;
6020 const DWORD exp_adjacency0[] = {-1, -1, -1};
6021 const DWORD exp_id_adjacency0[] = {-1, -1, -1};
6022 const DWORD point_rep0[] = {0, 1, 2};
6023 /* mesh1 (right)
6025 * 0--1 3
6026 * | / /|
6027 * |/ / |
6028 * 2 5--4
6030 const struct vertex_pnc vertices1[] =
6032 {{ 0.0f, 3.0f, 0.f}, up, RED},
6033 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
6034 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
6036 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
6037 {{ 3.0f, 0.0f, 0.f}, up, RED},
6038 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
6040 const DWORD indices1[] = {0, 1, 2, 3, 4, 5};
6041 const unsigned int num_vertices1 = ARRAY_SIZE(vertices1);
6042 const unsigned int num_faces1 = num_vertices1 / VERTS_PER_FACE;
6043 const DWORD exp_adjacency1[] = {-1, 1, -1, -1, -1, 0};
6044 const DWORD exp_id_adjacency1[] = {-1, -1, -1, -1, -1, -1};
6045 const DWORD point_rep1[] = {0, 1, 2, 1, 4, 2};
6046 /* mesh2 (left)
6048 * 3 0--1
6049 * /| | /
6050 * / | |/
6051 * 5--4 2
6053 const struct vertex_pnc vertices2[] =
6055 {{ 0.0f, 3.0f, 0.f}, up, RED},
6056 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
6057 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
6059 {{-1.0f, 3.0f, 0.f}, up, RED},
6060 {{-1.0f, 0.0f, 0.f}, up, GREEN},
6061 {{-3.0f, 0.0f, 0.f}, up, BLUE},
6063 const DWORD indices2[] = {0, 1, 2, 3, 4, 5};
6064 const unsigned int num_vertices2 = ARRAY_SIZE(vertices2);
6065 const unsigned int num_faces2 = num_vertices2 / VERTS_PER_FACE;
6066 const DWORD exp_adjacency2[] = {-1, -1, 1, 0, -1, -1};
6067 const DWORD exp_id_adjacency2[] = {-1, -1, -1, -1, -1, -1};
6068 const DWORD point_rep2[] = {0, 1, 2, 0, 2, 5};
6069 /* mesh3 (above)
6072 * /|
6073 * / |
6074 * 5--4
6075 * 0--1
6076 * | /
6077 * |/
6080 struct vertex_pnc vertices3[] =
6082 {{ 0.0f, 3.0f, 0.f}, up, RED},
6083 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
6084 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
6086 {{ 2.0f, 7.0f, 0.f}, up, BLUE},
6087 {{ 2.0f, 4.0f, 0.f}, up, GREEN},
6088 {{ 0.0f, 4.0f, 0.f}, up, RED},
6090 const DWORD indices3[] = {0, 1, 2, 3, 4, 5};
6091 const unsigned int num_vertices3 = ARRAY_SIZE(vertices3);
6092 const unsigned int num_faces3 = num_vertices3 / VERTS_PER_FACE;
6093 const DWORD exp_adjacency3[] = {1, -1, -1, -1, 0, -1};
6094 const DWORD exp_id_adjacency3[] = {-1, -1, -1, -1, -1, -1};
6095 const DWORD point_rep3[] = {0, 1, 2, 3, 1, 0};
6096 /* mesh4 (below, tip against tip)
6098 * 0--1
6099 * | /
6100 * |/
6103 * |\
6104 * | \
6105 * 5--4
6107 struct vertex_pnc vertices4[] =
6109 {{ 0.0f, 3.0f, 0.f}, up, RED},
6110 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
6111 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
6113 {{ 0.0f, -4.0f, 0.f}, up, BLUE},
6114 {{ 2.0f, -7.0f, 0.f}, up, GREEN},
6115 {{ 0.0f, -7.0f, 0.f}, up, RED},
6117 const DWORD indices4[] = {0, 1, 2, 3, 4, 5};
6118 const unsigned int num_vertices4 = ARRAY_SIZE(vertices4);
6119 const unsigned int num_faces4 = num_vertices4 / VERTS_PER_FACE;
6120 const DWORD exp_adjacency4[] = {-1, -1, -1, -1, -1, -1};
6121 const DWORD exp_id_adjacency4[] = {-1, -1, -1, -1, -1, -1};
6122 const DWORD point_rep4[] = {0, 1, 2, 3, 4, 5};
6123 /* mesh5 (gap in mesh)
6125 * 0 3-----4 15
6126 * / \ \ / / \
6127 * / \ \ / / \
6128 * 2-----1 5 17-----16
6129 * 6-----7 9 12-----13
6130 * \ / / \ \ /
6131 * \ / / \ \ /
6132 * 8 10-----11 14
6135 const struct vertex_pnc vertices5[] =
6137 {{ 0.0f, 1.0f, 0.f}, up, RED},
6138 {{ 1.0f, -1.0f, 0.f}, up, GREEN},
6139 {{-1.0f, -1.0f, 0.f}, up, BLUE},
6141 {{ 0.1f, 1.0f, 0.f}, up, RED},
6142 {{ 2.1f, 1.0f, 0.f}, up, BLUE},
6143 {{ 1.1f, -1.0f, 0.f}, up, GREEN},
6145 {{-1.0f, -1.1f, 0.f}, up, BLUE},
6146 {{ 1.0f, -1.1f, 0.f}, up, GREEN},
6147 {{ 0.0f, -3.1f, 0.f}, up, RED},
6149 {{ 1.1f, -1.1f, 0.f}, up, GREEN},
6150 {{ 2.1f, -3.1f, 0.f}, up, BLUE},
6151 {{ 0.1f, -3.1f, 0.f}, up, RED},
6153 {{ 1.2f, -1.1f, 0.f}, up, GREEN},
6154 {{ 3.2f, -1.1f, 0.f}, up, RED},
6155 {{ 2.2f, -3.1f, 0.f}, up, BLUE},
6157 {{ 2.2f, 1.0f, 0.f}, up, BLUE},
6158 {{ 3.2f, -1.0f, 0.f}, up, RED},
6159 {{ 1.2f, -1.0f, 0.f}, up, GREEN},
6161 const DWORD indices5[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17};
6162 const unsigned int num_vertices5 = ARRAY_SIZE(vertices5);
6163 const unsigned int num_faces5 = num_vertices5 / VERTS_PER_FACE;
6164 const DWORD exp_adjacency5[] = {-1, 2, -1, -1, 5, -1, 0, -1, -1, 4, -1, -1, 5, -1, 3, -1, 4, 1};
6165 const DWORD exp_id_adjacency5[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
6166 const DWORD point_rep5[] = {0, 1, 2, 3, 4, 5, 2, 1, 8, 5, 10, 11, 5, 13, 10, 4, 13, 5};
6167 /* mesh6 (indices re-ordering)
6169 * 0--1 6 3
6170 * | / /| |\
6171 * |/ / | | \
6172 * 2 8--7 5--4
6174 const struct vertex_pnc vertices6[] =
6176 {{ 0.0f, 3.0f, 0.f}, up, RED},
6177 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
6178 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
6180 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
6181 {{ 3.0f, 0.0f, 0.f}, up, RED},
6182 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
6184 {{ 4.0f, 3.0f, 0.f}, up, GREEN},
6185 {{ 6.0f, 0.0f, 0.f}, up, BLUE},
6186 {{ 4.0f, 0.0f, 0.f}, up, RED},
6188 const DWORD indices6[] = {0, 1, 2, 6, 7, 8, 3, 4, 5};
6189 const unsigned int num_vertices6 = ARRAY_SIZE(vertices6);
6190 const unsigned int num_faces6 = num_vertices6 / VERTS_PER_FACE;
6191 const DWORD exp_adjacency6[] = {-1, 1, -1, 2, -1, 0, -1, -1, 1};
6192 const DWORD exp_id_adjacency6[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1};
6193 const DWORD point_rep6[] = {0, 1, 2, 1, 4, 5, 1, 5, 2};
6194 /* mesh7 (expands collapsed triangle)
6196 * 0--1 3
6197 * | / /|
6198 * |/ / |
6199 * 2 5--4
6201 const struct vertex_pnc vertices7[] =
6203 {{ 0.0f, 3.0f, 0.f}, up, RED},
6204 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
6205 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
6207 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
6208 {{ 3.0f, 0.0f, 0.f}, up, RED},
6209 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
6211 const DWORD indices7[] = {0, 1, 2, 3, 3, 3}; /* Face 1 is collapsed*/
6212 const unsigned int num_vertices7 = ARRAY_SIZE(vertices7);
6213 const unsigned int num_faces7 = num_vertices7 / VERTS_PER_FACE;
6214 const DWORD exp_adjacency7[] = {-1, -1, -1, -1, -1, -1};
6215 const DWORD exp_id_adjacency7[] = {-1, -1, -1, -1, -1, -1};
6216 const DWORD point_rep7[] = {0, 1, 2, 3, 4, 5};
6217 /* mesh8 (indices re-ordering and double replacement)
6219 * 0--1 9 6
6220 * | / /| |\
6221 * |/ / | | \
6222 * 2 11-10 8--7
6223 * 3--4
6224 * | /
6225 * |/
6228 const struct vertex_pnc vertices8[] =
6230 {{ 0.0f, 3.0f, 0.f}, up, RED},
6231 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
6232 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
6234 {{ 4.0, -4.0, 0.f}, up, RED},
6235 {{ 6.0, -4.0, 0.f}, up, BLUE},
6236 {{ 4.0, -7.0, 0.f}, up, GREEN},
6238 {{ 4.0f, 3.0f, 0.f}, up, GREEN},
6239 {{ 6.0f, 0.0f, 0.f}, up, BLUE},
6240 {{ 4.0f, 0.0f, 0.f}, up, RED},
6242 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
6243 {{ 3.0f, 0.0f, 0.f}, up, RED},
6244 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
6246 const DWORD indices8[] = {0, 1, 2, 9, 10, 11, 6, 7, 8, 3, 4, 5};
6247 const WORD indices8_16bit[] = {0, 1, 2, 9, 10, 11, 6, 7, 8, 3, 4, 5};
6248 const unsigned int num_vertices8 = ARRAY_SIZE(vertices8);
6249 const unsigned int num_faces8 = num_vertices8 / VERTS_PER_FACE;
6250 const DWORD exp_adjacency8[] = {-1, 1, -1, 2, -1, 0, -1, 3, 1, 2, -1, -1};
6251 const DWORD exp_id_adjacency8[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
6252 const DWORD point_rep8[] = {0, 1, 2, 3, 4, 5, 1, 4, 3, 1, 3, 2};
6253 /* mesh9 (right, shared vertices)
6255 * 0--1
6256 * | /|
6257 * |/ |
6258 * 2--3
6260 const struct vertex_pnc vertices9[] =
6262 {{ 0.0f, 3.0f, 0.f}, up, RED},
6263 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
6264 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
6266 {{ 2.0f, 0.0f, 0.f}, up, RED},
6268 const DWORD indices9[] = {0, 1, 2, 1, 3, 2};
6269 const unsigned int num_vertices9 = ARRAY_SIZE(vertices9);
6270 const unsigned int num_faces9 = 2;
6271 const DWORD exp_adjacency9[] = {-1, 1, -1, -1, -1, 0};
6272 const DWORD exp_id_adjacency9[] = {-1, 1, -1, -1, -1, 0};
6273 const DWORD point_rep9[] = {0, 1, 2, 3};
6274 /* All mesh data */
6275 ID3DXMesh *mesh = NULL;
6276 ID3DXMesh *mesh_null_check = NULL;
6277 unsigned int attributes[] = {0};
6278 struct
6280 const struct vertex_pnc *vertices;
6281 const DWORD *indices;
6282 const DWORD num_vertices;
6283 const DWORD num_faces;
6284 const DWORD *point_reps;
6285 const DWORD *exp_adjacency;
6286 const DWORD *exp_id_adjacency;
6287 const DWORD options;
6289 tc[] =
6292 vertices0,
6293 indices0,
6294 num_vertices0,
6295 num_faces0,
6296 point_rep0,
6297 exp_adjacency0,
6298 exp_id_adjacency0,
6299 options
6302 vertices1,
6303 indices1,
6304 num_vertices1,
6305 num_faces1,
6306 point_rep1,
6307 exp_adjacency1,
6308 exp_id_adjacency1,
6309 options
6312 vertices2,
6313 indices2,
6314 num_vertices2,
6315 num_faces2,
6316 point_rep2,
6317 exp_adjacency2,
6318 exp_id_adjacency2,
6319 options
6322 vertices3,
6323 indices3,
6324 num_vertices3,
6325 num_faces3,
6326 point_rep3,
6327 exp_adjacency3,
6328 exp_id_adjacency3,
6329 options
6332 vertices4,
6333 indices4,
6334 num_vertices4,
6335 num_faces4,
6336 point_rep4,
6337 exp_adjacency4,
6338 exp_id_adjacency4,
6339 options
6342 vertices5,
6343 indices5,
6344 num_vertices5,
6345 num_faces5,
6346 point_rep5,
6347 exp_adjacency5,
6348 exp_id_adjacency5,
6349 options
6352 vertices6,
6353 indices6,
6354 num_vertices6,
6355 num_faces6,
6356 point_rep6,
6357 exp_adjacency6,
6358 exp_id_adjacency6,
6359 options
6362 vertices7,
6363 indices7,
6364 num_vertices7,
6365 num_faces7,
6366 point_rep7,
6367 exp_adjacency7,
6368 exp_id_adjacency7,
6369 options
6372 vertices8,
6373 indices8,
6374 num_vertices8,
6375 num_faces8,
6376 point_rep8,
6377 exp_adjacency8,
6378 exp_id_adjacency8,
6379 options
6382 vertices9,
6383 indices9,
6384 num_vertices9,
6385 num_faces9,
6386 point_rep9,
6387 exp_adjacency9,
6388 exp_id_adjacency9,
6389 options
6392 vertices8,
6393 (DWORD*)indices8_16bit,
6394 num_vertices8,
6395 num_faces8,
6396 point_rep8,
6397 exp_adjacency8,
6398 exp_id_adjacency8,
6399 options_16bit
6402 DWORD *adjacency = NULL;
6404 test_context = new_test_context();
6405 if (!test_context)
6407 skip("Couldn't create test context\n");
6408 goto cleanup;
6411 for (i = 0; i < ARRAY_SIZE(tc); i++)
6413 hr = D3DXCreateMesh(tc[i].num_faces, tc[i].num_vertices, tc[i].options,
6414 declaration, test_context->device, &mesh);
6415 if (FAILED(hr))
6417 skip("Couldn't create mesh %d. Got %lx expected D3D_OK\n", i, hr);
6418 goto cleanup;
6421 if (i == 0) /* Save first mesh for later NULL checks */
6422 mesh_null_check = mesh;
6424 adjacency = malloc(VERTS_PER_FACE * tc[i].num_faces * sizeof(*adjacency));
6425 if (!adjacency)
6427 skip("Couldn't allocate adjacency array.\n");
6428 goto cleanup;
6431 hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, &vertex_buffer);
6432 if (FAILED(hr))
6434 skip("Couldn't lock vertex buffer.\n");
6435 goto cleanup;
6437 memcpy(vertex_buffer, tc[i].vertices, tc[i].num_vertices * sizeof(*tc[i].vertices));
6438 hr = mesh->lpVtbl->UnlockVertexBuffer(mesh);
6439 if (FAILED(hr))
6441 skip("Couldn't unlock vertex buffer.\n");
6442 goto cleanup;
6444 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, &index_buffer);
6445 if (FAILED(hr))
6447 skip("Couldn't lock index buffer.\n");
6448 goto cleanup;
6450 if (tc[i].options & D3DXMESH_32BIT)
6452 memcpy(index_buffer, tc[i].indices, VERTS_PER_FACE * tc[i].num_faces * sizeof(DWORD));
6454 else
6456 memcpy(index_buffer, tc[i].indices, VERTS_PER_FACE * tc[i].num_faces * sizeof(WORD));
6458 hr = mesh->lpVtbl->UnlockIndexBuffer(mesh);
6459 if (FAILED(hr)) {
6460 skip("Couldn't unlock index buffer.\n");
6461 goto cleanup;
6464 hr = mesh->lpVtbl->LockAttributeBuffer(mesh, 0, &attributes_buffer);
6465 if (FAILED(hr))
6467 skip("Couldn't lock attributes buffer.\n");
6468 goto cleanup;
6470 memcpy(attributes_buffer, attributes, sizeof(attributes));
6471 hr = mesh->lpVtbl->UnlockAttributeBuffer(mesh);
6472 if (FAILED(hr))
6474 skip("Couldn't unlock attributes buffer.\n");
6475 goto cleanup;
6478 /* Convert point representation to adjacency*/
6479 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++) adjacency[j] = -2;
6481 hr = mesh->lpVtbl->ConvertPointRepsToAdjacency(mesh, tc[i].point_reps, adjacency);
6482 ok(hr == D3D_OK, "ConvertPointRepsToAdjacency failed case %d. "
6483 "Got %lx expected D3D_OK\n", i, hr);
6484 /* Check adjacency */
6485 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
6487 ok(adjacency[j] == tc[i].exp_adjacency[j],
6488 "Unexpected adjacency information at (%d, %d)."
6489 " Got %ld expected %ld\n",
6490 i, j, adjacency[j], tc[i].exp_adjacency[j]);
6493 /* NULL point representation is considered identity. */
6494 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++) adjacency[j] = -2;
6495 hr = mesh_null_check->lpVtbl->ConvertPointRepsToAdjacency(mesh, NULL, adjacency);
6496 ok(hr == D3D_OK, "ConvertPointRepsToAdjacency NULL point_reps. "
6497 "Got %lx expected D3D_OK\n", hr);
6498 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
6500 ok(adjacency[j] == tc[i].exp_id_adjacency[j],
6501 "Unexpected adjacency information (id) at (%d, %d)."
6502 " Got %ld expected %ld\n",
6503 i, j, adjacency[j], tc[i].exp_id_adjacency[j]);
6506 free(adjacency);
6507 adjacency = NULL;
6508 if (i != 0) /* First mesh will be freed during cleanup */
6509 mesh->lpVtbl->Release(mesh);
6512 /* NULL checks */
6513 hr = mesh_null_check->lpVtbl->ConvertPointRepsToAdjacency(mesh_null_check, tc[0].point_reps, NULL);
6514 ok(hr == D3DERR_INVALIDCALL, "ConvertPointRepsToAdjacency NULL adjacency. "
6515 "Got %lx expected D3DERR_INVALIDCALL\n", hr);
6516 hr = mesh_null_check->lpVtbl->ConvertPointRepsToAdjacency(mesh_null_check, NULL, NULL);
6517 ok(hr == D3DERR_INVALIDCALL, "ConvertPointRepsToAdjacency NULL point_reps and adjacency. "
6518 "Got %lx expected D3DERR_INVALIDCALL\n", hr);
6520 cleanup:
6521 if (mesh_null_check)
6522 mesh_null_check->lpVtbl->Release(mesh_null_check);
6523 free(adjacency);
6524 free_test_context(test_context);
6527 static HRESULT init_test_mesh(const DWORD num_faces, const DWORD num_vertices,
6528 const DWORD options,
6529 const D3DVERTEXELEMENT9 *declaration,
6530 IDirect3DDevice9 *device, ID3DXMesh **mesh_ptr,
6531 const void *vertices, const DWORD vertex_size,
6532 const DWORD *indices, const DWORD *attributes)
6534 HRESULT hr;
6535 void *vertex_buffer;
6536 void *index_buffer;
6537 DWORD *attributes_buffer;
6538 ID3DXMesh *mesh = NULL;
6540 hr = D3DXCreateMesh(num_faces, num_vertices, options, declaration, device, mesh_ptr);
6541 if (FAILED(hr))
6543 skip("Couldn't create mesh. Got %lx expected D3D_OK\n", hr);
6544 goto cleanup;
6546 mesh = *mesh_ptr;
6548 hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, &vertex_buffer);
6549 if (FAILED(hr))
6551 skip("Couldn't lock vertex buffer.\n");
6552 goto cleanup;
6554 memcpy(vertex_buffer, vertices, num_vertices * vertex_size);
6555 hr = mesh->lpVtbl->UnlockVertexBuffer(mesh);
6556 if (FAILED(hr))
6558 skip("Couldn't unlock vertex buffer.\n");
6559 goto cleanup;
6562 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, &index_buffer);
6563 if (FAILED(hr))
6565 skip("Couldn't lock index buffer.\n");
6566 goto cleanup;
6568 if (options & D3DXMESH_32BIT)
6570 if (indices)
6571 memcpy(index_buffer, indices, 3 * num_faces * sizeof(DWORD));
6572 else
6574 /* Fill index buffer with 0, 1, 2, ...*/
6575 DWORD *indices_32bit = (DWORD*)index_buffer;
6576 UINT i;
6577 for (i = 0; i < 3 * num_faces; i++)
6578 indices_32bit[i] = i;
6581 else
6583 if (indices)
6584 memcpy(index_buffer, indices, 3 * num_faces * sizeof(WORD));
6585 else
6587 /* Fill index buffer with 0, 1, 2, ...*/
6588 WORD *indices_16bit = (WORD*)index_buffer;
6589 UINT i;
6590 for (i = 0; i < 3 * num_faces; i++)
6591 indices_16bit[i] = i;
6594 hr = mesh->lpVtbl->UnlockIndexBuffer(mesh);
6595 if (FAILED(hr)) {
6596 skip("Couldn't unlock index buffer.\n");
6597 goto cleanup;
6600 hr = mesh->lpVtbl->LockAttributeBuffer(mesh, 0, &attributes_buffer);
6601 if (FAILED(hr))
6603 skip("Couldn't lock attributes buffer.\n");
6604 goto cleanup;
6607 if (attributes)
6608 memcpy(attributes_buffer, attributes, num_faces * sizeof(*attributes));
6609 else
6610 memset(attributes_buffer, 0, num_faces * sizeof(*attributes));
6612 hr = mesh->lpVtbl->UnlockAttributeBuffer(mesh);
6613 if (FAILED(hr))
6615 skip("Couldn't unlock attributes buffer.\n");
6616 goto cleanup;
6619 hr = D3D_OK;
6620 cleanup:
6621 return hr;
6624 /* Using structs instead of bit-fields in order to avoid compiler issues. */
6625 struct udec3
6627 UINT x;
6628 UINT y;
6629 UINT z;
6630 UINT w;
6633 struct dec3n
6635 INT x;
6636 INT y;
6637 INT z;
6638 INT w;
6641 static DWORD init_udec3_dword(UINT x, UINT y, UINT z, UINT w)
6643 DWORD d = 0;
6645 d |= x & 0x3ff;
6646 d |= (y << 10) & 0xffc00;
6647 d |= (z << 20) & 0x3ff00000;
6648 d |= (w << 30) & 0xc0000000;
6650 return d;
6653 static DWORD init_dec3n_dword(INT x, INT y, INT z, INT w)
6655 DWORD d = 0;
6657 d |= x & 0x3ff;
6658 d |= (y << 10) & 0xffc00;
6659 d |= (z << 20) & 0x3ff00000;
6660 d |= (w << 30) & 0xc0000000;
6662 return d;
6665 static struct udec3 dword_to_udec3(DWORD d)
6667 struct udec3 v;
6669 v.x = d & 0x3ff;
6670 v.y = (d & 0xffc00) >> 10;
6671 v.z = (d & 0x3ff00000) >> 20;
6672 v.w = (d & 0xc0000000) >> 30;
6674 return v;
6677 static struct dec3n dword_to_dec3n(DWORD d)
6679 struct dec3n v;
6681 v.x = d & 0x3ff;
6682 v.y = (d & 0xffc00) >> 10;
6683 v.z = (d & 0x3ff00000) >> 20;
6684 v.w = (d & 0xc0000000) >> 30;
6686 return v;
6689 static void check_vertex_components(int line, int mesh_number, int vertex_number, BYTE *got_ptr, const BYTE *exp_ptr, D3DVERTEXELEMENT9 *declaration)
6691 const char *usage_strings[] =
6693 "position",
6694 "blend weight",
6695 "blend indices",
6696 "normal",
6697 "point size",
6698 "texture coordinates",
6699 "tangent",
6700 "binormal",
6701 "tessellation factor",
6702 "position transformed",
6703 "color",
6704 "fog",
6705 "depth",
6706 "sample"
6708 D3DVERTEXELEMENT9 *decl_ptr;
6709 const float PRECISION = 1e-5f;
6711 for (decl_ptr = declaration; decl_ptr->Stream != 0xFF; decl_ptr++)
6713 switch (decl_ptr->Type)
6715 case D3DDECLTYPE_FLOAT1:
6717 FLOAT *got = (FLOAT*)(got_ptr + decl_ptr->Offset);
6718 FLOAT *exp = (FLOAT*)(exp_ptr + decl_ptr->Offset);
6719 FLOAT diff = fabsf(*got - *exp);
6720 ok_(__FILE__,line)(diff <= PRECISION, "Mesh %d: Got %f for vertex %d %s, expected %f.\n",
6721 mesh_number, *got, vertex_number, usage_strings[decl_ptr->Usage], *exp);
6722 break;
6724 case D3DDECLTYPE_FLOAT2:
6726 D3DXVECTOR2 *got = (D3DXVECTOR2*)(got_ptr + decl_ptr->Offset);
6727 D3DXVECTOR2 *exp = (D3DXVECTOR2*)(exp_ptr + decl_ptr->Offset);
6728 FLOAT diff = max(fabsf(got->x - exp->x), fabsf(got->y - exp->y));
6729 ok_(__FILE__,line)(diff <= PRECISION, "Mesh %d: Got (%f, %f) for vertex %d %s, expected (%f, %f).\n",
6730 mesh_number, got->x, got->y, vertex_number, usage_strings[decl_ptr->Usage], exp->x, exp->y);
6731 break;
6733 case D3DDECLTYPE_FLOAT3:
6735 D3DXVECTOR3 *got = (D3DXVECTOR3*)(got_ptr + decl_ptr->Offset);
6736 D3DXVECTOR3 *exp = (D3DXVECTOR3*)(exp_ptr + decl_ptr->Offset);
6737 FLOAT diff = max(fabsf(got->x - exp->x), fabsf(got->y - exp->y));
6738 diff = max(diff, fabsf(got->z - exp->z));
6739 ok_(__FILE__,line)(diff <= PRECISION, "Mesh %d: Got (%f, %f, %f) for vertex %d %s, expected (%f, %f, %f).\n",
6740 mesh_number, got->x, got->y, got->z, vertex_number, usage_strings[decl_ptr->Usage], exp->x, exp->y, exp->z);
6741 break;
6743 case D3DDECLTYPE_FLOAT4:
6745 D3DXVECTOR4 *got = (D3DXVECTOR4*)(got_ptr + decl_ptr->Offset);
6746 D3DXVECTOR4 *exp = (D3DXVECTOR4*)(exp_ptr + decl_ptr->Offset);
6747 FLOAT diff = max(fabsf(got->x - exp->x), fabsf(got->y - exp->y));
6748 diff = max(diff, fabsf(got->z - exp->z));
6749 diff = max(diff, fabsf(got->w - exp->w));
6750 ok_(__FILE__,line)(diff <= PRECISION, "Mesh %d: Got (%f, %f, %f, %f) for vertex %d %s, expected (%f, %f, %f, %f).\n",
6751 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);
6752 break;
6754 case D3DDECLTYPE_D3DCOLOR:
6756 BYTE *got = got_ptr + decl_ptr->Offset;
6757 const BYTE *exp = exp_ptr + decl_ptr->Offset;
6758 BOOL same_color = got[0] == exp[0] && got[1] == exp[1]
6759 && got[2] == exp[2] && got[3] == exp[3];
6760 const char *color_types[] = {"diffuse", "specular", "undefined color"};
6761 BYTE usage_index = decl_ptr->UsageIndex;
6762 if (usage_index > 1) usage_index = 2;
6763 ok_(__FILE__,line)(same_color, "Mesh %d: Got (%u, %u, %u, %u) for vertex %d %s, expected (%u, %u, %u, %u).\n",
6764 mesh_number, got[0], got[1], got[2], got[3], vertex_number, color_types[usage_index], exp[0], exp[1], exp[2], exp[3]);
6765 break;
6767 case D3DDECLTYPE_UBYTE4:
6768 case D3DDECLTYPE_UBYTE4N:
6770 BYTE *got = got_ptr + decl_ptr->Offset;
6771 const BYTE *exp = exp_ptr + decl_ptr->Offset;
6772 BOOL same = got[0] == exp[0] && got[1] == exp[1]
6773 && got[2] == exp[2] && got[3] == exp[3];
6774 ok_(__FILE__,line)(same, "Mesh %d: Got (%u, %u, %u, %u) for vertex %d %s, expected (%u, %u, %u, %u).\n",
6775 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]);
6776 break;
6778 case D3DDECLTYPE_SHORT2:
6779 case D3DDECLTYPE_SHORT2N:
6781 SHORT *got = (SHORT*)(got_ptr + decl_ptr->Offset);
6782 SHORT *exp = (SHORT*)(exp_ptr + decl_ptr->Offset);
6783 BOOL same = got[0] == exp[0] && got[1] == exp[1];
6784 ok_(__FILE__,line)(same, "Mesh %d: Got (%hd, %hd) for vertex %d %s, expected (%hd, %hd).\n",
6785 mesh_number, got[0], got[1], vertex_number, usage_strings[decl_ptr->Usage], exp[0], exp[1]);
6786 break;
6788 case D3DDECLTYPE_SHORT4:
6789 case D3DDECLTYPE_SHORT4N:
6791 SHORT *got = (SHORT*)(got_ptr + decl_ptr->Offset);
6792 SHORT *exp = (SHORT*)(exp_ptr + decl_ptr->Offset);
6793 BOOL same = got[0] == exp[0] && got[1] == exp[1]
6794 && got[2] == exp[2] && got[3] == exp[3];
6795 ok_(__FILE__,line)(same, "Mesh %d: Got (%hd, %hd, %hd, %hd) for vertex %d %s, expected (%hd, %hd, %hd, %hd).\n",
6796 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]);
6797 break;
6799 case D3DDECLTYPE_USHORT2N:
6801 USHORT *got = (USHORT*)(got_ptr + decl_ptr->Offset);
6802 USHORT *exp = (USHORT*)(exp_ptr + decl_ptr->Offset);
6803 BOOL same = got[0] == exp[0] && got[1] == exp[1];
6804 ok_(__FILE__,line)(same, "Mesh %d: Got (%hu, %hu) for vertex %d %s, expected (%hu, %hu).\n",
6805 mesh_number, got[0], got[1], vertex_number, usage_strings[decl_ptr->Usage], exp[0], exp[1]);
6806 break;
6808 case D3DDECLTYPE_USHORT4N:
6810 USHORT *got = (USHORT*)(got_ptr + decl_ptr->Offset);
6811 USHORT *exp = (USHORT*)(exp_ptr + decl_ptr->Offset);
6812 BOOL same = got[0] == exp[0] && got[1] == exp[1]
6813 && got[2] == exp[2] && got[3] == exp[3];
6814 ok_(__FILE__,line)(same, "Mesh %d: Got (%hu, %hu, %hu, %hu) for vertex %d %s, expected (%hu, %hu, %hu, %hu).\n",
6815 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]);
6816 break;
6818 case D3DDECLTYPE_UDEC3:
6820 DWORD *got = (DWORD*)(got_ptr + decl_ptr->Offset);
6821 DWORD *exp = (DWORD*)(exp_ptr + decl_ptr->Offset);
6822 BOOL same = memcmp(got, exp, sizeof(*got)) == 0;
6823 struct udec3 got_udec3 = dword_to_udec3(*got);
6824 struct udec3 exp_udec3 = dword_to_udec3(*exp);
6825 ok_(__FILE__,line)(same, "Mesh %d: Got (%u, %u, %u, %u) for vertex %d %s, expected (%u, %u, %u, %u).\n",
6826 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);
6828 break;
6830 case D3DDECLTYPE_DEC3N:
6832 DWORD *got = (DWORD*)(got_ptr + decl_ptr->Offset);
6833 DWORD *exp = (DWORD*)(exp_ptr + decl_ptr->Offset);
6834 BOOL same = memcmp(got, exp, sizeof(*got)) == 0;
6835 struct dec3n got_dec3n = dword_to_dec3n(*got);
6836 struct dec3n exp_dec3n = dword_to_dec3n(*exp);
6837 ok_(__FILE__,line)(same, "Mesh %d: Got (%d, %d, %d, %d) for vertex %d %s, expected (%d, %d, %d, %d).\n",
6838 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);
6839 break;
6841 case D3DDECLTYPE_FLOAT16_2:
6843 WORD *got = (WORD*)(got_ptr + decl_ptr->Offset);
6844 WORD *exp = (WORD*)(exp_ptr + decl_ptr->Offset);
6845 BOOL same = got[0] == exp[0] && got[1] == exp[1];
6846 ok_(__FILE__,line)(same, "Mesh %d: Got (%hx, %hx) for vertex %d %s, expected (%hx, %hx).\n",
6847 mesh_number, got[0], got[1], vertex_number, usage_strings[decl_ptr->Usage], exp[0], exp[1]);
6848 break;
6850 case D3DDECLTYPE_FLOAT16_4:
6852 WORD *got = (WORD*)(got_ptr + decl_ptr->Offset);
6853 WORD *exp = (WORD*)(exp_ptr + decl_ptr->Offset);
6854 BOOL same = got[0] == exp[0] && got[1] == exp[1]
6855 && got[2] == exp[2] && got[3] == exp[3];
6856 ok_(__FILE__,line)(same, "Mesh %d: Got (%hx, %hx, %hx, %hx) for vertex %d %s, expected (%hx, %hx, %hx, %hx).\n",
6857 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]);
6858 break;
6860 default:
6861 break;
6866 static void test_weld_vertices(void)
6868 HRESULT hr;
6869 struct test_context *test_context = NULL;
6870 DWORD i;
6871 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
6872 const DWORD options_16bit = D3DXMESH_SYSTEMMEM;
6873 BYTE *vertices = NULL;
6874 DWORD *indices = NULL;
6875 WORD *indices_16bit = NULL;
6876 const UINT VERTS_PER_FACE = 3;
6877 const D3DXVECTOR3 up = {0.0f, 0.0f, 1.0f};
6878 struct vertex_normal
6880 D3DXVECTOR3 position;
6881 D3DXVECTOR3 normal;
6883 struct vertex_blendweight
6885 D3DXVECTOR3 position;
6886 FLOAT blendweight;
6888 struct vertex_texcoord
6890 D3DXVECTOR3 position;
6891 D3DXVECTOR2 texcoord;
6893 struct vertex_color
6895 D3DXVECTOR3 position;
6896 DWORD color;
6898 struct vertex_color_ubyte4
6900 D3DXVECTOR3 position;
6901 BYTE color[4];
6903 struct vertex_texcoord_short2
6905 D3DXVECTOR3 position;
6906 SHORT texcoord[2];
6908 struct vertex_texcoord_ushort2n
6910 D3DXVECTOR3 position;
6911 USHORT texcoord[2];
6913 struct vertex_normal_short4
6915 D3DXVECTOR3 position;
6916 SHORT normal[4];
6918 struct vertex_texcoord_float16_2
6920 D3DXVECTOR3 position;
6921 WORD texcoord[2];
6923 struct vertex_texcoord_float16_4
6925 D3DXVECTOR3 position;
6926 WORD texcoord[4];
6928 struct vertex_normal_udec3
6930 D3DXVECTOR3 position;
6931 DWORD normal;
6933 struct vertex_normal_dec3n
6935 D3DXVECTOR3 position;
6936 DWORD normal;
6938 UINT vertex_size_normal = sizeof(struct vertex_normal);
6939 UINT vertex_size_blendweight = sizeof(struct vertex_blendweight);
6940 UINT vertex_size_texcoord = sizeof(struct vertex_texcoord);
6941 UINT vertex_size_color = sizeof(struct vertex_color);
6942 UINT vertex_size_color_ubyte4 = sizeof(struct vertex_color_ubyte4);
6943 UINT vertex_size_texcoord_short2 = sizeof(struct vertex_texcoord_short2);
6944 UINT vertex_size_normal_short4 = sizeof(struct vertex_normal_short4);
6945 UINT vertex_size_texcoord_float16_2 = sizeof(struct vertex_texcoord_float16_2);
6946 UINT vertex_size_texcoord_float16_4 = sizeof(struct vertex_texcoord_float16_4);
6947 UINT vertex_size_normal_udec3 = sizeof(struct vertex_normal_udec3);
6948 UINT vertex_size_normal_dec3n = sizeof(struct vertex_normal_dec3n);
6949 D3DVERTEXELEMENT9 declaration_normal[] =
6951 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6952 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6953 D3DDECL_END()
6955 D3DVERTEXELEMENT9 declaration_normal3[] =
6957 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 3},
6958 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6959 D3DDECL_END()
6961 D3DVERTEXELEMENT9 declaration_blendweight[] =
6963 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6964 {0, 12, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BLENDWEIGHT, 0},
6965 D3DDECL_END()
6967 D3DVERTEXELEMENT9 declaration_texcoord[] =
6969 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6970 {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6971 D3DDECL_END()
6973 D3DVERTEXELEMENT9 declaration_color[] =
6975 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6976 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
6977 D3DDECL_END()
6979 D3DVERTEXELEMENT9 declaration_color_ubyte4n[] =
6981 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6982 {0, 12, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
6983 D3DDECL_END()
6985 D3DVERTEXELEMENT9 declaration_color_ubyte4[] =
6987 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6988 {0, 12, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
6989 D3DDECL_END()
6991 D3DVERTEXELEMENT9 declaration_texcoord_short2[] =
6993 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6994 {0, 12, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6995 D3DDECL_END()
6997 D3DVERTEXELEMENT9 declaration_texcoord_short2n[] =
6999 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
7000 {0, 12, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
7001 D3DDECL_END()
7003 D3DVERTEXELEMENT9 declaration_texcoord_ushort2n[] =
7005 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
7006 {0, 12, D3DDECLTYPE_USHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
7007 D3DDECL_END()
7009 D3DVERTEXELEMENT9 declaration_normal_short4[] =
7011 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
7012 {0, 12, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
7013 D3DDECL_END()
7015 D3DVERTEXELEMENT9 declaration_normal_short4n[] =
7017 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
7018 {0, 12, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
7019 D3DDECL_END()
7021 D3DVERTEXELEMENT9 declaration_normal_ushort4n[] =
7023 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
7024 {0, 12, D3DDECLTYPE_USHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
7025 D3DDECL_END()
7027 D3DVERTEXELEMENT9 declaration_texcoord10[] =
7029 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
7030 {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 10},
7031 D3DDECL_END()
7033 D3DVERTEXELEMENT9 declaration_color2[] =
7035 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
7036 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 2},
7037 D3DDECL_END()
7039 D3DVERTEXELEMENT9 declaration_color1[] =
7041 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
7042 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 1},
7043 D3DDECL_END()
7045 D3DVERTEXELEMENT9 declaration_texcoord_float16_2[] =
7047 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
7048 {0, 12, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
7049 D3DDECL_END()
7051 D3DVERTEXELEMENT9 declaration_texcoord_float16_4[] =
7053 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
7054 {0, 12, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
7055 D3DDECL_END()
7057 D3DVERTEXELEMENT9 declaration_normal_udec3[] =
7059 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
7060 {0, 12, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
7061 D3DDECL_END()
7063 D3DVERTEXELEMENT9 declaration_normal_dec3n[] =
7065 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
7066 {0, 12, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
7067 D3DDECL_END()
7069 /* Test 0. One face and no welding.
7071 * 0--1
7072 * | /
7073 * |/
7076 const struct vertex vertices0[] =
7078 {{ 0.0f, 3.0f, 0.f}, up},
7079 {{ 2.0f, 3.0f, 0.f}, up},
7080 {{ 0.0f, 0.0f, 0.f}, up},
7082 const DWORD indices0[] = {0, 1, 2};
7083 const DWORD attributes0[] = {0};
7084 const DWORD exp_indices0[] = {0, 1, 2};
7085 const UINT num_vertices0 = ARRAY_SIZE(vertices0);
7086 const UINT num_faces0 = ARRAY_SIZE(indices0) / VERTS_PER_FACE;
7087 const DWORD flags0 = D3DXWELDEPSILONS_WELDALL;
7088 /* epsilons0 is NULL */
7089 const DWORD adjacency0[] = {-1, -1, -1};
7090 const struct vertex exp_vertices0[] =
7092 {{ 0.0f, 3.0f, 0.f}, up},
7093 {{ 2.0f, 3.0f, 0.f}, up},
7094 {{ 0.0f, 0.0f, 0.f}, up},
7096 const DWORD exp_face_remap0[] = {0};
7097 const DWORD exp_vertex_remap0[] = {0, 1, 2};
7098 const DWORD exp_new_num_vertices0 = ARRAY_SIZE(exp_vertices0);
7099 /* Test 1. Two vertices should be removed without regard to epsilon.
7101 * 0--1 3
7102 * | / /|
7103 * |/ / |
7104 * 2 5--4
7106 const struct vertex_normal vertices1[] =
7108 {{ 0.0f, 3.0f, 0.f}, up},
7109 {{ 2.0f, 3.0f, 0.f}, up},
7110 {{ 0.0f, 0.0f, 0.f}, up},
7112 {{ 3.0f, 3.0f, 0.f}, up},
7113 {{ 3.0f, 0.0f, 0.f}, up},
7114 {{ 1.0f, 0.0f, 0.f}, up},
7116 const DWORD indices1[] = {0, 1, 2, 3, 4, 5};
7117 const DWORD attributes1[] = {0, 0};
7118 const UINT num_vertices1 = ARRAY_SIZE(vertices1);
7119 const UINT num_faces1 = ARRAY_SIZE(indices1) / VERTS_PER_FACE;
7120 const DWORD flags1 = D3DXWELDEPSILONS_WELDALL;
7121 /* epsilons1 is NULL */
7122 const DWORD adjacency1[] = {-1, 1, -1, -1, -1, 0};
7123 const struct vertex_normal exp_vertices1[] =
7125 {{ 0.0f, 3.0f, 0.f}, up},
7126 {{ 2.0f, 3.0f, 0.f}, up},
7127 {{ 0.0f, 0.0f, 0.f}, up},
7129 {{ 3.0f, 0.0f, 0.f}, up}
7131 const DWORD exp_indices1[] = {0, 1, 2, 1, 3, 2};
7132 const DWORD exp_face_remap1[] = {0, 1};
7133 const DWORD exp_vertex_remap1[] = {0, 1, 2, 4, -1, -1};
7134 const DWORD exp_new_num_vertices1 = ARRAY_SIZE(exp_vertices1);
7135 /* Test 2. Two faces. No vertices should be removed because of normal
7136 * epsilon, but the positions should be replaced. */
7137 const struct vertex_normal vertices2[] =
7139 {{ 0.0f, 3.0f, 0.f}, up},
7140 {{ 2.0f, 3.0f, 0.f}, up},
7141 {{ 0.0f, 0.0f, 0.f}, up},
7143 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
7144 {{ 3.0f, 0.0f, 0.f}, up},
7145 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
7147 const DWORD indices2[] = {0, 1, 2, 3, 4, 5};
7148 const DWORD attributes2[] = {0, 0};
7149 const UINT num_vertices2 = ARRAY_SIZE(vertices2);
7150 const UINT num_faces2 = ARRAY_SIZE(indices2) / VERTS_PER_FACE;
7151 DWORD flags2 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7152 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};
7153 const DWORD adjacency2[] = {-1, 1, -1, -1, -1, 0};
7154 const struct vertex_normal exp_vertices2[] =
7156 {{ 0.0f, 3.0f, 0.f}, up},
7157 {{ 2.0f, 3.0f, 0.f}, up},
7158 {{ 0.0f, 0.0f, 0.f}, up},
7160 {{ 2.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
7161 {{ 3.0f, 0.0f, 0.f}, up},
7162 {{ 0.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
7164 const DWORD exp_indices2[] = {0, 1, 2, 3, 4, 5};
7165 const DWORD exp_face_remap2[] = {0, 1};
7166 const DWORD exp_vertex_remap2[] = {0, 1, 2, 3, 4, 5};
7167 const DWORD exp_new_num_vertices2 = ARRAY_SIZE(exp_vertices2);
7168 /* Test 3. Two faces. One vertex should be removed because of normal epsilon. */
7169 const struct vertex_normal vertices3[] =
7171 {{ 0.0f, 3.0f, 0.f}, up},
7172 {{ 2.0f, 3.0f, 0.f}, up},
7173 {{ 0.0f, 0.0f, 0.f}, up},
7175 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
7176 {{ 3.0f, 0.0f, 0.f}, up},
7177 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
7179 const DWORD indices3[] = {0, 1, 2, 3, 4, 5};
7180 const DWORD attributes3[] = {0, 0};
7181 const UINT num_vertices3 = ARRAY_SIZE(vertices3);
7182 const UINT num_faces3 = ARRAY_SIZE(indices3) / VERTS_PER_FACE;
7183 DWORD flags3 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7184 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};
7185 const DWORD adjacency3[] = {-1, 1, -1, -1, -1, 0};
7186 const struct vertex_normal exp_vertices3[] =
7188 {{ 0.0f, 3.0f, 0.f}, up},
7189 {{ 2.0f, 3.0f, 0.f}, up},
7190 {{ 0.0f, 0.0f, 0.f}, up},
7192 {{ 3.0f, 0.0f, 0.f}, up},
7193 {{ 0.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
7195 const DWORD exp_indices3[] = {0, 1, 2, 1, 3, 4};
7196 const DWORD exp_face_remap3[] = {0, 1};
7197 const DWORD exp_vertex_remap3[] = {0, 1, 2, 4, 5, -1};
7198 const DWORD exp_new_num_vertices3 = ARRAY_SIZE(exp_vertices3);
7199 /* Test 4 Two faces. Two vertices should be removed. */
7200 const struct vertex_normal vertices4[] =
7202 {{ 0.0f, 3.0f, 0.f}, up},
7203 {{ 2.0f, 3.0f, 0.f}, up},
7204 {{ 0.0f, 0.0f, 0.f}, up},
7206 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
7207 {{ 3.0f, 0.0f, 0.f}, up},
7208 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
7210 const DWORD indices4[] = {0, 1, 2, 3, 4, 5};
7211 const DWORD attributes4[] = {0, 0};
7212 const UINT num_vertices4 = ARRAY_SIZE(vertices4);
7213 const UINT num_faces4 = ARRAY_SIZE(indices4) / VERTS_PER_FACE;
7214 DWORD flags4 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7215 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};
7216 const DWORD adjacency4[] = {-1, 1, -1, -1, -1, 0};
7217 const struct vertex_normal exp_vertices4[] =
7219 {{ 0.0f, 3.0f, 0.f}, up},
7220 {{ 2.0f, 3.0f, 0.f}, up},
7221 {{ 0.0f, 0.0f, 0.f}, up},
7223 {{ 3.0f, 0.0f, 0.f}, up},
7225 const DWORD exp_indices4[] = {0, 1, 2, 1, 3, 2};
7226 const DWORD exp_face_remap4[] = {0, 1};
7227 const DWORD exp_vertex_remap4[] = {0, 1, 2, 4, -1, -1};
7228 const DWORD exp_new_num_vertices4 = ARRAY_SIZE(exp_vertices4);
7229 /* Test 5. Odd face ordering.
7231 * 0--1 6 3
7232 * | / /| |\
7233 * |/ / | | \
7234 * 2 8--7 5--4
7236 const struct vertex_normal vertices5[] =
7238 {{ 0.0f, 3.0f, 0.f}, up},
7239 {{ 2.0f, 3.0f, 0.f}, up},
7240 {{ 0.0f, 0.0f, 0.f}, up},
7242 {{ 3.0f, 3.0f, 0.f}, up},
7243 {{ 3.0f, 0.0f, 0.f}, up},
7244 {{ 1.0f, 0.0f, 0.f}, up},
7246 {{ 4.0f, 3.0f, 0.f}, up},
7247 {{ 6.0f, 0.0f, 0.f}, up},
7248 {{ 4.0f, 0.0f, 0.f}, up},
7250 const DWORD indices5[] = {0, 1, 2, 6, 7, 8, 3, 4, 5};
7251 const DWORD exp_indices5[] = {0, 1, 2, 1, 4, 2, 1, 3, 4};
7252 const DWORD attributes5[] = {0, 0, 0};
7253 const UINT num_vertices5 = ARRAY_SIZE(vertices5);
7254 const UINT num_faces5 = ARRAY_SIZE(indices5) / VERTS_PER_FACE;
7255 DWORD flags5 = D3DXWELDEPSILONS_WELDALL;
7256 const DWORD adjacency5[] = {-1, 1, -1, 2, -1, 0, -1, -1, 1};
7257 const struct vertex_normal exp_vertices5[] =
7259 {{ 0.0f, 3.0f, 0.f}, up},
7260 {{ 2.0f, 3.0f, 0.f}, up},
7261 {{ 0.0f, 0.0f, 0.f}, up},
7263 {{ 3.0f, 0.0f, 0.f}, up},
7264 {{ 1.0f, 0.0f, 0.f}, up},
7266 const DWORD exp_face_remap5[] = {0, 1, 2};
7267 const DWORD exp_vertex_remap5[] = {0, 1, 2, 4, 5, -1, -1, -1, -1};
7268 const DWORD exp_new_num_vertices5 = ARRAY_SIZE(exp_vertices5);
7269 /* Test 6. Two faces. Do not remove flag is used, so no vertices should be
7270 * removed. */
7271 const struct vertex_normal vertices6[] =
7273 {{ 0.0f, 3.0f, 0.f}, up},
7274 {{ 2.0f, 3.0f, 0.f}, up},
7275 {{ 0.0f, 0.0f, 0.f}, up},
7277 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
7278 {{ 3.0f, 0.0f, 0.f}, up},
7279 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
7281 const DWORD indices6[] = {0, 1, 2, 3, 4, 5};
7282 const DWORD attributes6[] = {0, 0};
7283 const UINT num_vertices6 = ARRAY_SIZE(vertices6);
7284 const UINT num_faces6 = ARRAY_SIZE(indices6) / VERTS_PER_FACE;
7285 DWORD flags6 = D3DXWELDEPSILONS_WELDPARTIALMATCHES | D3DXWELDEPSILONS_DONOTREMOVEVERTICES;
7286 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};
7287 const DWORD adjacency6[] = {-1, 1, -1, -1, -1, 0};
7288 const struct vertex_normal exp_vertices6[] =
7290 {{ 0.0f, 3.0f, 0.f}, up},
7291 {{ 2.0f, 3.0f, 0.f}, up},
7292 {{ 0.0f, 0.0f, 0.f}, up},
7294 {{ 2.0f, 3.0f, 0.f}, up},
7295 {{ 3.0f, 0.0f, 0.f}, up},
7296 {{ 0.0f, 0.0f, 0.f}, up},
7299 const DWORD exp_indices6[] = {0, 1, 2, 3, 4, 5};
7300 const DWORD exp_face_remap6[] = {0, 1};
7301 const DWORD exp_vertex_remap6[] = {0, 1, 2, 3, 4, 5};
7302 const DWORD exp_new_num_vertices6 = ARRAY_SIZE(exp_vertices6);
7303 /* Test 7. Same as test 6 but with 16 bit indices. */
7304 const WORD indices6_16bit[] = {0, 1, 2, 3, 4, 5};
7305 /* Test 8. No flags. Same result as D3DXWELDEPSILONS_WELDPARTIALMATCHES. */
7306 const struct vertex_normal vertices8[] =
7308 {{ 0.0f, 3.0f, 0.f}, up},
7309 {{ 2.0f, 3.0f, 0.f}, up},
7310 {{ 0.0f, 0.0f, 0.f}, up},
7312 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
7313 {{ 3.0f, 0.0f, 0.f}, up},
7314 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
7316 const DWORD indices8[] = {0, 1, 2, 1, 3, 4};
7317 const DWORD attributes8[] = {0, 0};
7318 const UINT num_vertices8 = ARRAY_SIZE(vertices8);
7319 const UINT num_faces8 = ARRAY_SIZE(indices8) / VERTS_PER_FACE;
7320 DWORD flags8 = 0;
7321 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};
7322 const DWORD adjacency8[] = {-1, 1, -1, -1, -1, 0};
7323 const struct vertex_normal exp_vertices8[] =
7325 {{ 0.0f, 3.0f, 0.f}, up},
7326 {{ 2.0f, 3.0f, 0.f}, up},
7327 {{ 0.0f, 0.0f, 0.f}, up},
7329 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
7330 {{ 3.0f, 0.0f, 0.f}, up},
7332 const DWORD exp_indices8[] = {0, 1, 2, 1, 3, 4};
7333 const DWORD exp_face_remap8[] = {0, 1};
7334 const DWORD exp_vertex_remap8[] = {0, 1, 2, 3, 4, -1};
7335 const DWORD exp_new_num_vertices8 = ARRAY_SIZE(exp_vertices8);
7336 /* Test 9. Vertices are removed even though they belong to separate
7337 * attribute groups if D3DXWELDEPSILONS_DONOTSPLIT is set. */
7338 const struct vertex_normal vertices9[] =
7340 {{ 0.0f, 3.0f, 0.f}, up},
7341 {{ 2.0f, 3.0f, 0.f}, up},
7342 {{ 0.0f, 0.0f, 0.f}, up},
7344 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
7345 {{ 3.0f, 0.0f, 0.f}, up},
7346 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
7348 const DWORD indices9[] = {0, 1, 2, 3, 4, 5};
7349 const DWORD attributes9[] = {0, 1};
7350 const UINT num_vertices9 = ARRAY_SIZE(vertices9);
7351 const UINT num_faces9 = ARRAY_SIZE(indices9) / VERTS_PER_FACE;
7352 DWORD flags9 = D3DXWELDEPSILONS_WELDPARTIALMATCHES | D3DXWELDEPSILONS_DONOTSPLIT;
7353 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};
7354 const DWORD adjacency9[] = {-1, 1, -1, -1, -1, 0};
7355 const struct vertex_normal exp_vertices9[] =
7357 {{ 0.0f, 3.0f, 0.f}, up},
7358 {{ 2.0f, 3.0f, 0.f}, up},
7359 {{ 0.0f, 0.0f, 0.f}, up},
7361 {{ 3.0f, 0.0f, 0.f}, up},
7363 const DWORD exp_indices9[] = {0, 1, 2, 1, 3, 2};
7364 const DWORD exp_face_remap9[] = {0, 1};
7365 const DWORD exp_vertex_remap9[] = {0, 1, 2, 4, -1, -1};
7366 const DWORD exp_new_num_vertices9 = ARRAY_SIZE(exp_vertices9);
7367 /* Test 10. Weld blendweight (FLOAT1). */
7368 const struct vertex_blendweight vertices10[] =
7370 {{ 0.0f, 3.0f, 0.f}, 1.0f},
7371 {{ 2.0f, 3.0f, 0.f}, 1.0f},
7372 {{ 0.0f, 0.0f, 0.f}, 1.0f},
7374 {{ 3.0f, 3.0f, 0.f}, 0.9},
7375 {{ 3.0f, 0.0f, 0.f}, 1.0},
7376 {{ 1.0f, 0.0f, 0.f}, 0.4},
7378 const DWORD indices10[] = {0, 1, 2, 3, 4, 5};
7379 const DWORD attributes10[] = {0, 0};
7380 const UINT num_vertices10 = ARRAY_SIZE(vertices10);
7381 const UINT num_faces10 = ARRAY_SIZE(indices10) / VERTS_PER_FACE;
7382 DWORD flags10 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7383 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};
7384 const DWORD adjacency10[] = {-1, 1, -1, -1, -1, 0};
7385 const struct vertex_blendweight exp_vertices10[] =
7387 {{ 0.0f, 3.0f, 0.f}, 1.0f},
7388 {{ 2.0f, 3.0f, 0.f}, 1.0f},
7389 {{ 0.0f, 0.0f, 0.f}, 1.0f},
7391 {{ 3.0f, 0.0f, 0.f}, 1.0},
7392 {{ 0.0f, 0.0f, 0.f}, 0.4},
7394 const DWORD exp_indices10[] = {0, 1, 2, 1, 3, 4};
7395 const DWORD exp_face_remap10[] = {0, 1};
7396 const DWORD exp_vertex_remap10[] = {0, 1, 2, 4, 5, -1};
7397 const DWORD exp_new_num_vertices10 = ARRAY_SIZE(exp_vertices10);
7398 /* Test 11. Weld texture coordinates. */
7399 const struct vertex_texcoord vertices11[] =
7401 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f}},
7402 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.7f}},
7403 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
7405 {{ 3.0f, 3.0f, 0.f}, {0.2f, 0.3f}},
7406 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f}},
7407 {{ 1.0f, 0.0f, 0.f}, {0.1f, 0.2f}}
7409 const DWORD indices11[] = {0, 1, 2, 3, 4, 5};
7410 const DWORD attributes11[] = {0, 0};
7411 const UINT num_vertices11 = ARRAY_SIZE(vertices11);
7412 const UINT num_faces11 = ARRAY_SIZE(indices11) / VERTS_PER_FACE;
7413 DWORD flags11 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7414 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};
7415 const DWORD adjacency11[] = {-1, 1, -1, -1, -1, 0};
7416 const struct vertex_texcoord exp_vertices11[] =
7418 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f}},
7419 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.7f}},
7420 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
7422 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f}},
7423 {{ 0.0f, 0.0f, 0.f}, {0.1f, 0.2f}},
7425 const DWORD exp_indices11[] = {0, 1, 2, 1, 3, 4};
7426 const DWORD exp_face_remap11[] = {0, 1};
7427 const DWORD exp_vertex_remap11[] = {0, 1, 2, 4, 5, -1};
7428 const DWORD exp_new_num_vertices11 = ARRAY_SIZE(exp_vertices11);
7429 /* Test 12. Weld with color. */
7430 const struct vertex_color vertices12[] =
7432 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7433 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7434 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7436 {{ 3.0f, 3.0f, 0.f}, 0x00000000},
7437 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7438 {{ 1.0f, 0.0f, 0.f}, 0x88888888},
7440 const DWORD indices12[] = {0, 1, 2, 3, 4, 5};
7441 const DWORD attributes12[] = {0, 0};
7442 const UINT num_vertices12 = ARRAY_SIZE(vertices12);
7443 const UINT num_faces12 = ARRAY_SIZE(indices12) / VERTS_PER_FACE;
7444 DWORD flags12 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7445 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};
7446 const DWORD adjacency12[] = {-1, 1, -1, -1, -1, 0};
7447 const struct vertex_color exp_vertices12[] =
7449 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7450 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7451 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7453 {{ 2.0f, 3.0f, 0.f}, 0x00000000},
7454 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7456 const DWORD exp_indices12[] = {0, 1, 2, 3, 4, 2};
7457 const DWORD exp_face_remap12[] = {0, 1};
7458 const DWORD exp_vertex_remap12[] = {0, 1, 2, 3, 4, -1};
7459 const DWORD exp_new_num_vertices12 = ARRAY_SIZE(exp_vertices12);
7460 /* Test 13. Two faces. One vertex should be removed because of normal epsilon.
7461 * This is similar to test 3, but the declaration has been changed to NORMAL3.
7463 const struct vertex_normal vertices13[] =
7465 {{ 0.0f, 3.0f, 0.f}, up},
7466 {{ 2.0f, 3.0f, 0.f}, up},
7467 {{ 0.0f, 0.0f, 0.f}, up},
7469 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
7470 {{ 3.0f, 0.0f, 0.f}, up},
7471 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
7473 const DWORD indices13[] = {0, 1, 2, 3, 4, 5};
7474 const DWORD attributes13[] = {0, 0};
7475 const UINT num_vertices13 = ARRAY_SIZE(vertices3);
7476 const UINT num_faces13 = ARRAY_SIZE(indices3) / VERTS_PER_FACE;
7477 DWORD flags13 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7478 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};
7479 const DWORD adjacency13[] = {-1, 1, -1, -1, -1, 0};
7480 const struct vertex_normal exp_vertices13[] =
7482 {{ 0.0f, 3.0f, 0.f}, up},
7483 {{ 2.0f, 3.0f, 0.f}, up},
7484 {{ 0.0f, 0.0f, 0.f}, up},
7486 {{ 3.0f, 0.0f, 0.f}, up},
7487 {{ 0.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
7489 const DWORD exp_indices13[] = {0, 1, 2, 1, 3, 4};
7490 const DWORD exp_face_remap13[] = {0, 1};
7491 const DWORD exp_vertex_remap13[] = {0, 1, 2, 4, 5, -1};
7492 const DWORD exp_new_num_vertices13 = ARRAY_SIZE(exp_vertices13);
7493 /* Test 14. Another test for welding with color. */
7494 const struct vertex_color vertices14[] =
7496 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7497 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7498 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7500 {{ 3.0f, 3.0f, 0.f}, 0x00000000},
7501 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7502 {{ 1.0f, 0.0f, 0.f}, 0x01010101},
7504 const DWORD indices14[] = {0, 1, 2, 3, 4, 5};
7505 const DWORD attributes14[] = {0, 0};
7506 const UINT num_vertices14 = ARRAY_SIZE(vertices14);
7507 const UINT num_faces14 = ARRAY_SIZE(indices14) / VERTS_PER_FACE;
7508 DWORD flags14 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7509 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};
7510 const DWORD adjacency14[] = {-1, 1, -1, -1, -1, 0};
7511 const struct vertex_color exp_vertices14[] =
7513 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7514 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7515 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7517 {{ 2.0f, 3.0f, 0.f}, 0x00000000},
7518 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7520 const DWORD exp_indices14[] = {0, 1, 2, 3, 4, 2};
7521 const DWORD exp_face_remap14[] = {0, 1};
7522 const DWORD exp_vertex_remap14[] = {0, 1, 2, 3, 4, -1};
7523 const DWORD exp_new_num_vertices14 = ARRAY_SIZE(exp_vertices14);
7524 /* Test 15. Weld with color, but as UBYTE4N instead of D3DCOLOR. It shows
7525 * that UBYTE4N and D3DCOLOR are compared the same way.
7527 const struct vertex_color_ubyte4 vertices15[] =
7529 {{ 0.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7530 {{ 2.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7531 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7533 {{ 3.0f, 3.0f, 0.f}, { 0, 0, 0, 0}},
7534 {{ 3.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7535 {{ 1.0f, 0.0f, 0.f}, { 1, 1, 1, 1}},
7537 const DWORD indices15[] = {0, 1, 2, 3, 4, 5};
7538 const DWORD attributes15[] = {0, 0};
7539 const UINT num_vertices15 = ARRAY_SIZE(vertices15);
7540 const UINT num_faces15 = ARRAY_SIZE(indices15) / VERTS_PER_FACE;
7541 DWORD flags15 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7542 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};
7543 const DWORD adjacency15[] = {-1, 1, -1, -1, -1, 0};
7544 const struct vertex_color_ubyte4 exp_vertices15[] =
7546 {{ 0.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7547 {{ 2.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7548 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7550 {{ 2.0f, 3.0f, 0.f}, { 0, 0, 0, 0}},
7551 {{ 3.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7553 const DWORD exp_indices15[] = {0, 1, 2, 3, 4, 2};
7554 const DWORD exp_face_remap15[] = {0, 1};
7555 const DWORD exp_vertex_remap15[] = {0, 1, 2, 3, 4, -1};
7556 const DWORD exp_new_num_vertices15 = ARRAY_SIZE(exp_vertices15);
7557 /* Test 16. Weld with color, but as UBYTE4 instead of D3DCOLOR. It shows
7558 * that UBYTE4 is not normalized and that epsilon is truncated and compared
7559 * directly to each of the four bytes.
7561 const struct vertex_color_ubyte4 vertices16[] =
7563 {{ 0.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7564 {{ 2.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7565 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7567 {{ 3.0f, 3.0f, 0.f}, { 0, 0, 0, 0}},
7568 {{ 3.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7569 {{ 1.0f, 0.0f, 0.f}, { 1, 1, 1, 1}},
7571 const DWORD indices16[] = {0, 1, 2, 3, 4, 5};
7572 const DWORD attributes16[] = {0, 0};
7573 const UINT num_vertices16 = ARRAY_SIZE(vertices16);
7574 const UINT num_faces16 = ARRAY_SIZE(indices16) / VERTS_PER_FACE;
7575 DWORD flags16 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7576 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};
7577 const DWORD adjacency16[] = {-1, 1, -1, -1, -1, 0};
7578 const struct vertex_color_ubyte4 exp_vertices16[] =
7580 {{ 0.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7581 {{ 2.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7582 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7584 {{ 2.0f, 3.0f, 0.f}, { 0, 0, 0, 0}},
7585 {{ 3.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7587 const DWORD exp_indices16[] = {0, 1, 2, 3, 4, 2};
7588 const DWORD exp_face_remap16[] = {0, 1};
7589 const DWORD exp_vertex_remap16[] = {0, 1, 2, 3, 4, -1};
7590 const DWORD exp_new_num_vertices16 = ARRAY_SIZE(exp_vertices16);
7591 /* Test 17. Weld texture coordinates but as SHORT2 instead of D3DXVECTOR2.*/
7592 const struct vertex_texcoord_short2 vertices17[] =
7594 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7595 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7596 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7598 {{ 3.0f, 3.0f, 0.f}, {32767, 32767}},
7599 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7600 {{ 1.0f, 0.0f, 0.f}, {32766, 32766}},
7602 const DWORD indices17[] = {0, 1, 2, 3, 4, 5};
7603 const DWORD attributes17[] = {0, 0};
7604 const UINT num_vertices17 = ARRAY_SIZE(vertices17);
7605 const UINT num_faces17 = ARRAY_SIZE(indices17) / VERTS_PER_FACE;
7606 DWORD flags17 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7607 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};
7608 const DWORD adjacency17[] = {-1, 1, -1, -1, -1, 0};
7609 const struct vertex_texcoord_short2 exp_vertices17[] =
7611 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7612 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7613 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7615 {{ 2.0f, 3.0f, 0.f}, {32767, 32767}},
7616 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7618 const DWORD exp_indices17[] = {0, 1, 2, 3, 4, 2};
7619 const DWORD exp_face_remap17[] = {0, 1};
7620 const DWORD exp_vertex_remap17[] = {0, 1, 2, 3, 4, -1};
7621 const DWORD exp_new_num_vertices17 = ARRAY_SIZE(exp_vertices17);
7622 /* Test 18. Weld texture coordinates but as SHORT2N instead of D3DXVECTOR2. */
7623 const struct vertex_texcoord_short2 vertices18[] =
7625 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7626 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7627 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7629 {{ 3.0f, 3.0f, 0.f}, {32767, 32767}},
7630 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7631 {{ 1.0f, 0.0f, 0.f}, {32766, 32766}},
7633 const DWORD indices18[] = {0, 1, 2, 3, 4, 5};
7634 const DWORD attributes18[] = {0, 0};
7635 const UINT num_vertices18 = ARRAY_SIZE(vertices18);
7636 const UINT num_faces18 = ARRAY_SIZE(indices18) / VERTS_PER_FACE;
7637 DWORD flags18 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7638 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};
7639 const DWORD adjacency18[] = {-1, 1, -1, -1, -1, 0};
7640 const struct vertex_texcoord_short2 exp_vertices18[] =
7642 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7643 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7644 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7646 {{ 2.0f, 3.0f, 0.f}, {32767, 32767}},
7647 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7649 const DWORD exp_indices18[] = {0, 1, 2, 3, 4, 2};
7650 const DWORD exp_face_remap18[] = {0, 1};
7651 const DWORD exp_vertex_remap18[] = {0, 1, 2, 3, 4, -1};
7652 const DWORD exp_new_num_vertices18 = ARRAY_SIZE(exp_vertices18);
7653 /* Test 19. Weld texture coordinates but as USHORT2N instead of D3DXVECTOR2. */
7654 const struct vertex_texcoord_ushort2n vertices19[] =
7656 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7657 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7658 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7660 {{ 3.0f, 3.0f, 0.f}, {65535, 65535}},
7661 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7662 {{ 1.0f, 0.0f, 0.f}, {65534, 65534}},
7664 const DWORD indices19[] = {0, 1, 2, 3, 4, 5};
7665 const DWORD attributes19[] = {0, 0};
7666 const UINT num_vertices19 = ARRAY_SIZE(vertices19);
7667 const UINT num_faces19 = ARRAY_SIZE(indices19) / VERTS_PER_FACE;
7668 DWORD flags19 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7669 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};
7670 const DWORD adjacency19[] = {-1, 1, -1, -1, -1, 0};
7671 const struct vertex_texcoord_ushort2n exp_vertices19[] =
7673 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7674 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7675 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7677 {{ 2.0f, 3.0f, 0.f}, {65535, 65535}},
7678 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7680 const DWORD exp_indices19[] = {0, 1, 2, 3, 4, 2};
7681 const DWORD exp_face_remap19[] = {0, 1};
7682 const DWORD exp_vertex_remap19[] = {0, 1, 2, 3, 4, -1};
7683 const DWORD exp_new_num_vertices19 = ARRAY_SIZE(exp_vertices19);
7684 /* Test 20. Weld normal as SHORT4 instead of D3DXVECTOR3. */
7685 const struct vertex_normal_short4 vertices20[] =
7687 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7688 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7689 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7691 {{ 3.0f, 3.0f, 0.f}, {32767, 32767, 32767, 32767}},
7692 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7693 {{ 1.0f, 0.0f, 0.f}, {32766, 32766, 32766, 32766}},
7695 const DWORD indices20[] = {0, 1, 2, 3, 4, 5};
7696 const DWORD attributes20[] = {0, 0};
7697 const UINT num_vertices20 = ARRAY_SIZE(vertices20);
7698 const UINT num_faces20 = ARRAY_SIZE(indices20) / VERTS_PER_FACE;
7699 DWORD flags20 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7700 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};
7701 const DWORD adjacency20[] = {-1, 1, -1, -1, -1, 0};
7702 const struct vertex_normal_short4 exp_vertices20[] =
7704 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7705 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7706 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7708 {{ 2.0f, 3.0f, 0.f}, {32767, 32767, 32767, 32767}},
7709 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7711 const DWORD exp_indices20[] = {0, 1, 2, 3, 4, 2};
7712 const DWORD exp_face_remap20[] = {0, 1};
7713 const DWORD exp_vertex_remap20[] = {0, 1, 2, 3, 4, -1};
7714 const DWORD exp_new_num_vertices20 = ARRAY_SIZE(exp_vertices20);
7715 /* Test 21. Weld normal as SHORT4N instead of D3DXVECTOR3. */
7716 const struct vertex_normal_short4 vertices21[] =
7718 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7719 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7720 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7722 {{ 3.0f, 3.0f, 0.f}, {32767, 32767, 32767, 32767}},
7723 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7724 {{ 1.0f, 0.0f, 0.f}, {32766, 32766, 32766, 32766}},
7726 const DWORD indices21[] = {0, 1, 2, 3, 4, 5};
7727 const DWORD attributes21[] = {0, 0};
7728 const UINT num_vertices21 = ARRAY_SIZE(vertices21);
7729 const UINT num_faces21 = ARRAY_SIZE(indices21) / VERTS_PER_FACE;
7730 DWORD flags21 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7731 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};
7732 const DWORD adjacency21[] = {-1, 1, -1, -1, -1, 0};
7733 const struct vertex_normal_short4 exp_vertices21[] =
7735 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7736 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7737 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7739 {{ 2.0f, 3.0f, 0.f}, {32767, 32767, 32767, 32767}},
7740 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7742 const DWORD exp_indices21[] = {0, 1, 2, 3, 4, 2};
7743 const DWORD exp_face_remap21[] = {0, 1};
7744 const DWORD exp_vertex_remap21[] = {0, 1, 2, 3, 4, -1};
7745 const DWORD exp_new_num_vertices21 = ARRAY_SIZE(exp_vertices21);
7746 /* Test 22. Weld normal as USHORT4N instead of D3DXVECTOR3. */
7747 const struct vertex_normal_short4 vertices22[] =
7749 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7750 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7751 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7753 {{ 3.0f, 3.0f, 0.f}, {-1, -1, -1, -1}},
7754 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7755 {{ 1.0f, 0.0f, 0.f}, {-2, -2, -2, -2}},
7757 const DWORD indices22[] = {0, 1, 2, 3, 4, 5};
7758 const DWORD attributes22[] = {0, 0};
7759 const UINT num_vertices22 = ARRAY_SIZE(vertices22);
7760 const UINT num_faces22 = ARRAY_SIZE(indices22) / VERTS_PER_FACE;
7761 DWORD flags22 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7762 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};
7763 const DWORD adjacency22[] = {-1, 1, -1, -1, -1, 0};
7764 const struct vertex_normal_short4 exp_vertices22[] =
7766 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7767 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7768 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7770 {{ 2.0f, 3.0f, 0.f}, {-1, -1, -1, -1}},
7771 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7773 const DWORD exp_indices22[] = {0, 1, 2, 3, 4, 2};
7774 const DWORD exp_face_remap22[] = {0, 1};
7775 const DWORD exp_vertex_remap22[] = {0, 1, 2, 3, 4, -1};
7776 const DWORD exp_new_num_vertices22 = ARRAY_SIZE(exp_vertices22);
7777 /* Test 23. Weld texture coordinates as FLOAT16_2. Similar to test 11, but
7778 * with texture coordinates converted to float16 in hex. */
7779 const struct vertex_texcoord_float16_2 vertices23[] =
7781 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
7782 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */
7783 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */
7785 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd}}, /* {0.2f, 0.3f} */
7786 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
7787 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */
7789 const DWORD indices23[] = {0, 1, 2, 3, 4, 5};
7790 const DWORD attributes23[] = {0, 0};
7791 const UINT num_vertices23 = ARRAY_SIZE(vertices23);
7792 const UINT num_faces23 = ARRAY_SIZE(indices23) / VERTS_PER_FACE;
7793 DWORD flags23 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7794 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};
7795 const DWORD adjacency23[] = {-1, 1, -1, -1, -1, 0};
7796 const struct vertex_texcoord_float16_2 exp_vertices23[] =
7798 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
7799 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */
7800 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */
7802 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
7803 {{ 0.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */
7805 const DWORD exp_indices23[] = {0, 1, 2, 1, 3, 4};
7806 const DWORD exp_face_remap23[] = {0, 1};
7807 const DWORD exp_vertex_remap23[] = {0, 1, 2, 4, 5, -1};
7808 const DWORD exp_new_num_vertices23 = ARRAY_SIZE(exp_vertices23);
7809 /* Test 24. Weld texture coordinates as FLOAT16_4. Similar to test 24. */
7810 const struct vertex_texcoord_float16_4 vertices24[] =
7812 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}},
7813 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a, 0x3800, 0x399a}},
7814 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd, 0xb266, 0xb4cd}},
7816 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd, 0x3266, 0x34cd}},
7817 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}},
7818 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266, 0x2e66, 0x3266}},
7820 const DWORD indices24[] = {0, 1, 2, 3, 4, 5};
7821 const DWORD attributes24[] = {0, 0};
7822 const UINT num_vertices24 = ARRAY_SIZE(vertices24);
7823 const UINT num_faces24 = ARRAY_SIZE(indices24) / VERTS_PER_FACE;
7824 DWORD flags24 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7825 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};
7826 const DWORD adjacency24[] = {-1, 1, -1, -1, -1, 0};
7827 const struct vertex_texcoord_float16_4 exp_vertices24[] =
7829 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}},
7830 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a, 0x3800, 0x399a}},
7831 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd, 0xb266, 0xb4cd}},
7833 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}},
7834 {{ 0.0f, 0.0f, 0.f}, {0x2e66, 0x3266, 0x2e66, 0x3266}},
7836 const DWORD exp_indices24[] = {0, 1, 2, 1, 3, 4};
7837 const DWORD exp_face_remap24[] = {0, 1};
7838 const DWORD exp_vertex_remap24[] = {0, 1, 2, 4, 5, -1};
7839 const DWORD exp_new_num_vertices24 = ARRAY_SIZE(exp_vertices24);
7840 /* Test 25. Weld texture coordinates with usage index 10 (TEXCOORD10). The
7841 * usage index is capped at 7, so the epsilon for TEXCOORD7 is used instead.
7843 const struct vertex_texcoord vertices25[] =
7845 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f}},
7846 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.7f}},
7847 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
7849 {{ 3.0f, 3.0f, 0.f}, {0.2f, 0.3f}},
7850 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f}},
7851 {{ 1.0f, 0.0f, 0.f}, {0.1f, 0.2f}}
7853 const DWORD indices25[] = {0, 1, 2, 3, 4, 5};
7854 const DWORD attributes25[] = {0, 0};
7855 const UINT num_vertices25 = ARRAY_SIZE(vertices25);
7856 const UINT num_faces25 = ARRAY_SIZE(indices25) / VERTS_PER_FACE;
7857 DWORD flags25 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7858 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};
7859 const DWORD adjacency25[] = {-1, 1, -1, -1, -1, 0};
7860 const struct vertex_texcoord exp_vertices25[] =
7862 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f}},
7863 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.7f}},
7864 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
7866 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f}},
7867 {{ 0.0f, 0.0f, 0.f}, {0.1f, 0.2f}},
7869 const DWORD exp_indices25[] = {0, 1, 2, 1, 3, 4};
7870 const DWORD exp_face_remap25[] = {0, 1};
7871 const DWORD exp_vertex_remap25[] = {0, 1, 2, 4, 5, -1};
7872 const DWORD exp_new_num_vertices25 = ARRAY_SIZE(exp_vertices25);
7873 /* Test 26. Weld color with usage index larger than 1. Shows that none of
7874 * the epsilon values are used. */
7875 const struct vertex_color vertices26[] =
7877 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7878 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7879 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7881 {{ 3.0f, 3.0f, 0.f}, 0x00000000},
7882 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7883 {{ 1.0f, 0.0f, 0.f}, 0x01010101},
7885 const DWORD indices26[] = {0, 1, 2, 3, 4, 5};
7886 const DWORD attributes26[] = {0, 0};
7887 const UINT num_vertices26 = ARRAY_SIZE(vertices26);
7888 const UINT num_faces26 = ARRAY_SIZE(indices26) / VERTS_PER_FACE;
7889 DWORD flags26 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7890 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};
7891 const DWORD adjacency26[] = {-1, 1, -1, -1, -1, 0};
7892 const struct vertex_color exp_vertices26[] =
7894 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7895 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7896 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7898 {{ 2.0f, 3.0f, 0.f}, 0x00000000},
7899 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7900 {{ 0.0f, 0.0f, 0.f}, 0x01010101},
7902 const DWORD exp_indices26[] = {0, 1, 2, 3, 4, 5};
7903 const DWORD exp_face_remap26[] = {0, 1};
7904 const DWORD exp_vertex_remap26[] = {0, 1, 2, 3, 4, 5};
7905 const DWORD exp_new_num_vertices26 = ARRAY_SIZE(exp_vertices26);
7906 /* Test 27. Weld color with usage index 1 (specular). */
7907 /* Previously this test used float color values and index > 1 but that case
7908 * appears to be effectively unhandled in native so the test gave
7909 * inconsistent results. */
7910 const struct vertex_color vertices27[] =
7912 {{ 0.0f, 3.0f, 0.0f}, 0x00000000},
7913 {{ 2.0f, 3.0f, 0.0f}, 0x10203040},
7914 {{ 0.0f, 0.0f, 0.0f}, 0x50607080},
7916 {{ 3.0f, 3.0f, 0.0f}, 0x11213141},
7917 {{ 3.0f, 0.0f, 0.0f}, 0xffffffff},
7918 {{ 1.0f, 0.0f, 0.0f}, 0x51617181},
7920 const DWORD indices27[] = {0, 1, 2, 3, 4, 5};
7921 const DWORD attributes27[] = {0, 0};
7922 const UINT num_vertices27 = ARRAY_SIZE(vertices27);
7923 const UINT num_faces27 = ARRAY_SIZE(indices27) / VERTS_PER_FACE;
7924 DWORD flags27 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7925 const D3DXWELDEPSILONS epsilons27 =
7927 1.1f, 0.0f, 0.0f, 0.0f, 2.0f / 255.0f, 0.0f,
7928 {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, 0.0f, 0.0f, 0.0f
7930 const DWORD adjacency27[] = {-1, 1, -1, -1, -1, 0};
7931 const struct vertex_color exp_vertices27[] =
7933 {{ 0.0f, 3.0f, 0.0f}, 0x00000000},
7934 {{ 2.0f, 3.0f, 0.0f}, 0x10203040},
7935 {{ 0.0f, 0.0f, 0.0f}, 0x50607080},
7937 {{ 3.0f, 0.0f, 0.0f}, 0xffffffff},
7939 const DWORD exp_indices27[] = {0, 1, 2, 1, 3, 2};
7940 const DWORD exp_face_remap27[] = {0, 1};
7941 const DWORD exp_vertex_remap27[] = {0, 1, 2, 4, -1, -1};
7942 const DWORD exp_new_num_vertices27 = ARRAY_SIZE(exp_vertices27);
7943 /* Test 28. Weld one normal with UDEC3. */
7944 const DWORD dword_udec3_zero = init_udec3_dword(0, 0, 0, 1);
7945 const DWORD dword_udec3_1023 = init_udec3_dword(1023, 1023, 1023, 1);
7946 const DWORD dword_udec3_1022 = init_udec3_dword(1022, 1022, 1022, 1);
7947 const struct vertex_normal_udec3 vertices28[] =
7949 {{ 0.0f, 3.0f, 0.f}, dword_udec3_zero},
7950 {{ 2.0f, 3.0f, 0.f}, dword_udec3_zero},
7951 {{ 0.0f, 0.0f, 0.f}, dword_udec3_zero},
7953 {{ 3.0f, 3.0f, 0.f}, dword_udec3_1023},
7954 {{ 3.0f, 0.0f, 0.f}, dword_udec3_zero},
7955 {{ 1.0f, 0.0f, 0.f}, dword_udec3_1022},
7957 const DWORD indices28[] = {0, 1, 2, 3, 4, 5};
7958 const DWORD attributes28[] = {0, 0};
7959 const UINT num_vertices28 = ARRAY_SIZE(vertices28);
7960 const UINT num_faces28 = ARRAY_SIZE(indices28) / VERTS_PER_FACE;
7961 DWORD flags28 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7962 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};
7963 const DWORD adjacency28[] = {-1, 1, -1, -1, -1, 0};
7964 const struct vertex_normal_udec3 exp_vertices28[] =
7966 {{ 0.0f, 3.0f, 0.f}, dword_udec3_zero},
7967 {{ 2.0f, 3.0f, 0.f}, dword_udec3_zero},
7968 {{ 0.0f, 0.0f, 0.f}, dword_udec3_zero},
7970 {{ 2.0f, 3.0f, 0.f}, dword_udec3_1023},
7971 {{ 3.0f, 0.0f, 0.f}, dword_udec3_zero},
7973 const DWORD exp_indices28[] = {0, 1, 2, 3, 4, 2};
7974 const DWORD exp_face_remap28[] = {0, 1};
7975 const DWORD exp_vertex_remap28[] = {0, 1, 2, 3, 4, -1};
7976 const DWORD exp_new_num_vertices28 = ARRAY_SIZE(exp_vertices28);
7977 /* Test 29. Weld one normal with DEC3N. */
7978 const DWORD dword_dec3n_zero = init_dec3n_dword(0, 0, 0, 1);
7979 const DWORD dword_dec3n_511 = init_dec3n_dword(511, 511, 511, 1);
7980 const DWORD dword_dec3n_510 = init_dec3n_dword(510, 510, 510, 1);
7981 const struct vertex_normal_dec3n vertices29[] =
7983 {{ 0.0f, 3.0f, 0.f}, dword_dec3n_zero},
7984 {{ 2.0f, 3.0f, 0.f}, dword_dec3n_zero},
7985 {{ 0.0f, 0.0f, 0.f}, dword_dec3n_zero},
7987 {{ 3.0f, 3.0f, 0.f}, dword_dec3n_511},
7988 {{ 3.0f, 0.0f, 0.f}, dword_dec3n_zero},
7989 {{ 1.0f, 0.0f, 0.f}, dword_dec3n_510},
7991 const DWORD indices29[] = {0, 1, 2, 3, 4, 5};
7992 const DWORD attributes29[] = {0, 0};
7993 const UINT num_vertices29 = ARRAY_SIZE(vertices29);
7994 const UINT num_faces29 = ARRAY_SIZE(indices29) / VERTS_PER_FACE;
7995 DWORD flags29 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7996 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};
7997 const DWORD adjacency29[] = {-1, 1, -1, -1, -1, 0};
7998 const struct vertex_normal_dec3n exp_vertices29[] =
8000 {{ 0.0f, 3.0f, 0.f}, dword_dec3n_zero},
8001 {{ 2.0f, 3.0f, 0.f}, dword_dec3n_zero},
8002 {{ 0.0f, 0.0f, 0.f}, dword_dec3n_zero},
8004 {{ 2.0f, 3.0f, 0.f}, dword_dec3n_511},
8005 {{ 3.0f, 0.0f, 0.f}, dword_dec3n_zero},
8007 const DWORD exp_indices29[] = {0, 1, 2, 3, 4, 2};
8008 const DWORD exp_face_remap29[] = {0, 1};
8009 const DWORD exp_vertex_remap29[] = {0, 1, 2, 3, 4, -1};
8010 const DWORD exp_new_num_vertices29 = ARRAY_SIZE(exp_vertices29);
8011 /* All mesh data */
8012 DWORD *adjacency_out = NULL;
8013 DWORD *face_remap = NULL;
8014 ID3DXMesh *mesh = NULL;
8015 ID3DXBuffer *vertex_remap = NULL;
8016 struct
8018 const BYTE *vertices;
8019 const DWORD *indices;
8020 const DWORD *attributes;
8021 const DWORD num_vertices;
8022 const DWORD num_faces;
8023 const DWORD options;
8024 D3DVERTEXELEMENT9 *declaration;
8025 const UINT vertex_size;
8026 const DWORD flags;
8027 const D3DXWELDEPSILONS *epsilons;
8028 const DWORD *adjacency;
8029 const BYTE *exp_vertices;
8030 const DWORD *exp_indices;
8031 const DWORD *exp_face_remap;
8032 const DWORD *exp_vertex_remap;
8033 const DWORD exp_new_num_vertices;
8035 tc[] =
8038 (BYTE*)vertices0,
8039 indices0,
8040 attributes0,
8041 num_vertices0,
8042 num_faces0,
8043 options,
8044 declaration_normal,
8045 vertex_size_normal,
8046 flags0,
8047 NULL,
8048 adjacency0,
8049 (BYTE*)exp_vertices0,
8050 exp_indices0,
8051 exp_face_remap0,
8052 exp_vertex_remap0,
8053 exp_new_num_vertices0
8056 (BYTE*)vertices1,
8057 indices1,
8058 attributes1,
8059 num_vertices1,
8060 num_faces1,
8061 options,
8062 declaration_normal,
8063 vertex_size_normal,
8064 flags1,
8065 NULL,
8066 adjacency1,
8067 (BYTE*)exp_vertices1,
8068 exp_indices1,
8069 exp_face_remap1,
8070 exp_vertex_remap1,
8071 exp_new_num_vertices1
8074 (BYTE*)vertices2,
8075 indices2,
8076 attributes2,
8077 num_vertices2,
8078 num_faces2,
8079 options,
8080 declaration_normal,
8081 vertex_size_normal,
8082 flags2,
8083 &epsilons2,
8084 adjacency2,
8085 (BYTE*)exp_vertices2,
8086 exp_indices2,
8087 exp_face_remap2,
8088 exp_vertex_remap2,
8089 exp_new_num_vertices2
8092 (BYTE*)vertices3,
8093 indices3,
8094 attributes3,
8095 num_vertices3,
8096 num_faces3,
8097 options,
8098 declaration_normal,
8099 vertex_size_normal,
8100 flags3,
8101 &epsilons3,
8102 adjacency3,
8103 (BYTE*)exp_vertices3,
8104 exp_indices3,
8105 exp_face_remap3,
8106 exp_vertex_remap3,
8107 exp_new_num_vertices3
8110 (BYTE*)vertices4,
8111 indices4,
8112 attributes4,
8113 num_vertices4,
8114 num_faces4,
8115 options,
8116 declaration_normal,
8117 vertex_size_normal,
8118 flags4,
8119 &epsilons4,
8120 adjacency4,
8121 (BYTE*)exp_vertices4,
8122 exp_indices4,
8123 exp_face_remap4,
8124 exp_vertex_remap4,
8125 exp_new_num_vertices4
8127 /* Unusual ordering. */
8129 (BYTE*)vertices5,
8130 indices5,
8131 attributes5,
8132 num_vertices5,
8133 num_faces5,
8134 options,
8135 declaration_normal,
8136 vertex_size_normal,
8137 flags5,
8138 NULL,
8139 adjacency5,
8140 (BYTE*)exp_vertices5,
8141 exp_indices5,
8142 exp_face_remap5,
8143 exp_vertex_remap5,
8144 exp_new_num_vertices5
8147 (BYTE*)vertices6,
8148 indices6,
8149 attributes6,
8150 num_vertices6,
8151 num_faces6,
8152 options,
8153 declaration_normal,
8154 vertex_size_normal,
8155 flags6,
8156 &epsilons6,
8157 adjacency6,
8158 (BYTE*)exp_vertices6,
8159 exp_indices6,
8160 exp_face_remap6,
8161 exp_vertex_remap6,
8162 exp_new_num_vertices6
8165 (BYTE*)vertices6,
8166 (DWORD*)indices6_16bit,
8167 attributes6,
8168 num_vertices6,
8169 num_faces6,
8170 options_16bit,
8171 declaration_normal,
8172 vertex_size_normal,
8173 flags6,
8174 &epsilons6,
8175 adjacency6,
8176 (BYTE*)exp_vertices6,
8177 exp_indices6,
8178 exp_face_remap6,
8179 exp_vertex_remap6,
8180 exp_new_num_vertices6
8183 (BYTE*)vertices8,
8184 indices8,
8185 attributes8,
8186 num_vertices8,
8187 num_faces8,
8188 options,
8189 declaration_normal,
8190 vertex_size_normal,
8191 flags8,
8192 &epsilons8,
8193 adjacency8,
8194 (BYTE*)exp_vertices8,
8195 exp_indices8,
8196 exp_face_remap8,
8197 exp_vertex_remap8,
8198 exp_new_num_vertices8
8201 (BYTE*)vertices9,
8202 indices9,
8203 attributes9,
8204 num_vertices9,
8205 num_faces9,
8206 options,
8207 declaration_normal,
8208 vertex_size_normal,
8209 flags9,
8210 &epsilons9,
8211 adjacency9,
8212 (BYTE*)exp_vertices9,
8213 exp_indices9,
8214 exp_face_remap9,
8215 exp_vertex_remap9,
8216 exp_new_num_vertices9
8219 (BYTE*)vertices10,
8220 indices10,
8221 attributes10,
8222 num_vertices10,
8223 num_faces10,
8224 options,
8225 declaration_blendweight,
8226 vertex_size_blendweight,
8227 flags10,
8228 &epsilons10,
8229 adjacency10,
8230 (BYTE*)exp_vertices10,
8231 exp_indices10,
8232 exp_face_remap10,
8233 exp_vertex_remap10,
8234 exp_new_num_vertices10
8237 (BYTE*)vertices11,
8238 indices11,
8239 attributes11,
8240 num_vertices11,
8241 num_faces11,
8242 options,
8243 declaration_texcoord,
8244 vertex_size_texcoord,
8245 flags11,
8246 &epsilons11,
8247 adjacency11,
8248 (BYTE*)exp_vertices11,
8249 exp_indices11,
8250 exp_face_remap11,
8251 exp_vertex_remap11,
8252 exp_new_num_vertices11
8255 (BYTE*)vertices12,
8256 indices12,
8257 attributes12,
8258 num_vertices12,
8259 num_faces12,
8260 options,
8261 declaration_color,
8262 vertex_size_color,
8263 flags12,
8264 &epsilons12,
8265 adjacency12,
8266 (BYTE*)exp_vertices12,
8267 exp_indices12,
8268 exp_face_remap12,
8269 exp_vertex_remap12,
8270 exp_new_num_vertices12
8273 (BYTE*)vertices13,
8274 indices13,
8275 attributes13,
8276 num_vertices13,
8277 num_faces13,
8278 options,
8279 declaration_normal3,
8280 vertex_size_normal,
8281 flags13,
8282 &epsilons13,
8283 adjacency13,
8284 (BYTE*)exp_vertices13,
8285 exp_indices13,
8286 exp_face_remap13,
8287 exp_vertex_remap13,
8288 exp_new_num_vertices13
8291 (BYTE*)vertices14,
8292 indices14,
8293 attributes14,
8294 num_vertices14,
8295 num_faces14,
8296 options,
8297 declaration_color,
8298 vertex_size_color,
8299 flags14,
8300 &epsilons14,
8301 adjacency14,
8302 (BYTE*)exp_vertices14,
8303 exp_indices14,
8304 exp_face_remap14,
8305 exp_vertex_remap14,
8306 exp_new_num_vertices14
8309 (BYTE*)vertices15,
8310 indices15,
8311 attributes15,
8312 num_vertices15,
8313 num_faces15,
8314 options,
8315 declaration_color_ubyte4n,
8316 vertex_size_color_ubyte4, /* UBYTE4 same size as UBYTE4N */
8317 flags15,
8318 &epsilons15,
8319 adjacency15,
8320 (BYTE*)exp_vertices15,
8321 exp_indices15,
8322 exp_face_remap15,
8323 exp_vertex_remap15,
8324 exp_new_num_vertices15
8327 (BYTE*)vertices16,
8328 indices16,
8329 attributes16,
8330 num_vertices16,
8331 num_faces16,
8332 options,
8333 declaration_color_ubyte4,
8334 vertex_size_color_ubyte4,
8335 flags16,
8336 &epsilons16,
8337 adjacency16,
8338 (BYTE*)exp_vertices16,
8339 exp_indices16,
8340 exp_face_remap16,
8341 exp_vertex_remap16,
8342 exp_new_num_vertices16
8345 (BYTE*)vertices17,
8346 indices17,
8347 attributes17,
8348 num_vertices17,
8349 num_faces17,
8350 options,
8351 declaration_texcoord_short2,
8352 vertex_size_texcoord_short2,
8353 flags17,
8354 &epsilons17,
8355 adjacency17,
8356 (BYTE*)exp_vertices17,
8357 exp_indices17,
8358 exp_face_remap17,
8359 exp_vertex_remap17,
8360 exp_new_num_vertices17
8363 (BYTE*)vertices18,
8364 indices18,
8365 attributes18,
8366 num_vertices18,
8367 num_faces18,
8368 options,
8369 declaration_texcoord_short2n,
8370 vertex_size_texcoord_short2, /* SHORT2 same size as SHORT2N */
8371 flags18,
8372 &epsilons18,
8373 adjacency18,
8374 (BYTE*)exp_vertices18,
8375 exp_indices18,
8376 exp_face_remap18,
8377 exp_vertex_remap18,
8378 exp_new_num_vertices18
8381 (BYTE*)vertices19,
8382 indices19,
8383 attributes19,
8384 num_vertices19,
8385 num_faces19,
8386 options,
8387 declaration_texcoord_ushort2n,
8388 vertex_size_texcoord_short2, /* SHORT2 same size as USHORT2N */
8389 flags19,
8390 &epsilons19,
8391 adjacency19,
8392 (BYTE*)exp_vertices19,
8393 exp_indices19,
8394 exp_face_remap19,
8395 exp_vertex_remap19,
8396 exp_new_num_vertices19
8399 (BYTE*)vertices20,
8400 indices20,
8401 attributes20,
8402 num_vertices20,
8403 num_faces20,
8404 options,
8405 declaration_normal_short4,
8406 vertex_size_normal_short4,
8407 flags20,
8408 &epsilons20,
8409 adjacency20,
8410 (BYTE*)exp_vertices20,
8411 exp_indices20,
8412 exp_face_remap20,
8413 exp_vertex_remap20,
8414 exp_new_num_vertices20
8417 (BYTE*)vertices21,
8418 indices21,
8419 attributes21,
8420 num_vertices21,
8421 num_faces21,
8422 options,
8423 declaration_normal_short4n,
8424 vertex_size_normal_short4, /* SHORT4 same size as SHORT4N */
8425 flags21,
8426 &epsilons21,
8427 adjacency21,
8428 (BYTE*)exp_vertices21,
8429 exp_indices21,
8430 exp_face_remap21,
8431 exp_vertex_remap21,
8432 exp_new_num_vertices21
8435 (BYTE*)vertices22,
8436 indices22,
8437 attributes22,
8438 num_vertices22,
8439 num_faces22,
8440 options,
8441 declaration_normal_ushort4n,
8442 vertex_size_normal_short4, /* SHORT4 same size as USHORT4N */
8443 flags22,
8444 &epsilons22,
8445 adjacency22,
8446 (BYTE*)exp_vertices22,
8447 exp_indices22,
8448 exp_face_remap22,
8449 exp_vertex_remap22,
8450 exp_new_num_vertices22
8453 (BYTE*)vertices23,
8454 indices23,
8455 attributes23,
8456 num_vertices23,
8457 num_faces23,
8458 options,
8459 declaration_texcoord_float16_2,
8460 vertex_size_texcoord_float16_2,
8461 flags23,
8462 &epsilons23,
8463 adjacency23,
8464 (BYTE*)exp_vertices23,
8465 exp_indices23,
8466 exp_face_remap23,
8467 exp_vertex_remap23,
8468 exp_new_num_vertices23
8471 (BYTE*)vertices24,
8472 indices24,
8473 attributes24,
8474 num_vertices24,
8475 num_faces24,
8476 options,
8477 declaration_texcoord_float16_4,
8478 vertex_size_texcoord_float16_4,
8479 flags24,
8480 &epsilons24,
8481 adjacency24,
8482 (BYTE*)exp_vertices24,
8483 exp_indices24,
8484 exp_face_remap24,
8485 exp_vertex_remap24,
8486 exp_new_num_vertices24
8489 (BYTE*)vertices25,
8490 indices25,
8491 attributes25,
8492 num_vertices25,
8493 num_faces25,
8494 options,
8495 declaration_texcoord10,
8496 vertex_size_texcoord,
8497 flags25,
8498 &epsilons25,
8499 adjacency25,
8500 (BYTE*)exp_vertices25,
8501 exp_indices25,
8502 exp_face_remap25,
8503 exp_vertex_remap25,
8504 exp_new_num_vertices25
8507 (BYTE*)vertices26,
8508 indices26,
8509 attributes26,
8510 num_vertices26,
8511 num_faces26,
8512 options,
8513 declaration_color2,
8514 vertex_size_color,
8515 flags26,
8516 &epsilons26,
8517 adjacency26,
8518 (BYTE*)exp_vertices26,
8519 exp_indices26,
8520 exp_face_remap26,
8521 exp_vertex_remap26,
8522 exp_new_num_vertices26
8525 (BYTE*)vertices27,
8526 indices27,
8527 attributes27,
8528 num_vertices27,
8529 num_faces27,
8530 options,
8531 declaration_color1,
8532 vertex_size_color,
8533 flags27,
8534 &epsilons27,
8535 adjacency27,
8536 (BYTE*)exp_vertices27,
8537 exp_indices27,
8538 exp_face_remap27,
8539 exp_vertex_remap27,
8540 exp_new_num_vertices27
8543 (BYTE*)vertices28,
8544 indices28,
8545 attributes28,
8546 num_vertices28,
8547 num_faces28,
8548 options,
8549 declaration_normal_udec3,
8550 vertex_size_normal_udec3,
8551 flags28,
8552 &epsilons28,
8553 adjacency28,
8554 (BYTE*)exp_vertices28,
8555 exp_indices28,
8556 exp_face_remap28,
8557 exp_vertex_remap28,
8558 exp_new_num_vertices28
8561 (BYTE*)vertices29,
8562 indices29,
8563 attributes29,
8564 num_vertices29,
8565 num_faces29,
8566 options,
8567 declaration_normal_dec3n,
8568 vertex_size_normal_dec3n,
8569 flags29,
8570 &epsilons29,
8571 adjacency29,
8572 (BYTE*)exp_vertices29,
8573 exp_indices29,
8574 exp_face_remap29,
8575 exp_vertex_remap29,
8576 exp_new_num_vertices29
8580 test_context = new_test_context();
8581 if (!test_context)
8583 skip("Couldn't create test context\n");
8584 goto cleanup;
8587 for (i = 0; i < ARRAY_SIZE(tc); i++)
8589 DWORD j;
8590 DWORD *vertex_remap_ptr;
8591 DWORD new_num_vertices;
8593 hr = init_test_mesh(tc[i].num_faces, tc[i].num_vertices, tc[i].options,
8594 tc[i].declaration, test_context->device, &mesh,
8595 tc[i].vertices, tc[i].vertex_size,
8596 tc[i].indices, tc[i].attributes);
8597 if (FAILED(hr))
8599 skip("Couldn't initialize test mesh %ld.\n", i);
8600 goto cleanup;
8603 /* Allocate out parameters */
8604 adjacency_out = malloc(VERTS_PER_FACE * tc[i].num_faces * sizeof(*adjacency_out));
8605 if (!adjacency_out)
8607 skip("Couldn't allocate adjacency_out array.\n");
8608 goto cleanup;
8610 face_remap = malloc(tc[i].num_faces * sizeof(*face_remap));
8611 if (!face_remap)
8613 skip("Couldn't allocate face_remap array.\n");
8614 goto cleanup;
8617 hr = D3DXWeldVertices(mesh, tc[i].flags, tc[i].epsilons, tc[i].adjacency,
8618 adjacency_out, face_remap, &vertex_remap);
8619 ok(hr == D3D_OK, "Expected D3D_OK, got %#lx\n", hr);
8620 /* Check number of vertices*/
8621 new_num_vertices = mesh->lpVtbl->GetNumVertices(mesh);
8622 ok(new_num_vertices == tc[i].exp_new_num_vertices,
8623 "Mesh %ld: new_num_vertices == %ld, expected %ld.\n",
8624 i, new_num_vertices, tc[i].exp_new_num_vertices);
8625 /* Check index buffer */
8626 if (tc[i].options & D3DXMESH_32BIT)
8628 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, (void**)&indices);
8629 if (FAILED(hr))
8631 skip("Couldn't lock index buffer.\n");
8632 goto cleanup;
8634 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
8636 ok(indices[j] == tc[i].exp_indices[j],
8637 "Mesh %ld: indices[%ld] == %ld, expected %ld\n",
8638 i, j, indices[j], tc[i].exp_indices[j]);
8641 else
8643 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, (void**)&indices_16bit);
8644 if (FAILED(hr))
8646 skip("Couldn't lock index buffer.\n");
8647 goto cleanup;
8649 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
8651 ok(indices_16bit[j] == tc[i].exp_indices[j],
8652 "Mesh %ld: indices_16bit[%ld] == %d, expected %ld\n",
8653 i, j, indices_16bit[j], tc[i].exp_indices[j]);
8656 mesh->lpVtbl->UnlockIndexBuffer(mesh);
8657 indices = NULL;
8658 indices_16bit = NULL;
8659 /* Check adjacency_out */
8660 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
8662 ok(adjacency_out[j] == tc[i].adjacency[j],
8663 "Mesh %ld: adjacency_out[%ld] == %ld, expected %ld\n",
8664 i, j, adjacency_out[j], tc[i].adjacency[j]);
8666 /* Check face_remap */
8667 for (j = 0; j < tc[i].num_faces; j++)
8669 ok(face_remap[j] == tc[i].exp_face_remap[j],
8670 "Mesh %ld: face_remap[%ld] == %ld, expected %ld\n",
8671 i, j, face_remap[j], tc[i].exp_face_remap[j]);
8673 /* Check vertex_remap */
8674 vertex_remap_ptr = vertex_remap->lpVtbl->GetBufferPointer(vertex_remap);
8675 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
8677 ok(vertex_remap_ptr[j] == tc[i].exp_vertex_remap[j],
8678 "Mesh %ld: vertex_remap_ptr[%ld] == %ld, expected %ld\n",
8679 i, j, vertex_remap_ptr[j], tc[i].exp_vertex_remap[j]);
8681 /* Check vertex buffer */
8682 hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, (void*)&vertices);
8683 if (FAILED(hr))
8685 skip("Couldn't lock vertex buffer.\n");
8686 goto cleanup;
8688 /* Check contents of re-ordered vertex buffer */
8689 for (j = 0; j < tc[i].exp_new_num_vertices; j++)
8691 int index = tc[i].vertex_size*j;
8692 check_vertex_components(__LINE__, i, j, &vertices[index], &tc[i].exp_vertices[index], tc[i].declaration);
8694 mesh->lpVtbl->UnlockVertexBuffer(mesh);
8695 vertices = NULL;
8697 /* Free mesh and output data */
8698 free(adjacency_out);
8699 adjacency_out = NULL;
8700 free(face_remap);
8701 face_remap = NULL;
8702 vertex_remap->lpVtbl->Release(vertex_remap);
8703 vertex_remap = NULL;
8704 mesh->lpVtbl->Release(mesh);
8705 mesh = NULL;
8708 cleanup:
8709 free(adjacency_out);
8710 free(face_remap);
8711 if (indices) mesh->lpVtbl->UnlockIndexBuffer(mesh);
8712 if (indices_16bit) mesh->lpVtbl->UnlockIndexBuffer(mesh);
8713 if (mesh) mesh->lpVtbl->Release(mesh);
8714 if (vertex_remap) vertex_remap->lpVtbl->Release(vertex_remap);
8715 if (vertices) mesh->lpVtbl->UnlockVertexBuffer(mesh);
8716 free_test_context(test_context);
8719 static void test_clone_mesh(void)
8721 HRESULT hr;
8722 struct test_context *test_context = NULL;
8723 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
8724 D3DVERTEXELEMENT9 declaration_pn[] =
8726 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8727 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
8728 D3DDECL_END()
8730 D3DVERTEXELEMENT9 declaration_pntc[] =
8732 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8733 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
8734 {0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8735 D3DDECL_END()
8737 D3DVERTEXELEMENT9 declaration_ptcn[] =
8739 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8740 {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8741 {0, 20, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
8742 D3DDECL_END()
8744 D3DVERTEXELEMENT9 declaration_ptc[] =
8746 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8747 {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8748 D3DDECL_END()
8750 D3DVERTEXELEMENT9 declaration_ptc_float16_2[] =
8752 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8753 {0, 12, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8754 D3DDECL_END()
8756 D3DVERTEXELEMENT9 declaration_ptc_float16_4[] =
8758 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8759 {0, 12, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8760 D3DDECL_END()
8762 D3DVERTEXELEMENT9 declaration_ptc_float1[] =
8764 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8765 {0, 12, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8766 D3DDECL_END()
8768 D3DVERTEXELEMENT9 declaration_ptc_float3[] =
8770 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8771 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8772 D3DDECL_END()
8774 D3DVERTEXELEMENT9 declaration_ptc_float4[] =
8776 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8777 {0, 12, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8778 D3DDECL_END()
8780 D3DVERTEXELEMENT9 declaration_ptc_d3dcolor[] =
8782 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8783 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8784 D3DDECL_END()
8786 D3DVERTEXELEMENT9 declaration_ptc_ubyte4[] =
8788 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8789 {0, 12, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8790 D3DDECL_END()
8792 D3DVERTEXELEMENT9 declaration_ptc_ubyte4n[] =
8794 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8795 {0, 12, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8796 D3DDECL_END()
8798 D3DVERTEXELEMENT9 declaration_ptc_short2[] =
8800 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8801 {0, 12, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8802 D3DDECL_END()
8804 D3DVERTEXELEMENT9 declaration_ptc_short4[] =
8806 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8807 {0, 12, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8808 D3DDECL_END()
8810 D3DVERTEXELEMENT9 declaration_ptc_short2n[] =
8812 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8813 {0, 12, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8814 D3DDECL_END()
8816 D3DVERTEXELEMENT9 declaration_ptc_short4n[] =
8818 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8819 {0, 12, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8820 D3DDECL_END()
8822 D3DVERTEXELEMENT9 declaration_ptc_ushort2n[] =
8824 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8825 {0, 12, D3DDECLTYPE_USHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8826 D3DDECL_END()
8828 D3DVERTEXELEMENT9 declaration_ptc_ushort4n[] =
8830 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8831 {0, 12, D3DDECLTYPE_USHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8832 D3DDECL_END()
8834 D3DVERTEXELEMENT9 declaration_ptc_float16_2_partialu[] =
8836 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8837 {0, 12, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_PARTIALU, D3DDECLUSAGE_TEXCOORD, 0},
8838 D3DDECL_END()
8840 D3DVERTEXELEMENT9 declaration_pntc1[] =
8842 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8843 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
8844 {0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
8845 D3DDECL_END()
8847 const unsigned int VERTS_PER_FACE = 3;
8848 BYTE *vertices = NULL;
8849 INT i;
8850 struct vertex_pn
8852 D3DXVECTOR3 position;
8853 D3DXVECTOR3 normal;
8855 struct vertex_pntc
8857 D3DXVECTOR3 position;
8858 D3DXVECTOR3 normal;
8859 D3DXVECTOR2 texcoords;
8861 struct vertex_ptcn
8863 D3DXVECTOR3 position;
8864 D3DXVECTOR2 texcoords;
8865 D3DXVECTOR3 normal;
8867 struct vertex_ptc
8869 D3DXVECTOR3 position;
8870 D3DXVECTOR2 texcoords;
8872 struct vertex_ptc_float16_2
8874 D3DXVECTOR3 position;
8875 WORD texcoords[2]; /* float16_2 */
8877 struct vertex_ptc_float16_4
8879 D3DXVECTOR3 position;
8880 WORD texcoords[4]; /* float16_4 */
8882 struct vertex_ptc_float1
8884 D3DXVECTOR3 position;
8885 FLOAT texcoords;
8887 struct vertex_ptc_float3
8889 D3DXVECTOR3 position;
8890 FLOAT texcoords[3];
8892 struct vertex_ptc_float4
8894 D3DXVECTOR3 position;
8895 FLOAT texcoords[4];
8897 struct vertex_ptc_d3dcolor
8899 D3DXVECTOR3 position;
8900 BYTE texcoords[4];
8902 struct vertex_ptc_ubyte4
8904 D3DXVECTOR3 position;
8905 BYTE texcoords[4];
8907 struct vertex_ptc_ubyte4n
8909 D3DXVECTOR3 position;
8910 BYTE texcoords[4];
8912 struct vertex_ptc_short2
8914 D3DXVECTOR3 position;
8915 SHORT texcoords[2];
8917 struct vertex_ptc_short4
8919 D3DXVECTOR3 position;
8920 SHORT texcoords[4];
8922 struct vertex_ptc_ushort2n
8924 D3DXVECTOR3 position;
8925 USHORT texcoords[2];
8927 struct vertex_ptc_ushort4n
8929 D3DXVECTOR3 position;
8930 USHORT texcoords[4];
8932 struct vertex_ptc_udec3
8934 D3DXVECTOR3 position;
8935 DWORD texcoords;
8937 struct vertex_ptc_dec3n
8939 D3DXVECTOR3 position;
8940 DWORD texcoords;
8942 D3DXVECTOR3 up = {0.0f, 0.0f, 1.0f};
8943 D3DXVECTOR2 zero_vec2 = {0.0f, 0.0f};
8944 /* Test 0. Check that a mesh can be cloned if the new declaration is the
8945 * same as the one used to create the mesh.
8947 * 0--1 3
8948 * | / /|
8949 * |/ / |
8950 * 2 5--4
8952 const struct vertex_pn vertices0[] =
8954 {{ 0.0f, 3.0f, 0.f}, up},
8955 {{ 2.0f, 3.0f, 0.f}, up},
8956 {{ 0.0f, 0.0f, 0.f}, up},
8958 {{ 3.0f, 3.0f, 0.f}, up},
8959 {{ 3.0f, 0.0f, 0.f}, up},
8960 {{ 1.0f, 0.0f, 0.f}, up},
8962 const UINT num_vertices0 = ARRAY_SIZE(vertices0);
8963 const UINT num_faces0 = ARRAY_SIZE(vertices0) / VERTS_PER_FACE;
8964 const UINT vertex_size0 = sizeof(*vertices0);
8965 /* Test 1. Check that 16-bit indices are handled. */
8966 const DWORD options_16bit = D3DXMESH_SYSTEMMEM;
8967 /* Test 2. Check that the size of each vertex is increased and the data
8968 * moved if the new declaration adds an element after the original elements.
8970 const struct vertex_pntc exp_vertices2[] =
8972 {{ 0.0f, 3.0f, 0.f}, up, zero_vec2},
8973 {{ 2.0f, 3.0f, 0.f}, up, zero_vec2},
8974 {{ 0.0f, 0.0f, 0.f}, up, zero_vec2},
8976 {{ 3.0f, 3.0f, 0.f}, up, zero_vec2},
8977 {{ 3.0f, 0.0f, 0.f}, up, zero_vec2},
8978 {{ 1.0f, 0.0f, 0.f}, up, zero_vec2},
8980 const UINT exp_vertex_size2 = sizeof(*exp_vertices2);
8981 /* Test 3. Check that the size of each vertex is increased and the data
8982 * moved if the new declaration adds an element between the original
8983 * elements.
8985 const struct vertex_ptcn exp_vertices3[] =
8987 {{ 0.0f, 3.0f, 0.f}, zero_vec2, up},
8988 {{ 2.0f, 3.0f, 0.f}, zero_vec2, up},
8989 {{ 0.0f, 0.0f, 0.f}, zero_vec2, up},
8991 {{ 3.0f, 3.0f, 0.f}, zero_vec2, up},
8992 {{ 3.0f, 0.0f, 0.f}, zero_vec2, up},
8993 {{ 1.0f, 0.0f, 0.f}, zero_vec2, up},
8995 const UINT exp_vertex_size3 = sizeof(*exp_vertices3);
8996 /* Test 4. Test that data types can be converted, e.g. FLOAT2 to FLOAT16_2. */
8997 const struct vertex_ptc vertices4[] =
8999 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
9000 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
9001 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
9003 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
9004 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
9005 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
9007 const UINT num_vertices4 = ARRAY_SIZE(vertices4);
9008 const UINT num_faces4 = ARRAY_SIZE(vertices4) / VERTS_PER_FACE;
9009 const UINT vertex_size4 = sizeof(*vertices4);
9010 const struct vertex_ptc_float16_2 exp_vertices4[] =
9012 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
9013 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */
9014 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */
9016 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd}}, /* {0.2f, 0.3f} */
9017 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
9018 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */
9020 const UINT exp_vertex_size4 = sizeof(*exp_vertices4);
9021 /* Test 5. Convert FLOAT2 to FLOAT16_4. */
9022 const struct vertex_ptc vertices5[] =
9024 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
9025 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
9026 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
9028 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
9029 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
9030 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
9032 const UINT num_vertices5 = ARRAY_SIZE(vertices5);
9033 const UINT num_faces5 = ARRAY_SIZE(vertices5) / VERTS_PER_FACE;
9034 const UINT vertex_size5 = sizeof(*vertices5);
9035 const struct vertex_ptc_float16_4 exp_vertices5[] =
9037 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00, 0, 0x3c00}}, /* {1.0f, 1.0f, 0.0f, 1.0f} */
9038 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a, 0, 0x3c00}}, /* {0.5f, 0.7f, 0.0f, 1.0f} */
9039 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd, 0, 0x3c00}}, /* {-0.2f, -0.3f, 0.0f, 1.0f} */
9041 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd, 0, 0x3c00}}, /* {0.2f, 0.3f, 0.0f, 1.0f} */
9042 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00, 0, 0x3c00}}, /* {1.0f, 1.0f, 0.0f, 1.0f} */
9043 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266, 0, 0x3c00}}, /* {0.1f, 0.2f, 0.0f, 1.0f} */
9045 const UINT exp_vertex_size5 = sizeof(*exp_vertices5);
9046 /* Test 6. Convert FLOAT2 to FLOAT1. */
9047 const struct vertex_ptc vertices6[] =
9049 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
9050 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
9051 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
9053 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
9054 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
9055 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
9057 const UINT num_vertices6 = ARRAY_SIZE(vertices6);
9058 const UINT num_faces6 = ARRAY_SIZE(vertices6) / VERTS_PER_FACE;
9059 const UINT vertex_size6 = sizeof(*vertices6);
9060 const struct vertex_ptc_float1 exp_vertices6[] =
9062 {{ 0.0f, 3.0f, 0.f}, 1.0f},
9063 {{ 2.0f, 3.0f, 0.f}, 0.5f},
9064 {{ 0.0f, 0.0f, 0.f}, -0.2f},
9066 {{ 3.0f, 3.0f, 0.f}, 0.2f},
9067 {{ 3.0f, 0.0f, 0.f}, 1.0f},
9068 {{ 1.0f, 0.0f, 0.f}, 0.1f},
9070 const UINT exp_vertex_size6 = sizeof(*exp_vertices6);
9071 /* Test 7. Convert FLOAT2 to FLOAT3. */
9072 const struct vertex_ptc vertices7[] =
9074 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
9075 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
9076 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
9078 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
9079 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
9080 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
9082 const UINT num_vertices7 = ARRAY_SIZE(vertices7);
9083 const UINT num_faces7 = ARRAY_SIZE(vertices7) / VERTS_PER_FACE;
9084 const UINT vertex_size7 = sizeof(*vertices7);
9085 const struct vertex_ptc_float3 exp_vertices7[] =
9087 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f, 0.0f}},
9088 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f, 0.0f}},
9089 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f, 0.0f}},
9091 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f, 0.0f}},
9092 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f, 0.0f}},
9093 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f, 0.0f}},
9095 const UINT exp_vertex_size7 = sizeof(*exp_vertices7);
9096 /* Test 8. Convert FLOAT2 to FLOAT4. */
9097 const struct vertex_ptc vertices8[] =
9099 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
9100 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
9101 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
9103 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
9104 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
9105 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
9107 const UINT num_vertices8 = ARRAY_SIZE(vertices8);
9108 const UINT num_faces8 = ARRAY_SIZE(vertices8) / VERTS_PER_FACE;
9109 const UINT vertex_size8 = sizeof(*vertices8);
9110 const struct vertex_ptc_float4 exp_vertices8[] =
9112 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f, 0.0f, 1.0f}},
9113 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f, 0.0f, 1.0f}},
9114 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f, 0.0f, 1.0f}},
9116 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f, 0.0f, 1.0f}},
9117 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f, 0.0f, 1.0f}},
9118 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f, 0.0f, 1.0f}},
9120 const UINT exp_vertex_size8 = sizeof(*exp_vertices8);
9121 /* Test 9. Convert FLOAT2 to D3DCOLOR. */
9122 const struct vertex_ptc vertices9[] =
9124 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
9125 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
9126 {{ 0.0f, 0.0f, 0.f}, {-0.4f, -0.6f}},
9128 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
9129 {{ 3.0f, 0.0f, 0.f}, { 2.0f, 256.0f}},
9130 {{ 1.0f, 0.0f, 0.f}, { 0.11f, 0.2f}},
9132 const UINT num_vertices9 = ARRAY_SIZE(vertices9);
9133 const UINT num_faces9 = ARRAY_SIZE(vertices9) / VERTS_PER_FACE;
9134 const UINT vertex_size9 = sizeof(*vertices9);
9135 const struct vertex_ptc_d3dcolor exp_vertices9[] =
9137 {{ 0.0f, 3.0f, 0.f}, {0, 255, 255, 255}},
9138 {{ 2.0f, 3.0f, 0.f}, {0, 179, 128, 255}},
9139 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 255}},
9141 {{ 3.0f, 3.0f, 0.f}, {0, 77, 51, 255}},
9142 {{ 3.0f, 0.0f, 0.f}, {0, 255, 255, 255}},
9143 {{ 1.0f, 0.0f, 0.f}, {0, 51, 28, 255}},
9145 const UINT exp_vertex_size9 = sizeof(*exp_vertices9);
9146 /* Test 10. Convert FLOAT2 to UBYTE4. */
9147 const struct vertex_ptc vertices10[] =
9149 {{ 0.0f, 3.0f, 0.f}, { 0.0f, 1.0f}},
9150 {{ 2.0f, 3.0f, 0.f}, { 2.0f, 3.0f}},
9151 {{ 0.0f, 0.0f, 0.f}, { 254.0f, 255.0f}},
9153 {{ 3.0f, 3.0f, 0.f}, { 256.0f, 257.0f}},
9154 {{ 3.0f, 0.0f, 0.f}, { 1.4f, 1.5f}},
9155 {{ 1.0f, 0.0f, 0.f}, {-4.0f, -5.0f}},
9157 const UINT num_vertices10 = ARRAY_SIZE(vertices10);
9158 const UINT num_faces10 = ARRAY_SIZE(vertices10) / VERTS_PER_FACE;
9159 const UINT vertex_size10 = sizeof(*vertices10);
9160 const struct vertex_ptc_ubyte4 exp_vertices10[] =
9162 {{ 0.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
9163 {{ 2.0f, 3.0f, 0.f}, {2, 3, 0, 1}},
9164 {{ 0.0f, 0.0f, 0.f}, {254, 255, 0, 1}},
9166 {{ 3.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
9167 {{ 3.0f, 0.0f, 0.f}, {1, 2, 0, 1}},
9168 {{ 1.0f, 0.0f, 0.f}, {0, 0, 0, 1}},
9170 const UINT exp_vertex_size10 = sizeof(*exp_vertices10);
9171 /* Test 11. Convert FLOAT2 to SHORT2. */
9172 const struct vertex_ptc vertices11[] =
9174 {{ 0.0f, 3.0f, 0.f}, { 1.0f, -1.0f}},
9175 {{ 2.0f, 3.0f, 0.f}, { 0.4f, 0.5f}},
9176 {{ 0.0f, 0.0f, 0.f}, {-0.5f, -5.0f}},
9178 {{ 3.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MIN}},
9179 {{ 3.0f, 0.0f, 0.f}, {SHRT_MAX + 1.0f, SHRT_MIN - 1.0f}},
9180 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX + 2.0f, SHRT_MIN - 2.0f}},
9182 {{ 4.0f, 3.0f, 0.f}, {2 * SHRT_MAX, 2 * SHRT_MIN}},
9183 {{ 6.0f, 0.0f, 0.f}, {3 * SHRT_MAX, 3 * SHRT_MIN}},
9184 {{ 4.0f, 0.0f, 0.f}, {4 * SHRT_MAX, 4 * SHRT_MIN}},
9186 const UINT num_vertices11 = ARRAY_SIZE(vertices11);
9187 const UINT num_faces11 = ARRAY_SIZE(vertices11) / VERTS_PER_FACE;
9188 const UINT vertex_size11 = sizeof(*vertices11);
9189 const struct vertex_ptc_short2 exp_vertices11[] =
9191 {{ 0.0f, 3.0f, 0.f}, {1, 0}},
9192 {{ 2.0f, 3.0f, 0.f}, {0, 1}},
9193 {{ 0.0f, 0.0f, 0.f}, {0, -4}},
9195 {{ 3.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MIN + 1}},
9196 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MIN}},
9197 {{ 1.0f, 0.0f, 0.f}, {SHRT_MIN + 1, SHRT_MAX}},
9199 {{ 4.0f, 3.0f, 0.f}, {-2, 1}},
9200 {{ 6.0f, 0.0f, 0.f}, {32765, -32767}},
9201 {{ 4.0f, 0.0f, 0.f}, {-4, 1}},
9203 const UINT exp_vertex_size11 = sizeof(*exp_vertices11);
9204 /* Test 12. Convert FLOAT2 to SHORT4. */
9205 const struct vertex_ptc vertices12[] =
9207 {{ 0.0f, 3.0f, 0.f}, { 1.0f, -1.0f}},
9208 {{ 2.0f, 3.0f, 0.f}, { 0.4f, 0.5f}},
9209 {{ 0.0f, 0.0f, 0.f}, {-0.5f, -5.0f}},
9211 {{ 3.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MIN}},
9212 {{ 3.0f, 0.0f, 0.f}, {SHRT_MAX + 1.0f, SHRT_MIN - 1.0f}},
9213 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX + 2.0f, SHRT_MIN - 2.0f}},
9215 {{ 4.0f, 3.0f, 0.f}, {2 * SHRT_MAX, 2 * SHRT_MIN}},
9216 {{ 6.0f, 0.0f, 0.f}, {3 * SHRT_MAX, 3 * SHRT_MIN}},
9217 {{ 4.0f, 0.0f, 0.f}, {4 * SHRT_MAX, 4 * SHRT_MIN}},
9219 const UINT num_vertices12 = ARRAY_SIZE(vertices12);
9220 const UINT num_faces12 = ARRAY_SIZE(vertices12) / VERTS_PER_FACE;
9221 const UINT vertex_size12 = sizeof(*vertices12);
9222 const struct vertex_ptc_short4 exp_vertices12[] =
9224 {{ 0.0f, 3.0f, 0.f}, {1, 0, 0, 1}},
9225 {{ 2.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
9226 {{ 0.0f, 0.0f, 0.f}, {0, -4, 0, 1}},
9228 {{ 3.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MIN + 1, 0, 1}},
9229 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MIN, 0, 1}},
9230 {{ 1.0f, 0.0f, 0.f}, {SHRT_MIN + 1, SHRT_MAX, 0, 1}},
9232 {{ 4.0f, 3.0f, 0.f}, {-2, 1, 0, 1}},
9233 {{ 6.0f, 0.0f, 0.f}, {32765, -32767, 0, 1}},
9234 {{ 4.0f, 0.0f, 0.f}, {-4, 1, 0, 1}},
9236 const UINT exp_vertex_size12 = sizeof(*exp_vertices12);
9237 /* Test 13. Convert FLOAT2 to UBYTE4N. */
9238 const struct vertex_ptc vertices13[] =
9240 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 2.0f}},
9241 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
9242 {{ 0.0f, 0.0f, 0.f}, {-0.4f, -0.5f}},
9244 {{ 3.0f, 3.0f, 0.f}, {-0.6f, -1.0f}},
9245 {{ 3.0f, 0.0f, 0.f}, {UCHAR_MAX, UCHAR_MAX + 1}},
9246 {{ 1.0f, 0.0f, 0.f}, {2 * UCHAR_MAX, -UCHAR_MAX}},
9248 const UINT num_vertices13 = ARRAY_SIZE(vertices13);
9249 const UINT num_faces13 = ARRAY_SIZE(vertices13) / VERTS_PER_FACE;
9250 const UINT vertex_size13 = sizeof(*vertices13);
9251 const struct vertex_ptc_ubyte4n exp_vertices13[] =
9253 {{ 0.0f, 3.0f, 0.f}, {255, 255, 0, 255}},
9254 {{ 2.0f, 3.0f, 0.f}, {128, 179, 0, 255}},
9255 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 255}},
9257 {{ 3.0f, 3.0f, 0.f}, {0, 0, 0, 255}},
9258 {{ 3.0f, 0.0f, 0.f}, {255, 255, 0, 255}},
9259 {{ 1.0f, 0.0f, 0.f}, {255, 0, 0, 255}},
9261 const UINT exp_vertex_size13 = sizeof(*exp_vertices13);
9262 /* Test 14. Convert FLOAT2 to SHORT2N. */
9263 const struct vertex_ptc vertices14[] =
9265 {{ 0.0f, 3.0f, 0.f}, {1.0f, 2.0f}},
9266 {{ 2.0f, 3.0f, 0.f}, {0.4f, 0.5f}},
9267 {{ 0.0f, 0.0f, 0.f}, {0.6f, -1.0f}},
9269 {{ 3.0f, 3.0f, 0.f}, {-0.4f, -0.5f}},
9270 {{ 3.0f, 0.0f, 0.f}, {-0.9f, -0.99997}},
9271 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX, SHRT_MIN}},
9273 const UINT num_vertices14 = ARRAY_SIZE(vertices14);
9274 const UINT num_faces14 = ARRAY_SIZE(vertices14) / VERTS_PER_FACE;
9275 const UINT vertex_size14 = sizeof(*vertices14);
9276 const struct vertex_ptc_short2 exp_vertices14[] =
9278 {{ 0.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MAX}},
9279 {{ 2.0f, 3.0f, 0.f}, {13107, 16384}},
9280 {{ 0.0f, 0.0f, 0.f}, {19660, SHRT_MIN + 2}},
9282 {{ 3.0f, 3.0f, 0.f}, {-13106, -16383}},
9283 {{ 3.0f, 0.0f, 0.f}, {-29489, SHRT_MIN + 3}},
9284 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX, SHRT_MIN + 2}},
9286 const UINT exp_vertex_size14 = sizeof(*exp_vertices14);
9287 /* Test 15. Convert FLOAT2 to SHORT4N. */
9288 const struct vertex_ptc vertices15[] =
9290 {{ 0.0f, 3.0f, 0.f}, {1.0f, 2.0f}},
9291 {{ 2.0f, 3.0f, 0.f}, {0.4f, 0.5f}},
9292 {{ 0.0f, 0.0f, 0.f}, {0.6f, -1.0f}},
9294 {{ 3.0f, 3.0f, 0.f}, {-0.4f, -0.5f}},
9295 {{ 3.0f, 0.0f, 0.f}, {-0.9f, -0.99997}},
9296 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX, SHRT_MIN}},
9298 const UINT num_vertices15 = ARRAY_SIZE(vertices15);
9299 const UINT num_faces15 = ARRAY_SIZE(vertices15) / VERTS_PER_FACE;
9300 const UINT vertex_size15 = sizeof(*vertices15);
9301 const struct vertex_ptc_short4 exp_vertices15[] =
9303 {{ 0.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MAX, 0, SHRT_MAX}},
9304 {{ 2.0f, 3.0f, 0.f}, {13107, 16384, 0, SHRT_MAX}},
9305 {{ 0.0f, 0.0f, 0.f}, {19660, SHRT_MIN + 2, 0, SHRT_MAX}},
9307 {{ 3.0f, 3.0f, 0.f}, {-13106, -16383, 0, SHRT_MAX}},
9308 {{ 3.0f, 0.0f, 0.f}, {-29489, SHRT_MIN + 3, 0, SHRT_MAX}},
9309 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX, SHRT_MIN + 2, 0, SHRT_MAX}},
9311 const UINT exp_vertex_size15 = sizeof(*exp_vertices15);
9312 /* Test 16. Convert FLOAT2 to USHORT2N. */
9313 const struct vertex_ptc vertices16[] =
9315 {{ 0.0f, 3.0f, 0.f}, {1.0f, 2.0f}},
9316 {{ 2.0f, 3.0f, 0.f}, {0.4f, 0.5f}},
9317 {{ 0.0f, 0.0f, 0.f}, {0.6f, -1.0f}},
9319 {{ 3.0f, 3.0f, 0.f}, {-0.4f, -0.5f}},
9320 {{ 3.0f, 0.0f, 0.f}, {-0.9f, 0.99998f}},
9321 {{ 1.0f, 0.0f, 0.f}, {USHRT_MAX, 0.0f}},
9323 const UINT num_vertices16 = ARRAY_SIZE(vertices16);
9324 const UINT num_faces16 = ARRAY_SIZE(vertices16) / VERTS_PER_FACE;
9325 const UINT vertex_size16 = sizeof(*vertices16);
9326 const struct vertex_ptc_ushort2n exp_vertices16[] =
9328 {{ 0.0f, 3.0f, 0.f}, {USHRT_MAX, USHRT_MAX}},
9329 {{ 2.0f, 3.0f, 0.f}, {26214, 32768}},
9330 {{ 0.0f, 0.0f, 0.f}, {39321, 0}},
9332 {{ 3.0f, 3.0f, 0.f}, {0, 0}},
9333 {{ 3.0f, 0.0f, 0.f}, {0, USHRT_MAX - 1}},
9334 {{ 1.0f, 0.0f, 0.f}, {USHRT_MAX, 0}},
9336 const UINT exp_vertex_size16 = sizeof(*exp_vertices16);
9337 /* Test 17. Convert FLOAT2 to USHORT4N. */
9338 const struct vertex_ptc vertices17[] =
9340 {{ 0.0f, 3.0f, 0.f}, {1.0f, 2.0f}},
9341 {{ 2.0f, 3.0f, 0.f}, {0.4f, 0.5f}},
9342 {{ 0.0f, 0.0f, 0.f}, {0.6f, -1.0f}},
9344 {{ 3.0f, 3.0f, 0.f}, {-0.4f, -0.5f}},
9345 {{ 3.0f, 0.0f, 0.f}, {-0.9f, 0.99998f}},
9346 {{ 1.0f, 0.0f, 0.f}, {USHRT_MAX, 0.0f}},
9348 const UINT num_vertices17 = ARRAY_SIZE(vertices17);
9349 const UINT num_faces17 = ARRAY_SIZE(vertices17) / VERTS_PER_FACE;
9350 const UINT vertex_size17 = sizeof(*vertices17);
9351 const struct vertex_ptc_ushort4n exp_vertices17[] =
9353 {{ 0.0f, 3.0f, 0.f}, {USHRT_MAX, USHRT_MAX, 0, USHRT_MAX}},
9354 {{ 2.0f, 3.0f, 0.f}, {26214, 32768, 0, USHRT_MAX}},
9355 {{ 0.0f, 0.0f, 0.f}, {39321, 0, 0, USHRT_MAX}},
9357 {{ 3.0f, 3.0f, 0.f}, {0, 0, 0, USHRT_MAX}},
9358 {{ 3.0f, 0.0f, 0.f}, {0, USHRT_MAX - 1, 0, USHRT_MAX}},
9359 {{ 1.0f, 0.0f, 0.f}, {USHRT_MAX, 0, 0, USHRT_MAX}},
9361 const UINT exp_vertex_size17 = sizeof(*exp_vertices17);
9362 /* Test 18. Test that the method field is compared by converting a FLOAT2 to
9363 * FLOAT16_2. where the method field has been change from
9364 * D3DDECLMETHOD_DEFAULT to D3DDECLMETHOD_PARTIALU. */
9365 const struct vertex_ptc vertices18[] =
9367 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
9368 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
9369 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
9371 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
9372 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
9373 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
9375 const UINT num_vertices18 = ARRAY_SIZE(vertices18);
9376 const UINT num_faces18 = ARRAY_SIZE(vertices18) / VERTS_PER_FACE;
9377 const UINT vertex_size18 = sizeof(*vertices18);
9378 const struct vertex_ptc_float16_2 exp_vertices18[] =
9380 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
9381 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */
9382 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */
9384 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd}}, /* {0.2f, 0.3f} */
9385 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
9386 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */
9388 const UINT exp_vertex_size18 = sizeof(*exp_vertices18);
9389 /* Test 19. Test that data is lost if usage index changes, e.g. TEXCOORD0
9390 * TEXCOORD1. */
9391 const struct vertex_pntc vertices19[] =
9393 {{ 0.0f, 3.0f, 0.f}, up, { 1.0f, 1.0f}},
9394 {{ 2.0f, 3.0f, 0.f}, up, { 0.5f, 0.7f}},
9395 {{ 0.0f, 0.0f, 0.f}, up, {-0.2f, -0.3f}},
9397 {{ 3.0f, 3.0f, 0.f}, up, { 0.2f, 0.3f}},
9398 {{ 3.0f, 0.0f, 0.f}, up, { 1.0f, 1.0f}},
9399 {{ 1.0f, 0.0f, 0.f}, up, { 0.1f, 0.2f}},
9401 const UINT num_vertices19 = ARRAY_SIZE(vertices19);
9402 const UINT num_faces19 = ARRAY_SIZE(vertices19) / VERTS_PER_FACE;
9403 const UINT vertex_size19 = sizeof(*vertices19);
9404 const struct vertex_pntc exp_vertices19[] =
9406 {{ 0.0f, 3.0f, 0.f}, up, zero_vec2},
9407 {{ 2.0f, 3.0f, 0.f}, up, zero_vec2},
9408 {{ 0.0f, 0.0f, 0.f}, up, zero_vec2},
9410 {{ 3.0f, 3.0f, 0.f}, up, zero_vec2},
9411 {{ 3.0f, 0.0f, 0.f}, up, zero_vec2},
9412 {{ 1.0f, 0.0f, 0.f}, up, zero_vec2},
9414 const UINT exp_vertex_size19 = sizeof(*exp_vertices19);
9415 /* Test 20. Another test that data is lost if usage index changes, e.g.
9416 * TEXCOORD1 to TEXCOORD0. */
9417 const struct vertex_pntc vertices20[] =
9419 {{ 0.0f, 3.0f, 0.f}, up, { 1.0f, 1.0f}},
9420 {{ 2.0f, 3.0f, 0.f}, up, { 0.5f, 0.7f}},
9421 {{ 0.0f, 0.0f, 0.f}, up, {-0.2f, -0.3f}},
9423 {{ 3.0f, 3.0f, 0.f}, up, { 0.2f, 0.3f}},
9424 {{ 3.0f, 0.0f, 0.f}, up, { 1.0f, 1.0f}},
9425 {{ 1.0f, 0.0f, 0.f}, up, { 0.1f, 0.2f}},
9427 const UINT num_vertices20 = ARRAY_SIZE(vertices20);
9428 const UINT num_faces20 = ARRAY_SIZE(vertices20) / VERTS_PER_FACE;
9429 const UINT vertex_size20 = sizeof(*vertices20);
9430 const struct vertex_pntc exp_vertices20[] =
9432 {{ 0.0f, 3.0f, 0.f}, up, zero_vec2},
9433 {{ 2.0f, 3.0f, 0.f}, up, zero_vec2},
9434 {{ 0.0f, 0.0f, 0.f}, up, zero_vec2},
9436 {{ 3.0f, 3.0f, 0.f}, up, zero_vec2},
9437 {{ 3.0f, 0.0f, 0.f}, up, zero_vec2},
9438 {{ 1.0f, 0.0f, 0.f}, up, zero_vec2},
9440 const UINT exp_vertex_size20 = sizeof(*exp_vertices20);
9441 /* Test 21. Convert FLOAT1 to FLOAT2. */
9442 const struct vertex_ptc_float1 vertices21[] =
9444 {{ 0.0f, 3.0f, 0.f}, 1.0f},
9445 {{ 2.0f, 3.0f, 0.f}, 0.5f},
9446 {{ 0.0f, 0.0f, 0.f}, -0.2f},
9448 {{ 3.0f, 3.0f, 0.f}, 0.2f},
9449 {{ 3.0f, 0.0f, 0.f}, 1.0f},
9450 {{ 1.0f, 0.0f, 0.f}, 0.1f},
9452 const UINT num_vertices21 = ARRAY_SIZE(vertices21);
9453 const UINT num_faces21 = ARRAY_SIZE(vertices21) / VERTS_PER_FACE;
9454 const UINT vertex_size21 = sizeof(*vertices21);
9455 const struct vertex_ptc exp_vertices21[] =
9457 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 0.0f}},
9458 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.0f}},
9459 {{ 0.0f, 0.0f, 0.f}, {-0.2f, 0.0f}},
9461 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.0f}},
9462 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 0.0f}},
9463 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.0f}},
9465 const UINT exp_vertex_size21 = sizeof(*exp_vertices21);
9466 /* Test 22. Convert FLOAT1 to FLOAT3. */
9467 const struct vertex_ptc_float1 vertices22[] =
9469 {{ 0.0f, 3.0f, 0.f}, 1.0f},
9470 {{ 2.0f, 3.0f, 0.f}, 0.5f},
9471 {{ 0.0f, 0.0f, 0.f}, -0.2f},
9473 {{ 3.0f, 3.0f, 0.f}, 0.2f},
9474 {{ 3.0f, 0.0f, 0.f}, 1.0f},
9475 {{ 1.0f, 0.0f, 0.f}, 0.1f},
9477 const UINT num_vertices22 = ARRAY_SIZE(vertices22);
9478 const UINT num_faces22 = ARRAY_SIZE(vertices22) / VERTS_PER_FACE;
9479 const UINT vertex_size22 = sizeof(*vertices22);
9480 const struct vertex_ptc_float3 exp_vertices22[] =
9482 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 0.0f, 0.0f}},
9483 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.0f, 0.0f}},
9484 {{ 0.0f, 0.0f, 0.f}, {-0.2f, 0.0f, 0.0f}},
9486 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.0f, 0.0f}},
9487 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 0.0f, 0.0f}},
9488 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.0f, 0.0f}},
9490 const UINT exp_vertex_size22 = sizeof(*exp_vertices22);
9491 /* Test 23. Convert FLOAT1 to FLOAT4. */
9492 const struct vertex_ptc_float1 vertices23[] =
9494 {{ 0.0f, 3.0f, 0.f}, 1.0f},
9495 {{ 2.0f, 3.0f, 0.f}, 0.5f},
9496 {{ 0.0f, 0.0f, 0.f}, -0.2f},
9498 {{ 3.0f, 3.0f, 0.f}, 0.2f},
9499 {{ 3.0f, 0.0f, 0.f}, 1.0f},
9500 {{ 1.0f, 0.0f, 0.f}, 0.1f},
9502 const UINT num_vertices23 = ARRAY_SIZE(vertices23);
9503 const UINT num_faces23 = ARRAY_SIZE(vertices23) / VERTS_PER_FACE;
9504 const UINT vertex_size23 = sizeof(*vertices23);
9505 const struct vertex_ptc_float4 exp_vertices23[] =
9507 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 0.0f, 0.0f, 1.0f}},
9508 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.0f, 0.0f, 1.0f}},
9509 {{ 0.0f, 0.0f, 0.f}, {-0.2f, 0.0f, 0.0f, 1.0f}},
9511 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.0f, 0.0f, 1.0f}},
9512 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 0.0f, 0.0f, 1.0f}},
9513 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.0f, 0.0f, 1.0f}},
9515 const UINT exp_vertex_size23 = sizeof(*exp_vertices23);
9516 /* Test 24. Convert FLOAT1 to D3DCOLOR. */
9517 const struct vertex_ptc_float1 vertices24[] =
9519 {{ 0.0f, 3.0f, 0.f}, 1.0f},
9520 {{ 2.0f, 3.0f, 0.f}, 0.5f},
9521 {{ 0.0f, 0.0f, 0.f}, -0.2f},
9523 {{ 3.0f, 3.0f, 0.f}, 0.2f},
9524 {{ 3.0f, 0.0f, 0.f}, 1.0f},
9525 {{ 1.0f, 0.0f, 0.f}, 0.11f},
9527 const UINT num_vertices24 = ARRAY_SIZE(vertices24);
9528 const UINT num_faces24 = ARRAY_SIZE(vertices24) / VERTS_PER_FACE;
9529 const UINT vertex_size24 = sizeof(*vertices24);
9530 const struct vertex_ptc_d3dcolor exp_vertices24[] =
9532 {{ 0.0f, 3.0f, 0.f}, {0, 0, 255, 255}},
9533 {{ 2.0f, 3.0f, 0.f}, {0, 0, 128, 255}},
9534 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 255}},
9536 {{ 3.0f, 3.0f, 0.f}, {0, 0, 51, 255}},
9537 {{ 3.0f, 0.0f, 0.f}, {0, 0, 255, 255}},
9538 {{ 1.0f, 0.0f, 0.f}, {0, 0, 28, 255}},
9540 const UINT exp_vertex_size24 = sizeof(*exp_vertices24);
9541 /* Test 25. Convert FLOAT1 to ubyte4. */
9542 const struct vertex_ptc_float1 vertices25[] =
9544 {{ 0.0f, 3.0f, 0.f}, 0.0f},
9545 {{ 2.0f, 3.0f, 0.f}, 1.4f},
9546 {{ 0.0f, 0.0f, 0.f}, 1.5f},
9548 {{ 3.0f, 3.0f, 0.f}, 255.0f},
9549 {{ 3.0f, 0.0f, 0.f}, 256.0f},
9550 {{ 1.0f, 0.0f, 0.f}, -1.0f},
9552 const UINT num_vertices25 = ARRAY_SIZE(vertices25);
9553 const UINT num_faces25 = ARRAY_SIZE(vertices25) / VERTS_PER_FACE;
9554 const UINT vertex_size25 = sizeof(*vertices25);
9555 const struct vertex_ptc_ubyte4 exp_vertices25[] =
9557 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 1}},
9558 {{ 2.0f, 3.0f, 0.f}, {1, 0, 0, 1}},
9559 {{ 0.0f, 0.0f, 0.f}, {2, 0, 0, 1}},
9561 {{ 3.0f, 3.0f, 0.f}, {255, 0, 0, 1}},
9562 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 1}},
9563 {{ 1.0f, 0.0f, 0.f}, {0, 0, 0, 1}},
9565 const UINT exp_vertex_size25 = sizeof(*exp_vertices25);
9566 /* Test 26. Convert FLOAT4 to D3DCOLOR. */
9567 const struct vertex_ptc_float4 vertices26[] =
9569 {{ 0.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.4f, 0.5f}},
9570 {{ 2.0f, 3.0f, 0.f}, {-0.4f, -0.5f, -1.0f, -2.0f}},
9571 {{ 0.0f, 0.0f, 0.f}, {254.0f, 255.0f, 256.0f, 257.0f}},
9573 {{ 3.0f, 3.0f, 0.f}, {0.1f, 0.2f, 0.3f, 0.4f}},
9574 {{ 3.0f, 0.0f, 0.f}, {0.5f, 0.6f, 0.7f, 0.8f}},
9575 {{ 1.0f, 0.0f, 0.f}, {0.9f, 0.99f, 0.995f, 0.999f}},
9577 const UINT num_vertices26 = ARRAY_SIZE(vertices26);
9578 const UINT num_faces26 = ARRAY_SIZE(vertices26) / VERTS_PER_FACE;
9579 const UINT vertex_size26 = sizeof(*vertices26);
9580 const struct vertex_ptc_d3dcolor exp_vertices26[] =
9582 {{ 0.0f, 3.0f, 0.f}, {102, 255, 0, 128}},
9583 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9584 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
9586 {{ 3.0f, 3.0f, 0.f}, {77, 51, 26, 102}},
9587 {{ 3.0f, 0.0f, 0.f}, {179, 153, 128, 204}},
9588 {{ 1.0f, 0.0f, 0.f}, {254, 252, 230, 255}},
9590 const UINT exp_vertex_size26 = sizeof(*exp_vertices26);
9591 /* Test 27. Convert D3DCOLOR to FLOAT4. */
9592 const struct vertex_ptc_d3dcolor vertices27[] =
9594 {{ 0.0f, 3.0f, 0.f}, {102, 255, 0, 128}},
9595 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9596 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
9598 {{ 3.0f, 3.0f, 0.f}, {77, 51, 26, 102}},
9599 {{ 3.0f, 0.0f, 0.f}, {179, 153, 128, 204}},
9600 {{ 1.0f, 0.0f, 0.f}, {254, 252, 230, 255}},
9602 const UINT num_vertices27 = ARRAY_SIZE(vertices27);
9603 const UINT num_faces27 = ARRAY_SIZE(vertices27) / VERTS_PER_FACE;
9604 const UINT vertex_size27 = sizeof(*vertices27);
9605 const struct vertex_ptc_float4 exp_vertices27[] =
9607 {{ 0.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.4f, 0.501961f}},
9608 {{ 2.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9609 {{ 0.0f, 0.0f, 0.f}, {1.0f, 1.0f, 1.0f, 1.0f}},
9611 {{ 3.0f, 3.0f, 0.f}, {0.101961f, 0.2f, 0.301961f, 0.4f}},
9612 {{ 3.0f, 0.0f, 0.f}, {0.501961f, 0.6f, 0.701961f, 0.8f}},
9613 {{ 1.0f, 0.0f, 0.f}, {0.901961f, 0.988235f, 0.996078f, 1.0f}},
9615 const UINT exp_vertex_size27 = sizeof(*exp_vertices27);
9616 /* Test 28. Convert UBYTE4 to FLOAT4. */
9617 const struct vertex_ptc_ubyte4 vertices28[] =
9619 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9620 {{ 2.0f, 3.0f, 0.f}, {1, 1, 1, 1}},
9621 {{ 0.0f, 0.0f, 0.f}, {1, 0, 1, 0}},
9623 {{ 3.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
9624 {{ 3.0f, 0.0f, 0.f}, {10, 20, 30, 40}},
9625 {{ 1.0f, 0.0f, 0.f}, {50, 60, 127, 255}},
9627 const UINT num_vertices28 = ARRAY_SIZE(vertices28);
9628 const UINT num_faces28 = ARRAY_SIZE(vertices28) / VERTS_PER_FACE;
9629 const UINT vertex_size28 = sizeof(*vertices28);
9630 const struct vertex_ptc_float4 exp_vertices28[] =
9632 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9633 {{ 2.0f, 3.0f, 0.f}, {1.0f, 1.0f, 1.0f, 1.0f}},
9634 {{ 0.0f, 0.0f, 0.f}, {1.0f, 0.0f, 1.0f, 0.0f}},
9636 {{ 3.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.0f, 1.0f}},
9637 {{ 3.0f, 0.0f, 0.f}, {10.0f, 20.0f, 30.0f, 40.0f}},
9638 {{ 1.0f, 0.0f, 0.f}, {50.0f, 60.0f, 127.0f, 255.0f}},
9640 const UINT exp_vertex_size28 = sizeof(*exp_vertices28);
9641 /* Test 29. Convert SHORT2 to FLOAT4. */
9642 const struct vertex_ptc_short2 vertices29[] =
9644 {{ 0.0f, 3.0f, 0.f}, {0, 0}},
9645 {{ 2.0f, 3.0f, 0.f}, {0, 1}},
9646 {{ 0.0f, 0.0f, 0.f}, {1, 0}},
9648 {{ 3.0f, 3.0f, 0.f}, {1, 1}},
9649 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MAX}},
9650 {{ 1.0f, 0.0f, 0.f}, {-42, 42}},
9652 const UINT num_vertices29 = ARRAY_SIZE(vertices29);
9653 const UINT num_faces29 = ARRAY_SIZE(vertices29) / VERTS_PER_FACE;
9654 const UINT vertex_size29 = sizeof(*vertices29);
9655 const struct vertex_ptc_float4 exp_vertices29[] =
9657 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 1.0f}},
9658 {{ 2.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.0f, 1.0f }},
9659 {{ 0.0f, 0.0f, 0.f}, {1.0f, 0.0f, 0.0f, 1.0f}},
9661 {{ 3.0f, 3.0f, 0.f}, {1.0f, 1.0f, 0.0f, 1.0f}},
9662 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MAX, 0.0f, 1.0f}},
9663 {{ 1.0f, 0.0f, 0.f}, {-42.0f, 42.0f, 0.0f, 1.0f}},
9665 const UINT exp_vertex_size29 = sizeof(*exp_vertices29);
9666 /* Test 29. Convert SHORT4 to FLOAT4. */
9667 const struct vertex_ptc_short4 vertices30[] =
9669 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9670 {{ 2.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
9671 {{ 0.0f, 0.0f, 0.f}, {1, 0, 1, 0}},
9673 {{ 3.0f, 3.0f, 0.f}, {1, 1, 1, 1}},
9674 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MAX, 1, 0}},
9675 {{ 1.0f, 0.0f, 0.f}, {-42, 42, SHRT_MAX, SHRT_MIN}},
9677 const UINT num_vertices30 = ARRAY_SIZE(vertices30);
9678 const UINT num_faces30 = ARRAY_SIZE(vertices30) / VERTS_PER_FACE;
9679 const UINT vertex_size30 = sizeof(*vertices30);
9680 const struct vertex_ptc_float4 exp_vertices30[] =
9682 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9683 {{ 2.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.0f, 1.0f }},
9684 {{ 0.0f, 0.0f, 0.f}, {1.0f, 0.0f, 1.0f, 0.0f}},
9686 {{ 3.0f, 3.0f, 0.f}, {1.0f, 1.0f, 1.0f, 1.0f}},
9687 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MAX, 1.0f, 0.0f}},
9688 {{ 1.0f, 0.0f, 0.f}, {-42.0f, 42.0f, SHRT_MAX, SHRT_MIN}},
9690 const UINT exp_vertex_size30 = sizeof(*exp_vertices30);
9691 /* Test 31. Convert UBYTE4N to FLOAT4. */
9692 const struct vertex_ptc_ubyte4n vertices31[] =
9694 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9695 {{ 2.0f, 3.0f, 0.f}, {1, 1, 1, 1}},
9696 {{ 0.0f, 0.0f, 0.f}, {1, 0, 1, 0}},
9698 {{ 3.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
9699 {{ 3.0f, 0.0f, 0.f}, {10, 20, 30, 40}},
9700 {{ 1.0f, 0.0f, 0.f}, {50, 60, 70, UCHAR_MAX}},
9702 const UINT num_vertices31 = ARRAY_SIZE(vertices31);
9703 const UINT num_faces31 = ARRAY_SIZE(vertices31) / VERTS_PER_FACE;
9704 const UINT vertex_size31 = sizeof(*vertices31);
9705 const struct vertex_ptc_float4 exp_vertices31[] =
9707 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9708 {{ 2.0f, 3.0f, 0.f}, {(FLOAT)1/UCHAR_MAX, (FLOAT)1/UCHAR_MAX, (FLOAT)1/UCHAR_MAX, (FLOAT)1/UCHAR_MAX}},
9709 {{ 0.0f, 0.0f, 0.f}, {(FLOAT)1/UCHAR_MAX, 0.0f, (FLOAT)1/UCHAR_MAX, 0.0f}},
9711 {{ 3.0f, 3.0f, 0.f}, {0.0f, (FLOAT)1/UCHAR_MAX, 0.0f, (FLOAT)1/UCHAR_MAX}},
9712 {{ 3.0f, 0.0f, 0.f}, {(FLOAT)10/UCHAR_MAX, (FLOAT)20/UCHAR_MAX, (FLOAT)30/UCHAR_MAX, (FLOAT)40/UCHAR_MAX}},
9713 {{ 1.0f, 0.0f, 0.f}, {(FLOAT)50/UCHAR_MAX, (FLOAT)60/UCHAR_MAX, (FLOAT)70/UCHAR_MAX, 1.0f}},
9715 const UINT exp_vertex_size31 = sizeof(*exp_vertices31);
9716 /* Test 32. Convert SHORT2N to FLOAT4. */
9717 const struct vertex_ptc_short2 vertices32[] =
9719 {{ 0.0f, 3.0f, 0.f}, {0, 0}},
9720 {{ 2.0f, 3.0f, 0.f}, {0, 1}},
9721 {{ 0.0f, 0.0f, 0.f}, {1, 0}},
9723 {{ 3.0f, 3.0f, 0.f}, {1, 1}},
9724 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN + 1, SHRT_MAX}},
9725 {{ 1.0f, 0.0f, 0.f}, {-42, 42}},
9727 const UINT num_vertices32 = ARRAY_SIZE(vertices32);
9728 const UINT num_faces32 = ARRAY_SIZE(vertices32) / VERTS_PER_FACE;
9729 const UINT vertex_size32 = sizeof(*vertices32);
9730 const struct vertex_ptc_float4 exp_vertices32[] =
9732 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 1.0f}},
9733 {{ 2.0f, 3.0f, 0.f}, {0.0f, 1.0f/SHRT_MAX, 0.0f, 1.0f}},
9734 {{ 0.0f, 0.0f, 0.f}, {1.0f/SHRT_MAX, 0.0f, 0.0f, 1.0f}},
9736 {{ 3.0f, 3.0f, 0.f}, {1.0f/SHRT_MAX, 1.0f/SHRT_MAX, 0.0f, 1.0f}},
9737 {{ 3.0f, 0.0f, 0.f}, {-1.0f, 1.0f, 0.0f, 1.0f}},
9738 {{ 1.0f, 0.0f, 0.f}, {-42.0f/SHRT_MAX, 42.0f/SHRT_MAX, 0.0f, 1.0f}},
9740 const UINT exp_vertex_size32 = sizeof(*exp_vertices32);
9741 /* Test 33. Convert SHORT4N to FLOAT4. */
9742 const struct vertex_ptc_short4 vertices33[] =
9744 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9745 {{ 2.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
9746 {{ 0.0f, 0.0f, 0.f}, {1, 0, 1, 0}},
9748 {{ 3.0f, 3.0f, 0.f}, {1, 1, 1, 1}},
9749 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN + 1, SHRT_MAX, SHRT_MIN + 1, SHRT_MAX}},
9750 {{ 1.0f, 0.0f, 0.f}, {-42, 42, 1, 1}},
9752 const UINT num_vertices33 = ARRAY_SIZE(vertices33);
9753 const UINT num_faces33 = ARRAY_SIZE(vertices33) / VERTS_PER_FACE;
9754 const UINT vertex_size33 = sizeof(*vertices33);
9755 const struct vertex_ptc_float4 exp_vertices33[] =
9757 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9758 {{ 2.0f, 3.0f, 0.f}, {0.0f, 1.0f/SHRT_MAX, 0.0f, 1.0f/SHRT_MAX}},
9759 {{ 0.0f, 0.0f, 0.f}, {1.0f/SHRT_MAX, 0.0f, 1.0f/SHRT_MAX, 0.0f}},
9761 {{ 3.0f, 3.0f, 0.f}, {1.0f/SHRT_MAX, 1.0f/SHRT_MAX, 1.0f/SHRT_MAX, 1.0f/SHRT_MAX}},
9762 {{ 3.0f, 0.0f, 0.f}, {-1.0f, 1.0f, -1.0f, 1.0f}},
9763 {{ 1.0f, 0.0f, 0.f}, {-42.0f/SHRT_MAX, 42.0f/SHRT_MAX, 1.0f/SHRT_MAX, 1.0f/SHRT_MAX}},
9765 const UINT exp_vertex_size33 = sizeof(*exp_vertices33);
9766 /* Test 34. Convert FLOAT16_2 to FLOAT4. */
9767 const struct vertex_ptc_float16_2 vertices34[] =
9769 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
9770 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */
9771 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */
9773 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd}}, /* {0.2f, 0.3f} */
9774 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
9775 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */
9777 const UINT num_vertices34 = ARRAY_SIZE(vertices34);
9778 const UINT num_faces34 = ARRAY_SIZE(vertices34) / VERTS_PER_FACE;
9779 const UINT vertex_size34 = sizeof(*vertices34);
9780 const struct vertex_ptc_float4 exp_vertices34[] =
9782 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f, 0.0f, 1.0f}},
9783 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.700195f, 0.0f, 1.0f}},
9784 {{ 0.0f, 0.0f, 0.f}, {-0.199951f, -0.300049f, 0.0f, 1.0f}},
9786 {{ 3.0f, 3.0f, 0.f}, {0.199951f, 0.300049f, 0.0f, 1.0f}},
9787 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f, 0.0f, 1.0f}},
9788 {{ 1.0f, 0.0f, 0.f}, {0.099976f, 0.199951f, 0.0f, 1.0f}},
9790 const UINT exp_vertex_size34 = sizeof(*exp_vertices34);
9791 /* Test 35. Convert FLOAT16_4 to FLOAT4. */
9792 const struct vertex_ptc_float16_4 vertices35[] =
9794 {{ 0.0f, 3.0f, 0.f}, {0x0000, 0x0000, 0x0000, 0x0000}},
9795 {{ 2.0f, 3.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}},
9796 {{ 0.0f, 0.0f, 0.f}, {0x3c00, 0x0000, 0x3c00, 0x0000}},
9798 {{ 3.0f, 3.0f, 0.f}, {0x0000, 0x3c00, 0x0000, 0x3c00}},
9799 {{ 3.0f, 0.0f, 0.f}, {0x3800, 0x399a, 0xb266, 0xb4cd}},
9800 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266, 0x2e66, 0x3266}},
9802 const UINT num_vertices35 = ARRAY_SIZE(vertices35);
9803 const UINT num_faces35 = ARRAY_SIZE(vertices35) / VERTS_PER_FACE;
9804 const UINT vertex_size35 = sizeof(*vertices35);
9805 const struct vertex_ptc_float4 exp_vertices35[] =
9807 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9808 {{ 2.0f, 3.0f, 0.f}, {1.0f, 1.0f, 1.0f, 1.0f}},
9809 {{ 0.0f, 0.0f, 0.f}, {1.0f, 0.0f, 1.0f, 0.0f}},
9811 {{ 3.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.0f, 1.0f}},
9812 {{ 3.0f, 0.0f, 0.f}, {0.5f, 0.700195f, -0.199951f, -0.300049f}},
9813 {{ 1.0f, 0.0f, 0.f}, {0.099976f, 0.199951f, 0.099976f, 0.199951f}},
9815 const UINT exp_vertex_size35 = sizeof(*exp_vertices35);
9816 /* Test 36. Check that vertex buffer sharing is ok. */
9817 const struct vertex_pn vertices36[] =
9819 {{ 0.0f, 3.0f, 0.f}, up},
9820 {{ 2.0f, 3.0f, 0.f}, up},
9821 {{ 0.0f, 0.0f, 0.f}, up},
9823 const UINT num_vertices36 = ARRAY_SIZE(vertices36);
9824 const UINT num_faces36 = ARRAY_SIZE(vertices36) / VERTS_PER_FACE;
9825 const UINT vertex_size36 = sizeof(*vertices36);
9826 const DWORD clone_options36 = options | D3DXMESH_VB_SHARE;
9827 /* Common mesh data */
9828 ID3DXMesh *mesh = NULL;
9829 ID3DXMesh *mesh_clone = NULL;
9830 struct
9832 const BYTE *vertices;
9833 const DWORD *indices;
9834 const DWORD *attributes;
9835 const UINT num_vertices;
9836 const UINT num_faces;
9837 const UINT vertex_size;
9838 const DWORD create_options;
9839 const DWORD clone_options;
9840 D3DVERTEXELEMENT9 *declaration;
9841 D3DVERTEXELEMENT9 *new_declaration;
9842 const BYTE *exp_vertices;
9843 const UINT exp_vertex_size;
9845 tc[] =
9848 (BYTE*)vertices0,
9849 NULL,
9850 NULL,
9851 num_vertices0,
9852 num_faces0,
9853 vertex_size0,
9854 options,
9855 options,
9856 declaration_pn,
9857 declaration_pn,
9858 (BYTE*)vertices0,
9859 vertex_size0
9862 (BYTE*)vertices0,
9863 NULL,
9864 NULL,
9865 num_vertices0,
9866 num_faces0,
9867 vertex_size0,
9868 options_16bit,
9869 options_16bit,
9870 declaration_pn,
9871 declaration_pn,
9872 (BYTE*)vertices0,
9873 vertex_size0
9876 (BYTE*)vertices0,
9877 NULL,
9878 NULL,
9879 num_vertices0,
9880 num_faces0,
9881 vertex_size0,
9882 options,
9883 options,
9884 declaration_pn,
9885 declaration_pntc,
9886 (BYTE*)exp_vertices2,
9887 exp_vertex_size2
9890 (BYTE*)vertices0,
9891 NULL,
9892 NULL,
9893 num_vertices0,
9894 num_faces0,
9895 vertex_size0,
9896 options,
9897 options,
9898 declaration_pn,
9899 declaration_ptcn,
9900 (BYTE*)exp_vertices3,
9901 exp_vertex_size3
9904 (BYTE*)vertices4,
9905 NULL,
9906 NULL,
9907 num_vertices4,
9908 num_faces4,
9909 vertex_size4,
9910 options,
9911 options,
9912 declaration_ptc,
9913 declaration_ptc_float16_2,
9914 (BYTE*)exp_vertices4,
9915 exp_vertex_size4
9918 (BYTE*)vertices5,
9919 NULL,
9920 NULL,
9921 num_vertices5,
9922 num_faces5,
9923 vertex_size5,
9924 options,
9925 options,
9926 declaration_ptc,
9927 declaration_ptc_float16_4,
9928 (BYTE*)exp_vertices5,
9929 exp_vertex_size5
9932 (BYTE*)vertices6,
9933 NULL,
9934 NULL,
9935 num_vertices6,
9936 num_faces6,
9937 vertex_size6,
9938 options,
9939 options,
9940 declaration_ptc,
9941 declaration_ptc_float1,
9942 (BYTE*)exp_vertices6,
9943 exp_vertex_size6
9946 (BYTE*)vertices7,
9947 NULL,
9948 NULL,
9949 num_vertices7,
9950 num_faces7,
9951 vertex_size7,
9952 options,
9953 options,
9954 declaration_ptc,
9955 declaration_ptc_float3,
9956 (BYTE*)exp_vertices7,
9957 exp_vertex_size7
9960 (BYTE*)vertices8,
9961 NULL,
9962 NULL,
9963 num_vertices8,
9964 num_faces8,
9965 vertex_size8,
9966 options,
9967 options,
9968 declaration_ptc,
9969 declaration_ptc_float4,
9970 (BYTE*)exp_vertices8,
9971 exp_vertex_size8
9974 (BYTE*)vertices9,
9975 NULL,
9976 NULL,
9977 num_vertices9,
9978 num_faces9,
9979 vertex_size9,
9980 options,
9981 options,
9982 declaration_ptc,
9983 declaration_ptc_d3dcolor,
9984 (BYTE*)exp_vertices9,
9985 exp_vertex_size9
9988 (BYTE*)vertices10,
9989 NULL,
9990 NULL,
9991 num_vertices10,
9992 num_faces10,
9993 vertex_size10,
9994 options,
9995 options,
9996 declaration_ptc,
9997 declaration_ptc_ubyte4,
9998 (BYTE*)exp_vertices10,
9999 exp_vertex_size10
10002 (BYTE*)vertices11,
10003 NULL,
10004 NULL,
10005 num_vertices11,
10006 num_faces11,
10007 vertex_size11,
10008 options,
10009 options,
10010 declaration_ptc,
10011 declaration_ptc_short2,
10012 (BYTE*)exp_vertices11,
10013 exp_vertex_size11
10016 (BYTE*)vertices12,
10017 NULL,
10018 NULL,
10019 num_vertices12,
10020 num_faces12,
10021 vertex_size12,
10022 options,
10023 options,
10024 declaration_ptc,
10025 declaration_ptc_short4,
10026 (BYTE*)exp_vertices12,
10027 exp_vertex_size12
10030 (BYTE*)vertices13,
10031 NULL,
10032 NULL,
10033 num_vertices13,
10034 num_faces13,
10035 vertex_size13,
10036 options,
10037 options,
10038 declaration_ptc,
10039 declaration_ptc_ubyte4n,
10040 (BYTE*)exp_vertices13,
10041 exp_vertex_size13
10044 (BYTE*)vertices14,
10045 NULL,
10046 NULL,
10047 num_vertices14,
10048 num_faces14,
10049 vertex_size14,
10050 options,
10051 options,
10052 declaration_ptc,
10053 declaration_ptc_short2n,
10054 (BYTE*)exp_vertices14,
10055 exp_vertex_size14
10058 (BYTE*)vertices15,
10059 NULL,
10060 NULL,
10061 num_vertices15,
10062 num_faces15,
10063 vertex_size15,
10064 options,
10065 options,
10066 declaration_ptc,
10067 declaration_ptc_short4n,
10068 (BYTE*)exp_vertices15,
10069 exp_vertex_size15
10072 (BYTE*)vertices16,
10073 NULL,
10074 NULL,
10075 num_vertices16,
10076 num_faces16,
10077 vertex_size16,
10078 options,
10079 options,
10080 declaration_ptc,
10081 declaration_ptc_ushort2n,
10082 (BYTE*)exp_vertices16,
10083 exp_vertex_size16
10086 (BYTE*)vertices17,
10087 NULL,
10088 NULL,
10089 num_vertices17,
10090 num_faces17,
10091 vertex_size17,
10092 options,
10093 options,
10094 declaration_ptc,
10095 declaration_ptc_ushort4n,
10096 (BYTE*)exp_vertices17,
10097 exp_vertex_size17
10100 (BYTE*)vertices18,
10101 NULL,
10102 NULL,
10103 num_vertices18,
10104 num_faces18,
10105 vertex_size18,
10106 options,
10107 options,
10108 declaration_ptc,
10109 declaration_ptc_float16_2_partialu,
10110 (BYTE*)exp_vertices18,
10111 exp_vertex_size18
10114 (BYTE*)vertices19,
10115 NULL,
10116 NULL,
10117 num_vertices19,
10118 num_faces19,
10119 vertex_size19,
10120 options,
10121 options,
10122 declaration_pntc,
10123 declaration_pntc1,
10124 (BYTE*)exp_vertices19,
10125 exp_vertex_size19
10128 (BYTE*)vertices20,
10129 NULL,
10130 NULL,
10131 num_vertices20,
10132 num_faces20,
10133 vertex_size20,
10134 options,
10135 options,
10136 declaration_pntc1,
10137 declaration_pntc,
10138 (BYTE*)exp_vertices20,
10139 exp_vertex_size20
10142 (BYTE*)vertices21,
10143 NULL,
10144 NULL,
10145 num_vertices21,
10146 num_faces21,
10147 vertex_size21,
10148 options,
10149 options,
10150 declaration_ptc_float1,
10151 declaration_ptc,
10152 (BYTE*)exp_vertices21,
10153 exp_vertex_size21
10156 (BYTE*)vertices22,
10157 NULL,
10158 NULL,
10159 num_vertices22,
10160 num_faces22,
10161 vertex_size22,
10162 options,
10163 options,
10164 declaration_ptc_float1,
10165 declaration_ptc_float3,
10166 (BYTE*)exp_vertices22,
10167 exp_vertex_size22
10170 (BYTE*)vertices23,
10171 NULL,
10172 NULL,
10173 num_vertices23,
10174 num_faces23,
10175 vertex_size23,
10176 options,
10177 options,
10178 declaration_ptc_float1,
10179 declaration_ptc_float4,
10180 (BYTE*)exp_vertices23,
10181 exp_vertex_size23
10184 (BYTE*)vertices24,
10185 NULL,
10186 NULL,
10187 num_vertices24,
10188 num_faces24,
10189 vertex_size24,
10190 options,
10191 options,
10192 declaration_ptc_float1,
10193 declaration_ptc_d3dcolor,
10194 (BYTE*)exp_vertices24,
10195 exp_vertex_size24
10198 (BYTE*)vertices25,
10199 NULL,
10200 NULL,
10201 num_vertices25,
10202 num_faces25,
10203 vertex_size25,
10204 options,
10205 options,
10206 declaration_ptc_float1,
10207 declaration_ptc_ubyte4,
10208 (BYTE*)exp_vertices25,
10209 exp_vertex_size25
10212 (BYTE*)vertices26,
10213 NULL,
10214 NULL,
10215 num_vertices26,
10216 num_faces26,
10217 vertex_size26,
10218 options,
10219 options,
10220 declaration_ptc_float4,
10221 declaration_ptc_d3dcolor,
10222 (BYTE*)exp_vertices26,
10223 exp_vertex_size26
10226 (BYTE*)vertices27,
10227 NULL,
10228 NULL,
10229 num_vertices27,
10230 num_faces27,
10231 vertex_size27,
10232 options,
10233 options,
10234 declaration_ptc_d3dcolor,
10235 declaration_ptc_float4,
10236 (BYTE*)exp_vertices27,
10237 exp_vertex_size27
10240 (BYTE*)vertices28,
10241 NULL,
10242 NULL,
10243 num_vertices28,
10244 num_faces28,
10245 vertex_size28,
10246 options,
10247 options,
10248 declaration_ptc_ubyte4,
10249 declaration_ptc_float4,
10250 (BYTE*)exp_vertices28,
10251 exp_vertex_size28
10254 (BYTE*)vertices29,
10255 NULL,
10256 NULL,
10257 num_vertices29,
10258 num_faces29,
10259 vertex_size29,
10260 options,
10261 options,
10262 declaration_ptc_short2,
10263 declaration_ptc_float4,
10264 (BYTE*)exp_vertices29,
10265 exp_vertex_size29
10268 (BYTE*)vertices30,
10269 NULL,
10270 NULL,
10271 num_vertices30,
10272 num_faces30,
10273 vertex_size30,
10274 options,
10275 options,
10276 declaration_ptc_short4,
10277 declaration_ptc_float4,
10278 (BYTE*)exp_vertices30,
10279 exp_vertex_size30
10282 (BYTE*)vertices31,
10283 NULL,
10284 NULL,
10285 num_vertices31,
10286 num_faces31,
10287 vertex_size31,
10288 options,
10289 options,
10290 declaration_ptc_ubyte4n,
10291 declaration_ptc_float4,
10292 (BYTE*)exp_vertices31,
10293 exp_vertex_size31
10296 (BYTE*)vertices32,
10297 NULL,
10298 NULL,
10299 num_vertices32,
10300 num_faces32,
10301 vertex_size32,
10302 options,
10303 options,
10304 declaration_ptc_short2n,
10305 declaration_ptc_float4,
10306 (BYTE*)exp_vertices32,
10307 exp_vertex_size32
10310 (BYTE*)vertices33,
10311 NULL,
10312 NULL,
10313 num_vertices33,
10314 num_faces33,
10315 vertex_size33,
10316 options,
10317 options,
10318 declaration_ptc_short4n,
10319 declaration_ptc_float4,
10320 (BYTE*)exp_vertices33,
10321 exp_vertex_size33
10324 (BYTE*)vertices34,
10325 NULL,
10326 NULL,
10327 num_vertices34,
10328 num_faces34,
10329 vertex_size34,
10330 options,
10331 options,
10332 declaration_ptc_float16_2,
10333 declaration_ptc_float4,
10334 (BYTE*)exp_vertices34,
10335 exp_vertex_size34
10338 (BYTE*)vertices35,
10339 NULL,
10340 NULL,
10341 num_vertices35,
10342 num_faces35,
10343 vertex_size35,
10344 options,
10345 options,
10346 declaration_ptc_float16_4,
10347 declaration_ptc_float4,
10348 (BYTE*)exp_vertices35,
10349 exp_vertex_size35
10352 (BYTE*)vertices36,
10353 NULL,
10354 NULL,
10355 num_vertices36,
10356 num_faces36,
10357 vertex_size36,
10358 options,
10359 clone_options36,
10360 declaration_pn,
10361 declaration_pn,
10362 (BYTE*)vertices36,
10363 vertex_size36
10367 test_context = new_test_context();
10368 if (!test_context)
10370 skip("Couldn't create test context\n");
10371 goto cleanup;
10374 for (i = 0; i < ARRAY_SIZE(tc); i++)
10376 UINT j;
10377 D3DVERTEXELEMENT9 new_declaration[MAX_FVF_DECL_SIZE];
10378 UINT exp_new_decl_length, new_decl_length;
10379 UINT exp_new_decl_size, new_decl_size;
10381 hr = init_test_mesh(tc[i].num_faces, tc[i].num_vertices,
10382 tc[i].create_options,
10383 tc[i].declaration,
10384 test_context->device, &mesh,
10385 tc[i].vertices, tc[i].vertex_size,
10386 tc[i].indices, tc[i].attributes);
10387 if (FAILED(hr))
10389 skip("Couldn't initialize test mesh %d. Got %lx expected D3D_OK\n", i, hr);
10390 goto cleanup;
10393 hr = mesh->lpVtbl->CloneMesh(mesh, tc[i].clone_options, tc[i].new_declaration,
10394 test_context->device, &mesh_clone);
10395 ok(hr == D3D_OK, "Test %u, got unexpected hr %#lx.\n", i, hr);
10397 hr = mesh_clone->lpVtbl->GetDeclaration(mesh_clone, new_declaration);
10398 ok(hr == D3D_OK, "Test %u, got unexpected hr %#lx.\n", i, hr);
10399 /* Check declaration elements */
10400 for (j = 0; tc[i].new_declaration[j].Stream != 0xFF; j++)
10402 ok(memcmp(&tc[i].new_declaration[j], &new_declaration[j], sizeof(*new_declaration)) == 0,
10403 "Test case %d failed. Declaration element %d did not match.\n", i, j);
10406 /* Check declaration length */
10407 exp_new_decl_length = D3DXGetDeclLength(tc[i].new_declaration);
10408 new_decl_length = D3DXGetDeclLength(new_declaration);
10409 ok(new_decl_length == exp_new_decl_length,
10410 "Test case %d failed. Got new declaration length %d, expected %d\n",
10411 i, new_decl_length, exp_new_decl_length);
10413 /* Check declaration size */
10414 exp_new_decl_size = D3DXGetDeclVertexSize(tc[i].new_declaration, 0);
10415 new_decl_size = D3DXGetDeclVertexSize(new_declaration, 0);
10416 ok(new_decl_size == exp_new_decl_size,
10417 "Test case %d failed. Got new declaration size %d, expected %d\n",
10418 i, new_decl_size, exp_new_decl_size);
10420 /* Check vertex data in cloned mesh */
10421 hr = mesh_clone->lpVtbl->LockVertexBuffer(mesh_clone, 0, (void**)&vertices);
10422 if (FAILED(hr))
10424 skip("Couldn't lock cloned vertex buffer.\n");
10425 goto cleanup;
10427 for (j = 0; j < tc[i].num_vertices; j++)
10429 UINT index = tc[i].exp_vertex_size * j;
10430 check_vertex_components(__LINE__, i, j, &vertices[index], &tc[i].exp_vertices[index], tc[i].new_declaration);
10432 hr = mesh_clone->lpVtbl->UnlockVertexBuffer(mesh_clone);
10433 if (FAILED(hr))
10435 skip("Couldn't unlock vertex buffer.\n");
10436 goto cleanup;
10438 vertices = NULL;
10439 mesh->lpVtbl->Release(mesh);
10440 mesh = NULL;
10441 mesh_clone->lpVtbl->Release(mesh_clone);
10442 mesh_clone = NULL;
10445 /* The following test shows that it is not possible to share a vertex buffer
10446 * with D3DXMESH_VB_SHARE and change the vertex declaration at the same
10447 * time. It reuses the test data from test 2.
10449 hr = init_test_mesh(tc[2].num_faces, tc[2].num_vertices,
10450 tc[2].create_options,
10451 tc[2].declaration,
10452 test_context->device, &mesh,
10453 tc[2].vertices, tc[2].vertex_size,
10454 tc[2].indices, tc[2].attributes);
10455 if (FAILED(hr))
10457 skip("Couldn't initialize test mesh for D3DXMESH_VB_SHARE case."
10458 " Got %lx expected D3D_OK\n", hr);
10459 goto cleanup;
10462 hr = mesh->lpVtbl->CloneMesh(mesh, tc[2].create_options | D3DXMESH_VB_SHARE,
10463 tc[2].new_declaration, test_context->device,
10464 &mesh_clone);
10465 ok(hr == D3DERR_INVALIDCALL, "CloneMesh D3DXMESH_VB_SHARE with new"
10466 " declaration. Got %lx, expected D3DERR_INVALIDCALL\n",
10467 hr);
10468 mesh->lpVtbl->Release(mesh);
10469 mesh = NULL;
10470 mesh_clone = NULL;
10472 cleanup:
10473 if (vertices) mesh->lpVtbl->UnlockVertexBuffer(mesh);
10474 if (mesh) mesh->lpVtbl->Release(mesh);
10475 if (mesh_clone) mesh_clone->lpVtbl->Release(mesh_clone);
10476 free_test_context(test_context);
10479 static void test_valid_mesh(void)
10481 HRESULT hr;
10482 struct test_context *test_context = NULL;
10483 UINT i;
10484 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
10485 const D3DVERTEXELEMENT9 declaration[] =
10487 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
10488 D3DDECL_END()
10490 const unsigned int VERTS_PER_FACE = 3;
10491 /* mesh0 (one face)
10493 * 0--1
10494 * | /
10495 * |/
10498 const D3DXVECTOR3 vertices0[] =
10500 { 0.0f, 3.0f, 0.f},
10501 { 2.0f, 3.0f, 0.f},
10502 { 0.0f, 0.0f, 0.f},
10504 const DWORD indices0[] = {0, 1, 2};
10505 const unsigned int num_vertices0 = ARRAY_SIZE(vertices0);
10506 const unsigned int num_faces0 = ARRAY_SIZE(indices0) / VERTS_PER_FACE;
10507 const DWORD adjacency0[] = {-1, -1, -1};
10508 const HRESULT exp_hr0 = D3D_OK;
10509 /* mesh1 (Simple bow-tie)
10511 * 0--1 1--3
10512 * | / \ |
10513 * |/ \|
10514 * 2 4
10516 const D3DXVECTOR3 vertices1[] =
10518 { 0.0f, 3.0f, 0.f},
10519 { 2.0f, 3.0f, 0.f},
10520 { 0.0f, 0.0f, 0.f},
10522 { 4.0f, 3.0f, 0.f},
10523 { 4.0f, 0.0f, 0.f},
10525 const DWORD indices1[] = {0, 1, 2, 1, 3, 4};
10526 const unsigned int num_vertices1 = ARRAY_SIZE(vertices1);
10527 const unsigned int num_faces1 = ARRAY_SIZE(indices1) / VERTS_PER_FACE;
10528 const DWORD adjacency1[] = {-1, -1, -1, -1, -1, -1};
10529 const HRESULT exp_hr1 = D3DXERR_INVALIDMESH;
10530 /* Common mesh data */
10531 ID3DXMesh *mesh = NULL;
10532 UINT vertex_size = sizeof(D3DXVECTOR3);
10533 ID3DXBuffer *errors_and_warnings = NULL;
10534 struct
10536 const D3DXVECTOR3 *vertices;
10537 const DWORD *indices;
10538 const UINT num_vertices;
10539 const UINT num_faces;
10540 const DWORD *adjacency;
10541 const HRESULT exp_hr;
10543 tc[] =
10546 vertices0,
10547 indices0,
10548 num_vertices0,
10549 num_faces0,
10550 adjacency0,
10551 exp_hr0,
10554 vertices1,
10555 indices1,
10556 num_vertices1,
10557 num_faces1,
10558 adjacency1,
10559 exp_hr1,
10563 test_context = new_test_context();
10564 if (!test_context)
10566 skip("Couldn't create test context\n");
10567 goto cleanup;
10570 for (i = 0; i < ARRAY_SIZE(tc); i++)
10572 hr = init_test_mesh(tc[i].num_faces, tc[i].num_vertices,
10573 options, declaration,
10574 test_context->device, &mesh,
10575 tc[i].vertices, vertex_size,
10576 tc[i].indices, NULL);
10577 if (FAILED(hr))
10579 skip("Couldn't initialize test mesh %d. Got %lx expected D3D_OK\n", i, hr);
10580 goto cleanup;
10583 hr = D3DXValidMesh(mesh, tc[i].adjacency, &errors_and_warnings);
10584 todo_wine ok(hr == tc[i].exp_hr, "Test %u, got unexpected hr %#lx, expected %#lx.\n", i, hr, tc[i].exp_hr);
10586 /* Note errors_and_warnings is deliberately not checked because that
10587 * would require copying wast amounts of the text output. */
10588 if (errors_and_warnings)
10590 ID3DXBuffer_Release(errors_and_warnings);
10591 errors_and_warnings = NULL;
10593 mesh->lpVtbl->Release(mesh);
10594 mesh = NULL;
10597 cleanup:
10598 if (mesh) mesh->lpVtbl->Release(mesh);
10599 free_test_context(test_context);
10602 static void test_optimize_faces(void)
10604 HRESULT hr;
10605 UINT i;
10606 DWORD smallest_face_remap;
10607 /* mesh0
10609 * 0--1
10610 * | /
10611 * |/
10614 const DWORD indices0[] = {0, 1, 2};
10615 const UINT num_faces0 = 1;
10616 const UINT num_vertices0 = 3;
10617 const DWORD exp_face_remap0[] = {0};
10618 /* mesh1
10620 * 0--1 3
10621 * | / /|
10622 * |/ / |
10623 * 2 5--4
10625 const DWORD indices1[] = {0, 1, 2, 3, 4, 5};
10626 const UINT num_faces1 = 2;
10627 const UINT num_vertices1 = 6;
10628 const DWORD exp_face_remap1[] = {1, 0};
10629 /* mesh2
10631 * 0--1
10632 * | /|
10633 * |/ |
10634 * 2--3
10636 const DWORD indices2[] = {0, 1, 2, 1, 3, 2};
10637 const UINT num_faces2 = 2;
10638 const UINT num_vertices2 = 4;
10639 const DWORD exp_face_remap2[] = {1, 0};
10640 /* mesh3
10642 * 0--1
10643 * | /|
10644 * |/ |
10645 * 2--3
10646 * | /|
10647 * |/ |
10648 * 4--5
10650 const DWORD indices3[] = {0, 1, 2, 1, 3, 2, 2, 3, 4, 3, 4, 5};
10651 const UINT num_faces3 = 4;
10652 const UINT num_vertices3 = 6;
10653 const DWORD exp_face_remap3[] = {3, 2, 1, 0};
10654 /* mesh4
10656 * 0--1
10657 * | /|
10658 * |/ |
10659 * 2--3
10660 * | /|
10661 * |/ |
10662 * 4--5
10664 const WORD indices4[] = {0, 1, 2, 1, 3, 2, 2, 3, 4, 3, 4, 5};
10665 const UINT num_faces4 = 4;
10666 const UINT num_vertices4 = 6;
10667 const DWORD exp_face_remap4[] = {3, 2, 1, 0};
10668 /* Test cases are stored in the tc array */
10669 struct
10671 const VOID *indices;
10672 const UINT num_faces;
10673 const UINT num_vertices;
10674 const BOOL indices_are_32bit;
10675 const DWORD *exp_face_remap;
10677 tc[] =
10680 indices0,
10681 num_faces0,
10682 num_vertices0,
10683 TRUE,
10684 exp_face_remap0
10687 indices1,
10688 num_faces1,
10689 num_vertices1,
10690 TRUE,
10691 exp_face_remap1
10694 indices2,
10695 num_faces2,
10696 num_vertices2,
10697 TRUE,
10698 exp_face_remap2
10701 indices3,
10702 num_faces3,
10703 num_vertices3,
10704 TRUE,
10705 exp_face_remap3
10708 indices4,
10709 num_faces4,
10710 num_vertices4,
10711 FALSE,
10712 exp_face_remap4
10716 /* Go through all test cases */
10717 for (i = 0; i < ARRAY_SIZE(tc); i++)
10719 DWORD j;
10720 DWORD *face_remap;
10721 face_remap = calloc(tc[i].num_faces, sizeof(*face_remap));
10723 hr = D3DXOptimizeFaces(tc[i].indices, tc[i].num_faces,
10724 tc[i].num_vertices, tc[i].indices_are_32bit,
10725 face_remap);
10726 ok(hr == D3D_OK, "Test %u, got unexpected hr %#lx.\n", i, hr);
10728 /* Compare face remap with expected face remap */
10729 for (j = 0; j < tc[i].num_faces; j++)
10731 ok(tc[i].exp_face_remap[j] == face_remap[j],
10732 "Test case %d: Got face %ld at %ld, expected %ld\n", i,
10733 face_remap[j], j, tc[i].exp_face_remap[j]);
10736 free(face_remap);
10739 /* face_remap must not be NULL */
10740 hr = D3DXOptimizeFaces(tc[0].indices, tc[0].num_faces,
10741 tc[0].num_vertices, tc[0].indices_are_32bit,
10742 NULL);
10743 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
10745 /* Number of faces must be smaller than 2^15 */
10746 hr = D3DXOptimizeFaces(tc[0].indices, 2 << 15,
10747 tc[0].num_vertices, FALSE,
10748 &smallest_face_remap);
10749 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
10752 static HRESULT clear_normals(ID3DXMesh *mesh)
10754 HRESULT hr;
10755 BYTE *vertices;
10756 size_t normal_size;
10757 DWORD i, num_vertices, vertex_stride;
10758 const D3DXVECTOR4 normal = {NAN, NAN, NAN, NAN};
10759 D3DVERTEXELEMENT9 *normal_declaration = NULL;
10760 D3DVERTEXELEMENT9 declaration[MAX_FVF_DECL_SIZE] = {D3DDECL_END()};
10762 if (FAILED(hr = mesh->lpVtbl->GetDeclaration(mesh, declaration)))
10763 return hr;
10765 for (i = 0; declaration[i].Stream != 0xff; i++)
10767 if (declaration[i].Usage == D3DDECLUSAGE_NORMAL && !declaration[i].UsageIndex)
10769 normal_declaration = &declaration[i];
10770 break;
10774 if (!normal_declaration)
10775 return D3DERR_INVALIDCALL;
10777 if (normal_declaration->Type == D3DDECLTYPE_FLOAT3)
10779 normal_size = sizeof(D3DXVECTOR3);
10781 else if (normal_declaration->Type == D3DDECLTYPE_FLOAT4)
10783 normal_size = sizeof(D3DXVECTOR4);
10785 else
10787 trace("Cannot clear normals\n");
10788 return E_NOTIMPL;
10791 num_vertices = mesh->lpVtbl->GetNumVertices(mesh);
10792 vertex_stride = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
10794 if (FAILED(hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, (void **)&vertices)))
10795 return hr;
10797 vertices += normal_declaration->Offset;
10799 for (i = 0; i < num_vertices; i++, vertices += vertex_stride)
10800 memcpy(vertices, &normal, normal_size);
10802 return mesh->lpVtbl->UnlockVertexBuffer(mesh);
10805 static void compare_normals(unsigned int line, const char *test_name,
10806 ID3DXMesh *mesh, const D3DXVECTOR3 *normals, unsigned int num_normals)
10808 unsigned int i;
10809 BYTE *vertices;
10810 DWORD num_vertices, vertex_stride;
10811 D3DVERTEXELEMENT9 *normal_declaration = NULL;
10812 D3DVERTEXELEMENT9 declaration[MAX_FVF_DECL_SIZE] = {D3DDECL_END()};
10814 if (FAILED(mesh->lpVtbl->GetDeclaration(mesh, declaration)))
10816 ok_(__FILE__, line)(0, "%s: Failed to get declaration\n", test_name);
10817 return;
10820 for (i = 0; declaration[i].Stream != 0xff; i++)
10822 if (declaration[i].Usage == D3DDECLUSAGE_NORMAL && !declaration[i].UsageIndex)
10824 normal_declaration = &declaration[i];
10825 break;
10829 if (!normal_declaration)
10831 ok_(__FILE__, line)(0, "%s: Mesh has no normals\n", test_name);
10832 return;
10835 if (normal_declaration->Type != D3DDECLTYPE_FLOAT3 && normal_declaration->Type != D3DDECLTYPE_FLOAT4)
10837 ok_(__FILE__, line)(0, "%s: Mesh has invalid normals type\n", test_name);
10838 return;
10841 num_vertices = mesh->lpVtbl->GetNumVertices(mesh);
10842 vertex_stride = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
10844 ok_(__FILE__, line)(num_vertices == num_normals, "%s: Expected %u vertices, got %lu\n", test_name,
10845 num_normals, num_vertices);
10847 if (FAILED(mesh->lpVtbl->LockVertexBuffer(mesh, 0, (void **)&vertices)))
10849 ok_(__FILE__, line)(0, "%s: Failed to compare normals\n", test_name);
10850 return;
10853 vertices += normal_declaration->Offset;
10855 for (i = 0; i < min(num_vertices, num_normals); i++, vertices += vertex_stride)
10857 if (normal_declaration->Type == D3DDECLTYPE_FLOAT3)
10859 const D3DXVECTOR3 *n = (D3DXVECTOR3 *)vertices;
10860 ok_(__FILE__, line)(compare_vec3(*n, normals[i]),
10861 "%s: normal %2u, expected (%f, %f, %f), got (%f, %f, %f)\n",
10862 test_name, i, normals[i].x, normals[i].y, normals[i].z, n->x, n->y, n->z);
10864 else
10866 const D3DXVECTOR4 *n = (D3DXVECTOR4 *)vertices;
10867 const D3DXVECTOR4 normal = {normals[i].x, normals[i].y, normals[i].z, 1.0f};
10868 ok_(__FILE__, line)(compare_vec4(*n, normal),
10869 "%s: normal %2u, expected (%f, %f, %f, %f), got (%f, %f, %f, %f)\n",
10870 test_name, i, normals[i].x, normals[i].y, normals[i].z, 1.0f,
10871 n->x, n->y, n->z, n->w);
10875 mesh->lpVtbl->UnlockVertexBuffer(mesh);
10878 static HRESULT compute_normals_D3DXComputeNormals(ID3DXMesh *mesh, const DWORD *adjacency)
10880 return D3DXComputeNormals((ID3DXBaseMesh *)mesh, adjacency);
10883 static HRESULT compute_normals_D3DXComputeTangentFrameEx(ID3DXMesh *mesh, const DWORD *adjacency)
10885 return D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
10886 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS,
10887 adjacency, -1.01f, -0.01f, -1.01f, NULL, NULL);
10890 static void test_compute_normals(void)
10892 HRESULT hr;
10893 ULONG refcount;
10894 ID3DXMesh *mesh, *cloned_mesh;
10895 ID3DXBuffer *adjacency;
10896 IDirect3DDevice9 *device;
10897 struct test_context *test_context;
10898 unsigned int i;
10900 static const struct compute_normals_func
10902 const char *name;
10903 HRESULT (*apply)(ID3DXMesh *mesh, const DWORD *adjacency);
10905 compute_normals_funcs[] =
10907 {"D3DXComputeNormals", compute_normals_D3DXComputeNormals },
10908 {"D3DXComputeTangentFrameEx", compute_normals_D3DXComputeTangentFrameEx}
10911 static const D3DXVECTOR3 box_normals[24] =
10913 {-1.0f, 0.0f, 0.0f}, {-1.0f, 0.0f, 0.0f}, {-1.0f, 0.0f, 0.0f}, {-1.0f, 0.0f, 0.0f},
10914 { 0.0f, 1.0f, 0.0f}, { 0.0f, 1.0f, 0.0f}, { 0.0f, 1.0f, 0.0f}, { 0.0f, 1.0f, 0.0f},
10915 { 1.0f, 0.0f, 0.0f}, { 1.0f, 0.0f, 0.0f}, { 1.0f, 0.0f, 0.0f}, { 1.0f, 0.0f, 0.0f},
10916 { 0.0f,-1.0f, 0.0f}, { 0.0f,-1.0f, 0.0f}, { 0.0f,-1.0f, 0.0f}, { 0.0f,-1.0f, 0.0f},
10917 { 0.0f, 0.0f, 1.0f}, { 0.0f, 0.0f, 1.0f}, { 0.0f, 0.0f, 1.0f}, { 0.0f, 0.0f, 1.0f},
10918 { 0.0f, 0.0f,-1.0f}, { 0.0f, 0.0f,-1.0f}, { 0.0f, 0.0f,-1.0f}, { 0.0f, 0.0f,-1.0f}
10920 const float box_normal_component = 1.0f / sqrtf(3.0f);
10921 const D3DXVECTOR3 box_normals_adjacency[24] =
10923 {-box_normal_component, -box_normal_component, -box_normal_component},
10924 {-box_normal_component, -box_normal_component, box_normal_component},
10925 {-box_normal_component, box_normal_component, box_normal_component},
10926 {-box_normal_component, box_normal_component, -box_normal_component},
10927 {-box_normal_component, box_normal_component, -box_normal_component},
10928 {-box_normal_component, box_normal_component, box_normal_component},
10929 { box_normal_component, box_normal_component, box_normal_component},
10930 { box_normal_component, box_normal_component, -box_normal_component},
10931 { box_normal_component, box_normal_component, -box_normal_component},
10932 { box_normal_component, box_normal_component, box_normal_component},
10933 { box_normal_component, -box_normal_component, box_normal_component},
10934 { box_normal_component, -box_normal_component, -box_normal_component},
10935 {-box_normal_component, -box_normal_component, box_normal_component},
10936 {-box_normal_component, -box_normal_component, -box_normal_component},
10937 { box_normal_component, -box_normal_component, -box_normal_component},
10938 { box_normal_component, -box_normal_component, box_normal_component},
10939 {-box_normal_component, -box_normal_component, box_normal_component},
10940 { box_normal_component, -box_normal_component, box_normal_component},
10941 { box_normal_component, box_normal_component, box_normal_component},
10942 {-box_normal_component, box_normal_component, box_normal_component},
10943 {-box_normal_component, -box_normal_component, -box_normal_component},
10944 {-box_normal_component, box_normal_component, -box_normal_component},
10945 { box_normal_component, box_normal_component, -box_normal_component},
10946 { box_normal_component, -box_normal_component, -box_normal_component}
10948 static const D3DXVECTOR3 box_normals_adjacency_area[24] =
10950 {-0.666667f, -0.333333f, -0.666667f}, {-0.333333f, -0.666667f, 0.666667f},
10951 {-0.816496f, 0.408248f, 0.408248f}, {-0.408248f, 0.816496f, -0.408248f},
10952 {-0.408248f, 0.816496f, -0.408248f}, {-0.816496f, 0.408248f, 0.408248f},
10953 { 0.333333f, 0.666667f, 0.666667f}, { 0.666667f, 0.333333f, -0.666667f},
10954 { 0.666667f, 0.333333f, -0.666667f}, { 0.333333f, 0.666667f, 0.666667f},
10955 { 0.816496f, -0.408248f, 0.408248f}, { 0.408248f, -0.816496f, -0.408248f},
10956 {-0.333333f, -0.666667f, 0.666667f}, {-0.666667f, -0.333333f, -0.666667f},
10957 { 0.408248f, -0.816496f, -0.408248f}, { 0.816496f, -0.408248f, 0.408248f},
10958 {-0.333333f, -0.666667f, 0.666667f}, { 0.816497f, -0.408248f, 0.408248f},
10959 { 0.333333f, 0.666667f, 0.666667f}, {-0.816497f, 0.408248f, 0.408248f},
10960 {-0.666667f, -0.333333f, -0.666667f}, {-0.408248f, 0.816497f, -0.408248f},
10961 { 0.666667f, 0.333333f, -0.666667f}, { 0.408248f, -0.816496f, -0.408248f}
10963 static const D3DXVECTOR3 box_normals_position1f[24] = {{0}};
10964 static const D3DXVECTOR3 box_normals_position2f[24] =
10966 {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f},
10967 {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, 1.0f},
10968 {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, -1.0f},
10969 {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f},
10970 {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, -1.0f},
10971 {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f},
10972 {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f},
10973 {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, -1.0f}
10976 static const D3DXVECTOR3 sphere_normals[22] =
10978 { 0.000000f, -0.000000f, 1.000000f}, { 0.000000f, 0.582244f, 0.813014f},
10979 { 0.582244f, -0.000000f, 0.813014f}, {-0.000000f, -0.582244f, 0.813014f},
10980 {-0.582244f, 0.000000f, 0.813014f}, {-0.000000f, 0.890608f, 0.454772f},
10981 { 0.890608f, 0.000000f, 0.454772f}, { 0.000000f, -0.890608f, 0.454772f},
10982 {-0.890608f, -0.000000f, 0.454772f}, { 0.000000f, 1.000000f, -0.000000f},
10983 { 1.000000f, -0.000000f, -0.000000f}, {-0.000000f, -1.000000f, -0.000000f},
10984 {-1.000000f, 0.000000f, -0.000000f}, { 0.000000f, 0.890608f, -0.454773f},
10985 { 0.890608f, -0.000000f, -0.454772f}, {-0.000000f, -0.890608f, -0.454773f},
10986 {-0.890608f, 0.000000f, -0.454773f}, { 0.000000f, 0.582244f, -0.813015f},
10987 { 0.582244f, -0.000000f, -0.813015f}, { 0.000000f, -0.582244f, -0.813015f},
10988 {-0.582243f, 0.000000f, -0.813015f}, { 0.000000f, 0.000000f, -1.000000f}
10990 static const D3DXVECTOR3 sphere_normals_area[22] =
10992 { 0.000000f, -0.000000f, 1.000000f}, {-0.215311f, 0.554931f, 0.803550f},
10993 { 0.554931f, 0.215311f, 0.803550f}, { 0.215311f, -0.554931f, 0.803550f},
10994 {-0.554931f, -0.215311f, 0.803550f}, {-0.126638f, 0.872121f, 0.472618f},
10995 { 0.872121f, 0.126638f, 0.472618f}, { 0.126638f, -0.872121f, 0.472618f},
10996 {-0.872121f, -0.126637f, 0.472618f}, { 0.000000f, 1.000000f, -0.000000f},
10997 { 1.000000f, -0.000000f, -0.000000f}, {-0.000000f, -1.000000f, -0.000000f},
10998 {-1.000000f, 0.000000f, -0.000000f}, { 0.126638f, 0.872121f, -0.472618f},
10999 { 0.872121f, -0.126638f, -0.472618f}, {-0.126638f, -0.872121f, -0.472618f},
11000 {-0.872121f, 0.126638f, -0.472618f}, { 0.215311f, 0.554931f, -0.803550f},
11001 { 0.554931f, -0.215311f, -0.803550f}, {-0.215311f, -0.554931f, -0.803550f},
11002 {-0.554931f, 0.215311f, -0.803550f}, { 0.000000f, 0.000000f, -1.000000f}
11004 static const D3DXVECTOR3 sphere_normals_equal[22] =
11006 { 0.000000f, -0.000000f, 1.000000f}, {-0.134974f, 0.522078f, 0.842150f},
11007 { 0.522078f, 0.134974f, 0.842150f}, { 0.134974f, -0.522078f, 0.842150f},
11008 {-0.522078f, -0.134974f, 0.842150f}, {-0.026367f, 0.857121f, 0.514440f},
11009 { 0.857121f, 0.026367f, 0.514440f}, { 0.026367f, -0.857121f, 0.514440f},
11010 {-0.857121f, -0.026367f, 0.514440f}, { 0.000000f, 1.000000f, -0.000000f},
11011 { 1.000000f, -0.000000f, -0.000000f}, {-0.000000f, -1.000000f, -0.000000f},
11012 {-1.000000f, 0.000000f, -0.000000f}, { 0.026367f, 0.857121f, -0.514440f},
11013 { 0.857121f, -0.026367f, -0.514440f}, {-0.026367f, -0.857121f, -0.514440f},
11014 {-0.857121f, 0.026367f, -0.514440f}, { 0.134975f, 0.522078f, -0.842150f},
11015 { 0.522078f, -0.134975f, -0.842150f}, {-0.134974f, -0.522078f, -0.842150f},
11016 {-0.522078f, 0.134974f, -0.842150f}, { 0.000000f, 0.000000f, -1.000000f}
11019 static const D3DVERTEXELEMENT9 position3f_normal1f_declaration[] =
11021 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
11022 {0, sizeof(D3DXVECTOR3), D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
11023 D3DDECL_END()
11025 static const D3DVERTEXELEMENT9 position3f_normal2f_declaration[] =
11027 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
11028 {0, sizeof(D3DXVECTOR3), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
11029 D3DDECL_END()
11031 static const D3DVERTEXELEMENT9 normal4f_position3f_declaration[] =
11033 {0, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
11034 {0, sizeof(D3DXVECTOR4), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
11035 D3DDECL_END()
11037 static const D3DVERTEXELEMENT9 position1f_normal3f_declaration[] =
11039 {0, 0, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
11040 {0, sizeof(float), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
11041 D3DDECL_END()
11043 static const D3DVERTEXELEMENT9 position2f_normal3f_declaration[] =
11045 {0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
11046 {0, sizeof(D3DXVECTOR2), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
11047 D3DDECL_END()
11049 static const D3DVERTEXELEMENT9 position4f_normal3f_declaration[] =
11051 {0, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
11052 {0, sizeof(D3DXVECTOR4), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
11053 D3DDECL_END()
11056 for (i = 0; i < ARRAY_SIZE(compute_normals_funcs); i++)
11058 hr = compute_normals_funcs[i].apply(NULL, NULL);
11059 ok(hr == D3DERR_INVALIDCALL, "%s returned %#lx, expected D3DERR_INVALIDCALL\n", compute_normals_funcs[i].name, hr);
11062 if (!(test_context = new_test_context()))
11064 skip("Couldn't create test context\n");
11065 return;
11067 device = test_context->device;
11069 hr = D3DXCreateBox(device, 1.0f, 1.0f, 1.0f, &mesh, &adjacency);
11070 ok(SUCCEEDED(hr), "D3DXCreateBox failed %#lx\n", hr);
11072 /* Check wrong input */
11073 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
11074 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE, NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
11075 todo_wine ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#lx, expected D3DERR_INVALIDCALL\n", hr);
11077 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DDECLUSAGE_NORMAL, 0,
11078 D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_BY_AREA | D3DXTANGENT_WEIGHT_EQUAL,
11079 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
11080 ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#lx, expected D3DERR_INVALIDCALL\n", hr);
11082 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
11083 D3DDECLUSAGE_NORMAL, 0, 0, NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
11084 todo_wine ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#lx, expected D3DERR_INVALIDCALL\n", hr);
11086 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
11087 D3DDECLUSAGE_NORMAL, 1, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS,
11088 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
11089 ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#lx, expected D3DERR_INVALIDCALL\n", hr);
11091 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
11092 D3DX_DEFAULT, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS,
11093 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
11094 ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#lx, expected D3DERR_INVALIDCALL\n", hr);
11096 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
11097 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_CALCULATE_NORMALS,
11098 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
11099 todo_wine ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#lx, expected D3DERR_INVALIDCALL\n", hr);
11101 for (i = 0; i < ARRAY_SIZE(compute_normals_funcs); i++)
11103 const struct compute_normals_func *func = &compute_normals_funcs[i];
11105 /* Mesh without normals */
11106 hr = mesh->lpVtbl->CloneMeshFVF(mesh, 0, D3DFVF_XYZ, device, &cloned_mesh);
11107 ok(SUCCEEDED(hr), "CloneMeshFVF failed %#lx\n", hr);
11109 hr = func->apply(cloned_mesh, NULL);
11110 ok(hr == D3DERR_INVALIDCALL, "%s returned %#lx, expected D3DERR_INVALIDCALL\n", func->name, hr);
11112 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh);
11113 ok(!refcount, "Mesh has %lu references left\n", refcount);
11115 /* Mesh without positions */
11116 hr = mesh->lpVtbl->CloneMeshFVF(mesh, 0, D3DFVF_NORMAL, device, &cloned_mesh);
11117 ok(SUCCEEDED(hr), "CloneMeshFVF failed %#lx\n", hr);
11119 hr = func->apply(cloned_mesh, NULL);
11120 ok(hr == D3DERR_INVALIDCALL, "%s returned %#lx, expected D3DERR_INVALIDCALL\n", func->name, hr);
11122 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh);
11123 ok(!refcount, "Mesh has %lu references left\n", refcount);
11125 /* Mesh with D3DDECLTYPE_FLOAT1 normals */
11126 hr = mesh->lpVtbl->CloneMesh(mesh, 0, position3f_normal1f_declaration, device, &cloned_mesh);
11127 ok(SUCCEEDED(hr), "CloneMesh failed %#lx\n", hr);
11129 hr = func->apply(cloned_mesh, NULL);
11130 ok(hr == D3DERR_INVALIDCALL, "%s returned %#lx, expected D3DERR_INVALIDCALL\n", func->name, hr);
11132 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh);
11133 ok(!refcount, "Mesh has %lu references left\n", refcount);
11135 /* Mesh with D3DDECLTYPE_FLOAT2 normals */
11136 hr = mesh->lpVtbl->CloneMesh(mesh, 0, position3f_normal2f_declaration, device, &cloned_mesh);
11137 ok(SUCCEEDED(hr), "CloneMesh failed %#lx\n", hr);
11139 hr = func->apply(cloned_mesh, NULL);
11140 ok(hr == D3DERR_INVALIDCALL, "%s returned %#lx, expected D3DERR_INVALIDCALL\n", func->name, hr);
11142 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh);
11143 ok(!refcount, "Mesh has %lu references left\n", refcount);
11145 /* Mesh without adjacency data */
11146 hr = clear_normals(mesh);
11147 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#lx\n", hr);
11149 hr = func->apply(mesh, NULL);
11150 ok(hr == D3D_OK, "%s returned %#lx, expected D3D_OK\n", func->name, hr);
11152 compare_normals(__LINE__, func->name, mesh, box_normals, ARRAY_SIZE(box_normals));
11154 /* Mesh with adjacency data */
11155 hr = clear_normals(mesh);
11156 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#lx\n", hr);
11158 hr = func->apply(mesh, ID3DXBuffer_GetBufferPointer(adjacency));
11159 ok(hr == D3D_OK, "%s returned %#lx, expected D3D_OK\n", func->name, hr);
11161 compare_normals(__LINE__, func->name, mesh, box_normals_adjacency, ARRAY_SIZE(box_normals_adjacency));
11163 /* Mesh with custom vertex format, D3DDECLTYPE_FLOAT4 normals and adjacency */
11164 hr = mesh->lpVtbl->CloneMesh(mesh, 0, normal4f_position3f_declaration, device, &cloned_mesh);
11165 ok(SUCCEEDED(hr), "CloneMesh failed %#lx\n", hr);
11167 hr = clear_normals(cloned_mesh);
11168 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#lx\n", hr);
11170 hr = func->apply(cloned_mesh, ID3DXBuffer_GetBufferPointer(adjacency));
11171 ok(hr == D3D_OK, "%s returned %#lx, expected D3D_OK\n", func->name, hr);
11173 compare_normals(__LINE__, func->name, cloned_mesh, box_normals_adjacency, ARRAY_SIZE(box_normals_adjacency));
11175 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh);
11176 ok(!refcount, "Mesh has %lu references left\n", refcount);
11178 /* Mesh with D3DDECLTYPE_FLOAT1 positions and D3DDECLTYPE_FLOAT3 normals */
11179 hr = mesh->lpVtbl->CloneMesh(mesh, 0, position1f_normal3f_declaration, device, &cloned_mesh);
11180 ok(SUCCEEDED(hr), "CloneMesh failed %#lx\n", hr);
11182 hr = clear_normals(cloned_mesh);
11183 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#lx\n", hr);
11185 hr = func->apply(cloned_mesh, ID3DXBuffer_GetBufferPointer(adjacency));
11186 ok(hr == D3D_OK, "%s returned %#lx, expected D3D_OK\n", func->name, hr);
11188 compare_normals(__LINE__, func->name, cloned_mesh, box_normals_position1f, ARRAY_SIZE(box_normals_position1f));
11190 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh);
11191 ok(!refcount, "Mesh has %lu references left\n", refcount);
11193 /* Mesh with D3DDECLTYPE_FLOAT2 positions and D3DDECLTYPE_FLOAT3 normals */
11194 hr = mesh->lpVtbl->CloneMesh(mesh, 0, position2f_normal3f_declaration, device, &cloned_mesh);
11195 ok(SUCCEEDED(hr), "CloneMesh failed %#lx\n", hr);
11197 hr = clear_normals(cloned_mesh);
11198 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#lx\n", hr);
11200 hr = func->apply(cloned_mesh, ID3DXBuffer_GetBufferPointer(adjacency));
11201 ok(hr == D3D_OK, "%s returned %#lx, expected D3D_OK\n", func->name, hr);
11203 compare_normals(__LINE__, func->name, cloned_mesh, box_normals_position2f, ARRAY_SIZE(box_normals_position2f));
11205 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh);
11206 ok(!refcount, "Mesh has %lu references left\n", refcount);
11208 /* Mesh with D3DDECLTYPE_FLOAT4 positions and D3DDECLTYPE_FLOAT3 normals */
11209 hr = mesh->lpVtbl->CloneMesh(mesh, 0, position4f_normal3f_declaration, device, &cloned_mesh);
11210 ok(SUCCEEDED(hr), "CloneMesh failed %#lx\n", hr);
11212 hr = clear_normals(cloned_mesh);
11213 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#lx\n", hr);
11215 hr = func->apply(cloned_mesh, ID3DXBuffer_GetBufferPointer(adjacency));
11216 ok(hr == D3D_OK, "%s returned %#lx, expected D3D_OK\n", func->name, hr);
11218 compare_normals(__LINE__, func->name, cloned_mesh, box_normals_adjacency, ARRAY_SIZE(box_normals_adjacency));
11220 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh);
11221 ok(!refcount, "Mesh has %lu references left\n", refcount);
11224 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
11225 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_BY_AREA,
11226 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
11227 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#lx, expected D3D_OK\n", hr);
11229 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, box_normals, ARRAY_SIZE(box_normals));
11231 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
11232 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_BY_AREA,
11233 ID3DXBuffer_GetBufferPointer(adjacency), -1.01f, -0.01f, -1.01f, NULL, NULL);
11234 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#lx, expected D3D_OK\n", hr);
11236 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, box_normals_adjacency_area, ARRAY_SIZE(box_normals_adjacency_area));
11238 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
11239 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_EQUAL,
11240 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
11241 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#lx, expected D3D_OK\n", hr);
11243 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, box_normals, ARRAY_SIZE(box_normals));
11245 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
11246 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_EQUAL,
11247 ID3DXBuffer_GetBufferPointer(adjacency), -1.01f, -0.01f, -1.01f, NULL, NULL);
11248 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#lx, expected D3D_OK\n", hr);
11250 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, box_normals_adjacency_area, ARRAY_SIZE(box_normals_adjacency_area));
11252 refcount = mesh->lpVtbl->Release(mesh);
11253 ok(!refcount, "Mesh has %lu references left\n", refcount);
11254 refcount = ID3DXBuffer_Release(adjacency);
11255 ok(!refcount, "Buffer has %lu references left\n", refcount);
11257 hr = D3DXCreateSphere(device, 1.0f, 4, 6, &mesh, &adjacency);
11258 ok(SUCCEEDED(hr), "D3DXCreateSphere failed %#lx\n", hr);
11260 for (i = 0; i < ARRAY_SIZE(compute_normals_funcs); i++)
11262 const struct compute_normals_func *func = &compute_normals_funcs[i];
11264 /* Sphere without adjacency data */
11265 hr = clear_normals(mesh);
11266 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#lx\n", hr);
11268 hr = func->apply(mesh, NULL);
11269 ok(hr == D3D_OK, "%s returned %#lx, expected D3D_OK\n", func->name, hr);
11271 compare_normals(__LINE__, func->name, mesh, sphere_normals, ARRAY_SIZE(sphere_normals));
11273 /* Sphere with adjacency data */
11274 hr = clear_normals(mesh);
11275 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#lx\n", hr);
11277 hr = func->apply(mesh, ID3DXBuffer_GetBufferPointer(adjacency));
11278 ok(hr == D3D_OK, "%s returned %#lx, expected D3D_OK\n", func->name, hr);
11280 compare_normals(__LINE__, func->name, mesh, sphere_normals, ARRAY_SIZE(sphere_normals));
11283 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
11284 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_BY_AREA,
11285 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
11286 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#lx, expected D3D_OK\n", hr);
11288 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, sphere_normals_area, ARRAY_SIZE(sphere_normals_area));
11290 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
11291 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_BY_AREA,
11292 ID3DXBuffer_GetBufferPointer(adjacency), -1.01f, -0.01f, -1.01f, NULL, NULL);
11293 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#lx, expected D3D_OK\n", hr);
11295 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, sphere_normals_area, ARRAY_SIZE(sphere_normals_area));
11297 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
11298 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_EQUAL,
11299 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
11300 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#lx, expected D3D_OK\n", hr);
11302 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, sphere_normals_equal, ARRAY_SIZE(sphere_normals_equal));
11304 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
11305 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_EQUAL,
11306 ID3DXBuffer_GetBufferPointer(adjacency), -1.01f, -0.01f, -1.01f, NULL, NULL);
11307 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#lx, expected D3D_OK\n", hr);
11309 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, sphere_normals_equal, ARRAY_SIZE(sphere_normals_equal));
11311 refcount = mesh->lpVtbl->Release(mesh);
11312 ok(!refcount, "Mesh has %lu references left\n", refcount);
11313 refcount = ID3DXBuffer_Release(adjacency);
11314 ok(!refcount, "Buffer has %lu references left\n", refcount);
11316 free_test_context(test_context);
11319 static void D3DXCreateAnimationControllerTest(void)
11321 HRESULT hr;
11322 ID3DXAnimationController *animation;
11323 UINT value;
11325 hr = D3DXCreateAnimationController(0, 0, 0, 0, NULL);
11326 ok(hr == D3D_OK, "Got unexpected hr returned %#lx.\n", hr);
11328 animation = (void*)0xdeadbeef;
11329 hr = D3DXCreateAnimationController(0, 1, 1, 1, &animation);
11330 ok(hr == D3D_OK, "Got unexpected hr returned %#lx.\n", hr);
11331 ok(animation == (void*)0xdeadbeef, "Got unexpected animation %p.\n", animation);
11333 animation = (void*)0xdeadbeef;
11334 hr = D3DXCreateAnimationController(1, 0, 1, 1, &animation);
11335 ok(hr == D3D_OK, "Got unexpected hr returned %#lx.\n", hr);
11336 ok(animation == (void*)0xdeadbeef, "Got unexpected animation %p.\n", animation);
11338 animation = (void*)0xdeadbeef;
11339 hr = D3DXCreateAnimationController(1, 1, 0, 1, &animation);
11340 ok(hr == D3D_OK, "Got unexpected hr returned %#lx.\n", hr);
11341 ok(animation == (void*)0xdeadbeef, "Got unexpected animation %p.\n", animation);
11343 animation = (void*)0xdeadbeef;
11344 hr = D3DXCreateAnimationController(1, 1, 1, 0, &animation);
11345 ok(hr == D3D_OK, "Got unexpected hr returned %#lx.\n", hr);
11346 ok(animation == (void*)0xdeadbeef, "Got unexpected animation %p.\n", animation);
11348 hr = D3DXCreateAnimationController(1, 1, 1, 1, &animation);
11349 ok(hr == D3D_OK, "Got unexpected hr returned %#lx.\n", hr);
11351 value = animation->lpVtbl->GetMaxNumAnimationOutputs(animation);
11352 ok(value == 1, "Got unexpected value %u.\n", value);
11354 value = animation->lpVtbl->GetMaxNumAnimationSets(animation);
11355 ok(value == 1, "Got unexpected value %u.\n", value);
11357 value = animation->lpVtbl->GetMaxNumTracks(animation);
11358 ok(value == 1, "Got unexpected value %u.\n", value);
11360 value = animation->lpVtbl->GetMaxNumEvents(animation);
11361 ok(value == 1, "Got unexpected value %u.\n", value);
11363 animation->lpVtbl->Release(animation);
11365 hr = D3DXCreateAnimationController(100, 101, 102, 103, &animation);
11366 ok(hr == D3D_OK, "Got unexpected hr returned %#lx.\n", hr);
11368 value = animation->lpVtbl->GetMaxNumAnimationOutputs(animation);
11369 ok(value == 100, "Got unexpected value %u.\n", value);
11371 value = animation->lpVtbl->GetMaxNumAnimationSets(animation);
11372 ok(value == 101, "Got unexpected value %u.\n", value);
11374 value = animation->lpVtbl->GetMaxNumTracks(animation);
11375 ok(value == 102, "Got unexpected value %u.\n", value);
11377 value = animation->lpVtbl->GetMaxNumEvents(animation);
11378 ok(value == 103, "Got unexpected value %u.\n", value);
11380 animation->lpVtbl->Release(animation);
11383 static void D3DXCreateKeyframedAnimationSetTest(void)
11385 ID3DXKeyframedAnimationSet *set;
11386 D3DXPLAYBACK_TYPE type;
11387 unsigned int count;
11388 const char *name;
11389 HRESULT hr;
11391 hr = D3DXCreateKeyframedAnimationSet("wine_bottle", 5.0, D3DXPLAY_LOOP, 0, 0, NULL, &set);
11392 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
11394 hr = D3DXCreateKeyframedAnimationSet("wine_bottle", 5.0, D3DXPLAY_LOOP, 10, 0, NULL, &set);
11395 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
11397 name = set->lpVtbl->GetName(set);
11398 ok(!strcmp(name, "wine_bottle"), "Got unexpected name %s.\n", debugstr_a(name));
11400 type = set->lpVtbl->GetPlaybackType(set);
11401 ok(type == D3DXPLAY_LOOP, "Got unexpected value %u.\n", type);
11403 count = set->lpVtbl->GetNumAnimations(set);
11404 ok(!count, "Got unexpected value %u.\n", count);
11406 set->lpVtbl->Release(set);
11409 static void test_D3DXFrameFind(void)
11411 static char n1[] = "name1";
11412 static char n2[] = "name2";
11413 static char n3[] = "name3";
11414 static char n4[] = "name4";
11415 static char n5[] = "name5";
11416 static char n6[] = "name6";
11417 static char N1[] = "Name1";
11418 D3DXFRAME root, sibling, sibling2, child, *ret;
11419 D3DXFRAME child2, child3;
11421 ret = D3DXFrameFind(NULL, NULL);
11422 ok(ret == NULL, "Unexpected frame, %p.\n", ret);
11424 ret = D3DXFrameFind(NULL, "test");
11425 ok(ret == NULL, "Unexpected frame, %p.\n", ret);
11427 memset(&root, 0, sizeof(root));
11429 ret = D3DXFrameFind(&root, NULL);
11430 ok(ret == &root, "Unexpected frame, %p.\n", ret);
11432 root.Name = n1;
11433 ret = D3DXFrameFind(&root, NULL);
11434 ok(ret == NULL, "Unexpected frame, %p.\n", ret);
11436 ret = D3DXFrameFind(&root, n1);
11437 ok(ret == &root, "Unexpected frame, %p.\n", ret);
11439 ret = D3DXFrameFind(&root, N1);
11440 ok(ret == NULL, "Unexpected frame, %p.\n", ret);
11442 /* Test siblings order traversal. */
11443 memset(&sibling, 0, sizeof(sibling));
11444 sibling.Name = n2;
11445 root.pFrameSibling = &sibling;
11446 ret = D3DXFrameFind(&root, n2);
11447 ok(ret == &sibling, "Unexpected frame, %p.\n", ret);
11449 memset(&sibling2, 0, sizeof(sibling2));
11450 sibling2.Name = n2;
11451 sibling.pFrameSibling = &sibling2;
11452 ret = D3DXFrameFind(&root, n2);
11453 ok(ret == &sibling, "Unexpected frame, %p.\n", ret);
11455 sibling2.Name = n3;
11456 ret = D3DXFrameFind(&root, n3);
11457 ok(ret == &sibling2, "Unexpected frame, %p.\n", ret);
11459 /* Siblings first. */
11460 memset(&child, 0, sizeof(child));
11461 child.Name = n2;
11462 root.pFrameFirstChild = &child;
11463 ret = D3DXFrameFind(&root, n2);
11464 ok(ret == &sibling, "Unexpected frame, %p.\n", ret);
11466 child.Name = n4;
11467 ret = D3DXFrameFind(&root, n4);
11468 ok(ret == &child, "Unexpected frame, %p.\n", ret);
11470 /* Link a grandchild and another one for sibling. */
11471 memset(&child2, 0, sizeof(child2));
11472 memset(&child3, 0, sizeof(child3));
11473 child2.Name = child3.Name = n5;
11474 sibling.pFrameFirstChild = &child2;
11475 child.pFrameFirstChild = &child3;
11476 ret = D3DXFrameFind(&root, n5);
11477 ok(ret == &child2, "Unexpected frame, %p.\n", ret);
11479 child3.Name = n6;
11480 ret = D3DXFrameFind(&root, n6);
11481 ok(ret == &child3, "Unexpected frame, %p.\n", ret);
11484 static ID3DXFileData *get_mesh_data(const void *memory, SIZE_T length)
11486 ID3DXFileData *file_data, *ret = NULL;
11487 ID3DXFileEnumObject *enum_obj = NULL;
11488 D3DXF_FILELOADMEMORY source;
11489 ID3DXFile *file;
11490 SIZE_T i, count;
11491 GUID guid;
11493 if (FAILED(D3DXFileCreate(&file)))
11494 return NULL;
11496 if (FAILED(file->lpVtbl->RegisterTemplates(file, D3DRM_XTEMPLATES, D3DRM_XTEMPLATE_BYTES)))
11497 goto cleanup;
11499 source.lpMemory = memory;
11500 source.dSize = length;
11501 if (FAILED(file->lpVtbl->CreateEnumObject(file, &source, D3DXF_FILELOAD_FROMMEMORY, &enum_obj)))
11502 goto cleanup;
11504 if (FAILED(enum_obj->lpVtbl->GetChildren(enum_obj, &count)))
11505 goto cleanup;
11507 for (i = 0; i < count; ++i)
11509 if (FAILED(enum_obj->lpVtbl->GetChild(enum_obj, i, &file_data)))
11510 goto cleanup;
11512 if (SUCCEEDED(file_data->lpVtbl->GetType(file_data, &guid))
11513 && IsEqualGUID(&guid, &TID_D3DRMMesh))
11515 ret = file_data;
11516 break;
11518 else
11520 file_data->lpVtbl->Release(file_data);
11524 cleanup:
11525 if (enum_obj)
11526 enum_obj->lpVtbl->Release(enum_obj);
11527 file->lpVtbl->Release(file);
11529 return ret;
11532 static void test_load_skin_mesh_from_xof(void)
11534 static const char simple_xfile[] =
11535 "xof 0303txt 0032"
11536 "Mesh {"
11537 "3;"
11538 "0.0; 0.0; 0.0;,"
11539 "0.0; 1.0; 0.0;,"
11540 "1.0; 1.0; 0.0;;"
11541 "1;"
11542 "3; 0, 1, 2;;"
11543 "}";
11544 static const char simple_xfile_empty[] =
11545 "xof 0303txt 0032"
11546 "Mesh { 0;; 0;; }";
11547 static const D3DVERTEXELEMENT9 expected_declaration[] =
11549 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
11550 D3DDECL_END(),
11552 D3DVERTEXELEMENT9 declaration[MAX_FVF_DECL_SIZE];
11553 ID3DXBuffer *adjacency, *materials, *effects;
11554 DWORD max_influences[3], count, fvf;
11555 D3DPRESENT_PARAMETERS d3dpp;
11556 IDirect3DDevice9 *device;
11557 ID3DXSkinInfo *skin_info;
11558 ID3DXFileData *file_data;
11559 const char *bone_name;
11560 D3DXMATRIX *matrix;
11561 float influence;
11562 ID3DXMesh *mesh;
11563 IDirect3D9 *d3d;
11564 ULONG refcount;
11565 HRESULT hr;
11566 HWND hwnd;
11568 if (!(hwnd = CreateWindowA("static", "d3dx9_test", WS_OVERLAPPEDWINDOW, 0, 0,
11569 640, 480, NULL, NULL, NULL, NULL)))
11571 skip("Failed to create application window.\n");
11572 return;
11575 d3d = Direct3DCreate9(D3D_SDK_VERSION);
11576 if (!d3d)
11578 skip("Failed to create d3d object.\n");
11579 DestroyWindow(hwnd);
11580 return;
11583 memset(&d3dpp, 0, sizeof(d3dpp));
11584 d3dpp.Windowed = TRUE;
11585 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
11587 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
11588 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device);
11589 IDirect3D9_Release(d3d);
11590 if (FAILED(hr))
11592 skip("Failed to create device, hr %#lx.\n", hr);
11593 DestroyWindow(hwnd);
11594 return;
11597 file_data = get_mesh_data(simple_xfile, sizeof(simple_xfile) - 1);
11598 ok(!!file_data, "Failed to load mesh data.\n");
11600 adjacency = materials = effects = (void *)0xdeadbeef;
11601 count = ~0u;
11602 skin_info = (void *)0xdeadbeef;
11603 mesh = (void *)0xdeadbeef;
11605 hr = D3DXLoadSkinMeshFromXof(file_data, 0, device, &adjacency, &materials, &effects, &count,
11606 &skin_info, &mesh);
11607 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
11608 ok(!!adjacency, "Got unexpected value %p.\n", adjacency);
11609 ok(!materials, "Got unexpected value %p.\n", materials);
11610 ok(!effects, "Got unexpected value %p.\n", effects);
11611 ok(!count, "Got unexpected value %lu.\n", count);
11612 ok(!!skin_info, "Got unexpected value %p.\n", skin_info);
11613 ok(!!mesh, "Got unexpected value %p.\n", mesh);
11614 count = mesh->lpVtbl->GetNumVertices(mesh);
11615 ok(count == 3, "Got unexpected value %lu.\n", count);
11616 count = mesh->lpVtbl->GetNumFaces(mesh);
11617 ok(count == 1, "Got unexpected value %lu.\n", count);
11619 hr = skin_info->lpVtbl->GetDeclaration(skin_info, declaration);
11620 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
11621 compare_elements(declaration, expected_declaration, __LINE__, 0);
11623 fvf = skin_info->lpVtbl->GetFVF(skin_info);
11624 ok(fvf == D3DFVF_XYZ, "Got unexpected value %lu.\n", fvf);
11626 count = skin_info->lpVtbl->GetNumBones(skin_info);
11627 ok(!count, "Got unexpected value %lu.\n", count);
11629 influence = skin_info->lpVtbl->GetMinBoneInfluence(skin_info);
11630 ok(!influence, "Got unexpected value %.8e.\n", influence);
11632 memset(max_influences, 0x55, sizeof(max_influences));
11633 hr = skin_info->lpVtbl->GetMaxVertexInfluences(skin_info, max_influences);
11634 todo_wine ok(hr == D3D_OK, "Got unexpected value %#lx.\n", hr);
11635 todo_wine ok(!max_influences[0], "Got unexpected value %lu.\n", max_influences[0]);
11636 ok(max_influences[1] == 0x55555555, "Got unexpected value %lu.\n", max_influences[1]);
11637 ok(max_influences[2] == 0x55555555, "Got unexpected value %lu.\n", max_influences[2]);
11639 bone_name = skin_info->lpVtbl->GetBoneName(skin_info, 0);
11640 ok(!bone_name, "Got unexpected value %p.\n", bone_name);
11642 count = skin_info->lpVtbl->GetNumBoneInfluences(skin_info, 0);
11643 ok(!count, "Got unexpected value %lu.\n", count);
11645 count = skin_info->lpVtbl->GetNumBoneInfluences(skin_info, 1);
11646 ok(!count, "Got unexpected value %lu.\n", count);
11648 matrix = skin_info->lpVtbl->GetBoneOffsetMatrix(skin_info, -1);
11649 ok(!matrix, "Got unexpected value %p.\n", matrix);
11651 matrix = skin_info->lpVtbl->GetBoneOffsetMatrix(skin_info, 0);
11652 ok(!matrix, "Got unexpected value %p.\n", matrix);
11654 skin_info->lpVtbl->Release(skin_info);
11655 mesh->lpVtbl->Release(mesh);
11656 adjacency->lpVtbl->Release(adjacency);
11657 file_data->lpVtbl->Release(file_data);
11659 /* Empty Mesh Test */
11660 file_data = get_mesh_data(simple_xfile_empty, sizeof(simple_xfile_empty) - 1);
11661 ok(!!file_data, "Failed to load mesh data.\n");
11663 adjacency = materials = effects = (void *)0xdeadbeef;
11664 count = 0xdeadbeefu;
11665 skin_info = (void *)0xdeadbeef;
11666 mesh = (void *)0xdeadbeef;
11668 hr = D3DXLoadSkinMeshFromXof(file_data, 0, device, &adjacency, &materials, &effects, &count,
11669 &skin_info, &mesh);
11670 todo_wine ok(hr == D3DXERR_LOADEDMESHASNODATA, "Unexpected hr %#lx.\n", hr);
11671 ok(!adjacency, "Unexpected adjacency %p.\n", adjacency);
11672 ok(!materials, "Unexpected materials %p.\n", materials);
11673 ok(!effects, "Unexpected effects %p.\n", effects);
11674 ok(count == 0xdeadbeefu, "Unexpected count %lu.\n", count);
11675 ok(skin_info == (void *)0xdeadbeef, "Unexpected skin_info %p.\n", skin_info);
11676 ok(!mesh, "Unexpected mesh %p.\n", mesh);
11678 file_data->lpVtbl->Release(file_data);
11680 refcount = IDirect3DDevice9_Release(device);
11681 ok(!refcount, "Device has %lu references left.\n", refcount);
11682 DestroyWindow(hwnd);
11685 static void test_mesh_optimize(void)
11688 * . _ .
11689 * / \ / \
11690 * . _ . _ .
11691 * \ / \ /
11692 * . _ .
11694 static const struct
11696 float c[3];
11697 float n[3];
11698 float t[2];
11700 vertices[] =
11702 { {-0.5f, -1.0f, 0.0f,}, {0.0f, 0.0f, 1.0f}, {-0.5f, -1.0f} },
11703 { { 0.5f, -1.0f, 0.0f,}, {0.0f, 0.0f, 1.0f}, { 0.5f, -1.0f} },
11705 { {-1.0f, 0.0f, 0.0f,}, {0.0f, 0.0f, 1.0f}, {-1.0f, 0.0f} },
11706 { { 0.0f, 0.0f, 0.0f,}, {0.0f, 0.0f, 1.0f}, { 0.0f, 0.0f} },
11707 { { 1.0f, 0.0f, 0.0f,}, {0.0f, 0.0f, 1.0f}, { 1.0f, 0.0f} },
11709 { {-0.5f, 1.0f, 0.0f,}, {0.0f, 0.0f, 1.0f}, {-0.5f, 1.0f} },
11710 { { 0.5f, 1.0f, 0.0f,}, {0.0f, 0.0f, 1.0f}, { 0.5f, 1.0f} },
11712 static const unsigned short indices[] =
11714 3, 0, 2,
11715 3, 2, 5,
11716 3, 5, 6,
11717 3, 6, 4,
11718 3, 4, 1,
11719 3, 1, 0,
11721 static const DWORD attrs[] = { 1, 2, 1, 2, 1, 2 };
11722 static const DWORD expected_adjacency[] =
11724 5, 0xffffffff, 1,
11725 0, 0xffffffff, 2,
11726 1, 0xffffffff, 3,
11727 2, 0xffffffff, 4,
11728 3, 0xffffffff, 5,
11729 4, 0xffffffff, 0,
11731 static const DWORD expected_adjacency_out[] =
11733 5, 0xffffffff, 3,
11734 3, 0xffffffff, 4,
11735 4, 0xffffffff, 5,
11736 0, 0xffffffff, 1,
11737 1, 0xffffffff, 2,
11738 2, 0xffffffff, 0,
11741 DWORD adjacency[6 * 3], adjacency_out[6 * 3];
11742 struct test_context *test_context;
11743 IDirect3DDevice9 *device;
11744 ID3DXBuffer *buffer;
11745 ID3DXMesh *mesh;
11746 unsigned int i;
11747 DWORD size;
11748 HRESULT hr;
11749 void *data;
11751 test_context = new_test_context();
11752 if (!test_context)
11754 skip("Couldn't create test context\n");
11755 return;
11757 device = test_context->device;
11759 hr = D3DXCreateMeshFVF(ARRAY_SIZE(attrs), ARRAY_SIZE(vertices), D3DXMESH_VB_MANAGED | D3DXMESH_IB_MANAGED,
11760 D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1, device, &mesh);
11761 ok(hr == S_OK, "got %#lx.\n", hr);
11763 hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, &data);
11764 ok(hr == S_OK, "got %#lx.\n", hr);
11765 memcpy(data, vertices, sizeof(vertices));
11766 hr = mesh->lpVtbl->UnlockVertexBuffer(mesh);
11767 ok(hr == S_OK, "got %#lx.\n", hr);
11769 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, &data);
11770 ok(hr == S_OK, "got %#lx.\n", hr);
11771 memcpy(data, indices, sizeof(indices));
11772 hr = mesh->lpVtbl->UnlockIndexBuffer(mesh);
11773 ok(hr == S_OK, "got %#lx.\n", hr);
11775 hr = mesh->lpVtbl->LockAttributeBuffer(mesh, 0, (DWORD **)&data);
11776 ok(hr == S_OK, "got %#lx.\n", hr);
11777 memcpy(data, attrs, sizeof(attrs));
11778 hr = mesh->lpVtbl->UnlockAttributeBuffer(mesh);
11779 ok(hr == S_OK, "got %#lx.\n", hr);
11781 hr = mesh->lpVtbl->GenerateAdjacency(mesh, 0.0f, adjacency);
11782 ok(hr == S_OK, "got %#lx.\n", hr);
11783 ok(!memcmp(adjacency, expected_adjacency, sizeof(adjacency)), "data mismatch.\n");
11785 hr = mesh->lpVtbl->OptimizeInplace(mesh, D3DXMESHOPT_IGNOREVERTS | D3DXMESHOPT_ATTRSORT | D3DXMESHOPT_DONOTSPLIT,
11786 adjacency, adjacency_out, NULL, &buffer);
11787 ok(hr == S_OK, "got %#lx.\n", hr);
11789 size = buffer->lpVtbl->GetBufferSize(buffer);
11790 ok(size == sizeof(DWORD) * ARRAY_SIZE(vertices), "got %lu.\n", size);
11791 data = buffer->lpVtbl->GetBufferPointer(buffer);
11792 for (i = 0; i < ARRAY_SIZE(vertices); ++i)
11793 ok(((DWORD *)data)[i] == i, "i %u, got %lu.\n", i, ((DWORD *)data)[i]);
11794 ok(!memcmp(adjacency_out, expected_adjacency_out, sizeof(adjacency)), "data mismatch.\n");
11796 buffer->lpVtbl->Release(buffer);
11797 mesh->lpVtbl->Release(mesh);
11798 free_test_context(test_context);
11801 START_TEST(mesh)
11803 D3DXBoundProbeTest();
11804 D3DXComputeBoundingBoxTest();
11805 D3DXComputeBoundingSphereTest();
11806 D3DXGetFVFVertexSizeTest();
11807 D3DXIntersectTriTest();
11808 D3DXCreateMeshTest();
11809 D3DXCreateMeshFVFTest();
11810 D3DXLoadMeshTest();
11811 D3DXCreateBoxTest();
11812 D3DXCreatePolygonTest();
11813 D3DXCreateSphereTest();
11814 D3DXCreateCylinderTest();
11815 D3DXCreateTextTest();
11816 D3DXCreateTorusTest();
11817 D3DXCreateAnimationControllerTest();
11818 D3DXCreateKeyframedAnimationSetTest();
11819 test_get_decl_length();
11820 test_get_decl_vertex_size();
11821 test_fvf_decl_conversion();
11822 D3DXGenerateAdjacencyTest();
11823 test_update_semantics();
11824 test_create_skin_info();
11825 test_convert_adjacency_to_point_reps();
11826 test_convert_point_reps_to_adjacency();
11827 test_weld_vertices();
11828 test_clone_mesh();
11829 test_valid_mesh();
11830 test_optimize_faces();
11831 test_compute_normals();
11832 test_D3DXFrameFind();
11833 test_load_skin_mesh_from_xof();
11834 test_mesh_optimize();