d3dx9: Added D3DXOptimizeFaces test.
[wine/multimedia.git] / dlls / d3dx9_36 / tests / mesh.c
blobb8123ab163b312e11ed5e4a803ddb1f89034e915
1 /*
2 * Copyright 2008 David Adam
3 * Copyright 2008 Luis Busquets
4 * Copyright 2009 Henri Verbeet for CodeWeavers
5 * Copyright 2011 Michael Mc Donnell
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #define COBJMACROS
23 #include <stdio.h>
24 #include <float.h>
25 #include <limits.h>
26 #include "wine/test.h"
27 #include "d3dx9.h"
29 /* Set the WINETEST_DEBUG environment variable to be greater than 1 for verbose
30 * function call traces of ID3DXAllocateHierarchy callbacks. */
31 #define TRACECALLBACK if(winetest_debug > 1) trace
33 #define admitted_error 0.0001f
35 #define ARRAY_SIZE(array) (sizeof(array)/sizeof(*array))
37 #define compare_vertex_sizes(type, exp) \
38 got=D3DXGetFVFVertexSize(type); \
39 ok(got==exp, "Expected: %d, Got: %d\n", exp, got);
41 #define compare_float(got, exp) \
42 do { \
43 float _got = (got); \
44 float _exp = (exp); \
45 ok(_got == _exp, "Expected: %g, Got: %g\n", _exp, _got); \
46 } while (0)
48 static BOOL compare(FLOAT u, FLOAT v)
50 return (fabs(u-v) < admitted_error);
53 static BOOL compare_vec3(D3DXVECTOR3 u, D3DXVECTOR3 v)
55 return ( compare(u.x, v.x) && compare(u.y, v.y) && compare(u.z, v.z) );
58 #define check_floats(got, exp, dim) check_floats_(__LINE__, "", got, exp, dim)
59 static void check_floats_(int line, const char *prefix, const float *got, const float *exp, int dim)
61 int i;
62 char exp_buffer[256] = "";
63 char got_buffer[256] = "";
64 char *exp_buffer_ptr = exp_buffer;
65 char *got_buffer_ptr = got_buffer;
66 BOOL equal = TRUE;
68 for (i = 0; i < dim; i++) {
69 if (i) {
70 exp_buffer_ptr += sprintf(exp_buffer_ptr, ", ");
71 got_buffer_ptr += sprintf(got_buffer_ptr, ", ");
73 equal = equal && compare(*exp, *got);
74 exp_buffer_ptr += sprintf(exp_buffer_ptr, "%g", *exp);
75 got_buffer_ptr += sprintf(got_buffer_ptr, "%g", *got);
76 exp++, got++;
78 ok_(__FILE__,line)(equal, "%sExpected (%s), got (%s)", prefix, exp_buffer, got_buffer);
81 struct vertex
83 D3DXVECTOR3 position;
84 D3DXVECTOR3 normal;
87 typedef WORD face[3];
89 static BOOL compare_face(face a, face b)
91 return (a[0]==b[0] && a[1] == b[1] && a[2] == b[2]);
94 struct test_context
96 HWND hwnd;
97 IDirect3D9 *d3d;
98 IDirect3DDevice9 *device;
101 /* Initializes a test context struct. Use it to initialize DirectX.
103 * Returns NULL if an error occurred.
105 static struct test_context *new_test_context(void)
107 HRESULT hr;
108 HWND hwnd = NULL;
109 IDirect3D9 *d3d = NULL;
110 IDirect3DDevice9 *device = NULL;
111 D3DPRESENT_PARAMETERS d3dpp = {0};
112 struct test_context *test_context;
114 hwnd = CreateWindow("static", "d3dx9_test", 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL);
115 if (!hwnd)
117 skip("Couldn't create application window\n");
118 goto error;
121 d3d = Direct3DCreate9(D3D_SDK_VERSION);
122 if (!d3d)
124 skip("Couldn't create IDirect3D9 object\n");
125 goto error;
128 memset(&d3dpp, 0, sizeof(d3dpp));
129 d3dpp.Windowed = TRUE;
130 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
131 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
132 D3DCREATE_MIXED_VERTEXPROCESSING, &d3dpp, &device);
133 if (FAILED(hr))
135 skip("Couldn't create IDirect3DDevice9 object %#x\n", hr);
136 goto error;
139 test_context = HeapAlloc(GetProcessHeap(), 0, sizeof(*test_context));
140 if (!test_context)
142 skip("Couldn't allocate memory for test_context\n");
143 goto error;
145 test_context->hwnd = hwnd;
146 test_context->d3d = d3d;
147 test_context->device = device;
149 return test_context;
151 error:
152 if (device)
153 IDirect3DDevice9_Release(device);
155 if (d3d)
156 IDirect3D9_Release(d3d);
158 if (hwnd)
159 DestroyWindow(hwnd);
161 return NULL;
164 static void free_test_context(struct test_context *test_context)
166 if (!test_context)
167 return;
169 if (test_context->device)
170 IDirect3DDevice9_Release(test_context->device);
172 if (test_context->d3d)
173 IDirect3D9_Release(test_context->d3d);
175 if (test_context->hwnd)
176 DestroyWindow(test_context->hwnd);
178 HeapFree(GetProcessHeap(), 0, test_context);
181 struct mesh
183 DWORD number_of_vertices;
184 struct vertex *vertices;
186 DWORD number_of_faces;
187 face *faces;
189 DWORD fvf;
190 UINT vertex_size;
193 static void free_mesh(struct mesh *mesh)
195 HeapFree(GetProcessHeap(), 0, mesh->faces);
196 HeapFree(GetProcessHeap(), 0, mesh->vertices);
199 static BOOL new_mesh(struct mesh *mesh, DWORD number_of_vertices, DWORD number_of_faces)
201 mesh->vertices = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, number_of_vertices * sizeof(*mesh->vertices));
202 if (!mesh->vertices)
204 return FALSE;
206 mesh->number_of_vertices = number_of_vertices;
208 mesh->faces = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, number_of_faces * sizeof(*mesh->faces));
209 if (!mesh->faces)
211 HeapFree(GetProcessHeap(), 0, mesh->vertices);
212 return FALSE;
214 mesh->number_of_faces = number_of_faces;
216 return TRUE;
219 static void compare_mesh(const char *name, ID3DXMesh *d3dxmesh, struct mesh *mesh)
221 HRESULT hr;
222 DWORD number_of_vertices, number_of_faces;
223 IDirect3DVertexBuffer9 *vertex_buffer;
224 IDirect3DIndexBuffer9 *index_buffer;
225 D3DVERTEXBUFFER_DESC vertex_buffer_description;
226 D3DINDEXBUFFER_DESC index_buffer_description;
227 struct vertex *vertices;
228 face *faces;
229 int expected, i;
231 number_of_vertices = d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh);
232 ok(number_of_vertices == mesh->number_of_vertices, "Test %s, result %u, expected %d\n",
233 name, number_of_vertices, mesh->number_of_vertices);
235 number_of_faces = d3dxmesh->lpVtbl->GetNumFaces(d3dxmesh);
236 ok(number_of_faces == mesh->number_of_faces, "Test %s, result %u, expected %d\n",
237 name, number_of_faces, mesh->number_of_faces);
239 /* vertex buffer */
240 hr = d3dxmesh->lpVtbl->GetVertexBuffer(d3dxmesh, &vertex_buffer);
241 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
243 if (hr != D3D_OK)
245 skip("Couldn't get vertex buffer\n");
247 else
249 hr = IDirect3DVertexBuffer9_GetDesc(vertex_buffer, &vertex_buffer_description);
250 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
252 if (hr != D3D_OK)
254 skip("Couldn't get vertex buffer description\n");
256 else
258 ok(vertex_buffer_description.Format == D3DFMT_VERTEXDATA, "Test %s, result %x, expected %x (D3DFMT_VERTEXDATA)\n",
259 name, vertex_buffer_description.Format, D3DFMT_VERTEXDATA);
260 ok(vertex_buffer_description.Type == D3DRTYPE_VERTEXBUFFER, "Test %s, result %x, expected %x (D3DRTYPE_VERTEXBUFFER)\n",
261 name, vertex_buffer_description.Type, D3DRTYPE_VERTEXBUFFER);
262 ok(vertex_buffer_description.Usage == 0, "Test %s, result %x, expected %x\n", name, vertex_buffer_description.Usage, 0);
263 ok(vertex_buffer_description.Pool == D3DPOOL_MANAGED, "Test %s, result %x, expected %x (D3DPOOL_MANAGED)\n",
264 name, vertex_buffer_description.Pool, D3DPOOL_MANAGED);
265 ok(vertex_buffer_description.FVF == mesh->fvf, "Test %s, result %x, expected %x\n",
266 name, vertex_buffer_description.FVF, mesh->fvf);
267 if (mesh->fvf == 0)
269 expected = number_of_vertices * mesh->vertex_size;
271 else
273 expected = number_of_vertices * D3DXGetFVFVertexSize(mesh->fvf);
275 ok(vertex_buffer_description.Size == expected, "Test %s, result %x, expected %x\n",
276 name, vertex_buffer_description.Size, expected);
279 /* specify offset and size to avoid potential overruns */
280 hr = IDirect3DVertexBuffer9_Lock(vertex_buffer, 0, number_of_vertices * sizeof(D3DXVECTOR3) * 2,
281 (LPVOID *)&vertices, D3DLOCK_DISCARD);
282 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
284 if (hr != D3D_OK)
286 skip("Couldn't lock vertex buffer\n");
288 else
290 for (i = 0; i < number_of_vertices; i++)
292 ok(compare_vec3(vertices[i].position, mesh->vertices[i].position),
293 "Test %s, vertex position %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i,
294 vertices[i].position.x, vertices[i].position.y, vertices[i].position.z,
295 mesh->vertices[i].position.x, mesh->vertices[i].position.y, mesh->vertices[i].position.z);
296 ok(compare_vec3(vertices[i].normal, mesh->vertices[i].normal),
297 "Test %s, vertex normal %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i,
298 vertices[i].normal.x, vertices[i].normal.y, vertices[i].normal.z,
299 mesh->vertices[i].normal.x, mesh->vertices[i].normal.y, mesh->vertices[i].normal.z);
302 IDirect3DVertexBuffer9_Unlock(vertex_buffer);
305 IDirect3DVertexBuffer9_Release(vertex_buffer);
308 /* index buffer */
309 hr = d3dxmesh->lpVtbl->GetIndexBuffer(d3dxmesh, &index_buffer);
310 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
312 if (!index_buffer)
314 skip("Couldn't get index buffer\n");
316 else
318 hr = IDirect3DIndexBuffer9_GetDesc(index_buffer, &index_buffer_description);
319 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
321 if (hr != D3D_OK)
323 skip("Couldn't get index buffer description\n");
325 else
327 ok(index_buffer_description.Format == D3DFMT_INDEX16, "Test %s, result %x, expected %x (D3DFMT_INDEX16)\n",
328 name, index_buffer_description.Format, D3DFMT_INDEX16);
329 ok(index_buffer_description.Type == D3DRTYPE_INDEXBUFFER, "Test %s, result %x, expected %x (D3DRTYPE_INDEXBUFFER)\n",
330 name, index_buffer_description.Type, D3DRTYPE_INDEXBUFFER);
331 ok(index_buffer_description.Usage == 0, "Test %s, result %#x, expected %#x.\n",
332 name, index_buffer_description.Usage, 0);
333 ok(index_buffer_description.Pool == D3DPOOL_MANAGED, "Test %s, result %x, expected %x (D3DPOOL_MANAGED)\n",
334 name, index_buffer_description.Pool, D3DPOOL_MANAGED);
335 expected = number_of_faces * sizeof(WORD) * 3;
336 ok(index_buffer_description.Size == expected, "Test %s, result %x, expected %x\n",
337 name, index_buffer_description.Size, expected);
340 /* specify offset and size to avoid potential overruns */
341 hr = IDirect3DIndexBuffer9_Lock(index_buffer, 0, number_of_faces * sizeof(WORD) * 3,
342 (LPVOID *)&faces, D3DLOCK_DISCARD);
343 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
345 if (hr != D3D_OK)
347 skip("Couldn't lock index buffer\n");
349 else
351 for (i = 0; i < number_of_faces; i++)
353 ok(compare_face(faces[i], mesh->faces[i]),
354 "Test %s, face %d, result (%u, %u, %u), expected (%u, %u, %u)\n", name, i,
355 faces[i][0], faces[i][1], faces[i][2],
356 mesh->faces[i][0], mesh->faces[i][1], mesh->faces[i][2]);
359 IDirect3DIndexBuffer9_Unlock(index_buffer);
362 IDirect3DIndexBuffer9_Release(index_buffer);
366 static void D3DXBoundProbeTest(void)
368 BOOL result;
369 D3DXVECTOR3 bottom_point, center, top_point, raydirection, rayposition;
370 FLOAT radius;
372 /*____________Test the Box case___________________________*/
373 bottom_point.x = -3.0f; bottom_point.y = -2.0f; bottom_point.z = -1.0f;
374 top_point.x = 7.0f; top_point.y = 8.0f; top_point.z = 9.0f;
376 raydirection.x = -4.0f; raydirection.y = -5.0f; raydirection.z = -6.0f;
377 rayposition.x = 5.0f; rayposition.y = 5.0f; rayposition.z = 11.0f;
378 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection);
379 ok(result == TRUE, "expected TRUE, received FALSE\n");
381 raydirection.x = 4.0f; raydirection.y = 5.0f; raydirection.z = 6.0f;
382 rayposition.x = 5.0f; rayposition.y = 5.0f; rayposition.z = 11.0f;
383 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection);
384 ok(result == FALSE, "expected FALSE, received TRUE\n");
386 rayposition.x = -4.0f; rayposition.y = 1.0f; rayposition.z = -2.0f;
387 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection);
388 ok(result == TRUE, "expected TRUE, received FALSE\n");
390 bottom_point.x = 1.0f; bottom_point.y = 0.0f; bottom_point.z = 0.0f;
391 top_point.x = 1.0f; top_point.y = 0.0f; top_point.z = 0.0f;
392 rayposition.x = 0.0f; rayposition.y = 1.0f; rayposition.z = 0.0f;
393 raydirection.x = 0.0f; raydirection.y = 3.0f; raydirection.z = 0.0f;
394 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection);
395 ok(result == FALSE, "expected FALSE, received TRUE\n");
397 bottom_point.x = 1.0f; bottom_point.y = 2.0f; bottom_point.z = 3.0f;
398 top_point.x = 10.0f; top_point.y = 15.0f; top_point.z = 20.0f;
400 raydirection.x = 7.0f; raydirection.y = 8.0f; raydirection.z = 9.0f;
401 rayposition.x = 3.0f; rayposition.y = 7.0f; rayposition.z = -6.0f;
402 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection);
403 ok(result == TRUE, "expected TRUE, received FALSE\n");
405 bottom_point.x = 0.0f; bottom_point.y = 0.0f; bottom_point.z = 0.0f;
406 top_point.x = 1.0f; top_point.y = 1.0f; top_point.z = 1.0f;
408 raydirection.x = 0.0f; raydirection.y = 1.0f; raydirection.z = .0f;
409 rayposition.x = -3.0f; rayposition.y = 0.0f; rayposition.z = 0.0f;
410 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection);
411 ok(result == FALSE, "expected FALSE, received TRUE\n");
413 raydirection.x = 1.0f; raydirection.y = 0.0f; raydirection.z = .0f;
414 rayposition.x = -3.0f; rayposition.y = 0.0f; rayposition.z = 0.0f;
415 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection);
416 ok(result == TRUE, "expected TRUE, received FALSE\n");
418 /*____________Test the Sphere case________________________*/
419 radius = sqrt(77.0f);
420 center.x = 1.0f; center.y = 2.0f; center.z = 3.0f;
421 raydirection.x = 2.0f; raydirection.y = -4.0f; raydirection.z = 2.0f;
423 rayposition.x = 5.0f; rayposition.y = 5.0f; rayposition.z = 9.0f;
424 result = D3DXSphereBoundProbe(&center, radius, &rayposition, &raydirection);
425 ok(result == TRUE, "expected TRUE, received FALSE\n");
427 rayposition.x = 45.0f; rayposition.y = -75.0f; rayposition.z = 49.0f;
428 result = D3DXSphereBoundProbe(&center, radius, &rayposition, &raydirection);
429 ok(result == FALSE, "expected FALSE, received TRUE\n");
431 rayposition.x = 5.0f; rayposition.y = 11.0f; rayposition.z = 9.0f;
432 result = D3DXSphereBoundProbe(&center, radius, &rayposition, &raydirection);
433 ok(result == FALSE, "expected FALSE, received TRUE\n");
436 static void D3DXComputeBoundingBoxTest(void)
438 D3DXVECTOR3 exp_max, exp_min, got_max, got_min, vertex[5];
439 HRESULT hr;
441 vertex[0].x = 1.0f; vertex[0].y = 1.0f; vertex[0].z = 1.0f;
442 vertex[1].x = 1.0f; vertex[1].y = 1.0f; vertex[1].z = 1.0f;
443 vertex[2].x = 1.0f; vertex[2].y = 1.0f; vertex[2].z = 1.0f;
444 vertex[3].x = 1.0f; vertex[3].y = 1.0f; vertex[3].z = 1.0f;
445 vertex[4].x = 9.0f; vertex[4].y = 9.0f; vertex[4].z = 9.0f;
447 exp_min.x = 1.0f; exp_min.y = 1.0f; exp_min.z = 1.0f;
448 exp_max.x = 9.0f; exp_max.y = 9.0f; exp_max.z = 9.0f;
450 hr = D3DXComputeBoundingBox(&vertex[3],2,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_min,&got_max);
452 ok( hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
453 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);
454 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);
456 /*________________________*/
458 vertex[0].x = 2.0f; vertex[0].y = 5.9f; vertex[0].z = -1.2f;
459 vertex[1].x = -1.87f; vertex[1].y = 7.9f; vertex[1].z = 7.4f;
460 vertex[2].x = 7.43f; vertex[2].y = -0.9f; vertex[2].z = 11.9f;
461 vertex[3].x = -6.92f; vertex[3].y = 6.3f; vertex[3].z = -3.8f;
462 vertex[4].x = 11.4f; vertex[4].y = -8.1f; vertex[4].z = 4.5f;
464 exp_min.x = -6.92f; exp_min.y = -8.1f; exp_min.z = -3.80f;
465 exp_max.x = 11.4f; exp_max.y = 7.90f; exp_max.z = 11.9f;
467 hr = D3DXComputeBoundingBox(&vertex[0],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_min,&got_max);
469 ok( hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
470 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);
471 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);
473 /*________________________*/
475 vertex[0].x = 2.0f; vertex[0].y = 5.9f; vertex[0].z = -1.2f;
476 vertex[1].x = -1.87f; vertex[1].y = 7.9f; vertex[1].z = 7.4f;
477 vertex[2].x = 7.43f; vertex[2].y = -0.9f; vertex[2].z = 11.9f;
478 vertex[3].x = -6.92f; vertex[3].y = 6.3f; vertex[3].z = -3.8f;
479 vertex[4].x = 11.4f; vertex[4].y = -8.1f; vertex[4].z = 4.5f;
481 exp_min.x = -6.92f; exp_min.y = -0.9f; exp_min.z = -3.8f;
482 exp_max.x = 7.43f; exp_max.y = 7.90f; exp_max.z = 11.9f;
484 hr = D3DXComputeBoundingBox(&vertex[0],4,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_min,&got_max);
486 ok( hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
487 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);
488 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);
490 /*________________________*/
491 hr = D3DXComputeBoundingBox(NULL,5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_min,&got_max);
492 ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
494 /*________________________*/
495 hr = D3DXComputeBoundingBox(&vertex[3],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),NULL,&got_max);
496 ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
498 /*________________________*/
499 hr = D3DXComputeBoundingBox(&vertex[3],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_min,NULL);
500 ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
503 static void D3DXComputeBoundingSphereTest(void)
505 D3DXVECTOR3 exp_cen, got_cen, vertex[5];
506 FLOAT exp_rad, got_rad;
507 HRESULT hr;
509 vertex[0].x = 1.0f; vertex[0].y = 1.0f; vertex[0].z = 1.0f;
510 vertex[1].x = 1.0f; vertex[1].y = 1.0f; vertex[1].z = 1.0f;
511 vertex[2].x = 1.0f; vertex[2].y = 1.0f; vertex[2].z = 1.0f;
512 vertex[3].x = 1.0f; vertex[3].y = 1.0f; vertex[3].z = 1.0f;
513 vertex[4].x = 9.0f; vertex[4].y = 9.0f; vertex[4].z = 9.0f;
515 exp_rad = 6.928203f;
516 exp_cen.x = 5.0; exp_cen.y = 5.0; exp_cen.z = 5.0;
518 hr = D3DXComputeBoundingSphere(&vertex[3],2,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_cen,&got_rad);
520 ok( hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
521 ok( compare(exp_rad, got_rad), "Expected radius: %f, got radius: %f\n", exp_rad, got_rad);
522 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);
524 /*________________________*/
526 vertex[0].x = 2.0f; vertex[0].y = 5.9f; vertex[0].z = -1.2f;
527 vertex[1].x = -1.87f; vertex[1].y = 7.9f; vertex[1].z = 7.4f;
528 vertex[2].x = 7.43f; vertex[2].y = -0.9f; vertex[2].z = 11.9f;
529 vertex[3].x = -6.92f; vertex[3].y = 6.3f; vertex[3].z = -3.8f;
530 vertex[4].x = 11.4f; vertex[4].y = -8.1f; vertex[4].z = 4.5f;
532 exp_rad = 13.707883f;
533 exp_cen.x = 2.408f; exp_cen.y = 2.22f; exp_cen.z = 3.76f;
535 hr = D3DXComputeBoundingSphere(&vertex[0],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_cen,&got_rad);
537 ok( hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
538 ok( compare(exp_rad, got_rad), "Expected radius: %f, got radius: %f\n", exp_rad, got_rad);
539 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);
541 /*________________________*/
542 hr = D3DXComputeBoundingSphere(NULL,5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_cen,&got_rad);
543 ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
545 /*________________________*/
546 hr = D3DXComputeBoundingSphere(&vertex[3],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),NULL,&got_rad);
547 ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
549 /*________________________*/
550 hr = D3DXComputeBoundingSphere(&vertex[3],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_cen,NULL);
551 ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
554 static void print_elements(const D3DVERTEXELEMENT9 *elements)
556 D3DVERTEXELEMENT9 last = D3DDECL_END();
557 const D3DVERTEXELEMENT9 *ptr = elements;
558 int count = 0;
560 while (memcmp(ptr, &last, sizeof(D3DVERTEXELEMENT9)))
562 trace(
563 "[Element %d] Stream = %d, Offset = %d, Type = %d, Method = %d, Usage = %d, UsageIndex = %d\n",
564 count, ptr->Stream, ptr->Offset, ptr->Type, ptr->Method, ptr->Usage, ptr->UsageIndex);
565 ptr++;
566 count++;
570 static void compare_elements(const D3DVERTEXELEMENT9 *elements, const D3DVERTEXELEMENT9 *expected_elements,
571 unsigned int line, unsigned int test_id)
573 D3DVERTEXELEMENT9 last = D3DDECL_END();
574 unsigned int i;
576 for (i = 0; i < MAX_FVF_DECL_SIZE; i++)
578 int end1 = memcmp(&elements[i], &last, sizeof(last));
579 int end2 = memcmp(&expected_elements[i], &last, sizeof(last));
580 int status;
582 if (!end1 && !end2) break;
584 status = !end1 ^ !end2;
585 ok(!status, "Line %u, test %u: Mismatch in size, test declaration is %s than expected.\n",
586 line, test_id, end1 ? "shorter" : "longer");
587 if (status)
589 print_elements(elements);
590 break;
593 status = memcmp(&elements[i], &expected_elements[i], sizeof(D3DVERTEXELEMENT9));
594 ok(!status, "Line %u, test %u: Mismatch in element %u.\n", line, test_id, i);
595 if (status)
597 print_elements(elements);
598 break;
603 static void test_fvf_to_decl(DWORD test_fvf, const D3DVERTEXELEMENT9 expected_elements[],
604 HRESULT expected_hr, unsigned int line, unsigned int test_id)
606 HRESULT hr;
607 D3DVERTEXELEMENT9 decl[MAX_FVF_DECL_SIZE];
609 hr = D3DXDeclaratorFromFVF(test_fvf, decl);
610 ok(hr == expected_hr,
611 "Line %u, test %u: D3DXDeclaratorFromFVF returned %#x, expected %#x.\n",
612 line, test_id, hr, expected_hr);
613 if (SUCCEEDED(hr)) compare_elements(decl, expected_elements, line, test_id);
616 static void test_decl_to_fvf(const D3DVERTEXELEMENT9 *decl, DWORD expected_fvf,
617 HRESULT expected_hr, unsigned int line, unsigned int test_id)
619 HRESULT hr;
620 DWORD result_fvf = 0xdeadbeef;
622 hr = D3DXFVFFromDeclarator(decl, &result_fvf);
623 ok(hr == expected_hr,
624 "Line %u, test %u: D3DXFVFFromDeclarator returned %#x, expected %#x.\n",
625 line, test_id, hr, expected_hr);
626 if (SUCCEEDED(hr))
628 ok(expected_fvf == result_fvf, "Line %u, test %u: Got FVF %#x, expected %#x.\n",
629 line, test_id, result_fvf, expected_fvf);
633 static void test_fvf_decl_conversion(void)
635 static const struct
637 D3DVERTEXELEMENT9 decl[MAXD3DDECLLENGTH + 1];
638 DWORD fvf;
640 test_data[] =
643 D3DDECL_END(),
644 }, 0},
646 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
647 D3DDECL_END(),
648 }, D3DFVF_XYZ},
650 {0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITIONT, 0},
651 D3DDECL_END(),
652 }, D3DFVF_XYZRHW},
654 {0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITIONT, 0},
655 D3DDECL_END(),
656 }, D3DFVF_XYZRHW},
658 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
659 {0, 12, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
660 D3DDECL_END(),
661 }, D3DFVF_XYZB1},
663 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
664 {0, 12, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
665 D3DDECL_END(),
666 }, D3DFVF_XYZB1 | D3DFVF_LASTBETA_UBYTE4},
668 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
669 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
670 D3DDECL_END(),
671 }, D3DFVF_XYZB1 | D3DFVF_LASTBETA_D3DCOLOR},
673 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
674 {0, 12, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
675 D3DDECL_END(),
676 }, D3DFVF_XYZB2},
678 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
679 {0, 12, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
680 {0, 16, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
681 D3DDECL_END(),
682 }, D3DFVF_XYZB2 | D3DFVF_LASTBETA_UBYTE4},
684 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
685 {0, 12, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
686 {0, 16, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
687 D3DDECL_END(),
688 }, D3DFVF_XYZB2 | D3DFVF_LASTBETA_D3DCOLOR},
690 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
691 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
692 D3DDECL_END(),
693 }, D3DFVF_XYZB3},
695 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
696 {0, 12, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
697 {0, 20, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
698 D3DDECL_END(),
699 }, D3DFVF_XYZB3 | D3DFVF_LASTBETA_UBYTE4},
701 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
702 {0, 12, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
703 {0, 20, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
704 D3DDECL_END(),
705 }, D3DFVF_XYZB3 | D3DFVF_LASTBETA_D3DCOLOR},
707 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
708 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
709 D3DDECL_END(),
710 }, D3DFVF_XYZB4},
712 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
713 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
714 {0, 24, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
715 D3DDECL_END(),
716 }, D3DFVF_XYZB4 | D3DFVF_LASTBETA_UBYTE4},
718 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
719 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
720 {0, 24, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
721 D3DDECL_END(),
722 }, D3DFVF_XYZB4 | D3DFVF_LASTBETA_D3DCOLOR},
724 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
725 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
726 {0, 28, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
727 D3DDECL_END(),
728 }, D3DFVF_XYZB5 | D3DFVF_LASTBETA_UBYTE4},
730 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
731 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
732 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
733 D3DDECL_END(),
734 }, D3DFVF_XYZB5 | D3DFVF_LASTBETA_D3DCOLOR},
736 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
737 D3DDECL_END(),
738 }, D3DFVF_NORMAL},
740 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
741 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
742 D3DDECL_END(),
743 }, D3DFVF_NORMAL | D3DFVF_DIFFUSE},
745 {0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_PSIZE, 0},
746 D3DDECL_END(),
747 }, D3DFVF_PSIZE},
749 {0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
750 D3DDECL_END(),
751 }, D3DFVF_DIFFUSE},
753 {0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1},
754 D3DDECL_END(),
755 }, D3DFVF_SPECULAR},
756 /* Make sure textures of different sizes work. */
758 {0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
759 D3DDECL_END(),
760 }, D3DFVF_TEXCOORDSIZE1(0) | D3DFVF_TEX1},
762 {0, 0, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 0},
763 D3DDECL_END(),
764 }, D3DFVF_TEXCOORDSIZE2(0) | D3DFVF_TEX1},
766 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 0},
767 D3DDECL_END(),
768 }, D3DFVF_TEXCOORDSIZE3(0) | D3DFVF_TEX1},
770 {0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 0},
771 D3DDECL_END(),
772 }, D3DFVF_TEXCOORDSIZE4(0) | D3DFVF_TEX1},
773 /* Make sure the TEXCOORD index works correctly - try several textures. */
775 {0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
776 {0, 4, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 1},
777 {0, 16, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 2},
778 {0, 24, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 3},
779 D3DDECL_END(),
780 }, D3DFVF_TEX4 | D3DFVF_TEXCOORDSIZE1(0) | D3DFVF_TEXCOORDSIZE3(1)
781 | D3DFVF_TEXCOORDSIZE2(2) | D3DFVF_TEXCOORDSIZE4(3)},
782 /* Now try some combination tests. */
784 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
785 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
786 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
787 {0, 32, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1},
788 {0, 36, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 0},
789 {0, 44, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 1},
790 D3DDECL_END(),
791 }, D3DFVF_XYZB4 | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_TEX2
792 | D3DFVF_TEXCOORDSIZE2(0) | D3DFVF_TEXCOORDSIZE3(1)},
794 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
795 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
796 {0, 24, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_PSIZE, 0},
797 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1},
798 {0, 32, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
799 {0, 36, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 1},
800 D3DDECL_END(),
801 }, D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_PSIZE | D3DFVF_SPECULAR | D3DFVF_TEX2
802 | D3DFVF_TEXCOORDSIZE1(0) | D3DFVF_TEXCOORDSIZE4(1)},
804 unsigned int i;
806 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
808 test_decl_to_fvf(test_data[i].decl, test_data[i].fvf, D3D_OK, __LINE__, i);
809 test_fvf_to_decl(test_data[i].fvf, test_data[i].decl, D3D_OK, __LINE__, i);
812 /* Usage indices for position and normal are apparently ignored. */
814 const D3DVERTEXELEMENT9 decl[] =
816 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 1},
817 D3DDECL_END(),
819 test_decl_to_fvf(decl, D3DFVF_XYZ, D3D_OK, __LINE__, 0);
822 const D3DVERTEXELEMENT9 decl[] =
824 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 1},
825 D3DDECL_END(),
827 test_decl_to_fvf(decl, D3DFVF_NORMAL, D3D_OK, __LINE__, 0);
829 /* D3DFVF_LASTBETA_UBYTE4 and D3DFVF_LASTBETA_D3DCOLOR are ignored if
830 * there are no blend matrices. */
832 const D3DVERTEXELEMENT9 decl[] =
834 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
835 D3DDECL_END(),
837 test_fvf_to_decl(D3DFVF_XYZ | D3DFVF_LASTBETA_UBYTE4, decl, D3D_OK, __LINE__, 0);
840 const D3DVERTEXELEMENT9 decl[] =
842 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
843 D3DDECL_END(),
845 test_fvf_to_decl(D3DFVF_XYZ | D3DFVF_LASTBETA_D3DCOLOR, decl, D3D_OK, __LINE__, 0);
847 /* D3DFVF_LASTBETA_UBYTE4 takes precedence over D3DFVF_LASTBETA_D3DCOLOR. */
849 const D3DVERTEXELEMENT9 decl[] =
851 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
852 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
853 {0, 28, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
854 D3DDECL_END(),
856 test_fvf_to_decl(D3DFVF_XYZB5 | D3DFVF_LASTBETA_D3DCOLOR | D3DFVF_LASTBETA_UBYTE4,
857 decl, D3D_OK, __LINE__, 0);
859 /* These are supposed to fail, both ways. */
861 const D3DVERTEXELEMENT9 decl[] =
863 {0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITION, 0},
864 D3DDECL_END(),
866 test_decl_to_fvf(decl, D3DFVF_XYZW, D3DERR_INVALIDCALL, __LINE__, 0);
867 test_fvf_to_decl(D3DFVF_XYZW, decl, D3DERR_INVALIDCALL, __LINE__, 0);
870 const D3DVERTEXELEMENT9 decl[] =
872 {0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITION, 0},
873 {0, 16, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
874 D3DDECL_END(),
876 test_decl_to_fvf(decl, D3DFVF_XYZW | D3DFVF_NORMAL, D3DERR_INVALIDCALL, __LINE__, 0);
877 test_fvf_to_decl(D3DFVF_XYZW | D3DFVF_NORMAL, decl, D3DERR_INVALIDCALL, __LINE__, 0);
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_FLOAT1, 0, D3DDECLUSAGE_BLENDINDICES, 0},
885 D3DDECL_END(),
887 test_decl_to_fvf(decl, D3DFVF_XYZB5, D3DERR_INVALIDCALL, __LINE__, 0);
888 test_fvf_to_decl(D3DFVF_XYZB5, decl, D3DERR_INVALIDCALL, __LINE__, 0);
890 /* Test a declaration that can't be converted to an FVF. */
892 const D3DVERTEXELEMENT9 decl[] =
894 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
895 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
896 {0, 24, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_PSIZE, 0},
897 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1},
898 {0, 32, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
899 /* 8 bytes padding */
900 {0, 44, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 1},
901 D3DDECL_END(),
903 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0);
905 /* Elements must be ordered by offset. */
907 const D3DVERTEXELEMENT9 decl[] =
909 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
910 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
911 D3DDECL_END(),
913 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0);
915 /* Basic tests for element order. */
917 const D3DVERTEXELEMENT9 decl[] =
919 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
920 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
921 {0, 16, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
922 D3DDECL_END(),
924 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0);
927 const D3DVERTEXELEMENT9 decl[] =
929 {0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
930 {0, 4, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
931 D3DDECL_END(),
933 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0);
936 const D3DVERTEXELEMENT9 decl[] =
938 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
939 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
940 D3DDECL_END(),
942 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0);
944 /* Textures must be ordered by texcoords. */
946 const D3DVERTEXELEMENT9 decl[] =
948 {0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
949 {0, 4, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 2},
950 {0, 16, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 1},
951 {0, 24, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 3},
952 D3DDECL_END(),
954 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0);
956 /* Duplicate elements are not allowed. */
958 const D3DVERTEXELEMENT9 decl[] =
960 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
961 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
962 {0, 16, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
963 D3DDECL_END(),
965 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0);
967 /* Invalid FVFs cannot be converted to a declarator. */
968 test_fvf_to_decl(0xdeadbeef, NULL, D3DERR_INVALIDCALL, __LINE__, 0);
971 static void D3DXGetFVFVertexSizeTest(void)
973 UINT got;
975 compare_vertex_sizes (D3DFVF_XYZ, 12);
977 compare_vertex_sizes (D3DFVF_XYZB3, 24);
979 compare_vertex_sizes (D3DFVF_XYZB5, 32);
981 compare_vertex_sizes (D3DFVF_XYZ | D3DFVF_NORMAL, 24);
983 compare_vertex_sizes (D3DFVF_XYZ | D3DFVF_DIFFUSE, 16);
985 compare_vertex_sizes (
986 D3DFVF_XYZ |
987 D3DFVF_TEX1 |
988 D3DFVF_TEXCOORDSIZE1(0), 16);
989 compare_vertex_sizes (
990 D3DFVF_XYZ |
991 D3DFVF_TEX2 |
992 D3DFVF_TEXCOORDSIZE1(0) |
993 D3DFVF_TEXCOORDSIZE1(1), 20);
995 compare_vertex_sizes (
996 D3DFVF_XYZ |
997 D3DFVF_TEX1 |
998 D3DFVF_TEXCOORDSIZE2(0), 20);
1000 compare_vertex_sizes (
1001 D3DFVF_XYZ |
1002 D3DFVF_TEX2 |
1003 D3DFVF_TEXCOORDSIZE2(0) |
1004 D3DFVF_TEXCOORDSIZE2(1), 28);
1006 compare_vertex_sizes (
1007 D3DFVF_XYZ |
1008 D3DFVF_TEX6 |
1009 D3DFVF_TEXCOORDSIZE2(0) |
1010 D3DFVF_TEXCOORDSIZE2(1) |
1011 D3DFVF_TEXCOORDSIZE2(2) |
1012 D3DFVF_TEXCOORDSIZE2(3) |
1013 D3DFVF_TEXCOORDSIZE2(4) |
1014 D3DFVF_TEXCOORDSIZE2(5), 60);
1016 compare_vertex_sizes (
1017 D3DFVF_XYZ |
1018 D3DFVF_TEX8 |
1019 D3DFVF_TEXCOORDSIZE2(0) |
1020 D3DFVF_TEXCOORDSIZE2(1) |
1021 D3DFVF_TEXCOORDSIZE2(2) |
1022 D3DFVF_TEXCOORDSIZE2(3) |
1023 D3DFVF_TEXCOORDSIZE2(4) |
1024 D3DFVF_TEXCOORDSIZE2(5) |
1025 D3DFVF_TEXCOORDSIZE2(6) |
1026 D3DFVF_TEXCOORDSIZE2(7), 76);
1028 compare_vertex_sizes (
1029 D3DFVF_XYZ |
1030 D3DFVF_TEX1 |
1031 D3DFVF_TEXCOORDSIZE3(0), 24);
1033 compare_vertex_sizes (
1034 D3DFVF_XYZ |
1035 D3DFVF_TEX4 |
1036 D3DFVF_TEXCOORDSIZE3(0) |
1037 D3DFVF_TEXCOORDSIZE3(1) |
1038 D3DFVF_TEXCOORDSIZE3(2) |
1039 D3DFVF_TEXCOORDSIZE3(3), 60);
1041 compare_vertex_sizes (
1042 D3DFVF_XYZ |
1043 D3DFVF_TEX1 |
1044 D3DFVF_TEXCOORDSIZE4(0), 28);
1046 compare_vertex_sizes (
1047 D3DFVF_XYZ |
1048 D3DFVF_TEX2 |
1049 D3DFVF_TEXCOORDSIZE4(0) |
1050 D3DFVF_TEXCOORDSIZE4(1), 44);
1052 compare_vertex_sizes (
1053 D3DFVF_XYZ |
1054 D3DFVF_TEX3 |
1055 D3DFVF_TEXCOORDSIZE4(0) |
1056 D3DFVF_TEXCOORDSIZE4(1) |
1057 D3DFVF_TEXCOORDSIZE4(2), 60);
1059 compare_vertex_sizes (
1060 D3DFVF_XYZB5 |
1061 D3DFVF_NORMAL |
1062 D3DFVF_DIFFUSE |
1063 D3DFVF_SPECULAR |
1064 D3DFVF_TEX8 |
1065 D3DFVF_TEXCOORDSIZE4(0) |
1066 D3DFVF_TEXCOORDSIZE4(1) |
1067 D3DFVF_TEXCOORDSIZE4(2) |
1068 D3DFVF_TEXCOORDSIZE4(3) |
1069 D3DFVF_TEXCOORDSIZE4(4) |
1070 D3DFVF_TEXCOORDSIZE4(5) |
1071 D3DFVF_TEXCOORDSIZE4(6) |
1072 D3DFVF_TEXCOORDSIZE4(7), 180);
1075 static void D3DXIntersectTriTest(void)
1077 BOOL exp_res, got_res;
1078 D3DXVECTOR3 position, ray, vertex[3];
1079 FLOAT exp_dist, got_dist, exp_u, got_u, exp_v, got_v;
1081 vertex[0].x = 1.0f; vertex[0].y = 0.0f; vertex[0].z = 0.0f;
1082 vertex[1].x = 2.0f; vertex[1].y = 0.0f; vertex[1].z = 0.0f;
1083 vertex[2].x = 1.0f; vertex[2].y = 1.0f; vertex[2].z = 0.0f;
1085 position.x = -14.5f; position.y = -23.75f; position.z = -32.0f;
1087 ray.x = 2.0f; ray.y = 3.0f; ray.z = 4.0f;
1089 exp_res = TRUE; exp_u = 0.5f; exp_v = 0.25f; exp_dist = 8.0f;
1091 got_res = D3DXIntersectTri(&vertex[0],&vertex[1],&vertex[2],&position,&ray,&got_u,&got_v,&got_dist);
1092 ok( got_res == exp_res, "Expected result = %d, got %d\n",exp_res,got_res);
1093 ok( compare(exp_u,got_u), "Expected u = %f, got %f\n",exp_u,got_u);
1094 ok( compare(exp_v,got_v), "Expected v = %f, got %f\n",exp_v,got_v);
1095 ok( compare(exp_dist,got_dist), "Expected distance = %f, got %f\n",exp_dist,got_dist);
1097 /*Only positive ray is taken in account*/
1099 vertex[0].x = 1.0f; vertex[0].y = 0.0f; vertex[0].z = 0.0f;
1100 vertex[1].x = 2.0f; vertex[1].y = 0.0f; vertex[1].z = 0.0f;
1101 vertex[2].x = 1.0f; vertex[2].y = 1.0f; vertex[2].z = 0.0f;
1103 position.x = 17.5f; position.y = 24.25f; position.z = 32.0f;
1105 ray.x = 2.0f; ray.y = 3.0f; ray.z = 4.0f;
1107 exp_res = FALSE;
1109 got_res = D3DXIntersectTri(&vertex[0],&vertex[1],&vertex[2],&position,&ray,&got_u,&got_v,&got_dist);
1110 ok( got_res == exp_res, "Expected result = %d, got %d\n",exp_res,got_res);
1112 /*Intersection between ray and triangle in a same plane is considered as empty*/
1114 vertex[0].x = 4.0f; vertex[0].y = 0.0f; vertex[0].z = 0.0f;
1115 vertex[1].x = 6.0f; vertex[1].y = 0.0f; vertex[1].z = 0.0f;
1116 vertex[2].x = 4.0f; vertex[2].y = 2.0f; vertex[2].z = 0.0f;
1118 position.x = 1.0f; position.y = 1.0f; position.z = 0.0f;
1120 ray.x = 1.0f; ray.y = 0.0f; ray.z = 0.0f;
1122 exp_res = FALSE;
1124 got_res = D3DXIntersectTri(&vertex[0],&vertex[1],&vertex[2],&position,&ray,&got_u,&got_v,&got_dist);
1125 ok( got_res == exp_res, "Expected result = %d, got %d\n",exp_res,got_res);
1128 static void D3DXCreateMeshTest(void)
1130 HRESULT hr;
1131 HWND wnd;
1132 IDirect3D9 *d3d;
1133 IDirect3DDevice9 *device, *test_device;
1134 D3DPRESENT_PARAMETERS d3dpp;
1135 ID3DXMesh *d3dxmesh;
1136 int i, size;
1137 D3DVERTEXELEMENT9 test_decl[MAX_FVF_DECL_SIZE];
1138 DWORD options;
1139 struct mesh mesh;
1141 static const D3DVERTEXELEMENT9 decl1[3] = {
1142 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1143 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
1144 D3DDECL_END(), };
1146 static const D3DVERTEXELEMENT9 decl2[] = {
1147 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1148 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
1149 {0, 24, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_PSIZE, 0},
1150 {0, 28, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 1},
1151 {0, 32, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
1152 /* 8 bytes padding */
1153 {0, 44, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
1154 D3DDECL_END(),
1157 static const D3DVERTEXELEMENT9 decl3[] = {
1158 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1159 {1, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
1160 D3DDECL_END(),
1163 hr = D3DXCreateMesh(0, 0, 0, NULL, NULL, NULL);
1164 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1166 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl1, NULL, &d3dxmesh);
1167 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1169 wnd = CreateWindow("static", "d3dx9_test", 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL);
1170 if (!wnd)
1172 skip("Couldn't create application window\n");
1173 return;
1175 d3d = Direct3DCreate9(D3D_SDK_VERSION);
1176 if (!d3d)
1178 skip("Couldn't create IDirect3D9 object\n");
1179 DestroyWindow(wnd);
1180 return;
1183 ZeroMemory(&d3dpp, sizeof(d3dpp));
1184 d3dpp.Windowed = TRUE;
1185 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1186 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, wnd, D3DCREATE_MIXED_VERTEXPROCESSING, &d3dpp, &device);
1187 if (FAILED(hr))
1189 skip("Failed to create IDirect3DDevice9 object %#x\n", hr);
1190 IDirect3D9_Release(d3d);
1191 DestroyWindow(wnd);
1192 return;
1195 hr = D3DXCreateMesh(0, 3, D3DXMESH_MANAGED, decl1, device, &d3dxmesh);
1196 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1198 hr = D3DXCreateMesh(1, 0, D3DXMESH_MANAGED, decl1, device, &d3dxmesh);
1199 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1201 hr = D3DXCreateMesh(1, 3, 0, decl1, device, &d3dxmesh);
1202 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
1204 if (hr == D3D_OK)
1206 d3dxmesh->lpVtbl->Release(d3dxmesh);
1209 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, 0, device, &d3dxmesh);
1210 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1212 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl1, device, NULL);
1213 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1215 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl1, device, &d3dxmesh);
1216 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
1218 if (hr == D3D_OK)
1220 /* device */
1221 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, NULL);
1222 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1224 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, &test_device);
1225 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
1226 ok(test_device == device, "Got result %p, expected %p\n", test_device, device);
1228 if (hr == D3D_OK)
1230 IDirect3DDevice9_Release(device);
1233 /* declaration */
1234 hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, NULL);
1235 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1237 hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, test_decl);
1238 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
1240 if (hr == D3D_OK)
1242 size = sizeof(decl1) / sizeof(decl1[0]);
1243 for (i = 0; i < size - 1; i++)
1245 ok(test_decl[i].Stream == decl1[i].Stream, "Returned stream %d, expected %d\n", test_decl[i].Stream, decl1[i].Stream);
1246 ok(test_decl[i].Type == decl1[i].Type, "Returned type %d, expected %d\n", test_decl[i].Type, decl1[i].Type);
1247 ok(test_decl[i].Method == decl1[i].Method, "Returned method %d, expected %d\n", test_decl[i].Method, decl1[i].Method);
1248 ok(test_decl[i].Usage == decl1[i].Usage, "Returned usage %d, expected %d\n", test_decl[i].Usage, decl1[i].Usage);
1249 ok(test_decl[i].UsageIndex == decl1[i].UsageIndex, "Returned usage index %d, expected %d\n", test_decl[i].UsageIndex, decl1[i].UsageIndex);
1250 ok(test_decl[i].Offset == decl1[i].Offset, "Returned offset %d, expected %d\n", test_decl[i].Offset, decl1[i].Offset);
1252 ok(decl1[size-1].Stream == 0xFF, "Returned too long vertex declaration\n"); /* end element */
1255 /* options */
1256 options = d3dxmesh->lpVtbl->GetOptions(d3dxmesh);
1257 ok(options == D3DXMESH_MANAGED, "Got result %x, expected %x (D3DXMESH_MANAGED)\n", options, D3DXMESH_MANAGED);
1259 /* rest */
1260 if (!new_mesh(&mesh, 3, 1))
1262 skip("Couldn't create mesh\n");
1264 else
1266 memset(mesh.vertices, 0, mesh.number_of_vertices * sizeof(*mesh.vertices));
1267 memset(mesh.faces, 0, mesh.number_of_faces * sizeof(*mesh.faces));
1268 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
1270 compare_mesh("createmesh1", d3dxmesh, &mesh);
1272 free_mesh(&mesh);
1275 d3dxmesh->lpVtbl->Release(d3dxmesh);
1278 /* Test a declaration that can't be converted to an FVF. */
1279 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl2, device, &d3dxmesh);
1280 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
1282 if (hr == D3D_OK)
1284 /* device */
1285 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, NULL);
1286 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1288 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, &test_device);
1289 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
1290 ok(test_device == device, "Got result %p, expected %p\n", test_device, device);
1292 if (hr == D3D_OK)
1294 IDirect3DDevice9_Release(device);
1297 /* declaration */
1298 hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, test_decl);
1299 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
1301 if (hr == D3D_OK)
1303 size = sizeof(decl2) / sizeof(decl2[0]);
1304 for (i = 0; i < size - 1; i++)
1306 ok(test_decl[i].Stream == decl2[i].Stream, "Returned stream %d, expected %d\n", test_decl[i].Stream, decl2[i].Stream);
1307 ok(test_decl[i].Type == decl2[i].Type, "Returned type %d, expected %d\n", test_decl[i].Type, decl2[i].Type);
1308 ok(test_decl[i].Method == decl2[i].Method, "Returned method %d, expected %d\n", test_decl[i].Method, decl2[i].Method);
1309 ok(test_decl[i].Usage == decl2[i].Usage, "Returned usage %d, expected %d\n", test_decl[i].Usage, decl2[i].Usage);
1310 ok(test_decl[i].UsageIndex == decl2[i].UsageIndex, "Returned usage index %d, expected %d\n", test_decl[i].UsageIndex, decl2[i].UsageIndex);
1311 ok(test_decl[i].Offset == decl2[i].Offset, "Returned offset %d, expected %d\n", test_decl[i].Offset, decl2[i].Offset);
1313 ok(decl2[size-1].Stream == 0xFF, "Returned too long vertex declaration\n"); /* end element */
1316 /* options */
1317 options = d3dxmesh->lpVtbl->GetOptions(d3dxmesh);
1318 ok(options == D3DXMESH_MANAGED, "Got result %x, expected %x (D3DXMESH_MANAGED)\n", options, D3DXMESH_MANAGED);
1320 /* rest */
1321 if (!new_mesh(&mesh, 3, 1))
1323 skip("Couldn't create mesh\n");
1325 else
1327 memset(mesh.vertices, 0, mesh.number_of_vertices * sizeof(*mesh.vertices));
1328 memset(mesh.faces, 0, mesh.number_of_faces * sizeof(*mesh.faces));
1329 mesh.fvf = 0;
1330 mesh.vertex_size = 60;
1332 compare_mesh("createmesh2", d3dxmesh, &mesh);
1334 free_mesh(&mesh);
1337 mesh.vertex_size = d3dxmesh->lpVtbl->GetNumBytesPerVertex(d3dxmesh);
1338 ok(mesh.vertex_size == 60, "Got vertex size %u, expected %u\n", mesh.vertex_size, 60);
1340 d3dxmesh->lpVtbl->Release(d3dxmesh);
1343 /* Test a declaration with multiple streams. */
1344 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl3, device, &d3dxmesh);
1345 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1347 IDirect3DDevice9_Release(device);
1348 IDirect3D9_Release(d3d);
1349 DestroyWindow(wnd);
1352 static void D3DXCreateMeshFVFTest(void)
1354 HRESULT hr;
1355 HWND wnd;
1356 IDirect3D9 *d3d;
1357 IDirect3DDevice9 *device, *test_device;
1358 D3DPRESENT_PARAMETERS d3dpp;
1359 ID3DXMesh *d3dxmesh;
1360 int i, size;
1361 D3DVERTEXELEMENT9 test_decl[MAX_FVF_DECL_SIZE];
1362 DWORD options;
1363 struct mesh mesh;
1365 static const D3DVERTEXELEMENT9 decl[3] = {
1366 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1367 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
1368 D3DDECL_END(), };
1370 hr = D3DXCreateMeshFVF(0, 0, 0, 0, NULL, NULL);
1371 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1373 hr = D3DXCreateMeshFVF(1, 3, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, NULL, &d3dxmesh);
1374 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1376 wnd = CreateWindow("static", "d3dx9_test", 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL);
1377 if (!wnd)
1379 skip("Couldn't create application window\n");
1380 return;
1382 d3d = Direct3DCreate9(D3D_SDK_VERSION);
1383 if (!d3d)
1385 skip("Couldn't create IDirect3D9 object\n");
1386 DestroyWindow(wnd);
1387 return;
1390 ZeroMemory(&d3dpp, sizeof(d3dpp));
1391 d3dpp.Windowed = TRUE;
1392 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1393 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, wnd, D3DCREATE_MIXED_VERTEXPROCESSING, &d3dpp, &device);
1394 if (FAILED(hr))
1396 skip("Failed to create IDirect3DDevice9 object %#x\n", hr);
1397 IDirect3D9_Release(d3d);
1398 DestroyWindow(wnd);
1399 return;
1402 hr = D3DXCreateMeshFVF(0, 3, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, device, &d3dxmesh);
1403 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1405 hr = D3DXCreateMeshFVF(1, 0, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, device, &d3dxmesh);
1406 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1408 hr = D3DXCreateMeshFVF(1, 3, 0, D3DFVF_XYZ | D3DFVF_NORMAL, device, &d3dxmesh);
1409 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
1411 if (hr == D3D_OK)
1413 d3dxmesh->lpVtbl->Release(d3dxmesh);
1416 hr = D3DXCreateMeshFVF(1, 3, D3DXMESH_MANAGED, 0xdeadbeef, device, &d3dxmesh);
1417 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1419 hr = D3DXCreateMeshFVF(1, 3, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, device, NULL);
1420 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1422 hr = D3DXCreateMeshFVF(1, 3, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, device, &d3dxmesh);
1423 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
1425 if (hr == D3D_OK)
1427 /* device */
1428 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, NULL);
1429 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1431 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, &test_device);
1432 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
1433 ok(test_device == device, "Got result %p, expected %p\n", test_device, device);
1435 if (hr == D3D_OK)
1437 IDirect3DDevice9_Release(device);
1440 /* declaration */
1441 hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, NULL);
1442 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1444 hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, test_decl);
1445 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
1447 if (hr == D3D_OK)
1449 size = sizeof(decl) / sizeof(decl[0]);
1450 for (i = 0; i < size - 1; i++)
1452 ok(test_decl[i].Stream == decl[i].Stream, "Returned stream %d, expected %d\n", test_decl[i].Stream, decl[i].Stream);
1453 ok(test_decl[i].Type == decl[i].Type, "Returned type %d, expected %d\n", test_decl[i].Type, decl[i].Type);
1454 ok(test_decl[i].Method == decl[i].Method, "Returned method %d, expected %d\n", test_decl[i].Method, decl[i].Method);
1455 ok(test_decl[i].Usage == decl[i].Usage, "Returned usage %d, expected %d\n", test_decl[i].Usage, decl[i].Usage);
1456 ok(test_decl[i].UsageIndex == decl[i].UsageIndex, "Returned usage index %d, expected %d\n",
1457 test_decl[i].UsageIndex, decl[i].UsageIndex);
1458 ok(test_decl[i].Offset == decl[i].Offset, "Returned offset %d, expected %d\n", test_decl[i].Offset, decl[i].Offset);
1460 ok(decl[size-1].Stream == 0xFF, "Returned too long vertex declaration\n"); /* end element */
1463 /* options */
1464 options = d3dxmesh->lpVtbl->GetOptions(d3dxmesh);
1465 ok(options == D3DXMESH_MANAGED, "Got result %x, expected %x (D3DXMESH_MANAGED)\n", options, D3DXMESH_MANAGED);
1467 /* rest */
1468 if (!new_mesh(&mesh, 3, 1))
1470 skip("Couldn't create mesh\n");
1472 else
1474 memset(mesh.vertices, 0, mesh.number_of_vertices * sizeof(*mesh.vertices));
1475 memset(mesh.faces, 0, mesh.number_of_faces * sizeof(*mesh.faces));
1476 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
1478 compare_mesh("createmeshfvf", d3dxmesh, &mesh);
1480 free_mesh(&mesh);
1483 d3dxmesh->lpVtbl->Release(d3dxmesh);
1486 IDirect3DDevice9_Release(device);
1487 IDirect3D9_Release(d3d);
1488 DestroyWindow(wnd);
1491 #define check_vertex_buffer(mesh, vertices, num_vertices, fvf) \
1492 check_vertex_buffer_(__LINE__, mesh, vertices, num_vertices, fvf)
1493 static void check_vertex_buffer_(int line, ID3DXMesh *mesh, const void *vertices, DWORD num_vertices, DWORD fvf)
1495 DWORD mesh_num_vertices = mesh->lpVtbl->GetNumVertices(mesh);
1496 DWORD mesh_fvf = mesh->lpVtbl->GetFVF(mesh);
1497 const void *mesh_vertices;
1498 HRESULT hr;
1500 ok_(__FILE__,line)(fvf == mesh_fvf, "expected FVF %x, got %x\n", fvf, mesh_fvf);
1501 ok_(__FILE__,line)(num_vertices == mesh_num_vertices,
1502 "Expected %u vertices, got %u\n", num_vertices, mesh_num_vertices);
1504 hr = mesh->lpVtbl->LockVertexBuffer(mesh, D3DLOCK_READONLY, (void**)&mesh_vertices);
1505 ok_(__FILE__,line)(hr == D3D_OK, "LockVertexBuffer returned %x, expected %x (D3D_OK)\n", hr, D3D_OK);
1506 if (FAILED(hr))
1507 return;
1509 if (mesh_fvf == fvf) {
1510 DWORD vertex_size = D3DXGetFVFVertexSize(fvf);
1511 int i;
1512 for (i = 0; i < min(num_vertices, mesh_num_vertices); i++)
1514 const FLOAT *exp_float = vertices;
1515 const FLOAT *got_float = mesh_vertices;
1516 DWORD texcount;
1517 DWORD pos_dim = 0;
1518 int j;
1519 BOOL last_beta_dword = FALSE;
1520 char prefix[128];
1522 switch (fvf & D3DFVF_POSITION_MASK) {
1523 case D3DFVF_XYZ: pos_dim = 3; break;
1524 case D3DFVF_XYZRHW: pos_dim = 4; break;
1525 case D3DFVF_XYZB1:
1526 case D3DFVF_XYZB2:
1527 case D3DFVF_XYZB3:
1528 case D3DFVF_XYZB4:
1529 case D3DFVF_XYZB5:
1530 pos_dim = (fvf & D3DFVF_POSITION_MASK) - D3DFVF_XYZB1 + 1;
1531 if (fvf & (D3DFVF_LASTBETA_UBYTE4 | D3DFVF_LASTBETA_D3DCOLOR))
1533 pos_dim--;
1534 last_beta_dword = TRUE;
1536 break;
1537 case D3DFVF_XYZW: pos_dim = 4; break;
1539 sprintf(prefix, "vertex[%u] position, ", i);
1540 check_floats_(line, prefix, got_float, exp_float, pos_dim);
1541 exp_float += pos_dim;
1542 got_float += pos_dim;
1544 if (last_beta_dword) {
1545 ok_(__FILE__,line)(*(DWORD*)exp_float == *(DWORD*)got_float,
1546 "Vertex[%u]: Expected last beta %08x, got %08x\n", i, *(DWORD*)exp_float, *(DWORD*)got_float);
1547 exp_float++;
1548 got_float++;
1551 if (fvf & D3DFVF_NORMAL) {
1552 sprintf(prefix, "vertex[%u] normal, ", i);
1553 check_floats_(line, prefix, got_float, exp_float, 3);
1554 exp_float += 3;
1555 got_float += 3;
1557 if (fvf & D3DFVF_PSIZE) {
1558 ok_(__FILE__,line)(compare(*exp_float, *got_float),
1559 "Vertex[%u]: Expected psize %g, got %g\n", i, *exp_float, *got_float);
1560 exp_float++;
1561 got_float++;
1563 if (fvf & D3DFVF_DIFFUSE) {
1564 ok_(__FILE__,line)(*(DWORD*)exp_float == *(DWORD*)got_float,
1565 "Vertex[%u]: Expected diffuse %08x, got %08x\n", i, *(DWORD*)exp_float, *(DWORD*)got_float);
1566 exp_float++;
1567 got_float++;
1569 if (fvf & D3DFVF_SPECULAR) {
1570 ok_(__FILE__,line)(*(DWORD*)exp_float == *(DWORD*)got_float,
1571 "Vertex[%u]: Expected specular %08x, got %08x\n", i, *(DWORD*)exp_float, *(DWORD*)got_float);
1572 exp_float++;
1573 got_float++;
1576 texcount = (fvf & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
1577 for (j = 0; j < texcount; j++) {
1578 DWORD dim = (((fvf >> (16 + 2 * j)) + 1) & 0x03) + 1;
1579 sprintf(prefix, "vertex[%u] texture, ", i);
1580 check_floats_(line, prefix, got_float, exp_float, dim);
1581 exp_float += dim;
1582 got_float += dim;
1585 vertices = (BYTE*)vertices + vertex_size;
1586 mesh_vertices = (BYTE*)mesh_vertices + vertex_size;
1590 mesh->lpVtbl->UnlockVertexBuffer(mesh);
1593 #define check_index_buffer(mesh, indices, num_indices, index_size) \
1594 check_index_buffer_(__LINE__, mesh, indices, num_indices, index_size)
1595 static void check_index_buffer_(int line, ID3DXMesh *mesh, const void *indices, DWORD num_indices, DWORD index_size)
1597 DWORD mesh_index_size = (mesh->lpVtbl->GetOptions(mesh) & D3DXMESH_32BIT) ? 4 : 2;
1598 DWORD mesh_num_indices = mesh->lpVtbl->GetNumFaces(mesh) * 3;
1599 const void *mesh_indices;
1600 HRESULT hr;
1601 DWORD i;
1603 ok_(__FILE__,line)(index_size == mesh_index_size,
1604 "Expected index size %u, got %u\n", index_size, mesh_index_size);
1605 ok_(__FILE__,line)(num_indices == mesh_num_indices,
1606 "Expected %u indices, got %u\n", num_indices, mesh_num_indices);
1608 hr = mesh->lpVtbl->LockIndexBuffer(mesh, D3DLOCK_READONLY, (void**)&mesh_indices);
1609 ok_(__FILE__,line)(hr == D3D_OK, "LockIndexBuffer returned %x, expected %x (D3D_OK)\n", hr, D3D_OK);
1610 if (FAILED(hr))
1611 return;
1613 if (mesh_index_size == index_size) {
1614 for (i = 0; i < min(num_indices, mesh_num_indices); i++)
1616 if (index_size == 4)
1617 ok_(__FILE__,line)(*(DWORD*)indices == *(DWORD*)mesh_indices,
1618 "Index[%u]: expected %u, got %u\n", i, *(DWORD*)indices, *(DWORD*)mesh_indices);
1619 else
1620 ok_(__FILE__,line)(*(WORD*)indices == *(WORD*)mesh_indices,
1621 "Index[%u]: expected %u, got %u\n", i, *(WORD*)indices, *(WORD*)mesh_indices);
1622 indices = (BYTE*)indices + index_size;
1623 mesh_indices = (BYTE*)mesh_indices + index_size;
1626 mesh->lpVtbl->UnlockIndexBuffer(mesh);
1629 #define check_matrix(got, expected) check_matrix_(__LINE__, got, expected)
1630 static void check_matrix_(int line, const D3DXMATRIX *got, const D3DXMATRIX *expected)
1632 int i, j;
1633 for (i = 0; i < 4; i++) {
1634 for (j = 0; j < 4; j++) {
1635 ok_(__FILE__,line)(compare(U(*expected).m[i][j], U(*got).m[i][j]),
1636 "matrix[%u][%u]: expected %g, got %g\n",
1637 i, j, U(*expected).m[i][j], U(*got).m[i][j]);
1642 static void check_colorvalue_(int line, const char *prefix, const D3DCOLORVALUE got, const D3DCOLORVALUE expected)
1644 ok_(__FILE__,line)(expected.r == got.r && expected.g == got.g && expected.b == got.b && expected.a == got.a,
1645 "%sExpected (%g, %g, %g, %g), got (%g, %g, %g, %g)\n", prefix,
1646 expected.r, expected.g, expected.b, expected.a, got.r, got.g, got.b, got.a);
1649 #define check_materials(got, got_count, expected, expected_count) \
1650 check_materials_(__LINE__, got, got_count, expected, expected_count)
1651 static void check_materials_(int line, const D3DXMATERIAL *got, DWORD got_count, const D3DXMATERIAL *expected, DWORD expected_count)
1653 int i;
1654 ok_(__FILE__,line)(expected_count == got_count, "Expected %u materials, got %u\n", expected_count, got_count);
1655 if (!expected) {
1656 ok_(__FILE__,line)(got == NULL, "Expected NULL material ptr, got %p\n", got);
1657 return;
1659 for (i = 0; i < min(expected_count, got_count); i++)
1661 if (!expected[i].pTextureFilename)
1662 ok_(__FILE__,line)(got[i].pTextureFilename == NULL,
1663 "Expected NULL pTextureFilename, got %p\n", got[i].pTextureFilename);
1664 else
1665 ok_(__FILE__,line)(!strcmp(expected[i].pTextureFilename, got[i].pTextureFilename),
1666 "Expected '%s' for pTextureFilename, got '%s'\n", expected[i].pTextureFilename, got[i].pTextureFilename);
1667 check_colorvalue_(line, "Diffuse: ", got[i].MatD3D.Diffuse, expected[i].MatD3D.Diffuse);
1668 check_colorvalue_(line, "Ambient: ", got[i].MatD3D.Ambient, expected[i].MatD3D.Ambient);
1669 check_colorvalue_(line, "Specular: ", got[i].MatD3D.Specular, expected[i].MatD3D.Specular);
1670 check_colorvalue_(line, "Emissive: ", got[i].MatD3D.Emissive, expected[i].MatD3D.Emissive);
1671 ok_(__FILE__,line)(expected[i].MatD3D.Power == got[i].MatD3D.Power,
1672 "Power: Expected %g, got %g\n", expected[i].MatD3D.Power, got[i].MatD3D.Power);
1676 #define check_generated_adjacency(mesh, got, epsilon) check_generated_adjacency_(__LINE__, mesh, got, epsilon)
1677 static void check_generated_adjacency_(int line, ID3DXMesh *mesh, const DWORD *got, FLOAT epsilon)
1679 DWORD *expected;
1680 DWORD num_faces = mesh->lpVtbl->GetNumFaces(mesh);
1681 HRESULT hr;
1683 expected = HeapAlloc(GetProcessHeap(), 0, num_faces * sizeof(DWORD) * 3);
1684 if (!expected) {
1685 skip_(__FILE__, line)("Out of memory\n");
1686 return;
1688 hr = mesh->lpVtbl->GenerateAdjacency(mesh, epsilon, expected);
1689 ok_(__FILE__, line)(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
1690 if (SUCCEEDED(hr))
1692 int i;
1693 for (i = 0; i < num_faces; i++)
1695 ok_(__FILE__, line)(expected[i * 3] == got[i * 3] &&
1696 expected[i * 3 + 1] == got[i * 3 + 1] &&
1697 expected[i * 3 + 2] == got[i * 3 + 2],
1698 "Face %u adjacencies: Expected (%u, %u, %u), got (%u, %u, %u)\n", i,
1699 expected[i * 3], expected[i * 3 + 1], expected[i * 3 + 2],
1700 got[i * 3], got[i * 3 + 1], got[i * 3 + 2]);
1703 HeapFree(GetProcessHeap(), 0, expected);
1706 #define check_generated_effects(materials, num_materials, effects) \
1707 check_generated_effects_(__LINE__, materials, num_materials, effects)
1708 static void check_generated_effects_(int line, const D3DXMATERIAL *materials, DWORD num_materials, const D3DXEFFECTINSTANCE *effects)
1710 int i;
1711 static const struct {
1712 const char *name;
1713 DWORD name_size;
1714 DWORD num_bytes;
1715 DWORD value_offset;
1716 } params[] = {
1717 #define EFFECT_TABLE_ENTRY(str, field) \
1718 {str, sizeof(str), sizeof(materials->MatD3D.field), offsetof(D3DXMATERIAL, MatD3D.field)}
1719 EFFECT_TABLE_ENTRY("Diffuse", Diffuse),
1720 EFFECT_TABLE_ENTRY("Power", Power),
1721 EFFECT_TABLE_ENTRY("Specular", Specular),
1722 EFFECT_TABLE_ENTRY("Emissive", Emissive),
1723 EFFECT_TABLE_ENTRY("Ambient", Ambient),
1724 #undef EFFECT_TABLE_ENTRY
1727 if (!num_materials) {
1728 ok_(__FILE__, line)(effects == NULL, "Expected NULL effects, got %p\n", effects);
1729 return;
1731 for (i = 0; i < num_materials; i++)
1733 int j;
1734 DWORD expected_num_defaults = ARRAY_SIZE(params) + (materials[i].pTextureFilename ? 1 : 0);
1736 ok_(__FILE__,line)(expected_num_defaults == effects[i].NumDefaults,
1737 "effect[%u] NumDefaults: Expected %u, got %u\n", i,
1738 expected_num_defaults, effects[i].NumDefaults);
1739 for (j = 0; j < min(ARRAY_SIZE(params), effects[i].NumDefaults); j++)
1741 int k;
1742 D3DXEFFECTDEFAULT *got_param = &effects[i].pDefaults[j];
1743 ok_(__FILE__,line)(!strcmp(params[j].name, got_param->pParamName),
1744 "effect[%u].pDefaults[%u].pParamName: Expected '%s', got '%s'\n", i, j,
1745 params[j].name, got_param->pParamName);
1746 ok_(__FILE__,line)(D3DXEDT_FLOATS == got_param->Type,
1747 "effect[%u].pDefaults[%u].Type: Expected %u, got %u\n", i, j,
1748 D3DXEDT_FLOATS, got_param->Type);
1749 ok_(__FILE__,line)(params[j].num_bytes == got_param->NumBytes,
1750 "effect[%u].pDefaults[%u].NumBytes: Expected %u, got %u\n", i, j,
1751 params[j].num_bytes, got_param->NumBytes);
1752 for (k = 0; k < min(params[j].num_bytes, got_param->NumBytes) / 4; k++)
1754 FLOAT expected = ((FLOAT*)((BYTE*)&materials[i] + params[j].value_offset))[k];
1755 FLOAT got = ((FLOAT*)got_param->pValue)[k];
1756 ok_(__FILE__,line)(compare(expected, got),
1757 "effect[%u].pDefaults[%u] float value %u: Expected %g, got %g\n", i, j, k, expected, got);
1760 if (effects[i].NumDefaults > ARRAY_SIZE(params)) {
1761 D3DXEFFECTDEFAULT *got_param = &effects[i].pDefaults[j];
1762 static const char *expected_name = "Texture0@Name";
1764 ok_(__FILE__,line)(!strcmp(expected_name, got_param->pParamName),
1765 "effect[%u].pDefaults[%u].pParamName: Expected '%s', got '%s'\n", i, j,
1766 expected_name, got_param->pParamName);
1767 ok_(__FILE__,line)(D3DXEDT_STRING == got_param->Type,
1768 "effect[%u].pDefaults[%u].Type: Expected %u, got %u\n", i, j,
1769 D3DXEDT_STRING, got_param->Type);
1770 if (materials[i].pTextureFilename) {
1771 ok_(__FILE__,line)(strlen(materials[i].pTextureFilename) + 1 == got_param->NumBytes,
1772 "effect[%u] texture filename length: Expected %u, got %u\n", i,
1773 (DWORD)strlen(materials[i].pTextureFilename) + 1, got_param->NumBytes);
1774 ok_(__FILE__,line)(!strcmp(materials[i].pTextureFilename, got_param->pValue),
1775 "effect[%u] texture filename: Expected '%s', got '%s'\n", i,
1776 materials[i].pTextureFilename, (char*)got_param->pValue);
1782 static LPSTR strdupA(LPCSTR p)
1784 LPSTR ret;
1785 if (!p) return NULL;
1786 ret = HeapAlloc(GetProcessHeap(), 0, strlen(p) + 1);
1787 if (ret) strcpy(ret, p);
1788 return ret;
1791 static CALLBACK HRESULT ID3DXAllocateHierarchyImpl_DestroyFrame(ID3DXAllocateHierarchy *iface, LPD3DXFRAME frame)
1793 TRACECALLBACK("ID3DXAllocateHierarchyImpl_DestroyFrame(%p, %p)\n", iface, frame);
1794 if (frame) {
1795 HeapFree(GetProcessHeap(), 0, frame->Name);
1796 HeapFree(GetProcessHeap(), 0, frame);
1798 return D3D_OK;
1801 static CALLBACK HRESULT ID3DXAllocateHierarchyImpl_CreateFrame(ID3DXAllocateHierarchy *iface, LPCSTR name, LPD3DXFRAME *new_frame)
1803 LPD3DXFRAME frame;
1805 TRACECALLBACK("ID3DXAllocateHierarchyImpl_CreateFrame(%p, '%s', %p)\n", iface, name, new_frame);
1806 frame = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*frame));
1807 if (!frame)
1808 return E_OUTOFMEMORY;
1809 if (name) {
1810 frame->Name = strdupA(name);
1811 if (!frame->Name) {
1812 HeapFree(GetProcessHeap(), 0, frame);
1813 return E_OUTOFMEMORY;
1816 *new_frame = frame;
1817 return D3D_OK;
1820 static HRESULT destroy_mesh_container(LPD3DXMESHCONTAINER mesh_container)
1822 int i;
1824 if (!mesh_container)
1825 return D3D_OK;
1826 HeapFree(GetProcessHeap(), 0, mesh_container->Name);
1827 if (U(mesh_container->MeshData).pMesh)
1828 IUnknown_Release(U(mesh_container->MeshData).pMesh);
1829 if (mesh_container->pMaterials) {
1830 for (i = 0; i < mesh_container->NumMaterials; i++)
1831 HeapFree(GetProcessHeap(), 0, mesh_container->pMaterials[i].pTextureFilename);
1832 HeapFree(GetProcessHeap(), 0, mesh_container->pMaterials);
1834 if (mesh_container->pEffects) {
1835 for (i = 0; i < mesh_container->NumMaterials; i++) {
1836 HeapFree(GetProcessHeap(), 0, mesh_container->pEffects[i].pEffectFilename);
1837 if (mesh_container->pEffects[i].pDefaults) {
1838 int j;
1839 for (j = 0; j < mesh_container->pEffects[i].NumDefaults; j++) {
1840 HeapFree(GetProcessHeap(), 0, mesh_container->pEffects[i].pDefaults[j].pParamName);
1841 HeapFree(GetProcessHeap(), 0, mesh_container->pEffects[i].pDefaults[j].pValue);
1843 HeapFree(GetProcessHeap(), 0, mesh_container->pEffects[i].pDefaults);
1846 HeapFree(GetProcessHeap(), 0, mesh_container->pEffects);
1848 HeapFree(GetProcessHeap(), 0, mesh_container->pAdjacency);
1849 if (mesh_container->pSkinInfo)
1850 IUnknown_Release(mesh_container->pSkinInfo);
1851 HeapFree(GetProcessHeap(), 0, mesh_container);
1852 return D3D_OK;
1855 static CALLBACK HRESULT ID3DXAllocateHierarchyImpl_DestroyMeshContainer(ID3DXAllocateHierarchy *iface, LPD3DXMESHCONTAINER mesh_container)
1857 TRACECALLBACK("ID3DXAllocateHierarchyImpl_DestroyMeshContainer(%p, %p)\n", iface, mesh_container);
1858 return destroy_mesh_container(mesh_container);
1861 static CALLBACK HRESULT ID3DXAllocateHierarchyImpl_CreateMeshContainer(ID3DXAllocateHierarchy *iface,
1862 LPCSTR name, CONST D3DXMESHDATA *mesh_data, CONST D3DXMATERIAL *materials,
1863 CONST D3DXEFFECTINSTANCE *effects, DWORD num_materials, CONST DWORD *adjacency,
1864 LPD3DXSKININFO skin_info, LPD3DXMESHCONTAINER *new_mesh_container)
1866 LPD3DXMESHCONTAINER mesh_container = NULL;
1867 int i;
1869 TRACECALLBACK("ID3DXAllocateHierarchyImpl_CreateMeshContainer(%p, '%s', %u, %p, %p, %p, %d, %p, %p, %p)\n",
1870 iface, name, mesh_data->Type, U(*mesh_data).pMesh, materials, effects,
1871 num_materials, adjacency, skin_info, *new_mesh_container);
1873 mesh_container = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*mesh_container));
1874 if (!mesh_container)
1875 return E_OUTOFMEMORY;
1877 if (name) {
1878 mesh_container->Name = strdupA(name);
1879 if (!mesh_container->Name)
1880 goto error;
1883 mesh_container->NumMaterials = num_materials;
1884 if (num_materials) {
1885 mesh_container->pMaterials = HeapAlloc(GetProcessHeap(), 0, num_materials * sizeof(*materials));
1886 if (!mesh_container->pMaterials)
1887 goto error;
1889 memcpy(mesh_container->pMaterials, materials, num_materials * sizeof(*materials));
1890 for (i = 0; i < num_materials; i++)
1891 mesh_container->pMaterials[i].pTextureFilename = NULL;
1892 for (i = 0; i < num_materials; i++) {
1893 if (materials[i].pTextureFilename) {
1894 mesh_container->pMaterials[i].pTextureFilename = strdupA(materials[i].pTextureFilename);
1895 if (!mesh_container->pMaterials[i].pTextureFilename)
1896 goto error;
1900 mesh_container->pEffects = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, num_materials * sizeof(*effects));
1901 if (!mesh_container->pEffects)
1902 goto error;
1903 for (i = 0; i < num_materials; i++) {
1904 int j;
1905 const D3DXEFFECTINSTANCE *effect_src = &effects[i];
1906 D3DXEFFECTINSTANCE *effect_dest = &mesh_container->pEffects[i];
1908 if (effect_src->pEffectFilename) {
1909 effect_dest->pEffectFilename = strdupA(effect_src->pEffectFilename);
1910 if (!effect_dest->pEffectFilename)
1911 goto error;
1913 effect_dest->pDefaults = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1914 effect_src->NumDefaults * sizeof(*effect_src->pDefaults));
1915 if (!effect_dest->pDefaults)
1916 goto error;
1917 effect_dest->NumDefaults = effect_src->NumDefaults;
1918 for (j = 0; j < effect_src->NumDefaults; j++) {
1919 const D3DXEFFECTDEFAULT *default_src = &effect_src->pDefaults[j];
1920 D3DXEFFECTDEFAULT *default_dest = &effect_dest->pDefaults[j];
1922 if (default_src->pParamName) {
1923 default_dest->pParamName = strdupA(default_src->pParamName);
1924 if (!default_dest->pParamName)
1925 goto error;
1927 default_dest->NumBytes = default_src->NumBytes;
1928 default_dest->Type = default_src->Type;
1929 default_dest->pValue = HeapAlloc(GetProcessHeap(), 0, default_src->NumBytes);
1930 memcpy(default_dest->pValue, default_src->pValue, default_src->NumBytes);
1935 ok(adjacency != NULL, "Expected non-NULL adjacency, got NULL\n");
1936 if (adjacency) {
1937 if (mesh_data->Type == D3DXMESHTYPE_MESH || mesh_data->Type == D3DXMESHTYPE_PMESH) {
1938 ID3DXBaseMesh *basemesh = (ID3DXBaseMesh*)U(*mesh_data).pMesh;
1939 DWORD num_faces = basemesh->lpVtbl->GetNumFaces(basemesh);
1940 size_t size = num_faces * sizeof(DWORD) * 3;
1941 mesh_container->pAdjacency = HeapAlloc(GetProcessHeap(), 0, size);
1942 if (!mesh_container->pAdjacency)
1943 goto error;
1944 memcpy(mesh_container->pAdjacency, adjacency, size);
1945 } else {
1946 ok(mesh_data->Type == D3DXMESHTYPE_PATCHMESH, "Unknown mesh type %u\n", mesh_data->Type);
1947 if (mesh_data->Type == D3DXMESHTYPE_PATCHMESH)
1948 trace("FIXME: copying adjacency data for patch mesh not implemented\n");
1952 memcpy(&mesh_container->MeshData, mesh_data, sizeof(*mesh_data));
1953 if (U(*mesh_data).pMesh)
1954 IUnknown_AddRef(U(*mesh_data).pMesh);
1955 if (skin_info) {
1956 mesh_container->pSkinInfo = skin_info;
1957 skin_info->lpVtbl->AddRef(skin_info);
1959 *new_mesh_container = mesh_container;
1961 return S_OK;
1962 error:
1963 destroy_mesh_container(mesh_container);
1964 return E_OUTOFMEMORY;
1967 static ID3DXAllocateHierarchyVtbl ID3DXAllocateHierarchyImpl_Vtbl = {
1968 ID3DXAllocateHierarchyImpl_CreateFrame,
1969 ID3DXAllocateHierarchyImpl_CreateMeshContainer,
1970 ID3DXAllocateHierarchyImpl_DestroyFrame,
1971 ID3DXAllocateHierarchyImpl_DestroyMeshContainer,
1973 static ID3DXAllocateHierarchy alloc_hier = { &ID3DXAllocateHierarchyImpl_Vtbl };
1975 #define test_LoadMeshFromX(device, xfile_str, vertex_array, fvf, index_array, materials_array, check_adjacency) \
1976 test_LoadMeshFromX_(__LINE__, device, xfile_str, sizeof(xfile_str) - 1, vertex_array, ARRAY_SIZE(vertex_array), fvf, \
1977 index_array, ARRAY_SIZE(index_array), sizeof(*index_array), materials_array, ARRAY_SIZE(materials_array), \
1978 check_adjacency);
1979 static void test_LoadMeshFromX_(int line, IDirect3DDevice9 *device, const char *xfile_str, size_t xfile_strlen,
1980 const void *vertices, DWORD num_vertices, DWORD fvf, const void *indices, DWORD num_indices, size_t index_size,
1981 const D3DXMATERIAL *expected_materials, DWORD expected_num_materials, BOOL check_adjacency)
1983 HRESULT hr;
1984 ID3DXBuffer *materials = NULL;
1985 ID3DXBuffer *effects = NULL;
1986 ID3DXBuffer *adjacency = NULL;
1987 ID3DXMesh *mesh = NULL;
1988 DWORD num_materials = 0;
1990 /* Adjacency is not checked when the X file contains multiple meshes,
1991 * since calling GenerateAdjacency on the merged mesh is not equivalent
1992 * to calling GenerateAdjacency on the individual meshes and then merging
1993 * the adjacency data. */
1994 hr = D3DXLoadMeshFromXInMemory(xfile_str, xfile_strlen, D3DXMESH_MANAGED, device,
1995 check_adjacency ? &adjacency : NULL, &materials, &effects, &num_materials, &mesh);
1996 ok_(__FILE__,line)(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
1997 if (SUCCEEDED(hr)) {
1998 D3DXMATERIAL *materials_ptr = materials ? ID3DXBuffer_GetBufferPointer(materials) : NULL;
1999 D3DXEFFECTINSTANCE *effects_ptr = effects ? ID3DXBuffer_GetBufferPointer(effects) : NULL;
2000 DWORD *adjacency_ptr = check_adjacency ? ID3DXBuffer_GetBufferPointer(adjacency) : NULL;
2002 check_vertex_buffer_(line, mesh, vertices, num_vertices, fvf);
2003 check_index_buffer_(line, mesh, indices, num_indices, index_size);
2004 check_materials_(line, materials_ptr, num_materials, expected_materials, expected_num_materials);
2005 check_generated_effects_(line, materials_ptr, num_materials, effects_ptr);
2006 if (check_adjacency)
2007 check_generated_adjacency_(line, mesh, adjacency_ptr, 0.0f);
2009 if (materials) ID3DXBuffer_Release(materials);
2010 if (effects) ID3DXBuffer_Release(effects);
2011 if (adjacency) ID3DXBuffer_Release(adjacency);
2012 IUnknown_Release(mesh);
2016 static void D3DXLoadMeshTest(void)
2018 static const char empty_xfile[] = "xof 0303txt 0032";
2019 /*________________________*/
2020 static const char simple_xfile[] =
2021 "xof 0303txt 0032"
2022 "Mesh {"
2023 "3;"
2024 "0.0; 0.0; 0.0;,"
2025 "0.0; 1.0; 0.0;,"
2026 "1.0; 1.0; 0.0;;"
2027 "1;"
2028 "3; 0, 1, 2;;"
2029 "}";
2030 static const WORD simple_index_buffer[] = {0, 1, 2};
2031 static const D3DXVECTOR3 simple_vertex_buffer[] = {
2032 {0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {1.0, 1.0, 0.0}
2034 const DWORD simple_fvf = D3DFVF_XYZ;
2035 static const char framed_xfile[] =
2036 "xof 0303txt 0032"
2037 "Frame {"
2038 "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;; }"
2039 "FrameTransformMatrix {" /* translation (0.0, 0.0, 2.0) */
2040 "1.0, 0.0, 0.0, 0.0,"
2041 "0.0, 1.0, 0.0, 0.0,"
2042 "0.0, 0.0, 1.0, 0.0,"
2043 "0.0, 0.0, 2.0, 1.0;;"
2045 "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;; }"
2046 "FrameTransformMatrix {" /* translation (0.0, 0.0, 3.0) */
2047 "1.0, 0.0, 0.0, 0.0,"
2048 "0.0, 1.0, 0.0, 0.0,"
2049 "0.0, 0.0, 1.0, 0.0,"
2050 "0.0, 0.0, 3.0, 1.0;;"
2052 "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;; }"
2053 "}";
2054 static const WORD framed_index_buffer[] = { 0, 1, 2 };
2055 static const D3DXVECTOR3 framed_vertex_buffers[3][3] = {
2056 {{0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {1.0, 1.0, 0.0}},
2057 {{0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {2.0, 1.0, 0.0}},
2058 {{0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {3.0, 1.0, 0.0}},
2060 static const WORD merged_index_buffer[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
2061 /* frame transforms accumulates for D3DXLoadMeshFromX */
2062 static const D3DXVECTOR3 merged_vertex_buffer[] = {
2063 {0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {1.0, 1.0, 0.0},
2064 {0.0, 0.0, 2.0}, {0.0, 1.0, 2.0}, {2.0, 1.0, 2.0},
2065 {0.0, 0.0, 5.0}, {0.0, 1.0, 5.0}, {3.0, 1.0, 5.0},
2067 const DWORD framed_fvf = D3DFVF_XYZ;
2068 /*________________________*/
2069 static const char box_xfile[] =
2070 "xof 0303txt 0032"
2071 "Mesh {"
2072 "8;" /* DWORD nVertices; */
2073 /* array Vector vertices[nVertices]; */
2074 "0.0; 0.0; 0.0;,"
2075 "0.0; 0.0; 1.0;,"
2076 "0.0; 1.0; 0.0;,"
2077 "0.0; 1.0; 1.0;,"
2078 "1.0; 0.0; 0.0;,"
2079 "1.0; 0.0; 1.0;,"
2080 "1.0; 1.0; 0.0;,"
2081 "1.0; 1.0; 1.0;;"
2082 "6;" /* DWORD nFaces; */
2083 /* array MeshFace faces[nFaces]; */
2084 "4; 0, 1, 3, 2;," /* (left side) */
2085 "4; 2, 3, 7, 6;," /* (top side) */
2086 "4; 6, 7, 5, 4;," /* (right side) */
2087 "4; 1, 0, 4, 5;," /* (bottom side) */
2088 "4; 1, 5, 7, 3;," /* (back side) */
2089 "4; 0, 2, 6, 4;;" /* (front side) */
2090 "MeshNormals {"
2091 "6;" /* DWORD nNormals; */
2092 /* array Vector normals[nNormals]; */
2093 "-1.0; 0.0; 0.0;,"
2094 "0.0; 1.0; 0.0;,"
2095 "1.0; 0.0; 0.0;,"
2096 "0.0; -1.0; 0.0;,"
2097 "0.0; 0.0; 1.0;,"
2098 "0.0; 0.0; -1.0;;"
2099 "6;" /* DWORD nFaceNormals; */
2100 /* array MeshFace faceNormals[nFaceNormals]; */
2101 "4; 0, 0, 0, 0;,"
2102 "4; 1, 1, 1, 1;,"
2103 "4; 2, 2, 2, 2;,"
2104 "4; 3, 3, 3, 3;,"
2105 "4; 4, 4, 4, 4;,"
2106 "4; 5, 5, 5, 5;;"
2108 "MeshMaterialList materials {"
2109 "2;" /* DWORD nMaterials; */
2110 "6;" /* DWORD nFaceIndexes; */
2111 /* array DWORD faceIndexes[nFaceIndexes]; */
2112 "0, 0, 0, 1, 1, 1;;"
2113 "Material {"
2114 /* ColorRGBA faceColor; */
2115 "0.0; 0.0; 1.0; 1.0;;"
2116 /* FLOAT power; */
2117 "0.5;"
2118 /* ColorRGB specularColor; */
2119 "1.0; 1.0; 1.0;;"
2120 /* ColorRGB emissiveColor; */
2121 "0.0; 0.0; 0.0;;"
2123 "Material {"
2124 /* ColorRGBA faceColor; */
2125 "1.0; 1.0; 1.0; 1.0;;"
2126 /* FLOAT power; */
2127 "1.0;"
2128 /* ColorRGB specularColor; */
2129 "1.0; 1.0; 1.0;;"
2130 /* ColorRGB emissiveColor; */
2131 "0.0; 0.0; 0.0;;"
2132 "TextureFilename { \"texture.jpg\"; }"
2135 "MeshVertexColors {"
2136 "8;" /* DWORD nVertexColors; */
2137 /* array IndexedColor vertexColors[nVertexColors]; */
2138 "0; 0.0; 0.0; 0.0; 0.0;;"
2139 "1; 0.0; 0.0; 1.0; 0.1;;"
2140 "2; 0.0; 1.0; 0.0; 0.2;;"
2141 "3; 0.0; 1.0; 1.0; 0.3;;"
2142 "4; 1.0; 0.0; 0.0; 0.4;;"
2143 "5; 1.0; 0.0; 1.0; 0.5;;"
2144 "6; 1.0; 1.0; 0.0; 0.6;;"
2145 "7; 1.0; 1.0; 1.0; 0.7;;"
2147 "MeshTextureCoords {"
2148 "8;" /* DWORD nTextureCoords; */
2149 /* array Coords2d textureCoords[nTextureCoords]; */
2150 "0.0; 1.0;,"
2151 "1.0; 1.0;,"
2152 "0.0; 0.0;,"
2153 "1.0; 0.0;,"
2154 "1.0; 1.0;,"
2155 "0.0; 1.0;,"
2156 "1.0; 0.0;,"
2157 "0.0; 0.0;;"
2159 "}";
2160 static const WORD box_index_buffer[] = {
2161 0, 1, 3,
2162 0, 3, 2,
2163 8, 9, 7,
2164 8, 7, 6,
2165 10, 11, 5,
2166 10, 5, 4,
2167 12, 13, 14,
2168 12, 14, 15,
2169 16, 17, 18,
2170 16, 18, 19,
2171 20, 21, 22,
2172 20, 22, 23,
2174 static const struct {
2175 D3DXVECTOR3 position;
2176 D3DXVECTOR3 normal;
2177 D3DCOLOR diffuse;
2178 D3DXVECTOR2 tex_coords;
2179 } box_vertex_buffer[] = {
2180 {{0.0, 0.0, 0.0}, {-1.0, 0.0, 0.0}, 0x00000000, {0.0, 1.0}},
2181 {{0.0, 0.0, 1.0}, {-1.0, 0.0, 0.0}, 0x1a0000ff, {1.0, 1.0}},
2182 {{0.0, 1.0, 0.0}, {-1.0, 0.0, 0.0}, 0x3300ff00, {0.0, 0.0}},
2183 {{0.0, 1.0, 1.0}, {-1.0, 0.0, 0.0}, 0x4d00ffff, {1.0, 0.0}},
2184 {{1.0, 0.0, 0.0}, {1.0, 0.0, 0.0}, 0x66ff0000, {1.0, 1.0}},
2185 {{1.0, 0.0, 1.0}, {1.0, 0.0, 0.0}, 0x80ff00ff, {0.0, 1.0}},
2186 {{1.0, 1.0, 0.0}, {0.0, 1.0, 0.0}, 0x99ffff00, {1.0, 0.0}},
2187 {{1.0, 1.0, 1.0}, {0.0, 1.0, 0.0}, 0xb3ffffff, {0.0, 0.0}},
2188 {{0.0, 1.0, 0.0}, {0.0, 1.0, 0.0}, 0x3300ff00, {0.0, 0.0}},
2189 {{0.0, 1.0, 1.0}, {0.0, 1.0, 0.0}, 0x4d00ffff, {1.0, 0.0}},
2190 {{1.0, 1.0, 0.0}, {1.0, 0.0, 0.0}, 0x99ffff00, {1.0, 0.0}},
2191 {{1.0, 1.0, 1.0}, {1.0, 0.0, 0.0}, 0xb3ffffff, {0.0, 0.0}},
2192 {{0.0, 0.0, 1.0}, {0.0, -1.0, 0.0}, 0x1a0000ff, {1.0, 1.0}},
2193 {{0.0, 0.0, 0.0}, {0.0, -1.0, 0.0}, 0x00000000, {0.0, 1.0}},
2194 {{1.0, 0.0, 0.0}, {0.0, -1.0, 0.0}, 0x66ff0000, {1.0, 1.0}},
2195 {{1.0, 0.0, 1.0}, {0.0, -1.0, 0.0}, 0x80ff00ff, {0.0, 1.0}},
2196 {{0.0, 0.0, 1.0}, {0.0, 0.0, 1.0}, 0x1a0000ff, {1.0, 1.0}},
2197 {{1.0, 0.0, 1.0}, {0.0, 0.0, 1.0}, 0x80ff00ff, {0.0, 1.0}},
2198 {{1.0, 1.0, 1.0}, {0.0, 0.0, 1.0}, 0xb3ffffff, {0.0, 0.0}},
2199 {{0.0, 1.0, 1.0}, {0.0, 0.0, 1.0}, 0x4d00ffff, {1.0, 0.0}},
2200 {{0.0, 0.0, 0.0}, {0.0, 0.0, -1.0}, 0x00000000, {0.0, 1.0}},
2201 {{0.0, 1.0, 0.0}, {0.0, 0.0, -1.0}, 0x3300ff00, {0.0, 0.0}},
2202 {{1.0, 1.0, 0.0}, {0.0, 0.0, -1.0}, 0x99ffff00, {1.0, 0.0}},
2203 {{1.0, 0.0, 0.0}, {0.0, 0.0, -1.0}, 0x66ff0000, {1.0, 1.0}},
2205 static const D3DXMATERIAL box_materials[] = {
2208 {0.0, 0.0, 1.0, 1.0}, /* Diffuse */
2209 {0.0, 0.0, 0.0, 1.0}, /* Ambient */
2210 {1.0, 1.0, 1.0, 1.0}, /* Specular */
2211 {0.0, 0.0, 0.0, 1.0}, /* Emissive */
2212 0.5, /* Power */
2214 NULL, /* pTextureFilename */
2218 {1.0, 1.0, 1.0, 1.0}, /* Diffuse */
2219 {0.0, 0.0, 0.0, 1.0}, /* Ambient */
2220 {1.0, 1.0, 1.0, 1.0}, /* Specular */
2221 {0.0, 0.0, 0.0, 1.0}, /* Emissive */
2222 1.0, /* Power */
2224 (char *)"texture.jpg", /* pTextureFilename */
2227 const DWORD box_fvf = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_TEX1;
2228 /*________________________*/
2229 static const D3DXMATERIAL default_materials[] = {
2232 {0.5, 0.5, 0.5, 0.0}, /* Diffuse */
2233 {0.0, 0.0, 0.0, 0.0}, /* Ambient */
2234 {0.5, 0.5, 0.5, 0.0}, /* Specular */
2235 {0.0, 0.0, 0.0, 0.0}, /* Emissive */
2236 0.0, /* Power */
2238 NULL, /* pTextureFilename */
2241 HRESULT hr;
2242 HWND wnd = NULL;
2243 IDirect3D9 *d3d = NULL;
2244 IDirect3DDevice9 *device = NULL;
2245 D3DPRESENT_PARAMETERS d3dpp;
2246 ID3DXMesh *mesh = NULL;
2247 D3DXFRAME *frame_hier = NULL;
2248 D3DXMATRIX transform;
2250 wnd = CreateWindow("static", "d3dx9_test", WS_POPUP, 0, 0, 1000, 1000, NULL, NULL, NULL, NULL);
2251 if (!wnd)
2253 skip("Couldn't create application window\n");
2254 return;
2256 d3d = Direct3DCreate9(D3D_SDK_VERSION);
2257 if (!d3d)
2259 skip("Couldn't create IDirect3D9 object\n");
2260 goto cleanup;
2263 ZeroMemory(&d3dpp, sizeof(d3dpp));
2264 d3dpp.Windowed = TRUE;
2265 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2266 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, wnd, D3DCREATE_MIXED_VERTEXPROCESSING, &d3dpp, &device);
2267 if (FAILED(hr))
2269 skip("Failed to create IDirect3DDevice9 object %#x\n", hr);
2270 goto cleanup;
2273 hr = D3DXLoadMeshHierarchyFromXInMemory(NULL, sizeof(simple_xfile) - 1,
2274 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
2275 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2277 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, 0,
2278 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
2279 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2281 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1,
2282 D3DXMESH_MANAGED, NULL, &alloc_hier, NULL, &frame_hier, NULL);
2283 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2285 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1,
2286 D3DXMESH_MANAGED, device, NULL, NULL, &frame_hier, NULL);
2287 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2289 hr = D3DXLoadMeshHierarchyFromXInMemory(empty_xfile, sizeof(empty_xfile) - 1,
2290 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
2291 ok(hr == E_FAIL, "Expected E_FAIL, got %#x\n", hr);
2293 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1,
2294 D3DXMESH_MANAGED, device, &alloc_hier, NULL, NULL, NULL);
2295 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2297 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1,
2298 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
2299 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2300 if (SUCCEEDED(hr)) {
2301 D3DXMESHCONTAINER *container = frame_hier->pMeshContainer;
2303 ok(frame_hier->Name == NULL, "Expected NULL, got '%s'\n", frame_hier->Name);
2304 D3DXMatrixIdentity(&transform);
2305 check_matrix(&frame_hier->TransformationMatrix, &transform);
2307 ok(!strcmp(container->Name, ""), "Expected '', got '%s'\n", container->Name);
2308 ok(container->MeshData.Type == D3DXMESHTYPE_MESH, "Expected %d, got %d\n",
2309 D3DXMESHTYPE_MESH, container->MeshData.Type);
2310 mesh = U(container->MeshData).pMesh;
2311 check_vertex_buffer(mesh, simple_vertex_buffer, ARRAY_SIZE(simple_vertex_buffer), simple_fvf);
2312 check_index_buffer(mesh, simple_index_buffer, ARRAY_SIZE(simple_index_buffer), sizeof(*simple_index_buffer));
2313 check_materials(container->pMaterials, container->NumMaterials, NULL, 0);
2314 check_generated_effects(container->pMaterials, container->NumMaterials, container->pEffects);
2315 check_generated_adjacency(mesh, container->pAdjacency, 0.0f);
2316 hr = D3DXFrameDestroy(frame_hier, &alloc_hier);
2317 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2318 frame_hier = NULL;
2321 hr = D3DXLoadMeshHierarchyFromXInMemory(box_xfile, sizeof(box_xfile) - 1,
2322 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
2323 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2324 if (SUCCEEDED(hr)) {
2325 D3DXMESHCONTAINER *container = frame_hier->pMeshContainer;
2327 ok(frame_hier->Name == NULL, "Expected NULL, got '%s'\n", frame_hier->Name);
2328 D3DXMatrixIdentity(&transform);
2329 check_matrix(&frame_hier->TransformationMatrix, &transform);
2331 ok(!strcmp(container->Name, ""), "Expected '', got '%s'\n", container->Name);
2332 ok(container->MeshData.Type == D3DXMESHTYPE_MESH, "Expected %d, got %d\n",
2333 D3DXMESHTYPE_MESH, container->MeshData.Type);
2334 mesh = U(container->MeshData).pMesh;
2335 check_vertex_buffer(mesh, box_vertex_buffer, ARRAY_SIZE(box_vertex_buffer), box_fvf);
2336 check_index_buffer(mesh, box_index_buffer, ARRAY_SIZE(box_index_buffer), sizeof(*box_index_buffer));
2337 check_materials(container->pMaterials, container->NumMaterials, box_materials, ARRAY_SIZE(box_materials));
2338 check_generated_effects(container->pMaterials, container->NumMaterials, container->pEffects);
2339 check_generated_adjacency(mesh, container->pAdjacency, 0.0f);
2340 hr = D3DXFrameDestroy(frame_hier, &alloc_hier);
2341 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2342 frame_hier = NULL;
2345 hr = D3DXLoadMeshHierarchyFromXInMemory(framed_xfile, sizeof(framed_xfile) - 1,
2346 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
2347 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2348 if (SUCCEEDED(hr)) {
2349 D3DXMESHCONTAINER *container = frame_hier->pMeshContainer;
2350 int i;
2352 ok(!strcmp(frame_hier->Name, ""), "Expected '', got '%s'\n", frame_hier->Name);
2353 /* last frame transform replaces the first */
2354 D3DXMatrixIdentity(&transform);
2355 U(transform).m[3][2] = 3.0;
2356 check_matrix(&frame_hier->TransformationMatrix, &transform);
2358 for (i = 0; i < 3; i++) {
2359 ok(!strcmp(container->Name, ""), "Expected '', got '%s'\n", container->Name);
2360 ok(container->MeshData.Type == D3DXMESHTYPE_MESH, "Expected %d, got %d\n",
2361 D3DXMESHTYPE_MESH, container->MeshData.Type);
2362 mesh = U(container->MeshData).pMesh;
2363 check_vertex_buffer(mesh, framed_vertex_buffers[i], ARRAY_SIZE(framed_vertex_buffers[0]), framed_fvf);
2364 check_index_buffer(mesh, framed_index_buffer, ARRAY_SIZE(framed_index_buffer), sizeof(*framed_index_buffer));
2365 check_materials(container->pMaterials, container->NumMaterials, NULL, 0);
2366 check_generated_effects(container->pMaterials, container->NumMaterials, container->pEffects);
2367 check_generated_adjacency(mesh, container->pAdjacency, 0.0f);
2368 container = container->pNextMeshContainer;
2370 ok(container == NULL, "Expected NULL, got %p\n", container);
2371 hr = D3DXFrameDestroy(frame_hier, &alloc_hier);
2372 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2373 frame_hier = NULL;
2377 hr = D3DXLoadMeshFromXInMemory(NULL, 0, D3DXMESH_MANAGED,
2378 device, NULL, NULL, NULL, NULL, &mesh);
2379 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2381 hr = D3DXLoadMeshFromXInMemory(NULL, sizeof(simple_xfile) - 1, D3DXMESH_MANAGED,
2382 device, NULL, NULL, NULL, NULL, &mesh);
2383 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2385 hr = D3DXLoadMeshFromXInMemory(simple_xfile, 0, D3DXMESH_MANAGED,
2386 device, NULL, NULL, NULL, NULL, &mesh);
2387 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2389 hr = D3DXLoadMeshFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1, D3DXMESH_MANAGED,
2390 device, NULL, NULL, NULL, NULL, NULL);
2391 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2393 hr = D3DXLoadMeshFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1, D3DXMESH_MANAGED,
2394 NULL, NULL, NULL, NULL, NULL, &mesh);
2395 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2397 hr = D3DXLoadMeshFromXInMemory(empty_xfile, sizeof(empty_xfile) - 1, D3DXMESH_MANAGED,
2398 device, NULL, NULL, NULL, NULL, &mesh);
2399 ok(hr == E_FAIL, "Expected E_FAIL, got %#x\n", hr);
2401 hr = D3DXLoadMeshFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1, D3DXMESH_MANAGED,
2402 device, NULL, NULL, NULL, NULL, &mesh);
2403 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2404 if (SUCCEEDED(hr))
2405 IUnknown_Release(mesh);
2407 test_LoadMeshFromX(device, simple_xfile, simple_vertex_buffer, simple_fvf, simple_index_buffer, default_materials, TRUE);
2408 test_LoadMeshFromX(device, box_xfile, box_vertex_buffer, box_fvf, box_index_buffer, box_materials, TRUE);
2409 test_LoadMeshFromX(device, framed_xfile, merged_vertex_buffer, framed_fvf, merged_index_buffer, default_materials, FALSE);
2411 cleanup:
2412 if (device) IDirect3DDevice9_Release(device);
2413 if (d3d) IDirect3D9_Release(d3d);
2414 if (wnd) DestroyWindow(wnd);
2417 static void D3DXCreateBoxTest(void)
2419 HRESULT hr;
2420 HWND wnd;
2421 WNDCLASS wc={0};
2422 IDirect3D9* d3d;
2423 IDirect3DDevice9* device;
2424 D3DPRESENT_PARAMETERS d3dpp;
2425 ID3DXMesh* box;
2426 ID3DXBuffer* ppBuffer;
2427 DWORD *buffer;
2428 static const DWORD adjacency[36]=
2429 {6, 9, 1, 2, 10, 0,
2430 1, 9, 3, 4, 10, 2,
2431 3, 8, 5, 7, 11, 4,
2432 0, 11, 7, 5, 8, 6,
2433 7, 4, 9, 2, 0, 8,
2434 1, 3, 11, 5, 6, 10};
2435 unsigned int i;
2437 wc.lpfnWndProc = DefWindowProcA;
2438 wc.lpszClassName = "d3dx9_test_wc";
2439 if (!RegisterClass(&wc))
2441 skip("RegisterClass failed\n");
2442 return;
2445 wnd = CreateWindow("d3dx9_test_wc", "d3dx9_test",
2446 WS_SYSMENU | WS_POPUP , 0, 0, 640, 480, 0, 0, 0, 0);
2447 ok(wnd != NULL, "Expected to have a window, received NULL\n");
2448 if (!wnd)
2450 skip("Couldn't create application window\n");
2451 return;
2454 d3d = Direct3DCreate9(D3D_SDK_VERSION);
2455 if (!d3d)
2457 skip("Couldn't create IDirect3D9 object\n");
2458 DestroyWindow(wnd);
2459 return;
2462 memset(&d3dpp, 0, sizeof(d3dpp));
2463 d3dpp.Windowed = TRUE;
2464 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2465 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, wnd, D3DCREATE_MIXED_VERTEXPROCESSING, &d3dpp, &device);
2466 if (FAILED(hr))
2468 skip("Failed to create IDirect3DDevice9 object %#x\n", hr);
2469 IDirect3D9_Release(d3d);
2470 DestroyWindow(wnd);
2471 return;
2474 hr = D3DXCreateBox(device,2.0f,20.0f,4.9f,NULL, &ppBuffer);
2475 todo_wine ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2477 hr = D3DXCreateBox(NULL,22.0f,20.0f,4.9f,&box, &ppBuffer);
2478 todo_wine ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2480 hr = D3DXCreateBox(device,-2.0f,20.0f,4.9f,&box, &ppBuffer);
2481 todo_wine ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2483 hr = D3DXCreateBox(device,22.0f,-20.0f,4.9f,&box, &ppBuffer);
2484 todo_wine ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2486 hr = D3DXCreateBox(device,22.0f,20.0f,-4.9f,&box, &ppBuffer);
2487 todo_wine ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2489 ppBuffer = NULL;
2490 hr = D3DXCreateBox(device,10.9f,20.0f,4.9f,&box, &ppBuffer);
2491 todo_wine ok(hr==D3D_OK, "Expected D3D_OK, received %#x\n", hr);
2493 if (FAILED(hr))
2495 skip("D3DXCreateBox failed\n");
2496 goto end;
2499 buffer = ID3DXBuffer_GetBufferPointer(ppBuffer);
2500 for(i=0; i<36; i++)
2501 todo_wine ok(adjacency[i]==buffer[i], "expected adjacency %d: %#x, received %#x\n",i,adjacency[i], buffer[i]);
2503 box->lpVtbl->Release(box);
2505 end:
2506 IDirect3DDevice9_Release(device);
2507 IDirect3D9_Release(d3d);
2508 if (ppBuffer) ID3DXBuffer_Release(ppBuffer);
2509 DestroyWindow(wnd);
2512 struct sincos_table
2514 float *sin;
2515 float *cos;
2518 static void free_sincos_table(struct sincos_table *sincos_table)
2520 HeapFree(GetProcessHeap(), 0, sincos_table->cos);
2521 HeapFree(GetProcessHeap(), 0, sincos_table->sin);
2524 /* pre compute sine and cosine tables; caller must free */
2525 static BOOL compute_sincos_table(struct sincos_table *sincos_table, float angle_start, float angle_step, int n)
2527 float angle;
2528 int i;
2530 sincos_table->sin = HeapAlloc(GetProcessHeap(), 0, n * sizeof(*sincos_table->sin));
2531 if (!sincos_table->sin)
2533 return FALSE;
2535 sincos_table->cos = HeapAlloc(GetProcessHeap(), 0, n * sizeof(*sincos_table->cos));
2536 if (!sincos_table->cos)
2538 HeapFree(GetProcessHeap(), 0, sincos_table->sin);
2539 return FALSE;
2542 angle = angle_start;
2543 for (i = 0; i < n; i++)
2545 sincos_table->sin[i] = sin(angle);
2546 sincos_table->cos[i] = cos(angle);
2547 angle += angle_step;
2550 return TRUE;
2553 static WORD vertex_index(UINT slices, int slice, int stack)
2555 return stack*slices+slice+1;
2558 /* slices = subdivisions along xy plane, stacks = subdivisions along z axis */
2559 static BOOL compute_sphere(struct mesh *mesh, FLOAT radius, UINT slices, UINT stacks)
2561 float theta_step, theta_start;
2562 struct sincos_table theta;
2563 float phi_step, phi_start;
2564 struct sincos_table phi;
2565 DWORD number_of_vertices, number_of_faces;
2566 DWORD vertex, face;
2567 int slice, stack;
2569 /* theta = angle on xy plane wrt x axis */
2570 theta_step = M_PI / stacks;
2571 theta_start = theta_step;
2573 /* phi = angle on xz plane wrt z axis */
2574 phi_step = -2 * M_PI / slices;
2575 phi_start = M_PI / 2;
2577 if (!compute_sincos_table(&theta, theta_start, theta_step, stacks))
2579 return FALSE;
2581 if (!compute_sincos_table(&phi, phi_start, phi_step, slices))
2583 free_sincos_table(&theta);
2584 return FALSE;
2587 number_of_vertices = 2 + slices * (stacks-1);
2588 number_of_faces = 2 * slices + (stacks - 2) * (2 * slices);
2590 if (!new_mesh(mesh, number_of_vertices, number_of_faces))
2592 free_sincos_table(&phi);
2593 free_sincos_table(&theta);
2594 return FALSE;
2597 vertex = 0;
2598 face = 0;
2600 mesh->vertices[vertex].normal.x = 0.0f;
2601 mesh->vertices[vertex].normal.y = 0.0f;
2602 mesh->vertices[vertex].normal.z = 1.0f;
2603 mesh->vertices[vertex].position.x = 0.0f;
2604 mesh->vertices[vertex].position.y = 0.0f;
2605 mesh->vertices[vertex].position.z = radius;
2606 vertex++;
2608 for (stack = 0; stack < stacks - 1; stack++)
2610 for (slice = 0; slice < slices; slice++)
2612 mesh->vertices[vertex].normal.x = theta.sin[stack] * phi.cos[slice];
2613 mesh->vertices[vertex].normal.y = theta.sin[stack] * phi.sin[slice];
2614 mesh->vertices[vertex].normal.z = theta.cos[stack];
2615 mesh->vertices[vertex].position.x = radius * theta.sin[stack] * phi.cos[slice];
2616 mesh->vertices[vertex].position.y = radius * theta.sin[stack] * phi.sin[slice];
2617 mesh->vertices[vertex].position.z = radius * theta.cos[stack];
2618 vertex++;
2620 if (slice > 0)
2622 if (stack == 0)
2624 /* top stack is triangle fan */
2625 mesh->faces[face][0] = 0;
2626 mesh->faces[face][1] = slice + 1;
2627 mesh->faces[face][2] = slice;
2628 face++;
2630 else
2632 /* stacks in between top and bottom are quad strips */
2633 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
2634 mesh->faces[face][1] = vertex_index(slices, slice, stack-1);
2635 mesh->faces[face][2] = vertex_index(slices, slice-1, stack);
2636 face++;
2638 mesh->faces[face][0] = vertex_index(slices, slice, stack-1);
2639 mesh->faces[face][1] = vertex_index(slices, slice, stack);
2640 mesh->faces[face][2] = vertex_index(slices, slice-1, stack);
2641 face++;
2646 if (stack == 0)
2648 mesh->faces[face][0] = 0;
2649 mesh->faces[face][1] = 1;
2650 mesh->faces[face][2] = slice;
2651 face++;
2653 else
2655 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
2656 mesh->faces[face][1] = vertex_index(slices, 0, stack-1);
2657 mesh->faces[face][2] = vertex_index(slices, slice-1, stack);
2658 face++;
2660 mesh->faces[face][0] = vertex_index(slices, 0, stack-1);
2661 mesh->faces[face][1] = vertex_index(slices, 0, stack);
2662 mesh->faces[face][2] = vertex_index(slices, slice-1, stack);
2663 face++;
2667 mesh->vertices[vertex].position.x = 0.0f;
2668 mesh->vertices[vertex].position.y = 0.0f;
2669 mesh->vertices[vertex].position.z = -radius;
2670 mesh->vertices[vertex].normal.x = 0.0f;
2671 mesh->vertices[vertex].normal.y = 0.0f;
2672 mesh->vertices[vertex].normal.z = -1.0f;
2674 /* bottom stack is triangle fan */
2675 for (slice = 1; slice < slices; slice++)
2677 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
2678 mesh->faces[face][1] = vertex_index(slices, slice, stack-1);
2679 mesh->faces[face][2] = vertex;
2680 face++;
2683 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
2684 mesh->faces[face][1] = vertex_index(slices, 0, stack-1);
2685 mesh->faces[face][2] = vertex;
2687 free_sincos_table(&phi);
2688 free_sincos_table(&theta);
2690 return TRUE;
2693 static void test_sphere(IDirect3DDevice9 *device, FLOAT radius, UINT slices, UINT stacks)
2695 HRESULT hr;
2696 ID3DXMesh *sphere;
2697 struct mesh mesh;
2698 char name[256];
2700 hr = D3DXCreateSphere(device, radius, slices, stacks, &sphere, NULL);
2701 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
2702 if (hr != D3D_OK)
2704 skip("Couldn't create sphere\n");
2705 return;
2708 if (!compute_sphere(&mesh, radius, slices, stacks))
2710 skip("Couldn't create mesh\n");
2711 sphere->lpVtbl->Release(sphere);
2712 return;
2715 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
2717 sprintf(name, "sphere (%g, %u, %u)", radius, slices, stacks);
2718 compare_mesh(name, sphere, &mesh);
2720 free_mesh(&mesh);
2722 sphere->lpVtbl->Release(sphere);
2725 static void D3DXCreateSphereTest(void)
2727 HRESULT hr;
2728 HWND wnd;
2729 IDirect3D9* d3d;
2730 IDirect3DDevice9* device;
2731 D3DPRESENT_PARAMETERS d3dpp;
2732 ID3DXMesh* sphere = NULL;
2734 hr = D3DXCreateSphere(NULL, 0.0f, 0, 0, NULL, NULL);
2735 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
2737 hr = D3DXCreateSphere(NULL, 0.1f, 0, 0, NULL, NULL);
2738 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
2740 hr = D3DXCreateSphere(NULL, 0.0f, 1, 0, NULL, NULL);
2741 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
2743 hr = D3DXCreateSphere(NULL, 0.0f, 0, 1, NULL, NULL);
2744 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
2746 wnd = CreateWindow("static", "d3dx9_test", 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL);
2747 d3d = Direct3DCreate9(D3D_SDK_VERSION);
2748 if (!wnd)
2750 skip("Couldn't create application window\n");
2751 return;
2753 if (!d3d)
2755 skip("Couldn't create IDirect3D9 object\n");
2756 DestroyWindow(wnd);
2757 return;
2760 ZeroMemory(&d3dpp, sizeof(d3dpp));
2761 d3dpp.Windowed = TRUE;
2762 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2763 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, wnd, D3DCREATE_MIXED_VERTEXPROCESSING, &d3dpp, &device);
2764 if (FAILED(hr))
2766 skip("Failed to create IDirect3DDevice9 object %#x\n", hr);
2767 IDirect3D9_Release(d3d);
2768 DestroyWindow(wnd);
2769 return;
2772 hr = D3DXCreateSphere(device, 1.0f, 1, 1, &sphere, NULL);
2773 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
2775 hr = D3DXCreateSphere(device, 1.0f, 2, 1, &sphere, NULL);
2776 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
2778 hr = D3DXCreateSphere(device, 1.0f, 1, 2, &sphere, NULL);
2779 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
2781 hr = D3DXCreateSphere(device, -0.1f, 1, 2, &sphere, NULL);
2782 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
2784 test_sphere(device, 0.0f, 2, 2);
2785 test_sphere(device, 1.0f, 2, 2);
2786 test_sphere(device, 1.0f, 3, 2);
2787 test_sphere(device, 1.0f, 4, 4);
2788 test_sphere(device, 1.0f, 3, 4);
2789 test_sphere(device, 5.0f, 6, 7);
2790 test_sphere(device, 10.0f, 11, 12);
2792 IDirect3DDevice9_Release(device);
2793 IDirect3D9_Release(d3d);
2794 DestroyWindow(wnd);
2797 static BOOL compute_cylinder(struct mesh *mesh, FLOAT radius1, FLOAT radius2, FLOAT length, UINT slices, UINT stacks)
2799 float theta_step, theta_start;
2800 struct sincos_table theta;
2801 FLOAT delta_radius, radius, radius_step;
2802 FLOAT z, z_step, z_normal;
2803 DWORD number_of_vertices, number_of_faces;
2804 DWORD vertex, face;
2805 int slice, stack;
2807 /* theta = angle on xy plane wrt x axis */
2808 theta_step = -2 * M_PI / slices;
2809 theta_start = M_PI / 2;
2811 if (!compute_sincos_table(&theta, theta_start, theta_step, slices))
2813 return FALSE;
2816 number_of_vertices = 2 + (slices * (3 + stacks));
2817 number_of_faces = 2 * slices + stacks * (2 * slices);
2819 if (!new_mesh(mesh, number_of_vertices, number_of_faces))
2821 free_sincos_table(&theta);
2822 return FALSE;
2825 vertex = 0;
2826 face = 0;
2828 delta_radius = radius1 - radius2;
2829 radius = radius1;
2830 radius_step = delta_radius / stacks;
2832 z = -length / 2;
2833 z_step = length / stacks;
2834 z_normal = delta_radius / length;
2835 if (isnan(z_normal))
2837 z_normal = 0.0f;
2840 mesh->vertices[vertex].normal.x = 0.0f;
2841 mesh->vertices[vertex].normal.y = 0.0f;
2842 mesh->vertices[vertex].normal.z = -1.0f;
2843 mesh->vertices[vertex].position.x = 0.0f;
2844 mesh->vertices[vertex].position.y = 0.0f;
2845 mesh->vertices[vertex++].position.z = z;
2847 for (slice = 0; slice < slices; slice++, vertex++)
2849 mesh->vertices[vertex].normal.x = 0.0f;
2850 mesh->vertices[vertex].normal.y = 0.0f;
2851 mesh->vertices[vertex].normal.z = -1.0f;
2852 mesh->vertices[vertex].position.x = radius * theta.cos[slice];
2853 mesh->vertices[vertex].position.y = radius * theta.sin[slice];
2854 mesh->vertices[vertex].position.z = z;
2856 if (slice > 0)
2858 mesh->faces[face][0] = 0;
2859 mesh->faces[face][1] = slice;
2860 mesh->faces[face++][2] = slice + 1;
2864 mesh->faces[face][0] = 0;
2865 mesh->faces[face][1] = slice;
2866 mesh->faces[face++][2] = 1;
2868 for (stack = 1; stack <= stacks+1; stack++)
2870 for (slice = 0; slice < slices; slice++, vertex++)
2872 mesh->vertices[vertex].normal.x = theta.cos[slice];
2873 mesh->vertices[vertex].normal.y = theta.sin[slice];
2874 mesh->vertices[vertex].normal.z = z_normal;
2875 D3DXVec3Normalize(&mesh->vertices[vertex].normal, &mesh->vertices[vertex].normal);
2876 mesh->vertices[vertex].position.x = radius * theta.cos[slice];
2877 mesh->vertices[vertex].position.y = radius * theta.sin[slice];
2878 mesh->vertices[vertex].position.z = z;
2880 if (stack > 1 && slice > 0)
2882 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
2883 mesh->faces[face][1] = vertex_index(slices, slice-1, stack);
2884 mesh->faces[face++][2] = vertex_index(slices, slice, stack-1);
2886 mesh->faces[face][0] = vertex_index(slices, slice, stack-1);
2887 mesh->faces[face][1] = vertex_index(slices, slice-1, stack);
2888 mesh->faces[face++][2] = vertex_index(slices, slice, stack);
2892 if (stack > 1)
2894 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
2895 mesh->faces[face][1] = vertex_index(slices, slice-1, stack);
2896 mesh->faces[face++][2] = vertex_index(slices, 0, stack-1);
2898 mesh->faces[face][0] = vertex_index(slices, 0, stack-1);
2899 mesh->faces[face][1] = vertex_index(slices, slice-1, stack);
2900 mesh->faces[face++][2] = vertex_index(slices, 0, stack);
2903 if (stack < stacks + 1)
2905 z += z_step;
2906 radius -= radius_step;
2910 for (slice = 0; slice < slices; slice++, vertex++)
2912 mesh->vertices[vertex].normal.x = 0.0f;
2913 mesh->vertices[vertex].normal.y = 0.0f;
2914 mesh->vertices[vertex].normal.z = 1.0f;
2915 mesh->vertices[vertex].position.x = radius * theta.cos[slice];
2916 mesh->vertices[vertex].position.y = radius * theta.sin[slice];
2917 mesh->vertices[vertex].position.z = z;
2919 if (slice > 0)
2921 mesh->faces[face][0] = vertex_index(slices, slice-1, stack);
2922 mesh->faces[face][1] = number_of_vertices - 1;
2923 mesh->faces[face++][2] = vertex_index(slices, slice, stack);
2927 mesh->vertices[vertex].position.x = 0.0f;
2928 mesh->vertices[vertex].position.y = 0.0f;
2929 mesh->vertices[vertex].position.z = z;
2930 mesh->vertices[vertex].normal.x = 0.0f;
2931 mesh->vertices[vertex].normal.y = 0.0f;
2932 mesh->vertices[vertex].normal.z = 1.0f;
2934 mesh->faces[face][0] = vertex_index(slices, slice-1, stack);
2935 mesh->faces[face][1] = number_of_vertices - 1;
2936 mesh->faces[face][2] = vertex_index(slices, 0, stack);
2938 free_sincos_table(&theta);
2940 return TRUE;
2943 static void test_cylinder(IDirect3DDevice9 *device, FLOAT radius1, FLOAT radius2, FLOAT length, UINT slices, UINT stacks)
2945 HRESULT hr;
2946 ID3DXMesh *cylinder;
2947 struct mesh mesh;
2948 char name[256];
2950 hr = D3DXCreateCylinder(device, radius1, radius2, length, slices, stacks, &cylinder, NULL);
2951 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
2952 if (hr != D3D_OK)
2954 skip("Couldn't create cylinder\n");
2955 return;
2958 if (!compute_cylinder(&mesh, radius1, radius2, length, slices, stacks))
2960 skip("Couldn't create mesh\n");
2961 cylinder->lpVtbl->Release(cylinder);
2962 return;
2965 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
2967 sprintf(name, "cylinder (%g, %g, %g, %u, %u)", radius1, radius2, length, slices, stacks);
2968 compare_mesh(name, cylinder, &mesh);
2970 free_mesh(&mesh);
2972 cylinder->lpVtbl->Release(cylinder);
2975 static void D3DXCreateCylinderTest(void)
2977 HRESULT hr;
2978 HWND wnd;
2979 IDirect3D9* d3d;
2980 IDirect3DDevice9* device;
2981 D3DPRESENT_PARAMETERS d3dpp;
2982 ID3DXMesh* cylinder = NULL;
2984 hr = D3DXCreateCylinder(NULL, 0.0f, 0.0f, 0.0f, 0, 0, NULL, NULL);
2985 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
2987 hr = D3DXCreateCylinder(NULL, 1.0f, 1.0f, 1.0f, 2, 1, &cylinder, NULL);
2988 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
2990 wnd = CreateWindow("static", "d3dx9_test", 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL);
2991 d3d = Direct3DCreate9(D3D_SDK_VERSION);
2992 if (!wnd)
2994 skip("Couldn't create application window\n");
2995 return;
2997 if (!d3d)
2999 skip("Couldn't create IDirect3D9 object\n");
3000 DestroyWindow(wnd);
3001 return;
3004 ZeroMemory(&d3dpp, sizeof(d3dpp));
3005 d3dpp.Windowed = TRUE;
3006 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
3007 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, wnd, D3DCREATE_MIXED_VERTEXPROCESSING, &d3dpp, &device);
3008 if (FAILED(hr))
3010 skip("Failed to create IDirect3DDevice9 object %#x\n", hr);
3011 IDirect3D9_Release(d3d);
3012 DestroyWindow(wnd);
3013 return;
3016 hr = D3DXCreateCylinder(device, -0.1f, 1.0f, 1.0f, 2, 1, &cylinder, NULL);
3017 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3019 hr = D3DXCreateCylinder(device, 0.0f, 1.0f, 1.0f, 2, 1, &cylinder, NULL);
3020 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n",hr);
3022 if (SUCCEEDED(hr) && cylinder)
3024 cylinder->lpVtbl->Release(cylinder);
3027 hr = D3DXCreateCylinder(device, 1.0f, -0.1f, 1.0f, 2, 1, &cylinder, NULL);
3028 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3030 hr = D3DXCreateCylinder(device, 1.0f, 0.0f, 1.0f, 2, 1, &cylinder, NULL);
3031 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n",hr);
3033 if (SUCCEEDED(hr) && cylinder)
3035 cylinder->lpVtbl->Release(cylinder);
3038 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, -0.1f, 2, 1, &cylinder, NULL);
3039 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3041 /* Test with length == 0.0f succeeds */
3042 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, 0.0f, 2, 1, &cylinder, NULL);
3043 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n",hr);
3045 if (SUCCEEDED(hr) && cylinder)
3047 cylinder->lpVtbl->Release(cylinder);
3050 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, 1.0f, 1, 1, &cylinder, NULL);
3051 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3053 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, 1.0f, 2, 0, &cylinder, NULL);
3054 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3056 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, 1.0f, 2, 1, NULL, NULL);
3057 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3059 test_cylinder(device, 0.0f, 0.0f, 0.0f, 2, 1);
3060 test_cylinder(device, 1.0f, 1.0f, 1.0f, 2, 1);
3061 test_cylinder(device, 1.0f, 1.0f, 2.0f, 3, 4);
3062 test_cylinder(device, 3.0f, 2.0f, 4.0f, 3, 4);
3063 test_cylinder(device, 2.0f, 3.0f, 4.0f, 3, 4);
3064 test_cylinder(device, 3.0f, 4.0f, 5.0f, 11, 20);
3066 IDirect3DDevice9_Release(device);
3067 IDirect3D9_Release(d3d);
3068 DestroyWindow(wnd);
3071 struct dynamic_array
3073 int count, capacity;
3074 void *items;
3077 enum pointtype {
3078 POINTTYPE_CURVE = 0,
3079 POINTTYPE_CORNER,
3080 POINTTYPE_CURVE_START,
3081 POINTTYPE_CURVE_END,
3082 POINTTYPE_CURVE_MIDDLE,
3085 struct point2d
3087 D3DXVECTOR2 pos;
3088 enum pointtype corner;
3091 /* is a dynamic_array */
3092 struct outline
3094 int count, capacity;
3095 struct point2d *items;
3098 /* is a dynamic_array */
3099 struct outline_array
3101 int count, capacity;
3102 struct outline *items;
3105 struct glyphinfo
3107 struct outline_array outlines;
3108 float offset_x;
3111 static BOOL reserve(struct dynamic_array *array, int count, int itemsize)
3113 if (count > array->capacity) {
3114 void *new_buffer;
3115 int new_capacity;
3116 if (array->items && array->capacity) {
3117 new_capacity = max(array->capacity * 2, count);
3118 new_buffer = HeapReAlloc(GetProcessHeap(), 0, array->items, new_capacity * itemsize);
3119 } else {
3120 new_capacity = max(16, count);
3121 new_buffer = HeapAlloc(GetProcessHeap(), 0, new_capacity * itemsize);
3123 if (!new_buffer)
3124 return FALSE;
3125 array->items = new_buffer;
3126 array->capacity = new_capacity;
3128 return TRUE;
3131 static struct point2d *add_point(struct outline *array)
3133 struct point2d *item;
3135 if (!reserve((struct dynamic_array *)array, array->count + 1, sizeof(array->items[0])))
3136 return NULL;
3138 item = &array->items[array->count++];
3139 ZeroMemory(item, sizeof(*item));
3140 return item;
3143 static struct outline *add_outline(struct outline_array *array)
3145 struct outline *item;
3147 if (!reserve((struct dynamic_array *)array, array->count + 1, sizeof(array->items[0])))
3148 return NULL;
3150 item = &array->items[array->count++];
3151 ZeroMemory(item, sizeof(*item));
3152 return item;
3155 static inline D3DXVECTOR2 *convert_fixed_to_float(POINTFX *pt, int count, float emsquare)
3157 D3DXVECTOR2 *ret = (D3DXVECTOR2*)pt;
3158 while (count--) {
3159 D3DXVECTOR2 *pt_flt = (D3DXVECTOR2*)pt;
3160 pt_flt->x = (pt->x.value + pt->x.fract / (float)0x10000) / emsquare;
3161 pt_flt->y = (pt->y.value + pt->y.fract / (float)0x10000) / emsquare;
3162 pt++;
3164 return ret;
3167 static HRESULT add_bezier_points(struct outline *outline, const D3DXVECTOR2 *p1,
3168 const D3DXVECTOR2 *p2, const D3DXVECTOR2 *p3,
3169 float max_deviation)
3171 D3DXVECTOR2 split1 = {0, 0}, split2 = {0, 0}, middle, vec;
3172 float deviation;
3174 D3DXVec2Scale(&split1, D3DXVec2Add(&split1, p1, p2), 0.5f);
3175 D3DXVec2Scale(&split2, D3DXVec2Add(&split2, p2, p3), 0.5f);
3176 D3DXVec2Scale(&middle, D3DXVec2Add(&middle, &split1, &split2), 0.5f);
3178 deviation = D3DXVec2Length(D3DXVec2Subtract(&vec, &middle, p2));
3179 if (deviation < max_deviation) {
3180 struct point2d *pt = add_point(outline);
3181 if (!pt) return E_OUTOFMEMORY;
3182 pt->pos = *p2;
3183 pt->corner = POINTTYPE_CURVE;
3184 /* the end point is omitted because the end line merges into the next segment of
3185 * the split bezier curve, and the end of the split bezier curve is added outside
3186 * this recursive function. */
3187 } else {
3188 HRESULT hr = add_bezier_points(outline, p1, &split1, &middle, max_deviation);
3189 if (hr != S_OK) return hr;
3190 hr = add_bezier_points(outline, &middle, &split2, p3, max_deviation);
3191 if (hr != S_OK) return hr;
3194 return S_OK;
3197 static inline BOOL is_direction_similar(D3DXVECTOR2 *dir1, D3DXVECTOR2 *dir2, float cos_theta)
3199 /* dot product = cos(theta) */
3200 return D3DXVec2Dot(dir1, dir2) > cos_theta;
3203 static inline D3DXVECTOR2 *unit_vec2(D3DXVECTOR2 *dir, const D3DXVECTOR2 *pt1, const D3DXVECTOR2 *pt2)
3205 return D3DXVec2Normalize(D3DXVec2Subtract(dir, pt2, pt1), dir);
3208 static BOOL attempt_line_merge(struct outline *outline,
3209 int pt_index,
3210 const D3DXVECTOR2 *nextpt,
3211 BOOL to_curve)
3213 D3DXVECTOR2 curdir, lastdir;
3214 struct point2d *prevpt, *pt;
3215 BOOL ret = FALSE;
3216 const float cos_half = cos(D3DXToRadian(0.5f));
3218 pt = &outline->items[pt_index];
3219 pt_index = (pt_index - 1 + outline->count) % outline->count;
3220 prevpt = &outline->items[pt_index];
3222 if (to_curve)
3223 pt->corner = pt->corner != POINTTYPE_CORNER ? POINTTYPE_CURVE_MIDDLE : POINTTYPE_CURVE_START;
3225 if (outline->count < 2)
3226 return FALSE;
3228 /* remove last point if the next line continues the last line */
3229 unit_vec2(&lastdir, &prevpt->pos, &pt->pos);
3230 unit_vec2(&curdir, &pt->pos, nextpt);
3231 if (is_direction_similar(&lastdir, &curdir, cos_half))
3233 outline->count--;
3234 if (pt->corner == POINTTYPE_CURVE_END)
3235 prevpt->corner = pt->corner;
3236 if (prevpt->corner == POINTTYPE_CURVE_END && to_curve)
3237 prevpt->corner = POINTTYPE_CURVE_MIDDLE;
3238 pt = prevpt;
3240 ret = TRUE;
3241 if (outline->count < 2)
3242 return ret;
3244 pt_index = (pt_index - 1 + outline->count) % outline->count;
3245 prevpt = &outline->items[pt_index];
3246 unit_vec2(&lastdir, &prevpt->pos, &pt->pos);
3247 unit_vec2(&curdir, &pt->pos, nextpt);
3249 return ret;
3252 static HRESULT create_outline(struct glyphinfo *glyph, void *raw_outline, int datasize,
3253 float max_deviation, float emsquare)
3255 const float cos_45 = cos(D3DXToRadian(45.0f));
3256 const float cos_90 = cos(D3DXToRadian(90.0f));
3257 TTPOLYGONHEADER *header = (TTPOLYGONHEADER *)raw_outline;
3259 while ((char *)header < (char *)raw_outline + datasize)
3261 TTPOLYCURVE *curve = (TTPOLYCURVE *)(header + 1);
3262 struct point2d *lastpt, *pt;
3263 D3DXVECTOR2 lastdir;
3264 D3DXVECTOR2 *pt_flt;
3265 int j;
3266 struct outline *outline = add_outline(&glyph->outlines);
3268 if (!outline)
3269 return E_OUTOFMEMORY;
3271 pt = add_point(outline);
3272 if (!pt)
3273 return E_OUTOFMEMORY;
3274 pt_flt = convert_fixed_to_float(&header->pfxStart, 1, emsquare);
3275 pt->pos = *pt_flt;
3276 pt->corner = POINTTYPE_CORNER;
3278 if (header->dwType != TT_POLYGON_TYPE)
3279 trace("Unknown header type %d\n", header->dwType);
3281 while ((char *)curve < (char *)header + header->cb)
3283 D3DXVECTOR2 bezier_start = outline->items[outline->count - 1].pos;
3284 BOOL to_curve = curve->wType != TT_PRIM_LINE && curve->cpfx > 1;
3286 if (!curve->cpfx) {
3287 curve = (TTPOLYCURVE *)&curve->apfx[curve->cpfx];
3288 continue;
3291 pt_flt = convert_fixed_to_float(curve->apfx, curve->cpfx, emsquare);
3293 attempt_line_merge(outline, outline->count - 1, &pt_flt[0], to_curve);
3295 if (to_curve)
3297 HRESULT hr;
3298 int count = curve->cpfx;
3299 j = 0;
3301 while (count > 2)
3303 D3DXVECTOR2 bezier_end;
3305 D3DXVec2Scale(&bezier_end, D3DXVec2Add(&bezier_end, &pt_flt[j], &pt_flt[j+1]), 0.5f);
3306 hr = add_bezier_points(outline, &bezier_start, &pt_flt[j], &bezier_end, max_deviation);
3307 if (hr != S_OK)
3308 return hr;
3309 bezier_start = bezier_end;
3310 count--;
3311 j++;
3313 hr = add_bezier_points(outline, &bezier_start, &pt_flt[j], &pt_flt[j+1], max_deviation);
3314 if (hr != S_OK)
3315 return hr;
3317 pt = add_point(outline);
3318 if (!pt)
3319 return E_OUTOFMEMORY;
3320 j++;
3321 pt->pos = pt_flt[j];
3322 pt->corner = POINTTYPE_CURVE_END;
3323 } else {
3324 for (j = 0; j < curve->cpfx; j++)
3326 pt = add_point(outline);
3327 if (!pt)
3328 return E_OUTOFMEMORY;
3329 pt->pos = pt_flt[j];
3330 pt->corner = POINTTYPE_CORNER;
3334 curve = (TTPOLYCURVE *)&curve->apfx[curve->cpfx];
3337 /* remove last point if the next line continues the last line */
3338 if (outline->count >= 3) {
3339 BOOL to_curve;
3341 lastpt = &outline->items[outline->count - 1];
3342 pt = &outline->items[0];
3343 if (pt->pos.x == lastpt->pos.x && pt->pos.y == lastpt->pos.y) {
3344 if (lastpt->corner == POINTTYPE_CURVE_END)
3346 if (pt->corner == POINTTYPE_CURVE_START)
3347 pt->corner = POINTTYPE_CURVE_MIDDLE;
3348 else
3349 pt->corner = POINTTYPE_CURVE_END;
3351 outline->count--;
3352 lastpt = &outline->items[outline->count - 1];
3353 } else {
3354 /* outline closed with a line from end to start point */
3355 attempt_line_merge(outline, outline->count - 1, &pt->pos, FALSE);
3357 lastpt = &outline->items[0];
3358 to_curve = lastpt->corner != POINTTYPE_CORNER && lastpt->corner != POINTTYPE_CURVE_END;
3359 if (lastpt->corner == POINTTYPE_CURVE_START)
3360 lastpt->corner = POINTTYPE_CORNER;
3361 pt = &outline->items[1];
3362 if (attempt_line_merge(outline, 0, &pt->pos, to_curve))
3363 *lastpt = outline->items[outline->count];
3366 lastpt = &outline->items[outline->count - 1];
3367 pt = &outline->items[0];
3368 unit_vec2(&lastdir, &lastpt->pos, &pt->pos);
3369 for (j = 0; j < outline->count; j++)
3371 D3DXVECTOR2 curdir;
3373 lastpt = pt;
3374 pt = &outline->items[(j + 1) % outline->count];
3375 unit_vec2(&curdir, &lastpt->pos, &pt->pos);
3377 switch (lastpt->corner)
3379 case POINTTYPE_CURVE_START:
3380 case POINTTYPE_CURVE_END:
3381 if (!is_direction_similar(&lastdir, &curdir, cos_45))
3382 lastpt->corner = POINTTYPE_CORNER;
3383 break;
3384 case POINTTYPE_CURVE_MIDDLE:
3385 if (!is_direction_similar(&lastdir, &curdir, cos_90))
3386 lastpt->corner = POINTTYPE_CORNER;
3387 else
3388 lastpt->corner = POINTTYPE_CURVE;
3389 break;
3390 default:
3391 break;
3393 lastdir = curdir;
3396 header = (TTPOLYGONHEADER *)((char *)header + header->cb);
3398 return S_OK;
3401 static BOOL compute_text_mesh(struct mesh *mesh, HDC hdc, LPCSTR text, FLOAT deviation, FLOAT extrusion, FLOAT otmEMSquare)
3403 HRESULT hr = E_FAIL;
3404 DWORD nb_vertices, nb_faces;
3405 DWORD nb_corners, nb_outline_points;
3406 int textlen = 0;
3407 float offset_x;
3408 char *raw_outline = NULL;
3409 struct glyphinfo *glyphs = NULL;
3410 GLYPHMETRICS gm;
3411 int i;
3412 struct vertex *vertex_ptr;
3413 face *face_ptr;
3415 if (deviation == 0.0f)
3416 deviation = 1.0f / otmEMSquare;
3418 textlen = strlen(text);
3419 glyphs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, textlen * sizeof(*glyphs));
3420 if (!glyphs) {
3421 hr = E_OUTOFMEMORY;
3422 goto error;
3425 offset_x = 0.0f;
3426 for (i = 0; i < textlen; i++)
3428 /* get outline points from data returned from GetGlyphOutline */
3429 const MAT2 identity = {{0, 1}, {0, 0}, {0, 0}, {0, 1}};
3430 int datasize;
3432 glyphs[i].offset_x = offset_x;
3434 datasize = GetGlyphOutline(hdc, text[i], GGO_NATIVE, &gm, 0, NULL, &identity);
3435 if (datasize < 0) {
3436 hr = E_FAIL;
3437 goto error;
3439 HeapFree(GetProcessHeap(), 0, raw_outline);
3440 raw_outline = HeapAlloc(GetProcessHeap(), 0, datasize);
3441 if (!glyphs) {
3442 hr = E_OUTOFMEMORY;
3443 goto error;
3445 datasize = GetGlyphOutline(hdc, text[i], GGO_NATIVE, &gm, datasize, raw_outline, &identity);
3447 create_outline(&glyphs[i], raw_outline, datasize, deviation, otmEMSquare);
3449 offset_x += gm.gmCellIncX / (float)otmEMSquare;
3452 /* corner points need an extra vertex for the different side faces normals */
3453 nb_corners = 0;
3454 nb_outline_points = 0;
3455 for (i = 0; i < textlen; i++)
3457 int j;
3458 for (j = 0; j < glyphs[i].outlines.count; j++)
3460 int k;
3461 struct outline *outline = &glyphs[i].outlines.items[j];
3462 nb_outline_points += outline->count;
3463 nb_corners++; /* first outline point always repeated as a corner */
3464 for (k = 1; k < outline->count; k++)
3465 if (outline->items[k].corner)
3466 nb_corners++;
3470 nb_vertices = (nb_outline_points + nb_corners) * 2 + textlen;
3471 nb_faces = nb_outline_points * 2;
3473 if (!new_mesh(mesh, nb_vertices, nb_faces))
3474 goto error;
3476 /* convert 2D vertices and faces into 3D mesh */
3477 vertex_ptr = mesh->vertices;
3478 face_ptr = mesh->faces;
3479 for (i = 0; i < textlen; i++)
3481 int j;
3483 /* side vertices and faces */
3484 for (j = 0; j < glyphs[i].outlines.count; j++)
3486 struct vertex *outline_vertices = vertex_ptr;
3487 struct outline *outline = &glyphs[i].outlines.items[j];
3488 int k;
3489 struct point2d *prevpt = &outline->items[outline->count - 1];
3490 struct point2d *pt = &outline->items[0];
3492 for (k = 1; k <= outline->count; k++)
3494 struct vertex vtx;
3495 struct point2d *nextpt = &outline->items[k % outline->count];
3496 WORD vtx_idx = vertex_ptr - mesh->vertices;
3497 D3DXVECTOR2 vec;
3499 if (pt->corner == POINTTYPE_CURVE_START)
3500 D3DXVec2Subtract(&vec, &pt->pos, &prevpt->pos);
3501 else if (pt->corner)
3502 D3DXVec2Subtract(&vec, &nextpt->pos, &pt->pos);
3503 else
3504 D3DXVec2Subtract(&vec, &nextpt->pos, &prevpt->pos);
3505 D3DXVec2Normalize(&vec, &vec);
3506 vtx.normal.x = -vec.y;
3507 vtx.normal.y = vec.x;
3508 vtx.normal.z = 0;
3510 vtx.position.x = pt->pos.x + glyphs[i].offset_x;
3511 vtx.position.y = pt->pos.y;
3512 vtx.position.z = 0;
3513 *vertex_ptr++ = vtx;
3515 vtx.position.z = -extrusion;
3516 *vertex_ptr++ = vtx;
3518 vtx.position.x = nextpt->pos.x + glyphs[i].offset_x;
3519 vtx.position.y = nextpt->pos.y;
3520 if (pt->corner && nextpt->corner && nextpt->corner != POINTTYPE_CURVE_END) {
3521 vtx.position.z = -extrusion;
3522 *vertex_ptr++ = vtx;
3523 vtx.position.z = 0;
3524 *vertex_ptr++ = vtx;
3526 (*face_ptr)[0] = vtx_idx;
3527 (*face_ptr)[1] = vtx_idx + 2;
3528 (*face_ptr)[2] = vtx_idx + 1;
3529 face_ptr++;
3531 (*face_ptr)[0] = vtx_idx;
3532 (*face_ptr)[1] = vtx_idx + 3;
3533 (*face_ptr)[2] = vtx_idx + 2;
3534 face_ptr++;
3535 } else {
3536 if (nextpt->corner) {
3537 if (nextpt->corner == POINTTYPE_CURVE_END) {
3538 struct point2d *nextpt2 = &outline->items[(k + 1) % outline->count];
3539 D3DXVec2Subtract(&vec, &nextpt2->pos, &nextpt->pos);
3540 } else {
3541 D3DXVec2Subtract(&vec, &nextpt->pos, &pt->pos);
3543 D3DXVec2Normalize(&vec, &vec);
3544 vtx.normal.x = -vec.y;
3545 vtx.normal.y = vec.x;
3547 vtx.position.z = 0;
3548 *vertex_ptr++ = vtx;
3549 vtx.position.z = -extrusion;
3550 *vertex_ptr++ = vtx;
3553 (*face_ptr)[0] = vtx_idx;
3554 (*face_ptr)[1] = vtx_idx + 3;
3555 (*face_ptr)[2] = vtx_idx + 1;
3556 face_ptr++;
3558 (*face_ptr)[0] = vtx_idx;
3559 (*face_ptr)[1] = vtx_idx + 2;
3560 (*face_ptr)[2] = vtx_idx + 3;
3561 face_ptr++;
3564 prevpt = pt;
3565 pt = nextpt;
3567 if (!pt->corner) {
3568 *vertex_ptr++ = *outline_vertices++;
3569 *vertex_ptr++ = *outline_vertices++;
3573 /* FIXME: compute expected faces */
3574 /* Add placeholder to separate glyph outlines */
3575 vertex_ptr->position.x = 0;
3576 vertex_ptr->position.y = 0;
3577 vertex_ptr->position.z = 0;
3578 vertex_ptr->normal.x = 0;
3579 vertex_ptr->normal.y = 0;
3580 vertex_ptr->normal.z = 1;
3581 vertex_ptr++;
3584 hr = D3D_OK;
3585 error:
3586 if (glyphs) {
3587 for (i = 0; i < textlen; i++)
3589 int j;
3590 for (j = 0; j < glyphs[i].outlines.count; j++)
3591 HeapFree(GetProcessHeap(), 0, glyphs[i].outlines.items[j].items);
3592 HeapFree(GetProcessHeap(), 0, glyphs[i].outlines.items);
3594 HeapFree(GetProcessHeap(), 0, glyphs);
3596 HeapFree(GetProcessHeap(), 0, raw_outline);
3598 return hr == D3D_OK;
3601 static void compare_text_outline_mesh(const char *name, ID3DXMesh *d3dxmesh, struct mesh *mesh, int textlen, float extrusion)
3603 HRESULT hr;
3604 DWORD number_of_vertices, number_of_faces;
3605 IDirect3DVertexBuffer9 *vertex_buffer = NULL;
3606 IDirect3DIndexBuffer9 *index_buffer = NULL;
3607 D3DVERTEXBUFFER_DESC vertex_buffer_description;
3608 D3DINDEXBUFFER_DESC index_buffer_description;
3609 struct vertex *vertices = NULL;
3610 face *faces = NULL;
3611 int expected, i;
3612 int vtx_idx1, face_idx1, vtx_idx2, face_idx2;
3614 number_of_vertices = d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh);
3615 number_of_faces = d3dxmesh->lpVtbl->GetNumFaces(d3dxmesh);
3617 /* vertex buffer */
3618 hr = d3dxmesh->lpVtbl->GetVertexBuffer(d3dxmesh, &vertex_buffer);
3619 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
3620 if (hr != D3D_OK)
3622 skip("Couldn't get vertex buffers\n");
3623 goto error;
3626 hr = IDirect3DVertexBuffer9_GetDesc(vertex_buffer, &vertex_buffer_description);
3627 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
3629 if (hr != D3D_OK)
3631 skip("Couldn't get vertex buffer description\n");
3633 else
3635 ok(vertex_buffer_description.Format == D3DFMT_VERTEXDATA, "Test %s, result %x, expected %x (D3DFMT_VERTEXDATA)\n",
3636 name, vertex_buffer_description.Format, D3DFMT_VERTEXDATA);
3637 ok(vertex_buffer_description.Type == D3DRTYPE_VERTEXBUFFER, "Test %s, result %x, expected %x (D3DRTYPE_VERTEXBUFFER)\n",
3638 name, vertex_buffer_description.Type, D3DRTYPE_VERTEXBUFFER);
3639 ok(vertex_buffer_description.Usage == 0, "Test %s, result %x, expected %x\n", name, vertex_buffer_description.Usage, 0);
3640 ok(vertex_buffer_description.Pool == D3DPOOL_MANAGED, "Test %s, result %x, expected %x (D3DPOOL_MANAGED)\n",
3641 name, vertex_buffer_description.Pool, D3DPOOL_MANAGED);
3642 ok(vertex_buffer_description.FVF == mesh->fvf, "Test %s, result %x, expected %x\n",
3643 name, vertex_buffer_description.FVF, mesh->fvf);
3644 if (mesh->fvf == 0)
3646 expected = number_of_vertices * mesh->vertex_size;
3648 else
3650 expected = number_of_vertices * D3DXGetFVFVertexSize(mesh->fvf);
3652 ok(vertex_buffer_description.Size == expected, "Test %s, result %x, expected %x\n",
3653 name, vertex_buffer_description.Size, expected);
3656 hr = d3dxmesh->lpVtbl->GetIndexBuffer(d3dxmesh, &index_buffer);
3657 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
3658 if (hr != D3D_OK)
3660 skip("Couldn't get index buffer\n");
3661 goto error;
3664 hr = IDirect3DIndexBuffer9_GetDesc(index_buffer, &index_buffer_description);
3665 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
3667 if (hr != D3D_OK)
3669 skip("Couldn't get index buffer description\n");
3671 else
3673 ok(index_buffer_description.Format == D3DFMT_INDEX16, "Test %s, result %x, expected %x (D3DFMT_INDEX16)\n",
3674 name, index_buffer_description.Format, D3DFMT_INDEX16);
3675 ok(index_buffer_description.Type == D3DRTYPE_INDEXBUFFER, "Test %s, result %x, expected %x (D3DRTYPE_INDEXBUFFER)\n",
3676 name, index_buffer_description.Type, D3DRTYPE_INDEXBUFFER);
3677 ok(index_buffer_description.Usage == 0, "Test %s, result %#x, expected %#x.\n",
3678 name, index_buffer_description.Usage, 0);
3679 ok(index_buffer_description.Pool == D3DPOOL_MANAGED, "Test %s, result %x, expected %x (D3DPOOL_MANAGED)\n",
3680 name, index_buffer_description.Pool, D3DPOOL_MANAGED);
3681 expected = number_of_faces * sizeof(WORD) * 3;
3682 ok(index_buffer_description.Size == expected, "Test %s, result %x, expected %x\n",
3683 name, index_buffer_description.Size, expected);
3686 /* specify offset and size to avoid potential overruns */
3687 hr = IDirect3DVertexBuffer9_Lock(vertex_buffer, 0, number_of_vertices * sizeof(D3DXVECTOR3) * 2,
3688 (LPVOID *)&vertices, D3DLOCK_DISCARD);
3689 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
3690 if (hr != D3D_OK)
3692 skip("Couldn't lock vertex buffer\n");
3693 goto error;
3695 hr = IDirect3DIndexBuffer9_Lock(index_buffer, 0, number_of_faces * sizeof(WORD) * 3,
3696 (LPVOID *)&faces, D3DLOCK_DISCARD);
3697 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
3698 if (hr != D3D_OK)
3700 skip("Couldn't lock index buffer\n");
3701 goto error;
3704 face_idx1 = 0;
3705 vtx_idx2 = 0;
3706 face_idx2 = 0;
3707 vtx_idx1 = 0;
3708 for (i = 0; i < textlen; i++)
3710 int nb_outline_vertices1, nb_outline_faces1;
3711 int nb_outline_vertices2, nb_outline_faces2;
3712 int nb_back_vertices, nb_back_faces;
3713 int first_vtx1, first_vtx2;
3714 int first_face1, first_face2;
3715 int j;
3717 first_vtx1 = vtx_idx1;
3718 first_vtx2 = vtx_idx2;
3719 for (; vtx_idx1 < number_of_vertices; vtx_idx1++) {
3720 if (vertices[vtx_idx1].normal.z != 0)
3721 break;
3723 for (; vtx_idx2 < mesh->number_of_vertices; vtx_idx2++) {
3724 if (mesh->vertices[vtx_idx2].normal.z != 0)
3725 break;
3727 nb_outline_vertices1 = vtx_idx1 - first_vtx1;
3728 nb_outline_vertices2 = vtx_idx2 - first_vtx2;
3729 ok(nb_outline_vertices1 == nb_outline_vertices2,
3730 "Test %s, glyph %d, outline vertex count result %d, expected %d\n", name, i,
3731 nb_outline_vertices1, nb_outline_vertices2);
3733 for (j = 0; j < min(nb_outline_vertices1, nb_outline_vertices2); j++)
3735 vtx_idx1 = first_vtx1 + j;
3736 vtx_idx2 = first_vtx2 + j;
3737 ok(compare_vec3(vertices[vtx_idx1].position, mesh->vertices[vtx_idx2].position),
3738 "Test %s, glyph %d, vertex position %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1,
3739 vertices[vtx_idx1].position.x, vertices[vtx_idx1].position.y, vertices[vtx_idx1].position.z,
3740 mesh->vertices[vtx_idx2].position.x, mesh->vertices[vtx_idx2].position.y, mesh->vertices[vtx_idx2].position.z);
3741 ok(compare_vec3(vertices[vtx_idx1].normal, mesh->vertices[first_vtx2 + j].normal),
3742 "Test %s, glyph %d, vertex normal %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1,
3743 vertices[vtx_idx1].normal.x, vertices[vtx_idx1].normal.y, vertices[vtx_idx1].normal.z,
3744 mesh->vertices[vtx_idx2].normal.x, mesh->vertices[vtx_idx2].normal.y, mesh->vertices[vtx_idx2].normal.z);
3746 vtx_idx1 = first_vtx1 + nb_outline_vertices1;
3747 vtx_idx2 = first_vtx2 + nb_outline_vertices2;
3749 first_face1 = face_idx1;
3750 first_face2 = face_idx2;
3751 for (; face_idx1 < number_of_faces; face_idx1++)
3753 if (faces[face_idx1][0] >= vtx_idx1 ||
3754 faces[face_idx1][1] >= vtx_idx1 ||
3755 faces[face_idx1][2] >= vtx_idx1)
3756 break;
3758 for (; face_idx2 < mesh->number_of_faces; face_idx2++)
3760 if (mesh->faces[face_idx2][0] >= vtx_idx2 ||
3761 mesh->faces[face_idx2][1] >= vtx_idx2 ||
3762 mesh->faces[face_idx2][2] >= vtx_idx2)
3763 break;
3765 nb_outline_faces1 = face_idx1 - first_face1;
3766 nb_outline_faces2 = face_idx2 - first_face2;
3767 ok(nb_outline_faces1 == nb_outline_faces2,
3768 "Test %s, glyph %d, outline face count result %d, expected %d\n", name, i,
3769 nb_outline_faces1, nb_outline_faces2);
3771 for (j = 0; j < min(nb_outline_faces1, nb_outline_faces2); j++)
3773 face_idx1 = first_face1 + j;
3774 face_idx2 = first_face2 + j;
3775 ok(faces[face_idx1][0] - first_vtx1 == mesh->faces[face_idx2][0] - first_vtx2 &&
3776 faces[face_idx1][1] - first_vtx1 == mesh->faces[face_idx2][1] - first_vtx2 &&
3777 faces[face_idx1][2] - first_vtx1 == mesh->faces[face_idx2][2] - first_vtx2,
3778 "Test %s, glyph %d, face %d, result (%d, %d, %d), expected (%d, %d, %d)\n", name, i, face_idx1,
3779 faces[face_idx1][0], faces[face_idx1][1], faces[face_idx1][2],
3780 mesh->faces[face_idx2][0] - first_vtx2 + first_vtx1,
3781 mesh->faces[face_idx2][1] - first_vtx2 + first_vtx1,
3782 mesh->faces[face_idx2][2] - first_vtx2 + first_vtx1);
3784 face_idx1 = first_face1 + nb_outline_faces1;
3785 face_idx2 = first_face2 + nb_outline_faces2;
3787 /* partial test on back vertices and faces */
3788 first_vtx1 = vtx_idx1;
3789 for (; vtx_idx1 < number_of_vertices; vtx_idx1++) {
3790 struct vertex vtx;
3792 if (vertices[vtx_idx1].normal.z != 1.0f)
3793 break;
3795 vtx.position.z = 0.0f;
3796 vtx.normal.x = 0.0f;
3797 vtx.normal.y = 0.0f;
3798 vtx.normal.z = 1.0f;
3799 ok(compare(vertices[vtx_idx1].position.z, vtx.position.z),
3800 "Test %s, glyph %d, vertex position.z %d, result %g, expected %g\n", name, i, vtx_idx1,
3801 vertices[vtx_idx1].position.z, vtx.position.z);
3802 ok(compare_vec3(vertices[vtx_idx1].normal, vtx.normal),
3803 "Test %s, glyph %d, vertex normal %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1,
3804 vertices[vtx_idx1].normal.x, vertices[vtx_idx1].normal.y, vertices[vtx_idx1].normal.z,
3805 vtx.normal.x, vtx.normal.y, vtx.normal.z);
3807 nb_back_vertices = vtx_idx1 - first_vtx1;
3808 first_face1 = face_idx1;
3809 for (; face_idx1 < number_of_faces; face_idx1++)
3811 const D3DXVECTOR3 *vtx1, *vtx2, *vtx3;
3812 D3DXVECTOR3 normal;
3813 D3DXVECTOR3 v1 = {0, 0, 0};
3814 D3DXVECTOR3 v2 = {0, 0, 0};
3815 D3DXVECTOR3 forward = {0.0f, 0.0f, 1.0f};
3817 if (faces[face_idx1][0] >= vtx_idx1 ||
3818 faces[face_idx1][1] >= vtx_idx1 ||
3819 faces[face_idx1][2] >= vtx_idx1)
3820 break;
3822 vtx1 = &vertices[faces[face_idx1][0]].position;
3823 vtx2 = &vertices[faces[face_idx1][1]].position;
3824 vtx3 = &vertices[faces[face_idx1][2]].position;
3826 D3DXVec3Subtract(&v1, vtx2, vtx1);
3827 D3DXVec3Subtract(&v2, vtx3, vtx2);
3828 D3DXVec3Cross(&normal, &v1, &v2);
3829 D3DXVec3Normalize(&normal, &normal);
3830 ok(!D3DXVec3Length(&normal) || compare_vec3(normal, forward),
3831 "Test %s, glyph %d, face %d normal, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, face_idx1,
3832 normal.x, normal.y, normal.z, forward.x, forward.y, forward.z);
3834 nb_back_faces = face_idx1 - first_face1;
3836 /* compare front and back faces & vertices */
3837 if (extrusion == 0.0f) {
3838 /* Oddly there are only back faces in this case */
3839 nb_back_vertices /= 2;
3840 nb_back_faces /= 2;
3841 face_idx1 -= nb_back_faces;
3842 vtx_idx1 -= nb_back_vertices;
3844 for (j = 0; j < nb_back_vertices; j++)
3846 struct vertex vtx = vertices[first_vtx1];
3847 vtx.position.z = -extrusion;
3848 vtx.normal.x = 0.0f;
3849 vtx.normal.y = 0.0f;
3850 vtx.normal.z = extrusion == 0.0f ? 1.0f : -1.0f;
3851 ok(compare_vec3(vertices[vtx_idx1].position, vtx.position),
3852 "Test %s, glyph %d, vertex position %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1,
3853 vertices[vtx_idx1].position.x, vertices[vtx_idx1].position.y, vertices[vtx_idx1].position.z,
3854 vtx.position.x, vtx.position.y, vtx.position.z);
3855 ok(compare_vec3(vertices[vtx_idx1].normal, vtx.normal),
3856 "Test %s, glyph %d, vertex normal %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1,
3857 vertices[vtx_idx1].normal.x, vertices[vtx_idx1].normal.y, vertices[vtx_idx1].normal.z,
3858 vtx.normal.x, vtx.normal.y, vtx.normal.z);
3859 vtx_idx1++;
3860 first_vtx1++;
3862 for (j = 0; j < nb_back_faces; j++)
3864 int f1, f2;
3865 if (extrusion == 0.0f) {
3866 f1 = 1;
3867 f2 = 2;
3868 } else {
3869 f1 = 2;
3870 f2 = 1;
3872 ok(faces[face_idx1][0] == faces[first_face1][0] + nb_back_vertices &&
3873 faces[face_idx1][1] == faces[first_face1][f1] + nb_back_vertices &&
3874 faces[face_idx1][2] == faces[first_face1][f2] + nb_back_vertices,
3875 "Test %s, glyph %d, face %d, result (%d, %d, %d), expected (%d, %d, %d)\n", name, i, face_idx1,
3876 faces[face_idx1][0], faces[face_idx1][1], faces[face_idx1][2],
3877 faces[first_face1][0] - nb_back_faces,
3878 faces[first_face1][f1] - nb_back_faces,
3879 faces[first_face1][f2] - nb_back_faces);
3880 first_face1++;
3881 face_idx1++;
3884 /* skip to the outline for the next glyph */
3885 for (; vtx_idx2 < mesh->number_of_vertices; vtx_idx2++) {
3886 if (mesh->vertices[vtx_idx2].normal.z == 0)
3887 break;
3889 for (; face_idx2 < mesh->number_of_faces; face_idx2++)
3891 if (mesh->faces[face_idx2][0] >= vtx_idx2 ||
3892 mesh->faces[face_idx2][1] >= vtx_idx2 ||
3893 mesh->faces[face_idx2][2] >= vtx_idx2) break;
3897 error:
3898 if (vertices) IDirect3DVertexBuffer9_Unlock(vertex_buffer);
3899 if (faces) IDirect3DIndexBuffer9_Unlock(index_buffer);
3900 if (index_buffer) IDirect3DIndexBuffer9_Release(index_buffer);
3901 if (vertex_buffer) IDirect3DVertexBuffer9_Release(vertex_buffer);
3904 static void test_createtext(IDirect3DDevice9 *device, HDC hdc, LPCSTR text, FLOAT deviation, FLOAT extrusion)
3906 HRESULT hr;
3907 ID3DXMesh *d3dxmesh;
3908 struct mesh mesh;
3909 char name[256];
3910 OUTLINETEXTMETRIC otm;
3911 GLYPHMETRICS gm;
3912 GLYPHMETRICSFLOAT *glyphmetrics_float = HeapAlloc(GetProcessHeap(), 0, sizeof(GLYPHMETRICSFLOAT) * strlen(text));
3913 int i;
3914 LOGFONT lf;
3915 HFONT font = NULL, oldfont = NULL;
3917 sprintf(name, "text ('%s', %f, %f)", text, deviation, extrusion);
3919 hr = D3DXCreateText(device, hdc, text, deviation, extrusion, &d3dxmesh, NULL, glyphmetrics_float);
3920 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
3921 if (hr != D3D_OK)
3923 skip("Couldn't create text with D3DXCreateText\n");
3924 return;
3927 /* must select a modified font having lfHeight = otm.otmEMSquare before
3928 * calling GetGlyphOutline to get the expected values */
3929 if (!GetObject(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf) ||
3930 !GetOutlineTextMetrics(hdc, sizeof(otm), &otm))
3932 d3dxmesh->lpVtbl->Release(d3dxmesh);
3933 skip("Couldn't get text outline\n");
3934 return;
3936 lf.lfHeight = otm.otmEMSquare;
3937 lf.lfWidth = 0;
3938 font = CreateFontIndirect(&lf);
3939 if (!font) {
3940 d3dxmesh->lpVtbl->Release(d3dxmesh);
3941 skip("Couldn't create the modified font\n");
3942 return;
3944 oldfont = SelectObject(hdc, font);
3946 for (i = 0; i < strlen(text); i++)
3948 const MAT2 identity = {{0, 1}, {0, 0}, {0, 0}, {0, 1}};
3949 GetGlyphOutlineA(hdc, text[i], GGO_NATIVE, &gm, 0, NULL, &identity);
3950 compare_float(glyphmetrics_float[i].gmfBlackBoxX, gm.gmBlackBoxX / (float)otm.otmEMSquare);
3951 compare_float(glyphmetrics_float[i].gmfBlackBoxY, gm.gmBlackBoxY / (float)otm.otmEMSquare);
3952 compare_float(glyphmetrics_float[i].gmfptGlyphOrigin.x, gm.gmptGlyphOrigin.x / (float)otm.otmEMSquare);
3953 compare_float(glyphmetrics_float[i].gmfptGlyphOrigin.y, gm.gmptGlyphOrigin.y / (float)otm.otmEMSquare);
3954 compare_float(glyphmetrics_float[i].gmfCellIncX, gm.gmCellIncX / (float)otm.otmEMSquare);
3955 compare_float(glyphmetrics_float[i].gmfCellIncY, gm.gmCellIncY / (float)otm.otmEMSquare);
3958 ZeroMemory(&mesh, sizeof(mesh));
3959 if (!compute_text_mesh(&mesh, hdc, text, deviation, extrusion, otm.otmEMSquare))
3961 skip("Couldn't create mesh\n");
3962 d3dxmesh->lpVtbl->Release(d3dxmesh);
3963 return;
3965 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
3967 compare_text_outline_mesh(name, d3dxmesh, &mesh, strlen(text), extrusion);
3969 free_mesh(&mesh);
3971 d3dxmesh->lpVtbl->Release(d3dxmesh);
3972 SelectObject(hdc, oldfont);
3973 HeapFree(GetProcessHeap(), 0, glyphmetrics_float);
3976 static void D3DXCreateTextTest(void)
3978 HRESULT hr;
3979 HWND wnd;
3980 HDC hdc;
3981 IDirect3D9* d3d;
3982 IDirect3DDevice9* device;
3983 D3DPRESENT_PARAMETERS d3dpp;
3984 ID3DXMesh* d3dxmesh = NULL;
3985 HFONT hFont;
3986 OUTLINETEXTMETRIC otm;
3987 int number_of_vertices;
3988 int number_of_faces;
3990 wnd = CreateWindow("static", "d3dx9_test", WS_POPUP, 0, 0, 1000, 1000, NULL, NULL, NULL, NULL);
3991 d3d = Direct3DCreate9(D3D_SDK_VERSION);
3992 if (!wnd)
3994 skip("Couldn't create application window\n");
3995 return;
3997 if (!d3d)
3999 skip("Couldn't create IDirect3D9 object\n");
4000 DestroyWindow(wnd);
4001 return;
4004 ZeroMemory(&d3dpp, sizeof(d3dpp));
4005 d3dpp.Windowed = TRUE;
4006 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
4007 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, wnd, D3DCREATE_MIXED_VERTEXPROCESSING, &d3dpp, &device);
4008 if (FAILED(hr))
4010 skip("Failed to create IDirect3DDevice9 object %#x\n", hr);
4011 IDirect3D9_Release(d3d);
4012 DestroyWindow(wnd);
4013 return;
4016 hdc = CreateCompatibleDC(NULL);
4018 hFont = CreateFont(12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET,
4019 OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE,
4020 "Arial");
4021 SelectObject(hdc, hFont);
4022 GetOutlineTextMetrics(hdc, sizeof(otm), &otm);
4024 hr = D3DXCreateText(device, hdc, "wine", 0.001f, 0.4f, NULL, NULL, NULL);
4025 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4027 /* D3DXCreateTextA page faults from passing NULL text */
4029 hr = D3DXCreateTextW(device, hdc, NULL, 0.001f, 0.4f, &d3dxmesh, NULL, NULL);
4030 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4032 hr = D3DXCreateText(device, hdc, "", 0.001f, 0.4f, &d3dxmesh, NULL, NULL);
4033 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4035 hr = D3DXCreateText(device, hdc, " ", 0.001f, 0.4f, &d3dxmesh, NULL, NULL);
4036 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4038 hr = D3DXCreateText(NULL, hdc, "wine", 0.001f, 0.4f, &d3dxmesh, NULL, NULL);
4039 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4041 hr = D3DXCreateText(device, NULL, "wine", 0.001f, 0.4f, &d3dxmesh, NULL, NULL);
4042 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4044 hr = D3DXCreateText(device, hdc, "wine", -FLT_MIN, 0.4f, &d3dxmesh, NULL, NULL);
4045 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4047 hr = D3DXCreateText(device, hdc, "wine", 0.001f, -FLT_MIN, &d3dxmesh, NULL, NULL);
4048 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4050 /* deviation = 0.0f treated as if deviation = 1.0f / otm.otmEMSquare */
4051 hr = D3DXCreateText(device, hdc, "wine", 1.0f / otm.otmEMSquare, 0.4f, &d3dxmesh, NULL, NULL);
4052 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
4053 number_of_vertices = d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh);
4054 number_of_faces = d3dxmesh->lpVtbl->GetNumFaces(d3dxmesh);
4055 if (SUCCEEDED(hr) && d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh);
4057 hr = D3DXCreateText(device, hdc, "wine", 0.0f, 0.4f, &d3dxmesh, NULL, NULL);
4058 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
4059 ok(number_of_vertices == d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh),
4060 "Got %d vertices, expected %d\n",
4061 d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh), number_of_vertices);
4062 ok(number_of_faces == d3dxmesh->lpVtbl->GetNumFaces(d3dxmesh),
4063 "Got %d faces, expected %d\n",
4064 d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh), number_of_faces);
4065 if (SUCCEEDED(hr) && d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh);
4067 #if 0
4068 /* too much detail requested, so will appear to hang */
4069 trace("Waiting for D3DXCreateText to finish with deviation = FLT_MIN ...\n");
4070 hr = D3DXCreateText(device, hdc, "wine", FLT_MIN, 0.4f, &d3dxmesh, NULL, NULL);
4071 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
4072 if (SUCCEEDED(hr) && d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh);
4073 trace("D3DXCreateText finish with deviation = FLT_MIN\n");
4074 #endif
4076 hr = D3DXCreateText(device, hdc, "wine", 0.001f, 0.4f, &d3dxmesh, NULL, NULL);
4077 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
4078 if (SUCCEEDED(hr) && d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh);
4080 test_createtext(device, hdc, "wine", FLT_MAX, 0.4f);
4081 test_createtext(device, hdc, "wine", 0.001f, FLT_MIN);
4082 test_createtext(device, hdc, "wine", 0.001f, 0.0f);
4083 test_createtext(device, hdc, "wine", 0.001f, FLT_MAX);
4084 test_createtext(device, hdc, "wine", 0.0f, 1.0f);
4086 DeleteDC(hdc);
4088 IDirect3DDevice9_Release(device);
4089 IDirect3D9_Release(d3d);
4090 DestroyWindow(wnd);
4093 static void test_get_decl_length(void)
4095 static const D3DVERTEXELEMENT9 declaration1[] =
4097 {0, 0, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4098 {1, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4099 {2, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4100 {3, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4101 {4, 0, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4102 {5, 0, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4103 {6, 0, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4104 {7, 0, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4105 {8, 0, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4106 {9, 0, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4107 {10, 0, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4108 {11, 0, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4109 {12, 0, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4110 {13, 0, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4111 {14, 0, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4112 D3DDECL_END(),
4114 static const D3DVERTEXELEMENT9 declaration2[] =
4116 {0, 8, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4117 {1, 8, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4118 {2, 8, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4119 {3, 8, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4120 {4, 8, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4121 {5, 8, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4122 {6, 8, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4123 {7, 8, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4124 {0, 8, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4125 {1, 8, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4126 {2, 8, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4127 {3, 8, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4128 {4, 8, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4129 {5, 8, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4130 {6, 8, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4131 {7, 8, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4132 D3DDECL_END(),
4134 UINT size;
4136 size = D3DXGetDeclLength(declaration1);
4137 ok(size == 15, "Got size %u, expected 15.\n", size);
4139 size = D3DXGetDeclLength(declaration2);
4140 ok(size == 16, "Got size %u, expected 16.\n", size);
4143 static void test_get_decl_vertex_size(void)
4145 static const D3DVERTEXELEMENT9 declaration1[] =
4147 {0, 0, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4148 {1, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4149 {2, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4150 {3, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4151 {4, 0, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4152 {5, 0, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4153 {6, 0, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4154 {7, 0, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4155 {8, 0, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4156 {9, 0, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4157 {10, 0, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4158 {11, 0, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4159 {12, 0, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4160 {13, 0, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4161 {14, 0, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4162 D3DDECL_END(),
4164 static const D3DVERTEXELEMENT9 declaration2[] =
4166 {0, 8, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4167 {1, 8, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4168 {2, 8, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4169 {3, 8, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4170 {4, 8, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4171 {5, 8, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4172 {6, 8, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4173 {7, 8, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4174 {0, 8, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4175 {1, 8, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4176 {2, 8, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4177 {3, 8, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4178 {4, 8, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4179 {5, 8, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4180 {6, 8, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4181 {7, 8, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4182 D3DDECL_END(),
4184 static const UINT sizes1[] =
4186 4, 8, 12, 16,
4187 4, 4, 4, 8,
4188 4, 4, 8, 4,
4189 4, 4, 8, 0,
4191 static const UINT sizes2[] =
4193 12, 16, 20, 24,
4194 12, 12, 16, 16,
4196 unsigned int i;
4197 UINT size;
4199 size = D3DXGetDeclVertexSize(NULL, 0);
4200 ok(size == 0, "Got size %#x, expected 0.\n", size);
4202 for (i = 0; i < 16; ++i)
4204 size = D3DXGetDeclVertexSize(declaration1, i);
4205 ok(size == sizes1[i], "Got size %u for stream %u, expected %u.\n", size, i, sizes1[i]);
4208 for (i = 0; i < 8; ++i)
4210 size = D3DXGetDeclVertexSize(declaration2, i);
4211 ok(size == sizes2[i], "Got size %u for stream %u, expected %u.\n", size, i, sizes2[i]);
4215 static void D3DXGenerateAdjacencyTest(void)
4217 HRESULT hr;
4218 HWND wnd;
4219 IDirect3D9 *d3d;
4220 IDirect3DDevice9 *device;
4221 D3DPRESENT_PARAMETERS d3dpp;
4222 ID3DXMesh *d3dxmesh = NULL;
4223 D3DXVECTOR3 *vertices = NULL;
4224 WORD *indices = NULL;
4225 int i;
4226 struct {
4227 DWORD num_vertices;
4228 D3DXVECTOR3 vertices[6];
4229 DWORD num_faces;
4230 WORD indices[3 * 3];
4231 FLOAT epsilon;
4232 DWORD adjacency[3 * 3];
4233 } test_data[] = {
4234 { /* for epsilon < 0, indices must match for faces to be adjacent */
4235 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}},
4236 2, {0, 1, 2, 0, 2, 3},
4237 -1.0,
4238 {-1, -1, 1, 0, -1, -1},
4241 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}},
4242 2, {0, 1, 2, 3, 4, 5},
4243 -1.0,
4244 {-1, -1, -1, -1, -1, -1},
4246 { /* for epsilon == 0, indices or vertices must match for faces to be adjacent */
4247 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}},
4248 2, {0, 1, 2, 3, 4, 5},
4249 0.0,
4250 {-1, -1, 1, 0, -1, -1},
4252 { /* for epsilon > 0, vertices must be less than (but NOT equal to) epsilon distance away */
4253 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}},
4254 2, {0, 1, 2, 3, 4, 5},
4255 0.25,
4256 {-1, -1, -1, -1, -1, -1},
4258 { /* for epsilon > 0, vertices must be less than (but NOT equal to) epsilon distance away */
4259 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}},
4260 2, {0, 1, 2, 3, 4, 5},
4261 0.250001,
4262 {-1, -1, 1, 0, -1, -1},
4264 { /* length between vertices are compared to epsilon, not the individual dimension deltas */
4265 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}},
4266 2, {0, 1, 2, 3, 4, 5},
4267 0.353, /* < sqrt(0.25*0.25 + 0.25*0.25) */
4268 {-1, -1, -1, -1, -1, -1},
4271 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}},
4272 2, {0, 1, 2, 3, 4, 5},
4273 0.354, /* > sqrt(0.25*0.25 + 0.25*0.25) */
4274 {-1, -1, 1, 0, -1, -1},
4276 { /* adjacent faces must have opposite winding orders at the shared edge */
4277 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}},
4278 2, {0, 1, 2, 0, 3, 2},
4279 0.0,
4280 {-1, -1, -1, -1, -1, -1},
4284 wnd = CreateWindow("static", "d3dx9_test", 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL);
4285 if (!wnd)
4287 skip("Couldn't create application window\n");
4288 return;
4290 d3d = Direct3DCreate9(D3D_SDK_VERSION);
4291 if (!d3d)
4293 skip("Couldn't create IDirect3D9 object\n");
4294 DestroyWindow(wnd);
4295 return;
4298 ZeroMemory(&d3dpp, sizeof(d3dpp));
4299 d3dpp.Windowed = TRUE;
4300 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
4301 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, wnd, D3DCREATE_MIXED_VERTEXPROCESSING, &d3dpp, &device);
4302 if (FAILED(hr))
4304 skip("Failed to create IDirect3DDevice9 object %#x\n", hr);
4305 IDirect3D9_Release(d3d);
4306 DestroyWindow(wnd);
4307 return;
4310 for (i = 0; i < ARRAY_SIZE(test_data); i++)
4312 DWORD adjacency[ARRAY_SIZE(test_data[0].adjacency)];
4313 int j;
4315 if (d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh);
4316 d3dxmesh = NULL;
4318 hr = D3DXCreateMeshFVF(test_data[i].num_faces, test_data[i].num_vertices, 0, D3DFVF_XYZ, device, &d3dxmesh);
4319 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
4321 hr = d3dxmesh->lpVtbl->LockVertexBuffer(d3dxmesh, D3DLOCK_DISCARD, (void**)&vertices);
4322 ok(hr == D3D_OK, "test %d: Got result %x, expected %x (D3D_OK)\n", i, hr, D3D_OK);
4323 if (FAILED(hr)) continue;
4324 CopyMemory(vertices, test_data[i].vertices, test_data[i].num_vertices * sizeof(test_data[0].vertices[0]));
4325 d3dxmesh->lpVtbl->UnlockVertexBuffer(d3dxmesh);
4327 hr = d3dxmesh->lpVtbl->LockIndexBuffer(d3dxmesh, D3DLOCK_DISCARD, (void**)&indices);
4328 ok(hr == D3D_OK, "test %d: Got result %x, expected %x (D3D_OK)\n", i, hr, D3D_OK);
4329 if (FAILED(hr)) continue;
4330 CopyMemory(indices, test_data[i].indices, test_data[i].num_faces * 3 * sizeof(test_data[0].indices[0]));
4331 d3dxmesh->lpVtbl->UnlockIndexBuffer(d3dxmesh);
4333 if (i == 0) {
4334 hr = d3dxmesh->lpVtbl->GenerateAdjacency(d3dxmesh, 0.0f, NULL);
4335 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4338 hr = d3dxmesh->lpVtbl->GenerateAdjacency(d3dxmesh, test_data[i].epsilon, adjacency);
4339 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
4340 if (FAILED(hr)) continue;
4342 for (j = 0; j < test_data[i].num_faces * 3; j++)
4343 ok(adjacency[j] == test_data[i].adjacency[j],
4344 "Test %d adjacency %d: Got result %u, expected %u\n", i, j,
4345 adjacency[j], test_data[i].adjacency[j]);
4347 if (d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh);
4350 static void test_update_semantics(void)
4352 HRESULT hr;
4353 struct test_context *test_context = NULL;
4354 ID3DXMesh *mesh = NULL;
4355 D3DVERTEXELEMENT9 declaration0[] =
4357 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4358 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4359 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4360 D3DDECL_END()
4362 D3DVERTEXELEMENT9 declaration_pos_type_color[] =
4364 {0, 0, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4365 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4366 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4367 D3DDECL_END()
4369 D3DVERTEXELEMENT9 declaration_smaller[] =
4371 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4372 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4373 D3DDECL_END()
4375 D3DVERTEXELEMENT9 declaration_larger[] =
4377 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4378 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4379 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4380 {0, 40, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT, 0},
4381 D3DDECL_END()
4383 D3DVERTEXELEMENT9 declaration_multiple_streams[] =
4385 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4386 {1, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT, 0},
4387 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4388 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4390 D3DDECL_END()
4392 D3DVERTEXELEMENT9 declaration_double_usage[] =
4394 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4395 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4396 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4397 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4398 D3DDECL_END()
4400 D3DVERTEXELEMENT9 declaration_undefined_type[] =
4402 {0, 0, D3DDECLTYPE_UNUSED+1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4403 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4404 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4405 D3DDECL_END()
4407 D3DVERTEXELEMENT9 declaration_not_4_byte_aligned_offset[] =
4409 {0, 3, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4410 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4411 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4412 D3DDECL_END()
4414 static const struct
4416 D3DXVECTOR3 position0;
4417 D3DXVECTOR3 position1;
4418 D3DXVECTOR3 normal;
4419 DWORD color;
4421 vertices[] =
4423 { { 0.0f, 1.0f, 0.f}, { 1.0f, 0.0f, 0.f}, {0.0f, 0.0f, 1.0f}, 0xffff0000 },
4424 { { 1.0f, -1.0f, 0.f}, {-1.0f, -1.0f, 0.f}, {0.0f, 0.0f, 1.0f}, 0xff00ff00 },
4425 { {-1.0f, -1.0f, 0.f}, {-1.0f, 1.0f, 0.f}, {0.0f, 0.0f, 1.0f}, 0xff0000ff },
4427 unsigned int faces[] = {0, 1, 2};
4428 unsigned int attributes[] = {0};
4429 unsigned int num_faces = ARRAY_SIZE(faces) / 3;
4430 unsigned int num_vertices = ARRAY_SIZE(vertices);
4431 int offset = sizeof(D3DXVECTOR3);
4432 DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
4433 void *vertex_buffer;
4434 void *index_buffer;
4435 DWORD *attributes_buffer;
4436 D3DVERTEXELEMENT9 declaration[MAX_FVF_DECL_SIZE];
4437 D3DVERTEXELEMENT9 *decl_ptr;
4438 DWORD exp_vertex_size = sizeof(*vertices);
4439 DWORD vertex_size = 0;
4440 int equal;
4441 int i = 0;
4442 int *decl_mem;
4443 int filler_a = 0xaaaaaaaa;
4444 int filler_b = 0xbbbbbbbb;
4446 test_context = new_test_context();
4447 if (!test_context)
4449 skip("Couldn't create a test_context\n");
4450 goto cleanup;
4453 hr = D3DXCreateMesh(num_faces, num_vertices, options, declaration0,
4454 test_context->device, &mesh);
4455 if (FAILED(hr))
4457 skip("Couldn't create test mesh %#x\n", hr);
4458 goto cleanup;
4461 mesh->lpVtbl->LockVertexBuffer(mesh, 0, &vertex_buffer);
4462 memcpy(vertex_buffer, vertices, sizeof(vertices));
4463 mesh->lpVtbl->UnlockVertexBuffer(mesh);
4465 mesh->lpVtbl->LockIndexBuffer(mesh, 0, &index_buffer);
4466 memcpy(index_buffer, faces, sizeof(faces));
4467 mesh->lpVtbl->UnlockIndexBuffer(mesh);
4469 mesh->lpVtbl->LockAttributeBuffer(mesh, 0, &attributes_buffer);
4470 memcpy(attributes_buffer, attributes, sizeof(attributes));
4471 mesh->lpVtbl->UnlockAttributeBuffer(mesh);
4473 /* Get the declaration and try to change it */
4474 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4475 if (FAILED(hr))
4477 skip("Couldn't get vertex declaration %#x\n", hr);
4478 goto cleanup;
4480 equal = memcmp(declaration, declaration0, sizeof(declaration0));
4481 ok(equal == 0, "Vertex declarations were not equal\n");
4483 for (decl_ptr = declaration; decl_ptr->Stream != 0xFF; decl_ptr++)
4485 if (decl_ptr->Usage == D3DDECLUSAGE_POSITION)
4487 /* Use second vertex position instead of first */
4488 decl_ptr->Offset = offset;
4492 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration);
4493 ok(hr == D3D_OK, "Test UpdateSematics, got %#x expected %#x\n", hr, D3D_OK);
4495 /* Check that declaration was written by getting it again */
4496 memset(declaration, 0, sizeof(declaration));
4497 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4498 if (FAILED(hr))
4500 skip("Couldn't get vertex declaration %#x\n", hr);
4501 goto cleanup;
4504 for (decl_ptr = declaration; decl_ptr->Stream != 0xFF; decl_ptr++)
4506 if (decl_ptr->Usage == D3DDECLUSAGE_POSITION)
4508 ok(decl_ptr->Offset == offset, "Test UpdateSematics, got offset %d expected %d\n",
4509 decl_ptr->Offset, offset);
4513 /* Check that GetDeclaration only writes up to the D3DDECL_END() marker and
4514 * not the full MAX_FVF_DECL_SIZE elements.
4516 memset(declaration, filler_a, sizeof(declaration));
4517 memcpy(declaration, declaration0, sizeof(declaration0));
4518 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration);
4519 ok(hr == D3D_OK, "Test UpdateSematics, "
4520 "got %#x expected D3D_OK\n", hr);
4521 memset(declaration, filler_b, sizeof(declaration));
4522 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4523 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4524 decl_mem = (int*)declaration;
4525 for (i = sizeof(declaration0)/sizeof(*decl_mem); i < sizeof(declaration)/sizeof(*decl_mem); i++)
4527 equal = memcmp(&decl_mem[i], &filler_b, sizeof(filler_b));
4528 ok(equal == 0,
4529 "GetDeclaration wrote past the D3DDECL_END() marker. "
4530 "Got %#x, expected %#x\n", decl_mem[i], filler_b);
4531 if (equal != 0) break;
4534 /* UpdateSemantics does not check for overlapping fields */
4535 memset(declaration, 0, sizeof(declaration));
4536 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4537 if (FAILED(hr))
4539 skip("Couldn't get vertex declaration %#x\n", hr);
4540 goto cleanup;
4543 for (decl_ptr = declaration; decl_ptr->Stream != 0xFF; decl_ptr++)
4545 if (decl_ptr->Type == D3DDECLTYPE_FLOAT3)
4547 decl_ptr->Type = D3DDECLTYPE_FLOAT4;
4551 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration);
4552 ok(hr == D3D_OK, "Test UpdateSematics for overlapping fields, "
4553 "got %#x expected D3D_OK\n", hr);
4555 /* Set the position type to color instead of float3 */
4556 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_pos_type_color);
4557 ok(hr == D3D_OK, "Test UpdateSematics position type color, "
4558 "got %#x expected D3D_OK\n", hr);
4560 /* The following test cases show that NULL, smaller or larger declarations,
4561 * and declarations with non-zero Stream values are not accepted.
4562 * UpdateSemantics returns D3DERR_INVALIDCALL and the previously set
4563 * declaration will be used by DrawSubset, GetNumBytesPerVertex, and
4564 * GetDeclaration.
4567 /* Null declaration (invalid declaration) */
4568 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4569 hr = mesh->lpVtbl->UpdateSemantics(mesh, NULL);
4570 ok(hr == D3DERR_INVALIDCALL, "Test UpdateSematics null pointer declaration, "
4571 "got %#x expected D3DERR_INVALIDCALL\n", hr);
4572 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4573 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4574 vertex_size, exp_vertex_size);
4575 memset(declaration, 0, sizeof(declaration));
4576 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4577 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4578 equal = memcmp(declaration, declaration0, sizeof(declaration0));
4579 ok(equal == 0, "Vertex declarations were not equal\n");
4581 /* Smaller vertex declaration (invalid declaration) */
4582 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4583 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_smaller);
4584 ok(hr == D3DERR_INVALIDCALL, "Test UpdateSematics for smaller vertex declaration, "
4585 "got %#x expected D3DERR_INVALIDCALL\n", hr);
4586 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4587 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4588 vertex_size, exp_vertex_size);
4589 memset(declaration, 0, sizeof(declaration));
4590 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4591 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4592 equal = memcmp(declaration, declaration0, sizeof(declaration0));
4593 ok(equal == 0, "Vertex declarations were not equal\n");
4595 /* Larger vertex declaration (invalid declaration) */
4596 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4597 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_larger);
4598 ok(hr == D3DERR_INVALIDCALL, "Test UpdateSematics for larger vertex declaration, "
4599 "got %#x expected D3DERR_INVALIDCALL\n", hr);
4600 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4601 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4602 vertex_size, exp_vertex_size);
4603 memset(declaration, 0, sizeof(declaration));
4604 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4605 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4606 equal = memcmp(declaration, declaration0, sizeof(declaration0));
4607 ok(equal == 0, "Vertex declarations were not equal\n");
4609 /* Use multiple streams and keep the same vertex size (invalid declaration) */
4610 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4611 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_multiple_streams);
4612 ok(hr == D3DERR_INVALIDCALL, "Test UpdateSematics using multiple streams, "
4613 "got %#x expected D3DERR_INVALIDCALL\n", hr);
4614 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4615 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4616 vertex_size, exp_vertex_size);
4617 memset(declaration, 0, sizeof(declaration));
4618 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4619 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4620 equal = memcmp(declaration, declaration0, sizeof(declaration0));
4621 ok(equal == 0, "Vertex declarations were not equal\n");
4623 /* The next following test cases show that some invalid declarations are
4624 * accepted with a D3D_OK. An access violation is thrown on Windows if
4625 * DrawSubset is called. The methods GetNumBytesPerVertex and GetDeclaration
4626 * are not affected, which indicates that the declaration is cached.
4629 /* Double usage (invalid declaration) */
4630 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4631 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_double_usage);
4632 ok(hr == D3D_OK, "Test UpdateSematics double usage, "
4633 "got %#x expected D3D_OK\n", hr);
4634 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4635 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4636 vertex_size, exp_vertex_size);
4637 memset(declaration, 0, sizeof(declaration));
4638 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4639 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4640 equal = memcmp(declaration, declaration_double_usage, sizeof(declaration_double_usage));
4641 ok(equal == 0, "Vertex declarations were not equal\n");
4643 /* Set the position to an undefined type (invalid declaration) */
4644 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4645 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_undefined_type);
4646 ok(hr == D3D_OK, "Test UpdateSematics undefined type, "
4647 "got %#x expected D3D_OK\n", hr);
4648 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4649 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4650 vertex_size, exp_vertex_size);
4651 memset(declaration, 0, sizeof(declaration));
4652 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4653 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4654 equal = memcmp(declaration, declaration_undefined_type, sizeof(declaration_undefined_type));
4655 ok(equal == 0, "Vertex declarations were not equal\n");
4657 /* Use a not 4 byte aligned offset (invalid declaration) */
4658 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4659 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_not_4_byte_aligned_offset);
4660 ok(hr == D3D_OK, "Test UpdateSematics not 4 byte aligned offset, "
4661 "got %#x expected D3D_OK\n", hr);
4662 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4663 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4664 vertex_size, exp_vertex_size);
4665 memset(declaration, 0, sizeof(declaration));
4666 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4667 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4668 equal = memcmp(declaration, declaration_not_4_byte_aligned_offset,
4669 sizeof(declaration_not_4_byte_aligned_offset));
4670 ok(equal == 0, "Vertex declarations were not equal\n");
4672 cleanup:
4673 if (mesh)
4674 mesh->lpVtbl->Release(mesh);
4676 free_test_context(test_context);
4679 static void test_create_skin_info(void)
4681 HRESULT hr;
4682 ID3DXSkinInfo *skininfo = NULL;
4683 D3DVERTEXELEMENT9 empty_declaration[] = { D3DDECL_END() };
4684 D3DVERTEXELEMENT9 declaration_out[MAX_FVF_DECL_SIZE];
4685 const D3DVERTEXELEMENT9 declaration_with_nonzero_stream[] = {
4686 {1, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
4687 D3DDECL_END()
4690 hr = D3DXCreateSkinInfo(0, empty_declaration, 0, &skininfo);
4691 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4692 if (skininfo) IUnknown_Release(skininfo);
4693 skininfo = NULL;
4695 hr = D3DXCreateSkinInfo(1, NULL, 1, &skininfo);
4696 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4698 hr = D3DXCreateSkinInfo(1, declaration_with_nonzero_stream, 1, &skininfo);
4699 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4701 hr = D3DXCreateSkinInfoFVF(1, 0, 1, &skininfo);
4702 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4703 if (skininfo) {
4704 DWORD dword_result;
4705 FLOAT flt_result;
4706 LPCSTR string_result;
4707 D3DXMATRIX *transform;
4708 D3DXMATRIX identity_matrix;
4710 /* test initial values */
4711 hr = skininfo->lpVtbl->GetDeclaration(skininfo, declaration_out);
4712 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4713 if (SUCCEEDED(hr))
4714 compare_elements(declaration_out, empty_declaration, __LINE__, 0);
4716 dword_result = skininfo->lpVtbl->GetNumBones(skininfo);
4717 ok(dword_result == 1, "Expected 1, got %u\n", dword_result);
4719 flt_result = skininfo->lpVtbl->GetMinBoneInfluence(skininfo);
4720 ok(flt_result == 0.0f, "Expected 0.0, got %g\n", flt_result);
4722 string_result = skininfo->lpVtbl->GetBoneName(skininfo, 0);
4723 ok(string_result == NULL, "Expected NULL, got %p\n", string_result);
4725 dword_result = skininfo->lpVtbl->GetFVF(skininfo);
4726 ok(dword_result == 0, "Expected 0, got %u\n", dword_result);
4728 dword_result = skininfo->lpVtbl->GetNumBoneInfluences(skininfo, 0);
4729 ok(dword_result == 0, "Expected 0, got %u\n", dword_result);
4731 dword_result = skininfo->lpVtbl->GetNumBoneInfluences(skininfo, 1);
4732 ok(dword_result == 0, "Expected 0, got %u\n", dword_result);
4734 transform = skininfo->lpVtbl->GetBoneOffsetMatrix(skininfo, -1);
4735 ok(transform == NULL, "Expected NULL, got %p\n", transform);
4738 /* test [GS]etBoneOffsetMatrix */
4739 hr = skininfo->lpVtbl->SetBoneOffsetMatrix(skininfo, 1, &identity_matrix);
4740 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4742 hr = skininfo->lpVtbl->SetBoneOffsetMatrix(skininfo, 0, NULL);
4743 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4745 D3DXMatrixIdentity(&identity_matrix);
4746 hr = skininfo->lpVtbl->SetBoneOffsetMatrix(skininfo, 0, &identity_matrix);
4747 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4749 transform = skininfo->lpVtbl->GetBoneOffsetMatrix(skininfo, 0);
4750 check_matrix(transform, &identity_matrix);
4754 /* test [GS]etBoneName */
4755 const char *name_in = "testBoneName";
4756 const char *string_result2;
4758 hr = skininfo->lpVtbl->SetBoneName(skininfo, 1, name_in);
4759 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4761 hr = skininfo->lpVtbl->SetBoneName(skininfo, 0, NULL);
4762 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4764 hr = skininfo->lpVtbl->SetBoneName(skininfo, 0, name_in);
4765 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4767 string_result = skininfo->lpVtbl->GetBoneName(skininfo, 0);
4768 ok(string_result != NULL, "Expected non-NULL string, got %p\n", string_result);
4769 ok(!strcmp(string_result, name_in), "Expected '%s', got '%s'\n", name_in, string_result);
4771 string_result2 = skininfo->lpVtbl->GetBoneName(skininfo, 0);
4772 ok(string_result == string_result2, "Expected %p, got %p\n", string_result, string_result2);
4774 string_result = skininfo->lpVtbl->GetBoneName(skininfo, 1);
4775 ok(string_result == NULL, "Expected NULL, got %p\n", string_result);
4779 /* test [GS]etBoneInfluence */
4780 DWORD vertices[2];
4781 FLOAT weights[2];
4782 int i;
4783 DWORD num_influences;
4784 DWORD exp_vertices[2];
4785 FLOAT exp_weights[2];
4787 /* vertex and weight arrays untouched when num_influences is 0 */
4788 vertices[0] = 0xdeadbeef;
4789 weights[0] = FLT_MAX;
4790 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, vertices, weights);
4791 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4792 ok(vertices[0] == 0xdeadbeef, "expected 0xdeadbeef, got %#x\n", vertices[0]);
4793 ok(weights[0] == FLT_MAX, "expected %g, got %g\n", FLT_MAX, weights[0]);
4795 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 1, vertices, weights);
4796 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4798 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, NULL, NULL);
4799 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4801 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, vertices, NULL);
4802 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4804 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, NULL, weights);
4805 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4808 /* no vertex or weight value checking */
4809 exp_vertices[0] = 0;
4810 exp_vertices[1] = 0x87654321;
4811 exp_weights[0] = 0.5;
4812 exp_weights[1] = 0.0f / 0.0f; /* NAN */
4813 num_influences = 2;
4815 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 1, num_influences, vertices, weights);
4816 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4818 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, num_influences, NULL, weights);
4819 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4821 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, num_influences, vertices, NULL);
4822 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4824 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, num_influences, NULL, NULL);
4825 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4827 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, num_influences, exp_vertices, exp_weights);
4828 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4830 memset(vertices, 0, sizeof(vertices));
4831 memset(weights, 0, sizeof(weights));
4832 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, vertices, weights);
4833 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4834 for (i = 0; i < num_influences; i++) {
4835 ok(exp_vertices[i] == vertices[i],
4836 "influence[%d]: expected vertex %u, got %u\n", i, exp_vertices[i], vertices[i]);
4837 ok((isnan(exp_weights[i]) && isnan(weights[i])) || exp_weights[i] == weights[i],
4838 "influence[%d]: expected weights %g, got %g\n", i, exp_weights[i], weights[i]);
4841 /* vertices and weights aren't returned after setting num_influences to 0 */
4842 memset(vertices, 0, sizeof(vertices));
4843 memset(weights, 0, sizeof(weights));
4844 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, 0, vertices, weights);
4845 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4847 vertices[0] = 0xdeadbeef;
4848 weights[0] = FLT_MAX;
4849 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, vertices, weights);
4850 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4851 ok(vertices[0] == 0xdeadbeef, "expected vertex 0xdeadbeef, got %u\n", vertices[0]);
4852 ok(weights[0] == FLT_MAX, "expected weight %g, got %g\n", FLT_MAX, weights[0]);
4856 /* test [GS]etFVF and [GS]etDeclaration */
4857 D3DVERTEXELEMENT9 declaration_in[MAX_FVF_DECL_SIZE];
4858 DWORD fvf = D3DFVF_XYZ;
4859 DWORD got_fvf;
4861 hr = skininfo->lpVtbl->SetDeclaration(skininfo, NULL);
4862 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4864 hr = skininfo->lpVtbl->SetDeclaration(skininfo, declaration_with_nonzero_stream);
4865 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4867 hr = skininfo->lpVtbl->SetFVF(skininfo, 0);
4868 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4870 hr = D3DXDeclaratorFromFVF(fvf, declaration_in);
4871 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4872 hr = skininfo->lpVtbl->SetDeclaration(skininfo, declaration_in);
4873 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4874 got_fvf = skininfo->lpVtbl->GetFVF(skininfo);
4875 ok(fvf == got_fvf, "Expected %#x, got %#x\n", fvf, got_fvf);
4876 hr = skininfo->lpVtbl->GetDeclaration(skininfo, declaration_out);
4877 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4878 compare_elements(declaration_out, declaration_in, __LINE__, 0);
4880 hr = skininfo->lpVtbl->SetDeclaration(skininfo, empty_declaration);
4881 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4882 got_fvf = skininfo->lpVtbl->GetFVF(skininfo);
4883 ok(got_fvf == 0, "Expected 0, got %#x\n", got_fvf);
4884 hr = skininfo->lpVtbl->GetDeclaration(skininfo, declaration_out);
4885 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4886 compare_elements(declaration_out, empty_declaration, __LINE__, 0);
4888 hr = skininfo->lpVtbl->SetFVF(skininfo, fvf);
4889 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4890 got_fvf = skininfo->lpVtbl->GetFVF(skininfo);
4891 ok(fvf == got_fvf, "Expected %#x, got %#x\n", fvf, got_fvf);
4892 hr = skininfo->lpVtbl->GetDeclaration(skininfo, declaration_out);
4893 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4894 compare_elements(declaration_out, declaration_in, __LINE__, 0);
4897 if (skininfo) IUnknown_Release(skininfo);
4898 skininfo = NULL;
4900 hr = D3DXCreateSkinInfoFVF(1, D3DFVF_XYZ, 1, NULL);
4901 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4903 hr = D3DXCreateSkinInfo(1, NULL, 1, &skininfo);
4904 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4907 static void test_convert_adjacency_to_point_reps(void)
4909 HRESULT hr;
4910 struct test_context *test_context = NULL;
4911 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
4912 const DWORD options_16bit = D3DXMESH_SYSTEMMEM;
4913 const D3DVERTEXELEMENT9 declaration[] =
4915 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4916 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4917 {0, 24, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4918 D3DDECL_END()
4920 const unsigned int VERTS_PER_FACE = 3;
4921 void *vertex_buffer;
4922 void *index_buffer;
4923 DWORD *attributes_buffer;
4924 int i, j;
4925 enum color { RED = 0xffff0000, GREEN = 0xff00ff00, BLUE = 0xff0000ff};
4926 struct vertex_pnc
4928 D3DXVECTOR3 position;
4929 D3DXVECTOR3 normal;
4930 enum color color; /* In case of manual visual inspection */
4932 D3DXVECTOR3 up = {0.0f, 0.0f, 1.0f};
4933 /* mesh0 (one face)
4935 * 0--1
4936 * | /
4937 * |/
4940 const struct vertex_pnc vertices0[] =
4942 {{ 0.0f, 3.0f, 0.f}, up, RED},
4943 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
4944 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
4946 const DWORD indices0[] = {0, 1, 2};
4947 const unsigned int num_vertices0 = ARRAY_SIZE(vertices0);
4948 const unsigned int num_faces0 = ARRAY_SIZE(indices0) / VERTS_PER_FACE;
4949 const DWORD adjacency0[] = {-1, -1, -1};
4950 const DWORD exp_point_rep0[] = {0, 1, 2};
4951 /* mesh1 (right)
4953 * 0--1 3
4954 * | / /|
4955 * |/ / |
4956 * 2 5--4
4958 const struct vertex_pnc vertices1[] =
4960 {{ 0.0f, 3.0f, 0.f}, up, RED},
4961 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
4962 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
4964 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
4965 {{ 3.0f, 0.0f, 0.f}, up, RED},
4966 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
4968 const DWORD indices1[] = {0, 1, 2, 3, 4, 5};
4969 const unsigned int num_vertices1 = ARRAY_SIZE(vertices1);
4970 const unsigned int num_faces1 = ARRAY_SIZE(indices1) / VERTS_PER_FACE;
4971 const DWORD adjacency1[] = {-1, 1, -1, -1, -1, 0};
4972 const DWORD exp_point_rep1[] = {0, 1, 2, 1, 4, 2};
4973 /* mesh2 (left)
4975 * 3 0--1
4976 * /| | /
4977 * / | |/
4978 * 5--4 2
4980 const struct vertex_pnc vertices2[] =
4982 {{ 0.0f, 3.0f, 0.f}, up, RED},
4983 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
4984 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
4986 {{-1.0f, 3.0f, 0.f}, up, RED},
4987 {{-1.0f, 0.0f, 0.f}, up, GREEN},
4988 {{-3.0f, 0.0f, 0.f}, up, BLUE},
4990 const DWORD indices2[] = {0, 1, 2, 3, 4, 5};
4991 const unsigned int num_vertices2 = ARRAY_SIZE(vertices2);
4992 const unsigned int num_faces2 = ARRAY_SIZE(indices2) / VERTS_PER_FACE;
4993 const DWORD adjacency2[] = {-1, -1, 1, 0, -1, -1};
4994 const DWORD exp_point_rep2[] = {0, 1, 2, 0, 2, 5};
4995 /* mesh3 (above)
4998 * /|
4999 * / |
5000 * 5--4
5001 * 0--1
5002 * | /
5003 * |/
5006 struct vertex_pnc vertices3[] =
5008 {{ 0.0f, 3.0f, 0.f}, up, RED},
5009 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5010 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5012 {{ 2.0f, 7.0f, 0.f}, up, BLUE},
5013 {{ 2.0f, 4.0f, 0.f}, up, GREEN},
5014 {{ 0.0f, 4.0f, 0.f}, up, RED},
5016 const DWORD indices3[] = {0, 1, 2, 3, 4, 5};
5017 const unsigned int num_vertices3 = ARRAY_SIZE(vertices3);
5018 const unsigned int num_faces3 = ARRAY_SIZE(indices3) / VERTS_PER_FACE;
5019 const DWORD adjacency3[] = {1, -1, -1, -1, 0, -1};
5020 const DWORD exp_point_rep3[] = {0, 1, 2, 3, 1, 0};
5021 /* mesh4 (below, tip against tip)
5023 * 0--1
5024 * | /
5025 * |/
5028 * |\
5029 * | \
5030 * 5--4
5032 struct vertex_pnc vertices4[] =
5034 {{ 0.0f, 3.0f, 0.f}, up, RED},
5035 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5036 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5038 {{ 0.0f, -4.0f, 0.f}, up, BLUE},
5039 {{ 2.0f, -7.0f, 0.f}, up, GREEN},
5040 {{ 0.0f, -7.0f, 0.f}, up, RED},
5042 const DWORD indices4[] = {0, 1, 2, 3, 4, 5};
5043 const unsigned int num_vertices4 = ARRAY_SIZE(vertices4);
5044 const unsigned int num_faces4 = ARRAY_SIZE(indices4) / VERTS_PER_FACE;
5045 const DWORD adjacency4[] = {-1, -1, -1, -1, -1, -1};
5046 const DWORD exp_point_rep4[] = {0, 1, 2, 3, 4, 5};
5047 /* mesh5 (gap in mesh)
5049 * 0 3-----4 15
5050 * / \ \ / / \
5051 * / \ \ / / \
5052 * 2-----1 5 17-----16
5053 * 6-----7 9 12-----13
5054 * \ / / \ \ /
5055 * \ / / \ \ /
5056 * 8 10-----11 14
5059 const struct vertex_pnc vertices5[] =
5061 {{ 0.0f, 1.0f, 0.f}, up, RED},
5062 {{ 1.0f, -1.0f, 0.f}, up, GREEN},
5063 {{-1.0f, -1.0f, 0.f}, up, BLUE},
5065 {{ 0.1f, 1.0f, 0.f}, up, RED},
5066 {{ 2.1f, 1.0f, 0.f}, up, BLUE},
5067 {{ 1.1f, -1.0f, 0.f}, up, GREEN},
5069 {{-1.0f, -1.1f, 0.f}, up, BLUE},
5070 {{ 1.0f, -1.1f, 0.f}, up, GREEN},
5071 {{ 0.0f, -3.1f, 0.f}, up, RED},
5073 {{ 1.1f, -1.1f, 0.f}, up, GREEN},
5074 {{ 2.1f, -3.1f, 0.f}, up, BLUE},
5075 {{ 0.1f, -3.1f, 0.f}, up, RED},
5077 {{ 1.2f, -1.1f, 0.f}, up, GREEN},
5078 {{ 3.2f, -1.1f, 0.f}, up, RED},
5079 {{ 2.2f, -3.1f, 0.f}, up, BLUE},
5081 {{ 2.2f, 1.0f, 0.f}, up, BLUE},
5082 {{ 3.2f, -1.0f, 0.f}, up, RED},
5083 {{ 1.2f, -1.0f, 0.f}, up, GREEN},
5085 const DWORD indices5[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17};
5086 const unsigned int num_vertices5 = ARRAY_SIZE(vertices5);
5087 const unsigned int num_faces5 = ARRAY_SIZE(indices5) / VERTS_PER_FACE;
5088 const DWORD adjacency5[] = {-1, 2, -1, -1, 5, -1, 0, -1, -1, 4, -1, -1, 5, -1, 3, -1, 4, 1};
5089 const DWORD exp_point_rep5[] = {0, 1, 2, 3, 4, 5, 2, 1, 8, 5, 10, 11, 5, 13, 10, 4, 13, 5};
5090 const WORD indices5_16bit[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17};
5091 /* mesh6 (indices re-ordering)
5093 * 0--1 6 3
5094 * | / /| |\
5095 * |/ / | | \
5096 * 2 8--7 5--4
5098 const struct vertex_pnc vertices6[] =
5100 {{ 0.0f, 3.0f, 0.f}, up, RED},
5101 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5102 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5104 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5105 {{ 3.0f, 0.0f, 0.f}, up, RED},
5106 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5108 {{ 4.0f, 3.0f, 0.f}, up, GREEN},
5109 {{ 6.0f, 0.0f, 0.f}, up, BLUE},
5110 {{ 4.0f, 0.0f, 0.f}, up, RED},
5112 const DWORD indices6[] = {0, 1, 2, 6, 7, 8, 3, 4, 5};
5113 const unsigned int num_vertices6 = ARRAY_SIZE(vertices6);
5114 const unsigned int num_faces6 = ARRAY_SIZE(indices6) / VERTS_PER_FACE;
5115 const DWORD adjacency6[] = {-1, 1, -1, 2, -1, 0, -1, -1, 1};
5116 const DWORD exp_point_rep6[] = {0, 1, 2, 1, 4, 5, 1, 5, 2};
5117 /* mesh7 (expands collapsed triangle)
5119 * 0--1 3
5120 * | / /|
5121 * |/ / |
5122 * 2 5--4
5124 const struct vertex_pnc vertices7[] =
5126 {{ 0.0f, 3.0f, 0.f}, up, RED},
5127 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5128 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5130 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5131 {{ 3.0f, 0.0f, 0.f}, up, RED},
5132 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5134 const DWORD indices7[] = {0, 1, 2, 3, 3, 3}; /* Face 1 is collapsed*/
5135 const unsigned int num_vertices7 = ARRAY_SIZE(vertices7);
5136 const unsigned int num_faces7 = ARRAY_SIZE(indices7) / VERTS_PER_FACE;
5137 const DWORD adjacency7[] = {-1, -1, -1, -1, -1, -1};
5138 const DWORD exp_point_rep7[] = {0, 1, 2, 3, 4, 5};
5139 /* mesh8 (indices re-ordering and double replacement)
5141 * 0--1 9 6
5142 * | / /| |\
5143 * |/ / | | \
5144 * 2 11-10 8--7
5145 * 3--4
5146 * | /
5147 * |/
5150 const struct vertex_pnc vertices8[] =
5152 {{ 0.0f, 3.0f, 0.f}, up, RED},
5153 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5154 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5156 {{ 4.0, -4.0, 0.f}, up, RED},
5157 {{ 6.0, -4.0, 0.f}, up, BLUE},
5158 {{ 4.0, -7.0, 0.f}, up, GREEN},
5160 {{ 4.0f, 3.0f, 0.f}, up, GREEN},
5161 {{ 6.0f, 0.0f, 0.f}, up, BLUE},
5162 {{ 4.0f, 0.0f, 0.f}, up, RED},
5164 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5165 {{ 3.0f, 0.0f, 0.f}, up, RED},
5166 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5168 const DWORD indices8[] = {0, 1, 2, 9, 10, 11, 6, 7, 8, 3, 4, 5};
5169 const unsigned int num_vertices8 = ARRAY_SIZE(vertices8);
5170 const unsigned int num_faces8 = ARRAY_SIZE(indices8) / VERTS_PER_FACE;
5171 const DWORD adjacency8[] = {-1, 1, -1, 2, -1, 0, -1, 3, 1, 2, -1, -1};
5172 const DWORD exp_point_rep8[] = {0, 1, 2, 3, 4, 5, 1, 4, 3, 1, 3, 2};
5173 /* mesh9 (right, shared vertices)
5175 * 0--1
5176 * | /|
5177 * |/ |
5178 * 2--3
5180 const struct vertex_pnc vertices9[] =
5182 {{ 0.0f, 3.0f, 0.f}, up, RED},
5183 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5184 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5186 {{ 2.0f, 0.0f, 0.f}, up, RED},
5188 const DWORD indices9[] = {0, 1, 2, 1, 3, 2};
5189 const unsigned int num_vertices9 = ARRAY_SIZE(vertices9);
5190 const unsigned int num_faces9 = ARRAY_SIZE(indices9) / VERTS_PER_FACE;
5191 const DWORD adjacency9[] = {-1, 1, -1, -1, -1, 0};
5192 const DWORD exp_point_rep9[] = {0, 1, 2, 3};
5193 /* All mesh data */
5194 ID3DXMesh *mesh = NULL;
5195 ID3DXMesh *mesh_null_check = NULL;
5196 unsigned int attributes[] = {0};
5197 struct
5199 const struct vertex_pnc *vertices;
5200 const DWORD *indices;
5201 const DWORD num_vertices;
5202 const DWORD num_faces;
5203 const DWORD *adjacency;
5204 const DWORD *exp_point_reps;
5205 const DWORD options;
5207 tc[] =
5210 vertices0,
5211 indices0,
5212 num_vertices0,
5213 num_faces0,
5214 adjacency0,
5215 exp_point_rep0,
5216 options
5219 vertices1,
5220 indices1,
5221 num_vertices1,
5222 num_faces1,
5223 adjacency1,
5224 exp_point_rep1,
5225 options
5228 vertices2,
5229 indices2,
5230 num_vertices2,
5231 num_faces2,
5232 adjacency2,
5233 exp_point_rep2,
5234 options
5237 vertices3,
5238 indices3,
5239 num_vertices3,
5240 num_faces3,
5241 adjacency3,
5242 exp_point_rep3,
5243 options
5246 vertices4,
5247 indices4,
5248 num_vertices4,
5249 num_faces4,
5250 adjacency4,
5251 exp_point_rep4,
5252 options
5255 vertices5,
5256 indices5,
5257 num_vertices5,
5258 num_faces5,
5259 adjacency5,
5260 exp_point_rep5,
5261 options
5264 vertices6,
5265 indices6,
5266 num_vertices6,
5267 num_faces6,
5268 adjacency6,
5269 exp_point_rep6,
5270 options
5273 vertices7,
5274 indices7,
5275 num_vertices7,
5276 num_faces7,
5277 adjacency7,
5278 exp_point_rep7,
5279 options
5282 vertices8,
5283 indices8,
5284 num_vertices8,
5285 num_faces8,
5286 adjacency8,
5287 exp_point_rep8,
5288 options
5291 vertices9,
5292 indices9,
5293 num_vertices9,
5294 num_faces9,
5295 adjacency9,
5296 exp_point_rep9,
5297 options
5300 vertices5,
5301 (DWORD*)indices5_16bit,
5302 num_vertices5,
5303 num_faces5,
5304 adjacency5,
5305 exp_point_rep5,
5306 options_16bit
5309 DWORD *point_reps = NULL;
5311 test_context = new_test_context();
5312 if (!test_context)
5314 skip("Couldn't create test context\n");
5315 goto cleanup;
5318 for (i = 0; i < ARRAY_SIZE(tc); i++)
5320 hr = D3DXCreateMesh(tc[i].num_faces, tc[i].num_vertices, tc[i].options, declaration,
5321 test_context->device, &mesh);
5322 if (FAILED(hr))
5324 skip("Couldn't create mesh %d. Got %x expected D3D_OK\n", i, hr);
5325 goto cleanup;
5328 if (i == 0) /* Save first mesh for later NULL checks */
5329 mesh_null_check = mesh;
5331 point_reps = HeapAlloc(GetProcessHeap(), 0, tc[i].num_vertices * sizeof(*point_reps));
5332 if (!point_reps)
5334 skip("Couldn't allocate point reps array.\n");
5335 goto cleanup;
5338 hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, &vertex_buffer);
5339 if (FAILED(hr))
5341 skip("Couldn't lock vertex buffer.\n");
5342 goto cleanup;
5344 memcpy(vertex_buffer, tc[i].vertices, tc[i].num_vertices * sizeof(*tc[i].vertices));
5345 hr = mesh->lpVtbl->UnlockVertexBuffer(mesh);
5346 if (FAILED(hr))
5348 skip("Couldn't unlock vertex buffer.\n");
5349 goto cleanup;
5352 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, &index_buffer);
5353 if (FAILED(hr))
5355 skip("Couldn't lock index buffer.\n");
5356 goto cleanup;
5358 if (tc[i].options & D3DXMESH_32BIT)
5360 memcpy(index_buffer, tc[i].indices, VERTS_PER_FACE * tc[i].num_faces * sizeof(DWORD));
5362 else
5364 memcpy(index_buffer, tc[i].indices, VERTS_PER_FACE * tc[i].num_faces * sizeof(WORD));
5366 hr = mesh->lpVtbl->UnlockIndexBuffer(mesh);
5367 if (FAILED(hr)) {
5368 skip("Couldn't unlock index buffer.\n");
5369 goto cleanup;
5372 hr = mesh->lpVtbl->LockAttributeBuffer(mesh, 0, &attributes_buffer);
5373 if (FAILED(hr))
5375 skip("Couldn't lock attributes buffer.\n");
5376 goto cleanup;
5378 memcpy(attributes_buffer, attributes, sizeof(attributes));
5379 hr = mesh->lpVtbl->UnlockAttributeBuffer(mesh);
5380 if (FAILED(hr))
5382 skip("Couldn't unlock attributes buffer.\n");
5383 goto cleanup;
5386 /* Convert adjacency to point representation */
5387 for (j = 0; j < tc[i].num_vertices; j++) point_reps[j] = -1;
5388 hr = mesh->lpVtbl->ConvertAdjacencyToPointReps(mesh, tc[i].adjacency, point_reps);
5389 ok(hr == D3D_OK, "ConvertAdjacencyToPointReps failed case %d. "
5390 "Got %x expected D3D_OK\n", i, hr);
5392 /* Check point representation */
5393 for (j = 0; j < tc[i].num_vertices; j++)
5395 ok(point_reps[j] == tc[i].exp_point_reps[j],
5396 "Unexpected point representation at (%d, %d)."
5397 " Got %d expected %d\n",
5398 i, j, point_reps[j], tc[i].exp_point_reps[j]);
5401 HeapFree(GetProcessHeap(), 0, point_reps);
5402 point_reps = NULL;
5404 if (i != 0) /* First mesh will be freed during cleanup */
5405 mesh->lpVtbl->Release(mesh);
5408 /* NULL checks */
5409 hr = mesh_null_check->lpVtbl->ConvertAdjacencyToPointReps(mesh_null_check, tc[0].adjacency, NULL);
5410 ok(hr == D3DERR_INVALIDCALL, "ConvertAdjacencyToPointReps point_reps NULL. "
5411 "Got %x expected D3DERR_INVALIDCALL\n", hr);
5412 hr = mesh_null_check->lpVtbl->ConvertAdjacencyToPointReps(mesh_null_check, NULL, NULL);
5413 ok(hr == D3DERR_INVALIDCALL, "ConvertAdjacencyToPointReps adjacency and point_reps NULL. "
5414 "Got %x expected D3DERR_INVALIDCALL\n", hr);
5416 cleanup:
5417 if (mesh_null_check)
5418 mesh_null_check->lpVtbl->Release(mesh_null_check);
5419 HeapFree(GetProcessHeap(), 0, point_reps);
5420 free_test_context(test_context);
5423 static void test_convert_point_reps_to_adjacency(void)
5425 HRESULT hr;
5426 struct test_context *test_context = NULL;
5427 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
5428 const DWORD options_16bit = D3DXMESH_SYSTEMMEM;
5429 const D3DVERTEXELEMENT9 declaration[] =
5431 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
5432 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
5433 {0, 24, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
5434 D3DDECL_END()
5436 const unsigned int VERTS_PER_FACE = 3;
5437 void *vertex_buffer;
5438 void *index_buffer;
5439 DWORD *attributes_buffer;
5440 int i, j;
5441 enum color { RED = 0xffff0000, GREEN = 0xff00ff00, BLUE = 0xff0000ff};
5442 struct vertex_pnc
5444 D3DXVECTOR3 position;
5445 D3DXVECTOR3 normal;
5446 enum color color; /* In case of manual visual inspection */
5448 D3DXVECTOR3 up = {0.0f, 0.0f, 1.0f};
5449 /* mesh0 (one face)
5451 * 0--1
5452 * | /
5453 * |/
5456 const struct vertex_pnc vertices0[] =
5458 {{ 0.0f, 3.0f, 0.f}, up, RED},
5459 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5460 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5462 const DWORD indices0[] = {0, 1, 2};
5463 const unsigned int num_vertices0 = ARRAY_SIZE(vertices0);
5464 const unsigned int num_faces0 = num_vertices0 / VERTS_PER_FACE;
5465 const DWORD exp_adjacency0[] = {-1, -1, -1};
5466 const DWORD exp_id_adjacency0[] = {-1, -1, -1};
5467 const DWORD point_rep0[] = {0, 1, 2};
5468 /* mesh1 (right)
5470 * 0--1 3
5471 * | / /|
5472 * |/ / |
5473 * 2 5--4
5475 const struct vertex_pnc vertices1[] =
5477 {{ 0.0f, 3.0f, 0.f}, up, RED},
5478 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5479 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5481 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5482 {{ 3.0f, 0.0f, 0.f}, up, RED},
5483 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5485 const DWORD indices1[] = {0, 1, 2, 3, 4, 5};
5486 const unsigned int num_vertices1 = ARRAY_SIZE(vertices1);
5487 const unsigned int num_faces1 = num_vertices1 / VERTS_PER_FACE;
5488 const DWORD exp_adjacency1[] = {-1, 1, -1, -1, -1, 0};
5489 const DWORD exp_id_adjacency1[] = {-1, -1, -1, -1, -1, -1};
5490 const DWORD point_rep1[] = {0, 1, 2, 1, 4, 2};
5491 /* mesh2 (left)
5493 * 3 0--1
5494 * /| | /
5495 * / | |/
5496 * 5--4 2
5498 const struct vertex_pnc vertices2[] =
5500 {{ 0.0f, 3.0f, 0.f}, up, RED},
5501 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5502 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5504 {{-1.0f, 3.0f, 0.f}, up, RED},
5505 {{-1.0f, 0.0f, 0.f}, up, GREEN},
5506 {{-3.0f, 0.0f, 0.f}, up, BLUE},
5508 const DWORD indices2[] = {0, 1, 2, 3, 4, 5};
5509 const unsigned int num_vertices2 = ARRAY_SIZE(vertices2);
5510 const unsigned int num_faces2 = num_vertices2 / VERTS_PER_FACE;
5511 const DWORD exp_adjacency2[] = {-1, -1, 1, 0, -1, -1};
5512 const DWORD exp_id_adjacency2[] = {-1, -1, -1, -1, -1, -1};
5513 const DWORD point_rep2[] = {0, 1, 2, 0, 2, 5};
5514 /* mesh3 (above)
5517 * /|
5518 * / |
5519 * 5--4
5520 * 0--1
5521 * | /
5522 * |/
5525 struct vertex_pnc vertices3[] =
5527 {{ 0.0f, 3.0f, 0.f}, up, RED},
5528 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5529 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5531 {{ 2.0f, 7.0f, 0.f}, up, BLUE},
5532 {{ 2.0f, 4.0f, 0.f}, up, GREEN},
5533 {{ 0.0f, 4.0f, 0.f}, up, RED},
5535 const DWORD indices3[] = {0, 1, 2, 3, 4, 5};
5536 const unsigned int num_vertices3 = ARRAY_SIZE(vertices3);
5537 const unsigned int num_faces3 = num_vertices3 / VERTS_PER_FACE;
5538 const DWORD exp_adjacency3[] = {1, -1, -1, -1, 0, -1};
5539 const DWORD exp_id_adjacency3[] = {-1, -1, -1, -1, -1, -1};
5540 const DWORD point_rep3[] = {0, 1, 2, 3, 1, 0};
5541 /* mesh4 (below, tip against tip)
5543 * 0--1
5544 * | /
5545 * |/
5548 * |\
5549 * | \
5550 * 5--4
5552 struct vertex_pnc vertices4[] =
5554 {{ 0.0f, 3.0f, 0.f}, up, RED},
5555 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5556 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5558 {{ 0.0f, -4.0f, 0.f}, up, BLUE},
5559 {{ 2.0f, -7.0f, 0.f}, up, GREEN},
5560 {{ 0.0f, -7.0f, 0.f}, up, RED},
5562 const DWORD indices4[] = {0, 1, 2, 3, 4, 5};
5563 const unsigned int num_vertices4 = ARRAY_SIZE(vertices4);
5564 const unsigned int num_faces4 = num_vertices4 / VERTS_PER_FACE;
5565 const DWORD exp_adjacency4[] = {-1, -1, -1, -1, -1, -1};
5566 const DWORD exp_id_adjacency4[] = {-1, -1, -1, -1, -1, -1};
5567 const DWORD point_rep4[] = {0, 1, 2, 3, 4, 5};
5568 /* mesh5 (gap in mesh)
5570 * 0 3-----4 15
5571 * / \ \ / / \
5572 * / \ \ / / \
5573 * 2-----1 5 17-----16
5574 * 6-----7 9 12-----13
5575 * \ / / \ \ /
5576 * \ / / \ \ /
5577 * 8 10-----11 14
5580 const struct vertex_pnc vertices5[] =
5582 {{ 0.0f, 1.0f, 0.f}, up, RED},
5583 {{ 1.0f, -1.0f, 0.f}, up, GREEN},
5584 {{-1.0f, -1.0f, 0.f}, up, BLUE},
5586 {{ 0.1f, 1.0f, 0.f}, up, RED},
5587 {{ 2.1f, 1.0f, 0.f}, up, BLUE},
5588 {{ 1.1f, -1.0f, 0.f}, up, GREEN},
5590 {{-1.0f, -1.1f, 0.f}, up, BLUE},
5591 {{ 1.0f, -1.1f, 0.f}, up, GREEN},
5592 {{ 0.0f, -3.1f, 0.f}, up, RED},
5594 {{ 1.1f, -1.1f, 0.f}, up, GREEN},
5595 {{ 2.1f, -3.1f, 0.f}, up, BLUE},
5596 {{ 0.1f, -3.1f, 0.f}, up, RED},
5598 {{ 1.2f, -1.1f, 0.f}, up, GREEN},
5599 {{ 3.2f, -1.1f, 0.f}, up, RED},
5600 {{ 2.2f, -3.1f, 0.f}, up, BLUE},
5602 {{ 2.2f, 1.0f, 0.f}, up, BLUE},
5603 {{ 3.2f, -1.0f, 0.f}, up, RED},
5604 {{ 1.2f, -1.0f, 0.f}, up, GREEN},
5606 const DWORD indices5[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17};
5607 const unsigned int num_vertices5 = ARRAY_SIZE(vertices5);
5608 const unsigned int num_faces5 = num_vertices5 / VERTS_PER_FACE;
5609 const DWORD exp_adjacency5[] = {-1, 2, -1, -1, 5, -1, 0, -1, -1, 4, -1, -1, 5, -1, 3, -1, 4, 1};
5610 const DWORD exp_id_adjacency5[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
5611 const DWORD point_rep5[] = {0, 1, 2, 3, 4, 5, 2, 1, 8, 5, 10, 11, 5, 13, 10, 4, 13, 5};
5612 /* mesh6 (indices re-ordering)
5614 * 0--1 6 3
5615 * | / /| |\
5616 * |/ / | | \
5617 * 2 8--7 5--4
5619 const struct vertex_pnc vertices6[] =
5621 {{ 0.0f, 3.0f, 0.f}, up, RED},
5622 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5623 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5625 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5626 {{ 3.0f, 0.0f, 0.f}, up, RED},
5627 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5629 {{ 4.0f, 3.0f, 0.f}, up, GREEN},
5630 {{ 6.0f, 0.0f, 0.f}, up, BLUE},
5631 {{ 4.0f, 0.0f, 0.f}, up, RED},
5633 const DWORD indices6[] = {0, 1, 2, 6, 7, 8, 3, 4, 5};
5634 const unsigned int num_vertices6 = ARRAY_SIZE(vertices6);
5635 const unsigned int num_faces6 = num_vertices6 / VERTS_PER_FACE;
5636 const DWORD exp_adjacency6[] = {-1, 1, -1, 2, -1, 0, -1, -1, 1};
5637 const DWORD exp_id_adjacency6[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1};
5638 const DWORD point_rep6[] = {0, 1, 2, 1, 4, 5, 1, 5, 2};
5639 /* mesh7 (expands collapsed triangle)
5641 * 0--1 3
5642 * | / /|
5643 * |/ / |
5644 * 2 5--4
5646 const struct vertex_pnc vertices7[] =
5648 {{ 0.0f, 3.0f, 0.f}, up, RED},
5649 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5650 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5652 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5653 {{ 3.0f, 0.0f, 0.f}, up, RED},
5654 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5656 const DWORD indices7[] = {0, 1, 2, 3, 3, 3}; /* Face 1 is collapsed*/
5657 const unsigned int num_vertices7 = ARRAY_SIZE(vertices7);
5658 const unsigned int num_faces7 = num_vertices7 / VERTS_PER_FACE;
5659 const DWORD exp_adjacency7[] = {-1, -1, -1, -1, -1, -1};
5660 const DWORD exp_id_adjacency7[] = {-1, -1, -1, -1, -1, -1};
5661 const DWORD point_rep7[] = {0, 1, 2, 3, 4, 5};
5662 /* mesh8 (indices re-ordering and double replacement)
5664 * 0--1 9 6
5665 * | / /| |\
5666 * |/ / | | \
5667 * 2 11-10 8--7
5668 * 3--4
5669 * | /
5670 * |/
5673 const struct vertex_pnc vertices8[] =
5675 {{ 0.0f, 3.0f, 0.f}, up, RED},
5676 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5677 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5679 {{ 4.0, -4.0, 0.f}, up, RED},
5680 {{ 6.0, -4.0, 0.f}, up, BLUE},
5681 {{ 4.0, -7.0, 0.f}, up, GREEN},
5683 {{ 4.0f, 3.0f, 0.f}, up, GREEN},
5684 {{ 6.0f, 0.0f, 0.f}, up, BLUE},
5685 {{ 4.0f, 0.0f, 0.f}, up, RED},
5687 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5688 {{ 3.0f, 0.0f, 0.f}, up, RED},
5689 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5691 const DWORD indices8[] = {0, 1, 2, 9, 10, 11, 6, 7, 8, 3, 4, 5};
5692 const WORD indices8_16bit[] = {0, 1, 2, 9, 10, 11, 6, 7, 8, 3, 4, 5};
5693 const unsigned int num_vertices8 = ARRAY_SIZE(vertices8);
5694 const unsigned int num_faces8 = num_vertices8 / VERTS_PER_FACE;
5695 const DWORD exp_adjacency8[] = {-1, 1, -1, 2, -1, 0, -1, 3, 1, 2, -1, -1};
5696 const DWORD exp_id_adjacency8[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
5697 const DWORD point_rep8[] = {0, 1, 2, 3, 4, 5, 1, 4, 3, 1, 3, 2};
5698 /* mesh9 (right, shared vertices)
5700 * 0--1
5701 * | /|
5702 * |/ |
5703 * 2--3
5705 const struct vertex_pnc vertices9[] =
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 {{ 2.0f, 0.0f, 0.f}, up, RED},
5713 const DWORD indices9[] = {0, 1, 2, 1, 3, 2};
5714 const unsigned int num_vertices9 = ARRAY_SIZE(vertices9);
5715 const unsigned int num_faces9 = 2;
5716 const DWORD exp_adjacency9[] = {-1, 1, -1, -1, -1, 0};
5717 const DWORD exp_id_adjacency9[] = {-1, 1, -1, -1, -1, 0};
5718 const DWORD point_rep9[] = {0, 1, 2, 3};
5719 /* All mesh data */
5720 ID3DXMesh *mesh = NULL;
5721 ID3DXMesh *mesh_null_check = NULL;
5722 unsigned int attributes[] = {0};
5723 struct
5725 const struct vertex_pnc *vertices;
5726 const DWORD *indices;
5727 const DWORD num_vertices;
5728 const DWORD num_faces;
5729 const DWORD *point_reps;
5730 const DWORD *exp_adjacency;
5731 const DWORD *exp_id_adjacency;
5732 const DWORD options;
5734 tc[] =
5737 vertices0,
5738 indices0,
5739 num_vertices0,
5740 num_faces0,
5741 point_rep0,
5742 exp_adjacency0,
5743 exp_id_adjacency0,
5744 options
5747 vertices1,
5748 indices1,
5749 num_vertices1,
5750 num_faces1,
5751 point_rep1,
5752 exp_adjacency1,
5753 exp_id_adjacency1,
5754 options
5757 vertices2,
5758 indices2,
5759 num_vertices2,
5760 num_faces2,
5761 point_rep2,
5762 exp_adjacency2,
5763 exp_id_adjacency2,
5764 options
5767 vertices3,
5768 indices3,
5769 num_vertices3,
5770 num_faces3,
5771 point_rep3,
5772 exp_adjacency3,
5773 exp_id_adjacency3,
5774 options
5777 vertices4,
5778 indices4,
5779 num_vertices4,
5780 num_faces4,
5781 point_rep4,
5782 exp_adjacency4,
5783 exp_id_adjacency4,
5784 options
5787 vertices5,
5788 indices5,
5789 num_vertices5,
5790 num_faces5,
5791 point_rep5,
5792 exp_adjacency5,
5793 exp_id_adjacency5,
5794 options
5797 vertices6,
5798 indices6,
5799 num_vertices6,
5800 num_faces6,
5801 point_rep6,
5802 exp_adjacency6,
5803 exp_id_adjacency6,
5804 options
5807 vertices7,
5808 indices7,
5809 num_vertices7,
5810 num_faces7,
5811 point_rep7,
5812 exp_adjacency7,
5813 exp_id_adjacency7,
5814 options
5817 vertices8,
5818 indices8,
5819 num_vertices8,
5820 num_faces8,
5821 point_rep8,
5822 exp_adjacency8,
5823 exp_id_adjacency8,
5824 options
5827 vertices9,
5828 indices9,
5829 num_vertices9,
5830 num_faces9,
5831 point_rep9,
5832 exp_adjacency9,
5833 exp_id_adjacency9,
5834 options
5837 vertices8,
5838 (DWORD*)indices8_16bit,
5839 num_vertices8,
5840 num_faces8,
5841 point_rep8,
5842 exp_adjacency8,
5843 exp_id_adjacency8,
5844 options_16bit
5847 DWORD *adjacency = NULL;
5849 test_context = new_test_context();
5850 if (!test_context)
5852 skip("Couldn't create test context\n");
5853 goto cleanup;
5856 for (i = 0; i < ARRAY_SIZE(tc); i++)
5858 hr = D3DXCreateMesh(tc[i].num_faces, tc[i].num_vertices, tc[i].options,
5859 declaration, test_context->device, &mesh);
5860 if (FAILED(hr))
5862 skip("Couldn't create mesh %d. Got %x expected D3D_OK\n", i, hr);
5863 goto cleanup;
5866 if (i == 0) /* Save first mesh for later NULL checks */
5867 mesh_null_check = mesh;
5869 adjacency = HeapAlloc(GetProcessHeap(), 0, VERTS_PER_FACE * tc[i].num_faces * sizeof(*adjacency));
5870 if (!adjacency)
5872 skip("Couldn't allocate adjacency array.\n");
5873 goto cleanup;
5876 hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, &vertex_buffer);
5877 if (FAILED(hr))
5879 skip("Couldn't lock vertex buffer.\n");
5880 goto cleanup;
5882 memcpy(vertex_buffer, tc[i].vertices, tc[i].num_vertices * sizeof(*tc[i].vertices));
5883 hr = mesh->lpVtbl->UnlockVertexBuffer(mesh);
5884 if (FAILED(hr))
5886 skip("Couldn't unlock vertex buffer.\n");
5887 goto cleanup;
5889 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, &index_buffer);
5890 if (FAILED(hr))
5892 skip("Couldn't lock index buffer.\n");
5893 goto cleanup;
5895 if (tc[i].options & D3DXMESH_32BIT)
5897 memcpy(index_buffer, tc[i].indices, VERTS_PER_FACE * tc[i].num_faces * sizeof(DWORD));
5899 else
5901 memcpy(index_buffer, tc[i].indices, VERTS_PER_FACE * tc[i].num_faces * sizeof(WORD));
5903 hr = mesh->lpVtbl->UnlockIndexBuffer(mesh);
5904 if (FAILED(hr)) {
5905 skip("Couldn't unlock index buffer.\n");
5906 goto cleanup;
5909 hr = mesh->lpVtbl->LockAttributeBuffer(mesh, 0, &attributes_buffer);
5910 if (FAILED(hr))
5912 skip("Couldn't lock attributes buffer.\n");
5913 goto cleanup;
5915 memcpy(attributes_buffer, attributes, sizeof(attributes));
5916 hr = mesh->lpVtbl->UnlockAttributeBuffer(mesh);
5917 if (FAILED(hr))
5919 skip("Couldn't unlock attributes buffer.\n");
5920 goto cleanup;
5923 /* Convert point representation to adjacency*/
5924 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++) adjacency[j] = -2;
5926 hr = mesh->lpVtbl->ConvertPointRepsToAdjacency(mesh, tc[i].point_reps, adjacency);
5927 ok(hr == D3D_OK, "ConvertPointRepsToAdjacency failed case %d. "
5928 "Got %x expected D3D_OK\n", i, hr);
5929 /* Check adjacency */
5930 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
5932 ok(adjacency[j] == tc[i].exp_adjacency[j],
5933 "Unexpected adjacency information at (%d, %d)."
5934 " Got %d expected %d\n",
5935 i, j, adjacency[j], tc[i].exp_adjacency[j]);
5938 /* NULL point representation is considered identity. */
5939 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++) adjacency[j] = -2;
5940 hr = mesh_null_check->lpVtbl->ConvertPointRepsToAdjacency(mesh, NULL, adjacency);
5941 ok(hr == D3D_OK, "ConvertPointRepsToAdjacency NULL point_reps. "
5942 "Got %x expected D3D_OK\n", hr);
5943 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
5945 ok(adjacency[j] == tc[i].exp_id_adjacency[j],
5946 "Unexpected adjacency information (id) at (%d, %d)."
5947 " Got %d expected %d\n",
5948 i, j, adjacency[j], tc[i].exp_id_adjacency[j]);
5951 HeapFree(GetProcessHeap(), 0, adjacency);
5952 adjacency = NULL;
5953 if (i != 0) /* First mesh will be freed during cleanup */
5954 mesh->lpVtbl->Release(mesh);
5957 /* NULL checks */
5958 hr = mesh_null_check->lpVtbl->ConvertPointRepsToAdjacency(mesh_null_check, tc[0].point_reps, NULL);
5959 ok(hr == D3DERR_INVALIDCALL, "ConvertPointRepsToAdjacency NULL adjacency. "
5960 "Got %x expected D3DERR_INVALIDCALL\n", hr);
5961 hr = mesh_null_check->lpVtbl->ConvertPointRepsToAdjacency(mesh_null_check, NULL, NULL);
5962 ok(hr == D3DERR_INVALIDCALL, "ConvertPointRepsToAdjacency NULL point_reps and adjacency. "
5963 "Got %x expected D3DERR_INVALIDCALL\n", hr);
5965 cleanup:
5966 if (mesh_null_check)
5967 mesh_null_check->lpVtbl->Release(mesh_null_check);
5968 HeapFree(GetProcessHeap(), 0, adjacency);
5969 free_test_context(test_context);
5972 static HRESULT init_test_mesh(const DWORD num_faces, const DWORD num_vertices,
5973 const DWORD options,
5974 const D3DVERTEXELEMENT9 *declaration,
5975 IDirect3DDevice9 *device, ID3DXMesh **mesh_ptr,
5976 const void *vertices, const DWORD vertex_size,
5977 const DWORD *indices, const DWORD *attributes)
5979 HRESULT hr;
5980 void *vertex_buffer;
5981 void *index_buffer;
5982 DWORD *attributes_buffer;
5983 ID3DXMesh *mesh = NULL;
5985 hr = D3DXCreateMesh(num_faces, num_vertices, options, declaration, device, mesh_ptr);
5986 if (FAILED(hr))
5988 skip("Couldn't create mesh. Got %x expected D3D_OK\n", hr);
5989 goto cleanup;
5991 mesh = *mesh_ptr;
5993 hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, &vertex_buffer);
5994 if (FAILED(hr))
5996 skip("Couldn't lock vertex buffer.\n");
5997 goto cleanup;
5999 memcpy(vertex_buffer, vertices, num_vertices * vertex_size);
6000 hr = mesh->lpVtbl->UnlockVertexBuffer(mesh);
6001 if (FAILED(hr))
6003 skip("Couldn't unlock vertex buffer.\n");
6004 goto cleanup;
6007 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, &index_buffer);
6008 if (FAILED(hr))
6010 skip("Couldn't lock index buffer.\n");
6011 goto cleanup;
6013 if (options & D3DXMESH_32BIT)
6015 if (indices)
6016 memcpy(index_buffer, indices, 3 * num_faces * sizeof(DWORD));
6017 else
6019 /* Fill index buffer with 0, 1, 2, ...*/
6020 DWORD *indices_32bit = (DWORD*)index_buffer;
6021 UINT i;
6022 for (i = 0; i < 3 * num_faces; i++)
6023 indices_32bit[i] = i;
6026 else
6028 if (indices)
6029 memcpy(index_buffer, indices, 3 * num_faces * sizeof(WORD));
6030 else
6032 /* Fill index buffer with 0, 1, 2, ...*/
6033 WORD *indices_16bit = (WORD*)index_buffer;
6034 UINT i;
6035 for (i = 0; i < 3 * num_faces; i++)
6036 indices_16bit[i] = i;
6039 hr = mesh->lpVtbl->UnlockIndexBuffer(mesh);
6040 if (FAILED(hr)) {
6041 skip("Couldn't unlock index buffer.\n");
6042 goto cleanup;
6045 hr = mesh->lpVtbl->LockAttributeBuffer(mesh, 0, &attributes_buffer);
6046 if (FAILED(hr))
6048 skip("Couldn't lock attributes buffer.\n");
6049 goto cleanup;
6052 if (attributes)
6053 memcpy(attributes_buffer, attributes, num_faces * sizeof(*attributes));
6054 else
6055 memset(attributes_buffer, 0, num_faces * sizeof(*attributes));
6057 hr = mesh->lpVtbl->UnlockAttributeBuffer(mesh);
6058 if (FAILED(hr))
6060 skip("Couldn't unlock attributes buffer.\n");
6061 goto cleanup;
6064 hr = D3D_OK;
6065 cleanup:
6066 return hr;
6069 /* Using structs instead of bit-fields in order to avoid compiler issues. */
6070 struct udec3
6072 UINT x;
6073 UINT y;
6074 UINT z;
6075 UINT w;
6078 struct dec3n
6080 INT x;
6081 INT y;
6082 INT z;
6083 INT w;
6086 static DWORD init_udec3_dword(UINT x, UINT y, UINT z, UINT w)
6088 DWORD d = 0;
6090 d |= x & 0x3ff;
6091 d |= (y << 10) & 0xffc00;
6092 d |= (z << 20) & 0x3ff00000;
6093 d |= (w << 30) & 0xc0000000;
6095 return d;
6098 static DWORD init_dec3n_dword(INT x, INT y, INT z, INT w)
6100 DWORD d = 0;
6102 d |= x & 0x3ff;
6103 d |= (y << 10) & 0xffc00;
6104 d |= (z << 20) & 0x3ff00000;
6105 d |= (w << 30) & 0xc0000000;
6107 return d;
6110 static struct udec3 dword_to_udec3(DWORD d)
6112 struct udec3 v;
6114 v.x = d & 0x3ff;
6115 v.y = (d & 0xffc00) >> 10;
6116 v.z = (d & 0x3ff00000) >> 20;
6117 v.w = (d & 0xc0000000) >> 30;
6119 return v;
6122 static struct dec3n dword_to_dec3n(DWORD d)
6124 struct dec3n v;
6126 v.x = d & 0x3ff;
6127 v.y = (d & 0xffc00) >> 10;
6128 v.z = (d & 0x3ff00000) >> 20;
6129 v.w = (d & 0xc0000000) >> 30;
6131 return v;
6134 static void check_vertex_components(int line, int mesh_number, int vertex_number, BYTE *got_ptr, const BYTE *exp_ptr, D3DVERTEXELEMENT9 *declaration)
6136 const char *usage_strings[] =
6138 "position",
6139 "blend weight",
6140 "blend indices",
6141 "normal",
6142 "point size",
6143 "texture coordinates",
6144 "tangent",
6145 "binormal",
6146 "tessellation factor",
6147 "position transformed",
6148 "color",
6149 "fog",
6150 "depth",
6151 "sample"
6153 D3DVERTEXELEMENT9 *decl_ptr;
6154 const float PRECISION = 1e-5f;
6156 for (decl_ptr = declaration; decl_ptr->Stream != 0xFF; decl_ptr++)
6158 switch (decl_ptr->Type)
6160 case D3DDECLTYPE_FLOAT1:
6162 FLOAT *got = (FLOAT*)(got_ptr + decl_ptr->Offset);
6163 FLOAT *exp = (FLOAT*)(exp_ptr + decl_ptr->Offset);
6164 FLOAT diff = fabsf(*got - *exp);
6165 ok_(__FILE__,line)(diff <= PRECISION, "Mesh %d: Got %f for vertex %d %s, expected %f.\n",
6166 mesh_number, *got, vertex_number, usage_strings[decl_ptr->Usage], *exp);
6167 break;
6169 case D3DDECLTYPE_FLOAT2:
6171 D3DXVECTOR2 *got = (D3DXVECTOR2*)(got_ptr + decl_ptr->Offset);
6172 D3DXVECTOR2 *exp = (D3DXVECTOR2*)(exp_ptr + decl_ptr->Offset);
6173 FLOAT diff = max(fabsf(got->x - exp->x), fabsf(got->y - exp->y));
6174 ok_(__FILE__,line)(diff <= PRECISION, "Mesh %d: Got (%f, %f) for vertex %d %s, expected (%f, %f).\n",
6175 mesh_number, got->x, got->y, vertex_number, usage_strings[decl_ptr->Usage], exp->x, exp->y);
6176 break;
6178 case D3DDECLTYPE_FLOAT3:
6180 D3DXVECTOR3 *got = (D3DXVECTOR3*)(got_ptr + decl_ptr->Offset);
6181 D3DXVECTOR3 *exp = (D3DXVECTOR3*)(exp_ptr + decl_ptr->Offset);
6182 FLOAT diff = max(fabsf(got->x - exp->x), fabsf(got->y - exp->y));
6183 diff = max(diff, fabsf(got->z - exp->z));
6184 ok_(__FILE__,line)(diff <= PRECISION, "Mesh %d: Got (%f, %f, %f) for vertex %d %s, expected (%f, %f, %f).\n",
6185 mesh_number, got->x, got->y, got->z, vertex_number, usage_strings[decl_ptr->Usage], exp->x, exp->y, exp->z);
6186 break;
6188 case D3DDECLTYPE_FLOAT4:
6190 D3DXVECTOR4 *got = (D3DXVECTOR4*)(got_ptr + decl_ptr->Offset);
6191 D3DXVECTOR4 *exp = (D3DXVECTOR4*)(exp_ptr + decl_ptr->Offset);
6192 FLOAT diff = max(fabsf(got->x - exp->x), fabsf(got->y - exp->y));
6193 diff = max(diff, fabsf(got->z - exp->z));
6194 diff = max(diff, fabsf(got->w - exp->w));
6195 ok_(__FILE__,line)(diff <= PRECISION, "Mesh %d: Got (%f, %f, %f, %f) for vertex %d %s, expected (%f, %f, %f, %f).\n",
6196 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);
6197 break;
6199 case D3DDECLTYPE_D3DCOLOR:
6201 BYTE *got = got_ptr + decl_ptr->Offset;
6202 const BYTE *exp = exp_ptr + decl_ptr->Offset;
6203 BOOL same_color = got[0] == exp[0] && got[1] == exp[1]
6204 && got[2] == exp[2] && got[3] == exp[3];
6205 const char *color_types[] = {"diffuse", "specular", "undefined color"};
6206 BYTE usage_index = decl_ptr->UsageIndex;
6207 if (usage_index > 1) usage_index = 2;
6208 ok_(__FILE__,line)(same_color, "Mesh %d: Got (%u, %u, %u, %u) for vertex %d %s, expected (%u, %u, %u, %u).\n",
6209 mesh_number, got[0], got[1], got[2], got[3], vertex_number, color_types[usage_index], exp[0], exp[1], exp[2], exp[3]);
6210 break;
6212 case D3DDECLTYPE_UBYTE4:
6213 case D3DDECLTYPE_UBYTE4N:
6215 BYTE *got = got_ptr + decl_ptr->Offset;
6216 const BYTE *exp = exp_ptr + decl_ptr->Offset;
6217 BOOL same = got[0] == exp[0] && got[1] == exp[1]
6218 && got[2] == exp[2] && got[3] == exp[3];
6219 ok_(__FILE__,line)(same, "Mesh %d: Got (%u, %u, %u, %u) for vertex %d %s, expected (%u, %u, %u, %u).\n",
6220 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]);
6221 break;
6223 case D3DDECLTYPE_SHORT2:
6224 case D3DDECLTYPE_SHORT2N:
6226 SHORT *got = (SHORT*)(got_ptr + decl_ptr->Offset);
6227 SHORT *exp = (SHORT*)(exp_ptr + decl_ptr->Offset);
6228 BOOL same = got[0] == exp[0] && got[1] == exp[1];
6229 ok_(__FILE__,line)(same, "Mesh %d: Got (%hd, %hd) for vertex %d %s, expected (%hd, %hd).\n",
6230 mesh_number, got[0], got[1], vertex_number, usage_strings[decl_ptr->Usage], exp[0], exp[1]);
6231 break;
6233 case D3DDECLTYPE_SHORT4:
6234 case D3DDECLTYPE_SHORT4N:
6236 SHORT *got = (SHORT*)(got_ptr + decl_ptr->Offset);
6237 SHORT *exp = (SHORT*)(exp_ptr + decl_ptr->Offset);
6238 BOOL same = got[0] == exp[0] && got[1] == exp[1]
6239 && got[2] == exp[2] && got[3] == exp[3];
6240 ok_(__FILE__,line)(same, "Mesh %d: Got (%hd, %hd, %hd, %hd) for vertex %d %s, expected (%hd, %hd, %hd, %hd).\n",
6241 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]);
6242 break;
6244 case D3DDECLTYPE_USHORT2N:
6246 USHORT *got = (USHORT*)(got_ptr + decl_ptr->Offset);
6247 USHORT *exp = (USHORT*)(exp_ptr + decl_ptr->Offset);
6248 BOOL same = got[0] == exp[0] && got[1] == exp[1];
6249 ok_(__FILE__,line)(same, "Mesh %d: Got (%hu, %hu) for vertex %d %s, expected (%hu, %hu).\n",
6250 mesh_number, got[0], got[1], vertex_number, usage_strings[decl_ptr->Usage], exp[0], exp[1]);
6251 break;
6253 case D3DDECLTYPE_USHORT4N:
6255 USHORT *got = (USHORT*)(got_ptr + decl_ptr->Offset);
6256 USHORT *exp = (USHORT*)(exp_ptr + decl_ptr->Offset);
6257 BOOL same = got[0] == exp[0] && got[1] == exp[1]
6258 && got[2] == exp[2] && got[3] == exp[3];
6259 ok_(__FILE__,line)(same, "Mesh %d: Got (%hu, %hu, %hu, %hu) for vertex %d %s, expected (%hu, %hu, %hu, %hu).\n",
6260 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]);
6261 break;
6263 case D3DDECLTYPE_UDEC3:
6265 DWORD *got = (DWORD*)(got_ptr + decl_ptr->Offset);
6266 DWORD *exp = (DWORD*)(exp_ptr + decl_ptr->Offset);
6267 BOOL same = memcmp(got, exp, sizeof(*got)) == 0;
6268 struct udec3 got_udec3 = dword_to_udec3(*got);
6269 struct udec3 exp_udec3 = dword_to_udec3(*exp);
6270 ok_(__FILE__,line)(same, "Mesh %d: Got (%u, %u, %u, %u) for vertex %d %s, expected (%u, %u, %u, %u).\n",
6271 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);
6273 break;
6275 case D3DDECLTYPE_DEC3N:
6277 DWORD *got = (DWORD*)(got_ptr + decl_ptr->Offset);
6278 DWORD *exp = (DWORD*)(exp_ptr + decl_ptr->Offset);
6279 BOOL same = memcmp(got, exp, sizeof(*got)) == 0;
6280 struct dec3n got_dec3n = dword_to_dec3n(*got);
6281 struct dec3n exp_dec3n = dword_to_dec3n(*exp);
6282 ok_(__FILE__,line)(same, "Mesh %d: Got (%d, %d, %d, %d) for vertex %d %s, expected (%d, %d, %d, %d).\n",
6283 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);
6284 break;
6286 case D3DDECLTYPE_FLOAT16_2:
6288 WORD *got = (WORD*)(got_ptr + decl_ptr->Offset);
6289 WORD *exp = (WORD*)(exp_ptr + decl_ptr->Offset);
6290 BOOL same = got[0] == exp[0] && got[1] == exp[1];
6291 ok_(__FILE__,line)(same, "Mesh %d: Got (%hx, %hx) for vertex %d %s, expected (%hx, %hx).\n",
6292 mesh_number, got[0], got[1], vertex_number, usage_strings[decl_ptr->Usage], exp[0], exp[1]);
6293 break;
6295 case D3DDECLTYPE_FLOAT16_4:
6297 WORD *got = (WORD*)(got_ptr + decl_ptr->Offset);
6298 WORD *exp = (WORD*)(exp_ptr + decl_ptr->Offset);
6299 BOOL same = got[0] == exp[0] && got[1] == exp[1]
6300 && got[2] == exp[2] && got[3] == exp[3];
6301 ok_(__FILE__,line)(same, "Mesh %d: Got (%hx, %hx, %hx, %hx) for vertex %d %s, expected (%hx, %hx, %hx, %hx).\n",
6302 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]);
6303 break;
6305 default:
6306 break;
6311 static void test_weld_vertices(void)
6313 HRESULT hr;
6314 struct test_context *test_context = NULL;
6315 DWORD i;
6316 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
6317 const DWORD options_16bit = D3DXMESH_SYSTEMMEM;
6318 BYTE *vertices = NULL;
6319 DWORD *indices = NULL;
6320 WORD *indices_16bit = NULL;
6321 const UINT VERTS_PER_FACE = 3;
6322 const D3DXVECTOR3 up = {0.0f, 0.0f, 1.0f};
6323 struct vertex_normal
6325 D3DXVECTOR3 position;
6326 D3DXVECTOR3 normal;
6328 struct vertex_blendweight
6330 D3DXVECTOR3 position;
6331 FLOAT blendweight;
6333 struct vertex_texcoord
6335 D3DXVECTOR3 position;
6336 D3DXVECTOR2 texcoord;
6338 struct vertex_color
6340 D3DXVECTOR3 position;
6341 DWORD color;
6343 struct vertex_color_ubyte4
6345 D3DXVECTOR3 position;
6346 BYTE color[4];
6348 struct vertex_texcoord_short2
6350 D3DXVECTOR3 position;
6351 SHORT texcoord[2];
6353 struct vertex_texcoord_ushort2n
6355 D3DXVECTOR3 position;
6356 USHORT texcoord[2];
6358 struct vertex_normal_short4
6360 D3DXVECTOR3 position;
6361 SHORT normal[4];
6363 struct vertex_color_float4
6365 D3DXVECTOR3 position;
6366 D3DXVECTOR4 color;
6368 struct vertex_texcoord_float16_2
6370 D3DXVECTOR3 position;
6371 WORD texcoord[2];
6373 struct vertex_texcoord_float16_4
6375 D3DXVECTOR3 position;
6376 WORD texcoord[4];
6378 struct vertex_normal_udec3
6380 D3DXVECTOR3 position;
6381 DWORD normal;
6383 struct vertex_normal_dec3n
6385 D3DXVECTOR3 position;
6386 DWORD normal;
6388 UINT vertex_size_normal = sizeof(struct vertex_normal);
6389 UINT vertex_size_blendweight = sizeof(struct vertex_blendweight);
6390 UINT vertex_size_texcoord = sizeof(struct vertex_texcoord);
6391 UINT vertex_size_color = sizeof(struct vertex_color);
6392 UINT vertex_size_color_ubyte4 = sizeof(struct vertex_color_ubyte4);
6393 UINT vertex_size_texcoord_short2 = sizeof(struct vertex_texcoord_short2);
6394 UINT vertex_size_normal_short4 = sizeof(struct vertex_normal_short4);
6395 UINT vertex_size_color_float4 = sizeof(struct vertex_color_float4);
6396 UINT vertex_size_texcoord_float16_2 = sizeof(struct vertex_texcoord_float16_2);
6397 UINT vertex_size_texcoord_float16_4 = sizeof(struct vertex_texcoord_float16_4);
6398 UINT vertex_size_normal_udec3 = sizeof(struct vertex_normal_udec3);
6399 UINT vertex_size_normal_dec3n = sizeof(struct vertex_normal_dec3n);
6400 D3DVERTEXELEMENT9 declaration_normal[] =
6402 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6403 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6404 D3DDECL_END()
6406 D3DVERTEXELEMENT9 declaration_normal3[] =
6408 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 3},
6409 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6410 D3DDECL_END()
6412 D3DVERTEXELEMENT9 declaration_blendweight[] =
6414 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6415 {0, 12, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BLENDWEIGHT, 0},
6416 D3DDECL_END()
6418 D3DVERTEXELEMENT9 declaration_texcoord[] =
6420 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6421 {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6422 D3DDECL_END()
6424 D3DVERTEXELEMENT9 declaration_color[] =
6426 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6427 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
6428 D3DDECL_END()
6430 D3DVERTEXELEMENT9 declaration_color_ubyte4n[] =
6432 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6433 {0, 12, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
6434 D3DDECL_END()
6436 D3DVERTEXELEMENT9 declaration_color_ubyte4[] =
6438 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6439 {0, 12, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
6440 D3DDECL_END()
6442 D3DVERTEXELEMENT9 declaration_texcoord_short2[] =
6444 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6445 {0, 12, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6446 D3DDECL_END()
6448 D3DVERTEXELEMENT9 declaration_texcoord_short2n[] =
6450 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6451 {0, 12, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6452 D3DDECL_END()
6454 D3DVERTEXELEMENT9 declaration_texcoord_ushort2n[] =
6456 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6457 {0, 12, D3DDECLTYPE_USHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6458 D3DDECL_END()
6460 D3DVERTEXELEMENT9 declaration_normal_short4[] =
6462 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6463 {0, 12, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6464 D3DDECL_END()
6466 D3DVERTEXELEMENT9 declaration_normal_short4n[] =
6468 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6469 {0, 12, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6470 D3DDECL_END()
6472 D3DVERTEXELEMENT9 declaration_normal_ushort4n[] =
6474 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6475 {0, 12, D3DDECLTYPE_USHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6476 D3DDECL_END()
6478 D3DVERTEXELEMENT9 declaration_texcoord10[] =
6480 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6481 {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 10},
6482 D3DDECL_END()
6484 D3DVERTEXELEMENT9 declaration_color2[] =
6486 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6487 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 2},
6488 D3DDECL_END()
6490 D3DVERTEXELEMENT9 declaration_color2_float4[] =
6492 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6493 {0, 12, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 2},
6494 D3DDECL_END()
6496 D3DVERTEXELEMENT9 declaration_texcoord_float16_2[] =
6498 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6499 {0, 12, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6500 D3DDECL_END()
6502 D3DVERTEXELEMENT9 declaration_texcoord_float16_4[] =
6504 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6505 {0, 12, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6506 D3DDECL_END()
6508 D3DVERTEXELEMENT9 declaration_normal_udec3[] =
6510 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6511 {0, 12, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6512 D3DDECL_END()
6514 D3DVERTEXELEMENT9 declaration_normal_dec3n[] =
6516 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6517 {0, 12, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6518 D3DDECL_END()
6520 /* Test 0. One face and no welding.
6522 * 0--1
6523 * | /
6524 * |/
6527 const struct vertex vertices0[] =
6529 {{ 0.0f, 3.0f, 0.f}, up},
6530 {{ 2.0f, 3.0f, 0.f}, up},
6531 {{ 0.0f, 0.0f, 0.f}, up},
6533 const DWORD indices0[] = {0, 1, 2};
6534 const DWORD attributes0[] = {0};
6535 const DWORD exp_indices0[] = {0, 1, 2};
6536 const UINT num_vertices0 = ARRAY_SIZE(vertices0);
6537 const UINT num_faces0 = ARRAY_SIZE(indices0) / VERTS_PER_FACE;
6538 const DWORD flags0 = D3DXWELDEPSILONS_WELDALL;
6539 /* epsilons0 is NULL */
6540 const DWORD adjacency0[] = {-1, -1, -1};
6541 const struct vertex exp_vertices0[] =
6543 {{ 0.0f, 3.0f, 0.f}, up},
6544 {{ 2.0f, 3.0f, 0.f}, up},
6545 {{ 0.0f, 0.0f, 0.f}, up},
6547 const DWORD exp_face_remap0[] = {0};
6548 const DWORD exp_vertex_remap0[] = {0, 1, 2};
6549 const DWORD exp_new_num_vertices0 = ARRAY_SIZE(exp_vertices0);
6550 /* Test 1. Two vertices should be removed without regard to epsilon.
6552 * 0--1 3
6553 * | / /|
6554 * |/ / |
6555 * 2 5--4
6557 const struct vertex_normal vertices1[] =
6559 {{ 0.0f, 3.0f, 0.f}, up},
6560 {{ 2.0f, 3.0f, 0.f}, up},
6561 {{ 0.0f, 0.0f, 0.f}, up},
6563 {{ 3.0f, 3.0f, 0.f}, up},
6564 {{ 3.0f, 0.0f, 0.f}, up},
6565 {{ 1.0f, 0.0f, 0.f}, up},
6567 const DWORD indices1[] = {0, 1, 2, 3, 4, 5};
6568 const DWORD attributes1[] = {0, 0};
6569 const UINT num_vertices1 = ARRAY_SIZE(vertices1);
6570 const UINT num_faces1 = ARRAY_SIZE(indices1) / VERTS_PER_FACE;
6571 const DWORD flags1 = D3DXWELDEPSILONS_WELDALL;
6572 /* epsilons1 is NULL */
6573 const DWORD adjacency1[] = {-1, 1, -1, -1, -1, 0};
6574 const struct vertex_normal exp_vertices1[] =
6576 {{ 0.0f, 3.0f, 0.f}, up},
6577 {{ 2.0f, 3.0f, 0.f}, up},
6578 {{ 0.0f, 0.0f, 0.f}, up},
6580 {{ 3.0f, 0.0f, 0.f}, up}
6582 const DWORD exp_indices1[] = {0, 1, 2, 1, 3, 2};
6583 const DWORD exp_face_remap1[] = {0, 1};
6584 const DWORD exp_vertex_remap1[] = {0, 1, 2, 4, -1, -1};
6585 const DWORD exp_new_num_vertices1 = ARRAY_SIZE(exp_vertices1);
6586 /* Test 2. Two faces. No vertices should be removed because of normal
6587 * epsilon, but the positions should be replaced. */
6588 const struct vertex_normal vertices2[] =
6590 {{ 0.0f, 3.0f, 0.f}, up},
6591 {{ 2.0f, 3.0f, 0.f}, up},
6592 {{ 0.0f, 0.0f, 0.f}, up},
6594 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
6595 {{ 3.0f, 0.0f, 0.f}, up},
6596 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6598 const DWORD indices2[] = {0, 1, 2, 3, 4, 5};
6599 const DWORD attributes2[] = {0, 0};
6600 const UINT num_vertices2 = ARRAY_SIZE(vertices2);
6601 const UINT num_faces2 = ARRAY_SIZE(indices2) / VERTS_PER_FACE;
6602 DWORD flags2 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
6603 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};
6604 const DWORD adjacency2[] = {-1, 1, -1, -1, -1, 0};
6605 const struct vertex_normal exp_vertices2[] =
6607 {{ 0.0f, 3.0f, 0.f}, up},
6608 {{ 2.0f, 3.0f, 0.f}, up},
6609 {{ 0.0f, 0.0f, 0.f}, up},
6611 {{ 2.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
6612 {{ 3.0f, 0.0f, 0.f}, up},
6613 {{ 0.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6615 const DWORD exp_indices2[] = {0, 1, 2, 3, 4, 5};
6616 const DWORD exp_face_remap2[] = {0, 1};
6617 const DWORD exp_vertex_remap2[] = {0, 1, 2, 3, 4, 5};
6618 const DWORD exp_new_num_vertices2 = ARRAY_SIZE(exp_vertices2);
6619 /* Test 3. Two faces. One vertex should be removed because of normal epsilon. */
6620 const struct vertex_normal vertices3[] =
6622 {{ 0.0f, 3.0f, 0.f}, up},
6623 {{ 2.0f, 3.0f, 0.f}, up},
6624 {{ 0.0f, 0.0f, 0.f}, up},
6626 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
6627 {{ 3.0f, 0.0f, 0.f}, up},
6628 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6630 const DWORD indices3[] = {0, 1, 2, 3, 4, 5};
6631 const DWORD attributes3[] = {0, 0};
6632 const UINT num_vertices3 = ARRAY_SIZE(vertices3);
6633 const UINT num_faces3 = ARRAY_SIZE(indices3) / VERTS_PER_FACE;
6634 DWORD flags3 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
6635 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};
6636 const DWORD adjacency3[] = {-1, 1, -1, -1, -1, 0};
6637 const struct vertex_normal exp_vertices3[] =
6639 {{ 0.0f, 3.0f, 0.f}, up},
6640 {{ 2.0f, 3.0f, 0.f}, up},
6641 {{ 0.0f, 0.0f, 0.f}, up},
6643 {{ 3.0f, 0.0f, 0.f}, up},
6644 {{ 0.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6646 const DWORD exp_indices3[] = {0, 1, 2, 1, 3, 4};
6647 const DWORD exp_face_remap3[] = {0, 1};
6648 const DWORD exp_vertex_remap3[] = {0, 1, 2, 4, 5, -1};
6649 const DWORD exp_new_num_vertices3 = ARRAY_SIZE(exp_vertices3);
6650 /* Test 4 Two faces. Two vertices should be removed. */
6651 const struct vertex_normal vertices4[] =
6653 {{ 0.0f, 3.0f, 0.f}, up},
6654 {{ 2.0f, 3.0f, 0.f}, up},
6655 {{ 0.0f, 0.0f, 0.f}, up},
6657 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
6658 {{ 3.0f, 0.0f, 0.f}, up},
6659 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6661 const DWORD indices4[] = {0, 1, 2, 3, 4, 5};
6662 const DWORD attributes4[] = {0, 0};
6663 const UINT num_vertices4 = ARRAY_SIZE(vertices4);
6664 const UINT num_faces4 = ARRAY_SIZE(indices4) / VERTS_PER_FACE;
6665 DWORD flags4 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
6666 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};
6667 const DWORD adjacency4[] = {-1, 1, -1, -1, -1, 0};
6668 const struct vertex_normal exp_vertices4[] =
6670 {{ 0.0f, 3.0f, 0.f}, up},
6671 {{ 2.0f, 3.0f, 0.f}, up},
6672 {{ 0.0f, 0.0f, 0.f}, up},
6674 {{ 3.0f, 0.0f, 0.f}, up},
6676 const DWORD exp_indices4[] = {0, 1, 2, 1, 3, 2};
6677 const DWORD exp_face_remap4[] = {0, 1};
6678 const DWORD exp_vertex_remap4[] = {0, 1, 2, 4, -1, -1};
6679 const DWORD exp_new_num_vertices4 = ARRAY_SIZE(exp_vertices4);
6680 /* Test 5. Odd face ordering.
6682 * 0--1 6 3
6683 * | / /| |\
6684 * |/ / | | \
6685 * 2 8--7 5--4
6687 const struct vertex_normal vertices5[] =
6689 {{ 0.0f, 3.0f, 0.f}, up},
6690 {{ 2.0f, 3.0f, 0.f}, up},
6691 {{ 0.0f, 0.0f, 0.f}, up},
6693 {{ 3.0f, 3.0f, 0.f}, up},
6694 {{ 3.0f, 0.0f, 0.f}, up},
6695 {{ 1.0f, 0.0f, 0.f}, up},
6697 {{ 4.0f, 3.0f, 0.f}, up},
6698 {{ 6.0f, 0.0f, 0.f}, up},
6699 {{ 4.0f, 0.0f, 0.f}, up},
6701 const DWORD indices5[] = {0, 1, 2, 6, 7, 8, 3, 4, 5};
6702 const DWORD exp_indices5[] = {0, 1, 2, 1, 4, 2, 1, 3, 4};
6703 const DWORD attributes5[] = {0, 0, 0};
6704 const UINT num_vertices5 = ARRAY_SIZE(vertices5);
6705 const UINT num_faces5 = ARRAY_SIZE(indices5) / VERTS_PER_FACE;
6706 DWORD flags5 = D3DXWELDEPSILONS_WELDALL;
6707 const DWORD adjacency5[] = {-1, 1, -1, 2, -1, 0, -1, -1, 1};
6708 const struct vertex_normal exp_vertices5[] =
6710 {{ 0.0f, 3.0f, 0.f}, up},
6711 {{ 2.0f, 3.0f, 0.f}, up},
6712 {{ 0.0f, 0.0f, 0.f}, up},
6714 {{ 3.0f, 0.0f, 0.f}, up},
6715 {{ 1.0f, 0.0f, 0.f}, up},
6717 const DWORD exp_face_remap5[] = {0, 1, 2};
6718 const DWORD exp_vertex_remap5[] = {0, 1, 2, 4, 5, -1, -1, -1, -1};
6719 const DWORD exp_new_num_vertices5 = ARRAY_SIZE(exp_vertices5);
6720 /* Test 6. Two faces. Do not remove flag is used, so no vertices should be
6721 * removed. */
6722 const struct vertex_normal vertices6[] =
6724 {{ 0.0f, 3.0f, 0.f}, up},
6725 {{ 2.0f, 3.0f, 0.f}, up},
6726 {{ 0.0f, 0.0f, 0.f}, up},
6728 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
6729 {{ 3.0f, 0.0f, 0.f}, up},
6730 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6732 const DWORD indices6[] = {0, 1, 2, 3, 4, 5};
6733 const DWORD attributes6[] = {0, 0};
6734 const UINT num_vertices6 = ARRAY_SIZE(vertices6);
6735 const UINT num_faces6 = ARRAY_SIZE(indices6) / VERTS_PER_FACE;
6736 DWORD flags6 = D3DXWELDEPSILONS_WELDPARTIALMATCHES | D3DXWELDEPSILONS_DONOTREMOVEVERTICES;
6737 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};
6738 const DWORD adjacency6[] = {-1, 1, -1, -1, -1, 0};
6739 const struct vertex_normal exp_vertices6[] =
6741 {{ 0.0f, 3.0f, 0.f}, up},
6742 {{ 2.0f, 3.0f, 0.f}, up},
6743 {{ 0.0f, 0.0f, 0.f}, up},
6745 {{ 2.0f, 3.0f, 0.f}, up},
6746 {{ 3.0f, 0.0f, 0.f}, up},
6747 {{ 0.0f, 0.0f, 0.f}, up},
6750 const DWORD exp_indices6[] = {0, 1, 2, 3, 4, 5};
6751 const DWORD exp_face_remap6[] = {0, 1};
6752 const DWORD exp_vertex_remap6[] = {0, 1, 2, 3, 4, 5};
6753 const DWORD exp_new_num_vertices6 = ARRAY_SIZE(exp_vertices6);
6754 /* Test 7. Same as test 6 but with 16 bit indices. */
6755 const WORD indices6_16bit[] = {0, 1, 2, 3, 4, 5};
6756 /* Test 8. No flags. Same result as D3DXWELDEPSILONS_WELDPARTIALMATCHES. */
6757 const struct vertex_normal vertices8[] =
6759 {{ 0.0f, 3.0f, 0.f}, up},
6760 {{ 2.0f, 3.0f, 0.f}, up},
6761 {{ 0.0f, 0.0f, 0.f}, up},
6763 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
6764 {{ 3.0f, 0.0f, 0.f}, up},
6765 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6767 const DWORD indices8[] = {0, 1, 2, 1, 3, 4};
6768 const DWORD attributes8[] = {0, 0};
6769 const UINT num_vertices8 = ARRAY_SIZE(vertices8);
6770 const UINT num_faces8 = ARRAY_SIZE(indices8) / VERTS_PER_FACE;
6771 DWORD flags8 = 0;
6772 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};
6773 const DWORD adjacency8[] = {-1, 1, -1, -1, -1, 0};
6774 const struct vertex_normal exp_vertices8[] =
6776 {{ 0.0f, 3.0f, 0.f}, up},
6777 {{ 2.0f, 3.0f, 0.f}, up},
6778 {{ 0.0f, 0.0f, 0.f}, up},
6780 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
6781 {{ 3.0f, 0.0f, 0.f}, up},
6783 const DWORD exp_indices8[] = {0, 1, 2, 1, 3, 4};
6784 const DWORD exp_face_remap8[] = {0, 1};
6785 const DWORD exp_vertex_remap8[] = {0, 1, 2, 3, 4, -1};
6786 const DWORD exp_new_num_vertices8 = ARRAY_SIZE(exp_vertices8);
6787 /* Test 9. Vertices are removed even though they belong to separate
6788 * attribute groups if D3DXWELDEPSILONS_DONOTSPLIT is set. */
6789 const struct vertex_normal vertices9[] =
6791 {{ 0.0f, 3.0f, 0.f}, up},
6792 {{ 2.0f, 3.0f, 0.f}, up},
6793 {{ 0.0f, 0.0f, 0.f}, up},
6795 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
6796 {{ 3.0f, 0.0f, 0.f}, up},
6797 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6799 const DWORD indices9[] = {0, 1, 2, 3, 4, 5};
6800 const DWORD attributes9[] = {0, 1};
6801 const UINT num_vertices9 = ARRAY_SIZE(vertices9);
6802 const UINT num_faces9 = ARRAY_SIZE(indices9) / VERTS_PER_FACE;
6803 DWORD flags9 = D3DXWELDEPSILONS_WELDPARTIALMATCHES | D3DXWELDEPSILONS_DONOTSPLIT;
6804 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};
6805 const DWORD adjacency9[] = {-1, 1, -1, -1, -1, 0};
6806 const struct vertex_normal exp_vertices9[] =
6808 {{ 0.0f, 3.0f, 0.f}, up},
6809 {{ 2.0f, 3.0f, 0.f}, up},
6810 {{ 0.0f, 0.0f, 0.f}, up},
6812 {{ 3.0f, 0.0f, 0.f}, up},
6814 const DWORD exp_indices9[] = {0, 1, 2, 1, 3, 2};
6815 const DWORD exp_face_remap9[] = {0, 1};
6816 const DWORD exp_vertex_remap9[] = {0, 1, 2, 4, -1, -1};
6817 const DWORD exp_new_num_vertices9 = ARRAY_SIZE(exp_vertices9);
6818 /* Test 10. Weld blendweight (FLOAT1). */
6819 const struct vertex_blendweight vertices10[] =
6821 {{ 0.0f, 3.0f, 0.f}, 1.0f},
6822 {{ 2.0f, 3.0f, 0.f}, 1.0f},
6823 {{ 0.0f, 0.0f, 0.f}, 1.0f},
6825 {{ 3.0f, 3.0f, 0.f}, 0.9},
6826 {{ 3.0f, 0.0f, 0.f}, 1.0},
6827 {{ 1.0f, 0.0f, 0.f}, 0.4},
6829 const DWORD indices10[] = {0, 1, 2, 3, 4, 5};
6830 const DWORD attributes10[] = {0, 0};
6831 const UINT num_vertices10 = ARRAY_SIZE(vertices10);
6832 const UINT num_faces10 = ARRAY_SIZE(indices10) / VERTS_PER_FACE;
6833 DWORD flags10 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
6834 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};
6835 const DWORD adjacency10[] = {-1, 1, -1, -1, -1, 0};
6836 const struct vertex_blendweight exp_vertices10[] =
6838 {{ 0.0f, 3.0f, 0.f}, 1.0f},
6839 {{ 2.0f, 3.0f, 0.f}, 1.0f},
6840 {{ 0.0f, 0.0f, 0.f}, 1.0f},
6842 {{ 3.0f, 0.0f, 0.f}, 1.0},
6843 {{ 0.0f, 0.0f, 0.f}, 0.4},
6845 const DWORD exp_indices10[] = {0, 1, 2, 1, 3, 4};
6846 const DWORD exp_face_remap10[] = {0, 1};
6847 const DWORD exp_vertex_remap10[] = {0, 1, 2, 4, 5, -1};
6848 const DWORD exp_new_num_vertices10 = ARRAY_SIZE(exp_vertices10);
6849 /* Test 11. Weld texture coordinates. */
6850 const struct vertex_texcoord vertices11[] =
6852 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f}},
6853 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.7f}},
6854 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
6856 {{ 3.0f, 3.0f, 0.f}, {0.2f, 0.3f}},
6857 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f}},
6858 {{ 1.0f, 0.0f, 0.f}, {0.1f, 0.2f}}
6860 const DWORD indices11[] = {0, 1, 2, 3, 4, 5};
6861 const DWORD attributes11[] = {0, 0};
6862 const UINT num_vertices11 = ARRAY_SIZE(vertices11);
6863 const UINT num_faces11 = ARRAY_SIZE(indices11) / VERTS_PER_FACE;
6864 DWORD flags11 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
6865 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};
6866 const DWORD adjacency11[] = {-1, 1, -1, -1, -1, 0};
6867 const struct vertex_texcoord exp_vertices11[] =
6869 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f}},
6870 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.7f}},
6871 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
6873 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f}},
6874 {{ 0.0f, 0.0f, 0.f}, {0.1f, 0.2f}},
6876 const DWORD exp_indices11[] = {0, 1, 2, 1, 3, 4};
6877 const DWORD exp_face_remap11[] = {0, 1};
6878 const DWORD exp_vertex_remap11[] = {0, 1, 2, 4, 5, -1};
6879 const DWORD exp_new_num_vertices11 = ARRAY_SIZE(exp_vertices11);
6880 /* Test 12. Weld with color. */
6881 const struct vertex_color vertices12[] =
6883 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
6884 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
6885 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
6887 {{ 3.0f, 3.0f, 0.f}, 0x00000000},
6888 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
6889 {{ 1.0f, 0.0f, 0.f}, 0x88888888},
6891 const DWORD indices12[] = {0, 1, 2, 3, 4, 5};
6892 const DWORD attributes12[] = {0, 0};
6893 const UINT num_vertices12 = ARRAY_SIZE(vertices12);
6894 const UINT num_faces12 = ARRAY_SIZE(indices12) / VERTS_PER_FACE;
6895 DWORD flags12 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
6896 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};
6897 const DWORD adjacency12[] = {-1, 1, -1, -1, -1, 0};
6898 const struct vertex_color exp_vertices12[] =
6900 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
6901 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
6902 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
6904 {{ 2.0f, 3.0f, 0.f}, 0x00000000},
6905 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
6907 const DWORD exp_indices12[] = {0, 1, 2, 3, 4, 2};
6908 const DWORD exp_face_remap12[] = {0, 1};
6909 const DWORD exp_vertex_remap12[] = {0, 1, 2, 3, 4, -1};
6910 const DWORD exp_new_num_vertices12 = ARRAY_SIZE(exp_vertices12);
6911 /* Test 13. Two faces. One vertex should be removed because of normal epsilon.
6912 * This is similar to test 3, but the declaration has been changed to NORMAL3.
6914 const struct vertex_normal vertices13[] =
6916 {{ 0.0f, 3.0f, 0.f}, up},
6917 {{ 2.0f, 3.0f, 0.f}, up},
6918 {{ 0.0f, 0.0f, 0.f}, up},
6920 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
6921 {{ 3.0f, 0.0f, 0.f}, up},
6922 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6924 const DWORD indices13[] = {0, 1, 2, 3, 4, 5};
6925 const DWORD attributes13[] = {0, 0};
6926 const UINT num_vertices13 = ARRAY_SIZE(vertices3);
6927 const UINT num_faces13 = ARRAY_SIZE(indices3) / VERTS_PER_FACE;
6928 DWORD flags13 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
6929 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};
6930 const DWORD adjacency13[] = {-1, 1, -1, -1, -1, 0};
6931 const struct vertex_normal exp_vertices13[] =
6933 {{ 0.0f, 3.0f, 0.f}, up},
6934 {{ 2.0f, 3.0f, 0.f}, up},
6935 {{ 0.0f, 0.0f, 0.f}, up},
6937 {{ 3.0f, 0.0f, 0.f}, up},
6938 {{ 0.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6940 const DWORD exp_indices13[] = {0, 1, 2, 1, 3, 4};
6941 const DWORD exp_face_remap13[] = {0, 1};
6942 const DWORD exp_vertex_remap13[] = {0, 1, 2, 4, 5, -1};
6943 const DWORD exp_new_num_vertices13 = ARRAY_SIZE(exp_vertices13);
6944 /* Test 14. Another test for welding with color. */
6945 const struct vertex_color vertices14[] =
6947 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
6948 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
6949 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
6951 {{ 3.0f, 3.0f, 0.f}, 0x00000000},
6952 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
6953 {{ 1.0f, 0.0f, 0.f}, 0x01010101},
6955 const DWORD indices14[] = {0, 1, 2, 3, 4, 5};
6956 const DWORD attributes14[] = {0, 0};
6957 const UINT num_vertices14 = ARRAY_SIZE(vertices14);
6958 const UINT num_faces14 = ARRAY_SIZE(indices14) / VERTS_PER_FACE;
6959 DWORD flags14 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
6960 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};
6961 const DWORD adjacency14[] = {-1, 1, -1, -1, -1, 0};
6962 const struct vertex_color exp_vertices14[] =
6964 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
6965 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
6966 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
6968 {{ 2.0f, 3.0f, 0.f}, 0x00000000},
6969 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
6971 const DWORD exp_indices14[] = {0, 1, 2, 3, 4, 2};
6972 const DWORD exp_face_remap14[] = {0, 1};
6973 const DWORD exp_vertex_remap14[] = {0, 1, 2, 3, 4, -1};
6974 const DWORD exp_new_num_vertices14 = ARRAY_SIZE(exp_vertices14);
6975 /* Test 15. Weld with color, but as UBYTE4N instead of D3DCOLOR. It shows
6976 * that UBYTE4N and D3DCOLOR are compared the same way.
6978 const struct vertex_color_ubyte4 vertices15[] =
6980 {{ 0.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
6981 {{ 2.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
6982 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
6984 {{ 3.0f, 3.0f, 0.f}, { 0, 0, 0, 0}},
6985 {{ 3.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
6986 {{ 1.0f, 0.0f, 0.f}, { 1, 1, 1, 1}},
6988 const DWORD indices15[] = {0, 1, 2, 3, 4, 5};
6989 const DWORD attributes15[] = {0, 0};
6990 const UINT num_vertices15 = ARRAY_SIZE(vertices15);
6991 const UINT num_faces15 = ARRAY_SIZE(indices15) / VERTS_PER_FACE;
6992 DWORD flags15 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
6993 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};
6994 const DWORD adjacency15[] = {-1, 1, -1, -1, -1, 0};
6995 const struct vertex_color_ubyte4 exp_vertices15[] =
6997 {{ 0.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
6998 {{ 2.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
6999 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7001 {{ 2.0f, 3.0f, 0.f}, { 0, 0, 0, 0}},
7002 {{ 3.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7004 const DWORD exp_indices15[] = {0, 1, 2, 3, 4, 2};
7005 const DWORD exp_face_remap15[] = {0, 1};
7006 const DWORD exp_vertex_remap15[] = {0, 1, 2, 3, 4, -1};
7007 const DWORD exp_new_num_vertices15 = ARRAY_SIZE(exp_vertices15);
7008 /* Test 16. Weld with color, but as UBYTE4 instead of D3DCOLOR. It shows
7009 * that UBYTE4 is not normalized and that epsilon is truncated and compared
7010 * directly to each of the four bytes.
7012 const struct vertex_color_ubyte4 vertices16[] =
7014 {{ 0.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7015 {{ 2.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7016 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7018 {{ 3.0f, 3.0f, 0.f}, { 0, 0, 0, 0}},
7019 {{ 3.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7020 {{ 1.0f, 0.0f, 0.f}, { 1, 1, 1, 1}},
7022 const DWORD indices16[] = {0, 1, 2, 3, 4, 5};
7023 const DWORD attributes16[] = {0, 0};
7024 const UINT num_vertices16 = ARRAY_SIZE(vertices16);
7025 const UINT num_faces16 = ARRAY_SIZE(indices16) / VERTS_PER_FACE;
7026 DWORD flags16 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7027 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};
7028 const DWORD adjacency16[] = {-1, 1, -1, -1, -1, 0};
7029 const struct vertex_color_ubyte4 exp_vertices16[] =
7031 {{ 0.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7032 {{ 2.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7033 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7035 {{ 2.0f, 3.0f, 0.f}, { 0, 0, 0, 0}},
7036 {{ 3.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7038 const DWORD exp_indices16[] = {0, 1, 2, 3, 4, 2};
7039 const DWORD exp_face_remap16[] = {0, 1};
7040 const DWORD exp_vertex_remap16[] = {0, 1, 2, 3, 4, -1};
7041 const DWORD exp_new_num_vertices16 = ARRAY_SIZE(exp_vertices16);
7042 /* Test 17. Weld texture coordinates but as SHORT2 instead of D3DXVECTOR2.*/
7043 const struct vertex_texcoord_short2 vertices17[] =
7045 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7046 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7047 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7049 {{ 3.0f, 3.0f, 0.f}, {32767, 32767}},
7050 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7051 {{ 1.0f, 0.0f, 0.f}, {32766, 32766}},
7053 const DWORD indices17[] = {0, 1, 2, 3, 4, 5};
7054 const DWORD attributes17[] = {0, 0};
7055 const UINT num_vertices17 = ARRAY_SIZE(vertices17);
7056 const UINT num_faces17 = ARRAY_SIZE(indices17) / VERTS_PER_FACE;
7057 DWORD flags17 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7058 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};
7059 const DWORD adjacency17[] = {-1, 1, -1, -1, -1, 0};
7060 const struct vertex_texcoord_short2 exp_vertices17[] =
7062 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7063 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7064 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7066 {{ 2.0f, 3.0f, 0.f}, {32767, 32767}},
7067 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7069 const DWORD exp_indices17[] = {0, 1, 2, 3, 4, 2};
7070 const DWORD exp_face_remap17[] = {0, 1};
7071 const DWORD exp_vertex_remap17[] = {0, 1, 2, 3, 4, -1};
7072 const DWORD exp_new_num_vertices17 = ARRAY_SIZE(exp_vertices17);
7073 /* Test 18. Weld texture coordinates but as SHORT2N instead of D3DXVECTOR2. */
7074 const struct vertex_texcoord_short2 vertices18[] =
7076 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7077 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7078 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7080 {{ 3.0f, 3.0f, 0.f}, {32767, 32767}},
7081 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7082 {{ 1.0f, 0.0f, 0.f}, {32766, 32766}},
7084 const DWORD indices18[] = {0, 1, 2, 3, 4, 5};
7085 const DWORD attributes18[] = {0, 0};
7086 const UINT num_vertices18 = ARRAY_SIZE(vertices18);
7087 const UINT num_faces18 = ARRAY_SIZE(indices18) / VERTS_PER_FACE;
7088 DWORD flags18 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7089 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};
7090 const DWORD adjacency18[] = {-1, 1, -1, -1, -1, 0};
7091 const struct vertex_texcoord_short2 exp_vertices18[] =
7093 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7094 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7095 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7097 {{ 2.0f, 3.0f, 0.f}, {32767, 32767}},
7098 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7100 const DWORD exp_indices18[] = {0, 1, 2, 3, 4, 2};
7101 const DWORD exp_face_remap18[] = {0, 1};
7102 const DWORD exp_vertex_remap18[] = {0, 1, 2, 3, 4, -1};
7103 const DWORD exp_new_num_vertices18 = ARRAY_SIZE(exp_vertices18);
7104 /* Test 19. Weld texture coordinates but as USHORT2N instead of D3DXVECTOR2. */
7105 const struct vertex_texcoord_ushort2n vertices19[] =
7107 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7108 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7109 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7111 {{ 3.0f, 3.0f, 0.f}, {65535, 65535}},
7112 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7113 {{ 1.0f, 0.0f, 0.f}, {65534, 65534}},
7115 const DWORD indices19[] = {0, 1, 2, 3, 4, 5};
7116 const DWORD attributes19[] = {0, 0};
7117 const UINT num_vertices19 = ARRAY_SIZE(vertices19);
7118 const UINT num_faces19 = ARRAY_SIZE(indices19) / VERTS_PER_FACE;
7119 DWORD flags19 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7120 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};
7121 const DWORD adjacency19[] = {-1, 1, -1, -1, -1, 0};
7122 const struct vertex_texcoord_ushort2n exp_vertices19[] =
7124 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7125 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7126 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7128 {{ 2.0f, 3.0f, 0.f}, {65535, 65535}},
7129 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7131 const DWORD exp_indices19[] = {0, 1, 2, 3, 4, 2};
7132 const DWORD exp_face_remap19[] = {0, 1};
7133 const DWORD exp_vertex_remap19[] = {0, 1, 2, 3, 4, -1};
7134 const DWORD exp_new_num_vertices19 = ARRAY_SIZE(exp_vertices19);
7135 /* Test 20. Weld normal as SHORT4 instead of D3DXVECTOR3. */
7136 const struct vertex_normal_short4 vertices20[] =
7138 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7139 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7140 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7142 {{ 3.0f, 3.0f, 0.f}, {32767, 32767, 32767, 32767}},
7143 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7144 {{ 1.0f, 0.0f, 0.f}, {32766, 32766, 32766, 32766}},
7146 const DWORD indices20[] = {0, 1, 2, 3, 4, 5};
7147 const DWORD attributes20[] = {0, 0};
7148 const UINT num_vertices20 = ARRAY_SIZE(vertices20);
7149 const UINT num_faces20 = ARRAY_SIZE(indices20) / VERTS_PER_FACE;
7150 DWORD flags20 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7151 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};
7152 const DWORD adjacency20[] = {-1, 1, -1, -1, -1, 0};
7153 const struct vertex_normal_short4 exp_vertices20[] =
7155 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7156 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7157 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7159 {{ 2.0f, 3.0f, 0.f}, {32767, 32767, 32767, 32767}},
7160 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7162 const DWORD exp_indices20[] = {0, 1, 2, 3, 4, 2};
7163 const DWORD exp_face_remap20[] = {0, 1};
7164 const DWORD exp_vertex_remap20[] = {0, 1, 2, 3, 4, -1};
7165 const DWORD exp_new_num_vertices20 = ARRAY_SIZE(exp_vertices20);
7166 /* Test 21. Weld normal as SHORT4N instead of D3DXVECTOR3. */
7167 const struct vertex_normal_short4 vertices21[] =
7169 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7170 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7171 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7173 {{ 3.0f, 3.0f, 0.f}, {32767, 32767, 32767, 32767}},
7174 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7175 {{ 1.0f, 0.0f, 0.f}, {32766, 32766, 32766, 32766}},
7177 const DWORD indices21[] = {0, 1, 2, 3, 4, 5};
7178 const DWORD attributes21[] = {0, 0};
7179 const UINT num_vertices21 = ARRAY_SIZE(vertices21);
7180 const UINT num_faces21 = ARRAY_SIZE(indices21) / VERTS_PER_FACE;
7181 DWORD flags21 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7182 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};
7183 const DWORD adjacency21[] = {-1, 1, -1, -1, -1, 0};
7184 const struct vertex_normal_short4 exp_vertices21[] =
7186 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7187 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7188 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7190 {{ 2.0f, 3.0f, 0.f}, {32767, 32767, 32767, 32767}},
7191 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7193 const DWORD exp_indices21[] = {0, 1, 2, 3, 4, 2};
7194 const DWORD exp_face_remap21[] = {0, 1};
7195 const DWORD exp_vertex_remap21[] = {0, 1, 2, 3, 4, -1};
7196 const DWORD exp_new_num_vertices21 = ARRAY_SIZE(exp_vertices21);
7197 /* Test 22. Weld normal as USHORT4N instead of D3DXVECTOR3. */
7198 const struct vertex_normal_short4 vertices22[] =
7200 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7201 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7202 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7204 {{ 3.0f, 3.0f, 0.f}, {65535, 65535, 65535, 65535}},
7205 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7206 {{ 1.0f, 0.0f, 0.f}, {65534, 65534, 65534, 65534}},
7208 const DWORD indices22[] = {0, 1, 2, 3, 4, 5};
7209 const DWORD attributes22[] = {0, 0};
7210 const UINT num_vertices22 = ARRAY_SIZE(vertices22);
7211 const UINT num_faces22 = ARRAY_SIZE(indices22) / VERTS_PER_FACE;
7212 DWORD flags22 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7213 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};
7214 const DWORD adjacency22[] = {-1, 1, -1, -1, -1, 0};
7215 const struct vertex_normal_short4 exp_vertices22[] =
7217 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7218 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7219 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7221 {{ 2.0f, 3.0f, 0.f}, {65535, 65535, 65535, 65535}},
7222 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7224 const DWORD exp_indices22[] = {0, 1, 2, 3, 4, 2};
7225 const DWORD exp_face_remap22[] = {0, 1};
7226 const DWORD exp_vertex_remap22[] = {0, 1, 2, 3, 4, -1};
7227 const DWORD exp_new_num_vertices22 = ARRAY_SIZE(exp_vertices22);
7228 /* Test 23. Weld texture coordinates as FLOAT16_2. Similar to test 11, but
7229 * with texture coordinates converted to float16 in hex. */
7230 const struct vertex_texcoord_float16_2 vertices23[] =
7232 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
7233 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */
7234 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */
7236 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd}}, /* {0.2f, 0.3f} */
7237 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
7238 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */
7240 const DWORD indices23[] = {0, 1, 2, 3, 4, 5};
7241 const DWORD attributes23[] = {0, 0};
7242 const UINT num_vertices23 = ARRAY_SIZE(vertices23);
7243 const UINT num_faces23 = ARRAY_SIZE(indices23) / VERTS_PER_FACE;
7244 DWORD flags23 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7245 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};
7246 const DWORD adjacency23[] = {-1, 1, -1, -1, -1, 0};
7247 const struct vertex_texcoord_float16_2 exp_vertices23[] =
7249 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
7250 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */
7251 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */
7253 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
7254 {{ 0.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */
7256 const DWORD exp_indices23[] = {0, 1, 2, 1, 3, 4};
7257 const DWORD exp_face_remap23[] = {0, 1};
7258 const DWORD exp_vertex_remap23[] = {0, 1, 2, 4, 5, -1};
7259 const DWORD exp_new_num_vertices23 = ARRAY_SIZE(exp_vertices23);
7260 /* Test 24. Weld texture coordinates as FLOAT16_4. Similar to test 24. */
7261 const struct vertex_texcoord_float16_4 vertices24[] =
7263 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}},
7264 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a, 0x3800, 0x399a}},
7265 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd, 0xb266, 0xb4cd}},
7267 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd, 0x3266, 0x34cd}},
7268 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}},
7269 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266, 0x2e66, 0x3266}},
7271 const DWORD indices24[] = {0, 1, 2, 3, 4, 5};
7272 const DWORD attributes24[] = {0, 0};
7273 const UINT num_vertices24 = ARRAY_SIZE(vertices24);
7274 const UINT num_faces24 = ARRAY_SIZE(indices24) / VERTS_PER_FACE;
7275 DWORD flags24 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7276 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};
7277 const DWORD adjacency24[] = {-1, 1, -1, -1, -1, 0};
7278 const struct vertex_texcoord_float16_4 exp_vertices24[] =
7280 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}},
7281 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a, 0x3800, 0x399a}},
7282 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd, 0xb266, 0xb4cd}},
7284 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}},
7285 {{ 0.0f, 0.0f, 0.f}, {0x2e66, 0x3266, 0x2e66, 0x3266}},
7287 const DWORD exp_indices24[] = {0, 1, 2, 1, 3, 4};
7288 const DWORD exp_face_remap24[] = {0, 1};
7289 const DWORD exp_vertex_remap24[] = {0, 1, 2, 4, 5, -1};
7290 const DWORD exp_new_num_vertices24 = ARRAY_SIZE(exp_vertices24);
7291 /* Test 25. Weld texture coordinates with usage index 10 (TEXCOORD10). The
7292 * usage index is capped at 7, so the epsilon for TEXCOORD7 is used instead.
7294 const struct vertex_texcoord vertices25[] =
7296 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f}},
7297 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.7f}},
7298 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
7300 {{ 3.0f, 3.0f, 0.f}, {0.2f, 0.3f}},
7301 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f}},
7302 {{ 1.0f, 0.0f, 0.f}, {0.1f, 0.2f}}
7304 const DWORD indices25[] = {0, 1, 2, 3, 4, 5};
7305 const DWORD attributes25[] = {0, 0};
7306 const UINT num_vertices25 = ARRAY_SIZE(vertices25);
7307 const UINT num_faces25 = ARRAY_SIZE(indices25) / VERTS_PER_FACE;
7308 DWORD flags25 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7309 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};
7310 const DWORD adjacency25[] = {-1, 1, -1, -1, -1, 0};
7311 const struct vertex_texcoord exp_vertices25[] =
7313 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f}},
7314 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.7f}},
7315 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
7317 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f}},
7318 {{ 0.0f, 0.0f, 0.f}, {0.1f, 0.2f}},
7320 const DWORD exp_indices25[] = {0, 1, 2, 1, 3, 4};
7321 const DWORD exp_face_remap25[] = {0, 1};
7322 const DWORD exp_vertex_remap25[] = {0, 1, 2, 4, 5, -1};
7323 const DWORD exp_new_num_vertices25 = ARRAY_SIZE(exp_vertices25);
7324 /* Test 26. Weld color with usage index larger than 1. Shows that none of
7325 * the epsilon values are used. */
7326 const struct vertex_color vertices26[] =
7328 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7329 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7330 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7332 {{ 3.0f, 3.0f, 0.f}, 0x00000000},
7333 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7334 {{ 1.0f, 0.0f, 0.f}, 0x01010101},
7336 const DWORD indices26[] = {0, 1, 2, 3, 4, 5};
7337 const DWORD attributes26[] = {0, 0};
7338 const UINT num_vertices26 = ARRAY_SIZE(vertices26);
7339 const UINT num_faces26 = ARRAY_SIZE(indices26) / VERTS_PER_FACE;
7340 DWORD flags26 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7341 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};
7342 const DWORD adjacency26[] = {-1, 1, -1, -1, -1, 0};
7343 const struct vertex_color exp_vertices26[] =
7345 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7346 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7347 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7349 {{ 2.0f, 3.0f, 0.f}, 0x00000000},
7350 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7351 {{ 0.0f, 0.0f, 0.f}, 0x01010101},
7353 const DWORD exp_indices26[] = {0, 1, 2, 3, 4, 5};
7354 const DWORD exp_face_remap26[] = {0, 1};
7355 const DWORD exp_vertex_remap26[] = {0, 1, 2, 3, 4, 5};
7356 const DWORD exp_new_num_vertices26 = ARRAY_SIZE(exp_vertices26);
7357 /* Test 27. Weld color with usage index larger than 1. Check that the
7358 * default epsilon of 1e-6f is used. */
7359 D3DXVECTOR4 zero_float4 = {0.0f, 0.0f, 0.0f, 0.0f};
7360 D3DXVECTOR4 almost_zero_float4 = {0.0f + FLT_EPSILON, 0.0f + FLT_EPSILON, 0.0f + FLT_EPSILON, 0.0f + FLT_EPSILON};
7361 const struct vertex_color_float4 vertices27[] =
7363 {{ 0.0f, 3.0f, 0.f}, zero_float4},
7364 {{ 2.0f, 3.0f, 0.f}, zero_float4},
7365 {{ 0.0f, 0.0f, 0.f}, zero_float4},
7367 {{ 3.0f, 3.0f, 0.f}, almost_zero_float4},
7368 {{ 3.0f, 0.0f, 0.f}, zero_float4},
7369 {{ 1.0f, 0.0f, 0.f}, almost_zero_float4},
7371 const DWORD indices27[] = {0, 1, 2, 3, 4, 5};
7372 const DWORD attributes27[] = {0, 0};
7373 const UINT num_vertices27 = ARRAY_SIZE(vertices27);
7374 const UINT num_faces27 = ARRAY_SIZE(indices27) / VERTS_PER_FACE;
7375 DWORD flags27 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7376 const D3DXWELDEPSILONS epsilons27 = {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.0f}, 0.0f, 0.0f, 0.0f};
7377 const DWORD adjacency27[] = {-1, 1, -1, -1, -1, 0};
7378 const struct vertex_color_float4 exp_vertices27[] =
7380 {{ 0.0f, 3.0f, 0.f}, zero_float4},
7381 {{ 2.0f, 3.0f, 0.f}, zero_float4},
7382 {{ 0.0f, 0.0f, 0.f}, zero_float4},
7384 {{ 3.0f, 0.0f, 0.f}, zero_float4},
7386 const DWORD exp_indices27[] = {0, 1, 2, 1, 3, 2};
7387 const DWORD exp_face_remap27[] = {0, 1};
7388 const DWORD exp_vertex_remap27[] = {0, 1, 2, 4, -1, -1};
7389 const DWORD exp_new_num_vertices27 = ARRAY_SIZE(exp_vertices27);
7390 /* Test 28. Weld one normal with UDEC3. */
7391 const DWORD dword_udec3_zero = init_udec3_dword(0, 0, 0, 1);
7392 const DWORD dword_udec3_1023 = init_udec3_dword(1023, 1023, 1023, 1);
7393 const DWORD dword_udec3_1022 = init_udec3_dword(1022, 1022, 1022, 1);
7394 const struct vertex_normal_udec3 vertices28[] =
7396 {{ 0.0f, 3.0f, 0.f}, dword_udec3_zero},
7397 {{ 2.0f, 3.0f, 0.f}, dword_udec3_zero},
7398 {{ 0.0f, 0.0f, 0.f}, dword_udec3_zero},
7400 {{ 3.0f, 3.0f, 0.f}, dword_udec3_1023},
7401 {{ 3.0f, 0.0f, 0.f}, dword_udec3_zero},
7402 {{ 1.0f, 0.0f, 0.f}, dword_udec3_1022},
7404 const DWORD indices28[] = {0, 1, 2, 3, 4, 5};
7405 const DWORD attributes28[] = {0, 0};
7406 const UINT num_vertices28 = ARRAY_SIZE(vertices28);
7407 const UINT num_faces28 = ARRAY_SIZE(indices28) / VERTS_PER_FACE;
7408 DWORD flags28 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7409 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};
7410 const DWORD adjacency28[] = {-1, 1, -1, -1, -1, 0};
7411 const struct vertex_normal_udec3 exp_vertices28[] =
7413 {{ 0.0f, 3.0f, 0.f}, dword_udec3_zero},
7414 {{ 2.0f, 3.0f, 0.f}, dword_udec3_zero},
7415 {{ 0.0f, 0.0f, 0.f}, dword_udec3_zero},
7417 {{ 2.0f, 3.0f, 0.f}, dword_udec3_1023},
7418 {{ 3.0f, 0.0f, 0.f}, dword_udec3_zero},
7420 const DWORD exp_indices28[] = {0, 1, 2, 3, 4, 2};
7421 const DWORD exp_face_remap28[] = {0, 1};
7422 const DWORD exp_vertex_remap28[] = {0, 1, 2, 3, 4, -1};
7423 const DWORD exp_new_num_vertices28 = ARRAY_SIZE(exp_vertices28);
7424 /* Test 29. Weld one normal with DEC3N. */
7425 const DWORD dword_dec3n_zero = init_dec3n_dword(0, 0, 0, 1);
7426 const DWORD dword_dec3n_511 = init_dec3n_dword(511, 511, 511, 1);
7427 const DWORD dword_dec3n_510 = init_dec3n_dword(510, 510, 510, 1);
7428 const struct vertex_normal_dec3n vertices29[] =
7430 {{ 0.0f, 3.0f, 0.f}, dword_dec3n_zero},
7431 {{ 2.0f, 3.0f, 0.f}, dword_dec3n_zero},
7432 {{ 0.0f, 0.0f, 0.f}, dword_dec3n_zero},
7434 {{ 3.0f, 3.0f, 0.f}, dword_dec3n_511},
7435 {{ 3.0f, 0.0f, 0.f}, dword_dec3n_zero},
7436 {{ 1.0f, 0.0f, 0.f}, dword_dec3n_510},
7438 const DWORD indices29[] = {0, 1, 2, 3, 4, 5};
7439 const DWORD attributes29[] = {0, 0};
7440 const UINT num_vertices29 = ARRAY_SIZE(vertices29);
7441 const UINT num_faces29 = ARRAY_SIZE(indices29) / VERTS_PER_FACE;
7442 DWORD flags29 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7443 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};
7444 const DWORD adjacency29[] = {-1, 1, -1, -1, -1, 0};
7445 const struct vertex_normal_dec3n exp_vertices29[] =
7447 {{ 0.0f, 3.0f, 0.f}, dword_dec3n_zero},
7448 {{ 2.0f, 3.0f, 0.f}, dword_dec3n_zero},
7449 {{ 0.0f, 0.0f, 0.f}, dword_dec3n_zero},
7451 {{ 2.0f, 3.0f, 0.f}, dword_dec3n_511},
7452 {{ 3.0f, 0.0f, 0.f}, dword_dec3n_zero},
7454 const DWORD exp_indices29[] = {0, 1, 2, 3, 4, 2};
7455 const DWORD exp_face_remap29[] = {0, 1};
7456 const DWORD exp_vertex_remap29[] = {0, 1, 2, 3, 4, -1};
7457 const DWORD exp_new_num_vertices29 = ARRAY_SIZE(exp_vertices29);
7458 /* All mesh data */
7459 DWORD *adjacency_out = NULL;
7460 DWORD *face_remap = NULL;
7461 ID3DXMesh *mesh = NULL;
7462 ID3DXBuffer *vertex_remap = NULL;
7463 struct
7465 const BYTE *vertices;
7466 const DWORD *indices;
7467 const DWORD *attributes;
7468 const DWORD num_vertices;
7469 const DWORD num_faces;
7470 const DWORD options;
7471 D3DVERTEXELEMENT9 *declaration;
7472 const UINT vertex_size;
7473 const DWORD flags;
7474 const D3DXWELDEPSILONS *epsilons;
7475 const DWORD *adjacency;
7476 const BYTE *exp_vertices;
7477 const DWORD *exp_indices;
7478 const DWORD *exp_face_remap;
7479 const DWORD *exp_vertex_remap;
7480 const DWORD exp_new_num_vertices;
7482 tc[] =
7485 (BYTE*)vertices0,
7486 indices0,
7487 attributes0,
7488 num_vertices0,
7489 num_faces0,
7490 options,
7491 declaration_normal,
7492 vertex_size_normal,
7493 flags0,
7494 NULL,
7495 adjacency0,
7496 (BYTE*)exp_vertices0,
7497 exp_indices0,
7498 exp_face_remap0,
7499 exp_vertex_remap0,
7500 exp_new_num_vertices0
7503 (BYTE*)vertices1,
7504 indices1,
7505 attributes1,
7506 num_vertices1,
7507 num_faces1,
7508 options,
7509 declaration_normal,
7510 vertex_size_normal,
7511 flags1,
7512 NULL,
7513 adjacency1,
7514 (BYTE*)exp_vertices1,
7515 exp_indices1,
7516 exp_face_remap1,
7517 exp_vertex_remap1,
7518 exp_new_num_vertices1
7521 (BYTE*)vertices2,
7522 indices2,
7523 attributes2,
7524 num_vertices2,
7525 num_faces2,
7526 options,
7527 declaration_normal,
7528 vertex_size_normal,
7529 flags2,
7530 &epsilons2,
7531 adjacency2,
7532 (BYTE*)exp_vertices2,
7533 exp_indices2,
7534 exp_face_remap2,
7535 exp_vertex_remap2,
7536 exp_new_num_vertices2
7539 (BYTE*)vertices3,
7540 indices3,
7541 attributes3,
7542 num_vertices3,
7543 num_faces3,
7544 options,
7545 declaration_normal,
7546 vertex_size_normal,
7547 flags3,
7548 &epsilons3,
7549 adjacency3,
7550 (BYTE*)exp_vertices3,
7551 exp_indices3,
7552 exp_face_remap3,
7553 exp_vertex_remap3,
7554 exp_new_num_vertices3
7557 (BYTE*)vertices4,
7558 indices4,
7559 attributes4,
7560 num_vertices4,
7561 num_faces4,
7562 options,
7563 declaration_normal,
7564 vertex_size_normal,
7565 flags4,
7566 &epsilons4,
7567 adjacency4,
7568 (BYTE*)exp_vertices4,
7569 exp_indices4,
7570 exp_face_remap4,
7571 exp_vertex_remap4,
7572 exp_new_num_vertices4
7574 /* Unusual ordering. */
7576 (BYTE*)vertices5,
7577 indices5,
7578 attributes5,
7579 num_vertices5,
7580 num_faces5,
7581 options,
7582 declaration_normal,
7583 vertex_size_normal,
7584 flags5,
7585 NULL,
7586 adjacency5,
7587 (BYTE*)exp_vertices5,
7588 exp_indices5,
7589 exp_face_remap5,
7590 exp_vertex_remap5,
7591 exp_new_num_vertices5
7594 (BYTE*)vertices6,
7595 indices6,
7596 attributes6,
7597 num_vertices6,
7598 num_faces6,
7599 options,
7600 declaration_normal,
7601 vertex_size_normal,
7602 flags6,
7603 &epsilons6,
7604 adjacency6,
7605 (BYTE*)exp_vertices6,
7606 exp_indices6,
7607 exp_face_remap6,
7608 exp_vertex_remap6,
7609 exp_new_num_vertices6
7612 (BYTE*)vertices6,
7613 (DWORD*)indices6_16bit,
7614 attributes6,
7615 num_vertices6,
7616 num_faces6,
7617 options_16bit,
7618 declaration_normal,
7619 vertex_size_normal,
7620 flags6,
7621 &epsilons6,
7622 adjacency6,
7623 (BYTE*)exp_vertices6,
7624 exp_indices6,
7625 exp_face_remap6,
7626 exp_vertex_remap6,
7627 exp_new_num_vertices6
7630 (BYTE*)vertices8,
7631 indices8,
7632 attributes8,
7633 num_vertices8,
7634 num_faces8,
7635 options,
7636 declaration_normal,
7637 vertex_size_normal,
7638 flags8,
7639 &epsilons8,
7640 adjacency8,
7641 (BYTE*)exp_vertices8,
7642 exp_indices8,
7643 exp_face_remap8,
7644 exp_vertex_remap8,
7645 exp_new_num_vertices8
7648 (BYTE*)vertices9,
7649 indices9,
7650 attributes9,
7651 num_vertices9,
7652 num_faces9,
7653 options,
7654 declaration_normal,
7655 vertex_size_normal,
7656 flags9,
7657 &epsilons9,
7658 adjacency9,
7659 (BYTE*)exp_vertices9,
7660 exp_indices9,
7661 exp_face_remap9,
7662 exp_vertex_remap9,
7663 exp_new_num_vertices9
7666 (BYTE*)vertices10,
7667 indices10,
7668 attributes10,
7669 num_vertices10,
7670 num_faces10,
7671 options,
7672 declaration_blendweight,
7673 vertex_size_blendweight,
7674 flags10,
7675 &epsilons10,
7676 adjacency10,
7677 (BYTE*)exp_vertices10,
7678 exp_indices10,
7679 exp_face_remap10,
7680 exp_vertex_remap10,
7681 exp_new_num_vertices10
7684 (BYTE*)vertices11,
7685 indices11,
7686 attributes11,
7687 num_vertices11,
7688 num_faces11,
7689 options,
7690 declaration_texcoord,
7691 vertex_size_texcoord,
7692 flags11,
7693 &epsilons11,
7694 adjacency11,
7695 (BYTE*)exp_vertices11,
7696 exp_indices11,
7697 exp_face_remap11,
7698 exp_vertex_remap11,
7699 exp_new_num_vertices11
7702 (BYTE*)vertices12,
7703 indices12,
7704 attributes12,
7705 num_vertices12,
7706 num_faces12,
7707 options,
7708 declaration_color,
7709 vertex_size_color,
7710 flags12,
7711 &epsilons12,
7712 adjacency12,
7713 (BYTE*)exp_vertices12,
7714 exp_indices12,
7715 exp_face_remap12,
7716 exp_vertex_remap12,
7717 exp_new_num_vertices12
7720 (BYTE*)vertices13,
7721 indices13,
7722 attributes13,
7723 num_vertices13,
7724 num_faces13,
7725 options,
7726 declaration_normal3,
7727 vertex_size_normal,
7728 flags13,
7729 &epsilons13,
7730 adjacency13,
7731 (BYTE*)exp_vertices13,
7732 exp_indices13,
7733 exp_face_remap13,
7734 exp_vertex_remap13,
7735 exp_new_num_vertices13
7738 (BYTE*)vertices14,
7739 indices14,
7740 attributes14,
7741 num_vertices14,
7742 num_faces14,
7743 options,
7744 declaration_color,
7745 vertex_size_color,
7746 flags14,
7747 &epsilons14,
7748 adjacency14,
7749 (BYTE*)exp_vertices14,
7750 exp_indices14,
7751 exp_face_remap14,
7752 exp_vertex_remap14,
7753 exp_new_num_vertices14
7756 (BYTE*)vertices15,
7757 indices15,
7758 attributes15,
7759 num_vertices15,
7760 num_faces15,
7761 options,
7762 declaration_color_ubyte4n,
7763 vertex_size_color_ubyte4, /* UBYTE4 same size as UBYTE4N */
7764 flags15,
7765 &epsilons15,
7766 adjacency15,
7767 (BYTE*)exp_vertices15,
7768 exp_indices15,
7769 exp_face_remap15,
7770 exp_vertex_remap15,
7771 exp_new_num_vertices15
7774 (BYTE*)vertices16,
7775 indices16,
7776 attributes16,
7777 num_vertices16,
7778 num_faces16,
7779 options,
7780 declaration_color_ubyte4,
7781 vertex_size_color_ubyte4,
7782 flags16,
7783 &epsilons16,
7784 adjacency16,
7785 (BYTE*)exp_vertices16,
7786 exp_indices16,
7787 exp_face_remap16,
7788 exp_vertex_remap16,
7789 exp_new_num_vertices16
7792 (BYTE*)vertices17,
7793 indices17,
7794 attributes17,
7795 num_vertices17,
7796 num_faces17,
7797 options,
7798 declaration_texcoord_short2,
7799 vertex_size_texcoord_short2,
7800 flags17,
7801 &epsilons17,
7802 adjacency17,
7803 (BYTE*)exp_vertices17,
7804 exp_indices17,
7805 exp_face_remap17,
7806 exp_vertex_remap17,
7807 exp_new_num_vertices17
7810 (BYTE*)vertices18,
7811 indices18,
7812 attributes18,
7813 num_vertices18,
7814 num_faces18,
7815 options,
7816 declaration_texcoord_short2n,
7817 vertex_size_texcoord_short2, /* SHORT2 same size as SHORT2N */
7818 flags18,
7819 &epsilons18,
7820 adjacency18,
7821 (BYTE*)exp_vertices18,
7822 exp_indices18,
7823 exp_face_remap18,
7824 exp_vertex_remap18,
7825 exp_new_num_vertices18
7828 (BYTE*)vertices19,
7829 indices19,
7830 attributes19,
7831 num_vertices19,
7832 num_faces19,
7833 options,
7834 declaration_texcoord_ushort2n,
7835 vertex_size_texcoord_short2, /* SHORT2 same size as USHORT2N */
7836 flags19,
7837 &epsilons19,
7838 adjacency19,
7839 (BYTE*)exp_vertices19,
7840 exp_indices19,
7841 exp_face_remap19,
7842 exp_vertex_remap19,
7843 exp_new_num_vertices19
7846 (BYTE*)vertices20,
7847 indices20,
7848 attributes20,
7849 num_vertices20,
7850 num_faces20,
7851 options,
7852 declaration_normal_short4,
7853 vertex_size_normal_short4,
7854 flags20,
7855 &epsilons20,
7856 adjacency20,
7857 (BYTE*)exp_vertices20,
7858 exp_indices20,
7859 exp_face_remap20,
7860 exp_vertex_remap20,
7861 exp_new_num_vertices20
7864 (BYTE*)vertices21,
7865 indices21,
7866 attributes21,
7867 num_vertices21,
7868 num_faces21,
7869 options,
7870 declaration_normal_short4n,
7871 vertex_size_normal_short4, /* SHORT4 same size as SHORT4N */
7872 flags21,
7873 &epsilons21,
7874 adjacency21,
7875 (BYTE*)exp_vertices21,
7876 exp_indices21,
7877 exp_face_remap21,
7878 exp_vertex_remap21,
7879 exp_new_num_vertices21
7882 (BYTE*)vertices22,
7883 indices22,
7884 attributes22,
7885 num_vertices22,
7886 num_faces22,
7887 options,
7888 declaration_normal_ushort4n,
7889 vertex_size_normal_short4, /* SHORT4 same size as USHORT4N */
7890 flags22,
7891 &epsilons22,
7892 adjacency22,
7893 (BYTE*)exp_vertices22,
7894 exp_indices22,
7895 exp_face_remap22,
7896 exp_vertex_remap22,
7897 exp_new_num_vertices22
7900 (BYTE*)vertices23,
7901 indices23,
7902 attributes23,
7903 num_vertices23,
7904 num_faces23,
7905 options,
7906 declaration_texcoord_float16_2,
7907 vertex_size_texcoord_float16_2,
7908 flags23,
7909 &epsilons23,
7910 adjacency23,
7911 (BYTE*)exp_vertices23,
7912 exp_indices23,
7913 exp_face_remap23,
7914 exp_vertex_remap23,
7915 exp_new_num_vertices23
7918 (BYTE*)vertices24,
7919 indices24,
7920 attributes24,
7921 num_vertices24,
7922 num_faces24,
7923 options,
7924 declaration_texcoord_float16_4,
7925 vertex_size_texcoord_float16_4,
7926 flags24,
7927 &epsilons24,
7928 adjacency24,
7929 (BYTE*)exp_vertices24,
7930 exp_indices24,
7931 exp_face_remap24,
7932 exp_vertex_remap24,
7933 exp_new_num_vertices24
7936 (BYTE*)vertices25,
7937 indices25,
7938 attributes25,
7939 num_vertices25,
7940 num_faces25,
7941 options,
7942 declaration_texcoord10,
7943 vertex_size_texcoord,
7944 flags25,
7945 &epsilons25,
7946 adjacency25,
7947 (BYTE*)exp_vertices25,
7948 exp_indices25,
7949 exp_face_remap25,
7950 exp_vertex_remap25,
7951 exp_new_num_vertices25
7954 (BYTE*)vertices26,
7955 indices26,
7956 attributes26,
7957 num_vertices26,
7958 num_faces26,
7959 options,
7960 declaration_color2,
7961 vertex_size_color,
7962 flags26,
7963 &epsilons26,
7964 adjacency26,
7965 (BYTE*)exp_vertices26,
7966 exp_indices26,
7967 exp_face_remap26,
7968 exp_vertex_remap26,
7969 exp_new_num_vertices26
7972 (BYTE*)vertices27,
7973 indices27,
7974 attributes27,
7975 num_vertices27,
7976 num_faces27,
7977 options,
7978 declaration_color2_float4,
7979 vertex_size_color_float4,
7980 flags27,
7981 &epsilons27,
7982 adjacency27,
7983 (BYTE*)exp_vertices27,
7984 exp_indices27,
7985 exp_face_remap27,
7986 exp_vertex_remap27,
7987 exp_new_num_vertices27
7990 (BYTE*)vertices28,
7991 indices28,
7992 attributes28,
7993 num_vertices28,
7994 num_faces28,
7995 options,
7996 declaration_normal_udec3,
7997 vertex_size_normal_udec3,
7998 flags28,
7999 &epsilons28,
8000 adjacency28,
8001 (BYTE*)exp_vertices28,
8002 exp_indices28,
8003 exp_face_remap28,
8004 exp_vertex_remap28,
8005 exp_new_num_vertices28
8008 (BYTE*)vertices29,
8009 indices29,
8010 attributes29,
8011 num_vertices29,
8012 num_faces29,
8013 options,
8014 declaration_normal_dec3n,
8015 vertex_size_normal_dec3n,
8016 flags29,
8017 &epsilons29,
8018 adjacency29,
8019 (BYTE*)exp_vertices29,
8020 exp_indices29,
8021 exp_face_remap29,
8022 exp_vertex_remap29,
8023 exp_new_num_vertices29
8027 test_context = new_test_context();
8028 if (!test_context)
8030 skip("Couldn't create test context\n");
8031 goto cleanup;
8034 for (i = 0; i < ARRAY_SIZE(tc); i++)
8036 DWORD j;
8037 DWORD *vertex_remap_ptr;
8038 DWORD new_num_vertices;
8040 hr = init_test_mesh(tc[i].num_faces, tc[i].num_vertices, tc[i].options,
8041 tc[i].declaration, test_context->device, &mesh,
8042 tc[i].vertices, tc[i].vertex_size,
8043 tc[i].indices, tc[i].attributes);
8044 if (FAILED(hr))
8046 skip("Couldn't initialize test mesh %d.\n", i);
8047 goto cleanup;
8050 /* Allocate out parameters */
8051 adjacency_out = HeapAlloc(GetProcessHeap(), 0, VERTS_PER_FACE * tc[i].num_faces * sizeof(*adjacency_out));
8052 if (!adjacency_out)
8054 skip("Couldn't allocate adjacency_out array.\n");
8055 goto cleanup;
8057 face_remap = HeapAlloc(GetProcessHeap(), 0, tc[i].num_faces * sizeof(*face_remap));
8058 if (!adjacency_out)
8060 skip("Couldn't allocate face_remap array.\n");
8061 goto cleanup;
8064 hr = D3DXWeldVertices(mesh, tc[i].flags, tc[i].epsilons, tc[i].adjacency,
8065 adjacency_out, face_remap, &vertex_remap);
8066 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
8067 /* Check number of vertices*/
8068 new_num_vertices = mesh->lpVtbl->GetNumVertices(mesh);
8069 ok(new_num_vertices == tc[i].exp_new_num_vertices,
8070 "Mesh %d: new_num_vertices == %d, expected %d.\n",
8071 i, new_num_vertices, tc[i].exp_new_num_vertices);
8072 /* Check index buffer */
8073 if (tc[i].options & D3DXMESH_32BIT)
8075 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, (void**)&indices);
8076 if (FAILED(hr))
8078 skip("Couldn't lock index buffer.\n");
8079 goto cleanup;
8081 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
8083 ok(indices[j] == tc[i].exp_indices[j],
8084 "Mesh %d: indices[%d] == %d, expected %d\n",
8085 i, j, indices[j], tc[i].exp_indices[j]);
8088 else
8090 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, (void**)&indices_16bit);
8091 if (FAILED(hr))
8093 skip("Couldn't lock index buffer.\n");
8094 goto cleanup;
8096 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
8098 ok(indices_16bit[j] == tc[i].exp_indices[j],
8099 "Mesh %d: indices_16bit[%d] == %d, expected %d\n",
8100 i, j, indices_16bit[j], tc[i].exp_indices[j]);
8103 mesh->lpVtbl->UnlockIndexBuffer(mesh);
8104 indices = NULL;
8105 indices_16bit = NULL;
8106 /* Check adjacency_out */
8107 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
8109 ok(adjacency_out[j] == tc[i].adjacency[j],
8110 "Mesh %d: adjacency_out[%d] == %d, expected %d\n",
8111 i, j, adjacency_out[j], tc[i].adjacency[j]);
8113 /* Check face_remap */
8114 for (j = 0; j < tc[i].num_faces; j++)
8116 ok(face_remap[j] == tc[i].exp_face_remap[j],
8117 "Mesh %d: face_remap[%d] == %d, expected %d\n",
8118 i, j, face_remap[j], tc[i].exp_face_remap[j]);
8120 /* Check vertex_remap */
8121 vertex_remap_ptr = vertex_remap->lpVtbl->GetBufferPointer(vertex_remap);
8122 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
8124 ok(vertex_remap_ptr[j] == tc[i].exp_vertex_remap[j],
8125 "Mesh %d: vertex_remap_ptr[%d] == %d, expected %d\n",
8126 i, j, vertex_remap_ptr[j], tc[i].exp_vertex_remap[j]);
8128 /* Check vertex buffer */
8129 hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, (void*)&vertices);
8130 if (FAILED(hr))
8132 skip("Couldn't lock vertex buffer.\n");
8133 goto cleanup;
8135 /* Check contents of re-ordered vertex buffer */
8136 for (j = 0; j < tc[i].exp_new_num_vertices; j++)
8138 int index = tc[i].vertex_size*j;
8139 check_vertex_components(__LINE__, i, j, &vertices[index], &tc[i].exp_vertices[index], tc[i].declaration);
8141 mesh->lpVtbl->UnlockVertexBuffer(mesh);
8142 vertices = NULL;
8144 /* Free mesh and output data */
8145 HeapFree(GetProcessHeap(), 0, adjacency_out);
8146 adjacency_out = NULL;
8147 HeapFree(GetProcessHeap(), 0, face_remap);
8148 face_remap = NULL;
8149 vertex_remap->lpVtbl->Release(vertex_remap);
8150 vertex_remap = NULL;
8151 mesh->lpVtbl->Release(mesh);
8152 mesh = NULL;
8155 cleanup:
8156 HeapFree(GetProcessHeap(), 0, adjacency_out);
8157 HeapFree(GetProcessHeap(), 0, face_remap);
8158 if (indices) mesh->lpVtbl->UnlockIndexBuffer(mesh);
8159 if (indices_16bit) mesh->lpVtbl->UnlockIndexBuffer(mesh);
8160 if (mesh) mesh->lpVtbl->Release(mesh);
8161 if (vertex_remap) vertex_remap->lpVtbl->Release(vertex_remap);
8162 if (vertices) mesh->lpVtbl->UnlockVertexBuffer(mesh);
8163 free_test_context(test_context);
8166 static void test_clone_mesh(void)
8168 HRESULT hr;
8169 struct test_context *test_context = NULL;
8170 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
8171 D3DVERTEXELEMENT9 declaration_pn[] =
8173 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8174 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
8175 D3DDECL_END()
8177 D3DVERTEXELEMENT9 declaration_pntc[] =
8179 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8180 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
8181 {0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8182 D3DDECL_END()
8184 D3DVERTEXELEMENT9 declaration_ptcn[] =
8186 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8187 {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8188 {0, 20, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
8189 D3DDECL_END()
8191 D3DVERTEXELEMENT9 declaration_ptc[] =
8193 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8194 {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8195 D3DDECL_END()
8197 D3DVERTEXELEMENT9 declaration_ptc_float16_2[] =
8199 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8200 {0, 12, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8201 D3DDECL_END()
8203 D3DVERTEXELEMENT9 declaration_ptc_float16_4[] =
8205 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8206 {0, 12, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8207 D3DDECL_END()
8209 D3DVERTEXELEMENT9 declaration_ptc_float1[] =
8211 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8212 {0, 12, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8213 D3DDECL_END()
8215 D3DVERTEXELEMENT9 declaration_ptc_float3[] =
8217 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8218 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8219 D3DDECL_END()
8221 D3DVERTEXELEMENT9 declaration_ptc_float4[] =
8223 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8224 {0, 12, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8225 D3DDECL_END()
8227 D3DVERTEXELEMENT9 declaration_ptc_d3dcolor[] =
8229 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8230 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8231 D3DDECL_END()
8233 D3DVERTEXELEMENT9 declaration_ptc_ubyte4[] =
8235 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8236 {0, 12, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8237 D3DDECL_END()
8239 D3DVERTEXELEMENT9 declaration_ptc_ubyte4n[] =
8241 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8242 {0, 12, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8243 D3DDECL_END()
8245 D3DVERTEXELEMENT9 declaration_ptc_short2[] =
8247 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8248 {0, 12, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8249 D3DDECL_END()
8251 D3DVERTEXELEMENT9 declaration_ptc_short4[] =
8253 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8254 {0, 12, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8255 D3DDECL_END()
8257 D3DVERTEXELEMENT9 declaration_ptc_short2n[] =
8259 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8260 {0, 12, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8261 D3DDECL_END()
8263 D3DVERTEXELEMENT9 declaration_ptc_short4n[] =
8265 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8266 {0, 12, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8267 D3DDECL_END()
8269 D3DVERTEXELEMENT9 declaration_ptc_ushort2n[] =
8271 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8272 {0, 12, D3DDECLTYPE_USHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8273 D3DDECL_END()
8275 D3DVERTEXELEMENT9 declaration_ptc_ushort4n[] =
8277 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8278 {0, 12, D3DDECLTYPE_USHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8279 D3DDECL_END()
8281 D3DVERTEXELEMENT9 declaration_ptc_float16_2_partialu[] =
8283 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8284 {0, 12, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_PARTIALU, D3DDECLUSAGE_TEXCOORD, 0},
8285 D3DDECL_END()
8287 D3DVERTEXELEMENT9 declaration_pntc1[] =
8289 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8290 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
8291 {0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
8292 D3DDECL_END()
8294 const unsigned int VERTS_PER_FACE = 3;
8295 BYTE *vertices = NULL;
8296 INT i;
8297 struct vertex_pn
8299 D3DXVECTOR3 position;
8300 D3DXVECTOR3 normal;
8302 struct vertex_pntc
8304 D3DXVECTOR3 position;
8305 D3DXVECTOR3 normal;
8306 D3DXVECTOR2 texcoords;
8308 struct vertex_ptcn
8310 D3DXVECTOR3 position;
8311 D3DXVECTOR2 texcoords;
8312 D3DXVECTOR3 normal;
8314 struct vertex_ptc
8316 D3DXVECTOR3 position;
8317 D3DXVECTOR2 texcoords;
8319 struct vertex_ptc_float16_2
8321 D3DXVECTOR3 position;
8322 WORD texcoords[2]; /* float16_2 */
8324 struct vertex_ptc_float16_4
8326 D3DXVECTOR3 position;
8327 WORD texcoords[4]; /* float16_4 */
8329 struct vertex_ptc_float1
8331 D3DXVECTOR3 position;
8332 FLOAT texcoords;
8334 struct vertex_ptc_float3
8336 D3DXVECTOR3 position;
8337 FLOAT texcoords[3];
8339 struct vertex_ptc_float4
8341 D3DXVECTOR3 position;
8342 FLOAT texcoords[4];
8344 struct vertex_ptc_d3dcolor
8346 D3DXVECTOR3 position;
8347 BYTE texcoords[4];
8349 struct vertex_ptc_ubyte4
8351 D3DXVECTOR3 position;
8352 BYTE texcoords[4];
8354 struct vertex_ptc_ubyte4n
8356 D3DXVECTOR3 position;
8357 BYTE texcoords[4];
8359 struct vertex_ptc_short2
8361 D3DXVECTOR3 position;
8362 SHORT texcoords[2];
8364 struct vertex_ptc_short4
8366 D3DXVECTOR3 position;
8367 SHORT texcoords[4];
8369 struct vertex_ptc_ushort2n
8371 D3DXVECTOR3 position;
8372 USHORT texcoords[2];
8374 struct vertex_ptc_ushort4n
8376 D3DXVECTOR3 position;
8377 USHORT texcoords[4];
8379 struct vertex_ptc_udec3
8381 D3DXVECTOR3 position;
8382 DWORD texcoords;
8384 struct vertex_ptc_dec3n
8386 D3DXVECTOR3 position;
8387 DWORD texcoords;
8389 D3DXVECTOR3 up = {0.0f, 0.0f, 1.0f};
8390 D3DXVECTOR2 zero_vec2 = {0.0f, 0.0f};
8391 /* Test 0. Check that a mesh can be cloned if the new declaration is the
8392 * same as the one used to create the mesh.
8394 * 0--1 3
8395 * | / /|
8396 * |/ / |
8397 * 2 5--4
8399 const struct vertex_pn vertices0[] =
8401 {{ 0.0f, 3.0f, 0.f}, up},
8402 {{ 2.0f, 3.0f, 0.f}, up},
8403 {{ 0.0f, 0.0f, 0.f}, up},
8405 {{ 3.0f, 3.0f, 0.f}, up},
8406 {{ 3.0f, 0.0f, 0.f}, up},
8407 {{ 1.0f, 0.0f, 0.f}, up},
8409 const UINT num_vertices0 = ARRAY_SIZE(vertices0);
8410 const UINT num_faces0 = ARRAY_SIZE(vertices0) / VERTS_PER_FACE;
8411 const UINT vertex_size0 = sizeof(*vertices0);
8412 /* Test 1. Check that 16-bit indices are handled. */
8413 const DWORD options_16bit = D3DXMESH_SYSTEMMEM;
8414 /* Test 2. Check that the size of each vertex is increased and the data
8415 * moved if the new declaration adds an element after the original elements.
8417 const struct vertex_pntc exp_vertices2[] =
8419 {{ 0.0f, 3.0f, 0.f}, up, zero_vec2},
8420 {{ 2.0f, 3.0f, 0.f}, up, zero_vec2},
8421 {{ 0.0f, 0.0f, 0.f}, up, zero_vec2},
8423 {{ 3.0f, 3.0f, 0.f}, up, zero_vec2},
8424 {{ 3.0f, 0.0f, 0.f}, up, zero_vec2},
8425 {{ 1.0f, 0.0f, 0.f}, up, zero_vec2},
8427 const UINT exp_vertex_size2 = sizeof(*exp_vertices2);
8428 /* Test 3. Check that the size of each vertex is increased and the data
8429 * moved if the new declaration adds an element between the original
8430 * elements.
8432 const struct vertex_ptcn exp_vertices3[] =
8434 {{ 0.0f, 3.0f, 0.f}, zero_vec2, up},
8435 {{ 2.0f, 3.0f, 0.f}, zero_vec2, up},
8436 {{ 0.0f, 0.0f, 0.f}, zero_vec2, up},
8438 {{ 3.0f, 3.0f, 0.f}, zero_vec2, up},
8439 {{ 3.0f, 0.0f, 0.f}, zero_vec2, up},
8440 {{ 1.0f, 0.0f, 0.f}, zero_vec2, up},
8442 const UINT exp_vertex_size3 = sizeof(*exp_vertices3);
8443 /* Test 4. Test that data types can be converted, e.g. FLOAT2 to FLOAT16_2. */
8444 const struct vertex_ptc vertices4[] =
8446 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8447 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8448 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
8450 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8451 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
8452 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
8454 const UINT num_vertices4 = ARRAY_SIZE(vertices4);
8455 const UINT num_faces4 = ARRAY_SIZE(vertices4) / VERTS_PER_FACE;
8456 const UINT vertex_size4 = sizeof(*vertices4);
8457 const struct vertex_ptc_float16_2 exp_vertices4[] =
8459 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
8460 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */
8461 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */
8463 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd}}, /* {0.2f, 0.3f} */
8464 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
8465 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */
8467 const UINT exp_vertex_size4 = sizeof(*exp_vertices4);
8468 /* Test 5. Convert FLOAT2 to FLOAT16_4. */
8469 const struct vertex_ptc vertices5[] =
8471 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8472 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8473 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
8475 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8476 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
8477 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
8479 const UINT num_vertices5 = ARRAY_SIZE(vertices5);
8480 const UINT num_faces5 = ARRAY_SIZE(vertices5) / VERTS_PER_FACE;
8481 const UINT vertex_size5 = sizeof(*vertices5);
8482 const struct vertex_ptc_float16_4 exp_vertices5[] =
8484 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00, 0, 0x3c00}}, /* {1.0f, 1.0f, 0.0f, 1.0f} */
8485 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a, 0, 0x3c00}}, /* {0.5f, 0.7f, 0.0f, 1.0f} */
8486 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd, 0, 0x3c00}}, /* {-0.2f, -0.3f, 0.0f, 1.0f} */
8488 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd, 0, 0x3c00}}, /* {0.2f, 0.3f, 0.0f, 1.0f} */
8489 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00, 0, 0x3c00}}, /* {1.0f, 1.0f, 0.0f, 1.0f} */
8490 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266, 0, 0x3c00}}, /* {0.1f, 0.2f, 0.0f, 1.0f} */
8492 const UINT exp_vertex_size5 = sizeof(*exp_vertices5);
8493 /* Test 6. Convert FLOAT2 to FLOAT1. */
8494 const struct vertex_ptc vertices6[] =
8496 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8497 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8498 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
8500 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8501 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
8502 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
8504 const UINT num_vertices6 = ARRAY_SIZE(vertices6);
8505 const UINT num_faces6 = ARRAY_SIZE(vertices6) / VERTS_PER_FACE;
8506 const UINT vertex_size6 = sizeof(*vertices6);
8507 const struct vertex_ptc_float1 exp_vertices6[] =
8509 {{ 0.0f, 3.0f, 0.f}, 1.0f},
8510 {{ 2.0f, 3.0f, 0.f}, 0.5f},
8511 {{ 0.0f, 0.0f, 0.f}, -0.2f},
8513 {{ 3.0f, 3.0f, 0.f}, 0.2f},
8514 {{ 3.0f, 0.0f, 0.f}, 1.0f},
8515 {{ 1.0f, 0.0f, 0.f}, 0.1f},
8517 const UINT exp_vertex_size6 = sizeof(*exp_vertices6);
8518 /* Test 7. Convert FLOAT2 to FLOAT3. */
8519 const struct vertex_ptc vertices7[] =
8521 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8522 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8523 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
8525 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8526 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
8527 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
8529 const UINT num_vertices7 = ARRAY_SIZE(vertices7);
8530 const UINT num_faces7 = ARRAY_SIZE(vertices7) / VERTS_PER_FACE;
8531 const UINT vertex_size7 = sizeof(*vertices7);
8532 const struct vertex_ptc_float3 exp_vertices7[] =
8534 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f, 0.0f}},
8535 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f, 0.0f}},
8536 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f, 0.0f}},
8538 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f, 0.0f}},
8539 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f, 0.0f}},
8540 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f, 0.0f}},
8542 const UINT exp_vertex_size7 = sizeof(*exp_vertices7);
8543 /* Test 8. Convert FLOAT2 to FLOAT4. */
8544 const struct vertex_ptc vertices8[] =
8546 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8547 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8548 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
8550 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8551 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
8552 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
8554 const UINT num_vertices8 = ARRAY_SIZE(vertices8);
8555 const UINT num_faces8 = ARRAY_SIZE(vertices8) / VERTS_PER_FACE;
8556 const UINT vertex_size8 = sizeof(*vertices8);
8557 const struct vertex_ptc_float4 exp_vertices8[] =
8559 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f, 0.0f, 1.0f}},
8560 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f, 0.0f, 1.0f}},
8561 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f, 0.0f, 1.0f}},
8563 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f, 0.0f, 1.0f}},
8564 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f, 0.0f, 1.0f}},
8565 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f, 0.0f, 1.0f}},
8567 const UINT exp_vertex_size8 = sizeof(*exp_vertices8);
8568 /* Test 9. Convert FLOAT2 to D3DCOLOR. */
8569 const struct vertex_ptc vertices9[] =
8571 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8572 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8573 {{ 0.0f, 0.0f, 0.f}, {-0.4f, -0.6f}},
8575 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8576 {{ 3.0f, 0.0f, 0.f}, { 2.0f, 256.0f}},
8577 {{ 1.0f, 0.0f, 0.f}, { 0.11f, 0.2f}},
8579 const UINT num_vertices9 = ARRAY_SIZE(vertices9);
8580 const UINT num_faces9 = ARRAY_SIZE(vertices9) / VERTS_PER_FACE;
8581 const UINT vertex_size9 = sizeof(*vertices9);
8582 const struct vertex_ptc_d3dcolor exp_vertices9[] =
8584 {{ 0.0f, 3.0f, 0.f}, {0, 255, 255, 255}},
8585 {{ 2.0f, 3.0f, 0.f}, {0, 179, 128, 255}},
8586 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 255}},
8588 {{ 3.0f, 3.0f, 0.f}, {0, 77, 51, 255}},
8589 {{ 3.0f, 0.0f, 0.f}, {0, 255, 255, 255}},
8590 {{ 1.0f, 0.0f, 0.f}, {0, 51, 28, 255}},
8592 const UINT exp_vertex_size9 = sizeof(*exp_vertices9);
8593 /* Test 10. Convert FLOAT2 to UBYTE4. */
8594 const struct vertex_ptc vertices10[] =
8596 {{ 0.0f, 3.0f, 0.f}, { 0.0f, 1.0f}},
8597 {{ 2.0f, 3.0f, 0.f}, { 2.0f, 3.0f}},
8598 {{ 0.0f, 0.0f, 0.f}, { 254.0f, 255.0f}},
8600 {{ 3.0f, 3.0f, 0.f}, { 256.0f, 257.0f}},
8601 {{ 3.0f, 0.0f, 0.f}, { 1.4f, 1.5f}},
8602 {{ 1.0f, 0.0f, 0.f}, {-4.0f, -5.0f}},
8604 const UINT num_vertices10 = ARRAY_SIZE(vertices10);
8605 const UINT num_faces10 = ARRAY_SIZE(vertices10) / VERTS_PER_FACE;
8606 const UINT vertex_size10 = sizeof(*vertices10);
8607 const struct vertex_ptc_ubyte4 exp_vertices10[] =
8609 {{ 0.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
8610 {{ 2.0f, 3.0f, 0.f}, {2, 3, 0, 1}},
8611 {{ 0.0f, 0.0f, 0.f}, {254, 255, 0, 1}},
8613 {{ 3.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
8614 {{ 3.0f, 0.0f, 0.f}, {1, 2, 0, 1}},
8615 {{ 1.0f, 0.0f, 0.f}, {0, 0, 0, 1}},
8617 const UINT exp_vertex_size10 = sizeof(*exp_vertices10);
8618 /* Test 11. Convert FLOAT2 to SHORT2. */
8619 const struct vertex_ptc vertices11[] =
8621 {{ 0.0f, 3.0f, 0.f}, { 1.0f, -1.0f}},
8622 {{ 2.0f, 3.0f, 0.f}, { 0.4f, 0.5f}},
8623 {{ 0.0f, 0.0f, 0.f}, {-0.5f, -5.0f}},
8625 {{ 3.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MIN}},
8626 {{ 3.0f, 0.0f, 0.f}, {SHRT_MAX + 1.0f, SHRT_MIN - 1.0f}},
8627 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX + 2.0f, SHRT_MIN - 2.0f}},
8629 {{ 4.0f, 3.0f, 0.f}, {2 * SHRT_MAX, 2 * SHRT_MIN}},
8630 {{ 6.0f, 0.0f, 0.f}, {3 * SHRT_MAX, 3 * SHRT_MIN}},
8631 {{ 4.0f, 0.0f, 0.f}, {4 * SHRT_MAX, 4 * SHRT_MIN}},
8633 const UINT num_vertices11 = ARRAY_SIZE(vertices11);
8634 const UINT num_faces11 = ARRAY_SIZE(vertices11) / VERTS_PER_FACE;
8635 const UINT vertex_size11 = sizeof(*vertices11);
8636 const struct vertex_ptc_short2 exp_vertices11[] =
8638 {{ 0.0f, 3.0f, 0.f}, {1, 0}},
8639 {{ 2.0f, 3.0f, 0.f}, {0, 1}},
8640 {{ 0.0f, 0.0f, 0.f}, {0, -4}},
8642 {{ 3.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MIN + 1}},
8643 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MIN}},
8644 {{ 1.0f, 0.0f, 0.f}, {SHRT_MIN + 1, SHRT_MAX}},
8646 {{ 4.0f, 3.0f, 0.f}, {-2, 1}},
8647 {{ 6.0f, 0.0f, 0.f}, {32765, -32767}},
8648 {{ 4.0f, 0.0f, 0.f}, {-4, 1}},
8650 const UINT exp_vertex_size11 = sizeof(*exp_vertices11);
8651 /* Test 12. Convert FLOAT2 to SHORT4. */
8652 const struct vertex_ptc vertices12[] =
8654 {{ 0.0f, 3.0f, 0.f}, { 1.0f, -1.0f}},
8655 {{ 2.0f, 3.0f, 0.f}, { 0.4f, 0.5f}},
8656 {{ 0.0f, 0.0f, 0.f}, {-0.5f, -5.0f}},
8658 {{ 3.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MIN}},
8659 {{ 3.0f, 0.0f, 0.f}, {SHRT_MAX + 1.0f, SHRT_MIN - 1.0f}},
8660 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX + 2.0f, SHRT_MIN - 2.0f}},
8662 {{ 4.0f, 3.0f, 0.f}, {2 * SHRT_MAX, 2 * SHRT_MIN}},
8663 {{ 6.0f, 0.0f, 0.f}, {3 * SHRT_MAX, 3 * SHRT_MIN}},
8664 {{ 4.0f, 0.0f, 0.f}, {4 * SHRT_MAX, 4 * SHRT_MIN}},
8666 const UINT num_vertices12 = ARRAY_SIZE(vertices12);
8667 const UINT num_faces12 = ARRAY_SIZE(vertices12) / VERTS_PER_FACE;
8668 const UINT vertex_size12 = sizeof(*vertices12);
8669 const struct vertex_ptc_short4 exp_vertices12[] =
8671 {{ 0.0f, 3.0f, 0.f}, {1, 0, 0, 1}},
8672 {{ 2.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
8673 {{ 0.0f, 0.0f, 0.f}, {0, -4, 0, 1}},
8675 {{ 3.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MIN + 1, 0, 1}},
8676 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MIN, 0, 1}},
8677 {{ 1.0f, 0.0f, 0.f}, {SHRT_MIN + 1, SHRT_MAX, 0, 1}},
8679 {{ 4.0f, 3.0f, 0.f}, {-2, 1, 0, 1}},
8680 {{ 6.0f, 0.0f, 0.f}, {32765, -32767, 0, 1}},
8681 {{ 4.0f, 0.0f, 0.f}, {-4, 1, 0, 1}},
8683 const UINT exp_vertex_size12 = sizeof(*exp_vertices12);
8684 /* Test 13. Convert FLOAT2 to UBYTE4N. */
8685 const struct vertex_ptc vertices13[] =
8687 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 2.0f}},
8688 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8689 {{ 0.0f, 0.0f, 0.f}, {-0.4f, -0.5f}},
8691 {{ 3.0f, 3.0f, 0.f}, {-0.6f, -1.0f}},
8692 {{ 3.0f, 0.0f, 0.f}, {UCHAR_MAX, UCHAR_MAX + 1}},
8693 {{ 1.0f, 0.0f, 0.f}, {2 * UCHAR_MAX, -UCHAR_MAX}},
8695 const UINT num_vertices13 = ARRAY_SIZE(vertices13);
8696 const UINT num_faces13 = ARRAY_SIZE(vertices13) / VERTS_PER_FACE;
8697 const UINT vertex_size13 = sizeof(*vertices13);
8698 const struct vertex_ptc_ubyte4n exp_vertices13[] =
8700 {{ 0.0f, 3.0f, 0.f}, {255, 255, 0, 255}},
8701 {{ 2.0f, 3.0f, 0.f}, {128, 179, 0, 255}},
8702 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 255}},
8704 {{ 3.0f, 3.0f, 0.f}, {0, 0, 0, 255}},
8705 {{ 3.0f, 0.0f, 0.f}, {255, 255, 0, 255}},
8706 {{ 1.0f, 0.0f, 0.f}, {255, 0, 0, 255}},
8708 const UINT exp_vertex_size13 = sizeof(*exp_vertices13);
8709 /* Test 14. Convert FLOAT2 to SHORT2N. */
8710 const struct vertex_ptc vertices14[] =
8712 {{ 0.0f, 3.0f, 0.f}, {1.0f, 2.0f}},
8713 {{ 2.0f, 3.0f, 0.f}, {0.4f, 0.5f}},
8714 {{ 0.0f, 0.0f, 0.f}, {0.6f, -1.0f}},
8716 {{ 3.0f, 3.0f, 0.f}, {-0.4f, -0.5f}},
8717 {{ 3.0f, 0.0f, 0.f}, {-0.9f, -0.99997}},
8718 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX, SHRT_MIN}},
8720 const UINT num_vertices14 = ARRAY_SIZE(vertices14);
8721 const UINT num_faces14 = ARRAY_SIZE(vertices14) / VERTS_PER_FACE;
8722 const UINT vertex_size14 = sizeof(*vertices14);
8723 const struct vertex_ptc_short2 exp_vertices14[] =
8725 {{ 0.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MAX}},
8726 {{ 2.0f, 3.0f, 0.f}, {13107, 16384}},
8727 {{ 0.0f, 0.0f, 0.f}, {19660, SHRT_MIN + 2}},
8729 {{ 3.0f, 3.0f, 0.f}, {-13106, -16383}},
8730 {{ 3.0f, 0.0f, 0.f}, {-29489, SHRT_MIN + 3}},
8731 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX, SHRT_MIN + 2}},
8733 const UINT exp_vertex_size14 = sizeof(*exp_vertices14);
8734 /* Test 15. Convert FLOAT2 to SHORT4N. */
8735 const struct vertex_ptc vertices15[] =
8737 {{ 0.0f, 3.0f, 0.f}, {1.0f, 2.0f}},
8738 {{ 2.0f, 3.0f, 0.f}, {0.4f, 0.5f}},
8739 {{ 0.0f, 0.0f, 0.f}, {0.6f, -1.0f}},
8741 {{ 3.0f, 3.0f, 0.f}, {-0.4f, -0.5f}},
8742 {{ 3.0f, 0.0f, 0.f}, {-0.9f, -0.99997}},
8743 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX, SHRT_MIN}},
8745 const UINT num_vertices15 = ARRAY_SIZE(vertices15);
8746 const UINT num_faces15 = ARRAY_SIZE(vertices15) / VERTS_PER_FACE;
8747 const UINT vertex_size15 = sizeof(*vertices15);
8748 const struct vertex_ptc_short4 exp_vertices15[] =
8750 {{ 0.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MAX, 0, SHRT_MAX}},
8751 {{ 2.0f, 3.0f, 0.f}, {13107, 16384, 0, SHRT_MAX}},
8752 {{ 0.0f, 0.0f, 0.f}, {19660, SHRT_MIN + 2, 0, SHRT_MAX}},
8754 {{ 3.0f, 3.0f, 0.f}, {-13106, -16383, 0, SHRT_MAX}},
8755 {{ 3.0f, 0.0f, 0.f}, {-29489, SHRT_MIN + 3, 0, SHRT_MAX}},
8756 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX, SHRT_MIN + 2, 0, SHRT_MAX}},
8758 const UINT exp_vertex_size15 = sizeof(*exp_vertices15);
8759 /* Test 16. Convert FLOAT2 to USHORT2N. */
8760 const struct vertex_ptc vertices16[] =
8762 {{ 0.0f, 3.0f, 0.f}, {1.0f, 2.0f}},
8763 {{ 2.0f, 3.0f, 0.f}, {0.4f, 0.5f}},
8764 {{ 0.0f, 0.0f, 0.f}, {0.6f, -1.0f}},
8766 {{ 3.0f, 3.0f, 0.f}, {-0.4f, -0.5f}},
8767 {{ 3.0f, 0.0f, 0.f}, {-0.9f, 0.99998f}},
8768 {{ 1.0f, 0.0f, 0.f}, {USHRT_MAX, 0.0f}},
8770 const UINT num_vertices16 = ARRAY_SIZE(vertices16);
8771 const UINT num_faces16 = ARRAY_SIZE(vertices16) / VERTS_PER_FACE;
8772 const UINT vertex_size16 = sizeof(*vertices16);
8773 const struct vertex_ptc_ushort2n exp_vertices16[] =
8775 {{ 0.0f, 3.0f, 0.f}, {USHRT_MAX, USHRT_MAX}},
8776 {{ 2.0f, 3.0f, 0.f}, {26214, 32768}},
8777 {{ 0.0f, 0.0f, 0.f}, {39321, 0}},
8779 {{ 3.0f, 3.0f, 0.f}, {0, 0}},
8780 {{ 3.0f, 0.0f, 0.f}, {0, USHRT_MAX - 1}},
8781 {{ 1.0f, 0.0f, 0.f}, {USHRT_MAX, 0}},
8783 const UINT exp_vertex_size16 = sizeof(*exp_vertices16);
8784 /* Test 17. Convert FLOAT2 to USHORT4N. */
8785 const struct vertex_ptc vertices17[] =
8787 {{ 0.0f, 3.0f, 0.f}, {1.0f, 2.0f}},
8788 {{ 2.0f, 3.0f, 0.f}, {0.4f, 0.5f}},
8789 {{ 0.0f, 0.0f, 0.f}, {0.6f, -1.0f}},
8791 {{ 3.0f, 3.0f, 0.f}, {-0.4f, -0.5f}},
8792 {{ 3.0f, 0.0f, 0.f}, {-0.9f, 0.99998f}},
8793 {{ 1.0f, 0.0f, 0.f}, {USHRT_MAX, 0.0f}},
8795 const UINT num_vertices17 = ARRAY_SIZE(vertices17);
8796 const UINT num_faces17 = ARRAY_SIZE(vertices17) / VERTS_PER_FACE;
8797 const UINT vertex_size17 = sizeof(*vertices17);
8798 const struct vertex_ptc_ushort4n exp_vertices17[] =
8800 {{ 0.0f, 3.0f, 0.f}, {USHRT_MAX, USHRT_MAX, 0, USHRT_MAX}},
8801 {{ 2.0f, 3.0f, 0.f}, {26214, 32768, 0, USHRT_MAX}},
8802 {{ 0.0f, 0.0f, 0.f}, {39321, 0, 0, USHRT_MAX}},
8804 {{ 3.0f, 3.0f, 0.f}, {0, 0, 0, USHRT_MAX}},
8805 {{ 3.0f, 0.0f, 0.f}, {0, USHRT_MAX - 1, 0, USHRT_MAX}},
8806 {{ 1.0f, 0.0f, 0.f}, {USHRT_MAX, 0, 0, USHRT_MAX}},
8808 const UINT exp_vertex_size17 = sizeof(*exp_vertices17);
8809 /* Test 18. Test that the method field is compared by converting a FLOAT2 to
8810 * FLOAT16_2. where the method field has been change from
8811 * D3DDECLMETHOD_DEFAULT to D3DDECLMETHOD_PARTIALU. */
8812 const struct vertex_ptc vertices18[] =
8814 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8815 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8816 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
8818 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8819 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
8820 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
8822 const UINT num_vertices18 = ARRAY_SIZE(vertices18);
8823 const UINT num_faces18 = ARRAY_SIZE(vertices18) / VERTS_PER_FACE;
8824 const UINT vertex_size18 = sizeof(*vertices18);
8825 const struct vertex_ptc_float16_2 exp_vertices18[] =
8827 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
8828 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */
8829 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */
8831 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd}}, /* {0.2f, 0.3f} */
8832 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
8833 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */
8835 const UINT exp_vertex_size18 = sizeof(*exp_vertices18);
8836 /* Test 19. Test that data is lost if usage index changes, e.g. TEXCOORD0
8837 * TEXCOORD1. */
8838 const struct vertex_pntc vertices19[] =
8840 {{ 0.0f, 3.0f, 0.f}, up, { 1.0f, 1.0f}},
8841 {{ 2.0f, 3.0f, 0.f}, up, { 0.5f, 0.7f}},
8842 {{ 0.0f, 0.0f, 0.f}, up, {-0.2f, -0.3f}},
8844 {{ 3.0f, 3.0f, 0.f}, up, { 0.2f, 0.3f}},
8845 {{ 3.0f, 0.0f, 0.f}, up, { 1.0f, 1.0f}},
8846 {{ 1.0f, 0.0f, 0.f}, up, { 0.1f, 0.2f}},
8848 const UINT num_vertices19 = ARRAY_SIZE(vertices19);
8849 const UINT num_faces19 = ARRAY_SIZE(vertices19) / VERTS_PER_FACE;
8850 const UINT vertex_size19 = sizeof(*vertices19);
8851 const struct vertex_pntc exp_vertices19[] =
8853 {{ 0.0f, 3.0f, 0.f}, up, zero_vec2},
8854 {{ 2.0f, 3.0f, 0.f}, up, zero_vec2},
8855 {{ 0.0f, 0.0f, 0.f}, up, zero_vec2},
8857 {{ 3.0f, 3.0f, 0.f}, up, zero_vec2},
8858 {{ 3.0f, 0.0f, 0.f}, up, zero_vec2},
8859 {{ 1.0f, 0.0f, 0.f}, up, zero_vec2},
8861 const UINT exp_vertex_size19 = sizeof(*exp_vertices19);
8862 /* Test 20. Another test that data is lost if usage index changes, e.g.
8863 * TEXCOORD1 to TEXCOORD0. */
8864 const struct vertex_pntc vertices20[] =
8866 {{ 0.0f, 3.0f, 0.f}, up, { 1.0f, 1.0f}},
8867 {{ 2.0f, 3.0f, 0.f}, up, { 0.5f, 0.7f}},
8868 {{ 0.0f, 0.0f, 0.f}, up, {-0.2f, -0.3f}},
8870 {{ 3.0f, 3.0f, 0.f}, up, { 0.2f, 0.3f}},
8871 {{ 3.0f, 0.0f, 0.f}, up, { 1.0f, 1.0f}},
8872 {{ 1.0f, 0.0f, 0.f}, up, { 0.1f, 0.2f}},
8874 const UINT num_vertices20 = ARRAY_SIZE(vertices20);
8875 const UINT num_faces20 = ARRAY_SIZE(vertices20) / VERTS_PER_FACE;
8876 const UINT vertex_size20 = sizeof(*vertices20);
8877 const struct vertex_pntc exp_vertices20[] =
8879 {{ 0.0f, 3.0f, 0.f}, up, zero_vec2},
8880 {{ 2.0f, 3.0f, 0.f}, up, zero_vec2},
8881 {{ 0.0f, 0.0f, 0.f}, up, zero_vec2},
8883 {{ 3.0f, 3.0f, 0.f}, up, zero_vec2},
8884 {{ 3.0f, 0.0f, 0.f}, up, zero_vec2},
8885 {{ 1.0f, 0.0f, 0.f}, up, zero_vec2},
8887 const UINT exp_vertex_size20 = sizeof(*exp_vertices20);
8888 /* Test 21. Convert FLOAT1 to FLOAT2. */
8889 const struct vertex_ptc_float1 vertices21[] =
8891 {{ 0.0f, 3.0f, 0.f}, 1.0f},
8892 {{ 2.0f, 3.0f, 0.f}, 0.5f},
8893 {{ 0.0f, 0.0f, 0.f}, -0.2f},
8895 {{ 3.0f, 3.0f, 0.f}, 0.2f},
8896 {{ 3.0f, 0.0f, 0.f}, 1.0f},
8897 {{ 1.0f, 0.0f, 0.f}, 0.1f},
8899 const UINT num_vertices21 = ARRAY_SIZE(vertices21);
8900 const UINT num_faces21 = ARRAY_SIZE(vertices21) / VERTS_PER_FACE;
8901 const UINT vertex_size21 = sizeof(*vertices21);
8902 const struct vertex_ptc exp_vertices21[] =
8904 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 0.0f}},
8905 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.0f}},
8906 {{ 0.0f, 0.0f, 0.f}, {-0.2f, 0.0f}},
8908 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.0f}},
8909 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 0.0f}},
8910 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.0f}},
8912 const UINT exp_vertex_size21 = sizeof(*exp_vertices21);
8913 /* Test 22. Convert FLOAT1 to FLOAT3. */
8914 const struct vertex_ptc_float1 vertices22[] =
8916 {{ 0.0f, 3.0f, 0.f}, 1.0f},
8917 {{ 2.0f, 3.0f, 0.f}, 0.5f},
8918 {{ 0.0f, 0.0f, 0.f}, -0.2f},
8920 {{ 3.0f, 3.0f, 0.f}, 0.2f},
8921 {{ 3.0f, 0.0f, 0.f}, 1.0f},
8922 {{ 1.0f, 0.0f, 0.f}, 0.1f},
8924 const UINT num_vertices22 = ARRAY_SIZE(vertices22);
8925 const UINT num_faces22 = ARRAY_SIZE(vertices22) / VERTS_PER_FACE;
8926 const UINT vertex_size22 = sizeof(*vertices22);
8927 const struct vertex_ptc_float3 exp_vertices22[] =
8929 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 0.0f, 0.0f}},
8930 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.0f, 0.0f}},
8931 {{ 0.0f, 0.0f, 0.f}, {-0.2f, 0.0f, 0.0f}},
8933 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.0f, 0.0f}},
8934 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 0.0f, 0.0f}},
8935 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.0f, 0.0f}},
8937 const UINT exp_vertex_size22 = sizeof(*exp_vertices22);
8938 /* Test 23. Convert FLOAT1 to FLOAT4. */
8939 const struct vertex_ptc_float1 vertices23[] =
8941 {{ 0.0f, 3.0f, 0.f}, 1.0f},
8942 {{ 2.0f, 3.0f, 0.f}, 0.5f},
8943 {{ 0.0f, 0.0f, 0.f}, -0.2f},
8945 {{ 3.0f, 3.0f, 0.f}, 0.2f},
8946 {{ 3.0f, 0.0f, 0.f}, 1.0f},
8947 {{ 1.0f, 0.0f, 0.f}, 0.1f},
8949 const UINT num_vertices23 = ARRAY_SIZE(vertices23);
8950 const UINT num_faces23 = ARRAY_SIZE(vertices23) / VERTS_PER_FACE;
8951 const UINT vertex_size23 = sizeof(*vertices23);
8952 const struct vertex_ptc_float4 exp_vertices23[] =
8954 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 0.0f, 0.0f, 1.0f}},
8955 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.0f, 0.0f, 1.0f}},
8956 {{ 0.0f, 0.0f, 0.f}, {-0.2f, 0.0f, 0.0f, 1.0f}},
8958 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.0f, 0.0f, 1.0f}},
8959 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 0.0f, 0.0f, 1.0f}},
8960 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.0f, 0.0f, 1.0f}},
8962 const UINT exp_vertex_size23 = sizeof(*exp_vertices23);
8963 /* Test 24. Convert FLOAT1 to D3DCOLOR. */
8964 const struct vertex_ptc_float1 vertices24[] =
8966 {{ 0.0f, 3.0f, 0.f}, 1.0f},
8967 {{ 2.0f, 3.0f, 0.f}, 0.5f},
8968 {{ 0.0f, 0.0f, 0.f}, -0.2f},
8970 {{ 3.0f, 3.0f, 0.f}, 0.2f},
8971 {{ 3.0f, 0.0f, 0.f}, 1.0f},
8972 {{ 1.0f, 0.0f, 0.f}, 0.11f},
8974 const UINT num_vertices24 = ARRAY_SIZE(vertices24);
8975 const UINT num_faces24 = ARRAY_SIZE(vertices24) / VERTS_PER_FACE;
8976 const UINT vertex_size24 = sizeof(*vertices24);
8977 const struct vertex_ptc_d3dcolor exp_vertices24[] =
8979 {{ 0.0f, 3.0f, 0.f}, {0, 0, 255, 255}},
8980 {{ 2.0f, 3.0f, 0.f}, {0, 0, 128, 255}},
8981 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 255}},
8983 {{ 3.0f, 3.0f, 0.f}, {0, 0, 51, 255}},
8984 {{ 3.0f, 0.0f, 0.f}, {0, 0, 255, 255}},
8985 {{ 1.0f, 0.0f, 0.f}, {0, 0, 28, 255}},
8987 const UINT exp_vertex_size24 = sizeof(*exp_vertices24);
8988 /* Test 25. Convert FLOAT1 to ubyte4. */
8989 const struct vertex_ptc_float1 vertices25[] =
8991 {{ 0.0f, 3.0f, 0.f}, 0.0f},
8992 {{ 2.0f, 3.0f, 0.f}, 1.4f},
8993 {{ 0.0f, 0.0f, 0.f}, 1.5f},
8995 {{ 3.0f, 3.0f, 0.f}, 255.0f},
8996 {{ 3.0f, 0.0f, 0.f}, 256.0f},
8997 {{ 1.0f, 0.0f, 0.f}, -1.0f},
8999 const UINT num_vertices25 = ARRAY_SIZE(vertices25);
9000 const UINT num_faces25 = ARRAY_SIZE(vertices25) / VERTS_PER_FACE;
9001 const UINT vertex_size25 = sizeof(*vertices25);
9002 const struct vertex_ptc_ubyte4 exp_vertices25[] =
9004 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 1}},
9005 {{ 2.0f, 3.0f, 0.f}, {1, 0, 0, 1}},
9006 {{ 0.0f, 0.0f, 0.f}, {2, 0, 0, 1}},
9008 {{ 3.0f, 3.0f, 0.f}, {255, 0, 0, 1}},
9009 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 1}},
9010 {{ 1.0f, 0.0f, 0.f}, {0, 0, 0, 1}},
9012 const UINT exp_vertex_size25 = sizeof(*exp_vertices25);
9013 /* Test 26. Convert FLOAT4 to D3DCOLOR. */
9014 const struct vertex_ptc_float4 vertices26[] =
9016 {{ 0.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.4f, 0.5f}},
9017 {{ 2.0f, 3.0f, 0.f}, {-0.4f, -0.5f, -1.0f, -2.0f}},
9018 {{ 0.0f, 0.0f, 0.f}, {254.0f, 255.0f, 256.0f, 257.0f}},
9020 {{ 3.0f, 3.0f, 0.f}, {0.1f, 0.2f, 0.3f, 0.4f}},
9021 {{ 3.0f, 0.0f, 0.f}, {0.5f, 0.6f, 0.7f, 0.8f}},
9022 {{ 1.0f, 0.0f, 0.f}, {0.9f, 0.99f, 0.995f, 0.999f}},
9024 const UINT num_vertices26 = ARRAY_SIZE(vertices26);
9025 const UINT num_faces26 = ARRAY_SIZE(vertices26) / VERTS_PER_FACE;
9026 const UINT vertex_size26 = sizeof(*vertices26);
9027 const struct vertex_ptc_d3dcolor exp_vertices26[] =
9029 {{ 0.0f, 3.0f, 0.f}, {102, 255, 0, 128}},
9030 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9031 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
9033 {{ 3.0f, 3.0f, 0.f}, {77, 51, 26, 102}},
9034 {{ 3.0f, 0.0f, 0.f}, {179, 153, 128, 204}},
9035 {{ 1.0f, 0.0f, 0.f}, {254, 252, 230, 255}},
9037 const UINT exp_vertex_size26 = sizeof(*exp_vertices26);
9038 /* Test 27. Convert D3DCOLOR to FLOAT4. */
9039 const struct vertex_ptc_d3dcolor vertices27[] =
9041 {{ 0.0f, 3.0f, 0.f}, {102, 255, 0, 128}},
9042 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9043 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
9045 {{ 3.0f, 3.0f, 0.f}, {77, 51, 26, 102}},
9046 {{ 3.0f, 0.0f, 0.f}, {179, 153, 128, 204}},
9047 {{ 1.0f, 0.0f, 0.f}, {254, 252, 230, 255}},
9049 const UINT num_vertices27 = ARRAY_SIZE(vertices27);
9050 const UINT num_faces27 = ARRAY_SIZE(vertices27) / VERTS_PER_FACE;
9051 const UINT vertex_size27 = sizeof(*vertices27);
9052 const struct vertex_ptc_float4 exp_vertices27[] =
9054 {{ 0.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.4f, 0.501961f}},
9055 {{ 2.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9056 {{ 0.0f, 0.0f, 0.f}, {1.0f, 1.0f, 1.0f, 1.0f}},
9058 {{ 3.0f, 3.0f, 0.f}, {0.101961f, 0.2f, 0.301961f, 0.4f}},
9059 {{ 3.0f, 0.0f, 0.f}, {0.501961f, 0.6f, 0.701961f, 0.8f}},
9060 {{ 1.0f, 0.0f, 0.f}, {0.901961f, 0.988235f, 0.996078f, 1.0f}},
9062 const UINT exp_vertex_size27 = sizeof(*exp_vertices27);
9063 /* Test 28. Convert UBYTE4 to FLOAT4. */
9064 const struct vertex_ptc_ubyte4 vertices28[] =
9066 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9067 {{ 2.0f, 3.0f, 0.f}, {1, 1, 1, 1}},
9068 {{ 0.0f, 0.0f, 0.f}, {1, 0, 1, 0}},
9070 {{ 3.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
9071 {{ 3.0f, 0.0f, 0.f}, {10, 20, 30, 40}},
9072 {{ 1.0f, 0.0f, 0.f}, {50, 60, 127, 255}},
9074 const UINT num_vertices28 = ARRAY_SIZE(vertices28);
9075 const UINT num_faces28 = ARRAY_SIZE(vertices28) / VERTS_PER_FACE;
9076 const UINT vertex_size28 = sizeof(*vertices28);
9077 const struct vertex_ptc_float4 exp_vertices28[] =
9079 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9080 {{ 2.0f, 3.0f, 0.f}, {1.0f, 1.0f, 1.0f, 1.0f}},
9081 {{ 0.0f, 0.0f, 0.f}, {1.0f, 0.0f, 1.0f, 0.0f}},
9083 {{ 3.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.0f, 1.0f}},
9084 {{ 3.0f, 0.0f, 0.f}, {10.0f, 20.0f, 30.0f, 40.0f}},
9085 {{ 1.0f, 0.0f, 0.f}, {50.0f, 60.0f, 127.0f, 255.0f}},
9087 const UINT exp_vertex_size28 = sizeof(*exp_vertices28);
9088 /* Test 29. Convert SHORT2 to FLOAT4. */
9089 const struct vertex_ptc_short2 vertices29[] =
9091 {{ 0.0f, 3.0f, 0.f}, {0, 0}},
9092 {{ 2.0f, 3.0f, 0.f}, {0, 1}},
9093 {{ 0.0f, 0.0f, 0.f}, {1, 0}},
9095 {{ 3.0f, 3.0f, 0.f}, {1, 1}},
9096 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MAX}},
9097 {{ 1.0f, 0.0f, 0.f}, {-42, 42}},
9099 const UINT num_vertices29 = ARRAY_SIZE(vertices29);
9100 const UINT num_faces29 = ARRAY_SIZE(vertices29) / VERTS_PER_FACE;
9101 const UINT vertex_size29 = sizeof(*vertices29);
9102 const struct vertex_ptc_float4 exp_vertices29[] =
9104 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 1.0f}},
9105 {{ 2.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.0f, 1.0f }},
9106 {{ 0.0f, 0.0f, 0.f}, {1.0f, 0.0f, 0.0f, 1.0f}},
9108 {{ 3.0f, 3.0f, 0.f}, {1.0f, 1.0f, 0.0f, 1.0f}},
9109 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MAX, 0.0f, 1.0f}},
9110 {{ 1.0f, 0.0f, 0.f}, {-42.0f, 42.0f, 0.0f, 1.0f}},
9112 const UINT exp_vertex_size29 = sizeof(*exp_vertices29);
9113 /* Test 29. Convert SHORT4 to FLOAT4. */
9114 const struct vertex_ptc_short4 vertices30[] =
9116 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9117 {{ 2.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
9118 {{ 0.0f, 0.0f, 0.f}, {1, 0, 1, 0}},
9120 {{ 3.0f, 3.0f, 0.f}, {1, 1, 1, 1}},
9121 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MAX, 1, 0}},
9122 {{ 1.0f, 0.0f, 0.f}, {-42, 42, SHRT_MAX, SHRT_MIN}},
9124 const UINT num_vertices30 = ARRAY_SIZE(vertices30);
9125 const UINT num_faces30 = ARRAY_SIZE(vertices30) / VERTS_PER_FACE;
9126 const UINT vertex_size30 = sizeof(*vertices30);
9127 const struct vertex_ptc_float4 exp_vertices30[] =
9129 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9130 {{ 2.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.0f, 1.0f }},
9131 {{ 0.0f, 0.0f, 0.f}, {1.0f, 0.0f, 1.0f, 0.0f}},
9133 {{ 3.0f, 3.0f, 0.f}, {1.0f, 1.0f, 1.0f, 1.0f}},
9134 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MAX, 1.0f, 0.0f}},
9135 {{ 1.0f, 0.0f, 0.f}, {-42.0f, 42.0f, SHRT_MAX, SHRT_MIN}},
9137 const UINT exp_vertex_size30 = sizeof(*exp_vertices30);
9138 /* Test 31. Convert UBYTE4N to FLOAT4. */
9139 const struct vertex_ptc_ubyte4n vertices31[] =
9141 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9142 {{ 2.0f, 3.0f, 0.f}, {1, 1, 1, 1}},
9143 {{ 0.0f, 0.0f, 0.f}, {1, 0, 1, 0}},
9145 {{ 3.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
9146 {{ 3.0f, 0.0f, 0.f}, {10, 20, 30, 40}},
9147 {{ 1.0f, 0.0f, 0.f}, {50, 60, 70, UCHAR_MAX}},
9149 const UINT num_vertices31 = ARRAY_SIZE(vertices31);
9150 const UINT num_faces31 = ARRAY_SIZE(vertices31) / VERTS_PER_FACE;
9151 const UINT vertex_size31 = sizeof(*vertices31);
9152 const struct vertex_ptc_float4 exp_vertices31[] =
9154 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9155 {{ 2.0f, 3.0f, 0.f}, {(FLOAT)1/UCHAR_MAX, (FLOAT)1/UCHAR_MAX, (FLOAT)1/UCHAR_MAX, (FLOAT)1/UCHAR_MAX}},
9156 {{ 0.0f, 0.0f, 0.f}, {(FLOAT)1/UCHAR_MAX, 0.0f, (FLOAT)1/UCHAR_MAX, 0.0f}},
9158 {{ 3.0f, 3.0f, 0.f}, {0.0f, (FLOAT)1/UCHAR_MAX, 0.0f, (FLOAT)1/UCHAR_MAX}},
9159 {{ 3.0f, 0.0f, 0.f}, {(FLOAT)10/UCHAR_MAX, (FLOAT)20/UCHAR_MAX, (FLOAT)30/UCHAR_MAX, (FLOAT)40/UCHAR_MAX}},
9160 {{ 1.0f, 0.0f, 0.f}, {(FLOAT)50/UCHAR_MAX, (FLOAT)60/UCHAR_MAX, (FLOAT)70/UCHAR_MAX, 1.0f}},
9162 const UINT exp_vertex_size31 = sizeof(*exp_vertices31);
9163 /* Test 32. Convert SHORT2N to FLOAT4. */
9164 const struct vertex_ptc_short2 vertices32[] =
9166 {{ 0.0f, 3.0f, 0.f}, {0, 0}},
9167 {{ 2.0f, 3.0f, 0.f}, {0, 1}},
9168 {{ 0.0f, 0.0f, 0.f}, {1, 0}},
9170 {{ 3.0f, 3.0f, 0.f}, {1, 1}},
9171 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN + 1, SHRT_MAX}},
9172 {{ 1.0f, 0.0f, 0.f}, {-42, 42}},
9174 const UINT num_vertices32 = ARRAY_SIZE(vertices32);
9175 const UINT num_faces32 = ARRAY_SIZE(vertices32) / VERTS_PER_FACE;
9176 const UINT vertex_size32 = sizeof(*vertices32);
9177 const struct vertex_ptc_float4 exp_vertices32[] =
9179 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 1.0f}},
9180 {{ 2.0f, 3.0f, 0.f}, {0.0f, 1.0f/SHRT_MAX, 0.0f, 1.0f}},
9181 {{ 0.0f, 0.0f, 0.f}, {1.0f/SHRT_MAX, 0.0f, 0.0f, 1.0f}},
9183 {{ 3.0f, 3.0f, 0.f}, {1.0f/SHRT_MAX, 1.0f/SHRT_MAX, 0.0f, 1.0f}},
9184 {{ 3.0f, 0.0f, 0.f}, {-1.0f, 1.0f, 0.0f, 1.0f}},
9185 {{ 1.0f, 0.0f, 0.f}, {-42.0f/SHRT_MAX, 42.0f/SHRT_MAX, 0.0f, 1.0f}},
9187 const UINT exp_vertex_size32 = sizeof(*exp_vertices32);
9188 /* Test 33. Convert SHORT4N to FLOAT4. */
9189 const struct vertex_ptc_short4 vertices33[] =
9191 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9192 {{ 2.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
9193 {{ 0.0f, 0.0f, 0.f}, {1, 0, 1, 0}},
9195 {{ 3.0f, 3.0f, 0.f}, {1, 1, 1, 1}},
9196 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN + 1, SHRT_MAX, SHRT_MIN + 1, SHRT_MAX}},
9197 {{ 1.0f, 0.0f, 0.f}, {-42, 42, 1, 1}},
9199 const UINT num_vertices33 = ARRAY_SIZE(vertices33);
9200 const UINT num_faces33 = ARRAY_SIZE(vertices33) / VERTS_PER_FACE;
9201 const UINT vertex_size33 = sizeof(*vertices33);
9202 const struct vertex_ptc_float4 exp_vertices33[] =
9204 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9205 {{ 2.0f, 3.0f, 0.f}, {0.0f, 1.0f/SHRT_MAX, 0.0f, 1.0f/SHRT_MAX}},
9206 {{ 0.0f, 0.0f, 0.f}, {1.0f/SHRT_MAX, 0.0f, 1.0f/SHRT_MAX, 0.0f}},
9208 {{ 3.0f, 3.0f, 0.f}, {1.0f/SHRT_MAX, 1.0f/SHRT_MAX, 1.0f/SHRT_MAX, 1.0f/SHRT_MAX}},
9209 {{ 3.0f, 0.0f, 0.f}, {-1.0f, 1.0f, -1.0f, 1.0f}},
9210 {{ 1.0f, 0.0f, 0.f}, {-42.0f/SHRT_MAX, 42.0f/SHRT_MAX, 1.0f/SHRT_MAX, 1.0f/SHRT_MAX}},
9212 const UINT exp_vertex_size33 = sizeof(*exp_vertices33);
9213 /* Test 34. Convert FLOAT16_2 to FLOAT4. */
9214 const struct vertex_ptc_float16_2 vertices34[] =
9216 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
9217 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */
9218 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */
9220 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd}}, /* {0.2f, 0.3f} */
9221 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
9222 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */
9224 const UINT num_vertices34 = ARRAY_SIZE(vertices34);
9225 const UINT num_faces34 = ARRAY_SIZE(vertices34) / VERTS_PER_FACE;
9226 const UINT vertex_size34 = sizeof(*vertices34);
9227 const struct vertex_ptc_float4 exp_vertices34[] =
9229 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f, 0.0f, 1.0f}},
9230 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.700195f, 0.0f, 1.0f}},
9231 {{ 0.0f, 0.0f, 0.f}, {-0.199951f, -0.300049f, 0.0f, 1.0f}},
9233 {{ 3.0f, 3.0f, 0.f}, {0.199951f, 0.300049f, 0.0f, 1.0f}},
9234 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f, 0.0f, 1.0f}},
9235 {{ 1.0f, 0.0f, 0.f}, {0.099976f, 0.199951f, 0.0f, 1.0f}},
9237 const UINT exp_vertex_size34 = sizeof(*exp_vertices34);
9238 /* Test 35. Convert FLOAT16_4 to FLOAT4. */
9239 const struct vertex_ptc_float16_4 vertices35[] =
9241 {{ 0.0f, 3.0f, 0.f}, {0x0000, 0x0000, 0x0000, 0x0000}},
9242 {{ 2.0f, 3.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}},
9243 {{ 0.0f, 0.0f, 0.f}, {0x3c00, 0x0000, 0x3c00, 0x0000}},
9245 {{ 3.0f, 3.0f, 0.f}, {0x0000, 0x3c00, 0x0000, 0x3c00}},
9246 {{ 3.0f, 0.0f, 0.f}, {0x3800, 0x399a, 0xb266, 0xb4cd}},
9247 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266, 0x2e66, 0x3266}},
9249 const UINT num_vertices35 = ARRAY_SIZE(vertices35);
9250 const UINT num_faces35 = ARRAY_SIZE(vertices35) / VERTS_PER_FACE;
9251 const UINT vertex_size35 = sizeof(*vertices35);
9252 const struct vertex_ptc_float4 exp_vertices35[] =
9254 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9255 {{ 2.0f, 3.0f, 0.f}, {1.0f, 1.0f, 1.0f, 1.0f}},
9256 {{ 0.0f, 0.0f, 0.f}, {1.0f, 0.0f, 1.0f, 0.0f}},
9258 {{ 3.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.0f, 1.0f}},
9259 {{ 3.0f, 0.0f, 0.f}, {0.5f, 0.700195f, -0.199951f, -0.300049f}},
9260 {{ 1.0f, 0.0f, 0.f}, {0.099976f, 0.199951f, 0.099976f, 0.199951f}},
9262 const UINT exp_vertex_size35 = sizeof(*exp_vertices35);
9263 /* Test 36. Check that vertex buffer sharing is ok. */
9264 const struct vertex_pn vertices36[] =
9266 {{ 0.0f, 3.0f, 0.f}, up},
9267 {{ 2.0f, 3.0f, 0.f}, up},
9268 {{ 0.0f, 0.0f, 0.f}, up},
9270 const UINT num_vertices36 = ARRAY_SIZE(vertices36);
9271 const UINT num_faces36 = ARRAY_SIZE(vertices36) / VERTS_PER_FACE;
9272 const UINT vertex_size36 = sizeof(*vertices36);
9273 const DWORD clone_options36 = options | D3DXMESH_VB_SHARE;
9274 /* Common mesh data */
9275 ID3DXMesh *mesh = NULL;
9276 ID3DXMesh *mesh_clone = NULL;
9277 struct
9279 const BYTE *vertices;
9280 const DWORD *indices;
9281 const DWORD *attributes;
9282 const UINT num_vertices;
9283 const UINT num_faces;
9284 const UINT vertex_size;
9285 const DWORD create_options;
9286 const DWORD clone_options;
9287 D3DVERTEXELEMENT9 *declaration;
9288 D3DVERTEXELEMENT9 *new_declaration;
9289 const BYTE *exp_vertices;
9290 const UINT exp_vertex_size;
9292 tc[] =
9295 (BYTE*)vertices0,
9296 NULL,
9297 NULL,
9298 num_vertices0,
9299 num_faces0,
9300 vertex_size0,
9301 options,
9302 options,
9303 declaration_pn,
9304 declaration_pn,
9305 (BYTE*)vertices0,
9306 vertex_size0
9309 (BYTE*)vertices0,
9310 NULL,
9311 NULL,
9312 num_vertices0,
9313 num_faces0,
9314 vertex_size0,
9315 options_16bit,
9316 options_16bit,
9317 declaration_pn,
9318 declaration_pn,
9319 (BYTE*)vertices0,
9320 vertex_size0
9323 (BYTE*)vertices0,
9324 NULL,
9325 NULL,
9326 num_vertices0,
9327 num_faces0,
9328 vertex_size0,
9329 options,
9330 options,
9331 declaration_pn,
9332 declaration_pntc,
9333 (BYTE*)exp_vertices2,
9334 exp_vertex_size2
9337 (BYTE*)vertices0,
9338 NULL,
9339 NULL,
9340 num_vertices0,
9341 num_faces0,
9342 vertex_size0,
9343 options,
9344 options,
9345 declaration_pn,
9346 declaration_ptcn,
9347 (BYTE*)exp_vertices3,
9348 exp_vertex_size3
9351 (BYTE*)vertices4,
9352 NULL,
9353 NULL,
9354 num_vertices4,
9355 num_faces4,
9356 vertex_size4,
9357 options,
9358 options,
9359 declaration_ptc,
9360 declaration_ptc_float16_2,
9361 (BYTE*)exp_vertices4,
9362 exp_vertex_size4
9365 (BYTE*)vertices5,
9366 NULL,
9367 NULL,
9368 num_vertices5,
9369 num_faces5,
9370 vertex_size5,
9371 options,
9372 options,
9373 declaration_ptc,
9374 declaration_ptc_float16_4,
9375 (BYTE*)exp_vertices5,
9376 exp_vertex_size5
9379 (BYTE*)vertices6,
9380 NULL,
9381 NULL,
9382 num_vertices6,
9383 num_faces6,
9384 vertex_size6,
9385 options,
9386 options,
9387 declaration_ptc,
9388 declaration_ptc_float1,
9389 (BYTE*)exp_vertices6,
9390 exp_vertex_size6
9393 (BYTE*)vertices7,
9394 NULL,
9395 NULL,
9396 num_vertices7,
9397 num_faces7,
9398 vertex_size7,
9399 options,
9400 options,
9401 declaration_ptc,
9402 declaration_ptc_float3,
9403 (BYTE*)exp_vertices7,
9404 exp_vertex_size7
9407 (BYTE*)vertices8,
9408 NULL,
9409 NULL,
9410 num_vertices8,
9411 num_faces8,
9412 vertex_size8,
9413 options,
9414 options,
9415 declaration_ptc,
9416 declaration_ptc_float4,
9417 (BYTE*)exp_vertices8,
9418 exp_vertex_size8
9421 (BYTE*)vertices9,
9422 NULL,
9423 NULL,
9424 num_vertices9,
9425 num_faces9,
9426 vertex_size9,
9427 options,
9428 options,
9429 declaration_ptc,
9430 declaration_ptc_d3dcolor,
9431 (BYTE*)exp_vertices9,
9432 exp_vertex_size9
9435 (BYTE*)vertices10,
9436 NULL,
9437 NULL,
9438 num_vertices10,
9439 num_faces10,
9440 vertex_size10,
9441 options,
9442 options,
9443 declaration_ptc,
9444 declaration_ptc_ubyte4,
9445 (BYTE*)exp_vertices10,
9446 exp_vertex_size10
9449 (BYTE*)vertices11,
9450 NULL,
9451 NULL,
9452 num_vertices11,
9453 num_faces11,
9454 vertex_size11,
9455 options,
9456 options,
9457 declaration_ptc,
9458 declaration_ptc_short2,
9459 (BYTE*)exp_vertices11,
9460 exp_vertex_size11
9463 (BYTE*)vertices12,
9464 NULL,
9465 NULL,
9466 num_vertices12,
9467 num_faces12,
9468 vertex_size12,
9469 options,
9470 options,
9471 declaration_ptc,
9472 declaration_ptc_short4,
9473 (BYTE*)exp_vertices12,
9474 exp_vertex_size12
9477 (BYTE*)vertices13,
9478 NULL,
9479 NULL,
9480 num_vertices13,
9481 num_faces13,
9482 vertex_size13,
9483 options,
9484 options,
9485 declaration_ptc,
9486 declaration_ptc_ubyte4n,
9487 (BYTE*)exp_vertices13,
9488 exp_vertex_size13
9491 (BYTE*)vertices14,
9492 NULL,
9493 NULL,
9494 num_vertices14,
9495 num_faces14,
9496 vertex_size14,
9497 options,
9498 options,
9499 declaration_ptc,
9500 declaration_ptc_short2n,
9501 (BYTE*)exp_vertices14,
9502 exp_vertex_size14
9505 (BYTE*)vertices15,
9506 NULL,
9507 NULL,
9508 num_vertices15,
9509 num_faces15,
9510 vertex_size15,
9511 options,
9512 options,
9513 declaration_ptc,
9514 declaration_ptc_short4n,
9515 (BYTE*)exp_vertices15,
9516 exp_vertex_size15
9519 (BYTE*)vertices16,
9520 NULL,
9521 NULL,
9522 num_vertices16,
9523 num_faces16,
9524 vertex_size16,
9525 options,
9526 options,
9527 declaration_ptc,
9528 declaration_ptc_ushort2n,
9529 (BYTE*)exp_vertices16,
9530 exp_vertex_size16
9533 (BYTE*)vertices17,
9534 NULL,
9535 NULL,
9536 num_vertices17,
9537 num_faces17,
9538 vertex_size17,
9539 options,
9540 options,
9541 declaration_ptc,
9542 declaration_ptc_ushort4n,
9543 (BYTE*)exp_vertices17,
9544 exp_vertex_size17
9547 (BYTE*)vertices18,
9548 NULL,
9549 NULL,
9550 num_vertices18,
9551 num_faces18,
9552 vertex_size18,
9553 options,
9554 options,
9555 declaration_ptc,
9556 declaration_ptc_float16_2_partialu,
9557 (BYTE*)exp_vertices18,
9558 exp_vertex_size18
9561 (BYTE*)vertices19,
9562 NULL,
9563 NULL,
9564 num_vertices19,
9565 num_faces19,
9566 vertex_size19,
9567 options,
9568 options,
9569 declaration_pntc,
9570 declaration_pntc1,
9571 (BYTE*)exp_vertices19,
9572 exp_vertex_size19
9575 (BYTE*)vertices20,
9576 NULL,
9577 NULL,
9578 num_vertices20,
9579 num_faces20,
9580 vertex_size20,
9581 options,
9582 options,
9583 declaration_pntc1,
9584 declaration_pntc,
9585 (BYTE*)exp_vertices20,
9586 exp_vertex_size20
9589 (BYTE*)vertices21,
9590 NULL,
9591 NULL,
9592 num_vertices21,
9593 num_faces21,
9594 vertex_size21,
9595 options,
9596 options,
9597 declaration_ptc_float1,
9598 declaration_ptc,
9599 (BYTE*)exp_vertices21,
9600 exp_vertex_size21
9603 (BYTE*)vertices22,
9604 NULL,
9605 NULL,
9606 num_vertices22,
9607 num_faces22,
9608 vertex_size22,
9609 options,
9610 options,
9611 declaration_ptc_float1,
9612 declaration_ptc_float3,
9613 (BYTE*)exp_vertices22,
9614 exp_vertex_size22
9617 (BYTE*)vertices23,
9618 NULL,
9619 NULL,
9620 num_vertices23,
9621 num_faces23,
9622 vertex_size23,
9623 options,
9624 options,
9625 declaration_ptc_float1,
9626 declaration_ptc_float4,
9627 (BYTE*)exp_vertices23,
9628 exp_vertex_size23
9631 (BYTE*)vertices24,
9632 NULL,
9633 NULL,
9634 num_vertices24,
9635 num_faces24,
9636 vertex_size24,
9637 options,
9638 options,
9639 declaration_ptc_float1,
9640 declaration_ptc_d3dcolor,
9641 (BYTE*)exp_vertices24,
9642 exp_vertex_size24
9645 (BYTE*)vertices25,
9646 NULL,
9647 NULL,
9648 num_vertices25,
9649 num_faces25,
9650 vertex_size25,
9651 options,
9652 options,
9653 declaration_ptc_float1,
9654 declaration_ptc_ubyte4,
9655 (BYTE*)exp_vertices25,
9656 exp_vertex_size25
9659 (BYTE*)vertices26,
9660 NULL,
9661 NULL,
9662 num_vertices26,
9663 num_faces26,
9664 vertex_size26,
9665 options,
9666 options,
9667 declaration_ptc_float4,
9668 declaration_ptc_d3dcolor,
9669 (BYTE*)exp_vertices26,
9670 exp_vertex_size26
9673 (BYTE*)vertices27,
9674 NULL,
9675 NULL,
9676 num_vertices27,
9677 num_faces27,
9678 vertex_size27,
9679 options,
9680 options,
9681 declaration_ptc_d3dcolor,
9682 declaration_ptc_float4,
9683 (BYTE*)exp_vertices27,
9684 exp_vertex_size27
9687 (BYTE*)vertices28,
9688 NULL,
9689 NULL,
9690 num_vertices28,
9691 num_faces28,
9692 vertex_size28,
9693 options,
9694 options,
9695 declaration_ptc_ubyte4,
9696 declaration_ptc_float4,
9697 (BYTE*)exp_vertices28,
9698 exp_vertex_size28
9701 (BYTE*)vertices29,
9702 NULL,
9703 NULL,
9704 num_vertices29,
9705 num_faces29,
9706 vertex_size29,
9707 options,
9708 options,
9709 declaration_ptc_short2,
9710 declaration_ptc_float4,
9711 (BYTE*)exp_vertices29,
9712 exp_vertex_size29
9715 (BYTE*)vertices30,
9716 NULL,
9717 NULL,
9718 num_vertices30,
9719 num_faces30,
9720 vertex_size30,
9721 options,
9722 options,
9723 declaration_ptc_short4,
9724 declaration_ptc_float4,
9725 (BYTE*)exp_vertices30,
9726 exp_vertex_size30
9729 (BYTE*)vertices31,
9730 NULL,
9731 NULL,
9732 num_vertices31,
9733 num_faces31,
9734 vertex_size31,
9735 options,
9736 options,
9737 declaration_ptc_ubyte4n,
9738 declaration_ptc_float4,
9739 (BYTE*)exp_vertices31,
9740 exp_vertex_size31
9743 (BYTE*)vertices32,
9744 NULL,
9745 NULL,
9746 num_vertices32,
9747 num_faces32,
9748 vertex_size32,
9749 options,
9750 options,
9751 declaration_ptc_short2n,
9752 declaration_ptc_float4,
9753 (BYTE*)exp_vertices32,
9754 exp_vertex_size32
9757 (BYTE*)vertices33,
9758 NULL,
9759 NULL,
9760 num_vertices33,
9761 num_faces33,
9762 vertex_size33,
9763 options,
9764 options,
9765 declaration_ptc_short4n,
9766 declaration_ptc_float4,
9767 (BYTE*)exp_vertices33,
9768 exp_vertex_size33
9771 (BYTE*)vertices34,
9772 NULL,
9773 NULL,
9774 num_vertices34,
9775 num_faces34,
9776 vertex_size34,
9777 options,
9778 options,
9779 declaration_ptc_float16_2,
9780 declaration_ptc_float4,
9781 (BYTE*)exp_vertices34,
9782 exp_vertex_size34
9785 (BYTE*)vertices35,
9786 NULL,
9787 NULL,
9788 num_vertices35,
9789 num_faces35,
9790 vertex_size35,
9791 options,
9792 options,
9793 declaration_ptc_float16_4,
9794 declaration_ptc_float4,
9795 (BYTE*)exp_vertices35,
9796 exp_vertex_size35
9799 (BYTE*)vertices36,
9800 NULL,
9801 NULL,
9802 num_vertices36,
9803 num_faces36,
9804 vertex_size36,
9805 options,
9806 clone_options36,
9807 declaration_pn,
9808 declaration_pn,
9809 (BYTE*)vertices36,
9810 vertex_size36
9814 test_context = new_test_context();
9815 if (!test_context)
9817 skip("Couldn't create test context\n");
9818 goto cleanup;
9821 for (i = 0; i < ARRAY_SIZE(tc); i++)
9823 UINT j;
9824 D3DVERTEXELEMENT9 new_declaration[MAX_FVF_DECL_SIZE];
9825 UINT exp_new_decl_length, new_decl_length;
9826 UINT exp_new_decl_size, new_decl_size;
9828 hr = init_test_mesh(tc[i].num_faces, tc[i].num_vertices,
9829 tc[i].create_options,
9830 tc[i].declaration,
9831 test_context->device, &mesh,
9832 tc[i].vertices, tc[i].vertex_size,
9833 tc[i].indices, tc[i].attributes);
9834 if (FAILED(hr))
9836 skip("Couldn't initialize test mesh %d. Got %x expected D3D_OK\n", i, hr);
9837 goto cleanup;
9840 hr = mesh->lpVtbl->CloneMesh(mesh, tc[i].clone_options, tc[i].new_declaration,
9841 test_context->device, &mesh_clone);
9842 ok(hr == D3D_OK, "CloneMesh test case %d failed. Got %x\n, expected D3D_OK\n", i, hr);
9844 hr = mesh_clone->lpVtbl->GetDeclaration(mesh_clone, new_declaration);
9845 ok(hr == D3D_OK, "GetDeclaration test case %d failed. Got %x\n, expected D3D_OK\n", i, hr);
9846 /* Check declaration elements */
9847 for (j = 0; tc[i].new_declaration[j].Stream != 0xFF; j++)
9849 ok(memcmp(&tc[i].new_declaration[j], &new_declaration[j], sizeof(*new_declaration)) == 0,
9850 "Test case %d failed. Declaration element %d did not match.\n", i, j);
9853 /* Check declaration length */
9854 exp_new_decl_length = D3DXGetDeclLength(tc[i].new_declaration);
9855 new_decl_length = D3DXGetDeclLength(new_declaration);
9856 ok(new_decl_length == exp_new_decl_length,
9857 "Test case %d failed. Got new declaration length %d, expected %d\n",
9858 i, new_decl_length, exp_new_decl_length);
9860 /* Check declaration size */
9861 exp_new_decl_size = D3DXGetDeclVertexSize(tc[i].new_declaration, 0);
9862 new_decl_size = D3DXGetDeclVertexSize(new_declaration, 0);
9863 ok(new_decl_size == exp_new_decl_size,
9864 "Test case %d failed. Got new declaration size %d, expected %d\n",
9865 i, new_decl_size, exp_new_decl_size);
9867 /* Check vertex data in cloned mesh */
9868 hr = mesh_clone->lpVtbl->LockVertexBuffer(mesh_clone, 0, (void**)&vertices);
9869 if (FAILED(hr))
9871 skip("Couldn't lock cloned vertex buffer.\n");
9872 goto cleanup;
9874 for (j = 0; j < tc[i].num_vertices; j++)
9876 UINT index = tc[i].exp_vertex_size * j;
9877 check_vertex_components(__LINE__, i, j, &vertices[index], &tc[i].exp_vertices[index], tc[i].new_declaration);
9879 hr = mesh_clone->lpVtbl->UnlockVertexBuffer(mesh_clone);
9880 if (FAILED(hr))
9882 skip("Couldn't unlock vertex buffer.\n");
9883 goto cleanup;
9885 vertices = NULL;
9886 mesh->lpVtbl->Release(mesh);
9887 mesh = NULL;
9888 mesh_clone->lpVtbl->Release(mesh_clone);
9889 mesh_clone = NULL;
9892 /* The following test shows that it is not possible to share a vertex buffer
9893 * with D3DXMESH_VB_SHARE and change the vertex declaration at the same
9894 * time. It reuses the test data from test 2.
9896 hr = init_test_mesh(tc[2].num_faces, tc[2].num_vertices,
9897 tc[2].create_options,
9898 tc[2].declaration,
9899 test_context->device, &mesh,
9900 tc[2].vertices, tc[2].vertex_size,
9901 tc[2].indices, tc[2].attributes);
9902 if (FAILED(hr))
9904 skip("Couldn't initialize test mesh for D3DXMESH_VB_SHARE case."
9905 " Got %x expected D3D_OK\n", hr);
9906 goto cleanup;
9909 hr = mesh->lpVtbl->CloneMesh(mesh, tc[2].create_options | D3DXMESH_VB_SHARE,
9910 tc[2].new_declaration, test_context->device,
9911 &mesh_clone);
9912 ok(hr == D3DERR_INVALIDCALL, "CloneMesh D3DXMESH_VB_SHARE with new"
9913 " declaration. Got %x, expected D3DERR_INVALIDCALL\n",
9914 hr);
9915 mesh->lpVtbl->Release(mesh);
9916 mesh = NULL;
9917 mesh_clone = NULL;
9919 cleanup:
9920 if (vertices) mesh->lpVtbl->UnlockVertexBuffer(mesh);
9921 if (mesh) mesh->lpVtbl->Release(mesh);
9922 if (mesh_clone) mesh_clone->lpVtbl->Release(mesh_clone);
9923 free_test_context(test_context);
9926 static void test_valid_mesh(void)
9928 HRESULT hr;
9929 struct test_context *test_context = NULL;
9930 UINT i;
9931 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
9932 const D3DVERTEXELEMENT9 declaration[] =
9934 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
9935 D3DDECL_END()
9937 const unsigned int VERTS_PER_FACE = 3;
9938 /* mesh0 (one face)
9940 * 0--1
9941 * | /
9942 * |/
9945 const D3DXVECTOR3 vertices0[] =
9947 { 0.0f, 3.0f, 0.f},
9948 { 2.0f, 3.0f, 0.f},
9949 { 0.0f, 0.0f, 0.f},
9951 const DWORD indices0[] = {0, 1, 2};
9952 const unsigned int num_vertices0 = ARRAY_SIZE(vertices0);
9953 const unsigned int num_faces0 = ARRAY_SIZE(indices0) / VERTS_PER_FACE;
9954 const DWORD adjacency0[] = {-1, -1, -1};
9955 const HRESULT exp_hr0 = D3D_OK;
9956 /* mesh1 (Simple bow-tie)
9958 * 0--1 1--3
9959 * | / \ |
9960 * |/ \|
9961 * 2 4
9963 const D3DXVECTOR3 vertices1[] =
9965 { 0.0f, 3.0f, 0.f},
9966 { 2.0f, 3.0f, 0.f},
9967 { 0.0f, 0.0f, 0.f},
9969 { 4.0f, 3.0f, 0.f},
9970 { 4.0f, 0.0f, 0.f},
9972 const DWORD indices1[] = {0, 1, 2, 1, 3, 4};
9973 const unsigned int num_vertices1 = ARRAY_SIZE(vertices1);
9974 const unsigned int num_faces1 = ARRAY_SIZE(indices1) / VERTS_PER_FACE;
9975 const DWORD adjacency1[] = {-1, -1, -1, -1, -1, -1};
9976 const HRESULT exp_hr1 = D3DXERR_INVALIDMESH;
9977 /* Common mesh data */
9978 ID3DXMesh *mesh = NULL;
9979 UINT vertex_size = sizeof(D3DXVECTOR3);
9980 ID3DXBuffer *errors_and_warnings = NULL;
9981 struct
9983 const D3DXVECTOR3 *vertices;
9984 const DWORD *indices;
9985 const UINT num_vertices;
9986 const UINT num_faces;
9987 const DWORD *adjacency;
9988 const HRESULT exp_hr;
9990 tc[] =
9993 vertices0,
9994 indices0,
9995 num_vertices0,
9996 num_faces0,
9997 adjacency0,
9998 exp_hr0,
10001 vertices1,
10002 indices1,
10003 num_vertices1,
10004 num_faces1,
10005 adjacency1,
10006 exp_hr1,
10010 test_context = new_test_context();
10011 if (!test_context)
10013 skip("Couldn't create test context\n");
10014 goto cleanup;
10017 for (i = 0; i < ARRAY_SIZE(tc); i++)
10019 hr = init_test_mesh(tc[i].num_faces, tc[i].num_vertices,
10020 options, declaration,
10021 test_context->device, &mesh,
10022 tc[i].vertices, vertex_size,
10023 tc[i].indices, NULL);
10024 if (FAILED(hr))
10026 skip("Couldn't initialize test mesh %d. Got %x expected D3D_OK\n", i, hr);
10027 goto cleanup;
10030 hr = D3DXValidMesh(mesh, tc[i].adjacency, &errors_and_warnings);
10031 todo_wine ok(hr == tc[i].exp_hr, "D3DXValidMesh test case %d failed. "
10032 "Got %x\n, expected %x\n", i, hr, tc[i].exp_hr);
10034 /* Note errors_and_warnings is deliberately not checked because that
10035 * would require copying wast amounts of the text output. */
10036 if (errors_and_warnings)
10038 ID3DXBuffer_Release(errors_and_warnings);
10039 errors_and_warnings = NULL;
10041 mesh->lpVtbl->Release(mesh);
10042 mesh = NULL;
10045 cleanup:
10046 if (mesh) mesh->lpVtbl->Release(mesh);
10047 free_test_context(test_context);
10050 static void test_optimize_faces(void)
10052 HRESULT hr;
10053 UINT i;
10054 DWORD smallest_face_remap;
10055 /* mesh0
10057 * 0--1
10058 * | /
10059 * |/
10062 const DWORD indices0[] = {0, 1, 2};
10063 const UINT num_faces0 = 1;
10064 const UINT num_vertices0 = 3;
10065 const DWORD exp_face_remap0[] = {0};
10066 /* mesh1
10068 * 0--1 3
10069 * | / /|
10070 * |/ / |
10071 * 2 5--4
10073 const DWORD indices1[] = {0, 1, 2, 3, 4, 5};
10074 const UINT num_faces1 = 2;
10075 const UINT num_vertices1 = 6;
10076 const DWORD exp_face_remap1[] = {1, 0};
10077 /* mesh2
10079 * 0--1
10080 * | /|
10081 * |/ |
10082 * 2--3
10084 const DWORD indices2[] = {0, 1, 2, 1, 3, 2};
10085 const UINT num_faces2 = 2;
10086 const UINT num_vertices2 = 4;
10087 const DWORD exp_face_remap2[] = {1, 0};
10088 /* mesh3
10090 * 0--1
10091 * | /|
10092 * |/ |
10093 * 2--3
10094 * | /|
10095 * |/ |
10096 * 4--5
10098 const DWORD indices3[] = {0, 1, 2, 1, 3, 2, 2, 3, 4, 3, 4, 5};
10099 const UINT num_faces3 = 4;
10100 const UINT num_vertices3 = 6;
10101 const DWORD exp_face_remap3[] = {3, 2, 1, 0};
10102 /* mesh4
10104 * 0--1
10105 * | /|
10106 * |/ |
10107 * 2--3
10108 * | /|
10109 * |/ |
10110 * 4--5
10112 const WORD indices4[] = {0, 1, 2, 1, 3, 2, 2, 3, 4, 3, 4, 5};
10113 const UINT num_faces4 = 4;
10114 const UINT num_vertices4 = 6;
10115 const DWORD exp_face_remap4[] = {3, 2, 1, 0};
10116 /* Test cases are stored in the tc array */
10117 struct
10119 const VOID *indices;
10120 const UINT num_faces;
10121 const UINT num_vertices;
10122 const BOOL indices_are_32bit;
10123 const DWORD *exp_face_remap;
10125 tc[] =
10128 indices0,
10129 num_faces0,
10130 num_vertices0,
10131 TRUE,
10132 exp_face_remap0
10135 indices1,
10136 num_faces1,
10137 num_vertices1,
10138 TRUE,
10139 exp_face_remap1
10142 indices2,
10143 num_faces2,
10144 num_vertices2,
10145 TRUE,
10146 exp_face_remap2
10149 indices3,
10150 num_faces3,
10151 num_vertices3,
10152 TRUE,
10153 exp_face_remap3
10156 indices4,
10157 num_faces4,
10158 num_vertices4,
10159 FALSE,
10160 exp_face_remap4
10164 /* Go through all test cases */
10165 for (i = 0; i < ARRAY_SIZE(tc); i++)
10167 DWORD j;
10168 DWORD *face_remap;
10169 face_remap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
10170 tc[i].num_faces*sizeof(face_remap));
10172 hr = D3DXOptimizeFaces(tc[i].indices, tc[i].num_faces,
10173 tc[i].num_vertices, tc[i].indices_are_32bit,
10174 face_remap);
10175 ok(hr == D3D_OK, "D3DXOptimizeFaces test case %d failed. "
10176 "Got %x\n, expected D3D_OK", i, hr);
10178 /* Compare face remap with expected face remap */
10179 for (j = 0; j < tc[i].num_faces; j++)
10181 ok(tc[i].exp_face_remap[j] == face_remap[j],
10182 "Test case %d: Got face %d at %d, expected %d\n", i,
10183 face_remap[j], j, tc[i].exp_face_remap[j]);
10186 HeapFree(GetProcessHeap(), 0, face_remap);
10189 /* face_remap must not be NULL */
10190 hr = D3DXOptimizeFaces(tc[0].indices, tc[0].num_faces,
10191 tc[0].num_vertices, tc[0].indices_are_32bit,
10192 NULL);
10193 ok(hr == D3DERR_INVALIDCALL, "D3DXOptimizeFaces passed NULL face_remap "
10194 "pointer. Got %x\n, expected D3DERR_INVALIDCALL\n", hr);
10196 /* Number of faces must be smaller than 2^15 */
10197 hr = D3DXOptimizeFaces(tc[0].indices, 2 << 15,
10198 tc[0].num_vertices, FALSE,
10199 &smallest_face_remap);
10200 ok(hr == D3DERR_INVALIDCALL, "D3DXOptimizeFaces should not accept 2^15 "
10201 "faces when using 16-bit indices. Got %x\n, expected D3DERR_INVALIDCALL\n", hr);
10204 START_TEST(mesh)
10206 D3DXBoundProbeTest();
10207 D3DXComputeBoundingBoxTest();
10208 D3DXComputeBoundingSphereTest();
10209 D3DXGetFVFVertexSizeTest();
10210 D3DXIntersectTriTest();
10211 D3DXCreateMeshTest();
10212 D3DXCreateMeshFVFTest();
10213 D3DXLoadMeshTest();
10214 D3DXCreateBoxTest();
10215 D3DXCreateSphereTest();
10216 D3DXCreateCylinderTest();
10217 D3DXCreateTextTest();
10218 test_get_decl_length();
10219 test_get_decl_vertex_size();
10220 test_fvf_decl_conversion();
10221 D3DXGenerateAdjacencyTest();
10222 test_update_semantics();
10223 test_create_skin_info();
10224 test_convert_adjacency_to_point_reps();
10225 test_convert_point_reps_to_adjacency();
10226 test_weld_vertices();
10227 test_clone_mesh();
10228 test_valid_mesh();
10229 test_optimize_faces();