po: Update Swedish translation.
[wine/wine-gecko.git] / dlls / d3dx9_36 / tests / mesh.c
blob390197deb6a0e4ee7ef1d8daa91c223170192fb3
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 = D3DXCreateBuffer(36 * sizeof(DWORD), &ppBuffer);
2475 ok(hr==D3D_OK, "Expected D3D_OK, received %#x\n", hr);
2476 if (FAILED(hr)) goto end;
2478 hr = D3DXCreateBox(device,2.0f,20.0f,4.9f,NULL, &ppBuffer);
2479 todo_wine ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2481 hr = D3DXCreateBox(NULL,22.0f,20.0f,4.9f,&box, &ppBuffer);
2482 todo_wine ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2484 hr = D3DXCreateBox(device,-2.0f,20.0f,4.9f,&box, &ppBuffer);
2485 todo_wine ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2487 hr = D3DXCreateBox(device,22.0f,-20.0f,4.9f,&box, &ppBuffer);
2488 todo_wine ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2490 hr = D3DXCreateBox(device,22.0f,20.0f,-4.9f,&box, &ppBuffer);
2491 todo_wine ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2493 hr = D3DXCreateBox(device,10.9f,20.0f,4.9f,&box, &ppBuffer);
2494 todo_wine ok(hr==D3D_OK, "Expected D3D_OK, received %#x\n", hr);
2496 if (FAILED(hr))
2498 skip("D3DXCreateBox failed\n");
2499 goto end;
2502 buffer = ID3DXBuffer_GetBufferPointer(ppBuffer);
2503 for(i=0; i<36; i++)
2504 todo_wine ok(adjacency[i]==buffer[i], "expected adjacency %d: %#x, received %#x\n",i,adjacency[i], buffer[i]);
2506 box->lpVtbl->Release(box);
2508 end:
2509 IDirect3DDevice9_Release(device);
2510 IDirect3D9_Release(d3d);
2511 ID3DXBuffer_Release(ppBuffer);
2512 DestroyWindow(wnd);
2515 struct sincos_table
2517 float *sin;
2518 float *cos;
2521 static void free_sincos_table(struct sincos_table *sincos_table)
2523 HeapFree(GetProcessHeap(), 0, sincos_table->cos);
2524 HeapFree(GetProcessHeap(), 0, sincos_table->sin);
2527 /* pre compute sine and cosine tables; caller must free */
2528 static BOOL compute_sincos_table(struct sincos_table *sincos_table, float angle_start, float angle_step, int n)
2530 float angle;
2531 int i;
2533 sincos_table->sin = HeapAlloc(GetProcessHeap(), 0, n * sizeof(*sincos_table->sin));
2534 if (!sincos_table->sin)
2536 return FALSE;
2538 sincos_table->cos = HeapAlloc(GetProcessHeap(), 0, n * sizeof(*sincos_table->cos));
2539 if (!sincos_table->cos)
2541 HeapFree(GetProcessHeap(), 0, sincos_table->sin);
2542 return FALSE;
2545 angle = angle_start;
2546 for (i = 0; i < n; i++)
2548 sincos_table->sin[i] = sin(angle);
2549 sincos_table->cos[i] = cos(angle);
2550 angle += angle_step;
2553 return TRUE;
2556 static WORD vertex_index(UINT slices, int slice, int stack)
2558 return stack*slices+slice+1;
2561 /* slices = subdivisions along xy plane, stacks = subdivisions along z axis */
2562 static BOOL compute_sphere(struct mesh *mesh, FLOAT radius, UINT slices, UINT stacks)
2564 float theta_step, theta_start;
2565 struct sincos_table theta;
2566 float phi_step, phi_start;
2567 struct sincos_table phi;
2568 DWORD number_of_vertices, number_of_faces;
2569 DWORD vertex, face;
2570 int slice, stack;
2572 /* theta = angle on xy plane wrt x axis */
2573 theta_step = M_PI / stacks;
2574 theta_start = theta_step;
2576 /* phi = angle on xz plane wrt z axis */
2577 phi_step = -2 * M_PI / slices;
2578 phi_start = M_PI / 2;
2580 if (!compute_sincos_table(&theta, theta_start, theta_step, stacks))
2582 return FALSE;
2584 if (!compute_sincos_table(&phi, phi_start, phi_step, slices))
2586 free_sincos_table(&theta);
2587 return FALSE;
2590 number_of_vertices = 2 + slices * (stacks-1);
2591 number_of_faces = 2 * slices + (stacks - 2) * (2 * slices);
2593 if (!new_mesh(mesh, number_of_vertices, number_of_faces))
2595 free_sincos_table(&phi);
2596 free_sincos_table(&theta);
2597 return FALSE;
2600 vertex = 0;
2601 face = 0;
2603 mesh->vertices[vertex].normal.x = 0.0f;
2604 mesh->vertices[vertex].normal.y = 0.0f;
2605 mesh->vertices[vertex].normal.z = 1.0f;
2606 mesh->vertices[vertex].position.x = 0.0f;
2607 mesh->vertices[vertex].position.y = 0.0f;
2608 mesh->vertices[vertex].position.z = radius;
2609 vertex++;
2611 for (stack = 0; stack < stacks - 1; stack++)
2613 for (slice = 0; slice < slices; slice++)
2615 mesh->vertices[vertex].normal.x = theta.sin[stack] * phi.cos[slice];
2616 mesh->vertices[vertex].normal.y = theta.sin[stack] * phi.sin[slice];
2617 mesh->vertices[vertex].normal.z = theta.cos[stack];
2618 mesh->vertices[vertex].position.x = radius * theta.sin[stack] * phi.cos[slice];
2619 mesh->vertices[vertex].position.y = radius * theta.sin[stack] * phi.sin[slice];
2620 mesh->vertices[vertex].position.z = radius * theta.cos[stack];
2621 vertex++;
2623 if (slice > 0)
2625 if (stack == 0)
2627 /* top stack is triangle fan */
2628 mesh->faces[face][0] = 0;
2629 mesh->faces[face][1] = slice + 1;
2630 mesh->faces[face][2] = slice;
2631 face++;
2633 else
2635 /* stacks in between top and bottom are quad strips */
2636 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
2637 mesh->faces[face][1] = vertex_index(slices, slice, stack-1);
2638 mesh->faces[face][2] = vertex_index(slices, slice-1, stack);
2639 face++;
2641 mesh->faces[face][0] = vertex_index(slices, slice, stack-1);
2642 mesh->faces[face][1] = vertex_index(slices, slice, stack);
2643 mesh->faces[face][2] = vertex_index(slices, slice-1, stack);
2644 face++;
2649 if (stack == 0)
2651 mesh->faces[face][0] = 0;
2652 mesh->faces[face][1] = 1;
2653 mesh->faces[face][2] = slice;
2654 face++;
2656 else
2658 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
2659 mesh->faces[face][1] = vertex_index(slices, 0, stack-1);
2660 mesh->faces[face][2] = vertex_index(slices, slice-1, stack);
2661 face++;
2663 mesh->faces[face][0] = vertex_index(slices, 0, stack-1);
2664 mesh->faces[face][1] = vertex_index(slices, 0, stack);
2665 mesh->faces[face][2] = vertex_index(slices, slice-1, stack);
2666 face++;
2670 mesh->vertices[vertex].position.x = 0.0f;
2671 mesh->vertices[vertex].position.y = 0.0f;
2672 mesh->vertices[vertex].position.z = -radius;
2673 mesh->vertices[vertex].normal.x = 0.0f;
2674 mesh->vertices[vertex].normal.y = 0.0f;
2675 mesh->vertices[vertex].normal.z = -1.0f;
2677 /* bottom stack is triangle fan */
2678 for (slice = 1; slice < slices; slice++)
2680 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
2681 mesh->faces[face][1] = vertex_index(slices, slice, stack-1);
2682 mesh->faces[face][2] = vertex;
2683 face++;
2686 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
2687 mesh->faces[face][1] = vertex_index(slices, 0, stack-1);
2688 mesh->faces[face][2] = vertex;
2690 free_sincos_table(&phi);
2691 free_sincos_table(&theta);
2693 return TRUE;
2696 static void test_sphere(IDirect3DDevice9 *device, FLOAT radius, UINT slices, UINT stacks)
2698 HRESULT hr;
2699 ID3DXMesh *sphere;
2700 struct mesh mesh;
2701 char name[256];
2703 hr = D3DXCreateSphere(device, radius, slices, stacks, &sphere, NULL);
2704 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
2705 if (hr != D3D_OK)
2707 skip("Couldn't create sphere\n");
2708 return;
2711 if (!compute_sphere(&mesh, radius, slices, stacks))
2713 skip("Couldn't create mesh\n");
2714 sphere->lpVtbl->Release(sphere);
2715 return;
2718 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
2720 sprintf(name, "sphere (%g, %u, %u)", radius, slices, stacks);
2721 compare_mesh(name, sphere, &mesh);
2723 free_mesh(&mesh);
2725 sphere->lpVtbl->Release(sphere);
2728 static void D3DXCreateSphereTest(void)
2730 HRESULT hr;
2731 HWND wnd;
2732 IDirect3D9* d3d;
2733 IDirect3DDevice9* device;
2734 D3DPRESENT_PARAMETERS d3dpp;
2735 ID3DXMesh* sphere = NULL;
2737 hr = D3DXCreateSphere(NULL, 0.0f, 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.1f, 0, 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, 1, 0, NULL, NULL);
2744 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
2746 hr = D3DXCreateSphere(NULL, 0.0f, 0, 1, NULL, NULL);
2747 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
2749 wnd = CreateWindow("static", "d3dx9_test", 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL);
2750 d3d = Direct3DCreate9(D3D_SDK_VERSION);
2751 if (!wnd)
2753 skip("Couldn't create application window\n");
2754 return;
2756 if (!d3d)
2758 skip("Couldn't create IDirect3D9 object\n");
2759 DestroyWindow(wnd);
2760 return;
2763 ZeroMemory(&d3dpp, sizeof(d3dpp));
2764 d3dpp.Windowed = TRUE;
2765 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2766 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, wnd, D3DCREATE_MIXED_VERTEXPROCESSING, &d3dpp, &device);
2767 if (FAILED(hr))
2769 skip("Failed to create IDirect3DDevice9 object %#x\n", hr);
2770 IDirect3D9_Release(d3d);
2771 DestroyWindow(wnd);
2772 return;
2775 hr = D3DXCreateSphere(device, 1.0f, 1, 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, 2, 1, &sphere, NULL);
2779 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
2781 hr = D3DXCreateSphere(device, 1.0f, 1, 2, &sphere, NULL);
2782 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
2784 hr = D3DXCreateSphere(device, -0.1f, 1, 2, &sphere, NULL);
2785 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
2787 test_sphere(device, 0.0f, 2, 2);
2788 test_sphere(device, 1.0f, 2, 2);
2789 test_sphere(device, 1.0f, 3, 2);
2790 test_sphere(device, 1.0f, 4, 4);
2791 test_sphere(device, 1.0f, 3, 4);
2792 test_sphere(device, 5.0f, 6, 7);
2793 test_sphere(device, 10.0f, 11, 12);
2795 IDirect3DDevice9_Release(device);
2796 IDirect3D9_Release(d3d);
2797 DestroyWindow(wnd);
2800 static BOOL compute_cylinder(struct mesh *mesh, FLOAT radius1, FLOAT radius2, FLOAT length, UINT slices, UINT stacks)
2802 float theta_step, theta_start;
2803 struct sincos_table theta;
2804 FLOAT delta_radius, radius, radius_step;
2805 FLOAT z, z_step, z_normal;
2806 DWORD number_of_vertices, number_of_faces;
2807 DWORD vertex, face;
2808 int slice, stack;
2810 /* theta = angle on xy plane wrt x axis */
2811 theta_step = -2 * M_PI / slices;
2812 theta_start = M_PI / 2;
2814 if (!compute_sincos_table(&theta, theta_start, theta_step, slices))
2816 return FALSE;
2819 number_of_vertices = 2 + (slices * (3 + stacks));
2820 number_of_faces = 2 * slices + stacks * (2 * slices);
2822 if (!new_mesh(mesh, number_of_vertices, number_of_faces))
2824 free_sincos_table(&theta);
2825 return FALSE;
2828 vertex = 0;
2829 face = 0;
2831 delta_radius = radius1 - radius2;
2832 radius = radius1;
2833 radius_step = delta_radius / stacks;
2835 z = -length / 2;
2836 z_step = length / stacks;
2837 z_normal = delta_radius / length;
2838 if (isnan(z_normal))
2840 z_normal = 0.0f;
2843 mesh->vertices[vertex].normal.x = 0.0f;
2844 mesh->vertices[vertex].normal.y = 0.0f;
2845 mesh->vertices[vertex].normal.z = -1.0f;
2846 mesh->vertices[vertex].position.x = 0.0f;
2847 mesh->vertices[vertex].position.y = 0.0f;
2848 mesh->vertices[vertex++].position.z = z;
2850 for (slice = 0; slice < slices; slice++, vertex++)
2852 mesh->vertices[vertex].normal.x = 0.0f;
2853 mesh->vertices[vertex].normal.y = 0.0f;
2854 mesh->vertices[vertex].normal.z = -1.0f;
2855 mesh->vertices[vertex].position.x = radius * theta.cos[slice];
2856 mesh->vertices[vertex].position.y = radius * theta.sin[slice];
2857 mesh->vertices[vertex].position.z = z;
2859 if (slice > 0)
2861 mesh->faces[face][0] = 0;
2862 mesh->faces[face][1] = slice;
2863 mesh->faces[face++][2] = slice + 1;
2867 mesh->faces[face][0] = 0;
2868 mesh->faces[face][1] = slice;
2869 mesh->faces[face++][2] = 1;
2871 for (stack = 1; stack <= stacks+1; stack++)
2873 for (slice = 0; slice < slices; slice++, vertex++)
2875 mesh->vertices[vertex].normal.x = theta.cos[slice];
2876 mesh->vertices[vertex].normal.y = theta.sin[slice];
2877 mesh->vertices[vertex].normal.z = z_normal;
2878 D3DXVec3Normalize(&mesh->vertices[vertex].normal, &mesh->vertices[vertex].normal);
2879 mesh->vertices[vertex].position.x = radius * theta.cos[slice];
2880 mesh->vertices[vertex].position.y = radius * theta.sin[slice];
2881 mesh->vertices[vertex].position.z = z;
2883 if (stack > 1 && slice > 0)
2885 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
2886 mesh->faces[face][1] = vertex_index(slices, slice-1, stack);
2887 mesh->faces[face++][2] = vertex_index(slices, slice, stack-1);
2889 mesh->faces[face][0] = vertex_index(slices, slice, stack-1);
2890 mesh->faces[face][1] = vertex_index(slices, slice-1, stack);
2891 mesh->faces[face++][2] = vertex_index(slices, slice, stack);
2895 if (stack > 1)
2897 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
2898 mesh->faces[face][1] = vertex_index(slices, slice-1, stack);
2899 mesh->faces[face++][2] = vertex_index(slices, 0, stack-1);
2901 mesh->faces[face][0] = vertex_index(slices, 0, stack-1);
2902 mesh->faces[face][1] = vertex_index(slices, slice-1, stack);
2903 mesh->faces[face++][2] = vertex_index(slices, 0, stack);
2906 if (stack < stacks + 1)
2908 z += z_step;
2909 radius -= radius_step;
2913 for (slice = 0; slice < slices; slice++, vertex++)
2915 mesh->vertices[vertex].normal.x = 0.0f;
2916 mesh->vertices[vertex].normal.y = 0.0f;
2917 mesh->vertices[vertex].normal.z = 1.0f;
2918 mesh->vertices[vertex].position.x = radius * theta.cos[slice];
2919 mesh->vertices[vertex].position.y = radius * theta.sin[slice];
2920 mesh->vertices[vertex].position.z = z;
2922 if (slice > 0)
2924 mesh->faces[face][0] = vertex_index(slices, slice-1, stack);
2925 mesh->faces[face][1] = number_of_vertices - 1;
2926 mesh->faces[face++][2] = vertex_index(slices, slice, stack);
2930 mesh->vertices[vertex].position.x = 0.0f;
2931 mesh->vertices[vertex].position.y = 0.0f;
2932 mesh->vertices[vertex].position.z = z;
2933 mesh->vertices[vertex].normal.x = 0.0f;
2934 mesh->vertices[vertex].normal.y = 0.0f;
2935 mesh->vertices[vertex].normal.z = 1.0f;
2937 mesh->faces[face][0] = vertex_index(slices, slice-1, stack);
2938 mesh->faces[face][1] = number_of_vertices - 1;
2939 mesh->faces[face][2] = vertex_index(slices, 0, stack);
2941 free_sincos_table(&theta);
2943 return TRUE;
2946 static void test_cylinder(IDirect3DDevice9 *device, FLOAT radius1, FLOAT radius2, FLOAT length, UINT slices, UINT stacks)
2948 HRESULT hr;
2949 ID3DXMesh *cylinder;
2950 struct mesh mesh;
2951 char name[256];
2953 hr = D3DXCreateCylinder(device, radius1, radius2, length, slices, stacks, &cylinder, NULL);
2954 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
2955 if (hr != D3D_OK)
2957 skip("Couldn't create cylinder\n");
2958 return;
2961 if (!compute_cylinder(&mesh, radius1, radius2, length, slices, stacks))
2963 skip("Couldn't create mesh\n");
2964 cylinder->lpVtbl->Release(cylinder);
2965 return;
2968 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
2970 sprintf(name, "cylinder (%g, %g, %g, %u, %u)", radius1, radius2, length, slices, stacks);
2971 compare_mesh(name, cylinder, &mesh);
2973 free_mesh(&mesh);
2975 cylinder->lpVtbl->Release(cylinder);
2978 static void D3DXCreateCylinderTest(void)
2980 HRESULT hr;
2981 HWND wnd;
2982 IDirect3D9* d3d;
2983 IDirect3DDevice9* device;
2984 D3DPRESENT_PARAMETERS d3dpp;
2985 ID3DXMesh* cylinder = NULL;
2987 hr = D3DXCreateCylinder(NULL, 0.0f, 0.0f, 0.0f, 0, 0, NULL, NULL);
2988 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
2990 hr = D3DXCreateCylinder(NULL, 1.0f, 1.0f, 1.0f, 2, 1, &cylinder, NULL);
2991 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
2993 wnd = CreateWindow("static", "d3dx9_test", 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL);
2994 d3d = Direct3DCreate9(D3D_SDK_VERSION);
2995 if (!wnd)
2997 skip("Couldn't create application window\n");
2998 return;
3000 if (!d3d)
3002 skip("Couldn't create IDirect3D9 object\n");
3003 DestroyWindow(wnd);
3004 return;
3007 ZeroMemory(&d3dpp, sizeof(d3dpp));
3008 d3dpp.Windowed = TRUE;
3009 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
3010 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, wnd, D3DCREATE_MIXED_VERTEXPROCESSING, &d3dpp, &device);
3011 if (FAILED(hr))
3013 skip("Failed to create IDirect3DDevice9 object %#x\n", hr);
3014 IDirect3D9_Release(d3d);
3015 DestroyWindow(wnd);
3016 return;
3019 hr = D3DXCreateCylinder(device, -0.1f, 1.0f, 1.0f, 2, 1, &cylinder, NULL);
3020 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3022 hr = D3DXCreateCylinder(device, 0.0f, 1.0f, 1.0f, 2, 1, &cylinder, NULL);
3023 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n",hr);
3025 if (SUCCEEDED(hr) && cylinder)
3027 cylinder->lpVtbl->Release(cylinder);
3030 hr = D3DXCreateCylinder(device, 1.0f, -0.1f, 1.0f, 2, 1, &cylinder, NULL);
3031 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3033 hr = D3DXCreateCylinder(device, 1.0f, 0.0f, 1.0f, 2, 1, &cylinder, NULL);
3034 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n",hr);
3036 if (SUCCEEDED(hr) && cylinder)
3038 cylinder->lpVtbl->Release(cylinder);
3041 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, -0.1f, 2, 1, &cylinder, NULL);
3042 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3044 /* Test with length == 0.0f succeeds */
3045 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, 0.0f, 2, 1, &cylinder, NULL);
3046 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n",hr);
3048 if (SUCCEEDED(hr) && cylinder)
3050 cylinder->lpVtbl->Release(cylinder);
3053 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, 1.0f, 1, 1, &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, 0, &cylinder, NULL);
3057 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3059 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, 1.0f, 2, 1, NULL, NULL);
3060 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3062 test_cylinder(device, 0.0f, 0.0f, 0.0f, 2, 1);
3063 test_cylinder(device, 1.0f, 1.0f, 1.0f, 2, 1);
3064 test_cylinder(device, 1.0f, 1.0f, 2.0f, 3, 4);
3065 test_cylinder(device, 3.0f, 2.0f, 4.0f, 3, 4);
3066 test_cylinder(device, 2.0f, 3.0f, 4.0f, 3, 4);
3067 test_cylinder(device, 3.0f, 4.0f, 5.0f, 11, 20);
3069 IDirect3DDevice9_Release(device);
3070 IDirect3D9_Release(d3d);
3071 DestroyWindow(wnd);
3074 struct dynamic_array
3076 int count, capacity;
3077 void *items;
3080 enum pointtype {
3081 POINTTYPE_CURVE = 0,
3082 POINTTYPE_CORNER,
3083 POINTTYPE_CURVE_START,
3084 POINTTYPE_CURVE_END,
3085 POINTTYPE_CURVE_MIDDLE,
3088 struct point2d
3090 D3DXVECTOR2 pos;
3091 enum pointtype corner;
3094 /* is a dynamic_array */
3095 struct outline
3097 int count, capacity;
3098 struct point2d *items;
3101 /* is a dynamic_array */
3102 struct outline_array
3104 int count, capacity;
3105 struct outline *items;
3108 struct glyphinfo
3110 struct outline_array outlines;
3111 float offset_x;
3114 static BOOL reserve(struct dynamic_array *array, int count, int itemsize)
3116 if (count > array->capacity) {
3117 void *new_buffer;
3118 int new_capacity;
3119 if (array->items && array->capacity) {
3120 new_capacity = max(array->capacity * 2, count);
3121 new_buffer = HeapReAlloc(GetProcessHeap(), 0, array->items, new_capacity * itemsize);
3122 } else {
3123 new_capacity = max(16, count);
3124 new_buffer = HeapAlloc(GetProcessHeap(), 0, new_capacity * itemsize);
3126 if (!new_buffer)
3127 return FALSE;
3128 array->items = new_buffer;
3129 array->capacity = new_capacity;
3131 return TRUE;
3134 static struct point2d *add_point(struct outline *array)
3136 struct point2d *item;
3138 if (!reserve((struct dynamic_array *)array, array->count + 1, sizeof(array->items[0])))
3139 return NULL;
3141 item = &array->items[array->count++];
3142 ZeroMemory(item, sizeof(*item));
3143 return item;
3146 static struct outline *add_outline(struct outline_array *array)
3148 struct outline *item;
3150 if (!reserve((struct dynamic_array *)array, array->count + 1, sizeof(array->items[0])))
3151 return NULL;
3153 item = &array->items[array->count++];
3154 ZeroMemory(item, sizeof(*item));
3155 return item;
3158 static inline D3DXVECTOR2 *convert_fixed_to_float(POINTFX *pt, int count, float emsquare)
3160 D3DXVECTOR2 *ret = (D3DXVECTOR2*)pt;
3161 while (count--) {
3162 D3DXVECTOR2 *pt_flt = (D3DXVECTOR2*)pt;
3163 pt_flt->x = (pt->x.value + pt->x.fract / (float)0x10000) / emsquare;
3164 pt_flt->y = (pt->y.value + pt->y.fract / (float)0x10000) / emsquare;
3165 pt++;
3167 return ret;
3170 static HRESULT add_bezier_points(struct outline *outline, const D3DXVECTOR2 *p1,
3171 const D3DXVECTOR2 *p2, const D3DXVECTOR2 *p3,
3172 float max_deviation)
3174 D3DXVECTOR2 split1 = {0, 0}, split2 = {0, 0}, middle, vec;
3175 float deviation;
3177 D3DXVec2Scale(&split1, D3DXVec2Add(&split1, p1, p2), 0.5f);
3178 D3DXVec2Scale(&split2, D3DXVec2Add(&split2, p2, p3), 0.5f);
3179 D3DXVec2Scale(&middle, D3DXVec2Add(&middle, &split1, &split2), 0.5f);
3181 deviation = D3DXVec2Length(D3DXVec2Subtract(&vec, &middle, p2));
3182 if (deviation < max_deviation) {
3183 struct point2d *pt = add_point(outline);
3184 if (!pt) return E_OUTOFMEMORY;
3185 pt->pos = *p2;
3186 pt->corner = POINTTYPE_CURVE;
3187 /* the end point is omitted because the end line merges into the next segment of
3188 * the split bezier curve, and the end of the split bezier curve is added outside
3189 * this recursive function. */
3190 } else {
3191 HRESULT hr = add_bezier_points(outline, p1, &split1, &middle, max_deviation);
3192 if (hr != S_OK) return hr;
3193 hr = add_bezier_points(outline, &middle, &split2, p3, max_deviation);
3194 if (hr != S_OK) return hr;
3197 return S_OK;
3200 static inline BOOL is_direction_similar(D3DXVECTOR2 *dir1, D3DXVECTOR2 *dir2, float cos_theta)
3202 /* dot product = cos(theta) */
3203 return D3DXVec2Dot(dir1, dir2) > cos_theta;
3206 static inline D3DXVECTOR2 *unit_vec2(D3DXVECTOR2 *dir, const D3DXVECTOR2 *pt1, const D3DXVECTOR2 *pt2)
3208 return D3DXVec2Normalize(D3DXVec2Subtract(dir, pt2, pt1), dir);
3211 static BOOL attempt_line_merge(struct outline *outline,
3212 int pt_index,
3213 const D3DXVECTOR2 *nextpt,
3214 BOOL to_curve)
3216 D3DXVECTOR2 curdir, lastdir;
3217 struct point2d *prevpt, *pt;
3218 BOOL ret = FALSE;
3219 const float cos_half = cos(D3DXToRadian(0.5f));
3221 pt = &outline->items[pt_index];
3222 pt_index = (pt_index - 1 + outline->count) % outline->count;
3223 prevpt = &outline->items[pt_index];
3225 if (to_curve)
3226 pt->corner = pt->corner != POINTTYPE_CORNER ? POINTTYPE_CURVE_MIDDLE : POINTTYPE_CURVE_START;
3228 if (outline->count < 2)
3229 return FALSE;
3231 /* remove last point if the next line continues the last line */
3232 unit_vec2(&lastdir, &prevpt->pos, &pt->pos);
3233 unit_vec2(&curdir, &pt->pos, nextpt);
3234 if (is_direction_similar(&lastdir, &curdir, cos_half))
3236 outline->count--;
3237 if (pt->corner == POINTTYPE_CURVE_END)
3238 prevpt->corner = pt->corner;
3239 if (prevpt->corner == POINTTYPE_CURVE_END && to_curve)
3240 prevpt->corner = POINTTYPE_CURVE_MIDDLE;
3241 pt = prevpt;
3243 ret = TRUE;
3244 if (outline->count < 2)
3245 return ret;
3247 pt_index = (pt_index - 1 + outline->count) % outline->count;
3248 prevpt = &outline->items[pt_index];
3249 unit_vec2(&lastdir, &prevpt->pos, &pt->pos);
3250 unit_vec2(&curdir, &pt->pos, nextpt);
3252 return ret;
3255 static HRESULT create_outline(struct glyphinfo *glyph, void *raw_outline, int datasize,
3256 float max_deviation, float emsquare)
3258 const float cos_45 = cos(D3DXToRadian(45.0f));
3259 const float cos_90 = cos(D3DXToRadian(90.0f));
3260 TTPOLYGONHEADER *header = (TTPOLYGONHEADER *)raw_outline;
3262 while ((char *)header < (char *)raw_outline + datasize)
3264 TTPOLYCURVE *curve = (TTPOLYCURVE *)(header + 1);
3265 struct point2d *lastpt, *pt;
3266 D3DXVECTOR2 lastdir;
3267 D3DXVECTOR2 *pt_flt;
3268 int j;
3269 struct outline *outline = add_outline(&glyph->outlines);
3271 if (!outline)
3272 return E_OUTOFMEMORY;
3274 pt = add_point(outline);
3275 if (!pt)
3276 return E_OUTOFMEMORY;
3277 pt_flt = convert_fixed_to_float(&header->pfxStart, 1, emsquare);
3278 pt->pos = *pt_flt;
3279 pt->corner = POINTTYPE_CORNER;
3281 if (header->dwType != TT_POLYGON_TYPE)
3282 trace("Unknown header type %d\n", header->dwType);
3284 while ((char *)curve < (char *)header + header->cb)
3286 D3DXVECTOR2 bezier_start = outline->items[outline->count - 1].pos;
3287 BOOL to_curve = curve->wType != TT_PRIM_LINE && curve->cpfx > 1;
3289 if (!curve->cpfx) {
3290 curve = (TTPOLYCURVE *)&curve->apfx[curve->cpfx];
3291 continue;
3294 pt_flt = convert_fixed_to_float(curve->apfx, curve->cpfx, emsquare);
3296 attempt_line_merge(outline, outline->count - 1, &pt_flt[0], to_curve);
3298 if (to_curve)
3300 HRESULT hr;
3301 int count = curve->cpfx;
3302 j = 0;
3304 while (count > 2)
3306 D3DXVECTOR2 bezier_end;
3308 D3DXVec2Scale(&bezier_end, D3DXVec2Add(&bezier_end, &pt_flt[j], &pt_flt[j+1]), 0.5f);
3309 hr = add_bezier_points(outline, &bezier_start, &pt_flt[j], &bezier_end, max_deviation);
3310 if (hr != S_OK)
3311 return hr;
3312 bezier_start = bezier_end;
3313 count--;
3314 j++;
3316 hr = add_bezier_points(outline, &bezier_start, &pt_flt[j], &pt_flt[j+1], max_deviation);
3317 if (hr != S_OK)
3318 return hr;
3320 pt = add_point(outline);
3321 if (!pt)
3322 return E_OUTOFMEMORY;
3323 j++;
3324 pt->pos = pt_flt[j];
3325 pt->corner = POINTTYPE_CURVE_END;
3326 } else {
3327 for (j = 0; j < curve->cpfx; j++)
3329 pt = add_point(outline);
3330 if (!pt)
3331 return E_OUTOFMEMORY;
3332 pt->pos = pt_flt[j];
3333 pt->corner = POINTTYPE_CORNER;
3337 curve = (TTPOLYCURVE *)&curve->apfx[curve->cpfx];
3340 /* remove last point if the next line continues the last line */
3341 if (outline->count >= 3) {
3342 BOOL to_curve;
3344 lastpt = &outline->items[outline->count - 1];
3345 pt = &outline->items[0];
3346 if (pt->pos.x == lastpt->pos.x && pt->pos.y == lastpt->pos.y) {
3347 if (lastpt->corner == POINTTYPE_CURVE_END)
3349 if (pt->corner == POINTTYPE_CURVE_START)
3350 pt->corner = POINTTYPE_CURVE_MIDDLE;
3351 else
3352 pt->corner = POINTTYPE_CURVE_END;
3354 outline->count--;
3355 lastpt = &outline->items[outline->count - 1];
3356 } else {
3357 /* outline closed with a line from end to start point */
3358 attempt_line_merge(outline, outline->count - 1, &pt->pos, FALSE);
3360 lastpt = &outline->items[0];
3361 to_curve = lastpt->corner != POINTTYPE_CORNER && lastpt->corner != POINTTYPE_CURVE_END;
3362 if (lastpt->corner == POINTTYPE_CURVE_START)
3363 lastpt->corner = POINTTYPE_CORNER;
3364 pt = &outline->items[1];
3365 if (attempt_line_merge(outline, 0, &pt->pos, to_curve))
3366 *lastpt = outline->items[outline->count];
3369 lastpt = &outline->items[outline->count - 1];
3370 pt = &outline->items[0];
3371 unit_vec2(&lastdir, &lastpt->pos, &pt->pos);
3372 for (j = 0; j < outline->count; j++)
3374 D3DXVECTOR2 curdir;
3376 lastpt = pt;
3377 pt = &outline->items[(j + 1) % outline->count];
3378 unit_vec2(&curdir, &lastpt->pos, &pt->pos);
3380 switch (lastpt->corner)
3382 case POINTTYPE_CURVE_START:
3383 case POINTTYPE_CURVE_END:
3384 if (!is_direction_similar(&lastdir, &curdir, cos_45))
3385 lastpt->corner = POINTTYPE_CORNER;
3386 break;
3387 case POINTTYPE_CURVE_MIDDLE:
3388 if (!is_direction_similar(&lastdir, &curdir, cos_90))
3389 lastpt->corner = POINTTYPE_CORNER;
3390 else
3391 lastpt->corner = POINTTYPE_CURVE;
3392 break;
3393 default:
3394 break;
3396 lastdir = curdir;
3399 header = (TTPOLYGONHEADER *)((char *)header + header->cb);
3401 return S_OK;
3404 static BOOL compute_text_mesh(struct mesh *mesh, HDC hdc, LPCSTR text, FLOAT deviation, FLOAT extrusion, FLOAT otmEMSquare)
3406 HRESULT hr = E_FAIL;
3407 DWORD nb_vertices, nb_faces;
3408 DWORD nb_corners, nb_outline_points;
3409 int textlen = 0;
3410 float offset_x;
3411 char *raw_outline = NULL;
3412 struct glyphinfo *glyphs = NULL;
3413 GLYPHMETRICS gm;
3414 int i;
3415 struct vertex *vertex_ptr;
3416 face *face_ptr;
3418 if (deviation == 0.0f)
3419 deviation = 1.0f / otmEMSquare;
3421 textlen = strlen(text);
3422 glyphs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, textlen * sizeof(*glyphs));
3423 if (!glyphs) {
3424 hr = E_OUTOFMEMORY;
3425 goto error;
3428 offset_x = 0.0f;
3429 for (i = 0; i < textlen; i++)
3431 /* get outline points from data returned from GetGlyphOutline */
3432 const MAT2 identity = {{0, 1}, {0, 0}, {0, 0}, {0, 1}};
3433 int datasize;
3435 glyphs[i].offset_x = offset_x;
3437 datasize = GetGlyphOutline(hdc, text[i], GGO_NATIVE, &gm, 0, NULL, &identity);
3438 if (datasize < 0) {
3439 hr = E_FAIL;
3440 goto error;
3442 HeapFree(GetProcessHeap(), 0, raw_outline);
3443 raw_outline = HeapAlloc(GetProcessHeap(), 0, datasize);
3444 if (!glyphs) {
3445 hr = E_OUTOFMEMORY;
3446 goto error;
3448 datasize = GetGlyphOutline(hdc, text[i], GGO_NATIVE, &gm, datasize, raw_outline, &identity);
3450 create_outline(&glyphs[i], raw_outline, datasize, deviation, otmEMSquare);
3452 offset_x += gm.gmCellIncX / (float)otmEMSquare;
3455 /* corner points need an extra vertex for the different side faces normals */
3456 nb_corners = 0;
3457 nb_outline_points = 0;
3458 for (i = 0; i < textlen; i++)
3460 int j;
3461 for (j = 0; j < glyphs[i].outlines.count; j++)
3463 int k;
3464 struct outline *outline = &glyphs[i].outlines.items[j];
3465 nb_outline_points += outline->count;
3466 nb_corners++; /* first outline point always repeated as a corner */
3467 for (k = 1; k < outline->count; k++)
3468 if (outline->items[k].corner)
3469 nb_corners++;
3473 nb_vertices = (nb_outline_points + nb_corners) * 2 + textlen;
3474 nb_faces = nb_outline_points * 2;
3476 if (!new_mesh(mesh, nb_vertices, nb_faces))
3477 goto error;
3479 /* convert 2D vertices and faces into 3D mesh */
3480 vertex_ptr = mesh->vertices;
3481 face_ptr = mesh->faces;
3482 for (i = 0; i < textlen; i++)
3484 int j;
3486 /* side vertices and faces */
3487 for (j = 0; j < glyphs[i].outlines.count; j++)
3489 struct vertex *outline_vertices = vertex_ptr;
3490 struct outline *outline = &glyphs[i].outlines.items[j];
3491 int k;
3492 struct point2d *prevpt = &outline->items[outline->count - 1];
3493 struct point2d *pt = &outline->items[0];
3495 for (k = 1; k <= outline->count; k++)
3497 struct vertex vtx;
3498 struct point2d *nextpt = &outline->items[k % outline->count];
3499 WORD vtx_idx = vertex_ptr - mesh->vertices;
3500 D3DXVECTOR2 vec;
3502 if (pt->corner == POINTTYPE_CURVE_START)
3503 D3DXVec2Subtract(&vec, &pt->pos, &prevpt->pos);
3504 else if (pt->corner)
3505 D3DXVec2Subtract(&vec, &nextpt->pos, &pt->pos);
3506 else
3507 D3DXVec2Subtract(&vec, &nextpt->pos, &prevpt->pos);
3508 D3DXVec2Normalize(&vec, &vec);
3509 vtx.normal.x = -vec.y;
3510 vtx.normal.y = vec.x;
3511 vtx.normal.z = 0;
3513 vtx.position.x = pt->pos.x + glyphs[i].offset_x;
3514 vtx.position.y = pt->pos.y;
3515 vtx.position.z = 0;
3516 *vertex_ptr++ = vtx;
3518 vtx.position.z = -extrusion;
3519 *vertex_ptr++ = vtx;
3521 vtx.position.x = nextpt->pos.x + glyphs[i].offset_x;
3522 vtx.position.y = nextpt->pos.y;
3523 if (pt->corner && nextpt->corner && nextpt->corner != POINTTYPE_CURVE_END) {
3524 vtx.position.z = -extrusion;
3525 *vertex_ptr++ = vtx;
3526 vtx.position.z = 0;
3527 *vertex_ptr++ = vtx;
3529 (*face_ptr)[0] = vtx_idx;
3530 (*face_ptr)[1] = vtx_idx + 2;
3531 (*face_ptr)[2] = vtx_idx + 1;
3532 face_ptr++;
3534 (*face_ptr)[0] = vtx_idx;
3535 (*face_ptr)[1] = vtx_idx + 3;
3536 (*face_ptr)[2] = vtx_idx + 2;
3537 face_ptr++;
3538 } else {
3539 if (nextpt->corner) {
3540 if (nextpt->corner == POINTTYPE_CURVE_END) {
3541 struct point2d *nextpt2 = &outline->items[(k + 1) % outline->count];
3542 D3DXVec2Subtract(&vec, &nextpt2->pos, &nextpt->pos);
3543 } else {
3544 D3DXVec2Subtract(&vec, &nextpt->pos, &pt->pos);
3546 D3DXVec2Normalize(&vec, &vec);
3547 vtx.normal.x = -vec.y;
3548 vtx.normal.y = vec.x;
3550 vtx.position.z = 0;
3551 *vertex_ptr++ = vtx;
3552 vtx.position.z = -extrusion;
3553 *vertex_ptr++ = vtx;
3556 (*face_ptr)[0] = vtx_idx;
3557 (*face_ptr)[1] = vtx_idx + 3;
3558 (*face_ptr)[2] = vtx_idx + 1;
3559 face_ptr++;
3561 (*face_ptr)[0] = vtx_idx;
3562 (*face_ptr)[1] = vtx_idx + 2;
3563 (*face_ptr)[2] = vtx_idx + 3;
3564 face_ptr++;
3567 prevpt = pt;
3568 pt = nextpt;
3570 if (!pt->corner) {
3571 *vertex_ptr++ = *outline_vertices++;
3572 *vertex_ptr++ = *outline_vertices++;
3576 /* FIXME: compute expected faces */
3577 /* Add placeholder to separate glyph outlines */
3578 vertex_ptr->position.x = 0;
3579 vertex_ptr->position.y = 0;
3580 vertex_ptr->position.z = 0;
3581 vertex_ptr->normal.x = 0;
3582 vertex_ptr->normal.y = 0;
3583 vertex_ptr->normal.z = 1;
3584 vertex_ptr++;
3587 hr = D3D_OK;
3588 error:
3589 if (glyphs) {
3590 for (i = 0; i < textlen; i++)
3592 int j;
3593 for (j = 0; j < glyphs[i].outlines.count; j++)
3594 HeapFree(GetProcessHeap(), 0, glyphs[i].outlines.items[j].items);
3595 HeapFree(GetProcessHeap(), 0, glyphs[i].outlines.items);
3597 HeapFree(GetProcessHeap(), 0, glyphs);
3599 HeapFree(GetProcessHeap(), 0, raw_outline);
3601 return hr == D3D_OK;
3604 static void compare_text_outline_mesh(const char *name, ID3DXMesh *d3dxmesh, struct mesh *mesh, int textlen, float extrusion)
3606 HRESULT hr;
3607 DWORD number_of_vertices, number_of_faces;
3608 IDirect3DVertexBuffer9 *vertex_buffer = NULL;
3609 IDirect3DIndexBuffer9 *index_buffer = NULL;
3610 D3DVERTEXBUFFER_DESC vertex_buffer_description;
3611 D3DINDEXBUFFER_DESC index_buffer_description;
3612 struct vertex *vertices = NULL;
3613 face *faces = NULL;
3614 int expected, i;
3615 int vtx_idx1, face_idx1, vtx_idx2, face_idx2;
3617 number_of_vertices = d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh);
3618 number_of_faces = d3dxmesh->lpVtbl->GetNumFaces(d3dxmesh);
3620 /* vertex buffer */
3621 hr = d3dxmesh->lpVtbl->GetVertexBuffer(d3dxmesh, &vertex_buffer);
3622 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
3623 if (hr != D3D_OK)
3625 skip("Couldn't get vertex buffers\n");
3626 goto error;
3629 hr = IDirect3DVertexBuffer9_GetDesc(vertex_buffer, &vertex_buffer_description);
3630 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
3632 if (hr != D3D_OK)
3634 skip("Couldn't get vertex buffer description\n");
3636 else
3638 ok(vertex_buffer_description.Format == D3DFMT_VERTEXDATA, "Test %s, result %x, expected %x (D3DFMT_VERTEXDATA)\n",
3639 name, vertex_buffer_description.Format, D3DFMT_VERTEXDATA);
3640 ok(vertex_buffer_description.Type == D3DRTYPE_VERTEXBUFFER, "Test %s, result %x, expected %x (D3DRTYPE_VERTEXBUFFER)\n",
3641 name, vertex_buffer_description.Type, D3DRTYPE_VERTEXBUFFER);
3642 ok(vertex_buffer_description.Usage == 0, "Test %s, result %x, expected %x\n", name, vertex_buffer_description.Usage, 0);
3643 ok(vertex_buffer_description.Pool == D3DPOOL_MANAGED, "Test %s, result %x, expected %x (D3DPOOL_MANAGED)\n",
3644 name, vertex_buffer_description.Pool, D3DPOOL_MANAGED);
3645 ok(vertex_buffer_description.FVF == mesh->fvf, "Test %s, result %x, expected %x\n",
3646 name, vertex_buffer_description.FVF, mesh->fvf);
3647 if (mesh->fvf == 0)
3649 expected = number_of_vertices * mesh->vertex_size;
3651 else
3653 expected = number_of_vertices * D3DXGetFVFVertexSize(mesh->fvf);
3655 ok(vertex_buffer_description.Size == expected, "Test %s, result %x, expected %x\n",
3656 name, vertex_buffer_description.Size, expected);
3659 hr = d3dxmesh->lpVtbl->GetIndexBuffer(d3dxmesh, &index_buffer);
3660 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
3661 if (hr != D3D_OK)
3663 skip("Couldn't get index buffer\n");
3664 goto error;
3667 hr = IDirect3DIndexBuffer9_GetDesc(index_buffer, &index_buffer_description);
3668 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
3670 if (hr != D3D_OK)
3672 skip("Couldn't get index buffer description\n");
3674 else
3676 ok(index_buffer_description.Format == D3DFMT_INDEX16, "Test %s, result %x, expected %x (D3DFMT_INDEX16)\n",
3677 name, index_buffer_description.Format, D3DFMT_INDEX16);
3678 ok(index_buffer_description.Type == D3DRTYPE_INDEXBUFFER, "Test %s, result %x, expected %x (D3DRTYPE_INDEXBUFFER)\n",
3679 name, index_buffer_description.Type, D3DRTYPE_INDEXBUFFER);
3680 ok(index_buffer_description.Usage == 0, "Test %s, result %#x, expected %#x.\n",
3681 name, index_buffer_description.Usage, 0);
3682 ok(index_buffer_description.Pool == D3DPOOL_MANAGED, "Test %s, result %x, expected %x (D3DPOOL_MANAGED)\n",
3683 name, index_buffer_description.Pool, D3DPOOL_MANAGED);
3684 expected = number_of_faces * sizeof(WORD) * 3;
3685 ok(index_buffer_description.Size == expected, "Test %s, result %x, expected %x\n",
3686 name, index_buffer_description.Size, expected);
3689 /* specify offset and size to avoid potential overruns */
3690 hr = IDirect3DVertexBuffer9_Lock(vertex_buffer, 0, number_of_vertices * sizeof(D3DXVECTOR3) * 2,
3691 (LPVOID *)&vertices, D3DLOCK_DISCARD);
3692 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
3693 if (hr != D3D_OK)
3695 skip("Couldn't lock vertex buffer\n");
3696 goto error;
3698 hr = IDirect3DIndexBuffer9_Lock(index_buffer, 0, number_of_faces * sizeof(WORD) * 3,
3699 (LPVOID *)&faces, D3DLOCK_DISCARD);
3700 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
3701 if (hr != D3D_OK)
3703 skip("Couldn't lock index buffer\n");
3704 goto error;
3707 face_idx1 = 0;
3708 vtx_idx2 = 0;
3709 face_idx2 = 0;
3710 vtx_idx1 = 0;
3711 for (i = 0; i < textlen; i++)
3713 int nb_outline_vertices1, nb_outline_faces1;
3714 int nb_outline_vertices2, nb_outline_faces2;
3715 int nb_back_vertices, nb_back_faces;
3716 int first_vtx1, first_vtx2;
3717 int first_face1, first_face2;
3718 int j;
3720 first_vtx1 = vtx_idx1;
3721 first_vtx2 = vtx_idx2;
3722 for (; vtx_idx1 < number_of_vertices; vtx_idx1++) {
3723 if (vertices[vtx_idx1].normal.z != 0)
3724 break;
3726 for (; vtx_idx2 < mesh->number_of_vertices; vtx_idx2++) {
3727 if (mesh->vertices[vtx_idx2].normal.z != 0)
3728 break;
3730 nb_outline_vertices1 = vtx_idx1 - first_vtx1;
3731 nb_outline_vertices2 = vtx_idx2 - first_vtx2;
3732 ok(nb_outline_vertices1 == nb_outline_vertices2,
3733 "Test %s, glyph %d, outline vertex count result %d, expected %d\n", name, i,
3734 nb_outline_vertices1, nb_outline_vertices2);
3736 for (j = 0; j < min(nb_outline_vertices1, nb_outline_vertices2); j++)
3738 vtx_idx1 = first_vtx1 + j;
3739 vtx_idx2 = first_vtx2 + j;
3740 ok(compare_vec3(vertices[vtx_idx1].position, mesh->vertices[vtx_idx2].position),
3741 "Test %s, glyph %d, vertex position %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1,
3742 vertices[vtx_idx1].position.x, vertices[vtx_idx1].position.y, vertices[vtx_idx1].position.z,
3743 mesh->vertices[vtx_idx2].position.x, mesh->vertices[vtx_idx2].position.y, mesh->vertices[vtx_idx2].position.z);
3744 ok(compare_vec3(vertices[vtx_idx1].normal, mesh->vertices[first_vtx2 + j].normal),
3745 "Test %s, glyph %d, vertex normal %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1,
3746 vertices[vtx_idx1].normal.x, vertices[vtx_idx1].normal.y, vertices[vtx_idx1].normal.z,
3747 mesh->vertices[vtx_idx2].normal.x, mesh->vertices[vtx_idx2].normal.y, mesh->vertices[vtx_idx2].normal.z);
3749 vtx_idx1 = first_vtx1 + nb_outline_vertices1;
3750 vtx_idx2 = first_vtx2 + nb_outline_vertices2;
3752 first_face1 = face_idx1;
3753 first_face2 = face_idx2;
3754 for (; face_idx1 < number_of_faces; face_idx1++)
3756 if (faces[face_idx1][0] >= vtx_idx1 ||
3757 faces[face_idx1][1] >= vtx_idx1 ||
3758 faces[face_idx1][2] >= vtx_idx1)
3759 break;
3761 for (; face_idx2 < mesh->number_of_faces; face_idx2++)
3763 if (mesh->faces[face_idx2][0] >= vtx_idx2 ||
3764 mesh->faces[face_idx2][1] >= vtx_idx2 ||
3765 mesh->faces[face_idx2][2] >= vtx_idx2)
3766 break;
3768 nb_outline_faces1 = face_idx1 - first_face1;
3769 nb_outline_faces2 = face_idx2 - first_face2;
3770 ok(nb_outline_faces1 == nb_outline_faces2,
3771 "Test %s, glyph %d, outline face count result %d, expected %d\n", name, i,
3772 nb_outline_faces1, nb_outline_faces2);
3774 for (j = 0; j < min(nb_outline_faces1, nb_outline_faces2); j++)
3776 face_idx1 = first_face1 + j;
3777 face_idx2 = first_face2 + j;
3778 ok(faces[face_idx1][0] - first_vtx1 == mesh->faces[face_idx2][0] - first_vtx2 &&
3779 faces[face_idx1][1] - first_vtx1 == mesh->faces[face_idx2][1] - first_vtx2 &&
3780 faces[face_idx1][2] - first_vtx1 == mesh->faces[face_idx2][2] - first_vtx2,
3781 "Test %s, glyph %d, face %d, result (%d, %d, %d), expected (%d, %d, %d)\n", name, i, face_idx1,
3782 faces[face_idx1][0], faces[face_idx1][1], faces[face_idx1][2],
3783 mesh->faces[face_idx2][0] - first_vtx2 + first_vtx1,
3784 mesh->faces[face_idx2][1] - first_vtx2 + first_vtx1,
3785 mesh->faces[face_idx2][2] - first_vtx2 + first_vtx1);
3787 face_idx1 = first_face1 + nb_outline_faces1;
3788 face_idx2 = first_face2 + nb_outline_faces2;
3790 /* partial test on back vertices and faces */
3791 first_vtx1 = vtx_idx1;
3792 for (; vtx_idx1 < number_of_vertices; vtx_idx1++) {
3793 struct vertex vtx;
3795 if (vertices[vtx_idx1].normal.z != 1.0f)
3796 break;
3798 vtx.position.z = 0.0f;
3799 vtx.normal.x = 0.0f;
3800 vtx.normal.y = 0.0f;
3801 vtx.normal.z = 1.0f;
3802 ok(compare(vertices[vtx_idx1].position.z, vtx.position.z),
3803 "Test %s, glyph %d, vertex position.z %d, result %g, expected %g\n", name, i, vtx_idx1,
3804 vertices[vtx_idx1].position.z, vtx.position.z);
3805 ok(compare_vec3(vertices[vtx_idx1].normal, vtx.normal),
3806 "Test %s, glyph %d, vertex normal %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1,
3807 vertices[vtx_idx1].normal.x, vertices[vtx_idx1].normal.y, vertices[vtx_idx1].normal.z,
3808 vtx.normal.x, vtx.normal.y, vtx.normal.z);
3810 nb_back_vertices = vtx_idx1 - first_vtx1;
3811 first_face1 = face_idx1;
3812 for (; face_idx1 < number_of_faces; face_idx1++)
3814 const D3DXVECTOR3 *vtx1, *vtx2, *vtx3;
3815 D3DXVECTOR3 normal;
3816 D3DXVECTOR3 v1 = {0, 0, 0};
3817 D3DXVECTOR3 v2 = {0, 0, 0};
3818 D3DXVECTOR3 forward = {0.0f, 0.0f, 1.0f};
3820 if (faces[face_idx1][0] >= vtx_idx1 ||
3821 faces[face_idx1][1] >= vtx_idx1 ||
3822 faces[face_idx1][2] >= vtx_idx1)
3823 break;
3825 vtx1 = &vertices[faces[face_idx1][0]].position;
3826 vtx2 = &vertices[faces[face_idx1][1]].position;
3827 vtx3 = &vertices[faces[face_idx1][2]].position;
3829 D3DXVec3Subtract(&v1, vtx2, vtx1);
3830 D3DXVec3Subtract(&v2, vtx3, vtx2);
3831 D3DXVec3Cross(&normal, &v1, &v2);
3832 D3DXVec3Normalize(&normal, &normal);
3833 ok(!D3DXVec3Length(&normal) || compare_vec3(normal, forward),
3834 "Test %s, glyph %d, face %d normal, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, face_idx1,
3835 normal.x, normal.y, normal.z, forward.x, forward.y, forward.z);
3837 nb_back_faces = face_idx1 - first_face1;
3839 /* compare front and back faces & vertices */
3840 if (extrusion == 0.0f) {
3841 /* Oddly there are only back faces in this case */
3842 nb_back_vertices /= 2;
3843 nb_back_faces /= 2;
3844 face_idx1 -= nb_back_faces;
3845 vtx_idx1 -= nb_back_vertices;
3847 for (j = 0; j < nb_back_vertices; j++)
3849 struct vertex vtx = vertices[first_vtx1];
3850 vtx.position.z = -extrusion;
3851 vtx.normal.x = 0.0f;
3852 vtx.normal.y = 0.0f;
3853 vtx.normal.z = extrusion == 0.0f ? 1.0f : -1.0f;
3854 ok(compare_vec3(vertices[vtx_idx1].position, vtx.position),
3855 "Test %s, glyph %d, vertex position %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1,
3856 vertices[vtx_idx1].position.x, vertices[vtx_idx1].position.y, vertices[vtx_idx1].position.z,
3857 vtx.position.x, vtx.position.y, vtx.position.z);
3858 ok(compare_vec3(vertices[vtx_idx1].normal, vtx.normal),
3859 "Test %s, glyph %d, vertex normal %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1,
3860 vertices[vtx_idx1].normal.x, vertices[vtx_idx1].normal.y, vertices[vtx_idx1].normal.z,
3861 vtx.normal.x, vtx.normal.y, vtx.normal.z);
3862 vtx_idx1++;
3863 first_vtx1++;
3865 for (j = 0; j < nb_back_faces; j++)
3867 int f1, f2;
3868 if (extrusion == 0.0f) {
3869 f1 = 1;
3870 f2 = 2;
3871 } else {
3872 f1 = 2;
3873 f2 = 1;
3875 ok(faces[face_idx1][0] == faces[first_face1][0] + nb_back_vertices &&
3876 faces[face_idx1][1] == faces[first_face1][f1] + nb_back_vertices &&
3877 faces[face_idx1][2] == faces[first_face1][f2] + nb_back_vertices,
3878 "Test %s, glyph %d, face %d, result (%d, %d, %d), expected (%d, %d, %d)\n", name, i, face_idx1,
3879 faces[face_idx1][0], faces[face_idx1][1], faces[face_idx1][2],
3880 faces[first_face1][0] - nb_back_faces,
3881 faces[first_face1][f1] - nb_back_faces,
3882 faces[first_face1][f2] - nb_back_faces);
3883 first_face1++;
3884 face_idx1++;
3887 /* skip to the outline for the next glyph */
3888 for (; vtx_idx2 < mesh->number_of_vertices; vtx_idx2++) {
3889 if (mesh->vertices[vtx_idx2].normal.z == 0)
3890 break;
3892 for (; face_idx2 < mesh->number_of_faces; face_idx2++)
3894 if (mesh->faces[face_idx2][0] >= vtx_idx2 ||
3895 mesh->faces[face_idx2][1] >= vtx_idx2 ||
3896 mesh->faces[face_idx2][2] >= vtx_idx2) break;
3900 error:
3901 if (vertices) IDirect3DVertexBuffer9_Unlock(vertex_buffer);
3902 if (faces) IDirect3DIndexBuffer9_Unlock(index_buffer);
3903 if (index_buffer) IDirect3DIndexBuffer9_Release(index_buffer);
3904 if (vertex_buffer) IDirect3DVertexBuffer9_Release(vertex_buffer);
3907 static void test_createtext(IDirect3DDevice9 *device, HDC hdc, LPCSTR text, FLOAT deviation, FLOAT extrusion)
3909 HRESULT hr;
3910 ID3DXMesh *d3dxmesh;
3911 struct mesh mesh;
3912 char name[256];
3913 OUTLINETEXTMETRIC otm;
3914 GLYPHMETRICS gm;
3915 GLYPHMETRICSFLOAT *glyphmetrics_float = HeapAlloc(GetProcessHeap(), 0, sizeof(GLYPHMETRICSFLOAT) * strlen(text));
3916 int i;
3917 LOGFONT lf;
3918 HFONT font = NULL, oldfont = NULL;
3920 sprintf(name, "text ('%s', %f, %f)", text, deviation, extrusion);
3922 hr = D3DXCreateText(device, hdc, text, deviation, extrusion, &d3dxmesh, NULL, glyphmetrics_float);
3923 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
3924 if (hr != D3D_OK)
3926 skip("Couldn't create text with D3DXCreateText\n");
3927 return;
3930 /* must select a modified font having lfHeight = otm.otmEMSquare before
3931 * calling GetGlyphOutline to get the expected values */
3932 if (!GetObject(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf) ||
3933 !GetOutlineTextMetrics(hdc, sizeof(otm), &otm))
3935 d3dxmesh->lpVtbl->Release(d3dxmesh);
3936 skip("Couldn't get text outline\n");
3937 return;
3939 lf.lfHeight = otm.otmEMSquare;
3940 lf.lfWidth = 0;
3941 font = CreateFontIndirect(&lf);
3942 if (!font) {
3943 d3dxmesh->lpVtbl->Release(d3dxmesh);
3944 skip("Couldn't create the modified font\n");
3945 return;
3947 oldfont = SelectObject(hdc, font);
3949 for (i = 0; i < strlen(text); i++)
3951 const MAT2 identity = {{0, 1}, {0, 0}, {0, 0}, {0, 1}};
3952 GetGlyphOutlineA(hdc, text[i], GGO_NATIVE, &gm, 0, NULL, &identity);
3953 compare_float(glyphmetrics_float[i].gmfBlackBoxX, gm.gmBlackBoxX / (float)otm.otmEMSquare);
3954 compare_float(glyphmetrics_float[i].gmfBlackBoxY, gm.gmBlackBoxY / (float)otm.otmEMSquare);
3955 compare_float(glyphmetrics_float[i].gmfptGlyphOrigin.x, gm.gmptGlyphOrigin.x / (float)otm.otmEMSquare);
3956 compare_float(glyphmetrics_float[i].gmfptGlyphOrigin.y, gm.gmptGlyphOrigin.y / (float)otm.otmEMSquare);
3957 compare_float(glyphmetrics_float[i].gmfCellIncX, gm.gmCellIncX / (float)otm.otmEMSquare);
3958 compare_float(glyphmetrics_float[i].gmfCellIncY, gm.gmCellIncY / (float)otm.otmEMSquare);
3961 ZeroMemory(&mesh, sizeof(mesh));
3962 if (!compute_text_mesh(&mesh, hdc, text, deviation, extrusion, otm.otmEMSquare))
3964 skip("Couldn't create mesh\n");
3965 d3dxmesh->lpVtbl->Release(d3dxmesh);
3966 return;
3968 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
3970 compare_text_outline_mesh(name, d3dxmesh, &mesh, strlen(text), extrusion);
3972 free_mesh(&mesh);
3974 d3dxmesh->lpVtbl->Release(d3dxmesh);
3975 SelectObject(hdc, oldfont);
3976 HeapFree(GetProcessHeap(), 0, glyphmetrics_float);
3979 static void D3DXCreateTextTest(void)
3981 HRESULT hr;
3982 HWND wnd;
3983 HDC hdc;
3984 IDirect3D9* d3d;
3985 IDirect3DDevice9* device;
3986 D3DPRESENT_PARAMETERS d3dpp;
3987 ID3DXMesh* d3dxmesh = NULL;
3988 HFONT hFont;
3989 OUTLINETEXTMETRIC otm;
3990 int number_of_vertices;
3991 int number_of_faces;
3993 wnd = CreateWindow("static", "d3dx9_test", WS_POPUP, 0, 0, 1000, 1000, NULL, NULL, NULL, NULL);
3994 d3d = Direct3DCreate9(D3D_SDK_VERSION);
3995 if (!wnd)
3997 skip("Couldn't create application window\n");
3998 return;
4000 if (!d3d)
4002 skip("Couldn't create IDirect3D9 object\n");
4003 DestroyWindow(wnd);
4004 return;
4007 ZeroMemory(&d3dpp, sizeof(d3dpp));
4008 d3dpp.Windowed = TRUE;
4009 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
4010 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, wnd, D3DCREATE_MIXED_VERTEXPROCESSING, &d3dpp, &device);
4011 if (FAILED(hr))
4013 skip("Failed to create IDirect3DDevice9 object %#x\n", hr);
4014 IDirect3D9_Release(d3d);
4015 DestroyWindow(wnd);
4016 return;
4019 hdc = CreateCompatibleDC(NULL);
4021 hFont = CreateFont(12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET,
4022 OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE,
4023 "Arial");
4024 SelectObject(hdc, hFont);
4025 GetOutlineTextMetrics(hdc, sizeof(otm), &otm);
4027 hr = D3DXCreateText(device, hdc, "wine", 0.001f, 0.4f, NULL, NULL, NULL);
4028 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4030 /* D3DXCreateTextA page faults from passing NULL text */
4032 hr = D3DXCreateTextW(device, hdc, NULL, 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(device, hdc, " ", 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(NULL, hdc, "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, NULL, "wine", 0.001f, 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", -FLT_MIN, 0.4f, &d3dxmesh, NULL, NULL);
4048 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4050 hr = D3DXCreateText(device, hdc, "wine", 0.001f, -FLT_MIN, &d3dxmesh, NULL, NULL);
4051 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4053 /* deviation = 0.0f treated as if deviation = 1.0f / otm.otmEMSquare */
4054 hr = D3DXCreateText(device, hdc, "wine", 1.0f / otm.otmEMSquare, 0.4f, &d3dxmesh, NULL, NULL);
4055 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
4056 number_of_vertices = d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh);
4057 number_of_faces = d3dxmesh->lpVtbl->GetNumFaces(d3dxmesh);
4058 if (SUCCEEDED(hr) && d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh);
4060 hr = D3DXCreateText(device, hdc, "wine", 0.0f, 0.4f, &d3dxmesh, NULL, NULL);
4061 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
4062 ok(number_of_vertices == d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh),
4063 "Got %d vertices, expected %d\n",
4064 d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh), number_of_vertices);
4065 ok(number_of_faces == d3dxmesh->lpVtbl->GetNumFaces(d3dxmesh),
4066 "Got %d faces, expected %d\n",
4067 d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh), number_of_faces);
4068 if (SUCCEEDED(hr) && d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh);
4070 #if 0
4071 /* too much detail requested, so will appear to hang */
4072 trace("Waiting for D3DXCreateText to finish with deviation = FLT_MIN ...\n");
4073 hr = D3DXCreateText(device, hdc, "wine", FLT_MIN, 0.4f, &d3dxmesh, NULL, NULL);
4074 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
4075 if (SUCCEEDED(hr) && d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh);
4076 trace("D3DXCreateText finish with deviation = FLT_MIN\n");
4077 #endif
4079 hr = D3DXCreateText(device, hdc, "wine", 0.001f, 0.4f, &d3dxmesh, NULL, NULL);
4080 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
4081 if (SUCCEEDED(hr) && d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh);
4083 test_createtext(device, hdc, "wine", FLT_MAX, 0.4f);
4084 test_createtext(device, hdc, "wine", 0.001f, FLT_MIN);
4085 test_createtext(device, hdc, "wine", 0.001f, 0.0f);
4086 test_createtext(device, hdc, "wine", 0.001f, FLT_MAX);
4087 test_createtext(device, hdc, "wine", 0.0f, 1.0f);
4089 DeleteDC(hdc);
4091 IDirect3DDevice9_Release(device);
4092 IDirect3D9_Release(d3d);
4093 DestroyWindow(wnd);
4096 static void test_get_decl_length(void)
4098 static const D3DVERTEXELEMENT9 declaration1[] =
4100 {0, 0, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4101 {1, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4102 {2, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4103 {3, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4104 {4, 0, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4105 {5, 0, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4106 {6, 0, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4107 {7, 0, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4108 {8, 0, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4109 {9, 0, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4110 {10, 0, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4111 {11, 0, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4112 {12, 0, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4113 {13, 0, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4114 {14, 0, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4115 D3DDECL_END(),
4117 static const D3DVERTEXELEMENT9 declaration2[] =
4119 {0, 8, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4120 {1, 8, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4121 {2, 8, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4122 {3, 8, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4123 {4, 8, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4124 {5, 8, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4125 {6, 8, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4126 {7, 8, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4127 {0, 8, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4128 {1, 8, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4129 {2, 8, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4130 {3, 8, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4131 {4, 8, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4132 {5, 8, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4133 {6, 8, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4134 {7, 8, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4135 D3DDECL_END(),
4137 UINT size;
4139 size = D3DXGetDeclLength(declaration1);
4140 ok(size == 15, "Got size %u, expected 15.\n", size);
4142 size = D3DXGetDeclLength(declaration2);
4143 ok(size == 16, "Got size %u, expected 16.\n", size);
4146 static void test_get_decl_vertex_size(void)
4148 static const D3DVERTEXELEMENT9 declaration1[] =
4150 {0, 0, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4151 {1, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4152 {2, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4153 {3, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4154 {4, 0, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4155 {5, 0, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4156 {6, 0, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4157 {7, 0, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4158 {8, 0, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4159 {9, 0, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4160 {10, 0, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4161 {11, 0, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4162 {12, 0, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4163 {13, 0, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4164 {14, 0, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4165 D3DDECL_END(),
4167 static const D3DVERTEXELEMENT9 declaration2[] =
4169 {0, 8, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4170 {1, 8, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4171 {2, 8, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4172 {3, 8, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4173 {4, 8, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4174 {5, 8, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4175 {6, 8, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4176 {7, 8, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4177 {0, 8, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4178 {1, 8, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4179 {2, 8, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4180 {3, 8, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4181 {4, 8, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4182 {5, 8, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4183 {6, 8, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4184 {7, 8, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4185 D3DDECL_END(),
4187 static const UINT sizes1[] =
4189 4, 8, 12, 16,
4190 4, 4, 4, 8,
4191 4, 4, 8, 4,
4192 4, 4, 8, 0,
4194 static const UINT sizes2[] =
4196 12, 16, 20, 24,
4197 12, 12, 16, 16,
4199 unsigned int i;
4200 UINT size;
4202 size = D3DXGetDeclVertexSize(NULL, 0);
4203 ok(size == 0, "Got size %#x, expected 0.\n", size);
4205 for (i = 0; i < 16; ++i)
4207 size = D3DXGetDeclVertexSize(declaration1, i);
4208 ok(size == sizes1[i], "Got size %u for stream %u, expected %u.\n", size, i, sizes1[i]);
4211 for (i = 0; i < 8; ++i)
4213 size = D3DXGetDeclVertexSize(declaration2, i);
4214 ok(size == sizes2[i], "Got size %u for stream %u, expected %u.\n", size, i, sizes2[i]);
4218 static void D3DXGenerateAdjacencyTest(void)
4220 HRESULT hr;
4221 HWND wnd;
4222 IDirect3D9 *d3d;
4223 IDirect3DDevice9 *device;
4224 D3DPRESENT_PARAMETERS d3dpp;
4225 ID3DXMesh *d3dxmesh = NULL;
4226 D3DXVECTOR3 *vertices = NULL;
4227 WORD *indices = NULL;
4228 int i;
4229 struct {
4230 DWORD num_vertices;
4231 D3DXVECTOR3 vertices[6];
4232 DWORD num_faces;
4233 WORD indices[3 * 3];
4234 FLOAT epsilon;
4235 DWORD adjacency[3 * 3];
4236 } test_data[] = {
4237 { /* for epsilon < 0, indices must match for faces to be adjacent */
4238 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}},
4239 2, {0, 1, 2, 0, 2, 3},
4240 -1.0,
4241 {-1, -1, 1, 0, -1, -1},
4244 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}},
4245 2, {0, 1, 2, 3, 4, 5},
4246 -1.0,
4247 {-1, -1, -1, -1, -1, -1},
4249 { /* for epsilon == 0, indices or vertices must match for faces to be adjacent */
4250 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}},
4251 2, {0, 1, 2, 3, 4, 5},
4252 0.0,
4253 {-1, -1, 1, 0, -1, -1},
4255 { /* for epsilon > 0, vertices must be less than (but NOT equal to) epsilon distance away */
4256 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}},
4257 2, {0, 1, 2, 3, 4, 5},
4258 0.25,
4259 {-1, -1, -1, -1, -1, -1},
4261 { /* for epsilon > 0, vertices must be less than (but NOT equal to) epsilon distance away */
4262 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}},
4263 2, {0, 1, 2, 3, 4, 5},
4264 0.250001,
4265 {-1, -1, 1, 0, -1, -1},
4267 { /* length between vertices are compared to epsilon, not the individual dimension deltas */
4268 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}},
4269 2, {0, 1, 2, 3, 4, 5},
4270 0.353, /* < sqrt(0.25*0.25 + 0.25*0.25) */
4271 {-1, -1, -1, -1, -1, -1},
4274 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}},
4275 2, {0, 1, 2, 3, 4, 5},
4276 0.354, /* > sqrt(0.25*0.25 + 0.25*0.25) */
4277 {-1, -1, 1, 0, -1, -1},
4279 { /* adjacent faces must have opposite winding orders at the shared edge */
4280 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}},
4281 2, {0, 1, 2, 0, 3, 2},
4282 0.0,
4283 {-1, -1, -1, -1, -1, -1},
4287 wnd = CreateWindow("static", "d3dx9_test", 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL);
4288 if (!wnd)
4290 skip("Couldn't create application window\n");
4291 return;
4293 d3d = Direct3DCreate9(D3D_SDK_VERSION);
4294 if (!d3d)
4296 skip("Couldn't create IDirect3D9 object\n");
4297 DestroyWindow(wnd);
4298 return;
4301 ZeroMemory(&d3dpp, sizeof(d3dpp));
4302 d3dpp.Windowed = TRUE;
4303 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
4304 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, wnd, D3DCREATE_MIXED_VERTEXPROCESSING, &d3dpp, &device);
4305 if (FAILED(hr))
4307 skip("Failed to create IDirect3DDevice9 object %#x\n", hr);
4308 IDirect3D9_Release(d3d);
4309 DestroyWindow(wnd);
4310 return;
4313 for (i = 0; i < ARRAY_SIZE(test_data); i++)
4315 DWORD adjacency[ARRAY_SIZE(test_data[0].adjacency)];
4316 int j;
4318 if (d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh);
4319 d3dxmesh = NULL;
4321 hr = D3DXCreateMeshFVF(test_data[i].num_faces, test_data[i].num_vertices, 0, D3DFVF_XYZ, device, &d3dxmesh);
4322 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
4324 hr = d3dxmesh->lpVtbl->LockVertexBuffer(d3dxmesh, D3DLOCK_DISCARD, (void**)&vertices);
4325 ok(hr == D3D_OK, "test %d: Got result %x, expected %x (D3D_OK)\n", i, hr, D3D_OK);
4326 if (FAILED(hr)) continue;
4327 CopyMemory(vertices, test_data[i].vertices, test_data[i].num_vertices * sizeof(test_data[0].vertices[0]));
4328 d3dxmesh->lpVtbl->UnlockVertexBuffer(d3dxmesh);
4330 hr = d3dxmesh->lpVtbl->LockIndexBuffer(d3dxmesh, D3DLOCK_DISCARD, (void**)&indices);
4331 ok(hr == D3D_OK, "test %d: Got result %x, expected %x (D3D_OK)\n", i, hr, D3D_OK);
4332 if (FAILED(hr)) continue;
4333 CopyMemory(indices, test_data[i].indices, test_data[i].num_faces * 3 * sizeof(test_data[0].indices[0]));
4334 d3dxmesh->lpVtbl->UnlockIndexBuffer(d3dxmesh);
4336 if (i == 0) {
4337 hr = d3dxmesh->lpVtbl->GenerateAdjacency(d3dxmesh, 0.0f, NULL);
4338 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4341 hr = d3dxmesh->lpVtbl->GenerateAdjacency(d3dxmesh, test_data[i].epsilon, adjacency);
4342 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
4343 if (FAILED(hr)) continue;
4345 for (j = 0; j < test_data[i].num_faces * 3; j++)
4346 ok(adjacency[j] == test_data[i].adjacency[j],
4347 "Test %d adjacency %d: Got result %u, expected %u\n", i, j,
4348 adjacency[j], test_data[i].adjacency[j]);
4350 if (d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh);
4353 static void test_update_semantics(void)
4355 HRESULT hr;
4356 struct test_context *test_context = NULL;
4357 ID3DXMesh *mesh = NULL;
4358 D3DVERTEXELEMENT9 declaration0[] =
4360 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4361 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4362 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4363 D3DDECL_END()
4365 D3DVERTEXELEMENT9 declaration_pos_type_color[] =
4367 {0, 0, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4368 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4369 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4370 D3DDECL_END()
4372 D3DVERTEXELEMENT9 declaration_smaller[] =
4374 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4375 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4376 D3DDECL_END()
4378 D3DVERTEXELEMENT9 declaration_larger[] =
4380 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4381 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4382 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4383 {0, 40, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT, 0},
4384 D3DDECL_END()
4386 D3DVERTEXELEMENT9 declaration_multiple_streams[] =
4388 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4389 {1, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT, 0},
4390 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4391 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4393 D3DDECL_END()
4395 D3DVERTEXELEMENT9 declaration_double_usage[] =
4397 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4398 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4399 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4400 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4401 D3DDECL_END()
4403 D3DVERTEXELEMENT9 declaration_undefined_type[] =
4405 {0, 0, D3DDECLTYPE_UNUSED+1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4406 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4407 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4408 D3DDECL_END()
4410 D3DVERTEXELEMENT9 declaration_not_4_byte_aligned_offset[] =
4412 {0, 3, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4413 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4414 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4415 D3DDECL_END()
4417 static const struct
4419 D3DXVECTOR3 position0;
4420 D3DXVECTOR3 position1;
4421 D3DXVECTOR3 normal;
4422 DWORD color;
4424 vertices[] =
4426 { { 0.0f, 1.0f, 0.f}, { 1.0f, 0.0f, 0.f}, {0.0f, 0.0f, 1.0f}, 0xffff0000 },
4427 { { 1.0f, -1.0f, 0.f}, {-1.0f, -1.0f, 0.f}, {0.0f, 0.0f, 1.0f}, 0xff00ff00 },
4428 { {-1.0f, -1.0f, 0.f}, {-1.0f, 1.0f, 0.f}, {0.0f, 0.0f, 1.0f}, 0xff0000ff },
4430 unsigned int faces[] = {0, 1, 2};
4431 unsigned int attributes[] = {0};
4432 unsigned int num_faces = ARRAY_SIZE(faces) / 3;
4433 unsigned int num_vertices = ARRAY_SIZE(vertices);
4434 int offset = sizeof(D3DXVECTOR3);
4435 DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
4436 void *vertex_buffer;
4437 void *index_buffer;
4438 DWORD *attributes_buffer;
4439 D3DVERTEXELEMENT9 declaration[MAX_FVF_DECL_SIZE];
4440 D3DVERTEXELEMENT9 *decl_ptr;
4441 DWORD exp_vertex_size = sizeof(*vertices);
4442 DWORD vertex_size = 0;
4443 int equal;
4444 int i = 0;
4445 int *decl_mem;
4446 int filler_a = 0xaaaaaaaa;
4447 int filler_b = 0xbbbbbbbb;
4449 test_context = new_test_context();
4450 if (!test_context)
4452 skip("Couldn't create a test_context\n");
4453 goto cleanup;
4456 hr = D3DXCreateMesh(num_faces, num_vertices, options, declaration0,
4457 test_context->device, &mesh);
4458 if (FAILED(hr))
4460 skip("Couldn't create test mesh %#x\n", hr);
4461 goto cleanup;
4464 mesh->lpVtbl->LockVertexBuffer(mesh, 0, &vertex_buffer);
4465 memcpy(vertex_buffer, vertices, sizeof(vertices));
4466 mesh->lpVtbl->UnlockVertexBuffer(mesh);
4468 mesh->lpVtbl->LockIndexBuffer(mesh, 0, &index_buffer);
4469 memcpy(index_buffer, faces, sizeof(faces));
4470 mesh->lpVtbl->UnlockIndexBuffer(mesh);
4472 mesh->lpVtbl->LockAttributeBuffer(mesh, 0, &attributes_buffer);
4473 memcpy(attributes_buffer, attributes, sizeof(attributes));
4474 mesh->lpVtbl->UnlockAttributeBuffer(mesh);
4476 /* Get the declaration and try to change it */
4477 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4478 if (FAILED(hr))
4480 skip("Couldn't get vertex declaration %#x\n", hr);
4481 goto cleanup;
4483 equal = memcmp(declaration, declaration0, sizeof(declaration0));
4484 ok(equal == 0, "Vertex declarations were not equal\n");
4486 for (decl_ptr = declaration; decl_ptr->Stream != 0xFF; decl_ptr++)
4488 if (decl_ptr->Usage == D3DDECLUSAGE_POSITION)
4490 /* Use second vertex position instead of first */
4491 decl_ptr->Offset = offset;
4495 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration);
4496 ok(hr == D3D_OK, "Test UpdateSematics, got %#x expected %#x\n", hr, D3D_OK);
4498 /* Check that declaration was written by getting it again */
4499 memset(declaration, 0, sizeof(declaration));
4500 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4501 if (FAILED(hr))
4503 skip("Couldn't get vertex declaration %#x\n", hr);
4504 goto cleanup;
4507 for (decl_ptr = declaration; decl_ptr->Stream != 0xFF; decl_ptr++)
4509 if (decl_ptr->Usage == D3DDECLUSAGE_POSITION)
4511 ok(decl_ptr->Offset == offset, "Test UpdateSematics, got offset %d expected %d\n",
4512 decl_ptr->Offset, offset);
4516 /* Check that GetDeclaration only writes up to the D3DDECL_END() marker and
4517 * not the full MAX_FVF_DECL_SIZE elements.
4519 memset(declaration, filler_a, sizeof(declaration));
4520 memcpy(declaration, declaration0, sizeof(declaration0));
4521 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration);
4522 ok(hr == D3D_OK, "Test UpdateSematics, "
4523 "got %#x expected D3D_OK\n", hr);
4524 memset(declaration, filler_b, sizeof(declaration));
4525 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4526 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4527 decl_mem = (int*)declaration;
4528 for (i = sizeof(declaration0)/sizeof(*decl_mem); i < sizeof(declaration)/sizeof(*decl_mem); i++)
4530 equal = memcmp(&decl_mem[i], &filler_b, sizeof(filler_b));
4531 ok(equal == 0,
4532 "GetDeclaration wrote past the D3DDECL_END() marker. "
4533 "Got %#x, expected %#x\n", decl_mem[i], filler_b);
4534 if (equal != 0) break;
4537 /* UpdateSemantics does not check for overlapping fields */
4538 memset(declaration, 0, sizeof(declaration));
4539 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4540 if (FAILED(hr))
4542 skip("Couldn't get vertex declaration %#x\n", hr);
4543 goto cleanup;
4546 for (decl_ptr = declaration; decl_ptr->Stream != 0xFF; decl_ptr++)
4548 if (decl_ptr->Type == D3DDECLTYPE_FLOAT3)
4550 decl_ptr->Type = D3DDECLTYPE_FLOAT4;
4554 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration);
4555 ok(hr == D3D_OK, "Test UpdateSematics for overlapping fields, "
4556 "got %#x expected D3D_OK\n", hr);
4558 /* Set the position type to color instead of float3 */
4559 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_pos_type_color);
4560 ok(hr == D3D_OK, "Test UpdateSematics position type color, "
4561 "got %#x expected D3D_OK\n", hr);
4563 /* The following test cases show that NULL, smaller or larger declarations,
4564 * and declarations with non-zero Stream values are not accepted.
4565 * UpdateSemantics returns D3DERR_INVALIDCALL and the previously set
4566 * declaration will be used by DrawSubset, GetNumBytesPerVertex, and
4567 * GetDeclaration.
4570 /* Null declaration (invalid declaration) */
4571 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4572 hr = mesh->lpVtbl->UpdateSemantics(mesh, NULL);
4573 ok(hr == D3DERR_INVALIDCALL, "Test UpdateSematics null pointer declaration, "
4574 "got %#x expected D3DERR_INVALIDCALL\n", hr);
4575 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4576 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4577 vertex_size, exp_vertex_size);
4578 memset(declaration, 0, sizeof(declaration));
4579 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4580 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4581 equal = memcmp(declaration, declaration0, sizeof(declaration0));
4582 ok(equal == 0, "Vertex declarations were not equal\n");
4584 /* Smaller vertex declaration (invalid declaration) */
4585 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4586 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_smaller);
4587 ok(hr == D3DERR_INVALIDCALL, "Test UpdateSematics for smaller vertex declaration, "
4588 "got %#x expected D3DERR_INVALIDCALL\n", hr);
4589 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4590 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4591 vertex_size, exp_vertex_size);
4592 memset(declaration, 0, sizeof(declaration));
4593 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4594 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4595 equal = memcmp(declaration, declaration0, sizeof(declaration0));
4596 ok(equal == 0, "Vertex declarations were not equal\n");
4598 /* Larger vertex declaration (invalid declaration) */
4599 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4600 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_larger);
4601 ok(hr == D3DERR_INVALIDCALL, "Test UpdateSematics for larger vertex declaration, "
4602 "got %#x expected D3DERR_INVALIDCALL\n", hr);
4603 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4604 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4605 vertex_size, exp_vertex_size);
4606 memset(declaration, 0, sizeof(declaration));
4607 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4608 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4609 equal = memcmp(declaration, declaration0, sizeof(declaration0));
4610 ok(equal == 0, "Vertex declarations were not equal\n");
4612 /* Use multiple streams and keep the same vertex size (invalid declaration) */
4613 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4614 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_multiple_streams);
4615 ok(hr == D3DERR_INVALIDCALL, "Test UpdateSematics using multiple streams, "
4616 "got %#x expected D3DERR_INVALIDCALL\n", hr);
4617 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4618 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4619 vertex_size, exp_vertex_size);
4620 memset(declaration, 0, sizeof(declaration));
4621 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4622 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4623 equal = memcmp(declaration, declaration0, sizeof(declaration0));
4624 ok(equal == 0, "Vertex declarations were not equal\n");
4626 /* The next following test cases show that some invalid declarations are
4627 * accepted with a D3D_OK. An access violation is thrown on Windows if
4628 * DrawSubset is called. The methods GetNumBytesPerVertex and GetDeclaration
4629 * are not affected, which indicates that the declaration is cached.
4632 /* Double usage (invalid declaration) */
4633 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4634 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_double_usage);
4635 ok(hr == D3D_OK, "Test UpdateSematics double usage, "
4636 "got %#x expected D3D_OK\n", hr);
4637 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4638 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4639 vertex_size, exp_vertex_size);
4640 memset(declaration, 0, sizeof(declaration));
4641 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4642 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4643 equal = memcmp(declaration, declaration_double_usage, sizeof(declaration_double_usage));
4644 ok(equal == 0, "Vertex declarations were not equal\n");
4646 /* Set the position to an undefined type (invalid declaration) */
4647 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4648 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_undefined_type);
4649 ok(hr == D3D_OK, "Test UpdateSematics undefined type, "
4650 "got %#x expected D3D_OK\n", hr);
4651 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4652 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4653 vertex_size, exp_vertex_size);
4654 memset(declaration, 0, sizeof(declaration));
4655 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4656 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4657 equal = memcmp(declaration, declaration_undefined_type, sizeof(declaration_undefined_type));
4658 ok(equal == 0, "Vertex declarations were not equal\n");
4660 /* Use a not 4 byte aligned offset (invalid declaration) */
4661 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4662 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_not_4_byte_aligned_offset);
4663 ok(hr == D3D_OK, "Test UpdateSematics not 4 byte aligned offset, "
4664 "got %#x expected D3D_OK\n", hr);
4665 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4666 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4667 vertex_size, exp_vertex_size);
4668 memset(declaration, 0, sizeof(declaration));
4669 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4670 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4671 equal = memcmp(declaration, declaration_not_4_byte_aligned_offset,
4672 sizeof(declaration_not_4_byte_aligned_offset));
4673 ok(equal == 0, "Vertex declarations were not equal\n");
4675 cleanup:
4676 if (mesh)
4677 mesh->lpVtbl->Release(mesh);
4679 free_test_context(test_context);
4682 static void test_create_skin_info(void)
4684 HRESULT hr;
4685 ID3DXSkinInfo *skininfo = NULL;
4686 D3DVERTEXELEMENT9 empty_declaration[] = { D3DDECL_END() };
4687 D3DVERTEXELEMENT9 declaration_out[MAX_FVF_DECL_SIZE];
4688 const D3DVERTEXELEMENT9 declaration_with_nonzero_stream[] = {
4689 {1, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
4690 D3DDECL_END()
4693 hr = D3DXCreateSkinInfo(0, empty_declaration, 0, &skininfo);
4694 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4695 if (skininfo) IUnknown_Release(skininfo);
4696 skininfo = NULL;
4698 hr = D3DXCreateSkinInfo(1, NULL, 1, &skininfo);
4699 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4701 hr = D3DXCreateSkinInfo(1, declaration_with_nonzero_stream, 1, &skininfo);
4702 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4704 hr = D3DXCreateSkinInfoFVF(1, 0, 1, &skininfo);
4705 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4706 if (skininfo) {
4707 DWORD dword_result;
4708 FLOAT flt_result;
4709 LPCSTR string_result;
4710 D3DXMATRIX *transform;
4711 D3DXMATRIX identity_matrix;
4713 /* test initial values */
4714 hr = skininfo->lpVtbl->GetDeclaration(skininfo, declaration_out);
4715 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4716 if (SUCCEEDED(hr))
4717 compare_elements(declaration_out, empty_declaration, __LINE__, 0);
4719 dword_result = skininfo->lpVtbl->GetNumBones(skininfo);
4720 ok(dword_result == 1, "Expected 1, got %u\n", dword_result);
4722 flt_result = skininfo->lpVtbl->GetMinBoneInfluence(skininfo);
4723 ok(flt_result == 0.0f, "Expected 0.0, got %g\n", flt_result);
4725 string_result = skininfo->lpVtbl->GetBoneName(skininfo, 0);
4726 ok(string_result == NULL, "Expected NULL, got %p\n", string_result);
4728 dword_result = skininfo->lpVtbl->GetFVF(skininfo);
4729 ok(dword_result == 0, "Expected 0, got %u\n", dword_result);
4731 dword_result = skininfo->lpVtbl->GetNumBoneInfluences(skininfo, 0);
4732 ok(dword_result == 0, "Expected 0, got %u\n", dword_result);
4734 dword_result = skininfo->lpVtbl->GetNumBoneInfluences(skininfo, 1);
4735 ok(dword_result == 0, "Expected 0, got %u\n", dword_result);
4737 transform = skininfo->lpVtbl->GetBoneOffsetMatrix(skininfo, -1);
4738 ok(transform == NULL, "Expected NULL, got %p\n", transform);
4741 /* test [GS]etBoneOffsetMatrix */
4742 hr = skininfo->lpVtbl->SetBoneOffsetMatrix(skininfo, 1, &identity_matrix);
4743 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4745 hr = skininfo->lpVtbl->SetBoneOffsetMatrix(skininfo, 0, NULL);
4746 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4748 D3DXMatrixIdentity(&identity_matrix);
4749 hr = skininfo->lpVtbl->SetBoneOffsetMatrix(skininfo, 0, &identity_matrix);
4750 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4752 transform = skininfo->lpVtbl->GetBoneOffsetMatrix(skininfo, 0);
4753 check_matrix(transform, &identity_matrix);
4757 /* test [GS]etBoneName */
4758 const char *name_in = "testBoneName";
4759 const char *string_result2;
4761 hr = skininfo->lpVtbl->SetBoneName(skininfo, 1, name_in);
4762 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4764 hr = skininfo->lpVtbl->SetBoneName(skininfo, 0, NULL);
4765 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4767 hr = skininfo->lpVtbl->SetBoneName(skininfo, 0, name_in);
4768 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4770 string_result = skininfo->lpVtbl->GetBoneName(skininfo, 0);
4771 ok(string_result != NULL, "Expected non-NULL string, got %p\n", string_result);
4772 ok(!strcmp(string_result, name_in), "Expected '%s', got '%s'\n", name_in, string_result);
4774 string_result2 = skininfo->lpVtbl->GetBoneName(skininfo, 0);
4775 ok(string_result == string_result2, "Expected %p, got %p\n", string_result, string_result2);
4777 string_result = skininfo->lpVtbl->GetBoneName(skininfo, 1);
4778 ok(string_result == NULL, "Expected NULL, got %p\n", string_result);
4782 /* test [GS]etBoneInfluence */
4783 DWORD vertices[2];
4784 FLOAT weights[2];
4785 int i;
4786 DWORD num_influences;
4787 DWORD exp_vertices[2];
4788 FLOAT exp_weights[2];
4790 /* vertex and weight arrays untouched when num_influences is 0 */
4791 vertices[0] = 0xdeadbeef;
4792 weights[0] = FLT_MAX;
4793 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, vertices, weights);
4794 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4795 ok(vertices[0] == 0xdeadbeef, "expected 0xdeadbeef, got %#x\n", vertices[0]);
4796 ok(weights[0] == FLT_MAX, "expected %g, got %g\n", FLT_MAX, weights[0]);
4798 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 1, vertices, weights);
4799 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4801 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, NULL, NULL);
4802 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4804 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, vertices, NULL);
4805 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4807 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, NULL, weights);
4808 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4811 /* no vertex or weight value checking */
4812 exp_vertices[0] = 0;
4813 exp_vertices[1] = 0x87654321;
4814 exp_weights[0] = 0.5;
4815 exp_weights[1] = 0.0f / 0.0f; /* NAN */
4816 num_influences = 2;
4818 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 1, num_influences, vertices, weights);
4819 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4821 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, num_influences, NULL, weights);
4822 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4824 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, num_influences, vertices, NULL);
4825 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4827 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, num_influences, NULL, NULL);
4828 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4830 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, num_influences, exp_vertices, exp_weights);
4831 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4833 memset(vertices, 0, sizeof(vertices));
4834 memset(weights, 0, sizeof(weights));
4835 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, vertices, weights);
4836 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4837 for (i = 0; i < num_influences; i++) {
4838 ok(exp_vertices[i] == vertices[i],
4839 "influence[%d]: expected vertex %u, got %u\n", i, exp_vertices[i], vertices[i]);
4840 ok((isnan(exp_weights[i]) && isnan(weights[i])) || exp_weights[i] == weights[i],
4841 "influence[%d]: expected weights %g, got %g\n", i, exp_weights[i], weights[i]);
4844 /* vertices and weights aren't returned after setting num_influences to 0 */
4845 memset(vertices, 0, sizeof(vertices));
4846 memset(weights, 0, sizeof(weights));
4847 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, 0, vertices, weights);
4848 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4850 vertices[0] = 0xdeadbeef;
4851 weights[0] = FLT_MAX;
4852 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, vertices, weights);
4853 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4854 ok(vertices[0] == 0xdeadbeef, "expected vertex 0xdeadbeef, got %u\n", vertices[0]);
4855 ok(weights[0] == FLT_MAX, "expected weight %g, got %g\n", FLT_MAX, weights[0]);
4859 /* test [GS]etFVF and [GS]etDeclaration */
4860 D3DVERTEXELEMENT9 declaration_in[MAX_FVF_DECL_SIZE];
4861 DWORD fvf = D3DFVF_XYZ;
4862 DWORD got_fvf;
4864 hr = skininfo->lpVtbl->SetDeclaration(skininfo, NULL);
4865 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4867 hr = skininfo->lpVtbl->SetDeclaration(skininfo, declaration_with_nonzero_stream);
4868 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4870 hr = skininfo->lpVtbl->SetFVF(skininfo, 0);
4871 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4873 hr = D3DXDeclaratorFromFVF(fvf, declaration_in);
4874 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4875 hr = skininfo->lpVtbl->SetDeclaration(skininfo, declaration_in);
4876 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4877 got_fvf = skininfo->lpVtbl->GetFVF(skininfo);
4878 ok(fvf == got_fvf, "Expected %#x, got %#x\n", fvf, got_fvf);
4879 hr = skininfo->lpVtbl->GetDeclaration(skininfo, declaration_out);
4880 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4881 compare_elements(declaration_out, declaration_in, __LINE__, 0);
4883 hr = skininfo->lpVtbl->SetDeclaration(skininfo, empty_declaration);
4884 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4885 got_fvf = skininfo->lpVtbl->GetFVF(skininfo);
4886 ok(got_fvf == 0, "Expected 0, got %#x\n", got_fvf);
4887 hr = skininfo->lpVtbl->GetDeclaration(skininfo, declaration_out);
4888 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4889 compare_elements(declaration_out, empty_declaration, __LINE__, 0);
4891 hr = skininfo->lpVtbl->SetFVF(skininfo, fvf);
4892 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4893 got_fvf = skininfo->lpVtbl->GetFVF(skininfo);
4894 ok(fvf == got_fvf, "Expected %#x, got %#x\n", fvf, got_fvf);
4895 hr = skininfo->lpVtbl->GetDeclaration(skininfo, declaration_out);
4896 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4897 compare_elements(declaration_out, declaration_in, __LINE__, 0);
4900 if (skininfo) IUnknown_Release(skininfo);
4901 skininfo = NULL;
4903 hr = D3DXCreateSkinInfoFVF(1, D3DFVF_XYZ, 1, NULL);
4904 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4906 hr = D3DXCreateSkinInfo(1, NULL, 1, &skininfo);
4907 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4910 static void test_convert_adjacency_to_point_reps(void)
4912 HRESULT hr;
4913 struct test_context *test_context = NULL;
4914 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
4915 const DWORD options_16bit = D3DXMESH_SYSTEMMEM;
4916 const D3DVERTEXELEMENT9 declaration[] =
4918 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4919 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4920 {0, 24, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4921 D3DDECL_END()
4923 const unsigned int VERTS_PER_FACE = 3;
4924 void *vertex_buffer;
4925 void *index_buffer;
4926 DWORD *attributes_buffer;
4927 int i, j;
4928 enum color { RED = 0xffff0000, GREEN = 0xff00ff00, BLUE = 0xff0000ff};
4929 struct vertex_pnc
4931 D3DXVECTOR3 position;
4932 D3DXVECTOR3 normal;
4933 enum color color; /* In case of manual visual inspection */
4935 D3DXVECTOR3 up = {0.0f, 0.0f, 1.0f};
4936 /* mesh0 (one face)
4938 * 0--1
4939 * | /
4940 * |/
4943 const struct vertex_pnc vertices0[] =
4945 {{ 0.0f, 3.0f, 0.f}, up, RED},
4946 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
4947 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
4949 const DWORD indices0[] = {0, 1, 2};
4950 const unsigned int num_vertices0 = ARRAY_SIZE(vertices0);
4951 const unsigned int num_faces0 = ARRAY_SIZE(indices0) / VERTS_PER_FACE;
4952 const DWORD adjacency0[] = {-1, -1, -1};
4953 const DWORD exp_point_rep0[] = {0, 1, 2};
4954 /* mesh1 (right)
4956 * 0--1 3
4957 * | / /|
4958 * |/ / |
4959 * 2 5--4
4961 const struct vertex_pnc vertices1[] =
4963 {{ 0.0f, 3.0f, 0.f}, up, RED},
4964 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
4965 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
4967 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
4968 {{ 3.0f, 0.0f, 0.f}, up, RED},
4969 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
4971 const DWORD indices1[] = {0, 1, 2, 3, 4, 5};
4972 const unsigned int num_vertices1 = ARRAY_SIZE(vertices1);
4973 const unsigned int num_faces1 = ARRAY_SIZE(indices1) / VERTS_PER_FACE;
4974 const DWORD adjacency1[] = {-1, 1, -1, -1, -1, 0};
4975 const DWORD exp_point_rep1[] = {0, 1, 2, 1, 4, 2};
4976 /* mesh2 (left)
4978 * 3 0--1
4979 * /| | /
4980 * / | |/
4981 * 5--4 2
4983 const struct vertex_pnc vertices2[] =
4985 {{ 0.0f, 3.0f, 0.f}, up, RED},
4986 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
4987 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
4989 {{-1.0f, 3.0f, 0.f}, up, RED},
4990 {{-1.0f, 0.0f, 0.f}, up, GREEN},
4991 {{-3.0f, 0.0f, 0.f}, up, BLUE},
4993 const DWORD indices2[] = {0, 1, 2, 3, 4, 5};
4994 const unsigned int num_vertices2 = ARRAY_SIZE(vertices2);
4995 const unsigned int num_faces2 = ARRAY_SIZE(indices2) / VERTS_PER_FACE;
4996 const DWORD adjacency2[] = {-1, -1, 1, 0, -1, -1};
4997 const DWORD exp_point_rep2[] = {0, 1, 2, 0, 2, 5};
4998 /* mesh3 (above)
5001 * /|
5002 * / |
5003 * 5--4
5004 * 0--1
5005 * | /
5006 * |/
5009 struct vertex_pnc vertices3[] =
5011 {{ 0.0f, 3.0f, 0.f}, up, RED},
5012 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5013 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5015 {{ 2.0f, 7.0f, 0.f}, up, BLUE},
5016 {{ 2.0f, 4.0f, 0.f}, up, GREEN},
5017 {{ 0.0f, 4.0f, 0.f}, up, RED},
5019 const DWORD indices3[] = {0, 1, 2, 3, 4, 5};
5020 const unsigned int num_vertices3 = ARRAY_SIZE(vertices3);
5021 const unsigned int num_faces3 = ARRAY_SIZE(indices3) / VERTS_PER_FACE;
5022 const DWORD adjacency3[] = {1, -1, -1, -1, 0, -1};
5023 const DWORD exp_point_rep3[] = {0, 1, 2, 3, 1, 0};
5024 /* mesh4 (below, tip against tip)
5026 * 0--1
5027 * | /
5028 * |/
5031 * |\
5032 * | \
5033 * 5--4
5035 struct vertex_pnc vertices4[] =
5037 {{ 0.0f, 3.0f, 0.f}, up, RED},
5038 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5039 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5041 {{ 0.0f, -4.0f, 0.f}, up, BLUE},
5042 {{ 2.0f, -7.0f, 0.f}, up, GREEN},
5043 {{ 0.0f, -7.0f, 0.f}, up, RED},
5045 const DWORD indices4[] = {0, 1, 2, 3, 4, 5};
5046 const unsigned int num_vertices4 = ARRAY_SIZE(vertices4);
5047 const unsigned int num_faces4 = ARRAY_SIZE(indices4) / VERTS_PER_FACE;
5048 const DWORD adjacency4[] = {-1, -1, -1, -1, -1, -1};
5049 const DWORD exp_point_rep4[] = {0, 1, 2, 3, 4, 5};
5050 /* mesh5 (gap in mesh)
5052 * 0 3-----4 15
5053 * / \ \ / / \
5054 * / \ \ / / \
5055 * 2-----1 5 17-----16
5056 * 6-----7 9 12-----13
5057 * \ / / \ \ /
5058 * \ / / \ \ /
5059 * 8 10-----11 14
5062 const struct vertex_pnc vertices5[] =
5064 {{ 0.0f, 1.0f, 0.f}, up, RED},
5065 {{ 1.0f, -1.0f, 0.f}, up, GREEN},
5066 {{-1.0f, -1.0f, 0.f}, up, BLUE},
5068 {{ 0.1f, 1.0f, 0.f}, up, RED},
5069 {{ 2.1f, 1.0f, 0.f}, up, BLUE},
5070 {{ 1.1f, -1.0f, 0.f}, up, GREEN},
5072 {{-1.0f, -1.1f, 0.f}, up, BLUE},
5073 {{ 1.0f, -1.1f, 0.f}, up, GREEN},
5074 {{ 0.0f, -3.1f, 0.f}, up, RED},
5076 {{ 1.1f, -1.1f, 0.f}, up, GREEN},
5077 {{ 2.1f, -3.1f, 0.f}, up, BLUE},
5078 {{ 0.1f, -3.1f, 0.f}, up, RED},
5080 {{ 1.2f, -1.1f, 0.f}, up, GREEN},
5081 {{ 3.2f, -1.1f, 0.f}, up, RED},
5082 {{ 2.2f, -3.1f, 0.f}, up, BLUE},
5084 {{ 2.2f, 1.0f, 0.f}, up, BLUE},
5085 {{ 3.2f, -1.0f, 0.f}, up, RED},
5086 {{ 1.2f, -1.0f, 0.f}, up, GREEN},
5088 const DWORD indices5[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17};
5089 const unsigned int num_vertices5 = ARRAY_SIZE(vertices5);
5090 const unsigned int num_faces5 = ARRAY_SIZE(indices5) / VERTS_PER_FACE;
5091 const DWORD adjacency5[] = {-1, 2, -1, -1, 5, -1, 0, -1, -1, 4, -1, -1, 5, -1, 3, -1, 4, 1};
5092 const DWORD exp_point_rep5[] = {0, 1, 2, 3, 4, 5, 2, 1, 8, 5, 10, 11, 5, 13, 10, 4, 13, 5};
5093 const WORD indices5_16bit[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17};
5094 /* mesh6 (indices re-ordering)
5096 * 0--1 6 3
5097 * | / /| |\
5098 * |/ / | | \
5099 * 2 8--7 5--4
5101 const struct vertex_pnc vertices6[] =
5103 {{ 0.0f, 3.0f, 0.f}, up, RED},
5104 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5105 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5107 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5108 {{ 3.0f, 0.0f, 0.f}, up, RED},
5109 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5111 {{ 4.0f, 3.0f, 0.f}, up, GREEN},
5112 {{ 6.0f, 0.0f, 0.f}, up, BLUE},
5113 {{ 4.0f, 0.0f, 0.f}, up, RED},
5115 const DWORD indices6[] = {0, 1, 2, 6, 7, 8, 3, 4, 5};
5116 const unsigned int num_vertices6 = ARRAY_SIZE(vertices6);
5117 const unsigned int num_faces6 = ARRAY_SIZE(indices6) / VERTS_PER_FACE;
5118 const DWORD adjacency6[] = {-1, 1, -1, 2, -1, 0, -1, -1, 1};
5119 const DWORD exp_point_rep6[] = {0, 1, 2, 1, 4, 5, 1, 5, 2};
5120 /* mesh7 (expands collapsed triangle)
5122 * 0--1 3
5123 * | / /|
5124 * |/ / |
5125 * 2 5--4
5127 const struct vertex_pnc vertices7[] =
5129 {{ 0.0f, 3.0f, 0.f}, up, RED},
5130 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5131 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5133 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5134 {{ 3.0f, 0.0f, 0.f}, up, RED},
5135 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5137 const DWORD indices7[] = {0, 1, 2, 3, 3, 3}; /* Face 1 is collapsed*/
5138 const unsigned int num_vertices7 = ARRAY_SIZE(vertices7);
5139 const unsigned int num_faces7 = ARRAY_SIZE(indices7) / VERTS_PER_FACE;
5140 const DWORD adjacency7[] = {-1, -1, -1, -1, -1, -1};
5141 const DWORD exp_point_rep7[] = {0, 1, 2, 3, 4, 5};
5142 /* mesh8 (indices re-ordering and double replacement)
5144 * 0--1 9 6
5145 * | / /| |\
5146 * |/ / | | \
5147 * 2 11-10 8--7
5148 * 3--4
5149 * | /
5150 * |/
5153 const struct vertex_pnc vertices8[] =
5155 {{ 0.0f, 3.0f, 0.f}, up, RED},
5156 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5157 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5159 {{ 4.0, -4.0, 0.f}, up, RED},
5160 {{ 6.0, -4.0, 0.f}, up, BLUE},
5161 {{ 4.0, -7.0, 0.f}, up, GREEN},
5163 {{ 4.0f, 3.0f, 0.f}, up, GREEN},
5164 {{ 6.0f, 0.0f, 0.f}, up, BLUE},
5165 {{ 4.0f, 0.0f, 0.f}, up, RED},
5167 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5168 {{ 3.0f, 0.0f, 0.f}, up, RED},
5169 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5171 const DWORD indices8[] = {0, 1, 2, 9, 10, 11, 6, 7, 8, 3, 4, 5};
5172 const unsigned int num_vertices8 = ARRAY_SIZE(vertices8);
5173 const unsigned int num_faces8 = ARRAY_SIZE(indices8) / VERTS_PER_FACE;
5174 const DWORD adjacency8[] = {-1, 1, -1, 2, -1, 0, -1, 3, 1, 2, -1, -1};
5175 const DWORD exp_point_rep8[] = {0, 1, 2, 3, 4, 5, 1, 4, 3, 1, 3, 2};
5176 /* mesh9 (right, shared vertices)
5178 * 0--1
5179 * | /|
5180 * |/ |
5181 * 2--3
5183 const struct vertex_pnc vertices9[] =
5185 {{ 0.0f, 3.0f, 0.f}, up, RED},
5186 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5187 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5189 {{ 2.0f, 0.0f, 0.f}, up, RED},
5191 const DWORD indices9[] = {0, 1, 2, 1, 3, 2};
5192 const unsigned int num_vertices9 = ARRAY_SIZE(vertices9);
5193 const unsigned int num_faces9 = ARRAY_SIZE(indices9) / VERTS_PER_FACE;
5194 const DWORD adjacency9[] = {-1, 1, -1, -1, -1, 0};
5195 const DWORD exp_point_rep9[] = {0, 1, 2, 3};
5196 /* All mesh data */
5197 ID3DXMesh *mesh = NULL;
5198 ID3DXMesh *mesh_null_check = NULL;
5199 unsigned int attributes[] = {0};
5200 struct
5202 const struct vertex_pnc *vertices;
5203 const DWORD *indices;
5204 const DWORD num_vertices;
5205 const DWORD num_faces;
5206 const DWORD *adjacency;
5207 const DWORD *exp_point_reps;
5208 const DWORD options;
5210 tc[] =
5213 vertices0,
5214 indices0,
5215 num_vertices0,
5216 num_faces0,
5217 adjacency0,
5218 exp_point_rep0,
5219 options
5222 vertices1,
5223 indices1,
5224 num_vertices1,
5225 num_faces1,
5226 adjacency1,
5227 exp_point_rep1,
5228 options
5231 vertices2,
5232 indices2,
5233 num_vertices2,
5234 num_faces2,
5235 adjacency2,
5236 exp_point_rep2,
5237 options
5240 vertices3,
5241 indices3,
5242 num_vertices3,
5243 num_faces3,
5244 adjacency3,
5245 exp_point_rep3,
5246 options
5249 vertices4,
5250 indices4,
5251 num_vertices4,
5252 num_faces4,
5253 adjacency4,
5254 exp_point_rep4,
5255 options
5258 vertices5,
5259 indices5,
5260 num_vertices5,
5261 num_faces5,
5262 adjacency5,
5263 exp_point_rep5,
5264 options
5267 vertices6,
5268 indices6,
5269 num_vertices6,
5270 num_faces6,
5271 adjacency6,
5272 exp_point_rep6,
5273 options
5276 vertices7,
5277 indices7,
5278 num_vertices7,
5279 num_faces7,
5280 adjacency7,
5281 exp_point_rep7,
5282 options
5285 vertices8,
5286 indices8,
5287 num_vertices8,
5288 num_faces8,
5289 adjacency8,
5290 exp_point_rep8,
5291 options
5294 vertices9,
5295 indices9,
5296 num_vertices9,
5297 num_faces9,
5298 adjacency9,
5299 exp_point_rep9,
5300 options
5303 vertices5,
5304 (DWORD*)indices5_16bit,
5305 num_vertices5,
5306 num_faces5,
5307 adjacency5,
5308 exp_point_rep5,
5309 options_16bit
5312 DWORD *point_reps = NULL;
5314 test_context = new_test_context();
5315 if (!test_context)
5317 skip("Couldn't create test context\n");
5318 goto cleanup;
5321 for (i = 0; i < ARRAY_SIZE(tc); i++)
5323 hr = D3DXCreateMesh(tc[i].num_faces, tc[i].num_vertices, tc[i].options, declaration,
5324 test_context->device, &mesh);
5325 if (FAILED(hr))
5327 skip("Couldn't create mesh %d. Got %x expected D3D_OK\n", i, hr);
5328 goto cleanup;
5331 if (i == 0) /* Save first mesh for later NULL checks */
5332 mesh_null_check = mesh;
5334 point_reps = HeapAlloc(GetProcessHeap(), 0, tc[i].num_vertices * sizeof(*point_reps));
5335 if (!point_reps)
5337 skip("Couldn't allocate point reps array.\n");
5338 goto cleanup;
5341 hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, &vertex_buffer);
5342 if (FAILED(hr))
5344 skip("Couldn't lock vertex buffer.\n");
5345 goto cleanup;
5347 memcpy(vertex_buffer, tc[i].vertices, tc[i].num_vertices * sizeof(*tc[i].vertices));
5348 hr = mesh->lpVtbl->UnlockVertexBuffer(mesh);
5349 if (FAILED(hr))
5351 skip("Couldn't unlock vertex buffer.\n");
5352 goto cleanup;
5355 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, &index_buffer);
5356 if (FAILED(hr))
5358 skip("Couldn't lock index buffer.\n");
5359 goto cleanup;
5361 if (tc[i].options & D3DXMESH_32BIT)
5363 memcpy(index_buffer, tc[i].indices, VERTS_PER_FACE * tc[i].num_faces * sizeof(DWORD));
5365 else
5367 memcpy(index_buffer, tc[i].indices, VERTS_PER_FACE * tc[i].num_faces * sizeof(WORD));
5369 hr = mesh->lpVtbl->UnlockIndexBuffer(mesh);
5370 if (FAILED(hr)) {
5371 skip("Couldn't unlock index buffer.\n");
5372 goto cleanup;
5375 hr = mesh->lpVtbl->LockAttributeBuffer(mesh, 0, &attributes_buffer);
5376 if (FAILED(hr))
5378 skip("Couldn't lock attributes buffer.\n");
5379 goto cleanup;
5381 memcpy(attributes_buffer, attributes, sizeof(attributes));
5382 hr = mesh->lpVtbl->UnlockAttributeBuffer(mesh);
5383 if (FAILED(hr))
5385 skip("Couldn't unlock attributes buffer.\n");
5386 goto cleanup;
5389 /* Convert adjacency to point representation */
5390 for (j = 0; j < tc[i].num_vertices; j++) point_reps[j] = -1;
5391 hr = mesh->lpVtbl->ConvertAdjacencyToPointReps(mesh, tc[i].adjacency, point_reps);
5392 ok(hr == D3D_OK, "ConvertAdjacencyToPointReps failed case %d. "
5393 "Got %x expected D3D_OK\n", i, hr);
5395 /* Check point representation */
5396 for (j = 0; j < tc[i].num_vertices; j++)
5398 ok(point_reps[j] == tc[i].exp_point_reps[j],
5399 "Unexpected point representation at (%d, %d)."
5400 " Got %d expected %d\n",
5401 i, j, point_reps[j], tc[i].exp_point_reps[j]);
5404 HeapFree(GetProcessHeap(), 0, point_reps);
5405 point_reps = NULL;
5407 if (i != 0) /* First mesh will be freed during cleanup */
5408 mesh->lpVtbl->Release(mesh);
5411 /* NULL checks */
5412 hr = mesh_null_check->lpVtbl->ConvertAdjacencyToPointReps(mesh_null_check, tc[0].adjacency, NULL);
5413 ok(hr == D3DERR_INVALIDCALL, "ConvertAdjacencyToPointReps point_reps NULL. "
5414 "Got %x expected D3DERR_INVALIDCALL\n", hr);
5415 hr = mesh_null_check->lpVtbl->ConvertAdjacencyToPointReps(mesh_null_check, NULL, NULL);
5416 ok(hr == D3DERR_INVALIDCALL, "ConvertAdjacencyToPointReps adjacency and point_reps NULL. "
5417 "Got %x expected D3DERR_INVALIDCALL\n", hr);
5419 cleanup:
5420 if (mesh_null_check)
5421 mesh_null_check->lpVtbl->Release(mesh_null_check);
5422 HeapFree(GetProcessHeap(), 0, point_reps);
5423 free_test_context(test_context);
5426 static void test_convert_point_reps_to_adjacency(void)
5428 HRESULT hr;
5429 struct test_context *test_context = NULL;
5430 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
5431 const DWORD options_16bit = D3DXMESH_SYSTEMMEM;
5432 const D3DVERTEXELEMENT9 declaration[] =
5434 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
5435 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
5436 {0, 24, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
5437 D3DDECL_END()
5439 const unsigned int VERTS_PER_FACE = 3;
5440 void *vertex_buffer;
5441 void *index_buffer;
5442 DWORD *attributes_buffer;
5443 int i, j;
5444 enum color { RED = 0xffff0000, GREEN = 0xff00ff00, BLUE = 0xff0000ff};
5445 struct vertex_pnc
5447 D3DXVECTOR3 position;
5448 D3DXVECTOR3 normal;
5449 enum color color; /* In case of manual visual inspection */
5451 D3DXVECTOR3 up = {0.0f, 0.0f, 1.0f};
5452 /* mesh0 (one face)
5454 * 0--1
5455 * | /
5456 * |/
5459 const struct vertex_pnc vertices0[] =
5461 {{ 0.0f, 3.0f, 0.f}, up, RED},
5462 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5463 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5465 const DWORD indices0[] = {0, 1, 2};
5466 const unsigned int num_vertices0 = ARRAY_SIZE(vertices0);
5467 const unsigned int num_faces0 = num_vertices0 / VERTS_PER_FACE;
5468 const DWORD exp_adjacency0[] = {-1, -1, -1};
5469 const DWORD exp_id_adjacency0[] = {-1, -1, -1};
5470 const DWORD point_rep0[] = {0, 1, 2};
5471 /* mesh1 (right)
5473 * 0--1 3
5474 * | / /|
5475 * |/ / |
5476 * 2 5--4
5478 const struct vertex_pnc vertices1[] =
5480 {{ 0.0f, 3.0f, 0.f}, up, RED},
5481 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5482 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5484 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5485 {{ 3.0f, 0.0f, 0.f}, up, RED},
5486 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5488 const DWORD indices1[] = {0, 1, 2, 3, 4, 5};
5489 const unsigned int num_vertices1 = ARRAY_SIZE(vertices1);
5490 const unsigned int num_faces1 = num_vertices1 / VERTS_PER_FACE;
5491 const DWORD exp_adjacency1[] = {-1, 1, -1, -1, -1, 0};
5492 const DWORD exp_id_adjacency1[] = {-1, -1, -1, -1, -1, -1};
5493 const DWORD point_rep1[] = {0, 1, 2, 1, 4, 2};
5494 /* mesh2 (left)
5496 * 3 0--1
5497 * /| | /
5498 * / | |/
5499 * 5--4 2
5501 const struct vertex_pnc vertices2[] =
5503 {{ 0.0f, 3.0f, 0.f}, up, RED},
5504 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5505 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5507 {{-1.0f, 3.0f, 0.f}, up, RED},
5508 {{-1.0f, 0.0f, 0.f}, up, GREEN},
5509 {{-3.0f, 0.0f, 0.f}, up, BLUE},
5511 const DWORD indices2[] = {0, 1, 2, 3, 4, 5};
5512 const unsigned int num_vertices2 = ARRAY_SIZE(vertices2);
5513 const unsigned int num_faces2 = num_vertices2 / VERTS_PER_FACE;
5514 const DWORD exp_adjacency2[] = {-1, -1, 1, 0, -1, -1};
5515 const DWORD exp_id_adjacency2[] = {-1, -1, -1, -1, -1, -1};
5516 const DWORD point_rep2[] = {0, 1, 2, 0, 2, 5};
5517 /* mesh3 (above)
5520 * /|
5521 * / |
5522 * 5--4
5523 * 0--1
5524 * | /
5525 * |/
5528 struct vertex_pnc vertices3[] =
5530 {{ 0.0f, 3.0f, 0.f}, up, RED},
5531 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5532 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5534 {{ 2.0f, 7.0f, 0.f}, up, BLUE},
5535 {{ 2.0f, 4.0f, 0.f}, up, GREEN},
5536 {{ 0.0f, 4.0f, 0.f}, up, RED},
5538 const DWORD indices3[] = {0, 1, 2, 3, 4, 5};
5539 const unsigned int num_vertices3 = ARRAY_SIZE(vertices3);
5540 const unsigned int num_faces3 = num_vertices3 / VERTS_PER_FACE;
5541 const DWORD exp_adjacency3[] = {1, -1, -1, -1, 0, -1};
5542 const DWORD exp_id_adjacency3[] = {-1, -1, -1, -1, -1, -1};
5543 const DWORD point_rep3[] = {0, 1, 2, 3, 1, 0};
5544 /* mesh4 (below, tip against tip)
5546 * 0--1
5547 * | /
5548 * |/
5551 * |\
5552 * | \
5553 * 5--4
5555 struct vertex_pnc vertices4[] =
5557 {{ 0.0f, 3.0f, 0.f}, up, RED},
5558 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5559 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5561 {{ 0.0f, -4.0f, 0.f}, up, BLUE},
5562 {{ 2.0f, -7.0f, 0.f}, up, GREEN},
5563 {{ 0.0f, -7.0f, 0.f}, up, RED},
5565 const DWORD indices4[] = {0, 1, 2, 3, 4, 5};
5566 const unsigned int num_vertices4 = ARRAY_SIZE(vertices4);
5567 const unsigned int num_faces4 = num_vertices4 / VERTS_PER_FACE;
5568 const DWORD exp_adjacency4[] = {-1, -1, -1, -1, -1, -1};
5569 const DWORD exp_id_adjacency4[] = {-1, -1, -1, -1, -1, -1};
5570 const DWORD point_rep4[] = {0, 1, 2, 3, 4, 5};
5571 /* mesh5 (gap in mesh)
5573 * 0 3-----4 15
5574 * / \ \ / / \
5575 * / \ \ / / \
5576 * 2-----1 5 17-----16
5577 * 6-----7 9 12-----13
5578 * \ / / \ \ /
5579 * \ / / \ \ /
5580 * 8 10-----11 14
5583 const struct vertex_pnc vertices5[] =
5585 {{ 0.0f, 1.0f, 0.f}, up, RED},
5586 {{ 1.0f, -1.0f, 0.f}, up, GREEN},
5587 {{-1.0f, -1.0f, 0.f}, up, BLUE},
5589 {{ 0.1f, 1.0f, 0.f}, up, RED},
5590 {{ 2.1f, 1.0f, 0.f}, up, BLUE},
5591 {{ 1.1f, -1.0f, 0.f}, up, GREEN},
5593 {{-1.0f, -1.1f, 0.f}, up, BLUE},
5594 {{ 1.0f, -1.1f, 0.f}, up, GREEN},
5595 {{ 0.0f, -3.1f, 0.f}, up, RED},
5597 {{ 1.1f, -1.1f, 0.f}, up, GREEN},
5598 {{ 2.1f, -3.1f, 0.f}, up, BLUE},
5599 {{ 0.1f, -3.1f, 0.f}, up, RED},
5601 {{ 1.2f, -1.1f, 0.f}, up, GREEN},
5602 {{ 3.2f, -1.1f, 0.f}, up, RED},
5603 {{ 2.2f, -3.1f, 0.f}, up, BLUE},
5605 {{ 2.2f, 1.0f, 0.f}, up, BLUE},
5606 {{ 3.2f, -1.0f, 0.f}, up, RED},
5607 {{ 1.2f, -1.0f, 0.f}, up, GREEN},
5609 const DWORD indices5[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17};
5610 const unsigned int num_vertices5 = ARRAY_SIZE(vertices5);
5611 const unsigned int num_faces5 = num_vertices5 / VERTS_PER_FACE;
5612 const DWORD exp_adjacency5[] = {-1, 2, -1, -1, 5, -1, 0, -1, -1, 4, -1, -1, 5, -1, 3, -1, 4, 1};
5613 const DWORD exp_id_adjacency5[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
5614 const DWORD point_rep5[] = {0, 1, 2, 3, 4, 5, 2, 1, 8, 5, 10, 11, 5, 13, 10, 4, 13, 5};
5615 /* mesh6 (indices re-ordering)
5617 * 0--1 6 3
5618 * | / /| |\
5619 * |/ / | | \
5620 * 2 8--7 5--4
5622 const struct vertex_pnc vertices6[] =
5624 {{ 0.0f, 3.0f, 0.f}, up, RED},
5625 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5626 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5628 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5629 {{ 3.0f, 0.0f, 0.f}, up, RED},
5630 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5632 {{ 4.0f, 3.0f, 0.f}, up, GREEN},
5633 {{ 6.0f, 0.0f, 0.f}, up, BLUE},
5634 {{ 4.0f, 0.0f, 0.f}, up, RED},
5636 const DWORD indices6[] = {0, 1, 2, 6, 7, 8, 3, 4, 5};
5637 const unsigned int num_vertices6 = ARRAY_SIZE(vertices6);
5638 const unsigned int num_faces6 = num_vertices6 / VERTS_PER_FACE;
5639 const DWORD exp_adjacency6[] = {-1, 1, -1, 2, -1, 0, -1, -1, 1};
5640 const DWORD exp_id_adjacency6[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1};
5641 const DWORD point_rep6[] = {0, 1, 2, 1, 4, 5, 1, 5, 2};
5642 /* mesh7 (expands collapsed triangle)
5644 * 0--1 3
5645 * | / /|
5646 * |/ / |
5647 * 2 5--4
5649 const struct vertex_pnc vertices7[] =
5651 {{ 0.0f, 3.0f, 0.f}, up, RED},
5652 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5653 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5655 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5656 {{ 3.0f, 0.0f, 0.f}, up, RED},
5657 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5659 const DWORD indices7[] = {0, 1, 2, 3, 3, 3}; /* Face 1 is collapsed*/
5660 const unsigned int num_vertices7 = ARRAY_SIZE(vertices7);
5661 const unsigned int num_faces7 = num_vertices7 / VERTS_PER_FACE;
5662 const DWORD exp_adjacency7[] = {-1, -1, -1, -1, -1, -1};
5663 const DWORD exp_id_adjacency7[] = {-1, -1, -1, -1, -1, -1};
5664 const DWORD point_rep7[] = {0, 1, 2, 3, 4, 5};
5665 /* mesh8 (indices re-ordering and double replacement)
5667 * 0--1 9 6
5668 * | / /| |\
5669 * |/ / | | \
5670 * 2 11-10 8--7
5671 * 3--4
5672 * | /
5673 * |/
5676 const struct vertex_pnc vertices8[] =
5678 {{ 0.0f, 3.0f, 0.f}, up, RED},
5679 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5680 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5682 {{ 4.0, -4.0, 0.f}, up, RED},
5683 {{ 6.0, -4.0, 0.f}, up, BLUE},
5684 {{ 4.0, -7.0, 0.f}, up, GREEN},
5686 {{ 4.0f, 3.0f, 0.f}, up, GREEN},
5687 {{ 6.0f, 0.0f, 0.f}, up, BLUE},
5688 {{ 4.0f, 0.0f, 0.f}, up, RED},
5690 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5691 {{ 3.0f, 0.0f, 0.f}, up, RED},
5692 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5694 const DWORD indices8[] = {0, 1, 2, 9, 10, 11, 6, 7, 8, 3, 4, 5};
5695 const WORD indices8_16bit[] = {0, 1, 2, 9, 10, 11, 6, 7, 8, 3, 4, 5};
5696 const unsigned int num_vertices8 = ARRAY_SIZE(vertices8);
5697 const unsigned int num_faces8 = num_vertices8 / VERTS_PER_FACE;
5698 const DWORD exp_adjacency8[] = {-1, 1, -1, 2, -1, 0, -1, 3, 1, 2, -1, -1};
5699 const DWORD exp_id_adjacency8[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
5700 const DWORD point_rep8[] = {0, 1, 2, 3, 4, 5, 1, 4, 3, 1, 3, 2};
5701 /* mesh9 (right, shared vertices)
5703 * 0--1
5704 * | /|
5705 * |/ |
5706 * 2--3
5708 const struct vertex_pnc vertices9[] =
5710 {{ 0.0f, 3.0f, 0.f}, up, RED},
5711 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5712 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5714 {{ 2.0f, 0.0f, 0.f}, up, RED},
5716 const DWORD indices9[] = {0, 1, 2, 1, 3, 2};
5717 const unsigned int num_vertices9 = ARRAY_SIZE(vertices9);
5718 const unsigned int num_faces9 = 2;
5719 const DWORD exp_adjacency9[] = {-1, 1, -1, -1, -1, 0};
5720 const DWORD exp_id_adjacency9[] = {-1, 1, -1, -1, -1, 0};
5721 const DWORD point_rep9[] = {0, 1, 2, 3};
5722 /* All mesh data */
5723 ID3DXMesh *mesh = NULL;
5724 ID3DXMesh *mesh_null_check = NULL;
5725 unsigned int attributes[] = {0};
5726 struct
5728 const struct vertex_pnc *vertices;
5729 const DWORD *indices;
5730 const DWORD num_vertices;
5731 const DWORD num_faces;
5732 const DWORD *point_reps;
5733 const DWORD *exp_adjacency;
5734 const DWORD *exp_id_adjacency;
5735 const DWORD options;
5737 tc[] =
5740 vertices0,
5741 indices0,
5742 num_vertices0,
5743 num_faces0,
5744 point_rep0,
5745 exp_adjacency0,
5746 exp_id_adjacency0,
5747 options
5750 vertices1,
5751 indices1,
5752 num_vertices1,
5753 num_faces1,
5754 point_rep1,
5755 exp_adjacency1,
5756 exp_id_adjacency1,
5757 options
5760 vertices2,
5761 indices2,
5762 num_vertices2,
5763 num_faces2,
5764 point_rep2,
5765 exp_adjacency2,
5766 exp_id_adjacency2,
5767 options
5770 vertices3,
5771 indices3,
5772 num_vertices3,
5773 num_faces3,
5774 point_rep3,
5775 exp_adjacency3,
5776 exp_id_adjacency3,
5777 options
5780 vertices4,
5781 indices4,
5782 num_vertices4,
5783 num_faces4,
5784 point_rep4,
5785 exp_adjacency4,
5786 exp_id_adjacency4,
5787 options
5790 vertices5,
5791 indices5,
5792 num_vertices5,
5793 num_faces5,
5794 point_rep5,
5795 exp_adjacency5,
5796 exp_id_adjacency5,
5797 options
5800 vertices6,
5801 indices6,
5802 num_vertices6,
5803 num_faces6,
5804 point_rep6,
5805 exp_adjacency6,
5806 exp_id_adjacency6,
5807 options
5810 vertices7,
5811 indices7,
5812 num_vertices7,
5813 num_faces7,
5814 point_rep7,
5815 exp_adjacency7,
5816 exp_id_adjacency7,
5817 options
5820 vertices8,
5821 indices8,
5822 num_vertices8,
5823 num_faces8,
5824 point_rep8,
5825 exp_adjacency8,
5826 exp_id_adjacency8,
5827 options
5830 vertices9,
5831 indices9,
5832 num_vertices9,
5833 num_faces9,
5834 point_rep9,
5835 exp_adjacency9,
5836 exp_id_adjacency9,
5837 options
5840 vertices8,
5841 (DWORD*)indices8_16bit,
5842 num_vertices8,
5843 num_faces8,
5844 point_rep8,
5845 exp_adjacency8,
5846 exp_id_adjacency8,
5847 options_16bit
5850 DWORD *adjacency = NULL;
5852 test_context = new_test_context();
5853 if (!test_context)
5855 skip("Couldn't create test context\n");
5856 goto cleanup;
5859 for (i = 0; i < ARRAY_SIZE(tc); i++)
5861 hr = D3DXCreateMesh(tc[i].num_faces, tc[i].num_vertices, tc[i].options,
5862 declaration, test_context->device, &mesh);
5863 if (FAILED(hr))
5865 skip("Couldn't create mesh %d. Got %x expected D3D_OK\n", i, hr);
5866 goto cleanup;
5869 if (i == 0) /* Save first mesh for later NULL checks */
5870 mesh_null_check = mesh;
5872 adjacency = HeapAlloc(GetProcessHeap(), 0, VERTS_PER_FACE * tc[i].num_faces * sizeof(*adjacency));
5873 if (!adjacency)
5875 skip("Couldn't allocate adjacency array.\n");
5876 goto cleanup;
5879 hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, &vertex_buffer);
5880 if (FAILED(hr))
5882 skip("Couldn't lock vertex buffer.\n");
5883 goto cleanup;
5885 memcpy(vertex_buffer, tc[i].vertices, tc[i].num_vertices * sizeof(*tc[i].vertices));
5886 hr = mesh->lpVtbl->UnlockVertexBuffer(mesh);
5887 if (FAILED(hr))
5889 skip("Couldn't unlock vertex buffer.\n");
5890 goto cleanup;
5892 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, &index_buffer);
5893 if (FAILED(hr))
5895 skip("Couldn't lock index buffer.\n");
5896 goto cleanup;
5898 if (tc[i].options & D3DXMESH_32BIT)
5900 memcpy(index_buffer, tc[i].indices, VERTS_PER_FACE * tc[i].num_faces * sizeof(DWORD));
5902 else
5904 memcpy(index_buffer, tc[i].indices, VERTS_PER_FACE * tc[i].num_faces * sizeof(WORD));
5906 hr = mesh->lpVtbl->UnlockIndexBuffer(mesh);
5907 if (FAILED(hr)) {
5908 skip("Couldn't unlock index buffer.\n");
5909 goto cleanup;
5912 hr = mesh->lpVtbl->LockAttributeBuffer(mesh, 0, &attributes_buffer);
5913 if (FAILED(hr))
5915 skip("Couldn't lock attributes buffer.\n");
5916 goto cleanup;
5918 memcpy(attributes_buffer, attributes, sizeof(attributes));
5919 hr = mesh->lpVtbl->UnlockAttributeBuffer(mesh);
5920 if (FAILED(hr))
5922 skip("Couldn't unlock attributes buffer.\n");
5923 goto cleanup;
5926 /* Convert point representation to adjacency*/
5927 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++) adjacency[j] = -2;
5929 hr = mesh->lpVtbl->ConvertPointRepsToAdjacency(mesh, tc[i].point_reps, adjacency);
5930 ok(hr == D3D_OK, "ConvertPointRepsToAdjacency failed case %d. "
5931 "Got %x expected D3D_OK\n", i, hr);
5932 /* Check adjacency */
5933 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
5935 ok(adjacency[j] == tc[i].exp_adjacency[j],
5936 "Unexpected adjacency information at (%d, %d)."
5937 " Got %d expected %d\n",
5938 i, j, adjacency[j], tc[i].exp_adjacency[j]);
5941 /* NULL point representation is considered identity. */
5942 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++) adjacency[j] = -2;
5943 hr = mesh_null_check->lpVtbl->ConvertPointRepsToAdjacency(mesh, NULL, adjacency);
5944 ok(hr == D3D_OK, "ConvertPointRepsToAdjacency NULL point_reps. "
5945 "Got %x expected D3D_OK\n", hr);
5946 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
5948 ok(adjacency[j] == tc[i].exp_id_adjacency[j],
5949 "Unexpected adjacency information (id) at (%d, %d)."
5950 " Got %d expected %d\n",
5951 i, j, adjacency[j], tc[i].exp_id_adjacency[j]);
5954 HeapFree(GetProcessHeap(), 0, adjacency);
5955 adjacency = NULL;
5956 if (i != 0) /* First mesh will be freed during cleanup */
5957 mesh->lpVtbl->Release(mesh);
5960 /* NULL checks */
5961 hr = mesh_null_check->lpVtbl->ConvertPointRepsToAdjacency(mesh_null_check, tc[0].point_reps, NULL);
5962 ok(hr == D3DERR_INVALIDCALL, "ConvertPointRepsToAdjacency NULL adjacency. "
5963 "Got %x expected D3DERR_INVALIDCALL\n", hr);
5964 hr = mesh_null_check->lpVtbl->ConvertPointRepsToAdjacency(mesh_null_check, NULL, NULL);
5965 ok(hr == D3DERR_INVALIDCALL, "ConvertPointRepsToAdjacency NULL point_reps and adjacency. "
5966 "Got %x expected D3DERR_INVALIDCALL\n", hr);
5968 cleanup:
5969 if (mesh_null_check)
5970 mesh_null_check->lpVtbl->Release(mesh_null_check);
5971 HeapFree(GetProcessHeap(), 0, adjacency);
5972 free_test_context(test_context);
5975 static HRESULT init_test_mesh(const DWORD num_faces, const DWORD num_vertices,
5976 const DWORD options,
5977 const D3DVERTEXELEMENT9 *declaration,
5978 IDirect3DDevice9 *device, ID3DXMesh **mesh_ptr,
5979 const void *vertices, const DWORD vertex_size,
5980 const DWORD *indices, const DWORD *attributes)
5982 HRESULT hr;
5983 void *vertex_buffer;
5984 void *index_buffer;
5985 DWORD *attributes_buffer;
5986 ID3DXMesh *mesh = NULL;
5988 hr = D3DXCreateMesh(num_faces, num_vertices, options, declaration, device, mesh_ptr);
5989 if (FAILED(hr))
5991 skip("Couldn't create mesh. Got %x expected D3D_OK\n", hr);
5992 goto cleanup;
5994 mesh = *mesh_ptr;
5996 hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, &vertex_buffer);
5997 if (FAILED(hr))
5999 skip("Couldn't lock vertex buffer.\n");
6000 goto cleanup;
6002 memcpy(vertex_buffer, vertices, num_vertices * vertex_size);
6003 hr = mesh->lpVtbl->UnlockVertexBuffer(mesh);
6004 if (FAILED(hr))
6006 skip("Couldn't unlock vertex buffer.\n");
6007 goto cleanup;
6010 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, &index_buffer);
6011 if (FAILED(hr))
6013 skip("Couldn't lock index buffer.\n");
6014 goto cleanup;
6016 if (options & D3DXMESH_32BIT)
6018 if (indices)
6019 memcpy(index_buffer, indices, 3 * num_faces * sizeof(DWORD));
6020 else
6022 /* Fill index buffer with 0, 1, 2, ...*/
6023 DWORD *indices_32bit = (DWORD*)index_buffer;
6024 UINT i;
6025 for (i = 0; i < 3 * num_faces; i++)
6026 indices_32bit[i] = i;
6029 else
6031 if (indices)
6032 memcpy(index_buffer, indices, 3 * num_faces * sizeof(WORD));
6033 else
6035 /* Fill index buffer with 0, 1, 2, ...*/
6036 WORD *indices_16bit = (WORD*)index_buffer;
6037 UINT i;
6038 for (i = 0; i < 3 * num_faces; i++)
6039 indices_16bit[i] = i;
6042 hr = mesh->lpVtbl->UnlockIndexBuffer(mesh);
6043 if (FAILED(hr)) {
6044 skip("Couldn't unlock index buffer.\n");
6045 goto cleanup;
6048 hr = mesh->lpVtbl->LockAttributeBuffer(mesh, 0, &attributes_buffer);
6049 if (FAILED(hr))
6051 skip("Couldn't lock attributes buffer.\n");
6052 goto cleanup;
6055 if (attributes)
6056 memcpy(attributes_buffer, attributes, num_faces * sizeof(*attributes));
6057 else
6058 memset(attributes_buffer, 0, num_faces * sizeof(*attributes));
6060 hr = mesh->lpVtbl->UnlockAttributeBuffer(mesh);
6061 if (FAILED(hr))
6063 skip("Couldn't unlock attributes buffer.\n");
6064 goto cleanup;
6067 hr = D3D_OK;
6068 cleanup:
6069 return hr;
6072 /* Using structs instead of bit-fields in order to avoid compiler issues. */
6073 struct udec3
6075 UINT x;
6076 UINT y;
6077 UINT z;
6078 UINT w;
6081 struct dec3n
6083 INT x;
6084 INT y;
6085 INT z;
6086 INT w;
6089 static DWORD init_udec3_dword(UINT x, UINT y, UINT z, UINT w)
6091 DWORD d = 0;
6093 d |= x & 0x3ff;
6094 d |= (y << 10) & 0xffc00;
6095 d |= (z << 20) & 0x3ff00000;
6096 d |= (w << 30) & 0xc0000000;
6098 return d;
6101 static DWORD init_dec3n_dword(INT x, INT y, INT z, INT w)
6103 DWORD d = 0;
6105 d |= x & 0x3ff;
6106 d |= (y << 10) & 0xffc00;
6107 d |= (z << 20) & 0x3ff00000;
6108 d |= (w << 30) & 0xc0000000;
6110 return d;
6113 static struct udec3 dword_to_udec3(DWORD d)
6115 struct udec3 v;
6117 v.x = d & 0x3ff;
6118 v.y = (d & 0xffc00) >> 10;
6119 v.z = (d & 0x3ff00000) >> 20;
6120 v.w = (d & 0xc0000000) >> 30;
6122 return v;
6125 static struct dec3n dword_to_dec3n(DWORD d)
6127 struct dec3n v;
6129 v.x = d & 0x3ff;
6130 v.y = (d & 0xffc00) >> 10;
6131 v.z = (d & 0x3ff00000) >> 20;
6132 v.w = (d & 0xc0000000) >> 30;
6134 return v;
6137 static void check_vertex_components(int line, int mesh_number, int vertex_number, BYTE *got_ptr, const BYTE *exp_ptr, D3DVERTEXELEMENT9 *declaration)
6139 const char *usage_strings[] =
6141 "position",
6142 "blend weight",
6143 "blend indices",
6144 "normal",
6145 "point size",
6146 "texture coordinates",
6147 "tangent",
6148 "binormal",
6149 "tessellation factor",
6150 "position transformed",
6151 "color",
6152 "fog",
6153 "depth",
6154 "sample"
6156 D3DVERTEXELEMENT9 *decl_ptr;
6157 const float PRECISION = 1e-5f;
6159 for (decl_ptr = declaration; decl_ptr->Stream != 0xFF; decl_ptr++)
6161 switch (decl_ptr->Type)
6163 case D3DDECLTYPE_FLOAT1:
6165 FLOAT *got = (FLOAT*)(got_ptr + decl_ptr->Offset);
6166 FLOAT *exp = (FLOAT*)(exp_ptr + decl_ptr->Offset);
6167 FLOAT diff = fabsf(*got - *exp);
6168 ok_(__FILE__,line)(diff <= PRECISION, "Mesh %d: Got %f for vertex %d %s, expected %f.\n",
6169 mesh_number, *got, vertex_number, usage_strings[decl_ptr->Usage], *exp);
6170 break;
6172 case D3DDECLTYPE_FLOAT2:
6174 D3DXVECTOR2 *got = (D3DXVECTOR2*)(got_ptr + decl_ptr->Offset);
6175 D3DXVECTOR2 *exp = (D3DXVECTOR2*)(exp_ptr + decl_ptr->Offset);
6176 FLOAT diff = max(fabsf(got->x - exp->x), fabsf(got->y - exp->y));
6177 ok_(__FILE__,line)(diff <= PRECISION, "Mesh %d: Got (%f, %f) for vertex %d %s, expected (%f, %f).\n",
6178 mesh_number, got->x, got->y, vertex_number, usage_strings[decl_ptr->Usage], exp->x, exp->y);
6179 break;
6181 case D3DDECLTYPE_FLOAT3:
6183 D3DXVECTOR3 *got = (D3DXVECTOR3*)(got_ptr + decl_ptr->Offset);
6184 D3DXVECTOR3 *exp = (D3DXVECTOR3*)(exp_ptr + decl_ptr->Offset);
6185 FLOAT diff = max(fabsf(got->x - exp->x), fabsf(got->y - exp->y));
6186 diff = max(diff, fabsf(got->z - exp->z));
6187 ok_(__FILE__,line)(diff <= PRECISION, "Mesh %d: Got (%f, %f, %f) for vertex %d %s, expected (%f, %f, %f).\n",
6188 mesh_number, got->x, got->y, got->z, vertex_number, usage_strings[decl_ptr->Usage], exp->x, exp->y, exp->z);
6189 break;
6191 case D3DDECLTYPE_FLOAT4:
6193 D3DXVECTOR4 *got = (D3DXVECTOR4*)(got_ptr + decl_ptr->Offset);
6194 D3DXVECTOR4 *exp = (D3DXVECTOR4*)(exp_ptr + decl_ptr->Offset);
6195 FLOAT diff = max(fabsf(got->x - exp->x), fabsf(got->y - exp->y));
6196 diff = max(diff, fabsf(got->z - exp->z));
6197 diff = max(diff, fabsf(got->w - exp->w));
6198 ok_(__FILE__,line)(diff <= PRECISION, "Mesh %d: Got (%f, %f, %f, %f) for vertex %d %s, expected (%f, %f, %f, %f).\n",
6199 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);
6200 break;
6202 case D3DDECLTYPE_D3DCOLOR:
6204 BYTE *got = got_ptr + decl_ptr->Offset;
6205 const BYTE *exp = exp_ptr + decl_ptr->Offset;
6206 BOOL same_color = got[0] == exp[0] && got[1] == exp[1]
6207 && got[2] == exp[2] && got[3] == exp[3];
6208 const char *color_types[] = {"diffuse", "specular", "undefined color"};
6209 BYTE usage_index = decl_ptr->UsageIndex;
6210 if (usage_index > 1) usage_index = 2;
6211 ok_(__FILE__,line)(same_color, "Mesh %d: Got (%u, %u, %u, %u) for vertex %d %s, expected (%u, %u, %u, %u).\n",
6212 mesh_number, got[0], got[1], got[2], got[3], vertex_number, color_types[usage_index], exp[0], exp[1], exp[2], exp[3]);
6213 break;
6215 case D3DDECLTYPE_UBYTE4:
6216 case D3DDECLTYPE_UBYTE4N:
6218 BYTE *got = got_ptr + decl_ptr->Offset;
6219 const BYTE *exp = exp_ptr + decl_ptr->Offset;
6220 BOOL same = got[0] == exp[0] && got[1] == exp[1]
6221 && got[2] == exp[2] && got[3] == exp[3];
6222 ok_(__FILE__,line)(same, "Mesh %d: Got (%u, %u, %u, %u) for vertex %d %s, expected (%u, %u, %u, %u).\n",
6223 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]);
6224 break;
6226 case D3DDECLTYPE_SHORT2:
6227 case D3DDECLTYPE_SHORT2N:
6229 SHORT *got = (SHORT*)(got_ptr + decl_ptr->Offset);
6230 SHORT *exp = (SHORT*)(exp_ptr + decl_ptr->Offset);
6231 BOOL same = got[0] == exp[0] && got[1] == exp[1];
6232 ok_(__FILE__,line)(same, "Mesh %d: Got (%hd, %hd) for vertex %d %s, expected (%hd, %hd).\n",
6233 mesh_number, got[0], got[1], vertex_number, usage_strings[decl_ptr->Usage], exp[0], exp[1]);
6234 break;
6236 case D3DDECLTYPE_SHORT4:
6237 case D3DDECLTYPE_SHORT4N:
6239 SHORT *got = (SHORT*)(got_ptr + decl_ptr->Offset);
6240 SHORT *exp = (SHORT*)(exp_ptr + decl_ptr->Offset);
6241 BOOL same = got[0] == exp[0] && got[1] == exp[1]
6242 && got[2] == exp[2] && got[3] == exp[3];
6243 ok_(__FILE__,line)(same, "Mesh %d: Got (%hd, %hd, %hd, %hd) for vertex %d %s, expected (%hd, %hd, %hd, %hd).\n",
6244 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]);
6245 break;
6247 case D3DDECLTYPE_USHORT2N:
6249 USHORT *got = (USHORT*)(got_ptr + decl_ptr->Offset);
6250 USHORT *exp = (USHORT*)(exp_ptr + decl_ptr->Offset);
6251 BOOL same = got[0] == exp[0] && got[1] == exp[1];
6252 ok_(__FILE__,line)(same, "Mesh %d: Got (%hu, %hu) for vertex %d %s, expected (%hu, %hu).\n",
6253 mesh_number, got[0], got[1], vertex_number, usage_strings[decl_ptr->Usage], exp[0], exp[1]);
6254 break;
6256 case D3DDECLTYPE_USHORT4N:
6258 USHORT *got = (USHORT*)(got_ptr + decl_ptr->Offset);
6259 USHORT *exp = (USHORT*)(exp_ptr + decl_ptr->Offset);
6260 BOOL same = got[0] == exp[0] && got[1] == exp[1]
6261 && got[2] == exp[2] && got[3] == exp[3];
6262 ok_(__FILE__,line)(same, "Mesh %d: Got (%hu, %hu, %hu, %hu) for vertex %d %s, expected (%hu, %hu, %hu, %hu).\n",
6263 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]);
6264 break;
6266 case D3DDECLTYPE_UDEC3:
6268 DWORD *got = (DWORD*)(got_ptr + decl_ptr->Offset);
6269 DWORD *exp = (DWORD*)(exp_ptr + decl_ptr->Offset);
6270 BOOL same = memcmp(got, exp, sizeof(*got)) == 0;
6271 struct udec3 got_udec3 = dword_to_udec3(*got);
6272 struct udec3 exp_udec3 = dword_to_udec3(*exp);
6273 ok_(__FILE__,line)(same, "Mesh %d: Got (%u, %u, %u, %u) for vertex %d %s, expected (%u, %u, %u, %u).\n",
6274 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);
6276 break;
6278 case D3DDECLTYPE_DEC3N:
6280 DWORD *got = (DWORD*)(got_ptr + decl_ptr->Offset);
6281 DWORD *exp = (DWORD*)(exp_ptr + decl_ptr->Offset);
6282 BOOL same = memcmp(got, exp, sizeof(*got)) == 0;
6283 struct dec3n got_dec3n = dword_to_dec3n(*got);
6284 struct dec3n exp_dec3n = dword_to_dec3n(*exp);
6285 ok_(__FILE__,line)(same, "Mesh %d: Got (%d, %d, %d, %d) for vertex %d %s, expected (%d, %d, %d, %d).\n",
6286 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);
6287 break;
6289 case D3DDECLTYPE_FLOAT16_2:
6291 WORD *got = (WORD*)(got_ptr + decl_ptr->Offset);
6292 WORD *exp = (WORD*)(exp_ptr + decl_ptr->Offset);
6293 BOOL same = got[0] == exp[0] && got[1] == exp[1];
6294 ok_(__FILE__,line)(same, "Mesh %d: Got (%hx, %hx) for vertex %d %s, expected (%hx, %hx).\n",
6295 mesh_number, got[0], got[1], vertex_number, usage_strings[decl_ptr->Usage], exp[0], exp[1]);
6296 break;
6298 case D3DDECLTYPE_FLOAT16_4:
6300 WORD *got = (WORD*)(got_ptr + decl_ptr->Offset);
6301 WORD *exp = (WORD*)(exp_ptr + decl_ptr->Offset);
6302 BOOL same = got[0] == exp[0] && got[1] == exp[1]
6303 && got[2] == exp[2] && got[3] == exp[3];
6304 ok_(__FILE__,line)(same, "Mesh %d: Got (%hx, %hx, %hx, %hx) for vertex %d %s, expected (%hx, %hx, %hx, %hx).\n",
6305 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]);
6306 break;
6308 default:
6309 break;
6314 static void test_weld_vertices(void)
6316 HRESULT hr;
6317 struct test_context *test_context = NULL;
6318 DWORD i;
6319 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
6320 const DWORD options_16bit = D3DXMESH_SYSTEMMEM;
6321 BYTE *vertices = NULL;
6322 DWORD *indices = NULL;
6323 WORD *indices_16bit = NULL;
6324 const UINT VERTS_PER_FACE = 3;
6325 const D3DXVECTOR3 up = {0.0f, 0.0f, 1.0f};
6326 struct vertex_normal
6328 D3DXVECTOR3 position;
6329 D3DXVECTOR3 normal;
6331 struct vertex_blendweight
6333 D3DXVECTOR3 position;
6334 FLOAT blendweight;
6336 struct vertex_texcoord
6338 D3DXVECTOR3 position;
6339 D3DXVECTOR2 texcoord;
6341 struct vertex_color
6343 D3DXVECTOR3 position;
6344 DWORD color;
6346 struct vertex_color_ubyte4
6348 D3DXVECTOR3 position;
6349 BYTE color[4];
6351 struct vertex_texcoord_short2
6353 D3DXVECTOR3 position;
6354 SHORT texcoord[2];
6356 struct vertex_texcoord_ushort2n
6358 D3DXVECTOR3 position;
6359 USHORT texcoord[2];
6361 struct vertex_normal_short4
6363 D3DXVECTOR3 position;
6364 SHORT normal[4];
6366 struct vertex_color_float4
6368 D3DXVECTOR3 position;
6369 D3DXVECTOR4 color;
6371 struct vertex_texcoord_float16_2
6373 D3DXVECTOR3 position;
6374 WORD texcoord[2];
6376 struct vertex_texcoord_float16_4
6378 D3DXVECTOR3 position;
6379 WORD texcoord[4];
6381 struct vertex_normal_udec3
6383 D3DXVECTOR3 position;
6384 DWORD normal;
6386 struct vertex_normal_dec3n
6388 D3DXVECTOR3 position;
6389 DWORD normal;
6391 UINT vertex_size_normal = sizeof(struct vertex_normal);
6392 UINT vertex_size_blendweight = sizeof(struct vertex_blendweight);
6393 UINT vertex_size_texcoord = sizeof(struct vertex_texcoord);
6394 UINT vertex_size_color = sizeof(struct vertex_color);
6395 UINT vertex_size_color_ubyte4 = sizeof(struct vertex_color_ubyte4);
6396 UINT vertex_size_texcoord_short2 = sizeof(struct vertex_texcoord_short2);
6397 UINT vertex_size_normal_short4 = sizeof(struct vertex_normal_short4);
6398 UINT vertex_size_color_float4 = sizeof(struct vertex_color_float4);
6399 UINT vertex_size_texcoord_float16_2 = sizeof(struct vertex_texcoord_float16_2);
6400 UINT vertex_size_texcoord_float16_4 = sizeof(struct vertex_texcoord_float16_4);
6401 UINT vertex_size_normal_udec3 = sizeof(struct vertex_normal_udec3);
6402 UINT vertex_size_normal_dec3n = sizeof(struct vertex_normal_dec3n);
6403 D3DVERTEXELEMENT9 declaration_normal[] =
6405 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6406 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6407 D3DDECL_END()
6409 D3DVERTEXELEMENT9 declaration_normal3[] =
6411 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 3},
6412 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6413 D3DDECL_END()
6415 D3DVERTEXELEMENT9 declaration_blendweight[] =
6417 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6418 {0, 12, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BLENDWEIGHT, 0},
6419 D3DDECL_END()
6421 D3DVERTEXELEMENT9 declaration_texcoord[] =
6423 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6424 {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6425 D3DDECL_END()
6427 D3DVERTEXELEMENT9 declaration_color[] =
6429 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6430 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
6431 D3DDECL_END()
6433 D3DVERTEXELEMENT9 declaration_color_ubyte4n[] =
6435 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6436 {0, 12, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
6437 D3DDECL_END()
6439 D3DVERTEXELEMENT9 declaration_color_ubyte4[] =
6441 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6442 {0, 12, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
6443 D3DDECL_END()
6445 D3DVERTEXELEMENT9 declaration_texcoord_short2[] =
6447 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6448 {0, 12, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6449 D3DDECL_END()
6451 D3DVERTEXELEMENT9 declaration_texcoord_short2n[] =
6453 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6454 {0, 12, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6455 D3DDECL_END()
6457 D3DVERTEXELEMENT9 declaration_texcoord_ushort2n[] =
6459 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6460 {0, 12, D3DDECLTYPE_USHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6461 D3DDECL_END()
6463 D3DVERTEXELEMENT9 declaration_normal_short4[] =
6465 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6466 {0, 12, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6467 D3DDECL_END()
6469 D3DVERTEXELEMENT9 declaration_normal_short4n[] =
6471 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6472 {0, 12, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6473 D3DDECL_END()
6475 D3DVERTEXELEMENT9 declaration_normal_ushort4n[] =
6477 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6478 {0, 12, D3DDECLTYPE_USHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6479 D3DDECL_END()
6481 D3DVERTEXELEMENT9 declaration_texcoord10[] =
6483 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6484 {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 10},
6485 D3DDECL_END()
6487 D3DVERTEXELEMENT9 declaration_color2[] =
6489 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6490 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 2},
6491 D3DDECL_END()
6493 D3DVERTEXELEMENT9 declaration_color2_float4[] =
6495 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6496 {0, 12, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 2},
6497 D3DDECL_END()
6499 D3DVERTEXELEMENT9 declaration_texcoord_float16_2[] =
6501 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6502 {0, 12, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6503 D3DDECL_END()
6505 D3DVERTEXELEMENT9 declaration_texcoord_float16_4[] =
6507 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6508 {0, 12, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6509 D3DDECL_END()
6511 D3DVERTEXELEMENT9 declaration_normal_udec3[] =
6513 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6514 {0, 12, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6515 D3DDECL_END()
6517 D3DVERTEXELEMENT9 declaration_normal_dec3n[] =
6519 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6520 {0, 12, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6521 D3DDECL_END()
6523 /* Test 0. One face and no welding.
6525 * 0--1
6526 * | /
6527 * |/
6530 const struct vertex vertices0[] =
6532 {{ 0.0f, 3.0f, 0.f}, up},
6533 {{ 2.0f, 3.0f, 0.f}, up},
6534 {{ 0.0f, 0.0f, 0.f}, up},
6536 const DWORD indices0[] = {0, 1, 2};
6537 const DWORD attributes0[] = {0};
6538 const DWORD exp_indices0[] = {0, 1, 2};
6539 const UINT num_vertices0 = ARRAY_SIZE(vertices0);
6540 const UINT num_faces0 = ARRAY_SIZE(indices0) / VERTS_PER_FACE;
6541 const DWORD flags0 = D3DXWELDEPSILONS_WELDALL;
6542 /* epsilons0 is NULL */
6543 const DWORD adjacency0[] = {-1, -1, -1};
6544 const struct vertex exp_vertices0[] =
6546 {{ 0.0f, 3.0f, 0.f}, up},
6547 {{ 2.0f, 3.0f, 0.f}, up},
6548 {{ 0.0f, 0.0f, 0.f}, up},
6550 const DWORD exp_face_remap0[] = {0};
6551 const DWORD exp_vertex_remap0[] = {0, 1, 2};
6552 const DWORD exp_new_num_vertices0 = ARRAY_SIZE(exp_vertices0);
6553 /* Test 1. Two vertices should be removed without regard to epsilon.
6555 * 0--1 3
6556 * | / /|
6557 * |/ / |
6558 * 2 5--4
6560 const struct vertex_normal vertices1[] =
6562 {{ 0.0f, 3.0f, 0.f}, up},
6563 {{ 2.0f, 3.0f, 0.f}, up},
6564 {{ 0.0f, 0.0f, 0.f}, up},
6566 {{ 3.0f, 3.0f, 0.f}, up},
6567 {{ 3.0f, 0.0f, 0.f}, up},
6568 {{ 1.0f, 0.0f, 0.f}, up},
6570 const DWORD indices1[] = {0, 1, 2, 3, 4, 5};
6571 const DWORD attributes1[] = {0, 0};
6572 const UINT num_vertices1 = ARRAY_SIZE(vertices1);
6573 const UINT num_faces1 = ARRAY_SIZE(indices1) / VERTS_PER_FACE;
6574 const DWORD flags1 = D3DXWELDEPSILONS_WELDALL;
6575 /* epsilons1 is NULL */
6576 const DWORD adjacency1[] = {-1, 1, -1, -1, -1, 0};
6577 const struct vertex_normal exp_vertices1[] =
6579 {{ 0.0f, 3.0f, 0.f}, up},
6580 {{ 2.0f, 3.0f, 0.f}, up},
6581 {{ 0.0f, 0.0f, 0.f}, up},
6583 {{ 3.0f, 0.0f, 0.f}, up}
6585 const DWORD exp_indices1[] = {0, 1, 2, 1, 3, 2};
6586 const DWORD exp_face_remap1[] = {0, 1};
6587 const DWORD exp_vertex_remap1[] = {0, 1, 2, 4, -1, -1};
6588 const DWORD exp_new_num_vertices1 = ARRAY_SIZE(exp_vertices1);
6589 /* Test 2. Two faces. No vertices should be removed because of normal
6590 * epsilon, but the positions should be replaced. */
6591 const struct vertex_normal vertices2[] =
6593 {{ 0.0f, 3.0f, 0.f}, up},
6594 {{ 2.0f, 3.0f, 0.f}, up},
6595 {{ 0.0f, 0.0f, 0.f}, up},
6597 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
6598 {{ 3.0f, 0.0f, 0.f}, up},
6599 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6601 const DWORD indices2[] = {0, 1, 2, 3, 4, 5};
6602 const DWORD attributes2[] = {0, 0};
6603 const UINT num_vertices2 = ARRAY_SIZE(vertices2);
6604 const UINT num_faces2 = ARRAY_SIZE(indices2) / VERTS_PER_FACE;
6605 DWORD flags2 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
6606 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};
6607 const DWORD adjacency2[] = {-1, 1, -1, -1, -1, 0};
6608 const struct vertex_normal exp_vertices2[] =
6610 {{ 0.0f, 3.0f, 0.f}, up},
6611 {{ 2.0f, 3.0f, 0.f}, up},
6612 {{ 0.0f, 0.0f, 0.f}, up},
6614 {{ 2.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
6615 {{ 3.0f, 0.0f, 0.f}, up},
6616 {{ 0.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6618 const DWORD exp_indices2[] = {0, 1, 2, 3, 4, 5};
6619 const DWORD exp_face_remap2[] = {0, 1};
6620 const DWORD exp_vertex_remap2[] = {0, 1, 2, 3, 4, 5};
6621 const DWORD exp_new_num_vertices2 = ARRAY_SIZE(exp_vertices2);
6622 /* Test 3. Two faces. One vertex should be removed because of normal epsilon. */
6623 const struct vertex_normal vertices3[] =
6625 {{ 0.0f, 3.0f, 0.f}, up},
6626 {{ 2.0f, 3.0f, 0.f}, up},
6627 {{ 0.0f, 0.0f, 0.f}, up},
6629 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
6630 {{ 3.0f, 0.0f, 0.f}, up},
6631 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6633 const DWORD indices3[] = {0, 1, 2, 3, 4, 5};
6634 const DWORD attributes3[] = {0, 0};
6635 const UINT num_vertices3 = ARRAY_SIZE(vertices3);
6636 const UINT num_faces3 = ARRAY_SIZE(indices3) / VERTS_PER_FACE;
6637 DWORD flags3 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
6638 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};
6639 const DWORD adjacency3[] = {-1, 1, -1, -1, -1, 0};
6640 const struct vertex_normal exp_vertices3[] =
6642 {{ 0.0f, 3.0f, 0.f}, up},
6643 {{ 2.0f, 3.0f, 0.f}, up},
6644 {{ 0.0f, 0.0f, 0.f}, up},
6646 {{ 3.0f, 0.0f, 0.f}, up},
6647 {{ 0.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6649 const DWORD exp_indices3[] = {0, 1, 2, 1, 3, 4};
6650 const DWORD exp_face_remap3[] = {0, 1};
6651 const DWORD exp_vertex_remap3[] = {0, 1, 2, 4, 5, -1};
6652 const DWORD exp_new_num_vertices3 = ARRAY_SIZE(exp_vertices3);
6653 /* Test 4 Two faces. Two vertices should be removed. */
6654 const struct vertex_normal vertices4[] =
6656 {{ 0.0f, 3.0f, 0.f}, up},
6657 {{ 2.0f, 3.0f, 0.f}, up},
6658 {{ 0.0f, 0.0f, 0.f}, up},
6660 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
6661 {{ 3.0f, 0.0f, 0.f}, up},
6662 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6664 const DWORD indices4[] = {0, 1, 2, 3, 4, 5};
6665 const DWORD attributes4[] = {0, 0};
6666 const UINT num_vertices4 = ARRAY_SIZE(vertices4);
6667 const UINT num_faces4 = ARRAY_SIZE(indices4) / VERTS_PER_FACE;
6668 DWORD flags4 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
6669 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};
6670 const DWORD adjacency4[] = {-1, 1, -1, -1, -1, 0};
6671 const struct vertex_normal exp_vertices4[] =
6673 {{ 0.0f, 3.0f, 0.f}, up},
6674 {{ 2.0f, 3.0f, 0.f}, up},
6675 {{ 0.0f, 0.0f, 0.f}, up},
6677 {{ 3.0f, 0.0f, 0.f}, up},
6679 const DWORD exp_indices4[] = {0, 1, 2, 1, 3, 2};
6680 const DWORD exp_face_remap4[] = {0, 1};
6681 const DWORD exp_vertex_remap4[] = {0, 1, 2, 4, -1, -1};
6682 const DWORD exp_new_num_vertices4 = ARRAY_SIZE(exp_vertices4);
6683 /* Test 5. Odd face ordering.
6685 * 0--1 6 3
6686 * | / /| |\
6687 * |/ / | | \
6688 * 2 8--7 5--4
6690 const struct vertex_normal vertices5[] =
6692 {{ 0.0f, 3.0f, 0.f}, up},
6693 {{ 2.0f, 3.0f, 0.f}, up},
6694 {{ 0.0f, 0.0f, 0.f}, up},
6696 {{ 3.0f, 3.0f, 0.f}, up},
6697 {{ 3.0f, 0.0f, 0.f}, up},
6698 {{ 1.0f, 0.0f, 0.f}, up},
6700 {{ 4.0f, 3.0f, 0.f}, up},
6701 {{ 6.0f, 0.0f, 0.f}, up},
6702 {{ 4.0f, 0.0f, 0.f}, up},
6704 const DWORD indices5[] = {0, 1, 2, 6, 7, 8, 3, 4, 5};
6705 const DWORD exp_indices5[] = {0, 1, 2, 1, 4, 2, 1, 3, 4};
6706 const DWORD attributes5[] = {0, 0, 0};
6707 const UINT num_vertices5 = ARRAY_SIZE(vertices5);
6708 const UINT num_faces5 = ARRAY_SIZE(indices5) / VERTS_PER_FACE;
6709 DWORD flags5 = D3DXWELDEPSILONS_WELDALL;
6710 const DWORD adjacency5[] = {-1, 1, -1, 2, -1, 0, -1, -1, 1};
6711 const struct vertex_normal exp_vertices5[] =
6713 {{ 0.0f, 3.0f, 0.f}, up},
6714 {{ 2.0f, 3.0f, 0.f}, up},
6715 {{ 0.0f, 0.0f, 0.f}, up},
6717 {{ 3.0f, 0.0f, 0.f}, up},
6718 {{ 1.0f, 0.0f, 0.f}, up},
6720 const DWORD exp_face_remap5[] = {0, 1, 2};
6721 const DWORD exp_vertex_remap5[] = {0, 1, 2, 4, 5, -1, -1, -1, -1};
6722 const DWORD exp_new_num_vertices5 = ARRAY_SIZE(exp_vertices5);
6723 /* Test 6. Two faces. Do not remove flag is used, so no vertices should be
6724 * removed. */
6725 const struct vertex_normal vertices6[] =
6727 {{ 0.0f, 3.0f, 0.f}, up},
6728 {{ 2.0f, 3.0f, 0.f}, up},
6729 {{ 0.0f, 0.0f, 0.f}, up},
6731 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
6732 {{ 3.0f, 0.0f, 0.f}, up},
6733 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6735 const DWORD indices6[] = {0, 1, 2, 3, 4, 5};
6736 const DWORD attributes6[] = {0, 0};
6737 const UINT num_vertices6 = ARRAY_SIZE(vertices6);
6738 const UINT num_faces6 = ARRAY_SIZE(indices6) / VERTS_PER_FACE;
6739 DWORD flags6 = D3DXWELDEPSILONS_WELDPARTIALMATCHES | D3DXWELDEPSILONS_DONOTREMOVEVERTICES;
6740 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};
6741 const DWORD adjacency6[] = {-1, 1, -1, -1, -1, 0};
6742 const struct vertex_normal exp_vertices6[] =
6744 {{ 0.0f, 3.0f, 0.f}, up},
6745 {{ 2.0f, 3.0f, 0.f}, up},
6746 {{ 0.0f, 0.0f, 0.f}, up},
6748 {{ 2.0f, 3.0f, 0.f}, up},
6749 {{ 3.0f, 0.0f, 0.f}, up},
6750 {{ 0.0f, 0.0f, 0.f}, up},
6753 const DWORD exp_indices6[] = {0, 1, 2, 3, 4, 5};
6754 const DWORD exp_face_remap6[] = {0, 1};
6755 const DWORD exp_vertex_remap6[] = {0, 1, 2, 3, 4, 5};
6756 const DWORD exp_new_num_vertices6 = ARRAY_SIZE(exp_vertices6);
6757 /* Test 7. Same as test 6 but with 16 bit indices. */
6758 const WORD indices6_16bit[] = {0, 1, 2, 3, 4, 5};
6759 /* Test 8. No flags. Same result as D3DXWELDEPSILONS_WELDPARTIALMATCHES. */
6760 const struct vertex_normal vertices8[] =
6762 {{ 0.0f, 3.0f, 0.f}, up},
6763 {{ 2.0f, 3.0f, 0.f}, up},
6764 {{ 0.0f, 0.0f, 0.f}, up},
6766 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
6767 {{ 3.0f, 0.0f, 0.f}, up},
6768 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6770 const DWORD indices8[] = {0, 1, 2, 1, 3, 4};
6771 const DWORD attributes8[] = {0, 0};
6772 const UINT num_vertices8 = ARRAY_SIZE(vertices8);
6773 const UINT num_faces8 = ARRAY_SIZE(indices8) / VERTS_PER_FACE;
6774 DWORD flags8 = 0;
6775 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};
6776 const DWORD adjacency8[] = {-1, 1, -1, -1, -1, 0};
6777 const struct vertex_normal exp_vertices8[] =
6779 {{ 0.0f, 3.0f, 0.f}, up},
6780 {{ 2.0f, 3.0f, 0.f}, up},
6781 {{ 0.0f, 0.0f, 0.f}, up},
6783 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
6784 {{ 3.0f, 0.0f, 0.f}, up},
6786 const DWORD exp_indices8[] = {0, 1, 2, 1, 3, 4};
6787 const DWORD exp_face_remap8[] = {0, 1};
6788 const DWORD exp_vertex_remap8[] = {0, 1, 2, 3, 4, -1};
6789 const DWORD exp_new_num_vertices8 = ARRAY_SIZE(exp_vertices8);
6790 /* Test 9. Vertices are removed even though they belong to separate
6791 * attribute groups if D3DXWELDEPSILONS_DONOTSPLIT is set. */
6792 const struct vertex_normal vertices9[] =
6794 {{ 0.0f, 3.0f, 0.f}, up},
6795 {{ 2.0f, 3.0f, 0.f}, up},
6796 {{ 0.0f, 0.0f, 0.f}, up},
6798 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
6799 {{ 3.0f, 0.0f, 0.f}, up},
6800 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6802 const DWORD indices9[] = {0, 1, 2, 3, 4, 5};
6803 const DWORD attributes9[] = {0, 1};
6804 const UINT num_vertices9 = ARRAY_SIZE(vertices9);
6805 const UINT num_faces9 = ARRAY_SIZE(indices9) / VERTS_PER_FACE;
6806 DWORD flags9 = D3DXWELDEPSILONS_WELDPARTIALMATCHES | D3DXWELDEPSILONS_DONOTSPLIT;
6807 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};
6808 const DWORD adjacency9[] = {-1, 1, -1, -1, -1, 0};
6809 const struct vertex_normal exp_vertices9[] =
6811 {{ 0.0f, 3.0f, 0.f}, up},
6812 {{ 2.0f, 3.0f, 0.f}, up},
6813 {{ 0.0f, 0.0f, 0.f}, up},
6815 {{ 3.0f, 0.0f, 0.f}, up},
6817 const DWORD exp_indices9[] = {0, 1, 2, 1, 3, 2};
6818 const DWORD exp_face_remap9[] = {0, 1};
6819 const DWORD exp_vertex_remap9[] = {0, 1, 2, 4, -1, -1};
6820 const DWORD exp_new_num_vertices9 = ARRAY_SIZE(exp_vertices9);
6821 /* Test 10. Weld blendweight (FLOAT1). */
6822 const struct vertex_blendweight vertices10[] =
6824 {{ 0.0f, 3.0f, 0.f}, 1.0f},
6825 {{ 2.0f, 3.0f, 0.f}, 1.0f},
6826 {{ 0.0f, 0.0f, 0.f}, 1.0f},
6828 {{ 3.0f, 3.0f, 0.f}, 0.9},
6829 {{ 3.0f, 0.0f, 0.f}, 1.0},
6830 {{ 1.0f, 0.0f, 0.f}, 0.4},
6832 const DWORD indices10[] = {0, 1, 2, 3, 4, 5};
6833 const DWORD attributes10[] = {0, 0};
6834 const UINT num_vertices10 = ARRAY_SIZE(vertices10);
6835 const UINT num_faces10 = ARRAY_SIZE(indices10) / VERTS_PER_FACE;
6836 DWORD flags10 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
6837 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};
6838 const DWORD adjacency10[] = {-1, 1, -1, -1, -1, 0};
6839 const struct vertex_blendweight exp_vertices10[] =
6841 {{ 0.0f, 3.0f, 0.f}, 1.0f},
6842 {{ 2.0f, 3.0f, 0.f}, 1.0f},
6843 {{ 0.0f, 0.0f, 0.f}, 1.0f},
6845 {{ 3.0f, 0.0f, 0.f}, 1.0},
6846 {{ 0.0f, 0.0f, 0.f}, 0.4},
6848 const DWORD exp_indices10[] = {0, 1, 2, 1, 3, 4};
6849 const DWORD exp_face_remap10[] = {0, 1};
6850 const DWORD exp_vertex_remap10[] = {0, 1, 2, 4, 5, -1};
6851 const DWORD exp_new_num_vertices10 = ARRAY_SIZE(exp_vertices10);
6852 /* Test 11. Weld texture coordinates. */
6853 const struct vertex_texcoord vertices11[] =
6855 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f}},
6856 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.7f}},
6857 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
6859 {{ 3.0f, 3.0f, 0.f}, {0.2f, 0.3f}},
6860 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f}},
6861 {{ 1.0f, 0.0f, 0.f}, {0.1f, 0.2f}}
6863 const DWORD indices11[] = {0, 1, 2, 3, 4, 5};
6864 const DWORD attributes11[] = {0, 0};
6865 const UINT num_vertices11 = ARRAY_SIZE(vertices11);
6866 const UINT num_faces11 = ARRAY_SIZE(indices11) / VERTS_PER_FACE;
6867 DWORD flags11 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
6868 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};
6869 const DWORD adjacency11[] = {-1, 1, -1, -1, -1, 0};
6870 const struct vertex_texcoord exp_vertices11[] =
6872 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f}},
6873 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.7f}},
6874 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
6876 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f}},
6877 {{ 0.0f, 0.0f, 0.f}, {0.1f, 0.2f}},
6879 const DWORD exp_indices11[] = {0, 1, 2, 1, 3, 4};
6880 const DWORD exp_face_remap11[] = {0, 1};
6881 const DWORD exp_vertex_remap11[] = {0, 1, 2, 4, 5, -1};
6882 const DWORD exp_new_num_vertices11 = ARRAY_SIZE(exp_vertices11);
6883 /* Test 12. Weld with color. */
6884 const struct vertex_color vertices12[] =
6886 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
6887 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
6888 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
6890 {{ 3.0f, 3.0f, 0.f}, 0x00000000},
6891 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
6892 {{ 1.0f, 0.0f, 0.f}, 0x88888888},
6894 const DWORD indices12[] = {0, 1, 2, 3, 4, 5};
6895 const DWORD attributes12[] = {0, 0};
6896 const UINT num_vertices12 = ARRAY_SIZE(vertices12);
6897 const UINT num_faces12 = ARRAY_SIZE(indices12) / VERTS_PER_FACE;
6898 DWORD flags12 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
6899 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};
6900 const DWORD adjacency12[] = {-1, 1, -1, -1, -1, 0};
6901 const struct vertex_color exp_vertices12[] =
6903 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
6904 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
6905 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
6907 {{ 2.0f, 3.0f, 0.f}, 0x00000000},
6908 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
6910 const DWORD exp_indices12[] = {0, 1, 2, 3, 4, 2};
6911 const DWORD exp_face_remap12[] = {0, 1};
6912 const DWORD exp_vertex_remap12[] = {0, 1, 2, 3, 4, -1};
6913 const DWORD exp_new_num_vertices12 = ARRAY_SIZE(exp_vertices12);
6914 /* Test 13. Two faces. One vertex should be removed because of normal epsilon.
6915 * This is similar to test 3, but the declaration has been changed to NORMAL3.
6917 const struct vertex_normal vertices13[] =
6919 {{ 0.0f, 3.0f, 0.f}, up},
6920 {{ 2.0f, 3.0f, 0.f}, up},
6921 {{ 0.0f, 0.0f, 0.f}, up},
6923 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
6924 {{ 3.0f, 0.0f, 0.f}, up},
6925 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6927 const DWORD indices13[] = {0, 1, 2, 3, 4, 5};
6928 const DWORD attributes13[] = {0, 0};
6929 const UINT num_vertices13 = ARRAY_SIZE(vertices3);
6930 const UINT num_faces13 = ARRAY_SIZE(indices3) / VERTS_PER_FACE;
6931 DWORD flags13 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
6932 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};
6933 const DWORD adjacency13[] = {-1, 1, -1, -1, -1, 0};
6934 const struct vertex_normal exp_vertices13[] =
6936 {{ 0.0f, 3.0f, 0.f}, up},
6937 {{ 2.0f, 3.0f, 0.f}, up},
6938 {{ 0.0f, 0.0f, 0.f}, up},
6940 {{ 3.0f, 0.0f, 0.f}, up},
6941 {{ 0.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6943 const DWORD exp_indices13[] = {0, 1, 2, 1, 3, 4};
6944 const DWORD exp_face_remap13[] = {0, 1};
6945 const DWORD exp_vertex_remap13[] = {0, 1, 2, 4, 5, -1};
6946 const DWORD exp_new_num_vertices13 = ARRAY_SIZE(exp_vertices13);
6947 /* Test 14. Another test for welding with color. */
6948 const struct vertex_color vertices14[] =
6950 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
6951 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
6952 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
6954 {{ 3.0f, 3.0f, 0.f}, 0x00000000},
6955 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
6956 {{ 1.0f, 0.0f, 0.f}, 0x01010101},
6958 const DWORD indices14[] = {0, 1, 2, 3, 4, 5};
6959 const DWORD attributes14[] = {0, 0};
6960 const UINT num_vertices14 = ARRAY_SIZE(vertices14);
6961 const UINT num_faces14 = ARRAY_SIZE(indices14) / VERTS_PER_FACE;
6962 DWORD flags14 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
6963 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};
6964 const DWORD adjacency14[] = {-1, 1, -1, -1, -1, 0};
6965 const struct vertex_color exp_vertices14[] =
6967 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
6968 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
6969 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
6971 {{ 2.0f, 3.0f, 0.f}, 0x00000000},
6972 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
6974 const DWORD exp_indices14[] = {0, 1, 2, 3, 4, 2};
6975 const DWORD exp_face_remap14[] = {0, 1};
6976 const DWORD exp_vertex_remap14[] = {0, 1, 2, 3, 4, -1};
6977 const DWORD exp_new_num_vertices14 = ARRAY_SIZE(exp_vertices14);
6978 /* Test 15. Weld with color, but as UBYTE4N instead of D3DCOLOR. It shows
6979 * that UBYTE4N and D3DCOLOR are compared the same way.
6981 const struct vertex_color_ubyte4 vertices15[] =
6983 {{ 0.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
6984 {{ 2.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
6985 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
6987 {{ 3.0f, 3.0f, 0.f}, { 0, 0, 0, 0}},
6988 {{ 3.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
6989 {{ 1.0f, 0.0f, 0.f}, { 1, 1, 1, 1}},
6991 const DWORD indices15[] = {0, 1, 2, 3, 4, 5};
6992 const DWORD attributes15[] = {0, 0};
6993 const UINT num_vertices15 = ARRAY_SIZE(vertices15);
6994 const UINT num_faces15 = ARRAY_SIZE(indices15) / VERTS_PER_FACE;
6995 DWORD flags15 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
6996 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};
6997 const DWORD adjacency15[] = {-1, 1, -1, -1, -1, 0};
6998 const struct vertex_color_ubyte4 exp_vertices15[] =
7000 {{ 0.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7001 {{ 2.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7002 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7004 {{ 2.0f, 3.0f, 0.f}, { 0, 0, 0, 0}},
7005 {{ 3.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7007 const DWORD exp_indices15[] = {0, 1, 2, 3, 4, 2};
7008 const DWORD exp_face_remap15[] = {0, 1};
7009 const DWORD exp_vertex_remap15[] = {0, 1, 2, 3, 4, -1};
7010 const DWORD exp_new_num_vertices15 = ARRAY_SIZE(exp_vertices15);
7011 /* Test 16. Weld with color, but as UBYTE4 instead of D3DCOLOR. It shows
7012 * that UBYTE4 is not normalized and that epsilon is truncated and compared
7013 * directly to each of the four bytes.
7015 const struct vertex_color_ubyte4 vertices16[] =
7017 {{ 0.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7018 {{ 2.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7019 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7021 {{ 3.0f, 3.0f, 0.f}, { 0, 0, 0, 0}},
7022 {{ 3.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7023 {{ 1.0f, 0.0f, 0.f}, { 1, 1, 1, 1}},
7025 const DWORD indices16[] = {0, 1, 2, 3, 4, 5};
7026 const DWORD attributes16[] = {0, 0};
7027 const UINT num_vertices16 = ARRAY_SIZE(vertices16);
7028 const UINT num_faces16 = ARRAY_SIZE(indices16) / VERTS_PER_FACE;
7029 DWORD flags16 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7030 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};
7031 const DWORD adjacency16[] = {-1, 1, -1, -1, -1, 0};
7032 const struct vertex_color_ubyte4 exp_vertices16[] =
7034 {{ 0.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7035 {{ 2.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7036 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7038 {{ 2.0f, 3.0f, 0.f}, { 0, 0, 0, 0}},
7039 {{ 3.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7041 const DWORD exp_indices16[] = {0, 1, 2, 3, 4, 2};
7042 const DWORD exp_face_remap16[] = {0, 1};
7043 const DWORD exp_vertex_remap16[] = {0, 1, 2, 3, 4, -1};
7044 const DWORD exp_new_num_vertices16 = ARRAY_SIZE(exp_vertices16);
7045 /* Test 17. Weld texture coordinates but as SHORT2 instead of D3DXVECTOR2.*/
7046 const struct vertex_texcoord_short2 vertices17[] =
7048 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7049 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7050 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7052 {{ 3.0f, 3.0f, 0.f}, {32767, 32767}},
7053 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7054 {{ 1.0f, 0.0f, 0.f}, {32766, 32766}},
7056 const DWORD indices17[] = {0, 1, 2, 3, 4, 5};
7057 const DWORD attributes17[] = {0, 0};
7058 const UINT num_vertices17 = ARRAY_SIZE(vertices17);
7059 const UINT num_faces17 = ARRAY_SIZE(indices17) / VERTS_PER_FACE;
7060 DWORD flags17 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7061 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};
7062 const DWORD adjacency17[] = {-1, 1, -1, -1, -1, 0};
7063 const struct vertex_texcoord_short2 exp_vertices17[] =
7065 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7066 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7067 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7069 {{ 2.0f, 3.0f, 0.f}, {32767, 32767}},
7070 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7072 const DWORD exp_indices17[] = {0, 1, 2, 3, 4, 2};
7073 const DWORD exp_face_remap17[] = {0, 1};
7074 const DWORD exp_vertex_remap17[] = {0, 1, 2, 3, 4, -1};
7075 const DWORD exp_new_num_vertices17 = ARRAY_SIZE(exp_vertices17);
7076 /* Test 18. Weld texture coordinates but as SHORT2N instead of D3DXVECTOR2. */
7077 const struct vertex_texcoord_short2 vertices18[] =
7079 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7080 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7081 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7083 {{ 3.0f, 3.0f, 0.f}, {32767, 32767}},
7084 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7085 {{ 1.0f, 0.0f, 0.f}, {32766, 32766}},
7087 const DWORD indices18[] = {0, 1, 2, 3, 4, 5};
7088 const DWORD attributes18[] = {0, 0};
7089 const UINT num_vertices18 = ARRAY_SIZE(vertices18);
7090 const UINT num_faces18 = ARRAY_SIZE(indices18) / VERTS_PER_FACE;
7091 DWORD flags18 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7092 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};
7093 const DWORD adjacency18[] = {-1, 1, -1, -1, -1, 0};
7094 const struct vertex_texcoord_short2 exp_vertices18[] =
7096 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7097 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7098 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7100 {{ 2.0f, 3.0f, 0.f}, {32767, 32767}},
7101 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7103 const DWORD exp_indices18[] = {0, 1, 2, 3, 4, 2};
7104 const DWORD exp_face_remap18[] = {0, 1};
7105 const DWORD exp_vertex_remap18[] = {0, 1, 2, 3, 4, -1};
7106 const DWORD exp_new_num_vertices18 = ARRAY_SIZE(exp_vertices18);
7107 /* Test 19. Weld texture coordinates but as USHORT2N instead of D3DXVECTOR2. */
7108 const struct vertex_texcoord_ushort2n vertices19[] =
7110 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7111 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7112 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7114 {{ 3.0f, 3.0f, 0.f}, {65535, 65535}},
7115 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7116 {{ 1.0f, 0.0f, 0.f}, {65534, 65534}},
7118 const DWORD indices19[] = {0, 1, 2, 3, 4, 5};
7119 const DWORD attributes19[] = {0, 0};
7120 const UINT num_vertices19 = ARRAY_SIZE(vertices19);
7121 const UINT num_faces19 = ARRAY_SIZE(indices19) / VERTS_PER_FACE;
7122 DWORD flags19 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7123 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};
7124 const DWORD adjacency19[] = {-1, 1, -1, -1, -1, 0};
7125 const struct vertex_texcoord_ushort2n exp_vertices19[] =
7127 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7128 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7129 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7131 {{ 2.0f, 3.0f, 0.f}, {65535, 65535}},
7132 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7134 const DWORD exp_indices19[] = {0, 1, 2, 3, 4, 2};
7135 const DWORD exp_face_remap19[] = {0, 1};
7136 const DWORD exp_vertex_remap19[] = {0, 1, 2, 3, 4, -1};
7137 const DWORD exp_new_num_vertices19 = ARRAY_SIZE(exp_vertices19);
7138 /* Test 20. Weld normal as SHORT4 instead of D3DXVECTOR3. */
7139 const struct vertex_normal_short4 vertices20[] =
7141 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7142 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7143 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7145 {{ 3.0f, 3.0f, 0.f}, {32767, 32767, 32767, 32767}},
7146 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7147 {{ 1.0f, 0.0f, 0.f}, {32766, 32766, 32766, 32766}},
7149 const DWORD indices20[] = {0, 1, 2, 3, 4, 5};
7150 const DWORD attributes20[] = {0, 0};
7151 const UINT num_vertices20 = ARRAY_SIZE(vertices20);
7152 const UINT num_faces20 = ARRAY_SIZE(indices20) / VERTS_PER_FACE;
7153 DWORD flags20 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7154 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};
7155 const DWORD adjacency20[] = {-1, 1, -1, -1, -1, 0};
7156 const struct vertex_normal_short4 exp_vertices20[] =
7158 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7159 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7160 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7162 {{ 2.0f, 3.0f, 0.f}, {32767, 32767, 32767, 32767}},
7163 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7165 const DWORD exp_indices20[] = {0, 1, 2, 3, 4, 2};
7166 const DWORD exp_face_remap20[] = {0, 1};
7167 const DWORD exp_vertex_remap20[] = {0, 1, 2, 3, 4, -1};
7168 const DWORD exp_new_num_vertices20 = ARRAY_SIZE(exp_vertices20);
7169 /* Test 21. Weld normal as SHORT4N instead of D3DXVECTOR3. */
7170 const struct vertex_normal_short4 vertices21[] =
7172 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7173 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7174 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7176 {{ 3.0f, 3.0f, 0.f}, {32767, 32767, 32767, 32767}},
7177 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7178 {{ 1.0f, 0.0f, 0.f}, {32766, 32766, 32766, 32766}},
7180 const DWORD indices21[] = {0, 1, 2, 3, 4, 5};
7181 const DWORD attributes21[] = {0, 0};
7182 const UINT num_vertices21 = ARRAY_SIZE(vertices21);
7183 const UINT num_faces21 = ARRAY_SIZE(indices21) / VERTS_PER_FACE;
7184 DWORD flags21 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7185 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};
7186 const DWORD adjacency21[] = {-1, 1, -1, -1, -1, 0};
7187 const struct vertex_normal_short4 exp_vertices21[] =
7189 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7190 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7191 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7193 {{ 2.0f, 3.0f, 0.f}, {32767, 32767, 32767, 32767}},
7194 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7196 const DWORD exp_indices21[] = {0, 1, 2, 3, 4, 2};
7197 const DWORD exp_face_remap21[] = {0, 1};
7198 const DWORD exp_vertex_remap21[] = {0, 1, 2, 3, 4, -1};
7199 const DWORD exp_new_num_vertices21 = ARRAY_SIZE(exp_vertices21);
7200 /* Test 22. Weld normal as USHORT4N instead of D3DXVECTOR3. */
7201 const struct vertex_normal_short4 vertices22[] =
7203 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7204 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7205 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7207 {{ 3.0f, 3.0f, 0.f}, {65535, 65535, 65535, 65535}},
7208 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7209 {{ 1.0f, 0.0f, 0.f}, {65534, 65534, 65534, 65534}},
7211 const DWORD indices22[] = {0, 1, 2, 3, 4, 5};
7212 const DWORD attributes22[] = {0, 0};
7213 const UINT num_vertices22 = ARRAY_SIZE(vertices22);
7214 const UINT num_faces22 = ARRAY_SIZE(indices22) / VERTS_PER_FACE;
7215 DWORD flags22 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7216 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};
7217 const DWORD adjacency22[] = {-1, 1, -1, -1, -1, 0};
7218 const struct vertex_normal_short4 exp_vertices22[] =
7220 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7221 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7222 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7224 {{ 2.0f, 3.0f, 0.f}, {65535, 65535, 65535, 65535}},
7225 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7227 const DWORD exp_indices22[] = {0, 1, 2, 3, 4, 2};
7228 const DWORD exp_face_remap22[] = {0, 1};
7229 const DWORD exp_vertex_remap22[] = {0, 1, 2, 3, 4, -1};
7230 const DWORD exp_new_num_vertices22 = ARRAY_SIZE(exp_vertices22);
7231 /* Test 23. Weld texture coordinates as FLOAT16_2. Similar to test 11, but
7232 * with texture coordinates converted to float16 in hex. */
7233 const struct vertex_texcoord_float16_2 vertices23[] =
7235 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
7236 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */
7237 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */
7239 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd}}, /* {0.2f, 0.3f} */
7240 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
7241 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */
7243 const DWORD indices23[] = {0, 1, 2, 3, 4, 5};
7244 const DWORD attributes23[] = {0, 0};
7245 const UINT num_vertices23 = ARRAY_SIZE(vertices23);
7246 const UINT num_faces23 = ARRAY_SIZE(indices23) / VERTS_PER_FACE;
7247 DWORD flags23 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7248 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};
7249 const DWORD adjacency23[] = {-1, 1, -1, -1, -1, 0};
7250 const struct vertex_texcoord_float16_2 exp_vertices23[] =
7252 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
7253 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */
7254 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */
7256 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
7257 {{ 0.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */
7259 const DWORD exp_indices23[] = {0, 1, 2, 1, 3, 4};
7260 const DWORD exp_face_remap23[] = {0, 1};
7261 const DWORD exp_vertex_remap23[] = {0, 1, 2, 4, 5, -1};
7262 const DWORD exp_new_num_vertices23 = ARRAY_SIZE(exp_vertices23);
7263 /* Test 24. Weld texture coordinates as FLOAT16_4. Similar to test 24. */
7264 const struct vertex_texcoord_float16_4 vertices24[] =
7266 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}},
7267 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a, 0x3800, 0x399a}},
7268 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd, 0xb266, 0xb4cd}},
7270 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd, 0x3266, 0x34cd}},
7271 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}},
7272 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266, 0x2e66, 0x3266}},
7274 const DWORD indices24[] = {0, 1, 2, 3, 4, 5};
7275 const DWORD attributes24[] = {0, 0};
7276 const UINT num_vertices24 = ARRAY_SIZE(vertices24);
7277 const UINT num_faces24 = ARRAY_SIZE(indices24) / VERTS_PER_FACE;
7278 DWORD flags24 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7279 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};
7280 const DWORD adjacency24[] = {-1, 1, -1, -1, -1, 0};
7281 const struct vertex_texcoord_float16_4 exp_vertices24[] =
7283 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}},
7284 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a, 0x3800, 0x399a}},
7285 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd, 0xb266, 0xb4cd}},
7287 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}},
7288 {{ 0.0f, 0.0f, 0.f}, {0x2e66, 0x3266, 0x2e66, 0x3266}},
7290 const DWORD exp_indices24[] = {0, 1, 2, 1, 3, 4};
7291 const DWORD exp_face_remap24[] = {0, 1};
7292 const DWORD exp_vertex_remap24[] = {0, 1, 2, 4, 5, -1};
7293 const DWORD exp_new_num_vertices24 = ARRAY_SIZE(exp_vertices24);
7294 /* Test 25. Weld texture coordinates with usage index 10 (TEXCOORD10). The
7295 * usage index is capped at 7, so the epsilon for TEXCOORD7 is used instead.
7297 const struct vertex_texcoord vertices25[] =
7299 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f}},
7300 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.7f}},
7301 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
7303 {{ 3.0f, 3.0f, 0.f}, {0.2f, 0.3f}},
7304 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f}},
7305 {{ 1.0f, 0.0f, 0.f}, {0.1f, 0.2f}}
7307 const DWORD indices25[] = {0, 1, 2, 3, 4, 5};
7308 const DWORD attributes25[] = {0, 0};
7309 const UINT num_vertices25 = ARRAY_SIZE(vertices25);
7310 const UINT num_faces25 = ARRAY_SIZE(indices25) / VERTS_PER_FACE;
7311 DWORD flags25 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7312 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};
7313 const DWORD adjacency25[] = {-1, 1, -1, -1, -1, 0};
7314 const struct vertex_texcoord exp_vertices25[] =
7316 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f}},
7317 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.7f}},
7318 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
7320 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f}},
7321 {{ 0.0f, 0.0f, 0.f}, {0.1f, 0.2f}},
7323 const DWORD exp_indices25[] = {0, 1, 2, 1, 3, 4};
7324 const DWORD exp_face_remap25[] = {0, 1};
7325 const DWORD exp_vertex_remap25[] = {0, 1, 2, 4, 5, -1};
7326 const DWORD exp_new_num_vertices25 = ARRAY_SIZE(exp_vertices25);
7327 /* Test 26. Weld color with usage index larger than 1. Shows that none of
7328 * the epsilon values are used. */
7329 const struct vertex_color vertices26[] =
7331 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7332 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7333 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7335 {{ 3.0f, 3.0f, 0.f}, 0x00000000},
7336 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7337 {{ 1.0f, 0.0f, 0.f}, 0x01010101},
7339 const DWORD indices26[] = {0, 1, 2, 3, 4, 5};
7340 const DWORD attributes26[] = {0, 0};
7341 const UINT num_vertices26 = ARRAY_SIZE(vertices26);
7342 const UINT num_faces26 = ARRAY_SIZE(indices26) / VERTS_PER_FACE;
7343 DWORD flags26 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7344 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};
7345 const DWORD adjacency26[] = {-1, 1, -1, -1, -1, 0};
7346 const struct vertex_color exp_vertices26[] =
7348 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7349 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7350 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7352 {{ 2.0f, 3.0f, 0.f}, 0x00000000},
7353 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7354 {{ 0.0f, 0.0f, 0.f}, 0x01010101},
7356 const DWORD exp_indices26[] = {0, 1, 2, 3, 4, 5};
7357 const DWORD exp_face_remap26[] = {0, 1};
7358 const DWORD exp_vertex_remap26[] = {0, 1, 2, 3, 4, 5};
7359 const DWORD exp_new_num_vertices26 = ARRAY_SIZE(exp_vertices26);
7360 /* Test 27. Weld color with usage index larger than 1. Check that the
7361 * default epsilon of 1e-6f is used. */
7362 D3DXVECTOR4 zero_float4 = {0.0f, 0.0f, 0.0f, 0.0f};
7363 D3DXVECTOR4 almost_zero_float4 = {0.0f + FLT_EPSILON, 0.0f + FLT_EPSILON, 0.0f + FLT_EPSILON, 0.0f + FLT_EPSILON};
7364 const struct vertex_color_float4 vertices27[] =
7366 {{ 0.0f, 3.0f, 0.f}, zero_float4},
7367 {{ 2.0f, 3.0f, 0.f}, zero_float4},
7368 {{ 0.0f, 0.0f, 0.f}, zero_float4},
7370 {{ 3.0f, 3.0f, 0.f}, almost_zero_float4},
7371 {{ 3.0f, 0.0f, 0.f}, zero_float4},
7372 {{ 1.0f, 0.0f, 0.f}, almost_zero_float4},
7374 const DWORD indices27[] = {0, 1, 2, 3, 4, 5};
7375 const DWORD attributes27[] = {0, 0};
7376 const UINT num_vertices27 = ARRAY_SIZE(vertices27);
7377 const UINT num_faces27 = ARRAY_SIZE(indices27) / VERTS_PER_FACE;
7378 DWORD flags27 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7379 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};
7380 const DWORD adjacency27[] = {-1, 1, -1, -1, -1, 0};
7381 const struct vertex_color_float4 exp_vertices27[] =
7383 {{ 0.0f, 3.0f, 0.f}, zero_float4},
7384 {{ 2.0f, 3.0f, 0.f}, zero_float4},
7385 {{ 0.0f, 0.0f, 0.f}, zero_float4},
7387 {{ 3.0f, 0.0f, 0.f}, zero_float4},
7389 const DWORD exp_indices27[] = {0, 1, 2, 1, 3, 2};
7390 const DWORD exp_face_remap27[] = {0, 1};
7391 const DWORD exp_vertex_remap27[] = {0, 1, 2, 4, -1, -1};
7392 const DWORD exp_new_num_vertices27 = ARRAY_SIZE(exp_vertices27);
7393 /* Test 28. Weld one normal with UDEC3. */
7394 const DWORD dword_udec3_zero = init_udec3_dword(0, 0, 0, 1);
7395 const DWORD dword_udec3_1023 = init_udec3_dword(1023, 1023, 1023, 1);
7396 const DWORD dword_udec3_1022 = init_udec3_dword(1022, 1022, 1022, 1);
7397 const struct vertex_normal_udec3 vertices28[] =
7399 {{ 0.0f, 3.0f, 0.f}, dword_udec3_zero},
7400 {{ 2.0f, 3.0f, 0.f}, dword_udec3_zero},
7401 {{ 0.0f, 0.0f, 0.f}, dword_udec3_zero},
7403 {{ 3.0f, 3.0f, 0.f}, dword_udec3_1023},
7404 {{ 3.0f, 0.0f, 0.f}, dword_udec3_zero},
7405 {{ 1.0f, 0.0f, 0.f}, dword_udec3_1022},
7407 const DWORD indices28[] = {0, 1, 2, 3, 4, 5};
7408 const DWORD attributes28[] = {0, 0};
7409 const UINT num_vertices28 = ARRAY_SIZE(vertices28);
7410 const UINT num_faces28 = ARRAY_SIZE(indices28) / VERTS_PER_FACE;
7411 DWORD flags28 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7412 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};
7413 const DWORD adjacency28[] = {-1, 1, -1, -1, -1, 0};
7414 const struct vertex_normal_udec3 exp_vertices28[] =
7416 {{ 0.0f, 3.0f, 0.f}, dword_udec3_zero},
7417 {{ 2.0f, 3.0f, 0.f}, dword_udec3_zero},
7418 {{ 0.0f, 0.0f, 0.f}, dword_udec3_zero},
7420 {{ 2.0f, 3.0f, 0.f}, dword_udec3_1023},
7421 {{ 3.0f, 0.0f, 0.f}, dword_udec3_zero},
7423 const DWORD exp_indices28[] = {0, 1, 2, 3, 4, 2};
7424 const DWORD exp_face_remap28[] = {0, 1};
7425 const DWORD exp_vertex_remap28[] = {0, 1, 2, 3, 4, -1};
7426 const DWORD exp_new_num_vertices28 = ARRAY_SIZE(exp_vertices28);
7427 /* Test 29. Weld one normal with DEC3N. */
7428 const DWORD dword_dec3n_zero = init_dec3n_dword(0, 0, 0, 1);
7429 const DWORD dword_dec3n_511 = init_dec3n_dword(511, 511, 511, 1);
7430 const DWORD dword_dec3n_510 = init_dec3n_dword(510, 510, 510, 1);
7431 const struct vertex_normal_dec3n vertices29[] =
7433 {{ 0.0f, 3.0f, 0.f}, dword_dec3n_zero},
7434 {{ 2.0f, 3.0f, 0.f}, dword_dec3n_zero},
7435 {{ 0.0f, 0.0f, 0.f}, dword_dec3n_zero},
7437 {{ 3.0f, 3.0f, 0.f}, dword_dec3n_511},
7438 {{ 3.0f, 0.0f, 0.f}, dword_dec3n_zero},
7439 {{ 1.0f, 0.0f, 0.f}, dword_dec3n_510},
7441 const DWORD indices29[] = {0, 1, 2, 3, 4, 5};
7442 const DWORD attributes29[] = {0, 0};
7443 const UINT num_vertices29 = ARRAY_SIZE(vertices29);
7444 const UINT num_faces29 = ARRAY_SIZE(indices29) / VERTS_PER_FACE;
7445 DWORD flags29 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7446 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};
7447 const DWORD adjacency29[] = {-1, 1, -1, -1, -1, 0};
7448 const struct vertex_normal_dec3n exp_vertices29[] =
7450 {{ 0.0f, 3.0f, 0.f}, dword_dec3n_zero},
7451 {{ 2.0f, 3.0f, 0.f}, dword_dec3n_zero},
7452 {{ 0.0f, 0.0f, 0.f}, dword_dec3n_zero},
7454 {{ 2.0f, 3.0f, 0.f}, dword_dec3n_511},
7455 {{ 3.0f, 0.0f, 0.f}, dword_dec3n_zero},
7457 const DWORD exp_indices29[] = {0, 1, 2, 3, 4, 2};
7458 const DWORD exp_face_remap29[] = {0, 1};
7459 const DWORD exp_vertex_remap29[] = {0, 1, 2, 3, 4, -1};
7460 const DWORD exp_new_num_vertices29 = ARRAY_SIZE(exp_vertices29);
7461 /* All mesh data */
7462 DWORD *adjacency_out = NULL;
7463 DWORD *face_remap = NULL;
7464 ID3DXMesh *mesh = NULL;
7465 ID3DXBuffer *vertex_remap = NULL;
7466 struct
7468 const BYTE *vertices;
7469 const DWORD *indices;
7470 const DWORD *attributes;
7471 const DWORD num_vertices;
7472 const DWORD num_faces;
7473 const DWORD options;
7474 D3DVERTEXELEMENT9 *declaration;
7475 const UINT vertex_size;
7476 const DWORD flags;
7477 const D3DXWELDEPSILONS *epsilons;
7478 const DWORD *adjacency;
7479 const BYTE *exp_vertices;
7480 const DWORD *exp_indices;
7481 const DWORD *exp_face_remap;
7482 const DWORD *exp_vertex_remap;
7483 const DWORD exp_new_num_vertices;
7485 tc[] =
7488 (BYTE*)vertices0,
7489 indices0,
7490 attributes0,
7491 num_vertices0,
7492 num_faces0,
7493 options,
7494 declaration_normal,
7495 vertex_size_normal,
7496 flags0,
7497 NULL,
7498 adjacency0,
7499 (BYTE*)exp_vertices0,
7500 exp_indices0,
7501 exp_face_remap0,
7502 exp_vertex_remap0,
7503 exp_new_num_vertices0
7506 (BYTE*)vertices1,
7507 indices1,
7508 attributes1,
7509 num_vertices1,
7510 num_faces1,
7511 options,
7512 declaration_normal,
7513 vertex_size_normal,
7514 flags1,
7515 NULL,
7516 adjacency1,
7517 (BYTE*)exp_vertices1,
7518 exp_indices1,
7519 exp_face_remap1,
7520 exp_vertex_remap1,
7521 exp_new_num_vertices1
7524 (BYTE*)vertices2,
7525 indices2,
7526 attributes2,
7527 num_vertices2,
7528 num_faces2,
7529 options,
7530 declaration_normal,
7531 vertex_size_normal,
7532 flags2,
7533 &epsilons2,
7534 adjacency2,
7535 (BYTE*)exp_vertices2,
7536 exp_indices2,
7537 exp_face_remap2,
7538 exp_vertex_remap2,
7539 exp_new_num_vertices2
7542 (BYTE*)vertices3,
7543 indices3,
7544 attributes3,
7545 num_vertices3,
7546 num_faces3,
7547 options,
7548 declaration_normal,
7549 vertex_size_normal,
7550 flags3,
7551 &epsilons3,
7552 adjacency3,
7553 (BYTE*)exp_vertices3,
7554 exp_indices3,
7555 exp_face_remap3,
7556 exp_vertex_remap3,
7557 exp_new_num_vertices3
7560 (BYTE*)vertices4,
7561 indices4,
7562 attributes4,
7563 num_vertices4,
7564 num_faces4,
7565 options,
7566 declaration_normal,
7567 vertex_size_normal,
7568 flags4,
7569 &epsilons4,
7570 adjacency4,
7571 (BYTE*)exp_vertices4,
7572 exp_indices4,
7573 exp_face_remap4,
7574 exp_vertex_remap4,
7575 exp_new_num_vertices4
7577 /* Unusual ordering. */
7579 (BYTE*)vertices5,
7580 indices5,
7581 attributes5,
7582 num_vertices5,
7583 num_faces5,
7584 options,
7585 declaration_normal,
7586 vertex_size_normal,
7587 flags5,
7588 NULL,
7589 adjacency5,
7590 (BYTE*)exp_vertices5,
7591 exp_indices5,
7592 exp_face_remap5,
7593 exp_vertex_remap5,
7594 exp_new_num_vertices5
7597 (BYTE*)vertices6,
7598 indices6,
7599 attributes6,
7600 num_vertices6,
7601 num_faces6,
7602 options,
7603 declaration_normal,
7604 vertex_size_normal,
7605 flags6,
7606 &epsilons6,
7607 adjacency6,
7608 (BYTE*)exp_vertices6,
7609 exp_indices6,
7610 exp_face_remap6,
7611 exp_vertex_remap6,
7612 exp_new_num_vertices6
7615 (BYTE*)vertices6,
7616 (DWORD*)indices6_16bit,
7617 attributes6,
7618 num_vertices6,
7619 num_faces6,
7620 options_16bit,
7621 declaration_normal,
7622 vertex_size_normal,
7623 flags6,
7624 &epsilons6,
7625 adjacency6,
7626 (BYTE*)exp_vertices6,
7627 exp_indices6,
7628 exp_face_remap6,
7629 exp_vertex_remap6,
7630 exp_new_num_vertices6
7633 (BYTE*)vertices8,
7634 indices8,
7635 attributes8,
7636 num_vertices8,
7637 num_faces8,
7638 options,
7639 declaration_normal,
7640 vertex_size_normal,
7641 flags8,
7642 &epsilons8,
7643 adjacency8,
7644 (BYTE*)exp_vertices8,
7645 exp_indices8,
7646 exp_face_remap8,
7647 exp_vertex_remap8,
7648 exp_new_num_vertices8
7651 (BYTE*)vertices9,
7652 indices9,
7653 attributes9,
7654 num_vertices9,
7655 num_faces9,
7656 options,
7657 declaration_normal,
7658 vertex_size_normal,
7659 flags9,
7660 &epsilons9,
7661 adjacency9,
7662 (BYTE*)exp_vertices9,
7663 exp_indices9,
7664 exp_face_remap9,
7665 exp_vertex_remap9,
7666 exp_new_num_vertices9
7669 (BYTE*)vertices10,
7670 indices10,
7671 attributes10,
7672 num_vertices10,
7673 num_faces10,
7674 options,
7675 declaration_blendweight,
7676 vertex_size_blendweight,
7677 flags10,
7678 &epsilons10,
7679 adjacency10,
7680 (BYTE*)exp_vertices10,
7681 exp_indices10,
7682 exp_face_remap10,
7683 exp_vertex_remap10,
7684 exp_new_num_vertices10
7687 (BYTE*)vertices11,
7688 indices11,
7689 attributes11,
7690 num_vertices11,
7691 num_faces11,
7692 options,
7693 declaration_texcoord,
7694 vertex_size_texcoord,
7695 flags11,
7696 &epsilons11,
7697 adjacency11,
7698 (BYTE*)exp_vertices11,
7699 exp_indices11,
7700 exp_face_remap11,
7701 exp_vertex_remap11,
7702 exp_new_num_vertices11
7705 (BYTE*)vertices12,
7706 indices12,
7707 attributes12,
7708 num_vertices12,
7709 num_faces12,
7710 options,
7711 declaration_color,
7712 vertex_size_color,
7713 flags12,
7714 &epsilons12,
7715 adjacency12,
7716 (BYTE*)exp_vertices12,
7717 exp_indices12,
7718 exp_face_remap12,
7719 exp_vertex_remap12,
7720 exp_new_num_vertices12
7723 (BYTE*)vertices13,
7724 indices13,
7725 attributes13,
7726 num_vertices13,
7727 num_faces13,
7728 options,
7729 declaration_normal3,
7730 vertex_size_normal,
7731 flags13,
7732 &epsilons13,
7733 adjacency13,
7734 (BYTE*)exp_vertices13,
7735 exp_indices13,
7736 exp_face_remap13,
7737 exp_vertex_remap13,
7738 exp_new_num_vertices13
7741 (BYTE*)vertices14,
7742 indices14,
7743 attributes14,
7744 num_vertices14,
7745 num_faces14,
7746 options,
7747 declaration_color,
7748 vertex_size_color,
7749 flags14,
7750 &epsilons14,
7751 adjacency14,
7752 (BYTE*)exp_vertices14,
7753 exp_indices14,
7754 exp_face_remap14,
7755 exp_vertex_remap14,
7756 exp_new_num_vertices14
7759 (BYTE*)vertices15,
7760 indices15,
7761 attributes15,
7762 num_vertices15,
7763 num_faces15,
7764 options,
7765 declaration_color_ubyte4n,
7766 vertex_size_color_ubyte4, /* UBYTE4 same size as UBYTE4N */
7767 flags15,
7768 &epsilons15,
7769 adjacency15,
7770 (BYTE*)exp_vertices15,
7771 exp_indices15,
7772 exp_face_remap15,
7773 exp_vertex_remap15,
7774 exp_new_num_vertices15
7777 (BYTE*)vertices16,
7778 indices16,
7779 attributes16,
7780 num_vertices16,
7781 num_faces16,
7782 options,
7783 declaration_color_ubyte4,
7784 vertex_size_color_ubyte4,
7785 flags16,
7786 &epsilons16,
7787 adjacency16,
7788 (BYTE*)exp_vertices16,
7789 exp_indices16,
7790 exp_face_remap16,
7791 exp_vertex_remap16,
7792 exp_new_num_vertices16
7795 (BYTE*)vertices17,
7796 indices17,
7797 attributes17,
7798 num_vertices17,
7799 num_faces17,
7800 options,
7801 declaration_texcoord_short2,
7802 vertex_size_texcoord_short2,
7803 flags17,
7804 &epsilons17,
7805 adjacency17,
7806 (BYTE*)exp_vertices17,
7807 exp_indices17,
7808 exp_face_remap17,
7809 exp_vertex_remap17,
7810 exp_new_num_vertices17
7813 (BYTE*)vertices18,
7814 indices18,
7815 attributes18,
7816 num_vertices18,
7817 num_faces18,
7818 options,
7819 declaration_texcoord_short2n,
7820 vertex_size_texcoord_short2, /* SHORT2 same size as SHORT2N */
7821 flags18,
7822 &epsilons18,
7823 adjacency18,
7824 (BYTE*)exp_vertices18,
7825 exp_indices18,
7826 exp_face_remap18,
7827 exp_vertex_remap18,
7828 exp_new_num_vertices18
7831 (BYTE*)vertices19,
7832 indices19,
7833 attributes19,
7834 num_vertices19,
7835 num_faces19,
7836 options,
7837 declaration_texcoord_ushort2n,
7838 vertex_size_texcoord_short2, /* SHORT2 same size as USHORT2N */
7839 flags19,
7840 &epsilons19,
7841 adjacency19,
7842 (BYTE*)exp_vertices19,
7843 exp_indices19,
7844 exp_face_remap19,
7845 exp_vertex_remap19,
7846 exp_new_num_vertices19
7849 (BYTE*)vertices20,
7850 indices20,
7851 attributes20,
7852 num_vertices20,
7853 num_faces20,
7854 options,
7855 declaration_normal_short4,
7856 vertex_size_normal_short4,
7857 flags20,
7858 &epsilons20,
7859 adjacency20,
7860 (BYTE*)exp_vertices20,
7861 exp_indices20,
7862 exp_face_remap20,
7863 exp_vertex_remap20,
7864 exp_new_num_vertices20
7867 (BYTE*)vertices21,
7868 indices21,
7869 attributes21,
7870 num_vertices21,
7871 num_faces21,
7872 options,
7873 declaration_normal_short4n,
7874 vertex_size_normal_short4, /* SHORT4 same size as SHORT4N */
7875 flags21,
7876 &epsilons21,
7877 adjacency21,
7878 (BYTE*)exp_vertices21,
7879 exp_indices21,
7880 exp_face_remap21,
7881 exp_vertex_remap21,
7882 exp_new_num_vertices21
7885 (BYTE*)vertices22,
7886 indices22,
7887 attributes22,
7888 num_vertices22,
7889 num_faces22,
7890 options,
7891 declaration_normal_ushort4n,
7892 vertex_size_normal_short4, /* SHORT4 same size as USHORT4N */
7893 flags22,
7894 &epsilons22,
7895 adjacency22,
7896 (BYTE*)exp_vertices22,
7897 exp_indices22,
7898 exp_face_remap22,
7899 exp_vertex_remap22,
7900 exp_new_num_vertices22
7903 (BYTE*)vertices23,
7904 indices23,
7905 attributes23,
7906 num_vertices23,
7907 num_faces23,
7908 options,
7909 declaration_texcoord_float16_2,
7910 vertex_size_texcoord_float16_2,
7911 flags23,
7912 &epsilons23,
7913 adjacency23,
7914 (BYTE*)exp_vertices23,
7915 exp_indices23,
7916 exp_face_remap23,
7917 exp_vertex_remap23,
7918 exp_new_num_vertices23
7921 (BYTE*)vertices24,
7922 indices24,
7923 attributes24,
7924 num_vertices24,
7925 num_faces24,
7926 options,
7927 declaration_texcoord_float16_4,
7928 vertex_size_texcoord_float16_4,
7929 flags24,
7930 &epsilons24,
7931 adjacency24,
7932 (BYTE*)exp_vertices24,
7933 exp_indices24,
7934 exp_face_remap24,
7935 exp_vertex_remap24,
7936 exp_new_num_vertices24
7939 (BYTE*)vertices25,
7940 indices25,
7941 attributes25,
7942 num_vertices25,
7943 num_faces25,
7944 options,
7945 declaration_texcoord10,
7946 vertex_size_texcoord,
7947 flags25,
7948 &epsilons25,
7949 adjacency25,
7950 (BYTE*)exp_vertices25,
7951 exp_indices25,
7952 exp_face_remap25,
7953 exp_vertex_remap25,
7954 exp_new_num_vertices25
7957 (BYTE*)vertices26,
7958 indices26,
7959 attributes26,
7960 num_vertices26,
7961 num_faces26,
7962 options,
7963 declaration_color2,
7964 vertex_size_color,
7965 flags26,
7966 &epsilons26,
7967 adjacency26,
7968 (BYTE*)exp_vertices26,
7969 exp_indices26,
7970 exp_face_remap26,
7971 exp_vertex_remap26,
7972 exp_new_num_vertices26
7975 (BYTE*)vertices27,
7976 indices27,
7977 attributes27,
7978 num_vertices27,
7979 num_faces27,
7980 options,
7981 declaration_color2_float4,
7982 vertex_size_color_float4,
7983 flags27,
7984 &epsilons27,
7985 adjacency27,
7986 (BYTE*)exp_vertices27,
7987 exp_indices27,
7988 exp_face_remap27,
7989 exp_vertex_remap27,
7990 exp_new_num_vertices27
7993 (BYTE*)vertices28,
7994 indices28,
7995 attributes28,
7996 num_vertices28,
7997 num_faces28,
7998 options,
7999 declaration_normal_udec3,
8000 vertex_size_normal_udec3,
8001 flags28,
8002 &epsilons28,
8003 adjacency28,
8004 (BYTE*)exp_vertices28,
8005 exp_indices28,
8006 exp_face_remap28,
8007 exp_vertex_remap28,
8008 exp_new_num_vertices28
8011 (BYTE*)vertices29,
8012 indices29,
8013 attributes29,
8014 num_vertices29,
8015 num_faces29,
8016 options,
8017 declaration_normal_dec3n,
8018 vertex_size_normal_dec3n,
8019 flags29,
8020 &epsilons29,
8021 adjacency29,
8022 (BYTE*)exp_vertices29,
8023 exp_indices29,
8024 exp_face_remap29,
8025 exp_vertex_remap29,
8026 exp_new_num_vertices29
8030 test_context = new_test_context();
8031 if (!test_context)
8033 skip("Couldn't create test context\n");
8034 goto cleanup;
8037 for (i = 0; i < ARRAY_SIZE(tc); i++)
8039 DWORD j;
8040 DWORD *vertex_remap_ptr;
8041 DWORD new_num_vertices;
8043 hr = init_test_mesh(tc[i].num_faces, tc[i].num_vertices, tc[i].options,
8044 tc[i].declaration, test_context->device, &mesh,
8045 tc[i].vertices, tc[i].vertex_size,
8046 tc[i].indices, tc[i].attributes);
8047 if (FAILED(hr))
8049 skip("Couldn't initialize test mesh %d.\n", i);
8050 goto cleanup;
8053 /* Allocate out parameters */
8054 adjacency_out = HeapAlloc(GetProcessHeap(), 0, VERTS_PER_FACE * tc[i].num_faces * sizeof(*adjacency_out));
8055 if (!adjacency_out)
8057 skip("Couldn't allocate adjacency_out array.\n");
8058 goto cleanup;
8060 face_remap = HeapAlloc(GetProcessHeap(), 0, tc[i].num_faces * sizeof(*face_remap));
8061 if (!adjacency_out)
8063 skip("Couldn't allocate face_remap array.\n");
8064 goto cleanup;
8066 hr = D3DXCreateBuffer(tc[i].num_vertices * sizeof(DWORD), &vertex_remap);
8067 if (FAILED(hr))
8069 skip("Couldn't create vertex_remap buffer.\n");
8070 goto cleanup;
8073 hr = D3DXWeldVertices(mesh, tc[i].flags, tc[i].epsilons, tc[i].adjacency,
8074 adjacency_out, face_remap, &vertex_remap);
8075 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
8076 /* Check number of vertices*/
8077 new_num_vertices = mesh->lpVtbl->GetNumVertices(mesh);
8078 ok(new_num_vertices == tc[i].exp_new_num_vertices,
8079 "Mesh %d: new_num_vertices == %d, expected %d.\n",
8080 i, new_num_vertices, tc[i].exp_new_num_vertices);
8081 /* Check index buffer */
8082 if (tc[i].options & D3DXMESH_32BIT)
8084 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, (void**)&indices);
8085 if (FAILED(hr))
8087 skip("Couldn't lock index buffer.\n");
8088 goto cleanup;
8090 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
8092 ok(indices[j] == tc[i].exp_indices[j],
8093 "Mesh %d: indices[%d] == %d, expected %d\n",
8094 i, j, indices[j], tc[i].exp_indices[j]);
8097 else
8099 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, (void**)&indices_16bit);
8100 if (FAILED(hr))
8102 skip("Couldn't lock index buffer.\n");
8103 goto cleanup;
8105 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
8107 ok(indices_16bit[j] == tc[i].exp_indices[j],
8108 "Mesh %d: indices_16bit[%d] == %d, expected %d\n",
8109 i, j, indices_16bit[j], tc[i].exp_indices[j]);
8112 mesh->lpVtbl->UnlockIndexBuffer(mesh);
8113 indices = NULL;
8114 indices_16bit = NULL;
8115 /* Check adjacency_out */
8116 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
8118 ok(adjacency_out[j] == tc[i].adjacency[j],
8119 "Mesh %d: adjacency_out[%d] == %d, expected %d\n",
8120 i, j, adjacency_out[j], tc[i].adjacency[j]);
8122 /* Check face_remap */
8123 for (j = 0; j < tc[i].num_faces; j++)
8125 ok(face_remap[j] == tc[i].exp_face_remap[j],
8126 "Mesh %d: face_remap[%d] == %d, expected %d\n",
8127 i, j, face_remap[j], tc[i].exp_face_remap[j]);
8129 /* Check vertex_remap */
8130 vertex_remap_ptr = vertex_remap->lpVtbl->GetBufferPointer(vertex_remap);
8131 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
8133 ok(vertex_remap_ptr[j] == tc[i].exp_vertex_remap[j],
8134 "Mesh %d: vertex_remap_ptr[%d] == %d, expected %d\n",
8135 i, j, vertex_remap_ptr[j], tc[i].exp_vertex_remap[j]);
8137 /* Check vertex buffer */
8138 hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, (void*)&vertices);
8139 if (FAILED(hr))
8141 skip("Couldn't lock vertex buffer.\n");
8142 goto cleanup;
8144 /* Check contents of re-ordered vertex buffer */
8145 for (j = 0; j < tc[i].exp_new_num_vertices; j++)
8147 int index = tc[i].vertex_size*j;
8148 check_vertex_components(__LINE__, i, j, &vertices[index], &tc[i].exp_vertices[index], tc[i].declaration);
8150 mesh->lpVtbl->UnlockVertexBuffer(mesh);
8151 vertices = NULL;
8153 /* Free mesh and output data */
8154 HeapFree(GetProcessHeap(), 0, adjacency_out);
8155 adjacency_out = NULL;
8156 HeapFree(GetProcessHeap(), 0, face_remap);
8157 face_remap = NULL;
8158 vertex_remap->lpVtbl->Release(vertex_remap);
8159 vertex_remap = NULL;
8160 mesh->lpVtbl->Release(mesh);
8161 mesh = NULL;
8164 cleanup:
8165 HeapFree(GetProcessHeap(), 0, adjacency_out);
8166 HeapFree(GetProcessHeap(), 0, face_remap);
8167 if (indices) mesh->lpVtbl->UnlockIndexBuffer(mesh);
8168 if (indices_16bit) mesh->lpVtbl->UnlockIndexBuffer(mesh);
8169 if (mesh) mesh->lpVtbl->Release(mesh);
8170 if (vertex_remap) vertex_remap->lpVtbl->Release(vertex_remap);
8171 if (vertices) mesh->lpVtbl->UnlockVertexBuffer(mesh);
8172 free_test_context(test_context);
8175 static void test_clone_mesh(void)
8177 HRESULT hr;
8178 struct test_context *test_context = NULL;
8179 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
8180 D3DVERTEXELEMENT9 declaration_pn[] =
8182 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8183 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
8184 D3DDECL_END()
8186 D3DVERTEXELEMENT9 declaration_pntc[] =
8188 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8189 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
8190 {0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8191 D3DDECL_END()
8193 D3DVERTEXELEMENT9 declaration_ptcn[] =
8195 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8196 {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8197 {0, 20, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
8198 D3DDECL_END()
8200 D3DVERTEXELEMENT9 declaration_ptc[] =
8202 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8203 {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8204 D3DDECL_END()
8206 D3DVERTEXELEMENT9 declaration_ptc_float16_2[] =
8208 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8209 {0, 12, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8210 D3DDECL_END()
8212 D3DVERTEXELEMENT9 declaration_ptc_float16_4[] =
8214 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8215 {0, 12, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8216 D3DDECL_END()
8218 D3DVERTEXELEMENT9 declaration_ptc_float1[] =
8220 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8221 {0, 12, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8222 D3DDECL_END()
8224 D3DVERTEXELEMENT9 declaration_ptc_float3[] =
8226 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8227 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8228 D3DDECL_END()
8230 D3DVERTEXELEMENT9 declaration_ptc_float4[] =
8232 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8233 {0, 12, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8234 D3DDECL_END()
8236 D3DVERTEXELEMENT9 declaration_ptc_d3dcolor[] =
8238 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8239 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8240 D3DDECL_END()
8242 D3DVERTEXELEMENT9 declaration_ptc_ubyte4[] =
8244 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8245 {0, 12, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8246 D3DDECL_END()
8248 D3DVERTEXELEMENT9 declaration_ptc_ubyte4n[] =
8250 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8251 {0, 12, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8252 D3DDECL_END()
8254 D3DVERTEXELEMENT9 declaration_ptc_short2[] =
8256 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8257 {0, 12, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8258 D3DDECL_END()
8260 D3DVERTEXELEMENT9 declaration_ptc_short4[] =
8262 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8263 {0, 12, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8264 D3DDECL_END()
8266 D3DVERTEXELEMENT9 declaration_ptc_short2n[] =
8268 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8269 {0, 12, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8270 D3DDECL_END()
8272 D3DVERTEXELEMENT9 declaration_ptc_short4n[] =
8274 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8275 {0, 12, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8276 D3DDECL_END()
8278 D3DVERTEXELEMENT9 declaration_ptc_ushort2n[] =
8280 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8281 {0, 12, D3DDECLTYPE_USHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8282 D3DDECL_END()
8284 D3DVERTEXELEMENT9 declaration_ptc_ushort4n[] =
8286 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8287 {0, 12, D3DDECLTYPE_USHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8288 D3DDECL_END()
8290 D3DVERTEXELEMENT9 declaration_ptc_float16_2_partialu[] =
8292 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8293 {0, 12, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_PARTIALU, D3DDECLUSAGE_TEXCOORD, 0},
8294 D3DDECL_END()
8296 D3DVERTEXELEMENT9 declaration_pntc1[] =
8298 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8299 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
8300 {0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
8301 D3DDECL_END()
8303 const unsigned int VERTS_PER_FACE = 3;
8304 BYTE *vertices = NULL;
8305 INT i;
8306 struct vertex_pn
8308 D3DXVECTOR3 position;
8309 D3DXVECTOR3 normal;
8311 struct vertex_pntc
8313 D3DXVECTOR3 position;
8314 D3DXVECTOR3 normal;
8315 D3DXVECTOR2 texcoords;
8317 struct vertex_ptcn
8319 D3DXVECTOR3 position;
8320 D3DXVECTOR2 texcoords;
8321 D3DXVECTOR3 normal;
8323 struct vertex_ptc
8325 D3DXVECTOR3 position;
8326 D3DXVECTOR2 texcoords;
8328 struct vertex_ptc_float16_2
8330 D3DXVECTOR3 position;
8331 WORD texcoords[2]; /* float16_2 */
8333 struct vertex_ptc_float16_4
8335 D3DXVECTOR3 position;
8336 WORD texcoords[4]; /* float16_4 */
8338 struct vertex_ptc_float1
8340 D3DXVECTOR3 position;
8341 FLOAT texcoords;
8343 struct vertex_ptc_float3
8345 D3DXVECTOR3 position;
8346 FLOAT texcoords[3];
8348 struct vertex_ptc_float4
8350 D3DXVECTOR3 position;
8351 FLOAT texcoords[4];
8353 struct vertex_ptc_d3dcolor
8355 D3DXVECTOR3 position;
8356 BYTE texcoords[4];
8358 struct vertex_ptc_ubyte4
8360 D3DXVECTOR3 position;
8361 BYTE texcoords[4];
8363 struct vertex_ptc_ubyte4n
8365 D3DXVECTOR3 position;
8366 BYTE texcoords[4];
8368 struct vertex_ptc_short2
8370 D3DXVECTOR3 position;
8371 SHORT texcoords[2];
8373 struct vertex_ptc_short4
8375 D3DXVECTOR3 position;
8376 SHORT texcoords[4];
8378 struct vertex_ptc_ushort2n
8380 D3DXVECTOR3 position;
8381 USHORT texcoords[2];
8383 struct vertex_ptc_ushort4n
8385 D3DXVECTOR3 position;
8386 USHORT texcoords[4];
8388 struct vertex_ptc_udec3
8390 D3DXVECTOR3 position;
8391 DWORD texcoords;
8393 struct vertex_ptc_dec3n
8395 D3DXVECTOR3 position;
8396 DWORD texcoords;
8398 D3DXVECTOR3 up = {0.0f, 0.0f, 1.0f};
8399 D3DXVECTOR2 zero_vec2 = {0.0f, 0.0f};
8400 /* Test 0. Check that a mesh can be cloned if the new declaration is the
8401 * same as the one used to create the mesh.
8403 * 0--1 3
8404 * | / /|
8405 * |/ / |
8406 * 2 5--4
8408 const struct vertex_pn vertices0[] =
8410 {{ 0.0f, 3.0f, 0.f}, up},
8411 {{ 2.0f, 3.0f, 0.f}, up},
8412 {{ 0.0f, 0.0f, 0.f}, up},
8414 {{ 3.0f, 3.0f, 0.f}, up},
8415 {{ 3.0f, 0.0f, 0.f}, up},
8416 {{ 1.0f, 0.0f, 0.f}, up},
8418 const UINT num_vertices0 = ARRAY_SIZE(vertices0);
8419 const UINT num_faces0 = ARRAY_SIZE(vertices0) / VERTS_PER_FACE;
8420 const UINT vertex_size0 = sizeof(*vertices0);
8421 /* Test 1. Check that 16-bit indices are handled. */
8422 const DWORD options_16bit = D3DXMESH_SYSTEMMEM;
8423 /* Test 2. Check that the size of each vertex is increased and the data
8424 * moved if the new declaration adds an element after the original elements.
8426 const struct vertex_pntc exp_vertices2[] =
8428 {{ 0.0f, 3.0f, 0.f}, up, zero_vec2},
8429 {{ 2.0f, 3.0f, 0.f}, up, zero_vec2},
8430 {{ 0.0f, 0.0f, 0.f}, up, zero_vec2},
8432 {{ 3.0f, 3.0f, 0.f}, up, zero_vec2},
8433 {{ 3.0f, 0.0f, 0.f}, up, zero_vec2},
8434 {{ 1.0f, 0.0f, 0.f}, up, zero_vec2},
8436 const UINT exp_vertex_size2 = sizeof(*exp_vertices2);
8437 /* Test 3. Check that the size of each vertex is increased and the data
8438 * moved if the new declaration adds an element between the original
8439 * elements.
8441 const struct vertex_ptcn exp_vertices3[] =
8443 {{ 0.0f, 3.0f, 0.f}, zero_vec2, up},
8444 {{ 2.0f, 3.0f, 0.f}, zero_vec2, up},
8445 {{ 0.0f, 0.0f, 0.f}, zero_vec2, up},
8447 {{ 3.0f, 3.0f, 0.f}, zero_vec2, up},
8448 {{ 3.0f, 0.0f, 0.f}, zero_vec2, up},
8449 {{ 1.0f, 0.0f, 0.f}, zero_vec2, up},
8451 const UINT exp_vertex_size3 = sizeof(*exp_vertices3);
8452 /* Test 4. Test that data types can be converted, e.g. FLOAT2 to FLOAT16_2. */
8453 const struct vertex_ptc vertices4[] =
8455 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8456 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8457 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
8459 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8460 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
8461 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
8463 const UINT num_vertices4 = ARRAY_SIZE(vertices4);
8464 const UINT num_faces4 = ARRAY_SIZE(vertices4) / VERTS_PER_FACE;
8465 const UINT vertex_size4 = sizeof(*vertices4);
8466 const struct vertex_ptc_float16_2 exp_vertices4[] =
8468 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
8469 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */
8470 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */
8472 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd}}, /* {0.2f, 0.3f} */
8473 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
8474 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */
8476 const UINT exp_vertex_size4 = sizeof(*exp_vertices4);
8477 /* Test 5. Convert FLOAT2 to FLOAT16_4. */
8478 const struct vertex_ptc vertices5[] =
8480 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8481 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8482 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
8484 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8485 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
8486 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
8488 const UINT num_vertices5 = ARRAY_SIZE(vertices5);
8489 const UINT num_faces5 = ARRAY_SIZE(vertices5) / VERTS_PER_FACE;
8490 const UINT vertex_size5 = sizeof(*vertices5);
8491 const struct vertex_ptc_float16_4 exp_vertices5[] =
8493 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00, 0, 0x3c00}}, /* {1.0f, 1.0f, 0.0f, 1.0f} */
8494 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a, 0, 0x3c00}}, /* {0.5f, 0.7f, 0.0f, 1.0f} */
8495 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd, 0, 0x3c00}}, /* {-0.2f, -0.3f, 0.0f, 1.0f} */
8497 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd, 0, 0x3c00}}, /* {0.2f, 0.3f, 0.0f, 1.0f} */
8498 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00, 0, 0x3c00}}, /* {1.0f, 1.0f, 0.0f, 1.0f} */
8499 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266, 0, 0x3c00}}, /* {0.1f, 0.2f, 0.0f, 1.0f} */
8501 const UINT exp_vertex_size5 = sizeof(*exp_vertices5);
8502 /* Test 6. Convert FLOAT2 to FLOAT1. */
8503 const struct vertex_ptc vertices6[] =
8505 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8506 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8507 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
8509 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8510 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
8511 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
8513 const UINT num_vertices6 = ARRAY_SIZE(vertices6);
8514 const UINT num_faces6 = ARRAY_SIZE(vertices6) / VERTS_PER_FACE;
8515 const UINT vertex_size6 = sizeof(*vertices6);
8516 const struct vertex_ptc_float1 exp_vertices6[] =
8518 {{ 0.0f, 3.0f, 0.f}, 1.0f},
8519 {{ 2.0f, 3.0f, 0.f}, 0.5f},
8520 {{ 0.0f, 0.0f, 0.f}, -0.2f},
8522 {{ 3.0f, 3.0f, 0.f}, 0.2f},
8523 {{ 3.0f, 0.0f, 0.f}, 1.0f},
8524 {{ 1.0f, 0.0f, 0.f}, 0.1f},
8526 const UINT exp_vertex_size6 = sizeof(*exp_vertices6);
8527 /* Test 7. Convert FLOAT2 to FLOAT3. */
8528 const struct vertex_ptc vertices7[] =
8530 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8531 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8532 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
8534 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8535 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
8536 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
8538 const UINT num_vertices7 = ARRAY_SIZE(vertices7);
8539 const UINT num_faces7 = ARRAY_SIZE(vertices7) / VERTS_PER_FACE;
8540 const UINT vertex_size7 = sizeof(*vertices7);
8541 const struct vertex_ptc_float3 exp_vertices7[] =
8543 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f, 0.0f}},
8544 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f, 0.0f}},
8545 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f, 0.0f}},
8547 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f, 0.0f}},
8548 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f, 0.0f}},
8549 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f, 0.0f}},
8551 const UINT exp_vertex_size7 = sizeof(*exp_vertices7);
8552 /* Test 8. Convert FLOAT2 to FLOAT4. */
8553 const struct vertex_ptc vertices8[] =
8555 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8556 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8557 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
8559 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8560 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
8561 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
8563 const UINT num_vertices8 = ARRAY_SIZE(vertices8);
8564 const UINT num_faces8 = ARRAY_SIZE(vertices8) / VERTS_PER_FACE;
8565 const UINT vertex_size8 = sizeof(*vertices8);
8566 const struct vertex_ptc_float4 exp_vertices8[] =
8568 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f, 0.0f, 1.0f}},
8569 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f, 0.0f, 1.0f}},
8570 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f, 0.0f, 1.0f}},
8572 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f, 0.0f, 1.0f}},
8573 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f, 0.0f, 1.0f}},
8574 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f, 0.0f, 1.0f}},
8576 const UINT exp_vertex_size8 = sizeof(*exp_vertices8);
8577 /* Test 9. Convert FLOAT2 to D3DCOLOR. */
8578 const struct vertex_ptc vertices9[] =
8580 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8581 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8582 {{ 0.0f, 0.0f, 0.f}, {-0.4f, -0.6f}},
8584 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8585 {{ 3.0f, 0.0f, 0.f}, { 2.0f, 256.0f}},
8586 {{ 1.0f, 0.0f, 0.f}, { 0.11f, 0.2f}},
8588 const UINT num_vertices9 = ARRAY_SIZE(vertices9);
8589 const UINT num_faces9 = ARRAY_SIZE(vertices9) / VERTS_PER_FACE;
8590 const UINT vertex_size9 = sizeof(*vertices9);
8591 const struct vertex_ptc_d3dcolor exp_vertices9[] =
8593 {{ 0.0f, 3.0f, 0.f}, {0, 255, 255, 255}},
8594 {{ 2.0f, 3.0f, 0.f}, {0, 179, 128, 255}},
8595 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 255}},
8597 {{ 3.0f, 3.0f, 0.f}, {0, 77, 51, 255}},
8598 {{ 3.0f, 0.0f, 0.f}, {0, 255, 255, 255}},
8599 {{ 1.0f, 0.0f, 0.f}, {0, 51, 28, 255}},
8601 const UINT exp_vertex_size9 = sizeof(*exp_vertices9);
8602 /* Test 10. Convert FLOAT2 to UBYTE4. */
8603 const struct vertex_ptc vertices10[] =
8605 {{ 0.0f, 3.0f, 0.f}, { 0.0f, 1.0f}},
8606 {{ 2.0f, 3.0f, 0.f}, { 2.0f, 3.0f}},
8607 {{ 0.0f, 0.0f, 0.f}, { 254.0f, 255.0f}},
8609 {{ 3.0f, 3.0f, 0.f}, { 256.0f, 257.0f}},
8610 {{ 3.0f, 0.0f, 0.f}, { 1.4f, 1.5f}},
8611 {{ 1.0f, 0.0f, 0.f}, {-4.0f, -5.0f}},
8613 const UINT num_vertices10 = ARRAY_SIZE(vertices10);
8614 const UINT num_faces10 = ARRAY_SIZE(vertices10) / VERTS_PER_FACE;
8615 const UINT vertex_size10 = sizeof(*vertices10);
8616 const struct vertex_ptc_ubyte4 exp_vertices10[] =
8618 {{ 0.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
8619 {{ 2.0f, 3.0f, 0.f}, {2, 3, 0, 1}},
8620 {{ 0.0f, 0.0f, 0.f}, {254, 255, 0, 1}},
8622 {{ 3.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
8623 {{ 3.0f, 0.0f, 0.f}, {1, 2, 0, 1}},
8624 {{ 1.0f, 0.0f, 0.f}, {0, 0, 0, 1}},
8626 const UINT exp_vertex_size10 = sizeof(*exp_vertices10);
8627 /* Test 11. Convert FLOAT2 to SHORT2. */
8628 const struct vertex_ptc vertices11[] =
8630 {{ 0.0f, 3.0f, 0.f}, { 1.0f, -1.0f}},
8631 {{ 2.0f, 3.0f, 0.f}, { 0.4f, 0.5f}},
8632 {{ 0.0f, 0.0f, 0.f}, {-0.5f, -5.0f}},
8634 {{ 3.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MIN}},
8635 {{ 3.0f, 0.0f, 0.f}, {SHRT_MAX + 1.0f, SHRT_MIN - 1.0f}},
8636 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX + 2.0f, SHRT_MIN - 2.0f}},
8638 {{ 4.0f, 3.0f, 0.f}, {2 * SHRT_MAX, 2 * SHRT_MIN}},
8639 {{ 6.0f, 0.0f, 0.f}, {3 * SHRT_MAX, 3 * SHRT_MIN}},
8640 {{ 4.0f, 0.0f, 0.f}, {4 * SHRT_MAX, 4 * SHRT_MIN}},
8642 const UINT num_vertices11 = ARRAY_SIZE(vertices11);
8643 const UINT num_faces11 = ARRAY_SIZE(vertices11) / VERTS_PER_FACE;
8644 const UINT vertex_size11 = sizeof(*vertices11);
8645 const struct vertex_ptc_short2 exp_vertices11[] =
8647 {{ 0.0f, 3.0f, 0.f}, {1, 0}},
8648 {{ 2.0f, 3.0f, 0.f}, {0, 1}},
8649 {{ 0.0f, 0.0f, 0.f}, {0, -4}},
8651 {{ 3.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MIN + 1}},
8652 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MIN}},
8653 {{ 1.0f, 0.0f, 0.f}, {SHRT_MIN + 1, SHRT_MAX}},
8655 {{ 4.0f, 3.0f, 0.f}, {-2, 1}},
8656 {{ 6.0f, 0.0f, 0.f}, {32765, -32767}},
8657 {{ 4.0f, 0.0f, 0.f}, {-4, 1}},
8659 const UINT exp_vertex_size11 = sizeof(*exp_vertices11);
8660 /* Test 12. Convert FLOAT2 to SHORT4. */
8661 const struct vertex_ptc vertices12[] =
8663 {{ 0.0f, 3.0f, 0.f}, { 1.0f, -1.0f}},
8664 {{ 2.0f, 3.0f, 0.f}, { 0.4f, 0.5f}},
8665 {{ 0.0f, 0.0f, 0.f}, {-0.5f, -5.0f}},
8667 {{ 3.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MIN}},
8668 {{ 3.0f, 0.0f, 0.f}, {SHRT_MAX + 1.0f, SHRT_MIN - 1.0f}},
8669 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX + 2.0f, SHRT_MIN - 2.0f}},
8671 {{ 4.0f, 3.0f, 0.f}, {2 * SHRT_MAX, 2 * SHRT_MIN}},
8672 {{ 6.0f, 0.0f, 0.f}, {3 * SHRT_MAX, 3 * SHRT_MIN}},
8673 {{ 4.0f, 0.0f, 0.f}, {4 * SHRT_MAX, 4 * SHRT_MIN}},
8675 const UINT num_vertices12 = ARRAY_SIZE(vertices12);
8676 const UINT num_faces12 = ARRAY_SIZE(vertices12) / VERTS_PER_FACE;
8677 const UINT vertex_size12 = sizeof(*vertices12);
8678 const struct vertex_ptc_short4 exp_vertices12[] =
8680 {{ 0.0f, 3.0f, 0.f}, {1, 0, 0, 1}},
8681 {{ 2.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
8682 {{ 0.0f, 0.0f, 0.f}, {0, -4, 0, 1}},
8684 {{ 3.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MIN + 1, 0, 1}},
8685 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MIN, 0, 1}},
8686 {{ 1.0f, 0.0f, 0.f}, {SHRT_MIN + 1, SHRT_MAX, 0, 1}},
8688 {{ 4.0f, 3.0f, 0.f}, {-2, 1, 0, 1}},
8689 {{ 6.0f, 0.0f, 0.f}, {32765, -32767, 0, 1}},
8690 {{ 4.0f, 0.0f, 0.f}, {-4, 1, 0, 1}},
8692 const UINT exp_vertex_size12 = sizeof(*exp_vertices12);
8693 /* Test 13. Convert FLOAT2 to UBYTE4N. */
8694 const struct vertex_ptc vertices13[] =
8696 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 2.0f}},
8697 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8698 {{ 0.0f, 0.0f, 0.f}, {-0.4f, -0.5f}},
8700 {{ 3.0f, 3.0f, 0.f}, {-0.6f, -1.0f}},
8701 {{ 3.0f, 0.0f, 0.f}, {UCHAR_MAX, UCHAR_MAX + 1}},
8702 {{ 1.0f, 0.0f, 0.f}, {2 * UCHAR_MAX, -UCHAR_MAX}},
8704 const UINT num_vertices13 = ARRAY_SIZE(vertices13);
8705 const UINT num_faces13 = ARRAY_SIZE(vertices13) / VERTS_PER_FACE;
8706 const UINT vertex_size13 = sizeof(*vertices13);
8707 const struct vertex_ptc_ubyte4n exp_vertices13[] =
8709 {{ 0.0f, 3.0f, 0.f}, {255, 255, 0, 255}},
8710 {{ 2.0f, 3.0f, 0.f}, {128, 179, 0, 255}},
8711 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 255}},
8713 {{ 3.0f, 3.0f, 0.f}, {0, 0, 0, 255}},
8714 {{ 3.0f, 0.0f, 0.f}, {255, 255, 0, 255}},
8715 {{ 1.0f, 0.0f, 0.f}, {255, 0, 0, 255}},
8717 const UINT exp_vertex_size13 = sizeof(*exp_vertices13);
8718 /* Test 14. Convert FLOAT2 to SHORT2N. */
8719 const struct vertex_ptc vertices14[] =
8721 {{ 0.0f, 3.0f, 0.f}, {1.0f, 2.0f}},
8722 {{ 2.0f, 3.0f, 0.f}, {0.4f, 0.5f}},
8723 {{ 0.0f, 0.0f, 0.f}, {0.6f, -1.0f}},
8725 {{ 3.0f, 3.0f, 0.f}, {-0.4f, -0.5f}},
8726 {{ 3.0f, 0.0f, 0.f}, {-0.9f, -0.99997}},
8727 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX, SHRT_MIN}},
8729 const UINT num_vertices14 = ARRAY_SIZE(vertices14);
8730 const UINT num_faces14 = ARRAY_SIZE(vertices14) / VERTS_PER_FACE;
8731 const UINT vertex_size14 = sizeof(*vertices14);
8732 const struct vertex_ptc_short2 exp_vertices14[] =
8734 {{ 0.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MAX}},
8735 {{ 2.0f, 3.0f, 0.f}, {13107, 16384}},
8736 {{ 0.0f, 0.0f, 0.f}, {19660, SHRT_MIN + 2}},
8738 {{ 3.0f, 3.0f, 0.f}, {-13106, -16383}},
8739 {{ 3.0f, 0.0f, 0.f}, {-29489, SHRT_MIN + 3}},
8740 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX, SHRT_MIN + 2}},
8742 const UINT exp_vertex_size14 = sizeof(*exp_vertices14);
8743 /* Test 15. Convert FLOAT2 to SHORT4N. */
8744 const struct vertex_ptc vertices15[] =
8746 {{ 0.0f, 3.0f, 0.f}, {1.0f, 2.0f}},
8747 {{ 2.0f, 3.0f, 0.f}, {0.4f, 0.5f}},
8748 {{ 0.0f, 0.0f, 0.f}, {0.6f, -1.0f}},
8750 {{ 3.0f, 3.0f, 0.f}, {-0.4f, -0.5f}},
8751 {{ 3.0f, 0.0f, 0.f}, {-0.9f, -0.99997}},
8752 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX, SHRT_MIN}},
8754 const UINT num_vertices15 = ARRAY_SIZE(vertices15);
8755 const UINT num_faces15 = ARRAY_SIZE(vertices15) / VERTS_PER_FACE;
8756 const UINT vertex_size15 = sizeof(*vertices15);
8757 const struct vertex_ptc_short4 exp_vertices15[] =
8759 {{ 0.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MAX, 0, SHRT_MAX}},
8760 {{ 2.0f, 3.0f, 0.f}, {13107, 16384, 0, SHRT_MAX}},
8761 {{ 0.0f, 0.0f, 0.f}, {19660, SHRT_MIN + 2, 0, SHRT_MAX}},
8763 {{ 3.0f, 3.0f, 0.f}, {-13106, -16383, 0, SHRT_MAX}},
8764 {{ 3.0f, 0.0f, 0.f}, {-29489, SHRT_MIN + 3, 0, SHRT_MAX}},
8765 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX, SHRT_MIN + 2, 0, SHRT_MAX}},
8767 const UINT exp_vertex_size15 = sizeof(*exp_vertices15);
8768 /* Test 16. Convert FLOAT2 to USHORT2N. */
8769 const struct vertex_ptc vertices16[] =
8771 {{ 0.0f, 3.0f, 0.f}, {1.0f, 2.0f}},
8772 {{ 2.0f, 3.0f, 0.f}, {0.4f, 0.5f}},
8773 {{ 0.0f, 0.0f, 0.f}, {0.6f, -1.0f}},
8775 {{ 3.0f, 3.0f, 0.f}, {-0.4f, -0.5f}},
8776 {{ 3.0f, 0.0f, 0.f}, {-0.9f, 0.99998f}},
8777 {{ 1.0f, 0.0f, 0.f}, {USHRT_MAX, 0.0f}},
8779 const UINT num_vertices16 = ARRAY_SIZE(vertices16);
8780 const UINT num_faces16 = ARRAY_SIZE(vertices16) / VERTS_PER_FACE;
8781 const UINT vertex_size16 = sizeof(*vertices16);
8782 const struct vertex_ptc_ushort2n exp_vertices16[] =
8784 {{ 0.0f, 3.0f, 0.f}, {USHRT_MAX, USHRT_MAX}},
8785 {{ 2.0f, 3.0f, 0.f}, {26214, 32768}},
8786 {{ 0.0f, 0.0f, 0.f}, {39321, 0}},
8788 {{ 3.0f, 3.0f, 0.f}, {0, 0}},
8789 {{ 3.0f, 0.0f, 0.f}, {0, USHRT_MAX - 1}},
8790 {{ 1.0f, 0.0f, 0.f}, {USHRT_MAX, 0}},
8792 const UINT exp_vertex_size16 = sizeof(*exp_vertices16);
8793 /* Test 17. Convert FLOAT2 to USHORT4N. */
8794 const struct vertex_ptc vertices17[] =
8796 {{ 0.0f, 3.0f, 0.f}, {1.0f, 2.0f}},
8797 {{ 2.0f, 3.0f, 0.f}, {0.4f, 0.5f}},
8798 {{ 0.0f, 0.0f, 0.f}, {0.6f, -1.0f}},
8800 {{ 3.0f, 3.0f, 0.f}, {-0.4f, -0.5f}},
8801 {{ 3.0f, 0.0f, 0.f}, {-0.9f, 0.99998f}},
8802 {{ 1.0f, 0.0f, 0.f}, {USHRT_MAX, 0.0f}},
8804 const UINT num_vertices17 = ARRAY_SIZE(vertices17);
8805 const UINT num_faces17 = ARRAY_SIZE(vertices17) / VERTS_PER_FACE;
8806 const UINT vertex_size17 = sizeof(*vertices17);
8807 const struct vertex_ptc_ushort4n exp_vertices17[] =
8809 {{ 0.0f, 3.0f, 0.f}, {USHRT_MAX, USHRT_MAX, 0, USHRT_MAX}},
8810 {{ 2.0f, 3.0f, 0.f}, {26214, 32768, 0, USHRT_MAX}},
8811 {{ 0.0f, 0.0f, 0.f}, {39321, 0, 0, USHRT_MAX}},
8813 {{ 3.0f, 3.0f, 0.f}, {0, 0, 0, USHRT_MAX}},
8814 {{ 3.0f, 0.0f, 0.f}, {0, USHRT_MAX - 1, 0, USHRT_MAX}},
8815 {{ 1.0f, 0.0f, 0.f}, {USHRT_MAX, 0, 0, USHRT_MAX}},
8817 const UINT exp_vertex_size17 = sizeof(*exp_vertices17);
8818 /* Test 18. Test that the method field is compared by converting a FLOAT2 to
8819 * FLOAT16_2. where the method field has been change from
8820 * D3DDECLMETHOD_DEFAULT to D3DDECLMETHOD_PARTIALU. */
8821 const struct vertex_ptc vertices18[] =
8823 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8824 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8825 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
8827 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8828 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
8829 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
8831 const UINT num_vertices18 = ARRAY_SIZE(vertices18);
8832 const UINT num_faces18 = ARRAY_SIZE(vertices18) / VERTS_PER_FACE;
8833 const UINT vertex_size18 = sizeof(*vertices18);
8834 const struct vertex_ptc_float16_2 exp_vertices18[] =
8836 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
8837 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */
8838 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */
8840 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd}}, /* {0.2f, 0.3f} */
8841 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
8842 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */
8844 const UINT exp_vertex_size18 = sizeof(*exp_vertices18);
8845 /* Test 19. Test that data is lost if usage index changes, e.g. TEXCOORD0
8846 * TEXCOORD1. */
8847 const struct vertex_pntc vertices19[] =
8849 {{ 0.0f, 3.0f, 0.f}, up, { 1.0f, 1.0f}},
8850 {{ 2.0f, 3.0f, 0.f}, up, { 0.5f, 0.7f}},
8851 {{ 0.0f, 0.0f, 0.f}, up, {-0.2f, -0.3f}},
8853 {{ 3.0f, 3.0f, 0.f}, up, { 0.2f, 0.3f}},
8854 {{ 3.0f, 0.0f, 0.f}, up, { 1.0f, 1.0f}},
8855 {{ 1.0f, 0.0f, 0.f}, up, { 0.1f, 0.2f}},
8857 const UINT num_vertices19 = ARRAY_SIZE(vertices19);
8858 const UINT num_faces19 = ARRAY_SIZE(vertices19) / VERTS_PER_FACE;
8859 const UINT vertex_size19 = sizeof(*vertices19);
8860 const struct vertex_pntc exp_vertices19[] =
8862 {{ 0.0f, 3.0f, 0.f}, up, zero_vec2},
8863 {{ 2.0f, 3.0f, 0.f}, up, zero_vec2},
8864 {{ 0.0f, 0.0f, 0.f}, up, zero_vec2},
8866 {{ 3.0f, 3.0f, 0.f}, up, zero_vec2},
8867 {{ 3.0f, 0.0f, 0.f}, up, zero_vec2},
8868 {{ 1.0f, 0.0f, 0.f}, up, zero_vec2},
8870 const UINT exp_vertex_size19 = sizeof(*exp_vertices19);
8871 /* Test 20. Another test that data is lost if usage index changes, e.g.
8872 * TEXCOORD1 to TEXCOORD0. */
8873 const struct vertex_pntc vertices20[] =
8875 {{ 0.0f, 3.0f, 0.f}, up, { 1.0f, 1.0f}},
8876 {{ 2.0f, 3.0f, 0.f}, up, { 0.5f, 0.7f}},
8877 {{ 0.0f, 0.0f, 0.f}, up, {-0.2f, -0.3f}},
8879 {{ 3.0f, 3.0f, 0.f}, up, { 0.2f, 0.3f}},
8880 {{ 3.0f, 0.0f, 0.f}, up, { 1.0f, 1.0f}},
8881 {{ 1.0f, 0.0f, 0.f}, up, { 0.1f, 0.2f}},
8883 const UINT num_vertices20 = ARRAY_SIZE(vertices20);
8884 const UINT num_faces20 = ARRAY_SIZE(vertices20) / VERTS_PER_FACE;
8885 const UINT vertex_size20 = sizeof(*vertices20);
8886 const struct vertex_pntc exp_vertices20[] =
8888 {{ 0.0f, 3.0f, 0.f}, up, zero_vec2},
8889 {{ 2.0f, 3.0f, 0.f}, up, zero_vec2},
8890 {{ 0.0f, 0.0f, 0.f}, up, zero_vec2},
8892 {{ 3.0f, 3.0f, 0.f}, up, zero_vec2},
8893 {{ 3.0f, 0.0f, 0.f}, up, zero_vec2},
8894 {{ 1.0f, 0.0f, 0.f}, up, zero_vec2},
8896 const UINT exp_vertex_size20 = sizeof(*exp_vertices20);
8897 /* Test 21. Convert FLOAT1 to FLOAT2. */
8898 const struct vertex_ptc_float1 vertices21[] =
8900 {{ 0.0f, 3.0f, 0.f}, 1.0f},
8901 {{ 2.0f, 3.0f, 0.f}, 0.5f},
8902 {{ 0.0f, 0.0f, 0.f}, -0.2f},
8904 {{ 3.0f, 3.0f, 0.f}, 0.2f},
8905 {{ 3.0f, 0.0f, 0.f}, 1.0f},
8906 {{ 1.0f, 0.0f, 0.f}, 0.1f},
8908 const UINT num_vertices21 = ARRAY_SIZE(vertices21);
8909 const UINT num_faces21 = ARRAY_SIZE(vertices21) / VERTS_PER_FACE;
8910 const UINT vertex_size21 = sizeof(*vertices21);
8911 const struct vertex_ptc exp_vertices21[] =
8913 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 0.0f}},
8914 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.0f}},
8915 {{ 0.0f, 0.0f, 0.f}, {-0.2f, 0.0f}},
8917 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.0f}},
8918 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 0.0f}},
8919 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.0f}},
8921 const UINT exp_vertex_size21 = sizeof(*exp_vertices21);
8922 /* Test 22. Convert FLOAT1 to FLOAT3. */
8923 const struct vertex_ptc_float1 vertices22[] =
8925 {{ 0.0f, 3.0f, 0.f}, 1.0f},
8926 {{ 2.0f, 3.0f, 0.f}, 0.5f},
8927 {{ 0.0f, 0.0f, 0.f}, -0.2f},
8929 {{ 3.0f, 3.0f, 0.f}, 0.2f},
8930 {{ 3.0f, 0.0f, 0.f}, 1.0f},
8931 {{ 1.0f, 0.0f, 0.f}, 0.1f},
8933 const UINT num_vertices22 = ARRAY_SIZE(vertices22);
8934 const UINT num_faces22 = ARRAY_SIZE(vertices22) / VERTS_PER_FACE;
8935 const UINT vertex_size22 = sizeof(*vertices22);
8936 const struct vertex_ptc_float3 exp_vertices22[] =
8938 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 0.0f, 0.0f}},
8939 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.0f, 0.0f}},
8940 {{ 0.0f, 0.0f, 0.f}, {-0.2f, 0.0f, 0.0f}},
8942 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.0f, 0.0f}},
8943 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 0.0f, 0.0f}},
8944 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.0f, 0.0f}},
8946 const UINT exp_vertex_size22 = sizeof(*exp_vertices22);
8947 /* Test 23. Convert FLOAT1 to FLOAT4. */
8948 const struct vertex_ptc_float1 vertices23[] =
8950 {{ 0.0f, 3.0f, 0.f}, 1.0f},
8951 {{ 2.0f, 3.0f, 0.f}, 0.5f},
8952 {{ 0.0f, 0.0f, 0.f}, -0.2f},
8954 {{ 3.0f, 3.0f, 0.f}, 0.2f},
8955 {{ 3.0f, 0.0f, 0.f}, 1.0f},
8956 {{ 1.0f, 0.0f, 0.f}, 0.1f},
8958 const UINT num_vertices23 = ARRAY_SIZE(vertices23);
8959 const UINT num_faces23 = ARRAY_SIZE(vertices23) / VERTS_PER_FACE;
8960 const UINT vertex_size23 = sizeof(*vertices23);
8961 const struct vertex_ptc_float4 exp_vertices23[] =
8963 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 0.0f, 0.0f, 1.0f}},
8964 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.0f, 0.0f, 1.0f}},
8965 {{ 0.0f, 0.0f, 0.f}, {-0.2f, 0.0f, 0.0f, 1.0f}},
8967 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.0f, 0.0f, 1.0f}},
8968 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 0.0f, 0.0f, 1.0f}},
8969 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.0f, 0.0f, 1.0f}},
8971 const UINT exp_vertex_size23 = sizeof(*exp_vertices23);
8972 /* Test 24. Convert FLOAT1 to D3DCOLOR. */
8973 const struct vertex_ptc_float1 vertices24[] =
8975 {{ 0.0f, 3.0f, 0.f}, 1.0f},
8976 {{ 2.0f, 3.0f, 0.f}, 0.5f},
8977 {{ 0.0f, 0.0f, 0.f}, -0.2f},
8979 {{ 3.0f, 3.0f, 0.f}, 0.2f},
8980 {{ 3.0f, 0.0f, 0.f}, 1.0f},
8981 {{ 1.0f, 0.0f, 0.f}, 0.11f},
8983 const UINT num_vertices24 = ARRAY_SIZE(vertices24);
8984 const UINT num_faces24 = ARRAY_SIZE(vertices24) / VERTS_PER_FACE;
8985 const UINT vertex_size24 = sizeof(*vertices24);
8986 const struct vertex_ptc_d3dcolor exp_vertices24[] =
8988 {{ 0.0f, 3.0f, 0.f}, {0, 0, 255, 255}},
8989 {{ 2.0f, 3.0f, 0.f}, {0, 0, 128, 255}},
8990 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 255}},
8992 {{ 3.0f, 3.0f, 0.f}, {0, 0, 51, 255}},
8993 {{ 3.0f, 0.0f, 0.f}, {0, 0, 255, 255}},
8994 {{ 1.0f, 0.0f, 0.f}, {0, 0, 28, 255}},
8996 const UINT exp_vertex_size24 = sizeof(*exp_vertices24);
8997 /* Test 25. Convert FLOAT1 to ubyte4. */
8998 const struct vertex_ptc_float1 vertices25[] =
9000 {{ 0.0f, 3.0f, 0.f}, 0.0f},
9001 {{ 2.0f, 3.0f, 0.f}, 1.4f},
9002 {{ 0.0f, 0.0f, 0.f}, 1.5f},
9004 {{ 3.0f, 3.0f, 0.f}, 255.0f},
9005 {{ 3.0f, 0.0f, 0.f}, 256.0f},
9006 {{ 1.0f, 0.0f, 0.f}, -1.0f},
9008 const UINT num_vertices25 = ARRAY_SIZE(vertices25);
9009 const UINT num_faces25 = ARRAY_SIZE(vertices25) / VERTS_PER_FACE;
9010 const UINT vertex_size25 = sizeof(*vertices25);
9011 const struct vertex_ptc_ubyte4 exp_vertices25[] =
9013 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 1}},
9014 {{ 2.0f, 3.0f, 0.f}, {1, 0, 0, 1}},
9015 {{ 0.0f, 0.0f, 0.f}, {2, 0, 0, 1}},
9017 {{ 3.0f, 3.0f, 0.f}, {255, 0, 0, 1}},
9018 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 1}},
9019 {{ 1.0f, 0.0f, 0.f}, {0, 0, 0, 1}},
9021 const UINT exp_vertex_size25 = sizeof(*exp_vertices25);
9022 /* Test 26. Convert FLOAT4 to D3DCOLOR. */
9023 const struct vertex_ptc_float4 vertices26[] =
9025 {{ 0.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.4f, 0.5f}},
9026 {{ 2.0f, 3.0f, 0.f}, {-0.4f, -0.5f, -1.0f, -2.0f}},
9027 {{ 0.0f, 0.0f, 0.f}, {254.0f, 255.0f, 256.0f, 257.0f}},
9029 {{ 3.0f, 3.0f, 0.f}, {0.1f, 0.2f, 0.3f, 0.4f}},
9030 {{ 3.0f, 0.0f, 0.f}, {0.5f, 0.6f, 0.7f, 0.8f}},
9031 {{ 1.0f, 0.0f, 0.f}, {0.9f, 0.99f, 0.995f, 0.999f}},
9033 const UINT num_vertices26 = ARRAY_SIZE(vertices26);
9034 const UINT num_faces26 = ARRAY_SIZE(vertices26) / VERTS_PER_FACE;
9035 const UINT vertex_size26 = sizeof(*vertices26);
9036 const struct vertex_ptc_d3dcolor exp_vertices26[] =
9038 {{ 0.0f, 3.0f, 0.f}, {102, 255, 0, 128}},
9039 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9040 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
9042 {{ 3.0f, 3.0f, 0.f}, {77, 51, 26, 102}},
9043 {{ 3.0f, 0.0f, 0.f}, {179, 153, 128, 204}},
9044 {{ 1.0f, 0.0f, 0.f}, {254, 252, 230, 255}},
9046 const UINT exp_vertex_size26 = sizeof(*exp_vertices26);
9047 /* Test 27. Convert D3DCOLOR to FLOAT4. */
9048 const struct vertex_ptc_d3dcolor vertices27[] =
9050 {{ 0.0f, 3.0f, 0.f}, {102, 255, 0, 128}},
9051 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9052 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
9054 {{ 3.0f, 3.0f, 0.f}, {77, 51, 26, 102}},
9055 {{ 3.0f, 0.0f, 0.f}, {179, 153, 128, 204}},
9056 {{ 1.0f, 0.0f, 0.f}, {254, 252, 230, 255}},
9058 const UINT num_vertices27 = ARRAY_SIZE(vertices27);
9059 const UINT num_faces27 = ARRAY_SIZE(vertices27) / VERTS_PER_FACE;
9060 const UINT vertex_size27 = sizeof(*vertices27);
9061 const struct vertex_ptc_float4 exp_vertices27[] =
9063 {{ 0.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.4f, 0.501961f}},
9064 {{ 2.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9065 {{ 0.0f, 0.0f, 0.f}, {1.0f, 1.0f, 1.0f, 1.0f}},
9067 {{ 3.0f, 3.0f, 0.f}, {0.101961f, 0.2f, 0.301961f, 0.4f}},
9068 {{ 3.0f, 0.0f, 0.f}, {0.501961f, 0.6f, 0.701961f, 0.8f}},
9069 {{ 1.0f, 0.0f, 0.f}, {0.901961f, 0.988235f, 0.996078f, 1.0f}},
9071 const UINT exp_vertex_size27 = sizeof(*exp_vertices27);
9072 /* Test 28. Convert UBYTE4 to FLOAT4. */
9073 const struct vertex_ptc_ubyte4 vertices28[] =
9075 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9076 {{ 2.0f, 3.0f, 0.f}, {1, 1, 1, 1}},
9077 {{ 0.0f, 0.0f, 0.f}, {1, 0, 1, 0}},
9079 {{ 3.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
9080 {{ 3.0f, 0.0f, 0.f}, {10, 20, 30, 40}},
9081 {{ 1.0f, 0.0f, 0.f}, {50, 60, 127, 255}},
9083 const UINT num_vertices28 = ARRAY_SIZE(vertices28);
9084 const UINT num_faces28 = ARRAY_SIZE(vertices28) / VERTS_PER_FACE;
9085 const UINT vertex_size28 = sizeof(*vertices28);
9086 const struct vertex_ptc_float4 exp_vertices28[] =
9088 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9089 {{ 2.0f, 3.0f, 0.f}, {1.0f, 1.0f, 1.0f, 1.0f}},
9090 {{ 0.0f, 0.0f, 0.f}, {1.0f, 0.0f, 1.0f, 0.0f}},
9092 {{ 3.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.0f, 1.0f}},
9093 {{ 3.0f, 0.0f, 0.f}, {10.0f, 20.0f, 30.0f, 40.0f}},
9094 {{ 1.0f, 0.0f, 0.f}, {50.0f, 60.0f, 127.0f, 255.0f}},
9096 const UINT exp_vertex_size28 = sizeof(*exp_vertices28);
9097 /* Test 29. Convert SHORT2 to FLOAT4. */
9098 const struct vertex_ptc_short2 vertices29[] =
9100 {{ 0.0f, 3.0f, 0.f}, {0, 0}},
9101 {{ 2.0f, 3.0f, 0.f}, {0, 1}},
9102 {{ 0.0f, 0.0f, 0.f}, {1, 0}},
9104 {{ 3.0f, 3.0f, 0.f}, {1, 1}},
9105 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MAX}},
9106 {{ 1.0f, 0.0f, 0.f}, {-42, 42}},
9108 const UINT num_vertices29 = ARRAY_SIZE(vertices29);
9109 const UINT num_faces29 = ARRAY_SIZE(vertices29) / VERTS_PER_FACE;
9110 const UINT vertex_size29 = sizeof(*vertices29);
9111 const struct vertex_ptc_float4 exp_vertices29[] =
9113 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 1.0f}},
9114 {{ 2.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.0f, 1.0f }},
9115 {{ 0.0f, 0.0f, 0.f}, {1.0f, 0.0f, 0.0f, 1.0f}},
9117 {{ 3.0f, 3.0f, 0.f}, {1.0f, 1.0f, 0.0f, 1.0f}},
9118 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MAX, 0.0f, 1.0f}},
9119 {{ 1.0f, 0.0f, 0.f}, {-42.0f, 42.0f, 0.0f, 1.0f}},
9121 const UINT exp_vertex_size29 = sizeof(*exp_vertices29);
9122 /* Test 29. Convert SHORT4 to FLOAT4. */
9123 const struct vertex_ptc_short4 vertices30[] =
9125 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9126 {{ 2.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
9127 {{ 0.0f, 0.0f, 0.f}, {1, 0, 1, 0}},
9129 {{ 3.0f, 3.0f, 0.f}, {1, 1, 1, 1}},
9130 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MAX, 1, 0}},
9131 {{ 1.0f, 0.0f, 0.f}, {-42, 42, SHRT_MAX, SHRT_MIN}},
9133 const UINT num_vertices30 = ARRAY_SIZE(vertices30);
9134 const UINT num_faces30 = ARRAY_SIZE(vertices30) / VERTS_PER_FACE;
9135 const UINT vertex_size30 = sizeof(*vertices30);
9136 const struct vertex_ptc_float4 exp_vertices30[] =
9138 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9139 {{ 2.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.0f, 1.0f }},
9140 {{ 0.0f, 0.0f, 0.f}, {1.0f, 0.0f, 1.0f, 0.0f}},
9142 {{ 3.0f, 3.0f, 0.f}, {1.0f, 1.0f, 1.0f, 1.0f}},
9143 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MAX, 1.0f, 0.0f}},
9144 {{ 1.0f, 0.0f, 0.f}, {-42.0f, 42.0f, SHRT_MAX, SHRT_MIN}},
9146 const UINT exp_vertex_size30 = sizeof(*exp_vertices30);
9147 /* Test 31. Convert UBYTE4N to FLOAT4. */
9148 const struct vertex_ptc_ubyte4n vertices31[] =
9150 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9151 {{ 2.0f, 3.0f, 0.f}, {1, 1, 1, 1}},
9152 {{ 0.0f, 0.0f, 0.f}, {1, 0, 1, 0}},
9154 {{ 3.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
9155 {{ 3.0f, 0.0f, 0.f}, {10, 20, 30, 40}},
9156 {{ 1.0f, 0.0f, 0.f}, {50, 60, 70, UCHAR_MAX}},
9158 const UINT num_vertices31 = ARRAY_SIZE(vertices31);
9159 const UINT num_faces31 = ARRAY_SIZE(vertices31) / VERTS_PER_FACE;
9160 const UINT vertex_size31 = sizeof(*vertices31);
9161 const struct vertex_ptc_float4 exp_vertices31[] =
9163 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9164 {{ 2.0f, 3.0f, 0.f}, {(FLOAT)1/UCHAR_MAX, (FLOAT)1/UCHAR_MAX, (FLOAT)1/UCHAR_MAX, (FLOAT)1/UCHAR_MAX}},
9165 {{ 0.0f, 0.0f, 0.f}, {(FLOAT)1/UCHAR_MAX, 0.0f, (FLOAT)1/UCHAR_MAX, 0.0f}},
9167 {{ 3.0f, 3.0f, 0.f}, {0.0f, (FLOAT)1/UCHAR_MAX, 0.0f, (FLOAT)1/UCHAR_MAX}},
9168 {{ 3.0f, 0.0f, 0.f}, {(FLOAT)10/UCHAR_MAX, (FLOAT)20/UCHAR_MAX, (FLOAT)30/UCHAR_MAX, (FLOAT)40/UCHAR_MAX}},
9169 {{ 1.0f, 0.0f, 0.f}, {(FLOAT)50/UCHAR_MAX, (FLOAT)60/UCHAR_MAX, (FLOAT)70/UCHAR_MAX, 1.0f}},
9171 const UINT exp_vertex_size31 = sizeof(*exp_vertices31);
9172 /* Test 32. Convert SHORT2N to FLOAT4. */
9173 const struct vertex_ptc_short2 vertices32[] =
9175 {{ 0.0f, 3.0f, 0.f}, {0, 0}},
9176 {{ 2.0f, 3.0f, 0.f}, {0, 1}},
9177 {{ 0.0f, 0.0f, 0.f}, {1, 0}},
9179 {{ 3.0f, 3.0f, 0.f}, {1, 1}},
9180 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN + 1, SHRT_MAX}},
9181 {{ 1.0f, 0.0f, 0.f}, {-42, 42}},
9183 const UINT num_vertices32 = ARRAY_SIZE(vertices32);
9184 const UINT num_faces32 = ARRAY_SIZE(vertices32) / VERTS_PER_FACE;
9185 const UINT vertex_size32 = sizeof(*vertices32);
9186 const struct vertex_ptc_float4 exp_vertices32[] =
9188 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 1.0f}},
9189 {{ 2.0f, 3.0f, 0.f}, {0.0f, 1.0f/SHRT_MAX, 0.0f, 1.0f}},
9190 {{ 0.0f, 0.0f, 0.f}, {1.0f/SHRT_MAX, 0.0f, 0.0f, 1.0f}},
9192 {{ 3.0f, 3.0f, 0.f}, {1.0f/SHRT_MAX, 1.0f/SHRT_MAX, 0.0f, 1.0f}},
9193 {{ 3.0f, 0.0f, 0.f}, {-1.0f, 1.0f, 0.0f, 1.0f}},
9194 {{ 1.0f, 0.0f, 0.f}, {-42.0f/SHRT_MAX, 42.0f/SHRT_MAX, 0.0f, 1.0f}},
9196 const UINT exp_vertex_size32 = sizeof(*exp_vertices32);
9197 /* Test 33. Convert SHORT4N to FLOAT4. */
9198 const struct vertex_ptc_short4 vertices33[] =
9200 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9201 {{ 2.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
9202 {{ 0.0f, 0.0f, 0.f}, {1, 0, 1, 0}},
9204 {{ 3.0f, 3.0f, 0.f}, {1, 1, 1, 1}},
9205 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN + 1, SHRT_MAX, SHRT_MIN + 1, SHRT_MAX}},
9206 {{ 1.0f, 0.0f, 0.f}, {-42, 42, 1, 1}},
9208 const UINT num_vertices33 = ARRAY_SIZE(vertices33);
9209 const UINT num_faces33 = ARRAY_SIZE(vertices33) / VERTS_PER_FACE;
9210 const UINT vertex_size33 = sizeof(*vertices33);
9211 const struct vertex_ptc_float4 exp_vertices33[] =
9213 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9214 {{ 2.0f, 3.0f, 0.f}, {0.0f, 1.0f/SHRT_MAX, 0.0f, 1.0f/SHRT_MAX}},
9215 {{ 0.0f, 0.0f, 0.f}, {1.0f/SHRT_MAX, 0.0f, 1.0f/SHRT_MAX, 0.0f}},
9217 {{ 3.0f, 3.0f, 0.f}, {1.0f/SHRT_MAX, 1.0f/SHRT_MAX, 1.0f/SHRT_MAX, 1.0f/SHRT_MAX}},
9218 {{ 3.0f, 0.0f, 0.f}, {-1.0f, 1.0f, -1.0f, 1.0f}},
9219 {{ 1.0f, 0.0f, 0.f}, {-42.0f/SHRT_MAX, 42.0f/SHRT_MAX, 1.0f/SHRT_MAX, 1.0f/SHRT_MAX}},
9221 const UINT exp_vertex_size33 = sizeof(*exp_vertices33);
9222 /* Test 34. Convert FLOAT16_2 to FLOAT4. */
9223 const struct vertex_ptc_float16_2 vertices34[] =
9225 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
9226 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */
9227 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */
9229 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd}}, /* {0.2f, 0.3f} */
9230 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
9231 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */
9233 const UINT num_vertices34 = ARRAY_SIZE(vertices34);
9234 const UINT num_faces34 = ARRAY_SIZE(vertices34) / VERTS_PER_FACE;
9235 const UINT vertex_size34 = sizeof(*vertices34);
9236 const struct vertex_ptc_float4 exp_vertices34[] =
9238 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f, 0.0f, 1.0f}},
9239 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.700195f, 0.0f, 1.0f}},
9240 {{ 0.0f, 0.0f, 0.f}, {-0.199951f, -0.300049f, 0.0f, 1.0f}},
9242 {{ 3.0f, 3.0f, 0.f}, {0.199951f, 0.300049f, 0.0f, 1.0f}},
9243 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f, 0.0f, 1.0f}},
9244 {{ 1.0f, 0.0f, 0.f}, {0.099976f, 0.199951f, 0.0f, 1.0f}},
9246 const UINT exp_vertex_size34 = sizeof(*exp_vertices34);
9247 /* Test 35. Convert FLOAT16_4 to FLOAT4. */
9248 const struct vertex_ptc_float16_4 vertices35[] =
9250 {{ 0.0f, 3.0f, 0.f}, {0x0000, 0x0000, 0x0000, 0x0000}},
9251 {{ 2.0f, 3.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}},
9252 {{ 0.0f, 0.0f, 0.f}, {0x3c00, 0x0000, 0x3c00, 0x0000}},
9254 {{ 3.0f, 3.0f, 0.f}, {0x0000, 0x3c00, 0x0000, 0x3c00}},
9255 {{ 3.0f, 0.0f, 0.f}, {0x3800, 0x399a, 0xb266, 0xb4cd}},
9256 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266, 0x2e66, 0x3266}},
9258 const UINT num_vertices35 = ARRAY_SIZE(vertices35);
9259 const UINT num_faces35 = ARRAY_SIZE(vertices35) / VERTS_PER_FACE;
9260 const UINT vertex_size35 = sizeof(*vertices35);
9261 const struct vertex_ptc_float4 exp_vertices35[] =
9263 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9264 {{ 2.0f, 3.0f, 0.f}, {1.0f, 1.0f, 1.0f, 1.0f}},
9265 {{ 0.0f, 0.0f, 0.f}, {1.0f, 0.0f, 1.0f, 0.0f}},
9267 {{ 3.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.0f, 1.0f}},
9268 {{ 3.0f, 0.0f, 0.f}, {0.5f, 0.700195f, -0.199951f, -0.300049f}},
9269 {{ 1.0f, 0.0f, 0.f}, {0.099976f, 0.199951f, 0.099976f, 0.199951f}},
9271 const UINT exp_vertex_size35 = sizeof(*exp_vertices35);
9272 /* Test 36. Check that vertex buffer sharing is ok. */
9273 const struct vertex_pn vertices36[] =
9275 {{ 0.0f, 3.0f, 0.f}, up},
9276 {{ 2.0f, 3.0f, 0.f}, up},
9277 {{ 0.0f, 0.0f, 0.f}, up},
9279 const UINT num_vertices36 = ARRAY_SIZE(vertices36);
9280 const UINT num_faces36 = ARRAY_SIZE(vertices36) / VERTS_PER_FACE;
9281 const UINT vertex_size36 = sizeof(*vertices36);
9282 const DWORD clone_options36 = options | D3DXMESH_VB_SHARE;
9283 /* Common mesh data */
9284 ID3DXMesh *mesh = NULL;
9285 ID3DXMesh *mesh_clone = NULL;
9286 struct
9288 const BYTE *vertices;
9289 const DWORD *indices;
9290 const DWORD *attributes;
9291 const UINT num_vertices;
9292 const UINT num_faces;
9293 const UINT vertex_size;
9294 const DWORD create_options;
9295 const DWORD clone_options;
9296 D3DVERTEXELEMENT9 *declaration;
9297 D3DVERTEXELEMENT9 *new_declaration;
9298 const BYTE *exp_vertices;
9299 const UINT exp_vertex_size;
9301 tc[] =
9304 (BYTE*)vertices0,
9305 NULL,
9306 NULL,
9307 num_vertices0,
9308 num_faces0,
9309 vertex_size0,
9310 options,
9311 options,
9312 declaration_pn,
9313 declaration_pn,
9314 (BYTE*)vertices0,
9315 vertex_size0
9318 (BYTE*)vertices0,
9319 NULL,
9320 NULL,
9321 num_vertices0,
9322 num_faces0,
9323 vertex_size0,
9324 options_16bit,
9325 options_16bit,
9326 declaration_pn,
9327 declaration_pn,
9328 (BYTE*)vertices0,
9329 vertex_size0
9332 (BYTE*)vertices0,
9333 NULL,
9334 NULL,
9335 num_vertices0,
9336 num_faces0,
9337 vertex_size0,
9338 options,
9339 options,
9340 declaration_pn,
9341 declaration_pntc,
9342 (BYTE*)exp_vertices2,
9343 exp_vertex_size2
9346 (BYTE*)vertices0,
9347 NULL,
9348 NULL,
9349 num_vertices0,
9350 num_faces0,
9351 vertex_size0,
9352 options,
9353 options,
9354 declaration_pn,
9355 declaration_ptcn,
9356 (BYTE*)exp_vertices3,
9357 exp_vertex_size3
9360 (BYTE*)vertices4,
9361 NULL,
9362 NULL,
9363 num_vertices4,
9364 num_faces4,
9365 vertex_size4,
9366 options,
9367 options,
9368 declaration_ptc,
9369 declaration_ptc_float16_2,
9370 (BYTE*)exp_vertices4,
9371 exp_vertex_size4
9374 (BYTE*)vertices5,
9375 NULL,
9376 NULL,
9377 num_vertices5,
9378 num_faces5,
9379 vertex_size5,
9380 options,
9381 options,
9382 declaration_ptc,
9383 declaration_ptc_float16_4,
9384 (BYTE*)exp_vertices5,
9385 exp_vertex_size5
9388 (BYTE*)vertices6,
9389 NULL,
9390 NULL,
9391 num_vertices6,
9392 num_faces6,
9393 vertex_size6,
9394 options,
9395 options,
9396 declaration_ptc,
9397 declaration_ptc_float1,
9398 (BYTE*)exp_vertices6,
9399 exp_vertex_size6
9402 (BYTE*)vertices7,
9403 NULL,
9404 NULL,
9405 num_vertices7,
9406 num_faces7,
9407 vertex_size7,
9408 options,
9409 options,
9410 declaration_ptc,
9411 declaration_ptc_float3,
9412 (BYTE*)exp_vertices7,
9413 exp_vertex_size7
9416 (BYTE*)vertices8,
9417 NULL,
9418 NULL,
9419 num_vertices8,
9420 num_faces8,
9421 vertex_size8,
9422 options,
9423 options,
9424 declaration_ptc,
9425 declaration_ptc_float4,
9426 (BYTE*)exp_vertices8,
9427 exp_vertex_size8
9430 (BYTE*)vertices9,
9431 NULL,
9432 NULL,
9433 num_vertices9,
9434 num_faces9,
9435 vertex_size9,
9436 options,
9437 options,
9438 declaration_ptc,
9439 declaration_ptc_d3dcolor,
9440 (BYTE*)exp_vertices9,
9441 exp_vertex_size9
9444 (BYTE*)vertices10,
9445 NULL,
9446 NULL,
9447 num_vertices10,
9448 num_faces10,
9449 vertex_size10,
9450 options,
9451 options,
9452 declaration_ptc,
9453 declaration_ptc_ubyte4,
9454 (BYTE*)exp_vertices10,
9455 exp_vertex_size10
9458 (BYTE*)vertices11,
9459 NULL,
9460 NULL,
9461 num_vertices11,
9462 num_faces11,
9463 vertex_size11,
9464 options,
9465 options,
9466 declaration_ptc,
9467 declaration_ptc_short2,
9468 (BYTE*)exp_vertices11,
9469 exp_vertex_size11
9472 (BYTE*)vertices12,
9473 NULL,
9474 NULL,
9475 num_vertices12,
9476 num_faces12,
9477 vertex_size12,
9478 options,
9479 options,
9480 declaration_ptc,
9481 declaration_ptc_short4,
9482 (BYTE*)exp_vertices12,
9483 exp_vertex_size12
9486 (BYTE*)vertices13,
9487 NULL,
9488 NULL,
9489 num_vertices13,
9490 num_faces13,
9491 vertex_size13,
9492 options,
9493 options,
9494 declaration_ptc,
9495 declaration_ptc_ubyte4n,
9496 (BYTE*)exp_vertices13,
9497 exp_vertex_size13
9500 (BYTE*)vertices14,
9501 NULL,
9502 NULL,
9503 num_vertices14,
9504 num_faces14,
9505 vertex_size14,
9506 options,
9507 options,
9508 declaration_ptc,
9509 declaration_ptc_short2n,
9510 (BYTE*)exp_vertices14,
9511 exp_vertex_size14
9514 (BYTE*)vertices15,
9515 NULL,
9516 NULL,
9517 num_vertices15,
9518 num_faces15,
9519 vertex_size15,
9520 options,
9521 options,
9522 declaration_ptc,
9523 declaration_ptc_short4n,
9524 (BYTE*)exp_vertices15,
9525 exp_vertex_size15
9528 (BYTE*)vertices16,
9529 NULL,
9530 NULL,
9531 num_vertices16,
9532 num_faces16,
9533 vertex_size16,
9534 options,
9535 options,
9536 declaration_ptc,
9537 declaration_ptc_ushort2n,
9538 (BYTE*)exp_vertices16,
9539 exp_vertex_size16
9542 (BYTE*)vertices17,
9543 NULL,
9544 NULL,
9545 num_vertices17,
9546 num_faces17,
9547 vertex_size17,
9548 options,
9549 options,
9550 declaration_ptc,
9551 declaration_ptc_ushort4n,
9552 (BYTE*)exp_vertices17,
9553 exp_vertex_size17
9556 (BYTE*)vertices18,
9557 NULL,
9558 NULL,
9559 num_vertices18,
9560 num_faces18,
9561 vertex_size18,
9562 options,
9563 options,
9564 declaration_ptc,
9565 declaration_ptc_float16_2_partialu,
9566 (BYTE*)exp_vertices18,
9567 exp_vertex_size18
9570 (BYTE*)vertices19,
9571 NULL,
9572 NULL,
9573 num_vertices19,
9574 num_faces19,
9575 vertex_size19,
9576 options,
9577 options,
9578 declaration_pntc,
9579 declaration_pntc1,
9580 (BYTE*)exp_vertices19,
9581 exp_vertex_size19
9584 (BYTE*)vertices20,
9585 NULL,
9586 NULL,
9587 num_vertices20,
9588 num_faces20,
9589 vertex_size20,
9590 options,
9591 options,
9592 declaration_pntc1,
9593 declaration_pntc,
9594 (BYTE*)exp_vertices20,
9595 exp_vertex_size20
9598 (BYTE*)vertices21,
9599 NULL,
9600 NULL,
9601 num_vertices21,
9602 num_faces21,
9603 vertex_size21,
9604 options,
9605 options,
9606 declaration_ptc_float1,
9607 declaration_ptc,
9608 (BYTE*)exp_vertices21,
9609 exp_vertex_size21
9612 (BYTE*)vertices22,
9613 NULL,
9614 NULL,
9615 num_vertices22,
9616 num_faces22,
9617 vertex_size22,
9618 options,
9619 options,
9620 declaration_ptc_float1,
9621 declaration_ptc_float3,
9622 (BYTE*)exp_vertices22,
9623 exp_vertex_size22
9626 (BYTE*)vertices23,
9627 NULL,
9628 NULL,
9629 num_vertices23,
9630 num_faces23,
9631 vertex_size23,
9632 options,
9633 options,
9634 declaration_ptc_float1,
9635 declaration_ptc_float4,
9636 (BYTE*)exp_vertices23,
9637 exp_vertex_size23
9640 (BYTE*)vertices24,
9641 NULL,
9642 NULL,
9643 num_vertices24,
9644 num_faces24,
9645 vertex_size24,
9646 options,
9647 options,
9648 declaration_ptc_float1,
9649 declaration_ptc_d3dcolor,
9650 (BYTE*)exp_vertices24,
9651 exp_vertex_size24
9654 (BYTE*)vertices25,
9655 NULL,
9656 NULL,
9657 num_vertices25,
9658 num_faces25,
9659 vertex_size25,
9660 options,
9661 options,
9662 declaration_ptc_float1,
9663 declaration_ptc_ubyte4,
9664 (BYTE*)exp_vertices25,
9665 exp_vertex_size25
9668 (BYTE*)vertices26,
9669 NULL,
9670 NULL,
9671 num_vertices26,
9672 num_faces26,
9673 vertex_size26,
9674 options,
9675 options,
9676 declaration_ptc_float4,
9677 declaration_ptc_d3dcolor,
9678 (BYTE*)exp_vertices26,
9679 exp_vertex_size26
9682 (BYTE*)vertices27,
9683 NULL,
9684 NULL,
9685 num_vertices27,
9686 num_faces27,
9687 vertex_size27,
9688 options,
9689 options,
9690 declaration_ptc_d3dcolor,
9691 declaration_ptc_float4,
9692 (BYTE*)exp_vertices27,
9693 exp_vertex_size27
9696 (BYTE*)vertices28,
9697 NULL,
9698 NULL,
9699 num_vertices28,
9700 num_faces28,
9701 vertex_size28,
9702 options,
9703 options,
9704 declaration_ptc_ubyte4,
9705 declaration_ptc_float4,
9706 (BYTE*)exp_vertices28,
9707 exp_vertex_size28
9710 (BYTE*)vertices29,
9711 NULL,
9712 NULL,
9713 num_vertices29,
9714 num_faces29,
9715 vertex_size29,
9716 options,
9717 options,
9718 declaration_ptc_short2,
9719 declaration_ptc_float4,
9720 (BYTE*)exp_vertices29,
9721 exp_vertex_size29
9724 (BYTE*)vertices30,
9725 NULL,
9726 NULL,
9727 num_vertices30,
9728 num_faces30,
9729 vertex_size30,
9730 options,
9731 options,
9732 declaration_ptc_short4,
9733 declaration_ptc_float4,
9734 (BYTE*)exp_vertices30,
9735 exp_vertex_size30
9738 (BYTE*)vertices31,
9739 NULL,
9740 NULL,
9741 num_vertices31,
9742 num_faces31,
9743 vertex_size31,
9744 options,
9745 options,
9746 declaration_ptc_ubyte4n,
9747 declaration_ptc_float4,
9748 (BYTE*)exp_vertices31,
9749 exp_vertex_size31
9752 (BYTE*)vertices32,
9753 NULL,
9754 NULL,
9755 num_vertices32,
9756 num_faces32,
9757 vertex_size32,
9758 options,
9759 options,
9760 declaration_ptc_short2n,
9761 declaration_ptc_float4,
9762 (BYTE*)exp_vertices32,
9763 exp_vertex_size32
9766 (BYTE*)vertices33,
9767 NULL,
9768 NULL,
9769 num_vertices33,
9770 num_faces33,
9771 vertex_size33,
9772 options,
9773 options,
9774 declaration_ptc_short4n,
9775 declaration_ptc_float4,
9776 (BYTE*)exp_vertices33,
9777 exp_vertex_size33
9780 (BYTE*)vertices34,
9781 NULL,
9782 NULL,
9783 num_vertices34,
9784 num_faces34,
9785 vertex_size34,
9786 options,
9787 options,
9788 declaration_ptc_float16_2,
9789 declaration_ptc_float4,
9790 (BYTE*)exp_vertices34,
9791 exp_vertex_size34
9794 (BYTE*)vertices35,
9795 NULL,
9796 NULL,
9797 num_vertices35,
9798 num_faces35,
9799 vertex_size35,
9800 options,
9801 options,
9802 declaration_ptc_float16_4,
9803 declaration_ptc_float4,
9804 (BYTE*)exp_vertices35,
9805 exp_vertex_size35
9808 (BYTE*)vertices36,
9809 NULL,
9810 NULL,
9811 num_vertices36,
9812 num_faces36,
9813 vertex_size36,
9814 options,
9815 clone_options36,
9816 declaration_pn,
9817 declaration_pn,
9818 (BYTE*)vertices36,
9819 vertex_size36
9823 test_context = new_test_context();
9824 if (!test_context)
9826 skip("Couldn't create test context\n");
9827 goto cleanup;
9830 for (i = 0; i < ARRAY_SIZE(tc); i++)
9832 UINT j;
9833 D3DVERTEXELEMENT9 new_declaration[MAX_FVF_DECL_SIZE];
9834 UINT exp_new_decl_length, new_decl_length;
9835 UINT exp_new_decl_size, new_decl_size;
9837 hr = init_test_mesh(tc[i].num_faces, tc[i].num_vertices,
9838 tc[i].create_options,
9839 tc[i].declaration,
9840 test_context->device, &mesh,
9841 tc[i].vertices, tc[i].vertex_size,
9842 tc[i].indices, tc[i].attributes);
9843 if (FAILED(hr))
9845 skip("Couldn't initialize test mesh %d. Got %x expected D3D_OK\n", i, hr);
9846 goto cleanup;
9849 hr = mesh->lpVtbl->CloneMesh(mesh, tc[i].clone_options, tc[i].new_declaration,
9850 test_context->device, &mesh_clone);
9851 ok(hr == D3D_OK, "CloneMesh test case %d failed. Got %x\n, expected D3D_OK\n", i, hr);
9853 hr = mesh_clone->lpVtbl->GetDeclaration(mesh_clone, new_declaration);
9854 ok(hr == D3D_OK, "GetDeclaration test case %d failed. Got %x\n, expected D3D_OK\n", i, hr);
9855 /* Check declaration elements */
9856 for (j = 0; tc[i].new_declaration[j].Stream != 0xFF; j++)
9858 ok(memcmp(&tc[i].new_declaration[j], &new_declaration[j], sizeof(*new_declaration)) == 0,
9859 "Test case %d failed. Declaration element %d did not match.\n", i, j);
9862 /* Check declaration length */
9863 exp_new_decl_length = D3DXGetDeclLength(tc[i].new_declaration);
9864 new_decl_length = D3DXGetDeclLength(new_declaration);
9865 ok(new_decl_length == exp_new_decl_length,
9866 "Test case %d failed. Got new declaration length %d, expected %d\n",
9867 i, new_decl_length, exp_new_decl_length);
9869 /* Check declaration size */
9870 exp_new_decl_size = D3DXGetDeclVertexSize(tc[i].new_declaration, 0);
9871 new_decl_size = D3DXGetDeclVertexSize(new_declaration, 0);
9872 ok(new_decl_size == exp_new_decl_size,
9873 "Test case %d failed. Got new declaration size %d, expected %d\n",
9874 i, new_decl_size, exp_new_decl_size);
9876 /* Check vertex data in cloned mesh */
9877 hr = mesh_clone->lpVtbl->LockVertexBuffer(mesh_clone, 0, (void**)&vertices);
9878 if (FAILED(hr))
9880 skip("Couldn't lock cloned vertex buffer.\n");
9881 goto cleanup;
9883 for (j = 0; j < tc[i].num_vertices; j++)
9885 UINT index = tc[i].exp_vertex_size * j;
9886 check_vertex_components(__LINE__, i, j, &vertices[index], &tc[i].exp_vertices[index], tc[i].new_declaration);
9888 hr = mesh_clone->lpVtbl->UnlockVertexBuffer(mesh_clone);
9889 if (FAILED(hr))
9891 skip("Couldn't unlock vertex buffer.\n");
9892 goto cleanup;
9894 vertices = NULL;
9895 mesh->lpVtbl->Release(mesh);
9896 mesh = NULL;
9897 mesh_clone->lpVtbl->Release(mesh_clone);
9898 mesh_clone = NULL;
9901 /* The following test shows that it is not possible to share a vertex buffer
9902 * with D3DXMESH_VB_SHARE and change the vertex declaration at the same
9903 * time. It reuses the test data from test 2.
9905 hr = init_test_mesh(tc[2].num_faces, tc[2].num_vertices,
9906 tc[2].create_options,
9907 tc[2].declaration,
9908 test_context->device, &mesh,
9909 tc[2].vertices, tc[2].vertex_size,
9910 tc[2].indices, tc[2].attributes);
9911 if (FAILED(hr))
9913 skip("Couldn't initialize test mesh for D3DXMESH_VB_SHARE case."
9914 " Got %x expected D3D_OK\n", hr);
9915 goto cleanup;
9918 hr = mesh->lpVtbl->CloneMesh(mesh, tc[2].create_options | D3DXMESH_VB_SHARE,
9919 tc[2].new_declaration, test_context->device,
9920 &mesh_clone);
9921 ok(hr == D3DERR_INVALIDCALL, "CloneMesh D3DXMESH_VB_SHARE with new"
9922 " declaration. Got %x, expected D3DERR_INVALIDCALL\n",
9923 hr);
9924 mesh->lpVtbl->Release(mesh);
9925 mesh = NULL;
9926 mesh_clone = NULL;
9928 cleanup:
9929 if (vertices) mesh->lpVtbl->UnlockVertexBuffer(mesh);
9930 if (mesh) mesh->lpVtbl->Release(mesh);
9931 if (mesh_clone) mesh_clone->lpVtbl->Release(mesh_clone);
9932 free_test_context(test_context);
9935 static void test_valid_mesh(void)
9937 HRESULT hr;
9938 struct test_context *test_context = NULL;
9939 UINT i;
9940 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
9941 const D3DVERTEXELEMENT9 declaration[] =
9943 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
9944 D3DDECL_END()
9946 const unsigned int VERTS_PER_FACE = 3;
9947 /* mesh0 (one face)
9949 * 0--1
9950 * | /
9951 * |/
9954 const D3DXVECTOR3 vertices0[] =
9956 { 0.0f, 3.0f, 0.f},
9957 { 2.0f, 3.0f, 0.f},
9958 { 0.0f, 0.0f, 0.f},
9960 const DWORD indices0[] = {0, 1, 2};
9961 const unsigned int num_vertices0 = ARRAY_SIZE(vertices0);
9962 const unsigned int num_faces0 = ARRAY_SIZE(indices0) / VERTS_PER_FACE;
9963 const DWORD adjacency0[] = {-1, -1, -1};
9964 const HRESULT exp_hr0 = D3D_OK;
9965 /* mesh1 (Simple bow-tie)
9967 * 0--1 1--3
9968 * | / \ |
9969 * |/ \|
9970 * 2 4
9972 const D3DXVECTOR3 vertices1[] =
9974 { 0.0f, 3.0f, 0.f},
9975 { 2.0f, 3.0f, 0.f},
9976 { 0.0f, 0.0f, 0.f},
9978 { 4.0f, 3.0f, 0.f},
9979 { 4.0f, 0.0f, 0.f},
9981 const DWORD indices1[] = {0, 1, 2, 1, 3, 4};
9982 const unsigned int num_vertices1 = ARRAY_SIZE(vertices1);
9983 const unsigned int num_faces1 = ARRAY_SIZE(indices1) / VERTS_PER_FACE;
9984 const DWORD adjacency1[] = {-1, -1, -1, -1, -1, -1};
9985 const HRESULT exp_hr1 = D3DXERR_INVALIDMESH;
9986 /* Common mesh data */
9987 ID3DXMesh *mesh = NULL;
9988 UINT vertex_size = sizeof(D3DXVECTOR3);
9989 ID3DXBuffer *errors_and_warnings = NULL;
9990 struct
9992 const D3DXVECTOR3 *vertices;
9993 const DWORD *indices;
9994 const UINT num_vertices;
9995 const UINT num_faces;
9996 const DWORD *adjacency;
9997 const HRESULT exp_hr;
9999 tc[] =
10002 vertices0,
10003 indices0,
10004 num_vertices0,
10005 num_faces0,
10006 adjacency0,
10007 exp_hr0,
10010 vertices1,
10011 indices1,
10012 num_vertices1,
10013 num_faces1,
10014 adjacency1,
10015 exp_hr1,
10019 test_context = new_test_context();
10020 if (!test_context)
10022 skip("Couldn't create test context\n");
10023 goto cleanup;
10026 for (i = 0; i < ARRAY_SIZE(tc); i++)
10028 hr = init_test_mesh(tc[i].num_faces, tc[i].num_vertices,
10029 options, declaration,
10030 test_context->device, &mesh,
10031 tc[i].vertices, vertex_size,
10032 tc[i].indices, NULL);
10033 if (FAILED(hr))
10035 skip("Couldn't initialize test mesh %d. Got %x expected D3D_OK\n", i, hr);
10036 goto cleanup;
10039 hr = D3DXValidMesh(mesh, tc[i].adjacency, &errors_and_warnings);
10040 todo_wine ok(hr == tc[i].exp_hr, "D3DXValidMesh test case %d failed. "
10041 "Got %x\n, expected %x\n", i, hr, tc[i].exp_hr);
10043 /* Note errors_and_warnings is deliberately not checked because that
10044 * would require copying wast amounts of the text output. */
10045 if (errors_and_warnings)
10047 ID3DXBuffer_Release(errors_and_warnings);
10048 errors_and_warnings = NULL;
10050 mesh->lpVtbl->Release(mesh);
10051 mesh = NULL;
10054 cleanup:
10055 if (mesh) mesh->lpVtbl->Release(mesh);
10056 free_test_context(test_context);
10059 START_TEST(mesh)
10061 D3DXBoundProbeTest();
10062 D3DXComputeBoundingBoxTest();
10063 D3DXComputeBoundingSphereTest();
10064 D3DXGetFVFVertexSizeTest();
10065 D3DXIntersectTriTest();
10066 D3DXCreateMeshTest();
10067 D3DXCreateMeshFVFTest();
10068 D3DXLoadMeshTest();
10069 D3DXCreateBoxTest();
10070 D3DXCreateSphereTest();
10071 D3DXCreateCylinderTest();
10072 D3DXCreateTextTest();
10073 test_get_decl_length();
10074 test_get_decl_vertex_size();
10075 test_fvf_decl_conversion();
10076 D3DXGenerateAdjacencyTest();
10077 test_update_semantics();
10078 test_create_skin_info();
10079 test_convert_adjacency_to_point_reps();
10080 test_convert_point_reps_to_adjacency();
10081 test_weld_vertices();
10082 test_clone_mesh();
10083 test_valid_mesh();