d3dx9/tests: Add a D3DXValidMesh test.
[wine/multimedia.git] / dlls / d3dx9_36 / tests / mesh.c
blobaf0a9e84c83145b31ab4463e7af557fb5c9f87d0
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 todo_wine ok(index_buffer_description.Usage == 0, "Test %s, result %x, expected %x\n", name, index_buffer_description.Usage, 0);
332 ok(index_buffer_description.Pool == D3DPOOL_MANAGED, "Test %s, result %x, expected %x (D3DPOOL_MANAGED)\n",
333 name, index_buffer_description.Pool, D3DPOOL_MANAGED);
334 expected = number_of_faces * sizeof(WORD) * 3;
335 ok(index_buffer_description.Size == expected, "Test %s, result %x, expected %x\n",
336 name, index_buffer_description.Size, expected);
339 /* specify offset and size to avoid potential overruns */
340 hr = IDirect3DIndexBuffer9_Lock(index_buffer, 0, number_of_faces * sizeof(WORD) * 3,
341 (LPVOID *)&faces, D3DLOCK_DISCARD);
342 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
344 if (hr != D3D_OK)
346 skip("Couldn't lock index buffer\n");
348 else
350 for (i = 0; i < number_of_faces; i++)
352 ok(compare_face(faces[i], mesh->faces[i]),
353 "Test %s, face %d, result (%u, %u, %u), expected (%u, %u, %u)\n", name, i,
354 faces[i][0], faces[i][1], faces[i][2],
355 mesh->faces[i][0], mesh->faces[i][1], mesh->faces[i][2]);
358 IDirect3DIndexBuffer9_Unlock(index_buffer);
361 IDirect3DIndexBuffer9_Release(index_buffer);
365 static void D3DXBoundProbeTest(void)
367 BOOL result;
368 D3DXVECTOR3 bottom_point, center, top_point, raydirection, rayposition;
369 FLOAT radius;
371 /*____________Test the Box case___________________________*/
372 bottom_point.x = -3.0f; bottom_point.y = -2.0f; bottom_point.z = -1.0f;
373 top_point.x = 7.0f; top_point.y = 8.0f; top_point.z = 9.0f;
375 raydirection.x = -4.0f; raydirection.y = -5.0f; raydirection.z = -6.0f;
376 rayposition.x = 5.0f; rayposition.y = 5.0f; rayposition.z = 11.0f;
377 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection);
378 ok(result == TRUE, "expected TRUE, received FALSE\n");
380 raydirection.x = 4.0f; raydirection.y = 5.0f; raydirection.z = 6.0f;
381 rayposition.x = 5.0f; rayposition.y = 5.0f; rayposition.z = 11.0f;
382 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection);
383 ok(result == FALSE, "expected FALSE, received TRUE\n");
385 rayposition.x = -4.0f; rayposition.y = 1.0f; rayposition.z = -2.0f;
386 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection);
387 ok(result == TRUE, "expected TRUE, received FALSE\n");
389 bottom_point.x = 1.0f; bottom_point.y = 0.0f; bottom_point.z = 0.0f;
390 top_point.x = 1.0f; top_point.y = 0.0f; top_point.z = 0.0f;
391 rayposition.x = 0.0f; rayposition.y = 1.0f; rayposition.z = 0.0f;
392 raydirection.x = 0.0f; raydirection.y = 3.0f; raydirection.z = 0.0f;
393 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection);
394 ok(result == FALSE, "expected FALSE, received TRUE\n");
396 bottom_point.x = 1.0f; bottom_point.y = 2.0f; bottom_point.z = 3.0f;
397 top_point.x = 10.0f; top_point.y = 15.0f; top_point.z = 20.0f;
399 raydirection.x = 7.0f; raydirection.y = 8.0f; raydirection.z = 9.0f;
400 rayposition.x = 3.0f; rayposition.y = 7.0f; rayposition.z = -6.0f;
401 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection);
402 ok(result == TRUE, "expected TRUE, received FALSE\n");
404 bottom_point.x = 0.0f; bottom_point.y = 0.0f; bottom_point.z = 0.0f;
405 top_point.x = 1.0f; top_point.y = 1.0f; top_point.z = 1.0f;
407 raydirection.x = 0.0f; raydirection.y = 1.0f; raydirection.z = .0f;
408 rayposition.x = -3.0f; rayposition.y = 0.0f; rayposition.z = 0.0f;
409 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection);
410 ok(result == FALSE, "expected FALSE, received TRUE\n");
412 raydirection.x = 1.0f; raydirection.y = 0.0f; raydirection.z = .0f;
413 rayposition.x = -3.0f; rayposition.y = 0.0f; rayposition.z = 0.0f;
414 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection);
415 ok(result == TRUE, "expected TRUE, received FALSE\n");
417 /*____________Test the Sphere case________________________*/
418 radius = sqrt(77.0f);
419 center.x = 1.0f; center.y = 2.0f; center.z = 3.0f;
420 raydirection.x = 2.0f; raydirection.y = -4.0f; raydirection.z = 2.0f;
422 rayposition.x = 5.0f; rayposition.y = 5.0f; rayposition.z = 9.0f;
423 result = D3DXSphereBoundProbe(&center, radius, &rayposition, &raydirection);
424 ok(result == TRUE, "expected TRUE, received FALSE\n");
426 rayposition.x = 45.0f; rayposition.y = -75.0f; rayposition.z = 49.0f;
427 result = D3DXSphereBoundProbe(&center, radius, &rayposition, &raydirection);
428 ok(result == FALSE, "expected FALSE, received TRUE\n");
430 rayposition.x = 5.0f; rayposition.y = 11.0f; rayposition.z = 9.0f;
431 result = D3DXSphereBoundProbe(&center, radius, &rayposition, &raydirection);
432 ok(result == FALSE, "expected FALSE, received TRUE\n");
435 static void D3DXComputeBoundingBoxTest(void)
437 D3DXVECTOR3 exp_max, exp_min, got_max, got_min, vertex[5];
438 HRESULT hr;
440 vertex[0].x = 1.0f; vertex[0].y = 1.0f; vertex[0].z = 1.0f;
441 vertex[1].x = 1.0f; vertex[1].y = 1.0f; vertex[1].z = 1.0f;
442 vertex[2].x = 1.0f; vertex[2].y = 1.0f; vertex[2].z = 1.0f;
443 vertex[3].x = 1.0f; vertex[3].y = 1.0f; vertex[3].z = 1.0f;
444 vertex[4].x = 9.0f; vertex[4].y = 9.0f; vertex[4].z = 9.0f;
446 exp_min.x = 1.0f; exp_min.y = 1.0f; exp_min.z = 1.0f;
447 exp_max.x = 9.0f; exp_max.y = 9.0f; exp_max.z = 9.0f;
449 hr = D3DXComputeBoundingBox(&vertex[3],2,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_min,&got_max);
451 ok( hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
452 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);
453 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);
455 /*________________________*/
457 vertex[0].x = 2.0f; vertex[0].y = 5.9f; vertex[0].z = -1.2f;
458 vertex[1].x = -1.87f; vertex[1].y = 7.9f; vertex[1].z = 7.4f;
459 vertex[2].x = 7.43f; vertex[2].y = -0.9f; vertex[2].z = 11.9f;
460 vertex[3].x = -6.92f; vertex[3].y = 6.3f; vertex[3].z = -3.8f;
461 vertex[4].x = 11.4f; vertex[4].y = -8.1f; vertex[4].z = 4.5f;
463 exp_min.x = -6.92f; exp_min.y = -8.1f; exp_min.z = -3.80f;
464 exp_max.x = 11.4f; exp_max.y = 7.90f; exp_max.z = 11.9f;
466 hr = D3DXComputeBoundingBox(&vertex[0],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_min,&got_max);
468 ok( hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
469 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);
470 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);
472 /*________________________*/
474 vertex[0].x = 2.0f; vertex[0].y = 5.9f; vertex[0].z = -1.2f;
475 vertex[1].x = -1.87f; vertex[1].y = 7.9f; vertex[1].z = 7.4f;
476 vertex[2].x = 7.43f; vertex[2].y = -0.9f; vertex[2].z = 11.9f;
477 vertex[3].x = -6.92f; vertex[3].y = 6.3f; vertex[3].z = -3.8f;
478 vertex[4].x = 11.4f; vertex[4].y = -8.1f; vertex[4].z = 4.5f;
480 exp_min.x = -6.92f; exp_min.y = -0.9f; exp_min.z = -3.8f;
481 exp_max.x = 7.43f; exp_max.y = 7.90f; exp_max.z = 11.9f;
483 hr = D3DXComputeBoundingBox(&vertex[0],4,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_min,&got_max);
485 ok( hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
486 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);
487 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);
489 /*________________________*/
490 hr = D3DXComputeBoundingBox(NULL,5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_min,&got_max);
491 ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
493 /*________________________*/
494 hr = D3DXComputeBoundingBox(&vertex[3],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),NULL,&got_max);
495 ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
497 /*________________________*/
498 hr = D3DXComputeBoundingBox(&vertex[3],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_min,NULL);
499 ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
502 static void D3DXComputeBoundingSphereTest(void)
504 D3DXVECTOR3 exp_cen, got_cen, vertex[5];
505 FLOAT exp_rad, got_rad;
506 HRESULT hr;
508 vertex[0].x = 1.0f; vertex[0].y = 1.0f; vertex[0].z = 1.0f;
509 vertex[1].x = 1.0f; vertex[1].y = 1.0f; vertex[1].z = 1.0f;
510 vertex[2].x = 1.0f; vertex[2].y = 1.0f; vertex[2].z = 1.0f;
511 vertex[3].x = 1.0f; vertex[3].y = 1.0f; vertex[3].z = 1.0f;
512 vertex[4].x = 9.0f; vertex[4].y = 9.0f; vertex[4].z = 9.0f;
514 exp_rad = 6.928203f;
515 exp_cen.x = 5.0; exp_cen.y = 5.0; exp_cen.z = 5.0;
517 hr = D3DXComputeBoundingSphere(&vertex[3],2,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_cen,&got_rad);
519 ok( hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
520 ok( compare(exp_rad, got_rad), "Expected radius: %f, got radius: %f\n", exp_rad, got_rad);
521 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);
523 /*________________________*/
525 vertex[0].x = 2.0f; vertex[0].y = 5.9f; vertex[0].z = -1.2f;
526 vertex[1].x = -1.87f; vertex[1].y = 7.9f; vertex[1].z = 7.4f;
527 vertex[2].x = 7.43f; vertex[2].y = -0.9f; vertex[2].z = 11.9f;
528 vertex[3].x = -6.92f; vertex[3].y = 6.3f; vertex[3].z = -3.8f;
529 vertex[4].x = 11.4f; vertex[4].y = -8.1f; vertex[4].z = 4.5f;
531 exp_rad = 13.707883f;
532 exp_cen.x = 2.408f; exp_cen.y = 2.22f; exp_cen.z = 3.76f;
534 hr = D3DXComputeBoundingSphere(&vertex[0],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_cen,&got_rad);
536 ok( hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
537 ok( compare(exp_rad, got_rad), "Expected radius: %f, got radius: %f\n", exp_rad, got_rad);
538 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);
540 /*________________________*/
541 hr = D3DXComputeBoundingSphere(NULL,5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_cen,&got_rad);
542 ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
544 /*________________________*/
545 hr = D3DXComputeBoundingSphere(&vertex[3],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),NULL,&got_rad);
546 ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
548 /*________________________*/
549 hr = D3DXComputeBoundingSphere(&vertex[3],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_cen,NULL);
550 ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
553 static void print_elements(const D3DVERTEXELEMENT9 *elements)
555 D3DVERTEXELEMENT9 last = D3DDECL_END();
556 const D3DVERTEXELEMENT9 *ptr = elements;
557 int count = 0;
559 while (memcmp(ptr, &last, sizeof(D3DVERTEXELEMENT9)))
561 trace(
562 "[Element %d] Stream = %d, Offset = %d, Type = %d, Method = %d, Usage = %d, UsageIndex = %d\n",
563 count, ptr->Stream, ptr->Offset, ptr->Type, ptr->Method, ptr->Usage, ptr->UsageIndex);
564 ptr++;
565 count++;
569 static void compare_elements(const D3DVERTEXELEMENT9 *elements, const D3DVERTEXELEMENT9 *expected_elements,
570 unsigned int line, unsigned int test_id)
572 D3DVERTEXELEMENT9 last = D3DDECL_END();
573 unsigned int i;
575 for (i = 0; i < MAX_FVF_DECL_SIZE; i++)
577 int end1 = memcmp(&elements[i], &last, sizeof(last));
578 int end2 = memcmp(&expected_elements[i], &last, sizeof(last));
579 int status;
581 if (!end1 && !end2) break;
583 status = !end1 ^ !end2;
584 ok(!status, "Line %u, test %u: Mismatch in size, test declaration is %s than expected.\n",
585 line, test_id, end1 ? "shorter" : "longer");
586 if (status)
588 print_elements(elements);
589 break;
592 status = memcmp(&elements[i], &expected_elements[i], sizeof(D3DVERTEXELEMENT9));
593 ok(!status, "Line %u, test %u: Mismatch in element %u.\n", line, test_id, i);
594 if (status)
596 print_elements(elements);
597 break;
602 static void test_fvf_to_decl(DWORD test_fvf, const D3DVERTEXELEMENT9 expected_elements[],
603 HRESULT expected_hr, unsigned int line, unsigned int test_id)
605 HRESULT hr;
606 D3DVERTEXELEMENT9 decl[MAX_FVF_DECL_SIZE];
608 hr = D3DXDeclaratorFromFVF(test_fvf, decl);
609 ok(hr == expected_hr,
610 "Line %u, test %u: D3DXDeclaratorFromFVF returned %#x, expected %#x.\n",
611 line, test_id, hr, expected_hr);
612 if (SUCCEEDED(hr)) compare_elements(decl, expected_elements, line, test_id);
615 static void test_decl_to_fvf(const D3DVERTEXELEMENT9 *decl, DWORD expected_fvf,
616 HRESULT expected_hr, unsigned int line, unsigned int test_id)
618 HRESULT hr;
619 DWORD result_fvf = 0xdeadbeef;
621 hr = D3DXFVFFromDeclarator(decl, &result_fvf);
622 ok(hr == expected_hr,
623 "Line %u, test %u: D3DXFVFFromDeclarator returned %#x, expected %#x.\n",
624 line, test_id, hr, expected_hr);
625 if (SUCCEEDED(hr))
627 ok(expected_fvf == result_fvf, "Line %u, test %u: Got FVF %#x, expected %#x.\n",
628 line, test_id, result_fvf, expected_fvf);
632 static void test_fvf_decl_conversion(void)
634 static const struct
636 D3DVERTEXELEMENT9 decl[MAXD3DDECLLENGTH + 1];
637 DWORD fvf;
639 test_data[] =
642 D3DDECL_END(),
643 }, 0},
645 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
646 D3DDECL_END(),
647 }, D3DFVF_XYZ},
649 {0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITIONT, 0},
650 D3DDECL_END(),
651 }, D3DFVF_XYZRHW},
653 {0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITIONT, 0},
654 D3DDECL_END(),
655 }, D3DFVF_XYZRHW},
657 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
658 {0, 12, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
659 D3DDECL_END(),
660 }, D3DFVF_XYZB1},
662 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
663 {0, 12, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
664 D3DDECL_END(),
665 }, D3DFVF_XYZB1 | D3DFVF_LASTBETA_UBYTE4},
667 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
668 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
669 D3DDECL_END(),
670 }, D3DFVF_XYZB1 | D3DFVF_LASTBETA_D3DCOLOR},
672 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
673 {0, 12, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
674 D3DDECL_END(),
675 }, D3DFVF_XYZB2},
677 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
678 {0, 12, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
679 {0, 16, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
680 D3DDECL_END(),
681 }, D3DFVF_XYZB2 | D3DFVF_LASTBETA_UBYTE4},
683 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
684 {0, 12, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
685 {0, 16, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
686 D3DDECL_END(),
687 }, D3DFVF_XYZB2 | D3DFVF_LASTBETA_D3DCOLOR},
689 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
690 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
691 D3DDECL_END(),
692 }, D3DFVF_XYZB3},
694 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
695 {0, 12, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
696 {0, 20, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
697 D3DDECL_END(),
698 }, D3DFVF_XYZB3 | D3DFVF_LASTBETA_UBYTE4},
700 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
701 {0, 12, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
702 {0, 20, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
703 D3DDECL_END(),
704 }, D3DFVF_XYZB3 | D3DFVF_LASTBETA_D3DCOLOR},
706 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
707 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
708 D3DDECL_END(),
709 }, D3DFVF_XYZB4},
711 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
712 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
713 {0, 24, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
714 D3DDECL_END(),
715 }, D3DFVF_XYZB4 | D3DFVF_LASTBETA_UBYTE4},
717 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
718 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
719 {0, 24, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
720 D3DDECL_END(),
721 }, D3DFVF_XYZB4 | D3DFVF_LASTBETA_D3DCOLOR},
723 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
724 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
725 {0, 28, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
726 D3DDECL_END(),
727 }, D3DFVF_XYZB5 | D3DFVF_LASTBETA_UBYTE4},
729 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
730 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
731 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
732 D3DDECL_END(),
733 }, D3DFVF_XYZB5 | D3DFVF_LASTBETA_D3DCOLOR},
735 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
736 D3DDECL_END(),
737 }, D3DFVF_NORMAL},
739 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
740 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
741 D3DDECL_END(),
742 }, D3DFVF_NORMAL | D3DFVF_DIFFUSE},
744 {0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_PSIZE, 0},
745 D3DDECL_END(),
746 }, D3DFVF_PSIZE},
748 {0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
749 D3DDECL_END(),
750 }, D3DFVF_DIFFUSE},
752 {0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1},
753 D3DDECL_END(),
754 }, D3DFVF_SPECULAR},
755 /* Make sure textures of different sizes work. */
757 {0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
758 D3DDECL_END(),
759 }, D3DFVF_TEXCOORDSIZE1(0) | D3DFVF_TEX1},
761 {0, 0, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 0},
762 D3DDECL_END(),
763 }, D3DFVF_TEXCOORDSIZE2(0) | D3DFVF_TEX1},
765 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 0},
766 D3DDECL_END(),
767 }, D3DFVF_TEXCOORDSIZE3(0) | D3DFVF_TEX1},
769 {0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 0},
770 D3DDECL_END(),
771 }, D3DFVF_TEXCOORDSIZE4(0) | D3DFVF_TEX1},
772 /* Make sure the TEXCOORD index works correctly - try several textures. */
774 {0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
775 {0, 4, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 1},
776 {0, 16, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 2},
777 {0, 24, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 3},
778 D3DDECL_END(),
779 }, D3DFVF_TEX4 | D3DFVF_TEXCOORDSIZE1(0) | D3DFVF_TEXCOORDSIZE3(1)
780 | D3DFVF_TEXCOORDSIZE2(2) | D3DFVF_TEXCOORDSIZE4(3)},
781 /* Now try some combination tests. */
783 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
784 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
785 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
786 {0, 32, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1},
787 {0, 36, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 0},
788 {0, 44, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 1},
789 D3DDECL_END(),
790 }, D3DFVF_XYZB4 | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_TEX2
791 | D3DFVF_TEXCOORDSIZE2(0) | D3DFVF_TEXCOORDSIZE3(1)},
793 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
794 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
795 {0, 24, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_PSIZE, 0},
796 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1},
797 {0, 32, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
798 {0, 36, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 1},
799 D3DDECL_END(),
800 }, D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_PSIZE | D3DFVF_SPECULAR | D3DFVF_TEX2
801 | D3DFVF_TEXCOORDSIZE1(0) | D3DFVF_TEXCOORDSIZE4(1)},
803 unsigned int i;
805 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
807 test_decl_to_fvf(test_data[i].decl, test_data[i].fvf, D3D_OK, __LINE__, i);
808 test_fvf_to_decl(test_data[i].fvf, test_data[i].decl, D3D_OK, __LINE__, i);
811 /* Usage indices for position and normal are apparently ignored. */
813 const D3DVERTEXELEMENT9 decl[] =
815 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 1},
816 D3DDECL_END(),
818 test_decl_to_fvf(decl, D3DFVF_XYZ, D3D_OK, __LINE__, 0);
821 const D3DVERTEXELEMENT9 decl[] =
823 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 1},
824 D3DDECL_END(),
826 test_decl_to_fvf(decl, D3DFVF_NORMAL, D3D_OK, __LINE__, 0);
828 /* D3DFVF_LASTBETA_UBYTE4 and D3DFVF_LASTBETA_D3DCOLOR are ignored if
829 * there are no blend matrices. */
831 const D3DVERTEXELEMENT9 decl[] =
833 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
834 D3DDECL_END(),
836 test_fvf_to_decl(D3DFVF_XYZ | D3DFVF_LASTBETA_UBYTE4, decl, D3D_OK, __LINE__, 0);
839 const D3DVERTEXELEMENT9 decl[] =
841 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
842 D3DDECL_END(),
844 test_fvf_to_decl(D3DFVF_XYZ | D3DFVF_LASTBETA_D3DCOLOR, decl, D3D_OK, __LINE__, 0);
846 /* D3DFVF_LASTBETA_UBYTE4 takes precedence over D3DFVF_LASTBETA_D3DCOLOR. */
848 const D3DVERTEXELEMENT9 decl[] =
850 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
851 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
852 {0, 28, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
853 D3DDECL_END(),
855 test_fvf_to_decl(D3DFVF_XYZB5 | D3DFVF_LASTBETA_D3DCOLOR | D3DFVF_LASTBETA_UBYTE4,
856 decl, D3D_OK, __LINE__, 0);
858 /* These are supposed to fail, both ways. */
860 const D3DVERTEXELEMENT9 decl[] =
862 {0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITION, 0},
863 D3DDECL_END(),
865 test_decl_to_fvf(decl, D3DFVF_XYZW, D3DERR_INVALIDCALL, __LINE__, 0);
866 test_fvf_to_decl(D3DFVF_XYZW, decl, D3DERR_INVALIDCALL, __LINE__, 0);
869 const D3DVERTEXELEMENT9 decl[] =
871 {0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITION, 0},
872 {0, 16, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
873 D3DDECL_END(),
875 test_decl_to_fvf(decl, D3DFVF_XYZW | D3DFVF_NORMAL, D3DERR_INVALIDCALL, __LINE__, 0);
876 test_fvf_to_decl(D3DFVF_XYZW | D3DFVF_NORMAL, decl, D3DERR_INVALIDCALL, __LINE__, 0);
879 const D3DVERTEXELEMENT9 decl[] =
881 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
882 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
883 {0, 28, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDINDICES, 0},
884 D3DDECL_END(),
886 test_decl_to_fvf(decl, D3DFVF_XYZB5, D3DERR_INVALIDCALL, __LINE__, 0);
887 test_fvf_to_decl(D3DFVF_XYZB5, decl, D3DERR_INVALIDCALL, __LINE__, 0);
889 /* Test a declaration that can't be converted to an FVF. */
891 const D3DVERTEXELEMENT9 decl[] =
893 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
894 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
895 {0, 24, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_PSIZE, 0},
896 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1},
897 {0, 32, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
898 /* 8 bytes padding */
899 {0, 44, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 1},
900 D3DDECL_END(),
902 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0);
904 /* Elements must be ordered by offset. */
906 const D3DVERTEXELEMENT9 decl[] =
908 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
909 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
910 D3DDECL_END(),
912 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0);
914 /* Basic tests for element order. */
916 const D3DVERTEXELEMENT9 decl[] =
918 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
919 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
920 {0, 16, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
921 D3DDECL_END(),
923 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0);
926 const D3DVERTEXELEMENT9 decl[] =
928 {0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
929 {0, 4, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
930 D3DDECL_END(),
932 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0);
935 const D3DVERTEXELEMENT9 decl[] =
937 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
938 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
939 D3DDECL_END(),
941 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0);
943 /* Textures must be ordered by texcoords. */
945 const D3DVERTEXELEMENT9 decl[] =
947 {0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
948 {0, 4, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 2},
949 {0, 16, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 1},
950 {0, 24, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 3},
951 D3DDECL_END(),
953 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0);
955 /* Duplicate elements are not allowed. */
957 const D3DVERTEXELEMENT9 decl[] =
959 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
960 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
961 {0, 16, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
962 D3DDECL_END(),
964 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0);
966 /* Invalid FVFs cannot be converted to a declarator. */
967 test_fvf_to_decl(0xdeadbeef, NULL, D3DERR_INVALIDCALL, __LINE__, 0);
970 static void D3DXGetFVFVertexSizeTest(void)
972 UINT got;
974 compare_vertex_sizes (D3DFVF_XYZ, 12);
976 compare_vertex_sizes (D3DFVF_XYZB3, 24);
978 compare_vertex_sizes (D3DFVF_XYZB5, 32);
980 compare_vertex_sizes (D3DFVF_XYZ | D3DFVF_NORMAL, 24);
982 compare_vertex_sizes (D3DFVF_XYZ | D3DFVF_DIFFUSE, 16);
984 compare_vertex_sizes (
985 D3DFVF_XYZ |
986 D3DFVF_TEX1 |
987 D3DFVF_TEXCOORDSIZE1(0), 16);
988 compare_vertex_sizes (
989 D3DFVF_XYZ |
990 D3DFVF_TEX2 |
991 D3DFVF_TEXCOORDSIZE1(0) |
992 D3DFVF_TEXCOORDSIZE1(1), 20);
994 compare_vertex_sizes (
995 D3DFVF_XYZ |
996 D3DFVF_TEX1 |
997 D3DFVF_TEXCOORDSIZE2(0), 20);
999 compare_vertex_sizes (
1000 D3DFVF_XYZ |
1001 D3DFVF_TEX2 |
1002 D3DFVF_TEXCOORDSIZE2(0) |
1003 D3DFVF_TEXCOORDSIZE2(1), 28);
1005 compare_vertex_sizes (
1006 D3DFVF_XYZ |
1007 D3DFVF_TEX6 |
1008 D3DFVF_TEXCOORDSIZE2(0) |
1009 D3DFVF_TEXCOORDSIZE2(1) |
1010 D3DFVF_TEXCOORDSIZE2(2) |
1011 D3DFVF_TEXCOORDSIZE2(3) |
1012 D3DFVF_TEXCOORDSIZE2(4) |
1013 D3DFVF_TEXCOORDSIZE2(5), 60);
1015 compare_vertex_sizes (
1016 D3DFVF_XYZ |
1017 D3DFVF_TEX8 |
1018 D3DFVF_TEXCOORDSIZE2(0) |
1019 D3DFVF_TEXCOORDSIZE2(1) |
1020 D3DFVF_TEXCOORDSIZE2(2) |
1021 D3DFVF_TEXCOORDSIZE2(3) |
1022 D3DFVF_TEXCOORDSIZE2(4) |
1023 D3DFVF_TEXCOORDSIZE2(5) |
1024 D3DFVF_TEXCOORDSIZE2(6) |
1025 D3DFVF_TEXCOORDSIZE2(7), 76);
1027 compare_vertex_sizes (
1028 D3DFVF_XYZ |
1029 D3DFVF_TEX1 |
1030 D3DFVF_TEXCOORDSIZE3(0), 24);
1032 compare_vertex_sizes (
1033 D3DFVF_XYZ |
1034 D3DFVF_TEX4 |
1035 D3DFVF_TEXCOORDSIZE3(0) |
1036 D3DFVF_TEXCOORDSIZE3(1) |
1037 D3DFVF_TEXCOORDSIZE3(2) |
1038 D3DFVF_TEXCOORDSIZE3(3), 60);
1040 compare_vertex_sizes (
1041 D3DFVF_XYZ |
1042 D3DFVF_TEX1 |
1043 D3DFVF_TEXCOORDSIZE4(0), 28);
1045 compare_vertex_sizes (
1046 D3DFVF_XYZ |
1047 D3DFVF_TEX2 |
1048 D3DFVF_TEXCOORDSIZE4(0) |
1049 D3DFVF_TEXCOORDSIZE4(1), 44);
1051 compare_vertex_sizes (
1052 D3DFVF_XYZ |
1053 D3DFVF_TEX3 |
1054 D3DFVF_TEXCOORDSIZE4(0) |
1055 D3DFVF_TEXCOORDSIZE4(1) |
1056 D3DFVF_TEXCOORDSIZE4(2), 60);
1058 compare_vertex_sizes (
1059 D3DFVF_XYZB5 |
1060 D3DFVF_NORMAL |
1061 D3DFVF_DIFFUSE |
1062 D3DFVF_SPECULAR |
1063 D3DFVF_TEX8 |
1064 D3DFVF_TEXCOORDSIZE4(0) |
1065 D3DFVF_TEXCOORDSIZE4(1) |
1066 D3DFVF_TEXCOORDSIZE4(2) |
1067 D3DFVF_TEXCOORDSIZE4(3) |
1068 D3DFVF_TEXCOORDSIZE4(4) |
1069 D3DFVF_TEXCOORDSIZE4(5) |
1070 D3DFVF_TEXCOORDSIZE4(6) |
1071 D3DFVF_TEXCOORDSIZE4(7), 180);
1074 static void D3DXIntersectTriTest(void)
1076 BOOL exp_res, got_res;
1077 D3DXVECTOR3 position, ray, vertex[3];
1078 FLOAT exp_dist, got_dist, exp_u, got_u, exp_v, got_v;
1080 vertex[0].x = 1.0f; vertex[0].y = 0.0f; vertex[0].z = 0.0f;
1081 vertex[1].x = 2.0f; vertex[1].y = 0.0f; vertex[1].z = 0.0f;
1082 vertex[2].x = 1.0f; vertex[2].y = 1.0f; vertex[2].z = 0.0f;
1084 position.x = -14.5f; position.y = -23.75f; position.z = -32.0f;
1086 ray.x = 2.0f; ray.y = 3.0f; ray.z = 4.0f;
1088 exp_res = TRUE; exp_u = 0.5f; exp_v = 0.25f; exp_dist = 8.0f;
1090 got_res = D3DXIntersectTri(&vertex[0],&vertex[1],&vertex[2],&position,&ray,&got_u,&got_v,&got_dist);
1091 ok( got_res == exp_res, "Expected result = %d, got %d\n",exp_res,got_res);
1092 ok( compare(exp_u,got_u), "Expected u = %f, got %f\n",exp_u,got_u);
1093 ok( compare(exp_v,got_v), "Expected v = %f, got %f\n",exp_v,got_v);
1094 ok( compare(exp_dist,got_dist), "Expected distance = %f, got %f\n",exp_dist,got_dist);
1096 /*Only positive ray is taken in account*/
1098 vertex[0].x = 1.0f; vertex[0].y = 0.0f; vertex[0].z = 0.0f;
1099 vertex[1].x = 2.0f; vertex[1].y = 0.0f; vertex[1].z = 0.0f;
1100 vertex[2].x = 1.0f; vertex[2].y = 1.0f; vertex[2].z = 0.0f;
1102 position.x = 17.5f; position.y = 24.25f; position.z = 32.0f;
1104 ray.x = 2.0f; ray.y = 3.0f; ray.z = 4.0f;
1106 exp_res = FALSE;
1108 got_res = D3DXIntersectTri(&vertex[0],&vertex[1],&vertex[2],&position,&ray,&got_u,&got_v,&got_dist);
1109 ok( got_res == exp_res, "Expected result = %d, got %d\n",exp_res,got_res);
1111 /*Intersection between ray and triangle in a same plane is considered as empty*/
1113 vertex[0].x = 4.0f; vertex[0].y = 0.0f; vertex[0].z = 0.0f;
1114 vertex[1].x = 6.0f; vertex[1].y = 0.0f; vertex[1].z = 0.0f;
1115 vertex[2].x = 4.0f; vertex[2].y = 2.0f; vertex[2].z = 0.0f;
1117 position.x = 1.0f; position.y = 1.0f; position.z = 0.0f;
1119 ray.x = 1.0f; ray.y = 0.0f; ray.z = 0.0f;
1121 exp_res = FALSE;
1123 got_res = D3DXIntersectTri(&vertex[0],&vertex[1],&vertex[2],&position,&ray,&got_u,&got_v,&got_dist);
1124 ok( got_res == exp_res, "Expected result = %d, got %d\n",exp_res,got_res);
1127 static void D3DXCreateMeshTest(void)
1129 HRESULT hr;
1130 HWND wnd;
1131 IDirect3D9 *d3d;
1132 IDirect3DDevice9 *device, *test_device;
1133 D3DPRESENT_PARAMETERS d3dpp;
1134 ID3DXMesh *d3dxmesh;
1135 int i, size;
1136 D3DVERTEXELEMENT9 test_decl[MAX_FVF_DECL_SIZE];
1137 DWORD options;
1138 struct mesh mesh;
1140 static const D3DVERTEXELEMENT9 decl1[3] = {
1141 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1142 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
1143 D3DDECL_END(), };
1145 static const D3DVERTEXELEMENT9 decl2[] = {
1146 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1147 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
1148 {0, 24, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_PSIZE, 0},
1149 {0, 28, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 1},
1150 {0, 32, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
1151 /* 8 bytes padding */
1152 {0, 44, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
1153 D3DDECL_END(),
1156 static const D3DVERTEXELEMENT9 decl3[] = {
1157 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1158 {1, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
1159 D3DDECL_END(),
1162 hr = D3DXCreateMesh(0, 0, 0, NULL, NULL, NULL);
1163 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1165 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl1, NULL, &d3dxmesh);
1166 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1168 wnd = CreateWindow("static", "d3dx9_test", 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL);
1169 if (!wnd)
1171 skip("Couldn't create application window\n");
1172 return;
1174 d3d = Direct3DCreate9(D3D_SDK_VERSION);
1175 if (!d3d)
1177 skip("Couldn't create IDirect3D9 object\n");
1178 DestroyWindow(wnd);
1179 return;
1182 ZeroMemory(&d3dpp, sizeof(d3dpp));
1183 d3dpp.Windowed = TRUE;
1184 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1185 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, wnd, D3DCREATE_MIXED_VERTEXPROCESSING, &d3dpp, &device);
1186 if (FAILED(hr))
1188 skip("Failed to create IDirect3DDevice9 object %#x\n", hr);
1189 IDirect3D9_Release(d3d);
1190 DestroyWindow(wnd);
1191 return;
1194 hr = D3DXCreateMesh(0, 3, D3DXMESH_MANAGED, decl1, device, &d3dxmesh);
1195 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1197 hr = D3DXCreateMesh(1, 0, D3DXMESH_MANAGED, decl1, device, &d3dxmesh);
1198 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1200 hr = D3DXCreateMesh(1, 3, 0, decl1, device, &d3dxmesh);
1201 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
1203 if (hr == D3D_OK)
1205 d3dxmesh->lpVtbl->Release(d3dxmesh);
1208 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, 0, device, &d3dxmesh);
1209 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1211 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl1, device, NULL);
1212 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1214 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl1, device, &d3dxmesh);
1215 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
1217 if (hr == D3D_OK)
1219 /* device */
1220 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, NULL);
1221 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1223 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, &test_device);
1224 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
1225 ok(test_device == device, "Got result %p, expected %p\n", test_device, device);
1227 if (hr == D3D_OK)
1229 IDirect3DDevice9_Release(device);
1232 /* declaration */
1233 hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, NULL);
1234 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1236 hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, test_decl);
1237 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
1239 if (hr == D3D_OK)
1241 size = sizeof(decl1) / sizeof(decl1[0]);
1242 for (i = 0; i < size - 1; i++)
1244 ok(test_decl[i].Stream == decl1[i].Stream, "Returned stream %d, expected %d\n", test_decl[i].Stream, decl1[i].Stream);
1245 ok(test_decl[i].Type == decl1[i].Type, "Returned type %d, expected %d\n", test_decl[i].Type, decl1[i].Type);
1246 ok(test_decl[i].Method == decl1[i].Method, "Returned method %d, expected %d\n", test_decl[i].Method, decl1[i].Method);
1247 ok(test_decl[i].Usage == decl1[i].Usage, "Returned usage %d, expected %d\n", test_decl[i].Usage, decl1[i].Usage);
1248 ok(test_decl[i].UsageIndex == decl1[i].UsageIndex, "Returned usage index %d, expected %d\n", test_decl[i].UsageIndex, decl1[i].UsageIndex);
1249 ok(test_decl[i].Offset == decl1[i].Offset, "Returned offset %d, expected %d\n", test_decl[i].Offset, decl1[i].Offset);
1251 ok(decl1[size-1].Stream == 0xFF, "Returned too long vertex declaration\n"); /* end element */
1254 /* options */
1255 options = d3dxmesh->lpVtbl->GetOptions(d3dxmesh);
1256 ok(options == D3DXMESH_MANAGED, "Got result %x, expected %x (D3DXMESH_MANAGED)\n", options, D3DXMESH_MANAGED);
1258 /* rest */
1259 if (!new_mesh(&mesh, 3, 1))
1261 skip("Couldn't create mesh\n");
1263 else
1265 memset(mesh.vertices, 0, mesh.number_of_vertices * sizeof(*mesh.vertices));
1266 memset(mesh.faces, 0, mesh.number_of_faces * sizeof(*mesh.faces));
1267 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
1269 compare_mesh("createmesh1", d3dxmesh, &mesh);
1271 free_mesh(&mesh);
1274 d3dxmesh->lpVtbl->Release(d3dxmesh);
1277 /* Test a declaration that can't be converted to an FVF. */
1278 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl2, device, &d3dxmesh);
1279 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
1281 if (hr == D3D_OK)
1283 /* device */
1284 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, NULL);
1285 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1287 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, &test_device);
1288 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
1289 ok(test_device == device, "Got result %p, expected %p\n", test_device, device);
1291 if (hr == D3D_OK)
1293 IDirect3DDevice9_Release(device);
1296 /* declaration */
1297 hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, test_decl);
1298 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
1300 if (hr == D3D_OK)
1302 size = sizeof(decl2) / sizeof(decl2[0]);
1303 for (i = 0; i < size - 1; i++)
1305 ok(test_decl[i].Stream == decl2[i].Stream, "Returned stream %d, expected %d\n", test_decl[i].Stream, decl2[i].Stream);
1306 ok(test_decl[i].Type == decl2[i].Type, "Returned type %d, expected %d\n", test_decl[i].Type, decl2[i].Type);
1307 ok(test_decl[i].Method == decl2[i].Method, "Returned method %d, expected %d\n", test_decl[i].Method, decl2[i].Method);
1308 ok(test_decl[i].Usage == decl2[i].Usage, "Returned usage %d, expected %d\n", test_decl[i].Usage, decl2[i].Usage);
1309 ok(test_decl[i].UsageIndex == decl2[i].UsageIndex, "Returned usage index %d, expected %d\n", test_decl[i].UsageIndex, decl2[i].UsageIndex);
1310 ok(test_decl[i].Offset == decl2[i].Offset, "Returned offset %d, expected %d\n", test_decl[i].Offset, decl2[i].Offset);
1312 ok(decl2[size-1].Stream == 0xFF, "Returned too long vertex declaration\n"); /* end element */
1315 /* options */
1316 options = d3dxmesh->lpVtbl->GetOptions(d3dxmesh);
1317 ok(options == D3DXMESH_MANAGED, "Got result %x, expected %x (D3DXMESH_MANAGED)\n", options, D3DXMESH_MANAGED);
1319 /* rest */
1320 if (!new_mesh(&mesh, 3, 1))
1322 skip("Couldn't create mesh\n");
1324 else
1326 memset(mesh.vertices, 0, mesh.number_of_vertices * sizeof(*mesh.vertices));
1327 memset(mesh.faces, 0, mesh.number_of_faces * sizeof(*mesh.faces));
1328 mesh.fvf = 0;
1329 mesh.vertex_size = 60;
1331 compare_mesh("createmesh2", d3dxmesh, &mesh);
1333 free_mesh(&mesh);
1336 mesh.vertex_size = d3dxmesh->lpVtbl->GetNumBytesPerVertex(d3dxmesh);
1337 ok(mesh.vertex_size == 60, "Got vertex size %u, expected %u\n", mesh.vertex_size, 60);
1339 d3dxmesh->lpVtbl->Release(d3dxmesh);
1342 /* Test a declaration with multiple streams. */
1343 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl3, device, &d3dxmesh);
1344 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1346 IDirect3DDevice9_Release(device);
1347 IDirect3D9_Release(d3d);
1348 DestroyWindow(wnd);
1351 static void D3DXCreateMeshFVFTest(void)
1353 HRESULT hr;
1354 HWND wnd;
1355 IDirect3D9 *d3d;
1356 IDirect3DDevice9 *device, *test_device;
1357 D3DPRESENT_PARAMETERS d3dpp;
1358 ID3DXMesh *d3dxmesh;
1359 int i, size;
1360 D3DVERTEXELEMENT9 test_decl[MAX_FVF_DECL_SIZE];
1361 DWORD options;
1362 struct mesh mesh;
1364 static const D3DVERTEXELEMENT9 decl[3] = {
1365 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1366 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
1367 D3DDECL_END(), };
1369 hr = D3DXCreateMeshFVF(0, 0, 0, 0, NULL, NULL);
1370 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1372 hr = D3DXCreateMeshFVF(1, 3, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, NULL, &d3dxmesh);
1373 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1375 wnd = CreateWindow("static", "d3dx9_test", 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL);
1376 if (!wnd)
1378 skip("Couldn't create application window\n");
1379 return;
1381 d3d = Direct3DCreate9(D3D_SDK_VERSION);
1382 if (!d3d)
1384 skip("Couldn't create IDirect3D9 object\n");
1385 DestroyWindow(wnd);
1386 return;
1389 ZeroMemory(&d3dpp, sizeof(d3dpp));
1390 d3dpp.Windowed = TRUE;
1391 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1392 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, wnd, D3DCREATE_MIXED_VERTEXPROCESSING, &d3dpp, &device);
1393 if (FAILED(hr))
1395 skip("Failed to create IDirect3DDevice9 object %#x\n", hr);
1396 IDirect3D9_Release(d3d);
1397 DestroyWindow(wnd);
1398 return;
1401 hr = D3DXCreateMeshFVF(0, 3, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, device, &d3dxmesh);
1402 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1404 hr = D3DXCreateMeshFVF(1, 0, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, device, &d3dxmesh);
1405 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1407 hr = D3DXCreateMeshFVF(1, 3, 0, D3DFVF_XYZ | D3DFVF_NORMAL, device, &d3dxmesh);
1408 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
1410 if (hr == D3D_OK)
1412 d3dxmesh->lpVtbl->Release(d3dxmesh);
1415 hr = D3DXCreateMeshFVF(1, 3, D3DXMESH_MANAGED, 0xdeadbeef, device, &d3dxmesh);
1416 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1418 hr = D3DXCreateMeshFVF(1, 3, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, device, NULL);
1419 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1421 hr = D3DXCreateMeshFVF(1, 3, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, device, &d3dxmesh);
1422 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
1424 if (hr == D3D_OK)
1426 /* device */
1427 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, NULL);
1428 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1430 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, &test_device);
1431 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
1432 ok(test_device == device, "Got result %p, expected %p\n", test_device, device);
1434 if (hr == D3D_OK)
1436 IDirect3DDevice9_Release(device);
1439 /* declaration */
1440 hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, NULL);
1441 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1443 hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, test_decl);
1444 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
1446 if (hr == D3D_OK)
1448 size = sizeof(decl) / sizeof(decl[0]);
1449 for (i = 0; i < size - 1; i++)
1451 ok(test_decl[i].Stream == decl[i].Stream, "Returned stream %d, expected %d\n", test_decl[i].Stream, decl[i].Stream);
1452 ok(test_decl[i].Type == decl[i].Type, "Returned type %d, expected %d\n", test_decl[i].Type, decl[i].Type);
1453 ok(test_decl[i].Method == decl[i].Method, "Returned method %d, expected %d\n", test_decl[i].Method, decl[i].Method);
1454 ok(test_decl[i].Usage == decl[i].Usage, "Returned usage %d, expected %d\n", test_decl[i].Usage, decl[i].Usage);
1455 ok(test_decl[i].UsageIndex == decl[i].UsageIndex, "Returned usage index %d, expected %d\n",
1456 test_decl[i].UsageIndex, decl[i].UsageIndex);
1457 ok(test_decl[i].Offset == decl[i].Offset, "Returned offset %d, expected %d\n", test_decl[i].Offset, decl[i].Offset);
1459 ok(decl[size-1].Stream == 0xFF, "Returned too long vertex declaration\n"); /* end element */
1462 /* options */
1463 options = d3dxmesh->lpVtbl->GetOptions(d3dxmesh);
1464 ok(options == D3DXMESH_MANAGED, "Got result %x, expected %x (D3DXMESH_MANAGED)\n", options, D3DXMESH_MANAGED);
1466 /* rest */
1467 if (!new_mesh(&mesh, 3, 1))
1469 skip("Couldn't create mesh\n");
1471 else
1473 memset(mesh.vertices, 0, mesh.number_of_vertices * sizeof(*mesh.vertices));
1474 memset(mesh.faces, 0, mesh.number_of_faces * sizeof(*mesh.faces));
1475 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
1477 compare_mesh("createmeshfvf", d3dxmesh, &mesh);
1479 free_mesh(&mesh);
1482 d3dxmesh->lpVtbl->Release(d3dxmesh);
1485 IDirect3DDevice9_Release(device);
1486 IDirect3D9_Release(d3d);
1487 DestroyWindow(wnd);
1490 #define check_vertex_buffer(mesh, vertices, num_vertices, fvf) \
1491 check_vertex_buffer_(__LINE__, mesh, vertices, num_vertices, fvf)
1492 static void check_vertex_buffer_(int line, ID3DXMesh *mesh, const void *vertices, DWORD num_vertices, DWORD fvf)
1494 DWORD mesh_num_vertices = mesh->lpVtbl->GetNumVertices(mesh);
1495 DWORD mesh_fvf = mesh->lpVtbl->GetFVF(mesh);
1496 const void *mesh_vertices;
1497 HRESULT hr;
1499 ok_(__FILE__,line)(fvf == mesh_fvf, "expected FVF %x, got %x\n", fvf, mesh_fvf);
1500 ok_(__FILE__,line)(num_vertices == mesh_num_vertices,
1501 "Expected %u vertices, got %u\n", num_vertices, mesh_num_vertices);
1503 hr = mesh->lpVtbl->LockVertexBuffer(mesh, D3DLOCK_READONLY, (void**)&mesh_vertices);
1504 ok_(__FILE__,line)(hr == D3D_OK, "LockVertexBuffer returned %x, expected %x (D3D_OK)\n", hr, D3D_OK);
1505 if (FAILED(hr))
1506 return;
1508 if (mesh_fvf == fvf) {
1509 DWORD vertex_size = D3DXGetFVFVertexSize(fvf);
1510 int i;
1511 for (i = 0; i < min(num_vertices, mesh_num_vertices); i++)
1513 const FLOAT *exp_float = vertices;
1514 const FLOAT *got_float = mesh_vertices;
1515 DWORD texcount;
1516 DWORD pos_dim = 0;
1517 int j;
1518 BOOL last_beta_dword = FALSE;
1519 char prefix[128];
1521 switch (fvf & D3DFVF_POSITION_MASK) {
1522 case D3DFVF_XYZ: pos_dim = 3; break;
1523 case D3DFVF_XYZRHW: pos_dim = 4; break;
1524 case D3DFVF_XYZB1:
1525 case D3DFVF_XYZB2:
1526 case D3DFVF_XYZB3:
1527 case D3DFVF_XYZB4:
1528 case D3DFVF_XYZB5:
1529 pos_dim = (fvf & D3DFVF_POSITION_MASK) - D3DFVF_XYZB1 + 1;
1530 if (fvf & (D3DFVF_LASTBETA_UBYTE4 | D3DFVF_LASTBETA_D3DCOLOR))
1532 pos_dim--;
1533 last_beta_dword = TRUE;
1535 break;
1536 case D3DFVF_XYZW: pos_dim = 4; break;
1538 sprintf(prefix, "vertex[%u] position, ", i);
1539 check_floats_(line, prefix, got_float, exp_float, pos_dim);
1540 exp_float += pos_dim;
1541 got_float += pos_dim;
1543 if (last_beta_dword) {
1544 ok_(__FILE__,line)(*(DWORD*)exp_float == *(DWORD*)got_float,
1545 "Vertex[%u]: Expected last beta %08x, got %08x\n", i, *(DWORD*)exp_float, *(DWORD*)got_float);
1546 exp_float++;
1547 got_float++;
1550 if (fvf & D3DFVF_NORMAL) {
1551 sprintf(prefix, "vertex[%u] normal, ", i);
1552 check_floats_(line, prefix, got_float, exp_float, 3);
1553 exp_float += 3;
1554 got_float += 3;
1556 if (fvf & D3DFVF_PSIZE) {
1557 ok_(__FILE__,line)(compare(*exp_float, *got_float),
1558 "Vertex[%u]: Expected psize %g, got %g\n", i, *exp_float, *got_float);
1559 exp_float++;
1560 got_float++;
1562 if (fvf & D3DFVF_DIFFUSE) {
1563 ok_(__FILE__,line)(*(DWORD*)exp_float == *(DWORD*)got_float,
1564 "Vertex[%u]: Expected diffuse %08x, got %08x\n", i, *(DWORD*)exp_float, *(DWORD*)got_float);
1565 exp_float++;
1566 got_float++;
1568 if (fvf & D3DFVF_SPECULAR) {
1569 ok_(__FILE__,line)(*(DWORD*)exp_float == *(DWORD*)got_float,
1570 "Vertex[%u]: Expected specular %08x, got %08x\n", i, *(DWORD*)exp_float, *(DWORD*)got_float);
1571 exp_float++;
1572 got_float++;
1575 texcount = (fvf & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
1576 for (j = 0; j < texcount; j++) {
1577 DWORD dim = (((fvf >> (16 + 2 * j)) + 1) & 0x03) + 1;
1578 sprintf(prefix, "vertex[%u] texture, ", i);
1579 check_floats_(line, prefix, got_float, exp_float, dim);
1580 exp_float += dim;
1581 got_float += dim;
1584 vertices = (BYTE*)vertices + vertex_size;
1585 mesh_vertices = (BYTE*)mesh_vertices + vertex_size;
1589 mesh->lpVtbl->UnlockVertexBuffer(mesh);
1592 #define check_index_buffer(mesh, indices, num_indices, index_size) \
1593 check_index_buffer_(__LINE__, mesh, indices, num_indices, index_size)
1594 static void check_index_buffer_(int line, ID3DXMesh *mesh, const void *indices, DWORD num_indices, DWORD index_size)
1596 DWORD mesh_index_size = (mesh->lpVtbl->GetOptions(mesh) & D3DXMESH_32BIT) ? 4 : 2;
1597 DWORD mesh_num_indices = mesh->lpVtbl->GetNumFaces(mesh) * 3;
1598 const void *mesh_indices;
1599 HRESULT hr;
1600 DWORD i;
1602 ok_(__FILE__,line)(index_size == mesh_index_size,
1603 "Expected index size %u, got %u\n", index_size, mesh_index_size);
1604 ok_(__FILE__,line)(num_indices == mesh_num_indices,
1605 "Expected %u indices, got %u\n", num_indices, mesh_num_indices);
1607 hr = mesh->lpVtbl->LockIndexBuffer(mesh, D3DLOCK_READONLY, (void**)&mesh_indices);
1608 ok_(__FILE__,line)(hr == D3D_OK, "LockIndexBuffer returned %x, expected %x (D3D_OK)\n", hr, D3D_OK);
1609 if (FAILED(hr))
1610 return;
1612 if (mesh_index_size == index_size) {
1613 for (i = 0; i < min(num_indices, mesh_num_indices); i++)
1615 if (index_size == 4)
1616 ok_(__FILE__,line)(*(DWORD*)indices == *(DWORD*)mesh_indices,
1617 "Index[%u]: expected %u, got %u\n", i, *(DWORD*)indices, *(DWORD*)mesh_indices);
1618 else
1619 ok_(__FILE__,line)(*(WORD*)indices == *(WORD*)mesh_indices,
1620 "Index[%u]: expected %u, got %u\n", i, *(WORD*)indices, *(WORD*)mesh_indices);
1621 indices = (BYTE*)indices + index_size;
1622 mesh_indices = (BYTE*)mesh_indices + index_size;
1625 mesh->lpVtbl->UnlockIndexBuffer(mesh);
1628 #define check_matrix(got, expected) check_matrix_(__LINE__, got, expected)
1629 static void check_matrix_(int line, const D3DXMATRIX *got, const D3DXMATRIX *expected)
1631 int i, j;
1632 for (i = 0; i < 4; i++) {
1633 for (j = 0; j < 4; j++) {
1634 ok_(__FILE__,line)(compare(U(*expected).m[i][j], U(*got).m[i][j]),
1635 "matrix[%u][%u]: expected %g, got %g\n",
1636 i, j, U(*expected).m[i][j], U(*got).m[i][j]);
1641 static void check_colorvalue_(int line, const char *prefix, const D3DCOLORVALUE got, const D3DCOLORVALUE expected)
1643 ok_(__FILE__,line)(expected.r == got.r && expected.g == got.g && expected.b == got.b && expected.a == got.a,
1644 "%sExpected (%g, %g, %g, %g), got (%g, %g, %g, %g)\n", prefix,
1645 expected.r, expected.g, expected.b, expected.a, got.r, got.g, got.b, got.a);
1648 #define check_materials(got, got_count, expected, expected_count) \
1649 check_materials_(__LINE__, got, got_count, expected, expected_count)
1650 static void check_materials_(int line, const D3DXMATERIAL *got, DWORD got_count, const D3DXMATERIAL *expected, DWORD expected_count)
1652 int i;
1653 ok_(__FILE__,line)(expected_count == got_count, "Expected %u materials, got %u\n", expected_count, got_count);
1654 if (!expected) {
1655 ok_(__FILE__,line)(got == NULL, "Expected NULL material ptr, got %p\n", got);
1656 return;
1658 for (i = 0; i < min(expected_count, got_count); i++)
1660 if (!expected[i].pTextureFilename)
1661 ok_(__FILE__,line)(got[i].pTextureFilename == NULL,
1662 "Expected NULL pTextureFilename, got %p\n", got[i].pTextureFilename);
1663 else
1664 ok_(__FILE__,line)(!strcmp(expected[i].pTextureFilename, got[i].pTextureFilename),
1665 "Expected '%s' for pTextureFilename, got '%s'\n", expected[i].pTextureFilename, got[i].pTextureFilename);
1666 check_colorvalue_(line, "Diffuse: ", got[i].MatD3D.Diffuse, expected[i].MatD3D.Diffuse);
1667 check_colorvalue_(line, "Ambient: ", got[i].MatD3D.Ambient, expected[i].MatD3D.Ambient);
1668 check_colorvalue_(line, "Specular: ", got[i].MatD3D.Specular, expected[i].MatD3D.Specular);
1669 check_colorvalue_(line, "Emissive: ", got[i].MatD3D.Emissive, expected[i].MatD3D.Emissive);
1670 ok_(__FILE__,line)(expected[i].MatD3D.Power == got[i].MatD3D.Power,
1671 "Power: Expected %g, got %g\n", expected[i].MatD3D.Power, got[i].MatD3D.Power);
1675 #define check_generated_adjacency(mesh, got, epsilon) check_generated_adjacency_(__LINE__, mesh, got, epsilon)
1676 static void check_generated_adjacency_(int line, ID3DXMesh *mesh, const DWORD *got, FLOAT epsilon)
1678 DWORD *expected;
1679 DWORD num_faces = mesh->lpVtbl->GetNumFaces(mesh);
1680 HRESULT hr;
1682 expected = HeapAlloc(GetProcessHeap(), 0, num_faces * sizeof(DWORD) * 3);
1683 if (!expected) {
1684 skip_(__FILE__, line)("Out of memory\n");
1685 return;
1687 hr = mesh->lpVtbl->GenerateAdjacency(mesh, epsilon, expected);
1688 ok_(__FILE__, line)(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
1689 if (SUCCEEDED(hr))
1691 int i;
1692 for (i = 0; i < num_faces; i++)
1694 ok_(__FILE__, line)(expected[i * 3] == got[i * 3] &&
1695 expected[i * 3 + 1] == got[i * 3 + 1] &&
1696 expected[i * 3 + 2] == got[i * 3 + 2],
1697 "Face %u adjacencies: Expected (%u, %u, %u), got (%u, %u, %u)\n", i,
1698 expected[i * 3], expected[i * 3 + 1], expected[i * 3 + 2],
1699 got[i * 3], got[i * 3 + 1], got[i * 3 + 2]);
1702 HeapFree(GetProcessHeap(), 0, expected);
1705 #define check_generated_effects(materials, num_materials, effects) \
1706 check_generated_effects_(__LINE__, materials, num_materials, effects)
1707 static void check_generated_effects_(int line, const D3DXMATERIAL *materials, DWORD num_materials, const D3DXEFFECTINSTANCE *effects)
1709 int i;
1710 static const struct {
1711 const char *name;
1712 DWORD name_size;
1713 DWORD num_bytes;
1714 DWORD value_offset;
1715 } params[] = {
1716 #define EFFECT_TABLE_ENTRY(str, field) \
1717 {str, sizeof(str), sizeof(materials->MatD3D.field), offsetof(D3DXMATERIAL, MatD3D.field)}
1718 EFFECT_TABLE_ENTRY("Diffuse", Diffuse),
1719 EFFECT_TABLE_ENTRY("Power", Power),
1720 EFFECT_TABLE_ENTRY("Specular", Specular),
1721 EFFECT_TABLE_ENTRY("Emissive", Emissive),
1722 EFFECT_TABLE_ENTRY("Ambient", Ambient),
1723 #undef EFFECT_TABLE_ENTRY
1726 if (!num_materials) {
1727 ok_(__FILE__, line)(effects == NULL, "Expected NULL effects, got %p\n", effects);
1728 return;
1730 for (i = 0; i < num_materials; i++)
1732 int j;
1733 DWORD expected_num_defaults = ARRAY_SIZE(params) + (materials[i].pTextureFilename ? 1 : 0);
1735 ok_(__FILE__,line)(expected_num_defaults == effects[i].NumDefaults,
1736 "effect[%u] NumDefaults: Expected %u, got %u\n", i,
1737 expected_num_defaults, effects[i].NumDefaults);
1738 for (j = 0; j < min(ARRAY_SIZE(params), effects[i].NumDefaults); j++)
1740 int k;
1741 D3DXEFFECTDEFAULT *got_param = &effects[i].pDefaults[j];
1742 ok_(__FILE__,line)(!strcmp(params[j].name, got_param->pParamName),
1743 "effect[%u].pDefaults[%u].pParamName: Expected '%s', got '%s'\n", i, j,
1744 params[j].name, got_param->pParamName);
1745 ok_(__FILE__,line)(D3DXEDT_FLOATS == got_param->Type,
1746 "effect[%u].pDefaults[%u].Type: Expected %u, got %u\n", i, j,
1747 D3DXEDT_FLOATS, got_param->Type);
1748 ok_(__FILE__,line)(params[j].num_bytes == got_param->NumBytes,
1749 "effect[%u].pDefaults[%u].NumBytes: Expected %u, got %u\n", i, j,
1750 params[j].num_bytes, got_param->NumBytes);
1751 for (k = 0; k < min(params[j].num_bytes, got_param->NumBytes) / 4; k++)
1753 FLOAT expected = ((FLOAT*)((BYTE*)&materials[i] + params[j].value_offset))[k];
1754 FLOAT got = ((FLOAT*)got_param->pValue)[k];
1755 ok_(__FILE__,line)(compare(expected, got),
1756 "effect[%u].pDefaults[%u] float value %u: Expected %g, got %g\n", i, j, k, expected, got);
1759 if (effects[i].NumDefaults > ARRAY_SIZE(params)) {
1760 D3DXEFFECTDEFAULT *got_param = &effects[i].pDefaults[j];
1761 static const char *expected_name = "Texture0@Name";
1763 ok_(__FILE__,line)(!strcmp(expected_name, got_param->pParamName),
1764 "effect[%u].pDefaults[%u].pParamName: Expected '%s', got '%s'\n", i, j,
1765 expected_name, got_param->pParamName);
1766 ok_(__FILE__,line)(D3DXEDT_STRING == got_param->Type,
1767 "effect[%u].pDefaults[%u].Type: Expected %u, got %u\n", i, j,
1768 D3DXEDT_STRING, got_param->Type);
1769 if (materials[i].pTextureFilename) {
1770 ok_(__FILE__,line)(strlen(materials[i].pTextureFilename) + 1 == got_param->NumBytes,
1771 "effect[%u] texture filename length: Expected %u, got %u\n", i,
1772 (DWORD)strlen(materials[i].pTextureFilename) + 1, got_param->NumBytes);
1773 ok_(__FILE__,line)(!strcmp(materials[i].pTextureFilename, got_param->pValue),
1774 "effect[%u] texture filename: Expected '%s', got '%s'\n", i,
1775 materials[i].pTextureFilename, (char*)got_param->pValue);
1781 static LPSTR strdupA(LPCSTR p)
1783 LPSTR ret;
1784 if (!p) return NULL;
1785 ret = HeapAlloc(GetProcessHeap(), 0, strlen(p) + 1);
1786 if (ret) strcpy(ret, p);
1787 return ret;
1790 static CALLBACK HRESULT ID3DXAllocateHierarchyImpl_DestroyFrame(ID3DXAllocateHierarchy *iface, LPD3DXFRAME frame)
1792 TRACECALLBACK("ID3DXAllocateHierarchyImpl_DestroyFrame(%p, %p)\n", iface, frame);
1793 if (frame) {
1794 HeapFree(GetProcessHeap(), 0, frame->Name);
1795 HeapFree(GetProcessHeap(), 0, frame);
1797 return D3D_OK;
1800 static CALLBACK HRESULT ID3DXAllocateHierarchyImpl_CreateFrame(ID3DXAllocateHierarchy *iface, LPCSTR name, LPD3DXFRAME *new_frame)
1802 LPD3DXFRAME frame;
1804 TRACECALLBACK("ID3DXAllocateHierarchyImpl_CreateFrame(%p, '%s', %p)\n", iface, name, new_frame);
1805 frame = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*frame));
1806 if (!frame)
1807 return E_OUTOFMEMORY;
1808 if (name) {
1809 frame->Name = strdupA(name);
1810 if (!frame->Name) {
1811 HeapFree(GetProcessHeap(), 0, frame);
1812 return E_OUTOFMEMORY;
1815 *new_frame = frame;
1816 return D3D_OK;
1819 static HRESULT destroy_mesh_container(LPD3DXMESHCONTAINER mesh_container)
1821 int i;
1823 if (!mesh_container)
1824 return D3D_OK;
1825 HeapFree(GetProcessHeap(), 0, mesh_container->Name);
1826 if (U(mesh_container->MeshData).pMesh)
1827 IUnknown_Release(U(mesh_container->MeshData).pMesh);
1828 if (mesh_container->pMaterials) {
1829 for (i = 0; i < mesh_container->NumMaterials; i++)
1830 HeapFree(GetProcessHeap(), 0, mesh_container->pMaterials[i].pTextureFilename);
1831 HeapFree(GetProcessHeap(), 0, mesh_container->pMaterials);
1833 if (mesh_container->pEffects) {
1834 for (i = 0; i < mesh_container->NumMaterials; i++) {
1835 HeapFree(GetProcessHeap(), 0, mesh_container->pEffects[i].pEffectFilename);
1836 if (mesh_container->pEffects[i].pDefaults) {
1837 int j;
1838 for (j = 0; j < mesh_container->pEffects[i].NumDefaults; j++) {
1839 HeapFree(GetProcessHeap(), 0, mesh_container->pEffects[i].pDefaults[j].pParamName);
1840 HeapFree(GetProcessHeap(), 0, mesh_container->pEffects[i].pDefaults[j].pValue);
1842 HeapFree(GetProcessHeap(), 0, mesh_container->pEffects[i].pDefaults);
1845 HeapFree(GetProcessHeap(), 0, mesh_container->pEffects);
1847 HeapFree(GetProcessHeap(), 0, mesh_container->pAdjacency);
1848 if (mesh_container->pSkinInfo)
1849 IUnknown_Release(mesh_container->pSkinInfo);
1850 HeapFree(GetProcessHeap(), 0, mesh_container);
1851 return D3D_OK;
1854 static CALLBACK HRESULT ID3DXAllocateHierarchyImpl_DestroyMeshContainer(ID3DXAllocateHierarchy *iface, LPD3DXMESHCONTAINER mesh_container)
1856 TRACECALLBACK("ID3DXAllocateHierarchyImpl_DestroyMeshContainer(%p, %p)\n", iface, mesh_container);
1857 return destroy_mesh_container(mesh_container);
1860 static CALLBACK HRESULT ID3DXAllocateHierarchyImpl_CreateMeshContainer(ID3DXAllocateHierarchy *iface,
1861 LPCSTR name, CONST D3DXMESHDATA *mesh_data, CONST D3DXMATERIAL *materials,
1862 CONST D3DXEFFECTINSTANCE *effects, DWORD num_materials, CONST DWORD *adjacency,
1863 LPD3DXSKININFO skin_info, LPD3DXMESHCONTAINER *new_mesh_container)
1865 LPD3DXMESHCONTAINER mesh_container = NULL;
1866 int i;
1868 TRACECALLBACK("ID3DXAllocateHierarchyImpl_CreateMeshContainer(%p, '%s', %u, %p, %p, %p, %d, %p, %p, %p)\n",
1869 iface, name, mesh_data->Type, U(*mesh_data).pMesh, materials, effects,
1870 num_materials, adjacency, skin_info, *new_mesh_container);
1872 mesh_container = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*mesh_container));
1873 if (!mesh_container)
1874 return E_OUTOFMEMORY;
1876 if (name) {
1877 mesh_container->Name = strdupA(name);
1878 if (!mesh_container->Name)
1879 goto error;
1882 mesh_container->NumMaterials = num_materials;
1883 if (num_materials) {
1884 mesh_container->pMaterials = HeapAlloc(GetProcessHeap(), 0, num_materials * sizeof(*materials));
1885 if (!mesh_container->pMaterials)
1886 goto error;
1888 memcpy(mesh_container->pMaterials, materials, num_materials * sizeof(*materials));
1889 for (i = 0; i < num_materials; i++)
1890 mesh_container->pMaterials[i].pTextureFilename = NULL;
1891 for (i = 0; i < num_materials; i++) {
1892 if (materials[i].pTextureFilename) {
1893 mesh_container->pMaterials[i].pTextureFilename = strdupA(materials[i].pTextureFilename);
1894 if (!mesh_container->pMaterials[i].pTextureFilename)
1895 goto error;
1899 mesh_container->pEffects = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, num_materials * sizeof(*effects));
1900 if (!mesh_container->pEffects)
1901 goto error;
1902 for (i = 0; i < num_materials; i++) {
1903 int j;
1904 const D3DXEFFECTINSTANCE *effect_src = &effects[i];
1905 D3DXEFFECTINSTANCE *effect_dest = &mesh_container->pEffects[i];
1907 if (effect_src->pEffectFilename) {
1908 effect_dest->pEffectFilename = strdupA(effect_src->pEffectFilename);
1909 if (!effect_dest->pEffectFilename)
1910 goto error;
1912 effect_dest->pDefaults = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1913 effect_src->NumDefaults * sizeof(*effect_src->pDefaults));
1914 if (!effect_dest->pDefaults)
1915 goto error;
1916 effect_dest->NumDefaults = effect_src->NumDefaults;
1917 for (j = 0; j < effect_src->NumDefaults; j++) {
1918 const D3DXEFFECTDEFAULT *default_src = &effect_src->pDefaults[j];
1919 D3DXEFFECTDEFAULT *default_dest = &effect_dest->pDefaults[j];
1921 if (default_src->pParamName) {
1922 default_dest->pParamName = strdupA(default_src->pParamName);
1923 if (!default_dest->pParamName)
1924 goto error;
1926 default_dest->NumBytes = default_src->NumBytes;
1927 default_dest->Type = default_src->Type;
1928 default_dest->pValue = HeapAlloc(GetProcessHeap(), 0, default_src->NumBytes);
1929 memcpy(default_dest->pValue, default_src->pValue, default_src->NumBytes);
1934 ok(adjacency != NULL, "Expected non-NULL adjacency, got NULL\n");
1935 if (adjacency) {
1936 if (mesh_data->Type == D3DXMESHTYPE_MESH || mesh_data->Type == D3DXMESHTYPE_PMESH) {
1937 ID3DXBaseMesh *basemesh = (ID3DXBaseMesh*)U(*mesh_data).pMesh;
1938 DWORD num_faces = basemesh->lpVtbl->GetNumFaces(basemesh);
1939 size_t size = num_faces * sizeof(DWORD) * 3;
1940 mesh_container->pAdjacency = HeapAlloc(GetProcessHeap(), 0, size);
1941 if (!mesh_container->pAdjacency)
1942 goto error;
1943 memcpy(mesh_container->pAdjacency, adjacency, size);
1944 } else {
1945 ok(mesh_data->Type == D3DXMESHTYPE_PATCHMESH, "Unknown mesh type %u\n", mesh_data->Type);
1946 if (mesh_data->Type == D3DXMESHTYPE_PATCHMESH)
1947 trace("FIXME: copying adjacency data for patch mesh not implemented\n");
1951 memcpy(&mesh_container->MeshData, mesh_data, sizeof(*mesh_data));
1952 if (U(*mesh_data).pMesh)
1953 IUnknown_AddRef(U(*mesh_data).pMesh);
1954 if (skin_info) {
1955 mesh_container->pSkinInfo = skin_info;
1956 skin_info->lpVtbl->AddRef(skin_info);
1958 *new_mesh_container = mesh_container;
1960 return S_OK;
1961 error:
1962 destroy_mesh_container(mesh_container);
1963 return E_OUTOFMEMORY;
1966 static ID3DXAllocateHierarchyVtbl ID3DXAllocateHierarchyImpl_Vtbl = {
1967 ID3DXAllocateHierarchyImpl_CreateFrame,
1968 ID3DXAllocateHierarchyImpl_CreateMeshContainer,
1969 ID3DXAllocateHierarchyImpl_DestroyFrame,
1970 ID3DXAllocateHierarchyImpl_DestroyMeshContainer,
1972 static ID3DXAllocateHierarchy alloc_hier = { &ID3DXAllocateHierarchyImpl_Vtbl };
1974 #define test_LoadMeshFromX(device, xfile_str, vertex_array, fvf, index_array, materials_array, check_adjacency) \
1975 test_LoadMeshFromX_(__LINE__, device, xfile_str, sizeof(xfile_str) - 1, vertex_array, ARRAY_SIZE(vertex_array), fvf, \
1976 index_array, ARRAY_SIZE(index_array), sizeof(*index_array), materials_array, ARRAY_SIZE(materials_array), \
1977 check_adjacency);
1978 static void test_LoadMeshFromX_(int line, IDirect3DDevice9 *device, const char *xfile_str, size_t xfile_strlen,
1979 const void *vertices, DWORD num_vertices, DWORD fvf, const void *indices, DWORD num_indices, size_t index_size,
1980 const D3DXMATERIAL *expected_materials, DWORD expected_num_materials, BOOL check_adjacency)
1982 HRESULT hr;
1983 ID3DXBuffer *materials = NULL;
1984 ID3DXBuffer *effects = NULL;
1985 ID3DXBuffer *adjacency = NULL;
1986 ID3DXMesh *mesh = NULL;
1987 DWORD num_materials = 0;
1989 /* Adjacency is not checked when the X file contains multiple meshes,
1990 * since calling GenerateAdjacency on the merged mesh is not equivalent
1991 * to calling GenerateAdjacency on the individual meshes and then merging
1992 * the adjacency data. */
1993 hr = D3DXLoadMeshFromXInMemory(xfile_str, xfile_strlen, D3DXMESH_MANAGED, device,
1994 check_adjacency ? &adjacency : NULL, &materials, &effects, &num_materials, &mesh);
1995 ok_(__FILE__,line)(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
1996 if (SUCCEEDED(hr)) {
1997 D3DXMATERIAL *materials_ptr = materials ? ID3DXBuffer_GetBufferPointer(materials) : NULL;
1998 D3DXEFFECTINSTANCE *effects_ptr = effects ? ID3DXBuffer_GetBufferPointer(effects) : NULL;
1999 DWORD *adjacency_ptr = check_adjacency ? ID3DXBuffer_GetBufferPointer(adjacency) : NULL;
2001 check_vertex_buffer_(line, mesh, vertices, num_vertices, fvf);
2002 check_index_buffer_(line, mesh, indices, num_indices, index_size);
2003 check_materials_(line, materials_ptr, num_materials, expected_materials, expected_num_materials);
2004 check_generated_effects_(line, materials_ptr, num_materials, effects_ptr);
2005 if (check_adjacency)
2006 check_generated_adjacency_(line, mesh, adjacency_ptr, 0.0f);
2008 if (materials) ID3DXBuffer_Release(materials);
2009 if (effects) ID3DXBuffer_Release(effects);
2010 if (adjacency) ID3DXBuffer_Release(adjacency);
2011 IUnknown_Release(mesh);
2015 static void D3DXLoadMeshTest(void)
2017 static const char empty_xfile[] = "xof 0303txt 0032";
2018 /*________________________*/
2019 static const char simple_xfile[] =
2020 "xof 0303txt 0032"
2021 "Mesh {"
2022 "3;"
2023 "0.0; 0.0; 0.0;,"
2024 "0.0; 1.0; 0.0;,"
2025 "1.0; 1.0; 0.0;;"
2026 "1;"
2027 "3; 0, 1, 2;;"
2028 "}";
2029 static const WORD simple_index_buffer[] = {0, 1, 2};
2030 static const D3DXVECTOR3 simple_vertex_buffer[] = {
2031 {0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {1.0, 1.0, 0.0}
2033 const DWORD simple_fvf = D3DFVF_XYZ;
2034 static const char framed_xfile[] =
2035 "xof 0303txt 0032"
2036 "Frame {"
2037 "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;; }"
2038 "FrameTransformMatrix {" /* translation (0.0, 0.0, 2.0) */
2039 "1.0, 0.0, 0.0, 0.0,"
2040 "0.0, 1.0, 0.0, 0.0,"
2041 "0.0, 0.0, 1.0, 0.0,"
2042 "0.0, 0.0, 2.0, 1.0;;"
2044 "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;; }"
2045 "FrameTransformMatrix {" /* translation (0.0, 0.0, 3.0) */
2046 "1.0, 0.0, 0.0, 0.0,"
2047 "0.0, 1.0, 0.0, 0.0,"
2048 "0.0, 0.0, 1.0, 0.0,"
2049 "0.0, 0.0, 3.0, 1.0;;"
2051 "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;; }"
2052 "}";
2053 static const WORD framed_index_buffer[] = { 0, 1, 2 };
2054 static const D3DXVECTOR3 framed_vertex_buffers[3][3] = {
2055 {{0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {1.0, 1.0, 0.0}},
2056 {{0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {2.0, 1.0, 0.0}},
2057 {{0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {3.0, 1.0, 0.0}},
2059 static const WORD merged_index_buffer[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
2060 /* frame transforms accumulates for D3DXLoadMeshFromX */
2061 static const D3DXVECTOR3 merged_vertex_buffer[] = {
2062 {0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {1.0, 1.0, 0.0},
2063 {0.0, 0.0, 2.0}, {0.0, 1.0, 2.0}, {2.0, 1.0, 2.0},
2064 {0.0, 0.0, 5.0}, {0.0, 1.0, 5.0}, {3.0, 1.0, 5.0},
2066 const DWORD framed_fvf = D3DFVF_XYZ;
2067 /*________________________*/
2068 static const char box_xfile[] =
2069 "xof 0303txt 0032"
2070 "Mesh {"
2071 "8;" /* DWORD nVertices; */
2072 /* array Vector vertices[nVertices]; */
2073 "0.0; 0.0; 0.0;,"
2074 "0.0; 0.0; 1.0;,"
2075 "0.0; 1.0; 0.0;,"
2076 "0.0; 1.0; 1.0;,"
2077 "1.0; 0.0; 0.0;,"
2078 "1.0; 0.0; 1.0;,"
2079 "1.0; 1.0; 0.0;,"
2080 "1.0; 1.0; 1.0;;"
2081 "6;" /* DWORD nFaces; */
2082 /* array MeshFace faces[nFaces]; */
2083 "4; 0, 1, 3, 2;," /* (left side) */
2084 "4; 2, 3, 7, 6;," /* (top side) */
2085 "4; 6, 7, 5, 4;," /* (right side) */
2086 "4; 1, 0, 4, 5;," /* (bottom side) */
2087 "4; 1, 5, 7, 3;," /* (back side) */
2088 "4; 0, 2, 6, 4;;" /* (front side) */
2089 "MeshNormals {"
2090 "6;" /* DWORD nNormals; */
2091 /* array Vector normals[nNormals]; */
2092 "-1.0; 0.0; 0.0;,"
2093 "0.0; 1.0; 0.0;,"
2094 "1.0; 0.0; 0.0;,"
2095 "0.0; -1.0; 0.0;,"
2096 "0.0; 0.0; 1.0;,"
2097 "0.0; 0.0; -1.0;;"
2098 "6;" /* DWORD nFaceNormals; */
2099 /* array MeshFace faceNormals[nFaceNormals]; */
2100 "4; 0, 0, 0, 0;,"
2101 "4; 1, 1, 1, 1;,"
2102 "4; 2, 2, 2, 2;,"
2103 "4; 3, 3, 3, 3;,"
2104 "4; 4, 4, 4, 4;,"
2105 "4; 5, 5, 5, 5;;"
2107 "MeshMaterialList materials {"
2108 "2;" /* DWORD nMaterials; */
2109 "6;" /* DWORD nFaceIndexes; */
2110 /* array DWORD faceIndexes[nFaceIndexes]; */
2111 "0, 0, 0, 1, 1, 1;;"
2112 "Material {"
2113 /* ColorRGBA faceColor; */
2114 "0.0; 0.0; 1.0; 1.0;;"
2115 /* FLOAT power; */
2116 "0.5;"
2117 /* ColorRGB specularColor; */
2118 "1.0; 1.0; 1.0;;"
2119 /* ColorRGB emissiveColor; */
2120 "0.0; 0.0; 0.0;;"
2122 "Material {"
2123 /* ColorRGBA faceColor; */
2124 "1.0; 1.0; 1.0; 1.0;;"
2125 /* FLOAT power; */
2126 "1.0;"
2127 /* ColorRGB specularColor; */
2128 "1.0; 1.0; 1.0;;"
2129 /* ColorRGB emissiveColor; */
2130 "0.0; 0.0; 0.0;;"
2131 "TextureFilename { \"texture.jpg\"; }"
2134 "MeshVertexColors {"
2135 "8;" /* DWORD nVertexColors; */
2136 /* array IndexedColor vertexColors[nVertexColors]; */
2137 "0; 0.0; 0.0; 0.0; 0.0;;"
2138 "1; 0.0; 0.0; 1.0; 0.1;;"
2139 "2; 0.0; 1.0; 0.0; 0.2;;"
2140 "3; 0.0; 1.0; 1.0; 0.3;;"
2141 "4; 1.0; 0.0; 0.0; 0.4;;"
2142 "5; 1.0; 0.0; 1.0; 0.5;;"
2143 "6; 1.0; 1.0; 0.0; 0.6;;"
2144 "7; 1.0; 1.0; 1.0; 0.7;;"
2146 "MeshTextureCoords {"
2147 "8;" /* DWORD nTextureCoords; */
2148 /* array Coords2d textureCoords[nTextureCoords]; */
2149 "0.0; 1.0;,"
2150 "1.0; 1.0;,"
2151 "0.0; 0.0;,"
2152 "1.0; 0.0;,"
2153 "1.0; 1.0;,"
2154 "0.0; 1.0;,"
2155 "1.0; 0.0;,"
2156 "0.0; 0.0;;"
2158 "}";
2159 static const WORD box_index_buffer[] = {
2160 0, 1, 3,
2161 0, 3, 2,
2162 8, 9, 7,
2163 8, 7, 6,
2164 10, 11, 5,
2165 10, 5, 4,
2166 12, 13, 14,
2167 12, 14, 15,
2168 16, 17, 18,
2169 16, 18, 19,
2170 20, 21, 22,
2171 20, 22, 23,
2173 static const struct {
2174 D3DXVECTOR3 position;
2175 D3DXVECTOR3 normal;
2176 D3DCOLOR diffuse;
2177 D3DXVECTOR2 tex_coords;
2178 } box_vertex_buffer[] = {
2179 {{0.0, 0.0, 0.0}, {-1.0, 0.0, 0.0}, 0x00000000, {0.0, 1.0}},
2180 {{0.0, 0.0, 1.0}, {-1.0, 0.0, 0.0}, 0x1a0000ff, {1.0, 1.0}},
2181 {{0.0, 1.0, 0.0}, {-1.0, 0.0, 0.0}, 0x3300ff00, {0.0, 0.0}},
2182 {{0.0, 1.0, 1.0}, {-1.0, 0.0, 0.0}, 0x4d00ffff, {1.0, 0.0}},
2183 {{1.0, 0.0, 0.0}, {1.0, 0.0, 0.0}, 0x66ff0000, {1.0, 1.0}},
2184 {{1.0, 0.0, 1.0}, {1.0, 0.0, 0.0}, 0x80ff00ff, {0.0, 1.0}},
2185 {{1.0, 1.0, 0.0}, {0.0, 1.0, 0.0}, 0x99ffff00, {1.0, 0.0}},
2186 {{1.0, 1.0, 1.0}, {0.0, 1.0, 0.0}, 0xb3ffffff, {0.0, 0.0}},
2187 {{0.0, 1.0, 0.0}, {0.0, 1.0, 0.0}, 0x3300ff00, {0.0, 0.0}},
2188 {{0.0, 1.0, 1.0}, {0.0, 1.0, 0.0}, 0x4d00ffff, {1.0, 0.0}},
2189 {{1.0, 1.0, 0.0}, {1.0, 0.0, 0.0}, 0x99ffff00, {1.0, 0.0}},
2190 {{1.0, 1.0, 1.0}, {1.0, 0.0, 0.0}, 0xb3ffffff, {0.0, 0.0}},
2191 {{0.0, 0.0, 1.0}, {0.0, -1.0, 0.0}, 0x1a0000ff, {1.0, 1.0}},
2192 {{0.0, 0.0, 0.0}, {0.0, -1.0, 0.0}, 0x00000000, {0.0, 1.0}},
2193 {{1.0, 0.0, 0.0}, {0.0, -1.0, 0.0}, 0x66ff0000, {1.0, 1.0}},
2194 {{1.0, 0.0, 1.0}, {0.0, -1.0, 0.0}, 0x80ff00ff, {0.0, 1.0}},
2195 {{0.0, 0.0, 1.0}, {0.0, 0.0, 1.0}, 0x1a0000ff, {1.0, 1.0}},
2196 {{1.0, 0.0, 1.0}, {0.0, 0.0, 1.0}, 0x80ff00ff, {0.0, 1.0}},
2197 {{1.0, 1.0, 1.0}, {0.0, 0.0, 1.0}, 0xb3ffffff, {0.0, 0.0}},
2198 {{0.0, 1.0, 1.0}, {0.0, 0.0, 1.0}, 0x4d00ffff, {1.0, 0.0}},
2199 {{0.0, 0.0, 0.0}, {0.0, 0.0, -1.0}, 0x00000000, {0.0, 1.0}},
2200 {{0.0, 1.0, 0.0}, {0.0, 0.0, -1.0}, 0x3300ff00, {0.0, 0.0}},
2201 {{1.0, 1.0, 0.0}, {0.0, 0.0, -1.0}, 0x99ffff00, {1.0, 0.0}},
2202 {{1.0, 0.0, 0.0}, {0.0, 0.0, -1.0}, 0x66ff0000, {1.0, 1.0}},
2204 static const D3DXMATERIAL box_materials[] = {
2207 {0.0, 0.0, 1.0, 1.0}, /* Diffuse */
2208 {0.0, 0.0, 0.0, 1.0}, /* Ambient */
2209 {1.0, 1.0, 1.0, 1.0}, /* Specular */
2210 {0.0, 0.0, 0.0, 1.0}, /* Emissive */
2211 0.5, /* Power */
2213 NULL, /* pTextureFilename */
2217 {1.0, 1.0, 1.0, 1.0}, /* Diffuse */
2218 {0.0, 0.0, 0.0, 1.0}, /* Ambient */
2219 {1.0, 1.0, 1.0, 1.0}, /* Specular */
2220 {0.0, 0.0, 0.0, 1.0}, /* Emissive */
2221 1.0, /* Power */
2223 (char *)"texture.jpg", /* pTextureFilename */
2226 const DWORD box_fvf = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_TEX1;
2227 /*________________________*/
2228 static const D3DXMATERIAL default_materials[] = {
2231 {0.5, 0.5, 0.5, 0.0}, /* Diffuse */
2232 {0.0, 0.0, 0.0, 0.0}, /* Ambient */
2233 {0.5, 0.5, 0.5, 0.0}, /* Specular */
2234 {0.0, 0.0, 0.0, 0.0}, /* Emissive */
2235 0.0, /* Power */
2237 NULL, /* pTextureFilename */
2240 HRESULT hr;
2241 HWND wnd = NULL;
2242 IDirect3D9 *d3d = NULL;
2243 IDirect3DDevice9 *device = NULL;
2244 D3DPRESENT_PARAMETERS d3dpp;
2245 ID3DXMesh *mesh = NULL;
2246 D3DXFRAME *frame_hier = NULL;
2247 D3DXMATRIX transform;
2249 wnd = CreateWindow("static", "d3dx9_test", WS_POPUP, 0, 0, 1000, 1000, NULL, NULL, NULL, NULL);
2250 if (!wnd)
2252 skip("Couldn't create application window\n");
2253 return;
2255 d3d = Direct3DCreate9(D3D_SDK_VERSION);
2256 if (!d3d)
2258 skip("Couldn't create IDirect3D9 object\n");
2259 goto cleanup;
2262 ZeroMemory(&d3dpp, sizeof(d3dpp));
2263 d3dpp.Windowed = TRUE;
2264 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2265 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, wnd, D3DCREATE_MIXED_VERTEXPROCESSING, &d3dpp, &device);
2266 if (FAILED(hr))
2268 skip("Failed to create IDirect3DDevice9 object %#x\n", hr);
2269 goto cleanup;
2272 hr = D3DXLoadMeshHierarchyFromXInMemory(NULL, sizeof(simple_xfile) - 1,
2273 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
2274 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2276 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, 0,
2277 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
2278 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2280 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1,
2281 D3DXMESH_MANAGED, NULL, &alloc_hier, NULL, &frame_hier, NULL);
2282 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2284 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1,
2285 D3DXMESH_MANAGED, device, NULL, NULL, &frame_hier, NULL);
2286 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2288 hr = D3DXLoadMeshHierarchyFromXInMemory(empty_xfile, sizeof(empty_xfile) - 1,
2289 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
2290 ok(hr == E_FAIL, "Expected E_FAIL, got %#x\n", hr);
2292 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1,
2293 D3DXMESH_MANAGED, device, &alloc_hier, NULL, NULL, NULL);
2294 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2296 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1,
2297 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
2298 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2299 if (SUCCEEDED(hr)) {
2300 D3DXMESHCONTAINER *container = frame_hier->pMeshContainer;
2302 ok(frame_hier->Name == NULL, "Expected NULL, got '%s'\n", frame_hier->Name);
2303 D3DXMatrixIdentity(&transform);
2304 check_matrix(&frame_hier->TransformationMatrix, &transform);
2306 ok(!strcmp(container->Name, ""), "Expected '', got '%s'\n", container->Name);
2307 ok(container->MeshData.Type == D3DXMESHTYPE_MESH, "Expected %d, got %d\n",
2308 D3DXMESHTYPE_MESH, container->MeshData.Type);
2309 mesh = U(container->MeshData).pMesh;
2310 check_vertex_buffer(mesh, simple_vertex_buffer, ARRAY_SIZE(simple_vertex_buffer), simple_fvf);
2311 check_index_buffer(mesh, simple_index_buffer, ARRAY_SIZE(simple_index_buffer), sizeof(*simple_index_buffer));
2312 check_materials(container->pMaterials, container->NumMaterials, NULL, 0);
2313 check_generated_effects(container->pMaterials, container->NumMaterials, container->pEffects);
2314 check_generated_adjacency(mesh, container->pAdjacency, 0.0f);
2315 hr = D3DXFrameDestroy(frame_hier, &alloc_hier);
2316 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2317 frame_hier = NULL;
2320 hr = D3DXLoadMeshHierarchyFromXInMemory(box_xfile, sizeof(box_xfile) - 1,
2321 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
2322 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2323 if (SUCCEEDED(hr)) {
2324 D3DXMESHCONTAINER *container = frame_hier->pMeshContainer;
2326 ok(frame_hier->Name == NULL, "Expected NULL, got '%s'\n", frame_hier->Name);
2327 D3DXMatrixIdentity(&transform);
2328 check_matrix(&frame_hier->TransformationMatrix, &transform);
2330 ok(!strcmp(container->Name, ""), "Expected '', got '%s'\n", container->Name);
2331 ok(container->MeshData.Type == D3DXMESHTYPE_MESH, "Expected %d, got %d\n",
2332 D3DXMESHTYPE_MESH, container->MeshData.Type);
2333 mesh = U(container->MeshData).pMesh;
2334 check_vertex_buffer(mesh, box_vertex_buffer, ARRAY_SIZE(box_vertex_buffer), box_fvf);
2335 check_index_buffer(mesh, box_index_buffer, ARRAY_SIZE(box_index_buffer), sizeof(*box_index_buffer));
2336 check_materials(container->pMaterials, container->NumMaterials, box_materials, ARRAY_SIZE(box_materials));
2337 check_generated_effects(container->pMaterials, container->NumMaterials, container->pEffects);
2338 check_generated_adjacency(mesh, container->pAdjacency, 0.0f);
2339 hr = D3DXFrameDestroy(frame_hier, &alloc_hier);
2340 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2341 frame_hier = NULL;
2344 hr = D3DXLoadMeshHierarchyFromXInMemory(framed_xfile, sizeof(framed_xfile) - 1,
2345 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
2346 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2347 if (SUCCEEDED(hr)) {
2348 D3DXMESHCONTAINER *container = frame_hier->pMeshContainer;
2349 int i;
2351 ok(!strcmp(frame_hier->Name, ""), "Expected '', got '%s'\n", frame_hier->Name);
2352 /* last frame transform replaces the first */
2353 D3DXMatrixIdentity(&transform);
2354 U(transform).m[3][2] = 3.0;
2355 check_matrix(&frame_hier->TransformationMatrix, &transform);
2357 for (i = 0; i < 3; i++) {
2358 ok(!strcmp(container->Name, ""), "Expected '', got '%s'\n", container->Name);
2359 ok(container->MeshData.Type == D3DXMESHTYPE_MESH, "Expected %d, got %d\n",
2360 D3DXMESHTYPE_MESH, container->MeshData.Type);
2361 mesh = U(container->MeshData).pMesh;
2362 check_vertex_buffer(mesh, framed_vertex_buffers[i], ARRAY_SIZE(framed_vertex_buffers[0]), framed_fvf);
2363 check_index_buffer(mesh, framed_index_buffer, ARRAY_SIZE(framed_index_buffer), sizeof(*framed_index_buffer));
2364 check_materials(container->pMaterials, container->NumMaterials, NULL, 0);
2365 check_generated_effects(container->pMaterials, container->NumMaterials, container->pEffects);
2366 check_generated_adjacency(mesh, container->pAdjacency, 0.0f);
2367 container = container->pNextMeshContainer;
2369 ok(container == NULL, "Expected NULL, got %p\n", container);
2370 hr = D3DXFrameDestroy(frame_hier, &alloc_hier);
2371 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2372 frame_hier = NULL;
2376 hr = D3DXLoadMeshFromXInMemory(NULL, 0, D3DXMESH_MANAGED,
2377 device, NULL, NULL, NULL, NULL, &mesh);
2378 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2380 hr = D3DXLoadMeshFromXInMemory(NULL, sizeof(simple_xfile) - 1, D3DXMESH_MANAGED,
2381 device, NULL, NULL, NULL, NULL, &mesh);
2382 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2384 hr = D3DXLoadMeshFromXInMemory(simple_xfile, 0, D3DXMESH_MANAGED,
2385 device, NULL, NULL, NULL, NULL, &mesh);
2386 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2388 hr = D3DXLoadMeshFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1, D3DXMESH_MANAGED,
2389 device, NULL, NULL, NULL, NULL, NULL);
2390 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2392 hr = D3DXLoadMeshFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1, D3DXMESH_MANAGED,
2393 NULL, NULL, NULL, NULL, NULL, &mesh);
2394 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2396 hr = D3DXLoadMeshFromXInMemory(empty_xfile, sizeof(empty_xfile) - 1, D3DXMESH_MANAGED,
2397 device, NULL, NULL, NULL, NULL, &mesh);
2398 ok(hr == E_FAIL, "Expected E_FAIL, got %#x\n", hr);
2400 hr = D3DXLoadMeshFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1, D3DXMESH_MANAGED,
2401 device, NULL, NULL, NULL, NULL, &mesh);
2402 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2403 if (SUCCEEDED(hr))
2404 IUnknown_Release(mesh);
2406 test_LoadMeshFromX(device, simple_xfile, simple_vertex_buffer, simple_fvf, simple_index_buffer, default_materials, TRUE);
2407 test_LoadMeshFromX(device, box_xfile, box_vertex_buffer, box_fvf, box_index_buffer, box_materials, TRUE);
2408 test_LoadMeshFromX(device, framed_xfile, merged_vertex_buffer, framed_fvf, merged_index_buffer, default_materials, FALSE);
2410 cleanup:
2411 if (device) IDirect3DDevice9_Release(device);
2412 if (d3d) IDirect3D9_Release(d3d);
2413 if (wnd) DestroyWindow(wnd);
2416 static void D3DXCreateBoxTest(void)
2418 HRESULT hr;
2419 HWND wnd;
2420 WNDCLASS wc={0};
2421 IDirect3D9* d3d;
2422 IDirect3DDevice9* device;
2423 D3DPRESENT_PARAMETERS d3dpp;
2424 ID3DXMesh* box;
2425 ID3DXBuffer* ppBuffer;
2426 DWORD *buffer;
2427 static const DWORD adjacency[36]=
2428 {6, 9, 1, 2, 10, 0,
2429 1, 9, 3, 4, 10, 2,
2430 3, 8, 5, 7, 11, 4,
2431 0, 11, 7, 5, 8, 6,
2432 7, 4, 9, 2, 0, 8,
2433 1, 3, 11, 5, 6, 10};
2434 unsigned int i;
2436 wc.lpfnWndProc = DefWindowProcA;
2437 wc.lpszClassName = "d3dx9_test_wc";
2438 if (!RegisterClass(&wc))
2440 skip("RegisterClass failed\n");
2441 return;
2444 wnd = CreateWindow("d3dx9_test_wc", "d3dx9_test",
2445 WS_SYSMENU | WS_POPUP , 0, 0, 640, 480, 0, 0, 0, 0);
2446 ok(wnd != NULL, "Expected to have a window, received NULL\n");
2447 if (!wnd)
2449 skip("Couldn't create application window\n");
2450 return;
2453 d3d = Direct3DCreate9(D3D_SDK_VERSION);
2454 if (!d3d)
2456 skip("Couldn't create IDirect3D9 object\n");
2457 DestroyWindow(wnd);
2458 return;
2461 memset(&d3dpp, 0, sizeof(d3dpp));
2462 d3dpp.Windowed = TRUE;
2463 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2464 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, wnd, D3DCREATE_MIXED_VERTEXPROCESSING, &d3dpp, &device);
2465 if (FAILED(hr))
2467 skip("Failed to create IDirect3DDevice9 object %#x\n", hr);
2468 IDirect3D9_Release(d3d);
2469 DestroyWindow(wnd);
2470 return;
2473 hr = D3DXCreateBuffer(36 * sizeof(DWORD), &ppBuffer);
2474 ok(hr==D3D_OK, "Expected D3D_OK, received %#x\n", hr);
2475 if (FAILED(hr)) goto end;
2477 hr = D3DXCreateBox(device,2.0f,20.0f,4.9f,NULL, &ppBuffer);
2478 todo_wine ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2480 hr = D3DXCreateBox(NULL,22.0f,20.0f,4.9f,&box, &ppBuffer);
2481 todo_wine ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2483 hr = D3DXCreateBox(device,-2.0f,20.0f,4.9f,&box, &ppBuffer);
2484 todo_wine ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2486 hr = D3DXCreateBox(device,22.0f,-20.0f,4.9f,&box, &ppBuffer);
2487 todo_wine ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2489 hr = D3DXCreateBox(device,22.0f,20.0f,-4.9f,&box, &ppBuffer);
2490 todo_wine ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2492 hr = D3DXCreateBox(device,10.9f,20.0f,4.9f,&box, &ppBuffer);
2493 todo_wine ok(hr==D3D_OK, "Expected D3D_OK, received %#x\n", hr);
2495 if (FAILED(hr))
2497 skip("D3DXCreateBox failed\n");
2498 goto end;
2501 buffer = ID3DXBuffer_GetBufferPointer(ppBuffer);
2502 for(i=0; i<36; i++)
2503 todo_wine ok(adjacency[i]==buffer[i], "expected adjacency %d: %#x, received %#x\n",i,adjacency[i], buffer[i]);
2505 box->lpVtbl->Release(box);
2507 end:
2508 IDirect3DDevice9_Release(device);
2509 IDirect3D9_Release(d3d);
2510 ID3DXBuffer_Release(ppBuffer);
2511 DestroyWindow(wnd);
2514 struct sincos_table
2516 float *sin;
2517 float *cos;
2520 static void free_sincos_table(struct sincos_table *sincos_table)
2522 HeapFree(GetProcessHeap(), 0, sincos_table->cos);
2523 HeapFree(GetProcessHeap(), 0, sincos_table->sin);
2526 /* pre compute sine and cosine tables; caller must free */
2527 static BOOL compute_sincos_table(struct sincos_table *sincos_table, float angle_start, float angle_step, int n)
2529 float angle;
2530 int i;
2532 sincos_table->sin = HeapAlloc(GetProcessHeap(), 0, n * sizeof(*sincos_table->sin));
2533 if (!sincos_table->sin)
2535 return FALSE;
2537 sincos_table->cos = HeapAlloc(GetProcessHeap(), 0, n * sizeof(*sincos_table->cos));
2538 if (!sincos_table->cos)
2540 HeapFree(GetProcessHeap(), 0, sincos_table->sin);
2541 return FALSE;
2544 angle = angle_start;
2545 for (i = 0; i < n; i++)
2547 sincos_table->sin[i] = sin(angle);
2548 sincos_table->cos[i] = cos(angle);
2549 angle += angle_step;
2552 return TRUE;
2555 static WORD vertex_index(UINT slices, int slice, int stack)
2557 return stack*slices+slice+1;
2560 /* slices = subdivisions along xy plane, stacks = subdivisions along z axis */
2561 static BOOL compute_sphere(struct mesh *mesh, FLOAT radius, UINT slices, UINT stacks)
2563 float theta_step, theta_start;
2564 struct sincos_table theta;
2565 float phi_step, phi_start;
2566 struct sincos_table phi;
2567 DWORD number_of_vertices, number_of_faces;
2568 DWORD vertex, face;
2569 int slice, stack;
2571 /* theta = angle on xy plane wrt x axis */
2572 theta_step = M_PI / stacks;
2573 theta_start = theta_step;
2575 /* phi = angle on xz plane wrt z axis */
2576 phi_step = -2 * M_PI / slices;
2577 phi_start = M_PI / 2;
2579 if (!compute_sincos_table(&theta, theta_start, theta_step, stacks))
2581 return FALSE;
2583 if (!compute_sincos_table(&phi, phi_start, phi_step, slices))
2585 free_sincos_table(&theta);
2586 return FALSE;
2589 number_of_vertices = 2 + slices * (stacks-1);
2590 number_of_faces = 2 * slices + (stacks - 2) * (2 * slices);
2592 if (!new_mesh(mesh, number_of_vertices, number_of_faces))
2594 free_sincos_table(&phi);
2595 free_sincos_table(&theta);
2596 return FALSE;
2599 vertex = 0;
2600 face = 0;
2602 mesh->vertices[vertex].normal.x = 0.0f;
2603 mesh->vertices[vertex].normal.y = 0.0f;
2604 mesh->vertices[vertex].normal.z = 1.0f;
2605 mesh->vertices[vertex].position.x = 0.0f;
2606 mesh->vertices[vertex].position.y = 0.0f;
2607 mesh->vertices[vertex].position.z = radius;
2608 vertex++;
2610 for (stack = 0; stack < stacks - 1; stack++)
2612 for (slice = 0; slice < slices; slice++)
2614 mesh->vertices[vertex].normal.x = theta.sin[stack] * phi.cos[slice];
2615 mesh->vertices[vertex].normal.y = theta.sin[stack] * phi.sin[slice];
2616 mesh->vertices[vertex].normal.z = theta.cos[stack];
2617 mesh->vertices[vertex].position.x = radius * theta.sin[stack] * phi.cos[slice];
2618 mesh->vertices[vertex].position.y = radius * theta.sin[stack] * phi.sin[slice];
2619 mesh->vertices[vertex].position.z = radius * theta.cos[stack];
2620 vertex++;
2622 if (slice > 0)
2624 if (stack == 0)
2626 /* top stack is triangle fan */
2627 mesh->faces[face][0] = 0;
2628 mesh->faces[face][1] = slice + 1;
2629 mesh->faces[face][2] = slice;
2630 face++;
2632 else
2634 /* stacks in between top and bottom are quad strips */
2635 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
2636 mesh->faces[face][1] = vertex_index(slices, slice, stack-1);
2637 mesh->faces[face][2] = vertex_index(slices, slice-1, stack);
2638 face++;
2640 mesh->faces[face][0] = vertex_index(slices, slice, stack-1);
2641 mesh->faces[face][1] = vertex_index(slices, slice, stack);
2642 mesh->faces[face][2] = vertex_index(slices, slice-1, stack);
2643 face++;
2648 if (stack == 0)
2650 mesh->faces[face][0] = 0;
2651 mesh->faces[face][1] = 1;
2652 mesh->faces[face][2] = slice;
2653 face++;
2655 else
2657 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
2658 mesh->faces[face][1] = vertex_index(slices, 0, stack-1);
2659 mesh->faces[face][2] = vertex_index(slices, slice-1, stack);
2660 face++;
2662 mesh->faces[face][0] = vertex_index(slices, 0, stack-1);
2663 mesh->faces[face][1] = vertex_index(slices, 0, stack);
2664 mesh->faces[face][2] = vertex_index(slices, slice-1, stack);
2665 face++;
2669 mesh->vertices[vertex].position.x = 0.0f;
2670 mesh->vertices[vertex].position.y = 0.0f;
2671 mesh->vertices[vertex].position.z = -radius;
2672 mesh->vertices[vertex].normal.x = 0.0f;
2673 mesh->vertices[vertex].normal.y = 0.0f;
2674 mesh->vertices[vertex].normal.z = -1.0f;
2676 /* bottom stack is triangle fan */
2677 for (slice = 1; slice < slices; slice++)
2679 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
2680 mesh->faces[face][1] = vertex_index(slices, slice, stack-1);
2681 mesh->faces[face][2] = vertex;
2682 face++;
2685 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
2686 mesh->faces[face][1] = vertex_index(slices, 0, stack-1);
2687 mesh->faces[face][2] = vertex;
2689 free_sincos_table(&phi);
2690 free_sincos_table(&theta);
2692 return TRUE;
2695 static void test_sphere(IDirect3DDevice9 *device, FLOAT radius, UINT slices, UINT stacks)
2697 HRESULT hr;
2698 ID3DXMesh *sphere;
2699 struct mesh mesh;
2700 char name[256];
2702 hr = D3DXCreateSphere(device, radius, slices, stacks, &sphere, NULL);
2703 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
2704 if (hr != D3D_OK)
2706 skip("Couldn't create sphere\n");
2707 return;
2710 if (!compute_sphere(&mesh, radius, slices, stacks))
2712 skip("Couldn't create mesh\n");
2713 sphere->lpVtbl->Release(sphere);
2714 return;
2717 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
2719 sprintf(name, "sphere (%g, %u, %u)", radius, slices, stacks);
2720 compare_mesh(name, sphere, &mesh);
2722 free_mesh(&mesh);
2724 sphere->lpVtbl->Release(sphere);
2727 static void D3DXCreateSphereTest(void)
2729 HRESULT hr;
2730 HWND wnd;
2731 IDirect3D9* d3d;
2732 IDirect3DDevice9* device;
2733 D3DPRESENT_PARAMETERS d3dpp;
2734 ID3DXMesh* sphere = NULL;
2736 hr = D3DXCreateSphere(NULL, 0.0f, 0, 0, NULL, NULL);
2737 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
2739 hr = D3DXCreateSphere(NULL, 0.1f, 0, 0, NULL, NULL);
2740 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
2742 hr = D3DXCreateSphere(NULL, 0.0f, 1, 0, NULL, NULL);
2743 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
2745 hr = D3DXCreateSphere(NULL, 0.0f, 0, 1, NULL, NULL);
2746 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
2748 wnd = CreateWindow("static", "d3dx9_test", 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL);
2749 d3d = Direct3DCreate9(D3D_SDK_VERSION);
2750 if (!wnd)
2752 skip("Couldn't create application window\n");
2753 return;
2755 if (!d3d)
2757 skip("Couldn't create IDirect3D9 object\n");
2758 DestroyWindow(wnd);
2759 return;
2762 ZeroMemory(&d3dpp, sizeof(d3dpp));
2763 d3dpp.Windowed = TRUE;
2764 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2765 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, wnd, D3DCREATE_MIXED_VERTEXPROCESSING, &d3dpp, &device);
2766 if (FAILED(hr))
2768 skip("Failed to create IDirect3DDevice9 object %#x\n", hr);
2769 IDirect3D9_Release(d3d);
2770 DestroyWindow(wnd);
2771 return;
2774 hr = D3DXCreateSphere(device, 1.0f, 1, 1, &sphere, NULL);
2775 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
2777 hr = D3DXCreateSphere(device, 1.0f, 2, 1, &sphere, NULL);
2778 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
2780 hr = D3DXCreateSphere(device, 1.0f, 1, 2, &sphere, NULL);
2781 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
2783 hr = D3DXCreateSphere(device, -0.1f, 1, 2, &sphere, NULL);
2784 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
2786 test_sphere(device, 0.0f, 2, 2);
2787 test_sphere(device, 1.0f, 2, 2);
2788 test_sphere(device, 1.0f, 3, 2);
2789 test_sphere(device, 1.0f, 4, 4);
2790 test_sphere(device, 1.0f, 3, 4);
2791 test_sphere(device, 5.0f, 6, 7);
2792 test_sphere(device, 10.0f, 11, 12);
2794 IDirect3DDevice9_Release(device);
2795 IDirect3D9_Release(d3d);
2796 DestroyWindow(wnd);
2799 static BOOL compute_cylinder(struct mesh *mesh, FLOAT radius1, FLOAT radius2, FLOAT length, UINT slices, UINT stacks)
2801 float theta_step, theta_start;
2802 struct sincos_table theta;
2803 FLOAT delta_radius, radius, radius_step;
2804 FLOAT z, z_step, z_normal;
2805 DWORD number_of_vertices, number_of_faces;
2806 DWORD vertex, face;
2807 int slice, stack;
2809 /* theta = angle on xy plane wrt x axis */
2810 theta_step = -2 * M_PI / slices;
2811 theta_start = M_PI / 2;
2813 if (!compute_sincos_table(&theta, theta_start, theta_step, slices))
2815 return FALSE;
2818 number_of_vertices = 2 + (slices * (3 + stacks));
2819 number_of_faces = 2 * slices + stacks * (2 * slices);
2821 if (!new_mesh(mesh, number_of_vertices, number_of_faces))
2823 free_sincos_table(&theta);
2824 return FALSE;
2827 vertex = 0;
2828 face = 0;
2830 delta_radius = radius1 - radius2;
2831 radius = radius1;
2832 radius_step = delta_radius / stacks;
2834 z = -length / 2;
2835 z_step = length / stacks;
2836 z_normal = delta_radius / length;
2837 if (isnan(z_normal))
2839 z_normal = 0.0f;
2842 mesh->vertices[vertex].normal.x = 0.0f;
2843 mesh->vertices[vertex].normal.y = 0.0f;
2844 mesh->vertices[vertex].normal.z = -1.0f;
2845 mesh->vertices[vertex].position.x = 0.0f;
2846 mesh->vertices[vertex].position.y = 0.0f;
2847 mesh->vertices[vertex++].position.z = z;
2849 for (slice = 0; slice < slices; slice++, vertex++)
2851 mesh->vertices[vertex].normal.x = 0.0f;
2852 mesh->vertices[vertex].normal.y = 0.0f;
2853 mesh->vertices[vertex].normal.z = -1.0f;
2854 mesh->vertices[vertex].position.x = radius * theta.cos[slice];
2855 mesh->vertices[vertex].position.y = radius * theta.sin[slice];
2856 mesh->vertices[vertex].position.z = z;
2858 if (slice > 0)
2860 mesh->faces[face][0] = 0;
2861 mesh->faces[face][1] = slice;
2862 mesh->faces[face++][2] = slice + 1;
2866 mesh->faces[face][0] = 0;
2867 mesh->faces[face][1] = slice;
2868 mesh->faces[face++][2] = 1;
2870 for (stack = 1; stack <= stacks+1; stack++)
2872 for (slice = 0; slice < slices; slice++, vertex++)
2874 mesh->vertices[vertex].normal.x = theta.cos[slice];
2875 mesh->vertices[vertex].normal.y = theta.sin[slice];
2876 mesh->vertices[vertex].normal.z = z_normal;
2877 D3DXVec3Normalize(&mesh->vertices[vertex].normal, &mesh->vertices[vertex].normal);
2878 mesh->vertices[vertex].position.x = radius * theta.cos[slice];
2879 mesh->vertices[vertex].position.y = radius * theta.sin[slice];
2880 mesh->vertices[vertex].position.z = z;
2882 if (stack > 1 && slice > 0)
2884 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
2885 mesh->faces[face][1] = vertex_index(slices, slice-1, stack);
2886 mesh->faces[face++][2] = vertex_index(slices, slice, stack-1);
2888 mesh->faces[face][0] = vertex_index(slices, slice, stack-1);
2889 mesh->faces[face][1] = vertex_index(slices, slice-1, stack);
2890 mesh->faces[face++][2] = vertex_index(slices, slice, stack);
2894 if (stack > 1)
2896 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
2897 mesh->faces[face][1] = vertex_index(slices, slice-1, stack);
2898 mesh->faces[face++][2] = vertex_index(slices, 0, stack-1);
2900 mesh->faces[face][0] = vertex_index(slices, 0, stack-1);
2901 mesh->faces[face][1] = vertex_index(slices, slice-1, stack);
2902 mesh->faces[face++][2] = vertex_index(slices, 0, stack);
2905 if (stack < stacks + 1)
2907 z += z_step;
2908 radius -= radius_step;
2912 for (slice = 0; slice < slices; slice++, vertex++)
2914 mesh->vertices[vertex].normal.x = 0.0f;
2915 mesh->vertices[vertex].normal.y = 0.0f;
2916 mesh->vertices[vertex].normal.z = 1.0f;
2917 mesh->vertices[vertex].position.x = radius * theta.cos[slice];
2918 mesh->vertices[vertex].position.y = radius * theta.sin[slice];
2919 mesh->vertices[vertex].position.z = z;
2921 if (slice > 0)
2923 mesh->faces[face][0] = vertex_index(slices, slice-1, stack);
2924 mesh->faces[face][1] = number_of_vertices - 1;
2925 mesh->faces[face++][2] = vertex_index(slices, slice, stack);
2929 mesh->vertices[vertex].position.x = 0.0f;
2930 mesh->vertices[vertex].position.y = 0.0f;
2931 mesh->vertices[vertex].position.z = z;
2932 mesh->vertices[vertex].normal.x = 0.0f;
2933 mesh->vertices[vertex].normal.y = 0.0f;
2934 mesh->vertices[vertex].normal.z = 1.0f;
2936 mesh->faces[face][0] = vertex_index(slices, slice-1, stack);
2937 mesh->faces[face][1] = number_of_vertices - 1;
2938 mesh->faces[face][2] = vertex_index(slices, 0, stack);
2940 free_sincos_table(&theta);
2942 return TRUE;
2945 static void test_cylinder(IDirect3DDevice9 *device, FLOAT radius1, FLOAT radius2, FLOAT length, UINT slices, UINT stacks)
2947 HRESULT hr;
2948 ID3DXMesh *cylinder;
2949 struct mesh mesh;
2950 char name[256];
2952 hr = D3DXCreateCylinder(device, radius1, radius2, length, slices, stacks, &cylinder, NULL);
2953 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
2954 if (hr != D3D_OK)
2956 skip("Couldn't create cylinder\n");
2957 return;
2960 if (!compute_cylinder(&mesh, radius1, radius2, length, slices, stacks))
2962 skip("Couldn't create mesh\n");
2963 cylinder->lpVtbl->Release(cylinder);
2964 return;
2967 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
2969 sprintf(name, "cylinder (%g, %g, %g, %u, %u)", radius1, radius2, length, slices, stacks);
2970 compare_mesh(name, cylinder, &mesh);
2972 free_mesh(&mesh);
2974 cylinder->lpVtbl->Release(cylinder);
2977 static void D3DXCreateCylinderTest(void)
2979 HRESULT hr;
2980 HWND wnd;
2981 IDirect3D9* d3d;
2982 IDirect3DDevice9* device;
2983 D3DPRESENT_PARAMETERS d3dpp;
2984 ID3DXMesh* cylinder = NULL;
2986 hr = D3DXCreateCylinder(NULL, 0.0f, 0.0f, 0.0f, 0, 0, NULL, NULL);
2987 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
2989 hr = D3DXCreateCylinder(NULL, 1.0f, 1.0f, 1.0f, 2, 1, &cylinder, NULL);
2990 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
2992 wnd = CreateWindow("static", "d3dx9_test", 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL);
2993 d3d = Direct3DCreate9(D3D_SDK_VERSION);
2994 if (!wnd)
2996 skip("Couldn't create application window\n");
2997 return;
2999 if (!d3d)
3001 skip("Couldn't create IDirect3D9 object\n");
3002 DestroyWindow(wnd);
3003 return;
3006 ZeroMemory(&d3dpp, sizeof(d3dpp));
3007 d3dpp.Windowed = TRUE;
3008 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
3009 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, wnd, D3DCREATE_MIXED_VERTEXPROCESSING, &d3dpp, &device);
3010 if (FAILED(hr))
3012 skip("Failed to create IDirect3DDevice9 object %#x\n", hr);
3013 IDirect3D9_Release(d3d);
3014 DestroyWindow(wnd);
3015 return;
3018 hr = D3DXCreateCylinder(device, -0.1f, 1.0f, 1.0f, 2, 1, &cylinder, NULL);
3019 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3021 hr = D3DXCreateCylinder(device, 0.0f, 1.0f, 1.0f, 2, 1, &cylinder, NULL);
3022 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n",hr);
3024 if (SUCCEEDED(hr) && cylinder)
3026 cylinder->lpVtbl->Release(cylinder);
3029 hr = D3DXCreateCylinder(device, 1.0f, -0.1f, 1.0f, 2, 1, &cylinder, NULL);
3030 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3032 hr = D3DXCreateCylinder(device, 1.0f, 0.0f, 1.0f, 2, 1, &cylinder, NULL);
3033 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n",hr);
3035 if (SUCCEEDED(hr) && cylinder)
3037 cylinder->lpVtbl->Release(cylinder);
3040 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, -0.1f, 2, 1, &cylinder, NULL);
3041 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3043 /* Test with length == 0.0f succeeds */
3044 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, 0.0f, 2, 1, &cylinder, NULL);
3045 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n",hr);
3047 if (SUCCEEDED(hr) && cylinder)
3049 cylinder->lpVtbl->Release(cylinder);
3052 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, 1.0f, 1, 1, &cylinder, NULL);
3053 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3055 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, 1.0f, 2, 0, &cylinder, NULL);
3056 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3058 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, 1.0f, 2, 1, NULL, NULL);
3059 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3061 test_cylinder(device, 0.0f, 0.0f, 0.0f, 2, 1);
3062 test_cylinder(device, 1.0f, 1.0f, 1.0f, 2, 1);
3063 test_cylinder(device, 1.0f, 1.0f, 2.0f, 3, 4);
3064 test_cylinder(device, 3.0f, 2.0f, 4.0f, 3, 4);
3065 test_cylinder(device, 2.0f, 3.0f, 4.0f, 3, 4);
3066 test_cylinder(device, 3.0f, 4.0f, 5.0f, 11, 20);
3068 IDirect3DDevice9_Release(device);
3069 IDirect3D9_Release(d3d);
3070 DestroyWindow(wnd);
3073 struct dynamic_array
3075 int count, capacity;
3076 void *items;
3079 enum pointtype {
3080 POINTTYPE_CURVE = 0,
3081 POINTTYPE_CORNER,
3082 POINTTYPE_CURVE_START,
3083 POINTTYPE_CURVE_END,
3084 POINTTYPE_CURVE_MIDDLE,
3087 struct point2d
3089 D3DXVECTOR2 pos;
3090 enum pointtype corner;
3093 /* is a dynamic_array */
3094 struct outline
3096 int count, capacity;
3097 struct point2d *items;
3100 /* is a dynamic_array */
3101 struct outline_array
3103 int count, capacity;
3104 struct outline *items;
3107 struct glyphinfo
3109 struct outline_array outlines;
3110 float offset_x;
3113 static BOOL reserve(struct dynamic_array *array, int count, int itemsize)
3115 if (count > array->capacity) {
3116 void *new_buffer;
3117 int new_capacity;
3118 if (array->items && array->capacity) {
3119 new_capacity = max(array->capacity * 2, count);
3120 new_buffer = HeapReAlloc(GetProcessHeap(), 0, array->items, new_capacity * itemsize);
3121 } else {
3122 new_capacity = max(16, count);
3123 new_buffer = HeapAlloc(GetProcessHeap(), 0, new_capacity * itemsize);
3125 if (!new_buffer)
3126 return FALSE;
3127 array->items = new_buffer;
3128 array->capacity = new_capacity;
3130 return TRUE;
3133 static struct point2d *add_point(struct outline *array)
3135 struct point2d *item;
3137 if (!reserve((struct dynamic_array *)array, array->count + 1, sizeof(array->items[0])))
3138 return NULL;
3140 item = &array->items[array->count++];
3141 ZeroMemory(item, sizeof(*item));
3142 return item;
3145 static struct outline *add_outline(struct outline_array *array)
3147 struct outline *item;
3149 if (!reserve((struct dynamic_array *)array, array->count + 1, sizeof(array->items[0])))
3150 return NULL;
3152 item = &array->items[array->count++];
3153 ZeroMemory(item, sizeof(*item));
3154 return item;
3157 static inline D3DXVECTOR2 *convert_fixed_to_float(POINTFX *pt, int count, float emsquare)
3159 D3DXVECTOR2 *ret = (D3DXVECTOR2*)pt;
3160 while (count--) {
3161 D3DXVECTOR2 *pt_flt = (D3DXVECTOR2*)pt;
3162 pt_flt->x = (pt->x.value + pt->x.fract / (float)0x10000) / emsquare;
3163 pt_flt->y = (pt->y.value + pt->y.fract / (float)0x10000) / emsquare;
3164 pt++;
3166 return ret;
3169 static HRESULT add_bezier_points(struct outline *outline, const D3DXVECTOR2 *p1,
3170 const D3DXVECTOR2 *p2, const D3DXVECTOR2 *p3,
3171 float max_deviation)
3173 D3DXVECTOR2 split1 = {0, 0}, split2 = {0, 0}, middle, vec;
3174 float deviation;
3176 D3DXVec2Scale(&split1, D3DXVec2Add(&split1, p1, p2), 0.5f);
3177 D3DXVec2Scale(&split2, D3DXVec2Add(&split2, p2, p3), 0.5f);
3178 D3DXVec2Scale(&middle, D3DXVec2Add(&middle, &split1, &split2), 0.5f);
3180 deviation = D3DXVec2Length(D3DXVec2Subtract(&vec, &middle, p2));
3181 if (deviation < max_deviation) {
3182 struct point2d *pt = add_point(outline);
3183 if (!pt) return E_OUTOFMEMORY;
3184 pt->pos = *p2;
3185 pt->corner = POINTTYPE_CURVE;
3186 /* the end point is omitted because the end line merges into the next segment of
3187 * the split bezier curve, and the end of the split bezier curve is added outside
3188 * this recursive function. */
3189 } else {
3190 HRESULT hr = add_bezier_points(outline, p1, &split1, &middle, max_deviation);
3191 if (hr != S_OK) return hr;
3192 hr = add_bezier_points(outline, &middle, &split2, p3, max_deviation);
3193 if (hr != S_OK) return hr;
3196 return S_OK;
3199 static inline BOOL is_direction_similar(D3DXVECTOR2 *dir1, D3DXVECTOR2 *dir2, float cos_theta)
3201 /* dot product = cos(theta) */
3202 return D3DXVec2Dot(dir1, dir2) > cos_theta;
3205 static inline D3DXVECTOR2 *unit_vec2(D3DXVECTOR2 *dir, const D3DXVECTOR2 *pt1, const D3DXVECTOR2 *pt2)
3207 return D3DXVec2Normalize(D3DXVec2Subtract(dir, pt2, pt1), dir);
3210 static BOOL attempt_line_merge(struct outline *outline,
3211 int pt_index,
3212 const D3DXVECTOR2 *nextpt,
3213 BOOL to_curve)
3215 D3DXVECTOR2 curdir, lastdir;
3216 struct point2d *prevpt, *pt;
3217 BOOL ret = FALSE;
3218 const float cos_half = cos(D3DXToRadian(0.5f));
3220 pt = &outline->items[pt_index];
3221 pt_index = (pt_index - 1 + outline->count) % outline->count;
3222 prevpt = &outline->items[pt_index];
3224 if (to_curve)
3225 pt->corner = pt->corner != POINTTYPE_CORNER ? POINTTYPE_CURVE_MIDDLE : POINTTYPE_CURVE_START;
3227 if (outline->count < 2)
3228 return FALSE;
3230 /* remove last point if the next line continues the last line */
3231 unit_vec2(&lastdir, &prevpt->pos, &pt->pos);
3232 unit_vec2(&curdir, &pt->pos, nextpt);
3233 if (is_direction_similar(&lastdir, &curdir, cos_half))
3235 outline->count--;
3236 if (pt->corner == POINTTYPE_CURVE_END)
3237 prevpt->corner = pt->corner;
3238 if (prevpt->corner == POINTTYPE_CURVE_END && to_curve)
3239 prevpt->corner = POINTTYPE_CURVE_MIDDLE;
3240 pt = prevpt;
3242 ret = TRUE;
3243 if (outline->count < 2)
3244 return ret;
3246 pt_index = (pt_index - 1 + outline->count) % outline->count;
3247 prevpt = &outline->items[pt_index];
3248 unit_vec2(&lastdir, &prevpt->pos, &pt->pos);
3249 unit_vec2(&curdir, &pt->pos, nextpt);
3251 return ret;
3254 static HRESULT create_outline(struct glyphinfo *glyph, void *raw_outline, int datasize,
3255 float max_deviation, float emsquare)
3257 const float cos_45 = cos(D3DXToRadian(45.0f));
3258 const float cos_90 = cos(D3DXToRadian(90.0f));
3259 TTPOLYGONHEADER *header = (TTPOLYGONHEADER *)raw_outline;
3261 while ((char *)header < (char *)raw_outline + datasize)
3263 TTPOLYCURVE *curve = (TTPOLYCURVE *)(header + 1);
3264 struct point2d *lastpt, *pt;
3265 D3DXVECTOR2 lastdir;
3266 D3DXVECTOR2 *pt_flt;
3267 int j;
3268 struct outline *outline = add_outline(&glyph->outlines);
3270 if (!outline)
3271 return E_OUTOFMEMORY;
3273 pt = add_point(outline);
3274 if (!pt)
3275 return E_OUTOFMEMORY;
3276 pt_flt = convert_fixed_to_float(&header->pfxStart, 1, emsquare);
3277 pt->pos = *pt_flt;
3278 pt->corner = POINTTYPE_CORNER;
3280 if (header->dwType != TT_POLYGON_TYPE)
3281 trace("Unknown header type %d\n", header->dwType);
3283 while ((char *)curve < (char *)header + header->cb)
3285 D3DXVECTOR2 bezier_start = outline->items[outline->count - 1].pos;
3286 BOOL to_curve = curve->wType != TT_PRIM_LINE && curve->cpfx > 1;
3288 if (!curve->cpfx) {
3289 curve = (TTPOLYCURVE *)&curve->apfx[curve->cpfx];
3290 continue;
3293 pt_flt = convert_fixed_to_float(curve->apfx, curve->cpfx, emsquare);
3295 attempt_line_merge(outline, outline->count - 1, &pt_flt[0], to_curve);
3297 if (to_curve)
3299 HRESULT hr;
3300 int count = curve->cpfx;
3301 j = 0;
3303 while (count > 2)
3305 D3DXVECTOR2 bezier_end;
3307 D3DXVec2Scale(&bezier_end, D3DXVec2Add(&bezier_end, &pt_flt[j], &pt_flt[j+1]), 0.5f);
3308 hr = add_bezier_points(outline, &bezier_start, &pt_flt[j], &bezier_end, max_deviation);
3309 if (hr != S_OK)
3310 return hr;
3311 bezier_start = bezier_end;
3312 count--;
3313 j++;
3315 hr = add_bezier_points(outline, &bezier_start, &pt_flt[j], &pt_flt[j+1], max_deviation);
3316 if (hr != S_OK)
3317 return hr;
3319 pt = add_point(outline);
3320 if (!pt)
3321 return E_OUTOFMEMORY;
3322 j++;
3323 pt->pos = pt_flt[j];
3324 pt->corner = POINTTYPE_CURVE_END;
3325 } else {
3326 for (j = 0; j < curve->cpfx; j++)
3328 pt = add_point(outline);
3329 if (!pt)
3330 return E_OUTOFMEMORY;
3331 pt->pos = pt_flt[j];
3332 pt->corner = POINTTYPE_CORNER;
3336 curve = (TTPOLYCURVE *)&curve->apfx[curve->cpfx];
3339 /* remove last point if the next line continues the last line */
3340 if (outline->count >= 3) {
3341 BOOL to_curve;
3343 lastpt = &outline->items[outline->count - 1];
3344 pt = &outline->items[0];
3345 if (pt->pos.x == lastpt->pos.x && pt->pos.y == lastpt->pos.y) {
3346 if (lastpt->corner == POINTTYPE_CURVE_END)
3348 if (pt->corner == POINTTYPE_CURVE_START)
3349 pt->corner = POINTTYPE_CURVE_MIDDLE;
3350 else
3351 pt->corner = POINTTYPE_CURVE_END;
3353 outline->count--;
3354 lastpt = &outline->items[outline->count - 1];
3355 } else {
3356 /* outline closed with a line from end to start point */
3357 attempt_line_merge(outline, outline->count - 1, &pt->pos, FALSE);
3359 lastpt = &outline->items[0];
3360 to_curve = lastpt->corner != POINTTYPE_CORNER && lastpt->corner != POINTTYPE_CURVE_END;
3361 if (lastpt->corner == POINTTYPE_CURVE_START)
3362 lastpt->corner = POINTTYPE_CORNER;
3363 pt = &outline->items[1];
3364 if (attempt_line_merge(outline, 0, &pt->pos, to_curve))
3365 *lastpt = outline->items[outline->count];
3368 lastpt = &outline->items[outline->count - 1];
3369 pt = &outline->items[0];
3370 unit_vec2(&lastdir, &lastpt->pos, &pt->pos);
3371 for (j = 0; j < outline->count; j++)
3373 D3DXVECTOR2 curdir;
3375 lastpt = pt;
3376 pt = &outline->items[(j + 1) % outline->count];
3377 unit_vec2(&curdir, &lastpt->pos, &pt->pos);
3379 switch (lastpt->corner)
3381 case POINTTYPE_CURVE_START:
3382 case POINTTYPE_CURVE_END:
3383 if (!is_direction_similar(&lastdir, &curdir, cos_45))
3384 lastpt->corner = POINTTYPE_CORNER;
3385 break;
3386 case POINTTYPE_CURVE_MIDDLE:
3387 if (!is_direction_similar(&lastdir, &curdir, cos_90))
3388 lastpt->corner = POINTTYPE_CORNER;
3389 else
3390 lastpt->corner = POINTTYPE_CURVE;
3391 break;
3392 default:
3393 break;
3395 lastdir = curdir;
3398 header = (TTPOLYGONHEADER *)((char *)header + header->cb);
3400 return S_OK;
3403 static BOOL compute_text_mesh(struct mesh *mesh, HDC hdc, LPCSTR text, FLOAT deviation, FLOAT extrusion, FLOAT otmEMSquare)
3405 HRESULT hr = E_FAIL;
3406 DWORD nb_vertices, nb_faces;
3407 DWORD nb_corners, nb_outline_points;
3408 int textlen = 0;
3409 float offset_x;
3410 char *raw_outline = NULL;
3411 struct glyphinfo *glyphs = NULL;
3412 GLYPHMETRICS gm;
3413 int i;
3414 struct vertex *vertex_ptr;
3415 face *face_ptr;
3417 if (deviation == 0.0f)
3418 deviation = 1.0f / otmEMSquare;
3420 textlen = strlen(text);
3421 glyphs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, textlen * sizeof(*glyphs));
3422 if (!glyphs) {
3423 hr = E_OUTOFMEMORY;
3424 goto error;
3427 offset_x = 0.0f;
3428 for (i = 0; i < textlen; i++)
3430 /* get outline points from data returned from GetGlyphOutline */
3431 const MAT2 identity = {{0, 1}, {0, 0}, {0, 0}, {0, 1}};
3432 int datasize;
3434 glyphs[i].offset_x = offset_x;
3436 datasize = GetGlyphOutline(hdc, text[i], GGO_NATIVE, &gm, 0, NULL, &identity);
3437 if (datasize < 0) {
3438 hr = E_FAIL;
3439 goto error;
3441 HeapFree(GetProcessHeap(), 0, raw_outline);
3442 raw_outline = HeapAlloc(GetProcessHeap(), 0, datasize);
3443 if (!glyphs) {
3444 hr = E_OUTOFMEMORY;
3445 goto error;
3447 datasize = GetGlyphOutline(hdc, text[i], GGO_NATIVE, &gm, datasize, raw_outline, &identity);
3449 create_outline(&glyphs[i], raw_outline, datasize, deviation, otmEMSquare);
3451 offset_x += gm.gmCellIncX / (float)otmEMSquare;
3454 /* corner points need an extra vertex for the different side faces normals */
3455 nb_corners = 0;
3456 nb_outline_points = 0;
3457 for (i = 0; i < textlen; i++)
3459 int j;
3460 for (j = 0; j < glyphs[i].outlines.count; j++)
3462 int k;
3463 struct outline *outline = &glyphs[i].outlines.items[j];
3464 nb_outline_points += outline->count;
3465 nb_corners++; /* first outline point always repeated as a corner */
3466 for (k = 1; k < outline->count; k++)
3467 if (outline->items[k].corner)
3468 nb_corners++;
3472 nb_vertices = (nb_outline_points + nb_corners) * 2 + textlen;
3473 nb_faces = nb_outline_points * 2;
3475 if (!new_mesh(mesh, nb_vertices, nb_faces))
3476 goto error;
3478 /* convert 2D vertices and faces into 3D mesh */
3479 vertex_ptr = mesh->vertices;
3480 face_ptr = mesh->faces;
3481 for (i = 0; i < textlen; i++)
3483 int j;
3485 /* side vertices and faces */
3486 for (j = 0; j < glyphs[i].outlines.count; j++)
3488 struct vertex *outline_vertices = vertex_ptr;
3489 struct outline *outline = &glyphs[i].outlines.items[j];
3490 int k;
3491 struct point2d *prevpt = &outline->items[outline->count - 1];
3492 struct point2d *pt = &outline->items[0];
3494 for (k = 1; k <= outline->count; k++)
3496 struct vertex vtx;
3497 struct point2d *nextpt = &outline->items[k % outline->count];
3498 WORD vtx_idx = vertex_ptr - mesh->vertices;
3499 D3DXVECTOR2 vec;
3501 if (pt->corner == POINTTYPE_CURVE_START)
3502 D3DXVec2Subtract(&vec, &pt->pos, &prevpt->pos);
3503 else if (pt->corner)
3504 D3DXVec2Subtract(&vec, &nextpt->pos, &pt->pos);
3505 else
3506 D3DXVec2Subtract(&vec, &nextpt->pos, &prevpt->pos);
3507 D3DXVec2Normalize(&vec, &vec);
3508 vtx.normal.x = -vec.y;
3509 vtx.normal.y = vec.x;
3510 vtx.normal.z = 0;
3512 vtx.position.x = pt->pos.x + glyphs[i].offset_x;
3513 vtx.position.y = pt->pos.y;
3514 vtx.position.z = 0;
3515 *vertex_ptr++ = vtx;
3517 vtx.position.z = -extrusion;
3518 *vertex_ptr++ = vtx;
3520 vtx.position.x = nextpt->pos.x + glyphs[i].offset_x;
3521 vtx.position.y = nextpt->pos.y;
3522 if (pt->corner && nextpt->corner && nextpt->corner != POINTTYPE_CURVE_END) {
3523 vtx.position.z = -extrusion;
3524 *vertex_ptr++ = vtx;
3525 vtx.position.z = 0;
3526 *vertex_ptr++ = vtx;
3528 (*face_ptr)[0] = vtx_idx;
3529 (*face_ptr)[1] = vtx_idx + 2;
3530 (*face_ptr)[2] = vtx_idx + 1;
3531 face_ptr++;
3533 (*face_ptr)[0] = vtx_idx;
3534 (*face_ptr)[1] = vtx_idx + 3;
3535 (*face_ptr)[2] = vtx_idx + 2;
3536 face_ptr++;
3537 } else {
3538 if (nextpt->corner) {
3539 if (nextpt->corner == POINTTYPE_CURVE_END) {
3540 struct point2d *nextpt2 = &outline->items[(k + 1) % outline->count];
3541 D3DXVec2Subtract(&vec, &nextpt2->pos, &nextpt->pos);
3542 } else {
3543 D3DXVec2Subtract(&vec, &nextpt->pos, &pt->pos);
3545 D3DXVec2Normalize(&vec, &vec);
3546 vtx.normal.x = -vec.y;
3547 vtx.normal.y = vec.x;
3549 vtx.position.z = 0;
3550 *vertex_ptr++ = vtx;
3551 vtx.position.z = -extrusion;
3552 *vertex_ptr++ = vtx;
3555 (*face_ptr)[0] = vtx_idx;
3556 (*face_ptr)[1] = vtx_idx + 3;
3557 (*face_ptr)[2] = vtx_idx + 1;
3558 face_ptr++;
3560 (*face_ptr)[0] = vtx_idx;
3561 (*face_ptr)[1] = vtx_idx + 2;
3562 (*face_ptr)[2] = vtx_idx + 3;
3563 face_ptr++;
3566 prevpt = pt;
3567 pt = nextpt;
3569 if (!pt->corner) {
3570 *vertex_ptr++ = *outline_vertices++;
3571 *vertex_ptr++ = *outline_vertices++;
3575 /* FIXME: compute expected faces */
3576 /* Add placeholder to separate glyph outlines */
3577 vertex_ptr->position.x = 0;
3578 vertex_ptr->position.y = 0;
3579 vertex_ptr->position.z = 0;
3580 vertex_ptr->normal.x = 0;
3581 vertex_ptr->normal.y = 0;
3582 vertex_ptr->normal.z = 1;
3583 vertex_ptr++;
3586 hr = D3D_OK;
3587 error:
3588 if (glyphs) {
3589 for (i = 0; i < textlen; i++)
3591 int j;
3592 for (j = 0; j < glyphs[i].outlines.count; j++)
3593 HeapFree(GetProcessHeap(), 0, glyphs[i].outlines.items[j].items);
3594 HeapFree(GetProcessHeap(), 0, glyphs[i].outlines.items);
3596 HeapFree(GetProcessHeap(), 0, glyphs);
3598 HeapFree(GetProcessHeap(), 0, raw_outline);
3600 return hr == D3D_OK;
3603 static void compare_text_outline_mesh(const char *name, ID3DXMesh *d3dxmesh, struct mesh *mesh, int textlen, float extrusion)
3605 HRESULT hr;
3606 DWORD number_of_vertices, number_of_faces;
3607 IDirect3DVertexBuffer9 *vertex_buffer = NULL;
3608 IDirect3DIndexBuffer9 *index_buffer = NULL;
3609 D3DVERTEXBUFFER_DESC vertex_buffer_description;
3610 D3DINDEXBUFFER_DESC index_buffer_description;
3611 struct vertex *vertices = NULL;
3612 face *faces = NULL;
3613 int expected, i;
3614 int vtx_idx1, face_idx1, vtx_idx2, face_idx2;
3616 number_of_vertices = d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh);
3617 number_of_faces = d3dxmesh->lpVtbl->GetNumFaces(d3dxmesh);
3619 /* vertex buffer */
3620 hr = d3dxmesh->lpVtbl->GetVertexBuffer(d3dxmesh, &vertex_buffer);
3621 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
3622 if (hr != D3D_OK)
3624 skip("Couldn't get vertex buffers\n");
3625 goto error;
3628 hr = IDirect3DVertexBuffer9_GetDesc(vertex_buffer, &vertex_buffer_description);
3629 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
3631 if (hr != D3D_OK)
3633 skip("Couldn't get vertex buffer description\n");
3635 else
3637 ok(vertex_buffer_description.Format == D3DFMT_VERTEXDATA, "Test %s, result %x, expected %x (D3DFMT_VERTEXDATA)\n",
3638 name, vertex_buffer_description.Format, D3DFMT_VERTEXDATA);
3639 ok(vertex_buffer_description.Type == D3DRTYPE_VERTEXBUFFER, "Test %s, result %x, expected %x (D3DRTYPE_VERTEXBUFFER)\n",
3640 name, vertex_buffer_description.Type, D3DRTYPE_VERTEXBUFFER);
3641 ok(vertex_buffer_description.Usage == 0, "Test %s, result %x, expected %x\n", name, vertex_buffer_description.Usage, 0);
3642 ok(vertex_buffer_description.Pool == D3DPOOL_MANAGED, "Test %s, result %x, expected %x (D3DPOOL_MANAGED)\n",
3643 name, vertex_buffer_description.Pool, D3DPOOL_MANAGED);
3644 ok(vertex_buffer_description.FVF == mesh->fvf, "Test %s, result %x, expected %x\n",
3645 name, vertex_buffer_description.FVF, mesh->fvf);
3646 if (mesh->fvf == 0)
3648 expected = number_of_vertices * mesh->vertex_size;
3650 else
3652 expected = number_of_vertices * D3DXGetFVFVertexSize(mesh->fvf);
3654 ok(vertex_buffer_description.Size == expected, "Test %s, result %x, expected %x\n",
3655 name, vertex_buffer_description.Size, expected);
3658 hr = d3dxmesh->lpVtbl->GetIndexBuffer(d3dxmesh, &index_buffer);
3659 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
3660 if (hr != D3D_OK)
3662 skip("Couldn't get index buffer\n");
3663 goto error;
3666 hr = IDirect3DIndexBuffer9_GetDesc(index_buffer, &index_buffer_description);
3667 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
3669 if (hr != D3D_OK)
3671 skip("Couldn't get index buffer description\n");
3673 else
3675 ok(index_buffer_description.Format == D3DFMT_INDEX16, "Test %s, result %x, expected %x (D3DFMT_INDEX16)\n",
3676 name, index_buffer_description.Format, D3DFMT_INDEX16);
3677 ok(index_buffer_description.Type == D3DRTYPE_INDEXBUFFER, "Test %s, result %x, expected %x (D3DRTYPE_INDEXBUFFER)\n",
3678 name, index_buffer_description.Type, D3DRTYPE_INDEXBUFFER);
3679 todo_wine ok(index_buffer_description.Usage == 0, "Test %s, result %x, expected %x\n", name, index_buffer_description.Usage, 0);
3680 ok(index_buffer_description.Pool == D3DPOOL_MANAGED, "Test %s, result %x, expected %x (D3DPOOL_MANAGED)\n",
3681 name, index_buffer_description.Pool, D3DPOOL_MANAGED);
3682 expected = number_of_faces * sizeof(WORD) * 3;
3683 ok(index_buffer_description.Size == expected, "Test %s, result %x, expected %x\n",
3684 name, index_buffer_description.Size, expected);
3687 /* specify offset and size to avoid potential overruns */
3688 hr = IDirect3DVertexBuffer9_Lock(vertex_buffer, 0, number_of_vertices * sizeof(D3DXVECTOR3) * 2,
3689 (LPVOID *)&vertices, D3DLOCK_DISCARD);
3690 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
3691 if (hr != D3D_OK)
3693 skip("Couldn't lock vertex buffer\n");
3694 goto error;
3696 hr = IDirect3DIndexBuffer9_Lock(index_buffer, 0, number_of_faces * sizeof(WORD) * 3,
3697 (LPVOID *)&faces, D3DLOCK_DISCARD);
3698 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
3699 if (hr != D3D_OK)
3701 skip("Couldn't lock index buffer\n");
3702 goto error;
3705 face_idx1 = 0;
3706 vtx_idx2 = 0;
3707 face_idx2 = 0;
3708 vtx_idx1 = 0;
3709 for (i = 0; i < textlen; i++)
3711 int nb_outline_vertices1, nb_outline_faces1;
3712 int nb_outline_vertices2, nb_outline_faces2;
3713 int nb_back_vertices, nb_back_faces;
3714 int first_vtx1, first_vtx2;
3715 int first_face1, first_face2;
3716 int j;
3718 first_vtx1 = vtx_idx1;
3719 first_vtx2 = vtx_idx2;
3720 for (; vtx_idx1 < number_of_vertices; vtx_idx1++) {
3721 if (vertices[vtx_idx1].normal.z != 0)
3722 break;
3724 for (; vtx_idx2 < mesh->number_of_vertices; vtx_idx2++) {
3725 if (mesh->vertices[vtx_idx2].normal.z != 0)
3726 break;
3728 nb_outline_vertices1 = vtx_idx1 - first_vtx1;
3729 nb_outline_vertices2 = vtx_idx2 - first_vtx2;
3730 ok(nb_outline_vertices1 == nb_outline_vertices2,
3731 "Test %s, glyph %d, outline vertex count result %d, expected %d\n", name, i,
3732 nb_outline_vertices1, nb_outline_vertices2);
3734 for (j = 0; j < min(nb_outline_vertices1, nb_outline_vertices2); j++)
3736 vtx_idx1 = first_vtx1 + j;
3737 vtx_idx2 = first_vtx2 + j;
3738 ok(compare_vec3(vertices[vtx_idx1].position, mesh->vertices[vtx_idx2].position),
3739 "Test %s, glyph %d, vertex position %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1,
3740 vertices[vtx_idx1].position.x, vertices[vtx_idx1].position.y, vertices[vtx_idx1].position.z,
3741 mesh->vertices[vtx_idx2].position.x, mesh->vertices[vtx_idx2].position.y, mesh->vertices[vtx_idx2].position.z);
3742 ok(compare_vec3(vertices[vtx_idx1].normal, mesh->vertices[first_vtx2 + j].normal),
3743 "Test %s, glyph %d, vertex normal %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1,
3744 vertices[vtx_idx1].normal.x, vertices[vtx_idx1].normal.y, vertices[vtx_idx1].normal.z,
3745 mesh->vertices[vtx_idx2].normal.x, mesh->vertices[vtx_idx2].normal.y, mesh->vertices[vtx_idx2].normal.z);
3747 vtx_idx1 = first_vtx1 + nb_outline_vertices1;
3748 vtx_idx2 = first_vtx2 + nb_outline_vertices2;
3750 first_face1 = face_idx1;
3751 first_face2 = face_idx2;
3752 for (; face_idx1 < number_of_faces; face_idx1++)
3754 if (faces[face_idx1][0] >= vtx_idx1 ||
3755 faces[face_idx1][1] >= vtx_idx1 ||
3756 faces[face_idx1][2] >= vtx_idx1)
3757 break;
3759 for (; face_idx2 < mesh->number_of_faces; face_idx2++)
3761 if (mesh->faces[face_idx2][0] >= vtx_idx2 ||
3762 mesh->faces[face_idx2][1] >= vtx_idx2 ||
3763 mesh->faces[face_idx2][2] >= vtx_idx2)
3764 break;
3766 nb_outline_faces1 = face_idx1 - first_face1;
3767 nb_outline_faces2 = face_idx2 - first_face2;
3768 ok(nb_outline_faces1 == nb_outline_faces2,
3769 "Test %s, glyph %d, outline face count result %d, expected %d\n", name, i,
3770 nb_outline_faces1, nb_outline_faces2);
3772 for (j = 0; j < min(nb_outline_faces1, nb_outline_faces2); j++)
3774 face_idx1 = first_face1 + j;
3775 face_idx2 = first_face2 + j;
3776 ok(faces[face_idx1][0] - first_vtx1 == mesh->faces[face_idx2][0] - first_vtx2 &&
3777 faces[face_idx1][1] - first_vtx1 == mesh->faces[face_idx2][1] - first_vtx2 &&
3778 faces[face_idx1][2] - first_vtx1 == mesh->faces[face_idx2][2] - first_vtx2,
3779 "Test %s, glyph %d, face %d, result (%d, %d, %d), expected (%d, %d, %d)\n", name, i, face_idx1,
3780 faces[face_idx1][0], faces[face_idx1][1], faces[face_idx1][2],
3781 mesh->faces[face_idx2][0] - first_vtx2 + first_vtx1,
3782 mesh->faces[face_idx2][1] - first_vtx2 + first_vtx1,
3783 mesh->faces[face_idx2][2] - first_vtx2 + first_vtx1);
3785 face_idx1 = first_face1 + nb_outline_faces1;
3786 face_idx2 = first_face2 + nb_outline_faces2;
3788 /* partial test on back vertices and faces */
3789 first_vtx1 = vtx_idx1;
3790 for (; vtx_idx1 < number_of_vertices; vtx_idx1++) {
3791 struct vertex vtx;
3793 if (vertices[vtx_idx1].normal.z != 1.0f)
3794 break;
3796 vtx.position.z = 0.0f;
3797 vtx.normal.x = 0.0f;
3798 vtx.normal.y = 0.0f;
3799 vtx.normal.z = 1.0f;
3800 ok(compare(vertices[vtx_idx1].position.z, vtx.position.z),
3801 "Test %s, glyph %d, vertex position.z %d, result %g, expected %g\n", name, i, vtx_idx1,
3802 vertices[vtx_idx1].position.z, vtx.position.z);
3803 ok(compare_vec3(vertices[vtx_idx1].normal, vtx.normal),
3804 "Test %s, glyph %d, vertex normal %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1,
3805 vertices[vtx_idx1].normal.x, vertices[vtx_idx1].normal.y, vertices[vtx_idx1].normal.z,
3806 vtx.normal.x, vtx.normal.y, vtx.normal.z);
3808 nb_back_vertices = vtx_idx1 - first_vtx1;
3809 first_face1 = face_idx1;
3810 for (; face_idx1 < number_of_faces; face_idx1++)
3812 const D3DXVECTOR3 *vtx1, *vtx2, *vtx3;
3813 D3DXVECTOR3 normal;
3814 D3DXVECTOR3 v1 = {0, 0, 0};
3815 D3DXVECTOR3 v2 = {0, 0, 0};
3816 D3DXVECTOR3 forward = {0.0f, 0.0f, 1.0f};
3818 if (faces[face_idx1][0] >= vtx_idx1 ||
3819 faces[face_idx1][1] >= vtx_idx1 ||
3820 faces[face_idx1][2] >= vtx_idx1)
3821 break;
3823 vtx1 = &vertices[faces[face_idx1][0]].position;
3824 vtx2 = &vertices[faces[face_idx1][1]].position;
3825 vtx3 = &vertices[faces[face_idx1][2]].position;
3827 D3DXVec3Subtract(&v1, vtx2, vtx1);
3828 D3DXVec3Subtract(&v2, vtx3, vtx2);
3829 D3DXVec3Cross(&normal, &v1, &v2);
3830 D3DXVec3Normalize(&normal, &normal);
3831 ok(!D3DXVec3Length(&normal) || compare_vec3(normal, forward),
3832 "Test %s, glyph %d, face %d normal, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, face_idx1,
3833 normal.x, normal.y, normal.z, forward.x, forward.y, forward.z);
3835 nb_back_faces = face_idx1 - first_face1;
3837 /* compare front and back faces & vertices */
3838 if (extrusion == 0.0f) {
3839 /* Oddly there are only back faces in this case */
3840 nb_back_vertices /= 2;
3841 nb_back_faces /= 2;
3842 face_idx1 -= nb_back_faces;
3843 vtx_idx1 -= nb_back_vertices;
3845 for (j = 0; j < nb_back_vertices; j++)
3847 struct vertex vtx = vertices[first_vtx1];
3848 vtx.position.z = -extrusion;
3849 vtx.normal.x = 0.0f;
3850 vtx.normal.y = 0.0f;
3851 vtx.normal.z = extrusion == 0.0f ? 1.0f : -1.0f;
3852 ok(compare_vec3(vertices[vtx_idx1].position, vtx.position),
3853 "Test %s, glyph %d, vertex position %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1,
3854 vertices[vtx_idx1].position.x, vertices[vtx_idx1].position.y, vertices[vtx_idx1].position.z,
3855 vtx.position.x, vtx.position.y, vtx.position.z);
3856 ok(compare_vec3(vertices[vtx_idx1].normal, vtx.normal),
3857 "Test %s, glyph %d, vertex normal %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1,
3858 vertices[vtx_idx1].normal.x, vertices[vtx_idx1].normal.y, vertices[vtx_idx1].normal.z,
3859 vtx.normal.x, vtx.normal.y, vtx.normal.z);
3860 vtx_idx1++;
3861 first_vtx1++;
3863 for (j = 0; j < nb_back_faces; j++)
3865 int f1, f2;
3866 if (extrusion == 0.0f) {
3867 f1 = 1;
3868 f2 = 2;
3869 } else {
3870 f1 = 2;
3871 f2 = 1;
3873 ok(faces[face_idx1][0] == faces[first_face1][0] + nb_back_vertices &&
3874 faces[face_idx1][1] == faces[first_face1][f1] + nb_back_vertices &&
3875 faces[face_idx1][2] == faces[first_face1][f2] + nb_back_vertices,
3876 "Test %s, glyph %d, face %d, result (%d, %d, %d), expected (%d, %d, %d)\n", name, i, face_idx1,
3877 faces[face_idx1][0], faces[face_idx1][1], faces[face_idx1][2],
3878 faces[first_face1][0] - nb_back_faces,
3879 faces[first_face1][f1] - nb_back_faces,
3880 faces[first_face1][f2] - nb_back_faces);
3881 first_face1++;
3882 face_idx1++;
3885 /* skip to the outline for the next glyph */
3886 for (; vtx_idx2 < mesh->number_of_vertices; vtx_idx2++) {
3887 if (mesh->vertices[vtx_idx2].normal.z == 0)
3888 break;
3890 for (; face_idx2 < mesh->number_of_faces; face_idx2++)
3892 if (mesh->faces[face_idx2][0] >= vtx_idx2 ||
3893 mesh->faces[face_idx2][1] >= vtx_idx2 ||
3894 mesh->faces[face_idx2][2] >= vtx_idx2) break;
3898 error:
3899 if (vertices) IDirect3DVertexBuffer9_Unlock(vertex_buffer);
3900 if (faces) IDirect3DIndexBuffer9_Unlock(index_buffer);
3901 if (index_buffer) IDirect3DIndexBuffer9_Release(index_buffer);
3902 if (vertex_buffer) IDirect3DVertexBuffer9_Release(vertex_buffer);
3905 static void test_createtext(IDirect3DDevice9 *device, HDC hdc, LPCSTR text, FLOAT deviation, FLOAT extrusion)
3907 HRESULT hr;
3908 ID3DXMesh *d3dxmesh;
3909 struct mesh mesh;
3910 char name[256];
3911 OUTLINETEXTMETRIC otm;
3912 GLYPHMETRICS gm;
3913 GLYPHMETRICSFLOAT *glyphmetrics_float = HeapAlloc(GetProcessHeap(), 0, sizeof(GLYPHMETRICSFLOAT) * strlen(text));
3914 int i;
3915 LOGFONT lf;
3916 HFONT font = NULL, oldfont = NULL;
3918 sprintf(name, "text ('%s', %f, %f)", text, deviation, extrusion);
3920 hr = D3DXCreateText(device, hdc, text, deviation, extrusion, &d3dxmesh, NULL, glyphmetrics_float);
3921 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
3922 if (hr != D3D_OK)
3924 skip("Couldn't create text with D3DXCreateText\n");
3925 return;
3928 /* must select a modified font having lfHeight = otm.otmEMSquare before
3929 * calling GetGlyphOutline to get the expected values */
3930 if (!GetObject(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf) ||
3931 !GetOutlineTextMetrics(hdc, sizeof(otm), &otm))
3933 d3dxmesh->lpVtbl->Release(d3dxmesh);
3934 skip("Couldn't get text outline\n");
3935 return;
3937 lf.lfHeight = otm.otmEMSquare;
3938 lf.lfWidth = 0;
3939 font = CreateFontIndirect(&lf);
3940 if (!font) {
3941 d3dxmesh->lpVtbl->Release(d3dxmesh);
3942 skip("Couldn't create the modified font\n");
3943 return;
3945 oldfont = SelectObject(hdc, font);
3947 for (i = 0; i < strlen(text); i++)
3949 const MAT2 identity = {{0, 1}, {0, 0}, {0, 0}, {0, 1}};
3950 GetGlyphOutlineA(hdc, text[i], GGO_NATIVE, &gm, 0, NULL, &identity);
3951 compare_float(glyphmetrics_float[i].gmfBlackBoxX, gm.gmBlackBoxX / (float)otm.otmEMSquare);
3952 compare_float(glyphmetrics_float[i].gmfBlackBoxY, gm.gmBlackBoxY / (float)otm.otmEMSquare);
3953 compare_float(glyphmetrics_float[i].gmfptGlyphOrigin.x, gm.gmptGlyphOrigin.x / (float)otm.otmEMSquare);
3954 compare_float(glyphmetrics_float[i].gmfptGlyphOrigin.y, gm.gmptGlyphOrigin.y / (float)otm.otmEMSquare);
3955 compare_float(glyphmetrics_float[i].gmfCellIncX, gm.gmCellIncX / (float)otm.otmEMSquare);
3956 compare_float(glyphmetrics_float[i].gmfCellIncY, gm.gmCellIncY / (float)otm.otmEMSquare);
3959 ZeroMemory(&mesh, sizeof(mesh));
3960 if (!compute_text_mesh(&mesh, hdc, text, deviation, extrusion, otm.otmEMSquare))
3962 skip("Couldn't create mesh\n");
3963 d3dxmesh->lpVtbl->Release(d3dxmesh);
3964 return;
3966 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
3968 compare_text_outline_mesh(name, d3dxmesh, &mesh, strlen(text), extrusion);
3970 free_mesh(&mesh);
3972 d3dxmesh->lpVtbl->Release(d3dxmesh);
3973 SelectObject(hdc, oldfont);
3974 HeapFree(GetProcessHeap(), 0, glyphmetrics_float);
3977 static void D3DXCreateTextTest(void)
3979 HRESULT hr;
3980 HWND wnd;
3981 HDC hdc;
3982 IDirect3D9* d3d;
3983 IDirect3DDevice9* device;
3984 D3DPRESENT_PARAMETERS d3dpp;
3985 ID3DXMesh* d3dxmesh = NULL;
3986 HFONT hFont;
3987 OUTLINETEXTMETRIC otm;
3988 int number_of_vertices;
3989 int number_of_faces;
3991 wnd = CreateWindow("static", "d3dx9_test", WS_POPUP, 0, 0, 1000, 1000, NULL, NULL, NULL, NULL);
3992 d3d = Direct3DCreate9(D3D_SDK_VERSION);
3993 if (!wnd)
3995 skip("Couldn't create application window\n");
3996 return;
3998 if (!d3d)
4000 skip("Couldn't create IDirect3D9 object\n");
4001 DestroyWindow(wnd);
4002 return;
4005 ZeroMemory(&d3dpp, sizeof(d3dpp));
4006 d3dpp.Windowed = TRUE;
4007 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
4008 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, wnd, D3DCREATE_MIXED_VERTEXPROCESSING, &d3dpp, &device);
4009 if (FAILED(hr))
4011 skip("Failed to create IDirect3DDevice9 object %#x\n", hr);
4012 IDirect3D9_Release(d3d);
4013 DestroyWindow(wnd);
4014 return;
4017 hdc = CreateCompatibleDC(NULL);
4019 hFont = CreateFont(12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET,
4020 OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE,
4021 "Arial");
4022 SelectObject(hdc, hFont);
4023 GetOutlineTextMetrics(hdc, sizeof(otm), &otm);
4025 hr = D3DXCreateText(device, hdc, "wine", 0.001f, 0.4f, NULL, NULL, NULL);
4026 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4028 /* D3DXCreateTextA page faults from passing NULL text */
4030 hr = D3DXCreateTextW(device, hdc, NULL, 0.001f, 0.4f, &d3dxmesh, NULL, NULL);
4031 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4033 hr = D3DXCreateText(device, hdc, "", 0.001f, 0.4f, &d3dxmesh, NULL, NULL);
4034 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4036 hr = D3DXCreateText(device, hdc, " ", 0.001f, 0.4f, &d3dxmesh, NULL, NULL);
4037 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4039 hr = D3DXCreateText(NULL, hdc, "wine", 0.001f, 0.4f, &d3dxmesh, NULL, NULL);
4040 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4042 hr = D3DXCreateText(device, NULL, "wine", 0.001f, 0.4f, &d3dxmesh, NULL, NULL);
4043 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4045 hr = D3DXCreateText(device, hdc, "wine", -FLT_MIN, 0.4f, &d3dxmesh, NULL, NULL);
4046 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4048 hr = D3DXCreateText(device, hdc, "wine", 0.001f, -FLT_MIN, &d3dxmesh, NULL, NULL);
4049 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4051 /* deviation = 0.0f treated as if deviation = 1.0f / otm.otmEMSquare */
4052 hr = D3DXCreateText(device, hdc, "wine", 1.0f / otm.otmEMSquare, 0.4f, &d3dxmesh, NULL, NULL);
4053 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
4054 number_of_vertices = d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh);
4055 number_of_faces = d3dxmesh->lpVtbl->GetNumFaces(d3dxmesh);
4056 if (SUCCEEDED(hr) && d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh);
4058 hr = D3DXCreateText(device, hdc, "wine", 0.0f, 0.4f, &d3dxmesh, NULL, NULL);
4059 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
4060 ok(number_of_vertices == d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh),
4061 "Got %d vertices, expected %d\n",
4062 d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh), number_of_vertices);
4063 ok(number_of_faces == d3dxmesh->lpVtbl->GetNumFaces(d3dxmesh),
4064 "Got %d faces, expected %d\n",
4065 d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh), number_of_faces);
4066 if (SUCCEEDED(hr) && d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh);
4068 #if 0
4069 /* too much detail requested, so will appear to hang */
4070 trace("Waiting for D3DXCreateText to finish with deviation = FLT_MIN ...\n");
4071 hr = D3DXCreateText(device, hdc, "wine", FLT_MIN, 0.4f, &d3dxmesh, NULL, NULL);
4072 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
4073 if (SUCCEEDED(hr) && d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh);
4074 trace("D3DXCreateText finish with deviation = FLT_MIN\n");
4075 #endif
4077 hr = D3DXCreateText(device, hdc, "wine", 0.001f, 0.4f, &d3dxmesh, NULL, NULL);
4078 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
4079 if (SUCCEEDED(hr) && d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh);
4081 test_createtext(device, hdc, "wine", FLT_MAX, 0.4f);
4082 test_createtext(device, hdc, "wine", 0.001f, FLT_MIN);
4083 test_createtext(device, hdc, "wine", 0.001f, 0.0f);
4084 test_createtext(device, hdc, "wine", 0.001f, FLT_MAX);
4085 test_createtext(device, hdc, "wine", 0.0f, 1.0f);
4087 DeleteDC(hdc);
4089 IDirect3DDevice9_Release(device);
4090 IDirect3D9_Release(d3d);
4091 DestroyWindow(wnd);
4094 static void test_get_decl_length(void)
4096 static const D3DVERTEXELEMENT9 declaration1[] =
4098 {0, 0, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4099 {1, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4100 {2, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4101 {3, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4102 {4, 0, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4103 {5, 0, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4104 {6, 0, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4105 {7, 0, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4106 {8, 0, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4107 {9, 0, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4108 {10, 0, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4109 {11, 0, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4110 {12, 0, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4111 {13, 0, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4112 {14, 0, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4113 D3DDECL_END(),
4115 static const D3DVERTEXELEMENT9 declaration2[] =
4117 {0, 8, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4118 {1, 8, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4119 {2, 8, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4120 {3, 8, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4121 {4, 8, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4122 {5, 8, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4123 {6, 8, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4124 {7, 8, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4125 {0, 8, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4126 {1, 8, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4127 {2, 8, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4128 {3, 8, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4129 {4, 8, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4130 {5, 8, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4131 {6, 8, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4132 {7, 8, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4133 D3DDECL_END(),
4135 UINT size;
4137 size = D3DXGetDeclLength(declaration1);
4138 ok(size == 15, "Got size %u, expected 15.\n", size);
4140 size = D3DXGetDeclLength(declaration2);
4141 ok(size == 16, "Got size %u, expected 16.\n", size);
4144 static void test_get_decl_vertex_size(void)
4146 static const D3DVERTEXELEMENT9 declaration1[] =
4148 {0, 0, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4149 {1, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4150 {2, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4151 {3, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4152 {4, 0, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4153 {5, 0, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4154 {6, 0, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4155 {7, 0, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4156 {8, 0, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4157 {9, 0, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4158 {10, 0, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4159 {11, 0, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4160 {12, 0, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4161 {13, 0, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4162 {14, 0, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4163 D3DDECL_END(),
4165 static const D3DVERTEXELEMENT9 declaration2[] =
4167 {0, 8, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4168 {1, 8, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4169 {2, 8, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4170 {3, 8, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4171 {4, 8, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4172 {5, 8, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4173 {6, 8, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4174 {7, 8, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4175 {0, 8, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4176 {1, 8, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4177 {2, 8, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4178 {3, 8, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4179 {4, 8, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4180 {5, 8, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4181 {6, 8, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4182 {7, 8, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4183 D3DDECL_END(),
4185 static const UINT sizes1[] =
4187 4, 8, 12, 16,
4188 4, 4, 4, 8,
4189 4, 4, 8, 4,
4190 4, 4, 8, 0,
4192 static const UINT sizes2[] =
4194 12, 16, 20, 24,
4195 12, 12, 16, 16,
4197 unsigned int i;
4198 UINT size;
4200 size = D3DXGetDeclVertexSize(NULL, 0);
4201 ok(size == 0, "Got size %#x, expected 0.\n", size);
4203 for (i = 0; i < 16; ++i)
4205 size = D3DXGetDeclVertexSize(declaration1, i);
4206 ok(size == sizes1[i], "Got size %u for stream %u, expected %u.\n", size, i, sizes1[i]);
4209 for (i = 0; i < 8; ++i)
4211 size = D3DXGetDeclVertexSize(declaration2, i);
4212 ok(size == sizes2[i], "Got size %u for stream %u, expected %u.\n", size, i, sizes2[i]);
4216 static void D3DXGenerateAdjacencyTest(void)
4218 HRESULT hr;
4219 HWND wnd;
4220 IDirect3D9 *d3d;
4221 IDirect3DDevice9 *device;
4222 D3DPRESENT_PARAMETERS d3dpp;
4223 ID3DXMesh *d3dxmesh = NULL;
4224 D3DXVECTOR3 *vertices = NULL;
4225 WORD *indices = NULL;
4226 int i;
4227 struct {
4228 DWORD num_vertices;
4229 D3DXVECTOR3 vertices[6];
4230 DWORD num_faces;
4231 WORD indices[3 * 3];
4232 FLOAT epsilon;
4233 DWORD adjacency[3 * 3];
4234 } test_data[] = {
4235 { /* for epsilon < 0, indices must match for faces to be adjacent */
4236 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}},
4237 2, {0, 1, 2, 0, 2, 3},
4238 -1.0,
4239 {-1, -1, 1, 0, -1, -1},
4242 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}},
4243 2, {0, 1, 2, 3, 4, 5},
4244 -1.0,
4245 {-1, -1, -1, -1, -1, -1},
4247 { /* for epsilon == 0, indices or vertices must match for faces to be adjacent */
4248 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}},
4249 2, {0, 1, 2, 3, 4, 5},
4250 0.0,
4251 {-1, -1, 1, 0, -1, -1},
4253 { /* for epsilon > 0, vertices must be less than (but NOT equal to) epsilon distance away */
4254 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}},
4255 2, {0, 1, 2, 3, 4, 5},
4256 0.25,
4257 {-1, -1, -1, -1, -1, -1},
4259 { /* for epsilon > 0, vertices must be less than (but NOT equal to) epsilon distance away */
4260 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}},
4261 2, {0, 1, 2, 3, 4, 5},
4262 0.250001,
4263 {-1, -1, 1, 0, -1, -1},
4265 { /* length between vertices are compared to epsilon, not the individual dimension deltas */
4266 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}},
4267 2, {0, 1, 2, 3, 4, 5},
4268 0.353, /* < sqrt(0.25*0.25 + 0.25*0.25) */
4269 {-1, -1, -1, -1, -1, -1},
4272 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}},
4273 2, {0, 1, 2, 3, 4, 5},
4274 0.354, /* > sqrt(0.25*0.25 + 0.25*0.25) */
4275 {-1, -1, 1, 0, -1, -1},
4277 { /* adjacent faces must have opposite winding orders at the shared edge */
4278 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}},
4279 2, {0, 1, 2, 0, 3, 2},
4280 0.0,
4281 {-1, -1, -1, -1, -1, -1},
4285 wnd = CreateWindow("static", "d3dx9_test", 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL);
4286 if (!wnd)
4288 skip("Couldn't create application window\n");
4289 return;
4291 d3d = Direct3DCreate9(D3D_SDK_VERSION);
4292 if (!d3d)
4294 skip("Couldn't create IDirect3D9 object\n");
4295 DestroyWindow(wnd);
4296 return;
4299 ZeroMemory(&d3dpp, sizeof(d3dpp));
4300 d3dpp.Windowed = TRUE;
4301 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
4302 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, wnd, D3DCREATE_MIXED_VERTEXPROCESSING, &d3dpp, &device);
4303 if (FAILED(hr))
4305 skip("Failed to create IDirect3DDevice9 object %#x\n", hr);
4306 IDirect3D9_Release(d3d);
4307 DestroyWindow(wnd);
4308 return;
4311 for (i = 0; i < ARRAY_SIZE(test_data); i++)
4313 DWORD adjacency[ARRAY_SIZE(test_data[0].adjacency)];
4314 int j;
4316 if (d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh);
4317 d3dxmesh = NULL;
4319 hr = D3DXCreateMeshFVF(test_data[i].num_faces, test_data[i].num_vertices, 0, D3DFVF_XYZ, device, &d3dxmesh);
4320 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
4322 hr = d3dxmesh->lpVtbl->LockVertexBuffer(d3dxmesh, D3DLOCK_DISCARD, (void**)&vertices);
4323 ok(hr == D3D_OK, "test %d: Got result %x, expected %x (D3D_OK)\n", i, hr, D3D_OK);
4324 if (FAILED(hr)) continue;
4325 CopyMemory(vertices, test_data[i].vertices, test_data[i].num_vertices * sizeof(test_data[0].vertices[0]));
4326 d3dxmesh->lpVtbl->UnlockVertexBuffer(d3dxmesh);
4328 hr = d3dxmesh->lpVtbl->LockIndexBuffer(d3dxmesh, D3DLOCK_DISCARD, (void**)&indices);
4329 ok(hr == D3D_OK, "test %d: Got result %x, expected %x (D3D_OK)\n", i, hr, D3D_OK);
4330 if (FAILED(hr)) continue;
4331 CopyMemory(indices, test_data[i].indices, test_data[i].num_faces * 3 * sizeof(test_data[0].indices[0]));
4332 d3dxmesh->lpVtbl->UnlockIndexBuffer(d3dxmesh);
4334 if (i == 0) {
4335 hr = d3dxmesh->lpVtbl->GenerateAdjacency(d3dxmesh, 0.0f, NULL);
4336 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4339 hr = d3dxmesh->lpVtbl->GenerateAdjacency(d3dxmesh, test_data[i].epsilon, adjacency);
4340 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
4341 if (FAILED(hr)) continue;
4343 for (j = 0; j < test_data[i].num_faces * 3; j++)
4344 ok(adjacency[j] == test_data[i].adjacency[j],
4345 "Test %d adjacency %d: Got result %u, expected %u\n", i, j,
4346 adjacency[j], test_data[i].adjacency[j]);
4348 if (d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh);
4351 static void test_update_semantics(void)
4353 HRESULT hr;
4354 struct test_context *test_context = NULL;
4355 ID3DXMesh *mesh = NULL;
4356 D3DVERTEXELEMENT9 declaration0[] =
4358 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4359 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4360 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4361 D3DDECL_END()
4363 D3DVERTEXELEMENT9 declaration_pos_type_color[] =
4365 {0, 0, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4366 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4367 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4368 D3DDECL_END()
4370 D3DVERTEXELEMENT9 declaration_smaller[] =
4372 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4373 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4374 D3DDECL_END()
4376 D3DVERTEXELEMENT9 declaration_larger[] =
4378 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4379 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4380 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4381 {0, 40, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT, 0},
4382 D3DDECL_END()
4384 D3DVERTEXELEMENT9 declaration_multiple_streams[] =
4386 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4387 {1, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT, 0},
4388 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4389 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4391 D3DDECL_END()
4393 D3DVERTEXELEMENT9 declaration_double_usage[] =
4395 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4396 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4397 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4398 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4399 D3DDECL_END()
4401 D3DVERTEXELEMENT9 declaration_undefined_type[] =
4403 {0, 0, D3DDECLTYPE_UNUSED+1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4404 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4405 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4406 D3DDECL_END()
4408 D3DVERTEXELEMENT9 declaration_not_4_byte_aligned_offset[] =
4410 {0, 3, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4411 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4412 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4413 D3DDECL_END()
4415 static const struct
4417 D3DXVECTOR3 position0;
4418 D3DXVECTOR3 position1;
4419 D3DXVECTOR3 normal;
4420 DWORD color;
4422 vertices[] =
4424 { { 0.0f, 1.0f, 0.f}, { 1.0f, 0.0f, 0.f}, {0.0f, 0.0f, 1.0f}, 0xffff0000 },
4425 { { 1.0f, -1.0f, 0.f}, {-1.0f, -1.0f, 0.f}, {0.0f, 0.0f, 1.0f}, 0xff00ff00 },
4426 { {-1.0f, -1.0f, 0.f}, {-1.0f, 1.0f, 0.f}, {0.0f, 0.0f, 1.0f}, 0xff0000ff },
4428 unsigned int faces[] = {0, 1, 2};
4429 unsigned int attributes[] = {0};
4430 unsigned int num_faces = ARRAY_SIZE(faces) / 3;
4431 unsigned int num_vertices = ARRAY_SIZE(vertices);
4432 int offset = sizeof(D3DXVECTOR3);
4433 DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
4434 void *vertex_buffer;
4435 void *index_buffer;
4436 DWORD *attributes_buffer;
4437 D3DVERTEXELEMENT9 declaration[MAX_FVF_DECL_SIZE];
4438 D3DVERTEXELEMENT9 *decl_ptr;
4439 DWORD exp_vertex_size = sizeof(*vertices);
4440 DWORD vertex_size = 0;
4441 int equal;
4442 int i = 0;
4443 int *decl_mem;
4444 int filler_a = 0xaaaaaaaa;
4445 int filler_b = 0xbbbbbbbb;
4447 test_context = new_test_context();
4448 if (!test_context)
4450 skip("Couldn't create a test_context\n");
4451 goto cleanup;
4454 hr = D3DXCreateMesh(num_faces, num_vertices, options, declaration0,
4455 test_context->device, &mesh);
4456 if (FAILED(hr))
4458 skip("Couldn't create test mesh %#x\n", hr);
4459 goto cleanup;
4462 mesh->lpVtbl->LockVertexBuffer(mesh, 0, &vertex_buffer);
4463 memcpy(vertex_buffer, vertices, sizeof(vertices));
4464 mesh->lpVtbl->UnlockVertexBuffer(mesh);
4466 mesh->lpVtbl->LockIndexBuffer(mesh, 0, &index_buffer);
4467 memcpy(index_buffer, faces, sizeof(faces));
4468 mesh->lpVtbl->UnlockIndexBuffer(mesh);
4470 mesh->lpVtbl->LockAttributeBuffer(mesh, 0, &attributes_buffer);
4471 memcpy(attributes_buffer, attributes, sizeof(attributes));
4472 mesh->lpVtbl->UnlockAttributeBuffer(mesh);
4474 /* Get the declaration and try to change it */
4475 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4476 if (FAILED(hr))
4478 skip("Couldn't get vertex declaration %#x\n", hr);
4479 goto cleanup;
4481 equal = memcmp(declaration, declaration0, sizeof(declaration0));
4482 ok(equal == 0, "Vertex declarations were not equal\n");
4484 for (decl_ptr = declaration; decl_ptr->Stream != 0xFF; decl_ptr++)
4486 if (decl_ptr->Usage == D3DDECLUSAGE_POSITION)
4488 /* Use second vertex position instead of first */
4489 decl_ptr->Offset = offset;
4493 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration);
4494 ok(hr == D3D_OK, "Test UpdateSematics, got %#x expected %#x\n", hr, D3D_OK);
4496 /* Check that declaration was written by getting it again */
4497 memset(declaration, 0, sizeof(declaration));
4498 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4499 if (FAILED(hr))
4501 skip("Couldn't get vertex declaration %#x\n", hr);
4502 goto cleanup;
4505 for (decl_ptr = declaration; decl_ptr->Stream != 0xFF; decl_ptr++)
4507 if (decl_ptr->Usage == D3DDECLUSAGE_POSITION)
4509 ok(decl_ptr->Offset == offset, "Test UpdateSematics, got offset %d expected %d\n",
4510 decl_ptr->Offset, offset);
4514 /* Check that GetDeclaration only writes up to the D3DDECL_END() marker and
4515 * not the full MAX_FVF_DECL_SIZE elements.
4517 memset(declaration, filler_a, sizeof(declaration));
4518 memcpy(declaration, declaration0, sizeof(declaration0));
4519 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration);
4520 ok(hr == D3D_OK, "Test UpdateSematics, "
4521 "got %#x expected D3D_OK\n", hr);
4522 memset(declaration, filler_b, sizeof(declaration));
4523 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4524 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4525 decl_mem = (int*)declaration;
4526 for (i = sizeof(declaration0)/sizeof(*decl_mem); i < sizeof(declaration)/sizeof(*decl_mem); i++)
4528 equal = memcmp(&decl_mem[i], &filler_b, sizeof(filler_b));
4529 ok(equal == 0,
4530 "GetDeclaration wrote past the D3DDECL_END() marker. "
4531 "Got %#x, expected %#x\n", decl_mem[i], filler_b);
4532 if (equal != 0) break;
4535 /* UpdateSemantics does not check for overlapping fields */
4536 memset(declaration, 0, sizeof(declaration));
4537 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4538 if (FAILED(hr))
4540 skip("Couldn't get vertex declaration %#x\n", hr);
4541 goto cleanup;
4544 for (decl_ptr = declaration; decl_ptr->Stream != 0xFF; decl_ptr++)
4546 if (decl_ptr->Type == D3DDECLTYPE_FLOAT3)
4548 decl_ptr->Type = D3DDECLTYPE_FLOAT4;
4552 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration);
4553 ok(hr == D3D_OK, "Test UpdateSematics for overlapping fields, "
4554 "got %#x expected D3D_OK\n", hr);
4556 /* Set the position type to color instead of float3 */
4557 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_pos_type_color);
4558 ok(hr == D3D_OK, "Test UpdateSematics position type color, "
4559 "got %#x expected D3D_OK\n", hr);
4561 /* The following test cases show that NULL, smaller or larger declarations,
4562 * and declarations with non-zero Stream values are not accepted.
4563 * UpdateSemantics returns D3DERR_INVALIDCALL and the previously set
4564 * declaration will be used by DrawSubset, GetNumBytesPerVertex, and
4565 * GetDeclaration.
4568 /* Null declaration (invalid declaration) */
4569 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4570 hr = mesh->lpVtbl->UpdateSemantics(mesh, NULL);
4571 ok(hr == D3DERR_INVALIDCALL, "Test UpdateSematics null pointer declaration, "
4572 "got %#x expected D3DERR_INVALIDCALL\n", hr);
4573 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4574 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4575 vertex_size, exp_vertex_size);
4576 memset(declaration, 0, sizeof(declaration));
4577 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4578 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4579 equal = memcmp(declaration, declaration0, sizeof(declaration0));
4580 ok(equal == 0, "Vertex declarations were not equal\n");
4582 /* Smaller vertex declaration (invalid declaration) */
4583 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4584 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_smaller);
4585 ok(hr == D3DERR_INVALIDCALL, "Test UpdateSematics for smaller vertex declaration, "
4586 "got %#x expected D3DERR_INVALIDCALL\n", hr);
4587 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4588 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4589 vertex_size, exp_vertex_size);
4590 memset(declaration, 0, sizeof(declaration));
4591 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4592 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4593 equal = memcmp(declaration, declaration0, sizeof(declaration0));
4594 ok(equal == 0, "Vertex declarations were not equal\n");
4596 /* Larger vertex declaration (invalid declaration) */
4597 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4598 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_larger);
4599 ok(hr == D3DERR_INVALIDCALL, "Test UpdateSematics for larger vertex declaration, "
4600 "got %#x expected D3DERR_INVALIDCALL\n", hr);
4601 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4602 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4603 vertex_size, exp_vertex_size);
4604 memset(declaration, 0, sizeof(declaration));
4605 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4606 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4607 equal = memcmp(declaration, declaration0, sizeof(declaration0));
4608 ok(equal == 0, "Vertex declarations were not equal\n");
4610 /* Use multiple streams and keep the same vertex size (invalid declaration) */
4611 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4612 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_multiple_streams);
4613 ok(hr == D3DERR_INVALIDCALL, "Test UpdateSematics using multiple streams, "
4614 "got %#x expected D3DERR_INVALIDCALL\n", hr);
4615 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4616 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4617 vertex_size, exp_vertex_size);
4618 memset(declaration, 0, sizeof(declaration));
4619 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4620 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4621 equal = memcmp(declaration, declaration0, sizeof(declaration0));
4622 ok(equal == 0, "Vertex declarations were not equal\n");
4624 /* The next following test cases show that some invalid declarations are
4625 * accepted with a D3D_OK. An access violation is thrown on Windows if
4626 * DrawSubset is called. The methods GetNumBytesPerVertex and GetDeclaration
4627 * are not affected, which indicates that the declaration is cached.
4630 /* Double usage (invalid declaration) */
4631 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4632 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_double_usage);
4633 ok(hr == D3D_OK, "Test UpdateSematics double usage, "
4634 "got %#x expected D3D_OK\n", hr);
4635 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4636 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4637 vertex_size, exp_vertex_size);
4638 memset(declaration, 0, sizeof(declaration));
4639 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4640 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4641 equal = memcmp(declaration, declaration_double_usage, sizeof(declaration_double_usage));
4642 ok(equal == 0, "Vertex declarations were not equal\n");
4644 /* Set the position to an undefined type (invalid declaration) */
4645 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4646 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_undefined_type);
4647 ok(hr == D3D_OK, "Test UpdateSematics undefined type, "
4648 "got %#x expected D3D_OK\n", hr);
4649 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4650 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4651 vertex_size, exp_vertex_size);
4652 memset(declaration, 0, sizeof(declaration));
4653 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4654 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4655 equal = memcmp(declaration, declaration_undefined_type, sizeof(declaration_undefined_type));
4656 ok(equal == 0, "Vertex declarations were not equal\n");
4658 /* Use a not 4 byte aligned offset (invalid declaration) */
4659 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4660 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_not_4_byte_aligned_offset);
4661 ok(hr == D3D_OK, "Test UpdateSematics not 4 byte aligned offset, "
4662 "got %#x expected D3D_OK\n", hr);
4663 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4664 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4665 vertex_size, exp_vertex_size);
4666 memset(declaration, 0, sizeof(declaration));
4667 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4668 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4669 equal = memcmp(declaration, declaration_not_4_byte_aligned_offset,
4670 sizeof(declaration_not_4_byte_aligned_offset));
4671 ok(equal == 0, "Vertex declarations were not equal\n");
4673 cleanup:
4674 if (mesh)
4675 mesh->lpVtbl->Release(mesh);
4677 free_test_context(test_context);
4680 static void test_create_skin_info(void)
4682 HRESULT hr;
4683 ID3DXSkinInfo *skininfo = NULL;
4684 D3DVERTEXELEMENT9 empty_declaration[] = { D3DDECL_END() };
4685 D3DVERTEXELEMENT9 declaration_out[MAX_FVF_DECL_SIZE];
4686 const D3DVERTEXELEMENT9 declaration_with_nonzero_stream[] = {
4687 {1, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
4688 D3DDECL_END()
4691 hr = D3DXCreateSkinInfo(0, empty_declaration, 0, &skininfo);
4692 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4693 if (skininfo) IUnknown_Release(skininfo);
4694 skininfo = NULL;
4696 hr = D3DXCreateSkinInfo(1, NULL, 1, &skininfo);
4697 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4699 hr = D3DXCreateSkinInfo(1, declaration_with_nonzero_stream, 1, &skininfo);
4700 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4702 hr = D3DXCreateSkinInfoFVF(1, 0, 1, &skininfo);
4703 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4704 if (skininfo) {
4705 DWORD dword_result;
4706 FLOAT flt_result;
4707 LPCSTR string_result;
4708 D3DXMATRIX *transform;
4709 D3DXMATRIX identity_matrix;
4711 /* test initial values */
4712 hr = skininfo->lpVtbl->GetDeclaration(skininfo, declaration_out);
4713 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4714 if (SUCCEEDED(hr))
4715 compare_elements(declaration_out, empty_declaration, __LINE__, 0);
4717 dword_result = skininfo->lpVtbl->GetNumBones(skininfo);
4718 ok(dword_result == 1, "Expected 1, got %u\n", dword_result);
4720 flt_result = skininfo->lpVtbl->GetMinBoneInfluence(skininfo);
4721 ok(flt_result == 0.0f, "Expected 0.0, got %g\n", flt_result);
4723 string_result = skininfo->lpVtbl->GetBoneName(skininfo, 0);
4724 ok(string_result == NULL, "Expected NULL, got %p\n", string_result);
4726 dword_result = skininfo->lpVtbl->GetFVF(skininfo);
4727 ok(dword_result == 0, "Expected 0, got %u\n", dword_result);
4729 dword_result = skininfo->lpVtbl->GetNumBoneInfluences(skininfo, 0);
4730 ok(dword_result == 0, "Expected 0, got %u\n", dword_result);
4732 dword_result = skininfo->lpVtbl->GetNumBoneInfluences(skininfo, 1);
4733 ok(dword_result == 0, "Expected 0, got %u\n", dword_result);
4735 transform = skininfo->lpVtbl->GetBoneOffsetMatrix(skininfo, -1);
4736 ok(transform == NULL, "Expected NULL, got %p\n", transform);
4739 /* test [GS]etBoneOffsetMatrix */
4740 hr = skininfo->lpVtbl->SetBoneOffsetMatrix(skininfo, 1, &identity_matrix);
4741 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4743 hr = skininfo->lpVtbl->SetBoneOffsetMatrix(skininfo, 0, NULL);
4744 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4746 D3DXMatrixIdentity(&identity_matrix);
4747 hr = skininfo->lpVtbl->SetBoneOffsetMatrix(skininfo, 0, &identity_matrix);
4748 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4750 transform = skininfo->lpVtbl->GetBoneOffsetMatrix(skininfo, 0);
4751 check_matrix(transform, &identity_matrix);
4755 /* test [GS]etBoneName */
4756 const char *name_in = "testBoneName";
4757 const char *string_result2;
4759 hr = skininfo->lpVtbl->SetBoneName(skininfo, 1, name_in);
4760 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4762 hr = skininfo->lpVtbl->SetBoneName(skininfo, 0, NULL);
4763 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4765 hr = skininfo->lpVtbl->SetBoneName(skininfo, 0, name_in);
4766 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4768 string_result = skininfo->lpVtbl->GetBoneName(skininfo, 0);
4769 ok(string_result != NULL, "Expected non-NULL string, got %p\n", string_result);
4770 ok(!strcmp(string_result, name_in), "Expected '%s', got '%s'\n", name_in, string_result);
4772 string_result2 = skininfo->lpVtbl->GetBoneName(skininfo, 0);
4773 ok(string_result == string_result2, "Expected %p, got %p\n", string_result, string_result2);
4775 string_result = skininfo->lpVtbl->GetBoneName(skininfo, 1);
4776 ok(string_result == NULL, "Expected NULL, got %p\n", string_result);
4780 /* test [GS]etBoneInfluence */
4781 DWORD vertices[2];
4782 FLOAT weights[2];
4783 int i;
4784 DWORD num_influences;
4785 DWORD exp_vertices[2];
4786 FLOAT exp_weights[2];
4788 /* vertex and weight arrays untouched when num_influences is 0 */
4789 vertices[0] = 0xdeadbeef;
4790 weights[0] = FLT_MAX;
4791 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, vertices, weights);
4792 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4793 ok(vertices[0] == 0xdeadbeef, "expected 0xdeadbeef, got %#x\n", vertices[0]);
4794 ok(weights[0] == FLT_MAX, "expected %g, got %g\n", FLT_MAX, weights[0]);
4796 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 1, vertices, weights);
4797 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4799 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, NULL, NULL);
4800 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4802 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, vertices, NULL);
4803 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4805 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, NULL, weights);
4806 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4809 /* no vertex or weight value checking */
4810 exp_vertices[0] = 0;
4811 exp_vertices[1] = 0x87654321;
4812 exp_weights[0] = 0.5;
4813 exp_weights[1] = 0.0f / 0.0f; /* NAN */
4814 num_influences = 2;
4816 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 1, num_influences, vertices, weights);
4817 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4819 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, num_influences, NULL, weights);
4820 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4822 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, num_influences, vertices, NULL);
4823 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4825 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, num_influences, NULL, NULL);
4826 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4828 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, num_influences, exp_vertices, exp_weights);
4829 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4831 memset(vertices, 0, sizeof(vertices));
4832 memset(weights, 0, sizeof(weights));
4833 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, vertices, weights);
4834 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4835 for (i = 0; i < num_influences; i++) {
4836 ok(exp_vertices[i] == vertices[i],
4837 "influence[%d]: expected vertex %u, got %u\n", i, exp_vertices[i], vertices[i]);
4838 ok((isnan(exp_weights[i]) && isnan(weights[i])) || exp_weights[i] == weights[i],
4839 "influence[%d]: expected weights %g, got %g\n", i, exp_weights[i], weights[i]);
4842 /* vertices and weights aren't returned after setting num_influences to 0 */
4843 memset(vertices, 0, sizeof(vertices));
4844 memset(weights, 0, sizeof(weights));
4845 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, 0, vertices, weights);
4846 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4848 vertices[0] = 0xdeadbeef;
4849 weights[0] = FLT_MAX;
4850 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, vertices, weights);
4851 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4852 ok(vertices[0] == 0xdeadbeef, "expected vertex 0xdeadbeef, got %u\n", vertices[0]);
4853 ok(weights[0] == FLT_MAX, "expected weight %g, got %g\n", FLT_MAX, weights[0]);
4857 /* test [GS]etFVF and [GS]etDeclaration */
4858 D3DVERTEXELEMENT9 declaration_in[MAX_FVF_DECL_SIZE];
4859 DWORD fvf = D3DFVF_XYZ;
4860 DWORD got_fvf;
4862 hr = skininfo->lpVtbl->SetDeclaration(skininfo, NULL);
4863 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4865 hr = skininfo->lpVtbl->SetDeclaration(skininfo, declaration_with_nonzero_stream);
4866 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4868 hr = skininfo->lpVtbl->SetFVF(skininfo, 0);
4869 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4871 hr = D3DXDeclaratorFromFVF(fvf, declaration_in);
4872 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4873 hr = skininfo->lpVtbl->SetDeclaration(skininfo, declaration_in);
4874 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4875 got_fvf = skininfo->lpVtbl->GetFVF(skininfo);
4876 ok(fvf == got_fvf, "Expected %#x, got %#x\n", fvf, got_fvf);
4877 hr = skininfo->lpVtbl->GetDeclaration(skininfo, declaration_out);
4878 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4879 compare_elements(declaration_out, declaration_in, __LINE__, 0);
4881 hr = skininfo->lpVtbl->SetDeclaration(skininfo, empty_declaration);
4882 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4883 got_fvf = skininfo->lpVtbl->GetFVF(skininfo);
4884 ok(got_fvf == 0, "Expected 0, got %#x\n", got_fvf);
4885 hr = skininfo->lpVtbl->GetDeclaration(skininfo, declaration_out);
4886 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4887 compare_elements(declaration_out, empty_declaration, __LINE__, 0);
4889 hr = skininfo->lpVtbl->SetFVF(skininfo, fvf);
4890 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4891 got_fvf = skininfo->lpVtbl->GetFVF(skininfo);
4892 ok(fvf == got_fvf, "Expected %#x, got %#x\n", fvf, got_fvf);
4893 hr = skininfo->lpVtbl->GetDeclaration(skininfo, declaration_out);
4894 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4895 compare_elements(declaration_out, declaration_in, __LINE__, 0);
4898 if (skininfo) IUnknown_Release(skininfo);
4899 skininfo = NULL;
4901 hr = D3DXCreateSkinInfoFVF(1, D3DFVF_XYZ, 1, NULL);
4902 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4904 hr = D3DXCreateSkinInfo(1, NULL, 1, &skininfo);
4905 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4908 static void test_convert_adjacency_to_point_reps(void)
4910 HRESULT hr;
4911 struct test_context *test_context = NULL;
4912 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
4913 const DWORD options_16bit = D3DXMESH_SYSTEMMEM;
4914 const D3DVERTEXELEMENT9 declaration[] =
4916 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4917 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4918 {0, 24, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4919 D3DDECL_END()
4921 const unsigned int VERTS_PER_FACE = 3;
4922 void *vertex_buffer;
4923 void *index_buffer;
4924 DWORD *attributes_buffer;
4925 int i, j;
4926 enum color { RED = 0xffff0000, GREEN = 0xff00ff00, BLUE = 0xff0000ff};
4927 struct vertex_pnc
4929 D3DXVECTOR3 position;
4930 D3DXVECTOR3 normal;
4931 enum color color; /* In case of manual visual inspection */
4933 D3DXVECTOR3 up = {0.0f, 0.0f, 1.0f};
4934 /* mesh0 (one face)
4936 * 0--1
4937 * | /
4938 * |/
4941 const struct vertex_pnc vertices0[] =
4943 {{ 0.0f, 3.0f, 0.f}, up, RED},
4944 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
4945 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
4947 const DWORD indices0[] = {0, 1, 2};
4948 const unsigned int num_vertices0 = ARRAY_SIZE(vertices0);
4949 const unsigned int num_faces0 = ARRAY_SIZE(indices0) / VERTS_PER_FACE;
4950 const DWORD adjacency0[] = {-1, -1, -1};
4951 const DWORD exp_point_rep0[] = {0, 1, 2};
4952 /* mesh1 (right)
4954 * 0--1 3
4955 * | / /|
4956 * |/ / |
4957 * 2 5--4
4959 const struct vertex_pnc vertices1[] =
4961 {{ 0.0f, 3.0f, 0.f}, up, RED},
4962 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
4963 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
4965 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
4966 {{ 3.0f, 0.0f, 0.f}, up, RED},
4967 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
4969 const DWORD indices1[] = {0, 1, 2, 3, 4, 5};
4970 const unsigned int num_vertices1 = ARRAY_SIZE(vertices1);
4971 const unsigned int num_faces1 = ARRAY_SIZE(indices1) / VERTS_PER_FACE;
4972 const DWORD adjacency1[] = {-1, 1, -1, -1, -1, 0};
4973 const DWORD exp_point_rep1[] = {0, 1, 2, 1, 4, 2};
4974 /* mesh2 (left)
4976 * 3 0--1
4977 * /| | /
4978 * / | |/
4979 * 5--4 2
4981 const struct vertex_pnc vertices2[] =
4983 {{ 0.0f, 3.0f, 0.f}, up, RED},
4984 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
4985 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
4987 {{-1.0f, 3.0f, 0.f}, up, RED},
4988 {{-1.0f, 0.0f, 0.f}, up, GREEN},
4989 {{-3.0f, 0.0f, 0.f}, up, BLUE},
4991 const DWORD indices2[] = {0, 1, 2, 3, 4, 5};
4992 const unsigned int num_vertices2 = ARRAY_SIZE(vertices2);
4993 const unsigned int num_faces2 = ARRAY_SIZE(indices2) / VERTS_PER_FACE;
4994 const DWORD adjacency2[] = {-1, -1, 1, 0, -1, -1};
4995 const DWORD exp_point_rep2[] = {0, 1, 2, 0, 2, 5};
4996 /* mesh3 (above)
4999 * /|
5000 * / |
5001 * 5--4
5002 * 0--1
5003 * | /
5004 * |/
5007 struct vertex_pnc vertices3[] =
5009 {{ 0.0f, 3.0f, 0.f}, up, RED},
5010 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5011 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5013 {{ 2.0f, 7.0f, 0.f}, up, BLUE},
5014 {{ 2.0f, 4.0f, 0.f}, up, GREEN},
5015 {{ 0.0f, 4.0f, 0.f}, up, RED},
5017 const DWORD indices3[] = {0, 1, 2, 3, 4, 5};
5018 const unsigned int num_vertices3 = ARRAY_SIZE(vertices3);
5019 const unsigned int num_faces3 = ARRAY_SIZE(indices3) / VERTS_PER_FACE;
5020 const DWORD adjacency3[] = {1, -1, -1, -1, 0, -1};
5021 const DWORD exp_point_rep3[] = {0, 1, 2, 3, 1, 0};
5022 /* mesh4 (below, tip against tip)
5024 * 0--1
5025 * | /
5026 * |/
5029 * |\
5030 * | \
5031 * 5--4
5033 struct vertex_pnc vertices4[] =
5035 {{ 0.0f, 3.0f, 0.f}, up, RED},
5036 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5037 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5039 {{ 0.0f, -4.0f, 0.f}, up, BLUE},
5040 {{ 2.0f, -7.0f, 0.f}, up, GREEN},
5041 {{ 0.0f, -7.0f, 0.f}, up, RED},
5043 const DWORD indices4[] = {0, 1, 2, 3, 4, 5};
5044 const unsigned int num_vertices4 = ARRAY_SIZE(vertices4);
5045 const unsigned int num_faces4 = ARRAY_SIZE(indices4) / VERTS_PER_FACE;
5046 const DWORD adjacency4[] = {-1, -1, -1, -1, -1, -1};
5047 const DWORD exp_point_rep4[] = {0, 1, 2, 3, 4, 5};
5048 /* mesh5 (gap in mesh)
5050 * 0 3-----4 15
5051 * / \ \ / / \
5052 * / \ \ / / \
5053 * 2-----1 5 17-----16
5054 * 6-----7 9 12-----13
5055 * \ / / \ \ /
5056 * \ / / \ \ /
5057 * 8 10-----11 14
5060 const struct vertex_pnc vertices5[] =
5062 {{ 0.0f, 1.0f, 0.f}, up, RED},
5063 {{ 1.0f, -1.0f, 0.f}, up, GREEN},
5064 {{-1.0f, -1.0f, 0.f}, up, BLUE},
5066 {{ 0.1f, 1.0f, 0.f}, up, RED},
5067 {{ 2.1f, 1.0f, 0.f}, up, BLUE},
5068 {{ 1.1f, -1.0f, 0.f}, up, GREEN},
5070 {{-1.0f, -1.1f, 0.f}, up, BLUE},
5071 {{ 1.0f, -1.1f, 0.f}, up, GREEN},
5072 {{ 0.0f, -3.1f, 0.f}, up, RED},
5074 {{ 1.1f, -1.1f, 0.f}, up, GREEN},
5075 {{ 2.1f, -3.1f, 0.f}, up, BLUE},
5076 {{ 0.1f, -3.1f, 0.f}, up, RED},
5078 {{ 1.2f, -1.1f, 0.f}, up, GREEN},
5079 {{ 3.2f, -1.1f, 0.f}, up, RED},
5080 {{ 2.2f, -3.1f, 0.f}, up, BLUE},
5082 {{ 2.2f, 1.0f, 0.f}, up, BLUE},
5083 {{ 3.2f, -1.0f, 0.f}, up, RED},
5084 {{ 1.2f, -1.0f, 0.f}, up, GREEN},
5086 const DWORD indices5[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17};
5087 const unsigned int num_vertices5 = ARRAY_SIZE(vertices5);
5088 const unsigned int num_faces5 = ARRAY_SIZE(indices5) / VERTS_PER_FACE;
5089 const DWORD adjacency5[] = {-1, 2, -1, -1, 5, -1, 0, -1, -1, 4, -1, -1, 5, -1, 3, -1, 4, 1};
5090 const DWORD exp_point_rep5[] = {0, 1, 2, 3, 4, 5, 2, 1, 8, 5, 10, 11, 5, 13, 10, 4, 13, 5};
5091 const WORD indices5_16bit[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17};
5092 /* mesh6 (indices re-ordering)
5094 * 0--1 6 3
5095 * | / /| |\
5096 * |/ / | | \
5097 * 2 8--7 5--4
5099 const struct vertex_pnc vertices6[] =
5101 {{ 0.0f, 3.0f, 0.f}, up, RED},
5102 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5103 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5105 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5106 {{ 3.0f, 0.0f, 0.f}, up, RED},
5107 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5109 {{ 4.0f, 3.0f, 0.f}, up, GREEN},
5110 {{ 6.0f, 0.0f, 0.f}, up, BLUE},
5111 {{ 4.0f, 0.0f, 0.f}, up, RED},
5113 const DWORD indices6[] = {0, 1, 2, 6, 7, 8, 3, 4, 5};
5114 const unsigned int num_vertices6 = ARRAY_SIZE(vertices6);
5115 const unsigned int num_faces6 = ARRAY_SIZE(indices6) / VERTS_PER_FACE;
5116 const DWORD adjacency6[] = {-1, 1, -1, 2, -1, 0, -1, -1, 1};
5117 const DWORD exp_point_rep6[] = {0, 1, 2, 1, 4, 5, 1, 5, 2};
5118 /* mesh7 (expands collapsed triangle)
5120 * 0--1 3
5121 * | / /|
5122 * |/ / |
5123 * 2 5--4
5125 const struct vertex_pnc vertices7[] =
5127 {{ 0.0f, 3.0f, 0.f}, up, RED},
5128 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5129 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5131 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5132 {{ 3.0f, 0.0f, 0.f}, up, RED},
5133 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5135 const DWORD indices7[] = {0, 1, 2, 3, 3, 3}; /* Face 1 is collapsed*/
5136 const unsigned int num_vertices7 = ARRAY_SIZE(vertices7);
5137 const unsigned int num_faces7 = ARRAY_SIZE(indices7) / VERTS_PER_FACE;
5138 const DWORD adjacency7[] = {-1, -1, -1, -1, -1, -1};
5139 const DWORD exp_point_rep7[] = {0, 1, 2, 3, 4, 5};
5140 /* mesh8 (indices re-ordering and double replacement)
5142 * 0--1 9 6
5143 * | / /| |\
5144 * |/ / | | \
5145 * 2 11-10 8--7
5146 * 3--4
5147 * | /
5148 * |/
5151 const struct vertex_pnc vertices8[] =
5153 {{ 0.0f, 3.0f, 0.f}, up, RED},
5154 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5155 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5157 {{ 4.0, -4.0, 0.f}, up, RED},
5158 {{ 6.0, -4.0, 0.f}, up, BLUE},
5159 {{ 4.0, -7.0, 0.f}, up, GREEN},
5161 {{ 4.0f, 3.0f, 0.f}, up, GREEN},
5162 {{ 6.0f, 0.0f, 0.f}, up, BLUE},
5163 {{ 4.0f, 0.0f, 0.f}, up, RED},
5165 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5166 {{ 3.0f, 0.0f, 0.f}, up, RED},
5167 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5169 const DWORD indices8[] = {0, 1, 2, 9, 10, 11, 6, 7, 8, 3, 4, 5};
5170 const unsigned int num_vertices8 = ARRAY_SIZE(vertices8);
5171 const unsigned int num_faces8 = ARRAY_SIZE(indices8) / VERTS_PER_FACE;
5172 const DWORD adjacency8[] = {-1, 1, -1, 2, -1, 0, -1, 3, 1, 2, -1, -1};
5173 const DWORD exp_point_rep8[] = {0, 1, 2, 3, 4, 5, 1, 4, 3, 1, 3, 2};
5174 /* mesh9 (right, shared vertices)
5176 * 0--1
5177 * | /|
5178 * |/ |
5179 * 2--3
5181 const struct vertex_pnc vertices9[] =
5183 {{ 0.0f, 3.0f, 0.f}, up, RED},
5184 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5185 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5187 {{ 2.0f, 0.0f, 0.f}, up, RED},
5189 const DWORD indices9[] = {0, 1, 2, 1, 3, 2};
5190 const unsigned int num_vertices9 = ARRAY_SIZE(vertices9);
5191 const unsigned int num_faces9 = ARRAY_SIZE(indices9) / VERTS_PER_FACE;
5192 const DWORD adjacency9[] = {-1, 1, -1, -1, -1, 0};
5193 const DWORD exp_point_rep9[] = {0, 1, 2, 3};
5194 /* All mesh data */
5195 ID3DXMesh *mesh = NULL;
5196 ID3DXMesh *mesh_null_check = NULL;
5197 unsigned int attributes[] = {0};
5198 struct
5200 const struct vertex_pnc *vertices;
5201 const DWORD *indices;
5202 const DWORD num_vertices;
5203 const DWORD num_faces;
5204 const DWORD *adjacency;
5205 const DWORD *exp_point_reps;
5206 const DWORD options;
5208 tc[] =
5211 vertices0,
5212 indices0,
5213 num_vertices0,
5214 num_faces0,
5215 adjacency0,
5216 exp_point_rep0,
5217 options
5220 vertices1,
5221 indices1,
5222 num_vertices1,
5223 num_faces1,
5224 adjacency1,
5225 exp_point_rep1,
5226 options
5229 vertices2,
5230 indices2,
5231 num_vertices2,
5232 num_faces2,
5233 adjacency2,
5234 exp_point_rep2,
5235 options
5238 vertices3,
5239 indices3,
5240 num_vertices3,
5241 num_faces3,
5242 adjacency3,
5243 exp_point_rep3,
5244 options
5247 vertices4,
5248 indices4,
5249 num_vertices4,
5250 num_faces4,
5251 adjacency4,
5252 exp_point_rep4,
5253 options
5256 vertices5,
5257 indices5,
5258 num_vertices5,
5259 num_faces5,
5260 adjacency5,
5261 exp_point_rep5,
5262 options
5265 vertices6,
5266 indices6,
5267 num_vertices6,
5268 num_faces6,
5269 adjacency6,
5270 exp_point_rep6,
5271 options
5274 vertices7,
5275 indices7,
5276 num_vertices7,
5277 num_faces7,
5278 adjacency7,
5279 exp_point_rep7,
5280 options
5283 vertices8,
5284 indices8,
5285 num_vertices8,
5286 num_faces8,
5287 adjacency8,
5288 exp_point_rep8,
5289 options
5292 vertices9,
5293 indices9,
5294 num_vertices9,
5295 num_faces9,
5296 adjacency9,
5297 exp_point_rep9,
5298 options
5301 vertices5,
5302 (DWORD*)indices5_16bit,
5303 num_vertices5,
5304 num_faces5,
5305 adjacency5,
5306 exp_point_rep5,
5307 options_16bit
5310 DWORD *point_reps = NULL;
5312 test_context = new_test_context();
5313 if (!test_context)
5315 skip("Couldn't create test context\n");
5316 goto cleanup;
5319 for (i = 0; i < ARRAY_SIZE(tc); i++)
5321 hr = D3DXCreateMesh(tc[i].num_faces, tc[i].num_vertices, tc[i].options, declaration,
5322 test_context->device, &mesh);
5323 if (FAILED(hr))
5325 skip("Couldn't create mesh %d. Got %x expected D3D_OK\n", i, hr);
5326 goto cleanup;
5329 if (i == 0) /* Save first mesh for later NULL checks */
5330 mesh_null_check = mesh;
5332 point_reps = HeapAlloc(GetProcessHeap(), 0, tc[i].num_vertices * sizeof(*point_reps));
5333 if (!point_reps)
5335 skip("Couldn't allocate point reps array.\n");
5336 goto cleanup;
5339 hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, &vertex_buffer);
5340 if (FAILED(hr))
5342 skip("Couldn't lock vertex buffer.\n");
5343 goto cleanup;
5345 memcpy(vertex_buffer, tc[i].vertices, tc[i].num_vertices * sizeof(*tc[i].vertices));
5346 hr = mesh->lpVtbl->UnlockVertexBuffer(mesh);
5347 if (FAILED(hr))
5349 skip("Couldn't unlock vertex buffer.\n");
5350 goto cleanup;
5353 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, &index_buffer);
5354 if (FAILED(hr))
5356 skip("Couldn't lock index buffer.\n");
5357 goto cleanup;
5359 if (tc[i].options & D3DXMESH_32BIT)
5361 memcpy(index_buffer, tc[i].indices, VERTS_PER_FACE * tc[i].num_faces * sizeof(DWORD));
5363 else
5365 memcpy(index_buffer, tc[i].indices, VERTS_PER_FACE * tc[i].num_faces * sizeof(WORD));
5367 hr = mesh->lpVtbl->UnlockIndexBuffer(mesh);
5368 if (FAILED(hr)) {
5369 skip("Couldn't unlock index buffer.\n");
5370 goto cleanup;
5373 hr = mesh->lpVtbl->LockAttributeBuffer(mesh, 0, &attributes_buffer);
5374 if (FAILED(hr))
5376 skip("Couldn't lock attributes buffer.\n");
5377 goto cleanup;
5379 memcpy(attributes_buffer, attributes, sizeof(attributes));
5380 hr = mesh->lpVtbl->UnlockAttributeBuffer(mesh);
5381 if (FAILED(hr))
5383 skip("Couldn't unlock attributes buffer.\n");
5384 goto cleanup;
5387 /* Convert adjacency to point representation */
5388 for (j = 0; j < tc[i].num_vertices; j++) point_reps[j] = -1;
5389 hr = mesh->lpVtbl->ConvertAdjacencyToPointReps(mesh, tc[i].adjacency, point_reps);
5390 ok(hr == D3D_OK, "ConvertAdjacencyToPointReps failed case %d. "
5391 "Got %x expected D3D_OK\n", i, hr);
5393 /* Check point representation */
5394 for (j = 0; j < tc[i].num_vertices; j++)
5396 ok(point_reps[j] == tc[i].exp_point_reps[j],
5397 "Unexpected point representation at (%d, %d)."
5398 " Got %d expected %d\n",
5399 i, j, point_reps[j], tc[i].exp_point_reps[j]);
5402 HeapFree(GetProcessHeap(), 0, point_reps);
5403 point_reps = NULL;
5405 if (i != 0) /* First mesh will be freed during cleanup */
5406 mesh->lpVtbl->Release(mesh);
5409 /* NULL checks */
5410 hr = mesh_null_check->lpVtbl->ConvertAdjacencyToPointReps(mesh_null_check, tc[0].adjacency, NULL);
5411 ok(hr == D3DERR_INVALIDCALL, "ConvertAdjacencyToPointReps point_reps NULL. "
5412 "Got %x expected D3DERR_INVALIDCALL\n", hr);
5413 hr = mesh_null_check->lpVtbl->ConvertAdjacencyToPointReps(mesh_null_check, NULL, NULL);
5414 ok(hr == D3DERR_INVALIDCALL, "ConvertAdjacencyToPointReps adjacency and point_reps NULL. "
5415 "Got %x expected D3DERR_INVALIDCALL\n", hr);
5417 cleanup:
5418 if (mesh_null_check)
5419 mesh_null_check->lpVtbl->Release(mesh_null_check);
5420 HeapFree(GetProcessHeap(), 0, point_reps);
5421 free_test_context(test_context);
5424 static void test_convert_point_reps_to_adjacency(void)
5426 HRESULT hr;
5427 struct test_context *test_context = NULL;
5428 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
5429 const DWORD options_16bit = D3DXMESH_SYSTEMMEM;
5430 const D3DVERTEXELEMENT9 declaration[] =
5432 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
5433 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
5434 {0, 24, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
5435 D3DDECL_END()
5437 const unsigned int VERTS_PER_FACE = 3;
5438 void *vertex_buffer;
5439 void *index_buffer;
5440 DWORD *attributes_buffer;
5441 int i, j;
5442 enum color { RED = 0xffff0000, GREEN = 0xff00ff00, BLUE = 0xff0000ff};
5443 struct vertex_pnc
5445 D3DXVECTOR3 position;
5446 D3DXVECTOR3 normal;
5447 enum color color; /* In case of manual visual inspection */
5449 D3DXVECTOR3 up = {0.0f, 0.0f, 1.0f};
5450 /* mesh0 (one face)
5452 * 0--1
5453 * | /
5454 * |/
5457 const struct vertex_pnc vertices0[] =
5459 {{ 0.0f, 3.0f, 0.f}, up, RED},
5460 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5461 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5463 const DWORD indices0[] = {0, 1, 2};
5464 const unsigned int num_vertices0 = ARRAY_SIZE(vertices0);
5465 const unsigned int num_faces0 = num_vertices0 / VERTS_PER_FACE;
5466 const DWORD exp_adjacency0[] = {-1, -1, -1};
5467 const DWORD exp_id_adjacency0[] = {-1, -1, -1};
5468 const DWORD point_rep0[] = {0, 1, 2};
5469 /* mesh1 (right)
5471 * 0--1 3
5472 * | / /|
5473 * |/ / |
5474 * 2 5--4
5476 const struct vertex_pnc vertices1[] =
5478 {{ 0.0f, 3.0f, 0.f}, up, RED},
5479 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5480 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5482 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5483 {{ 3.0f, 0.0f, 0.f}, up, RED},
5484 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5486 const DWORD indices1[] = {0, 1, 2, 3, 4, 5};
5487 const unsigned int num_vertices1 = ARRAY_SIZE(vertices1);
5488 const unsigned int num_faces1 = num_vertices1 / VERTS_PER_FACE;
5489 const DWORD exp_adjacency1[] = {-1, 1, -1, -1, -1, 0};
5490 const DWORD exp_id_adjacency1[] = {-1, -1, -1, -1, -1, -1};
5491 const DWORD point_rep1[] = {0, 1, 2, 1, 4, 2};
5492 /* mesh2 (left)
5494 * 3 0--1
5495 * /| | /
5496 * / | |/
5497 * 5--4 2
5499 const struct vertex_pnc vertices2[] =
5501 {{ 0.0f, 3.0f, 0.f}, up, RED},
5502 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5503 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5505 {{-1.0f, 3.0f, 0.f}, up, RED},
5506 {{-1.0f, 0.0f, 0.f}, up, GREEN},
5507 {{-3.0f, 0.0f, 0.f}, up, BLUE},
5509 const DWORD indices2[] = {0, 1, 2, 3, 4, 5};
5510 const unsigned int num_vertices2 = ARRAY_SIZE(vertices2);
5511 const unsigned int num_faces2 = num_vertices2 / VERTS_PER_FACE;
5512 const DWORD exp_adjacency2[] = {-1, -1, 1, 0, -1, -1};
5513 const DWORD exp_id_adjacency2[] = {-1, -1, -1, -1, -1, -1};
5514 const DWORD point_rep2[] = {0, 1, 2, 0, 2, 5};
5515 /* mesh3 (above)
5518 * /|
5519 * / |
5520 * 5--4
5521 * 0--1
5522 * | /
5523 * |/
5526 struct vertex_pnc vertices3[] =
5528 {{ 0.0f, 3.0f, 0.f}, up, RED},
5529 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5530 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5532 {{ 2.0f, 7.0f, 0.f}, up, BLUE},
5533 {{ 2.0f, 4.0f, 0.f}, up, GREEN},
5534 {{ 0.0f, 4.0f, 0.f}, up, RED},
5536 const DWORD indices3[] = {0, 1, 2, 3, 4, 5};
5537 const unsigned int num_vertices3 = ARRAY_SIZE(vertices3);
5538 const unsigned int num_faces3 = num_vertices3 / VERTS_PER_FACE;
5539 const DWORD exp_adjacency3[] = {1, -1, -1, -1, 0, -1};
5540 const DWORD exp_id_adjacency3[] = {-1, -1, -1, -1, -1, -1};
5541 const DWORD point_rep3[] = {0, 1, 2, 3, 1, 0};
5542 /* mesh4 (below, tip against tip)
5544 * 0--1
5545 * | /
5546 * |/
5549 * |\
5550 * | \
5551 * 5--4
5553 struct vertex_pnc vertices4[] =
5555 {{ 0.0f, 3.0f, 0.f}, up, RED},
5556 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5557 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5559 {{ 0.0f, -4.0f, 0.f}, up, BLUE},
5560 {{ 2.0f, -7.0f, 0.f}, up, GREEN},
5561 {{ 0.0f, -7.0f, 0.f}, up, RED},
5563 const DWORD indices4[] = {0, 1, 2, 3, 4, 5};
5564 const unsigned int num_vertices4 = ARRAY_SIZE(vertices4);
5565 const unsigned int num_faces4 = num_vertices4 / VERTS_PER_FACE;
5566 const DWORD exp_adjacency4[] = {-1, -1, -1, -1, -1, -1};
5567 const DWORD exp_id_adjacency4[] = {-1, -1, -1, -1, -1, -1};
5568 const DWORD point_rep4[] = {0, 1, 2, 3, 4, 5};
5569 /* mesh5 (gap in mesh)
5571 * 0 3-----4 15
5572 * / \ \ / / \
5573 * / \ \ / / \
5574 * 2-----1 5 17-----16
5575 * 6-----7 9 12-----13
5576 * \ / / \ \ /
5577 * \ / / \ \ /
5578 * 8 10-----11 14
5581 const struct vertex_pnc vertices5[] =
5583 {{ 0.0f, 1.0f, 0.f}, up, RED},
5584 {{ 1.0f, -1.0f, 0.f}, up, GREEN},
5585 {{-1.0f, -1.0f, 0.f}, up, BLUE},
5587 {{ 0.1f, 1.0f, 0.f}, up, RED},
5588 {{ 2.1f, 1.0f, 0.f}, up, BLUE},
5589 {{ 1.1f, -1.0f, 0.f}, up, GREEN},
5591 {{-1.0f, -1.1f, 0.f}, up, BLUE},
5592 {{ 1.0f, -1.1f, 0.f}, up, GREEN},
5593 {{ 0.0f, -3.1f, 0.f}, up, RED},
5595 {{ 1.1f, -1.1f, 0.f}, up, GREEN},
5596 {{ 2.1f, -3.1f, 0.f}, up, BLUE},
5597 {{ 0.1f, -3.1f, 0.f}, up, RED},
5599 {{ 1.2f, -1.1f, 0.f}, up, GREEN},
5600 {{ 3.2f, -1.1f, 0.f}, up, RED},
5601 {{ 2.2f, -3.1f, 0.f}, up, BLUE},
5603 {{ 2.2f, 1.0f, 0.f}, up, BLUE},
5604 {{ 3.2f, -1.0f, 0.f}, up, RED},
5605 {{ 1.2f, -1.0f, 0.f}, up, GREEN},
5607 const DWORD indices5[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17};
5608 const unsigned int num_vertices5 = ARRAY_SIZE(vertices5);
5609 const unsigned int num_faces5 = num_vertices5 / VERTS_PER_FACE;
5610 const DWORD exp_adjacency5[] = {-1, 2, -1, -1, 5, -1, 0, -1, -1, 4, -1, -1, 5, -1, 3, -1, 4, 1};
5611 const DWORD exp_id_adjacency5[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
5612 const DWORD point_rep5[] = {0, 1, 2, 3, 4, 5, 2, 1, 8, 5, 10, 11, 5, 13, 10, 4, 13, 5};
5613 /* mesh6 (indices re-ordering)
5615 * 0--1 6 3
5616 * | / /| |\
5617 * |/ / | | \
5618 * 2 8--7 5--4
5620 const struct vertex_pnc vertices6[] =
5622 {{ 0.0f, 3.0f, 0.f}, up, RED},
5623 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5624 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5626 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5627 {{ 3.0f, 0.0f, 0.f}, up, RED},
5628 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5630 {{ 4.0f, 3.0f, 0.f}, up, GREEN},
5631 {{ 6.0f, 0.0f, 0.f}, up, BLUE},
5632 {{ 4.0f, 0.0f, 0.f}, up, RED},
5634 const DWORD indices6[] = {0, 1, 2, 6, 7, 8, 3, 4, 5};
5635 const unsigned int num_vertices6 = ARRAY_SIZE(vertices6);
5636 const unsigned int num_faces6 = num_vertices6 / VERTS_PER_FACE;
5637 const DWORD exp_adjacency6[] = {-1, 1, -1, 2, -1, 0, -1, -1, 1};
5638 const DWORD exp_id_adjacency6[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1};
5639 const DWORD point_rep6[] = {0, 1, 2, 1, 4, 5, 1, 5, 2};
5640 /* mesh7 (expands collapsed triangle)
5642 * 0--1 3
5643 * | / /|
5644 * |/ / |
5645 * 2 5--4
5647 const struct vertex_pnc vertices7[] =
5649 {{ 0.0f, 3.0f, 0.f}, up, RED},
5650 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5651 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5653 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5654 {{ 3.0f, 0.0f, 0.f}, up, RED},
5655 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5657 const DWORD indices7[] = {0, 1, 2, 3, 3, 3}; /* Face 1 is collapsed*/
5658 const unsigned int num_vertices7 = ARRAY_SIZE(vertices7);
5659 const unsigned int num_faces7 = num_vertices7 / VERTS_PER_FACE;
5660 const DWORD exp_adjacency7[] = {-1, -1, -1, -1, -1, -1};
5661 const DWORD exp_id_adjacency7[] = {-1, -1, -1, -1, -1, -1};
5662 const DWORD point_rep7[] = {0, 1, 2, 3, 4, 5};
5663 /* mesh8 (indices re-ordering and double replacement)
5665 * 0--1 9 6
5666 * | / /| |\
5667 * |/ / | | \
5668 * 2 11-10 8--7
5669 * 3--4
5670 * | /
5671 * |/
5674 const struct vertex_pnc vertices8[] =
5676 {{ 0.0f, 3.0f, 0.f}, up, RED},
5677 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5678 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5680 {{ 4.0, -4.0, 0.f}, up, RED},
5681 {{ 6.0, -4.0, 0.f}, up, BLUE},
5682 {{ 4.0, -7.0, 0.f}, up, GREEN},
5684 {{ 4.0f, 3.0f, 0.f}, up, GREEN},
5685 {{ 6.0f, 0.0f, 0.f}, up, BLUE},
5686 {{ 4.0f, 0.0f, 0.f}, up, RED},
5688 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5689 {{ 3.0f, 0.0f, 0.f}, up, RED},
5690 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5692 const DWORD indices8[] = {0, 1, 2, 9, 10, 11, 6, 7, 8, 3, 4, 5};
5693 const WORD indices8_16bit[] = {0, 1, 2, 9, 10, 11, 6, 7, 8, 3, 4, 5};
5694 const unsigned int num_vertices8 = ARRAY_SIZE(vertices8);
5695 const unsigned int num_faces8 = num_vertices8 / VERTS_PER_FACE;
5696 const DWORD exp_adjacency8[] = {-1, 1, -1, 2, -1, 0, -1, 3, 1, 2, -1, -1};
5697 const DWORD exp_id_adjacency8[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
5698 const DWORD point_rep8[] = {0, 1, 2, 3, 4, 5, 1, 4, 3, 1, 3, 2};
5699 /* mesh9 (right, shared vertices)
5701 * 0--1
5702 * | /|
5703 * |/ |
5704 * 2--3
5706 const struct vertex_pnc vertices9[] =
5708 {{ 0.0f, 3.0f, 0.f}, up, RED},
5709 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5710 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5712 {{ 2.0f, 0.0f, 0.f}, up, RED},
5714 const DWORD indices9[] = {0, 1, 2, 1, 3, 2};
5715 const unsigned int num_vertices9 = ARRAY_SIZE(vertices9);
5716 const unsigned int num_faces9 = 2;
5717 const DWORD exp_adjacency9[] = {-1, 1, -1, -1, -1, 0};
5718 const DWORD exp_id_adjacency9[] = {-1, 1, -1, -1, -1, 0};
5719 const DWORD point_rep9[] = {0, 1, 2, 3};
5720 /* All mesh data */
5721 ID3DXMesh *mesh = NULL;
5722 ID3DXMesh *mesh_null_check = NULL;
5723 unsigned int attributes[] = {0};
5724 struct
5726 const struct vertex_pnc *vertices;
5727 const DWORD *indices;
5728 const DWORD num_vertices;
5729 const DWORD num_faces;
5730 const DWORD *point_reps;
5731 const DWORD *exp_adjacency;
5732 const DWORD *exp_id_adjacency;
5733 const DWORD options;
5735 tc[] =
5738 vertices0,
5739 indices0,
5740 num_vertices0,
5741 num_faces0,
5742 point_rep0,
5743 exp_adjacency0,
5744 exp_id_adjacency0,
5745 options
5748 vertices1,
5749 indices1,
5750 num_vertices1,
5751 num_faces1,
5752 point_rep1,
5753 exp_adjacency1,
5754 exp_id_adjacency1,
5755 options
5758 vertices2,
5759 indices2,
5760 num_vertices2,
5761 num_faces2,
5762 point_rep2,
5763 exp_adjacency2,
5764 exp_id_adjacency2,
5765 options
5768 vertices3,
5769 indices3,
5770 num_vertices3,
5771 num_faces3,
5772 point_rep3,
5773 exp_adjacency3,
5774 exp_id_adjacency3,
5775 options
5778 vertices4,
5779 indices4,
5780 num_vertices4,
5781 num_faces4,
5782 point_rep4,
5783 exp_adjacency4,
5784 exp_id_adjacency4,
5785 options
5788 vertices5,
5789 indices5,
5790 num_vertices5,
5791 num_faces5,
5792 point_rep5,
5793 exp_adjacency5,
5794 exp_id_adjacency5,
5795 options
5798 vertices6,
5799 indices6,
5800 num_vertices6,
5801 num_faces6,
5802 point_rep6,
5803 exp_adjacency6,
5804 exp_id_adjacency6,
5805 options
5808 vertices7,
5809 indices7,
5810 num_vertices7,
5811 num_faces7,
5812 point_rep7,
5813 exp_adjacency7,
5814 exp_id_adjacency7,
5815 options
5818 vertices8,
5819 indices8,
5820 num_vertices8,
5821 num_faces8,
5822 point_rep8,
5823 exp_adjacency8,
5824 exp_id_adjacency8,
5825 options
5828 vertices9,
5829 indices9,
5830 num_vertices9,
5831 num_faces9,
5832 point_rep9,
5833 exp_adjacency9,
5834 exp_id_adjacency9,
5835 options
5838 vertices8,
5839 (DWORD*)indices8_16bit,
5840 num_vertices8,
5841 num_faces8,
5842 point_rep8,
5843 exp_adjacency8,
5844 exp_id_adjacency8,
5845 options_16bit
5848 DWORD *adjacency = NULL;
5850 test_context = new_test_context();
5851 if (!test_context)
5853 skip("Couldn't create test context\n");
5854 goto cleanup;
5857 for (i = 0; i < ARRAY_SIZE(tc); i++)
5859 hr = D3DXCreateMesh(tc[i].num_faces, tc[i].num_vertices, tc[i].options,
5860 declaration, test_context->device, &mesh);
5861 if (FAILED(hr))
5863 skip("Couldn't create mesh %d. Got %x expected D3D_OK\n", i, hr);
5864 goto cleanup;
5867 if (i == 0) /* Save first mesh for later NULL checks */
5868 mesh_null_check = mesh;
5870 adjacency = HeapAlloc(GetProcessHeap(), 0, VERTS_PER_FACE * tc[i].num_faces * sizeof(*adjacency));
5871 if (!adjacency)
5873 skip("Couldn't allocate adjacency array.\n");
5874 goto cleanup;
5877 hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, &vertex_buffer);
5878 if (FAILED(hr))
5880 skip("Couldn't lock vertex buffer.\n");
5881 goto cleanup;
5883 memcpy(vertex_buffer, tc[i].vertices, tc[i].num_vertices * sizeof(*tc[i].vertices));
5884 hr = mesh->lpVtbl->UnlockVertexBuffer(mesh);
5885 if (FAILED(hr))
5887 skip("Couldn't unlock vertex buffer.\n");
5888 goto cleanup;
5890 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, &index_buffer);
5891 if (FAILED(hr))
5893 skip("Couldn't lock index buffer.\n");
5894 goto cleanup;
5896 if (tc[i].options & D3DXMESH_32BIT)
5898 memcpy(index_buffer, tc[i].indices, VERTS_PER_FACE * tc[i].num_faces * sizeof(DWORD));
5900 else
5902 memcpy(index_buffer, tc[i].indices, VERTS_PER_FACE * tc[i].num_faces * sizeof(WORD));
5904 hr = mesh->lpVtbl->UnlockIndexBuffer(mesh);
5905 if (FAILED(hr)) {
5906 skip("Couldn't unlock index buffer.\n");
5907 goto cleanup;
5910 hr = mesh->lpVtbl->LockAttributeBuffer(mesh, 0, &attributes_buffer);
5911 if (FAILED(hr))
5913 skip("Couldn't lock attributes buffer.\n");
5914 goto cleanup;
5916 memcpy(attributes_buffer, attributes, sizeof(attributes));
5917 hr = mesh->lpVtbl->UnlockAttributeBuffer(mesh);
5918 if (FAILED(hr))
5920 skip("Couldn't unlock attributes buffer.\n");
5921 goto cleanup;
5924 /* Convert point representation to adjacency*/
5925 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++) adjacency[j] = -2;
5927 hr = mesh->lpVtbl->ConvertPointRepsToAdjacency(mesh, tc[i].point_reps, adjacency);
5928 ok(hr == D3D_OK, "ConvertPointRepsToAdjacency failed case %d. "
5929 "Got %x expected D3D_OK\n", i, hr);
5930 /* Check adjacency */
5931 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
5933 ok(adjacency[j] == tc[i].exp_adjacency[j],
5934 "Unexpected adjacency information at (%d, %d)."
5935 " Got %d expected %d\n",
5936 i, j, adjacency[j], tc[i].exp_adjacency[j]);
5939 /* NULL point representation is considered identity. */
5940 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++) adjacency[j] = -2;
5941 hr = mesh_null_check->lpVtbl->ConvertPointRepsToAdjacency(mesh, NULL, adjacency);
5942 ok(hr == D3D_OK, "ConvertPointRepsToAdjacency NULL point_reps. "
5943 "Got %x expected D3D_OK\n", hr);
5944 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
5946 ok(adjacency[j] == tc[i].exp_id_adjacency[j],
5947 "Unexpected adjacency information (id) at (%d, %d)."
5948 " Got %d expected %d\n",
5949 i, j, adjacency[j], tc[i].exp_id_adjacency[j]);
5952 HeapFree(GetProcessHeap(), 0, adjacency);
5953 adjacency = NULL;
5954 if (i != 0) /* First mesh will be freed during cleanup */
5955 mesh->lpVtbl->Release(mesh);
5958 /* NULL checks */
5959 hr = mesh_null_check->lpVtbl->ConvertPointRepsToAdjacency(mesh_null_check, tc[0].point_reps, NULL);
5960 ok(hr == D3DERR_INVALIDCALL, "ConvertPointRepsToAdjacency NULL adjacency. "
5961 "Got %x expected D3DERR_INVALIDCALL\n", hr);
5962 hr = mesh_null_check->lpVtbl->ConvertPointRepsToAdjacency(mesh_null_check, NULL, NULL);
5963 ok(hr == D3DERR_INVALIDCALL, "ConvertPointRepsToAdjacency NULL point_reps and adjacency. "
5964 "Got %x expected D3DERR_INVALIDCALL\n", hr);
5966 cleanup:
5967 if (mesh_null_check)
5968 mesh_null_check->lpVtbl->Release(mesh_null_check);
5969 HeapFree(GetProcessHeap(), 0, adjacency);
5970 free_test_context(test_context);
5973 static HRESULT init_test_mesh(const DWORD num_faces, const DWORD num_vertices,
5974 const DWORD options,
5975 const D3DVERTEXELEMENT9 *declaration,
5976 IDirect3DDevice9 *device, ID3DXMesh **mesh_ptr,
5977 const void *vertices, const DWORD vertex_size,
5978 const DWORD *indices, const DWORD *attributes)
5980 HRESULT hr;
5981 void *vertex_buffer;
5982 void *index_buffer;
5983 DWORD *attributes_buffer;
5984 ID3DXMesh *mesh = NULL;
5986 hr = D3DXCreateMesh(num_faces, num_vertices, options, declaration, device, mesh_ptr);
5987 if (FAILED(hr))
5989 skip("Couldn't create mesh. Got %x expected D3D_OK\n", hr);
5990 goto cleanup;
5992 mesh = *mesh_ptr;
5994 hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, &vertex_buffer);
5995 if (FAILED(hr))
5997 skip("Couldn't lock vertex buffer.\n");
5998 goto cleanup;
6000 memcpy(vertex_buffer, vertices, num_vertices * vertex_size);
6001 hr = mesh->lpVtbl->UnlockVertexBuffer(mesh);
6002 if (FAILED(hr))
6004 skip("Couldn't unlock vertex buffer.\n");
6005 goto cleanup;
6008 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, &index_buffer);
6009 if (FAILED(hr))
6011 skip("Couldn't lock index buffer.\n");
6012 goto cleanup;
6014 if (options & D3DXMESH_32BIT)
6016 if (indices)
6017 memcpy(index_buffer, indices, 3 * num_faces * sizeof(DWORD));
6018 else
6020 /* Fill index buffer with 0, 1, 2, ...*/
6021 DWORD *indices_32bit = (DWORD*)index_buffer;
6022 UINT i;
6023 for (i = 0; i < 3 * num_faces; i++)
6024 indices_32bit[i] = i;
6027 else
6029 if (indices)
6030 memcpy(index_buffer, indices, 3 * num_faces * sizeof(WORD));
6031 else
6033 /* Fill index buffer with 0, 1, 2, ...*/
6034 WORD *indices_16bit = (WORD*)index_buffer;
6035 UINT i;
6036 for (i = 0; i < 3 * num_faces; i++)
6037 indices_16bit[i] = i;
6040 hr = mesh->lpVtbl->UnlockIndexBuffer(mesh);
6041 if (FAILED(hr)) {
6042 skip("Couldn't unlock index buffer.\n");
6043 goto cleanup;
6046 hr = mesh->lpVtbl->LockAttributeBuffer(mesh, 0, &attributes_buffer);
6047 if (FAILED(hr))
6049 skip("Couldn't lock attributes buffer.\n");
6050 goto cleanup;
6053 if (attributes)
6054 memcpy(attributes_buffer, attributes, num_faces * sizeof(*attributes));
6055 else
6056 memset(attributes_buffer, 0, num_faces * sizeof(*attributes));
6058 hr = mesh->lpVtbl->UnlockAttributeBuffer(mesh);
6059 if (FAILED(hr))
6061 skip("Couldn't unlock attributes buffer.\n");
6062 goto cleanup;
6065 hr = D3D_OK;
6066 cleanup:
6067 return hr;
6070 /* Using structs instead of bit-fields in order to avoid compiler issues. */
6071 struct udec3
6073 UINT x;
6074 UINT y;
6075 UINT z;
6076 UINT w;
6079 struct dec3n
6081 INT x;
6082 INT y;
6083 INT z;
6084 INT w;
6087 static DWORD init_udec3_dword(UINT x, UINT y, UINT z, UINT w)
6089 DWORD d = 0;
6091 d |= x & 0x3ff;
6092 d |= (y << 10) & 0xffc00;
6093 d |= (z << 20) & 0x3ff00000;
6094 d |= (w << 30) & 0xc0000000;
6096 return d;
6099 static DWORD init_dec3n_dword(INT x, INT y, INT z, INT w)
6101 DWORD d = 0;
6103 d |= x & 0x3ff;
6104 d |= (y << 10) & 0xffc00;
6105 d |= (z << 20) & 0x3ff00000;
6106 d |= (w << 30) & 0xc0000000;
6108 return d;
6111 static struct udec3 dword_to_udec3(DWORD d)
6113 struct udec3 v;
6115 v.x = d & 0x3ff;
6116 v.y = (d & 0xffc00) >> 10;
6117 v.z = (d & 0x3ff00000) >> 20;
6118 v.w = (d & 0xc0000000) >> 30;
6120 return v;
6123 static struct dec3n dword_to_dec3n(DWORD d)
6125 struct dec3n v;
6127 v.x = d & 0x3ff;
6128 v.y = (d & 0xffc00) >> 10;
6129 v.z = (d & 0x3ff00000) >> 20;
6130 v.w = (d & 0xc0000000) >> 30;
6132 return v;
6135 static void check_vertex_components(int line, int mesh_number, int vertex_number, BYTE *got_ptr, const BYTE *exp_ptr, D3DVERTEXELEMENT9 *declaration)
6137 const char *usage_strings[] =
6139 "position",
6140 "blend weight",
6141 "blend indices",
6142 "normal",
6143 "point size",
6144 "texture coordinates",
6145 "tangent",
6146 "binormal",
6147 "tessellation factor",
6148 "position transformed",
6149 "color",
6150 "fog",
6151 "depth",
6152 "sample"
6154 D3DVERTEXELEMENT9 *decl_ptr;
6155 const float PRECISION = 1e-5f;
6157 for (decl_ptr = declaration; decl_ptr->Stream != 0xFF; decl_ptr++)
6159 switch (decl_ptr->Type)
6161 case D3DDECLTYPE_FLOAT1:
6163 FLOAT *got = (FLOAT*)(got_ptr + decl_ptr->Offset);
6164 FLOAT *exp = (FLOAT*)(exp_ptr + decl_ptr->Offset);
6165 FLOAT diff = fabsf(*got - *exp);
6166 ok_(__FILE__,line)(diff <= PRECISION, "Mesh %d: Got %f for vertex %d %s, expected %f.\n",
6167 mesh_number, *got, vertex_number, usage_strings[decl_ptr->Usage], *exp);
6168 break;
6170 case D3DDECLTYPE_FLOAT2:
6172 D3DXVECTOR2 *got = (D3DXVECTOR2*)(got_ptr + decl_ptr->Offset);
6173 D3DXVECTOR2 *exp = (D3DXVECTOR2*)(exp_ptr + decl_ptr->Offset);
6174 FLOAT diff = max(fabsf(got->x - exp->x), fabsf(got->y - exp->y));
6175 ok_(__FILE__,line)(diff <= PRECISION, "Mesh %d: Got (%f, %f) for vertex %d %s, expected (%f, %f).\n",
6176 mesh_number, got->x, got->y, vertex_number, usage_strings[decl_ptr->Usage], exp->x, exp->y);
6177 break;
6179 case D3DDECLTYPE_FLOAT3:
6181 D3DXVECTOR3 *got = (D3DXVECTOR3*)(got_ptr + decl_ptr->Offset);
6182 D3DXVECTOR3 *exp = (D3DXVECTOR3*)(exp_ptr + decl_ptr->Offset);
6183 FLOAT diff = max(fabsf(got->x - exp->x), fabsf(got->y - exp->y));
6184 diff = max(diff, fabsf(got->z - exp->z));
6185 ok_(__FILE__,line)(diff <= PRECISION, "Mesh %d: Got (%f, %f, %f) for vertex %d %s, expected (%f, %f, %f).\n",
6186 mesh_number, got->x, got->y, got->z, vertex_number, usage_strings[decl_ptr->Usage], exp->x, exp->y, exp->z);
6187 break;
6189 case D3DDECLTYPE_FLOAT4:
6191 D3DXVECTOR4 *got = (D3DXVECTOR4*)(got_ptr + decl_ptr->Offset);
6192 D3DXVECTOR4 *exp = (D3DXVECTOR4*)(exp_ptr + decl_ptr->Offset);
6193 FLOAT diff = max(fabsf(got->x - exp->x), fabsf(got->y - exp->y));
6194 diff = max(diff, fabsf(got->z - exp->z));
6195 diff = max(diff, fabsf(got->w - exp->w));
6196 ok_(__FILE__,line)(diff <= PRECISION, "Mesh %d: Got (%f, %f, %f, %f) for vertex %d %s, expected (%f, %f, %f, %f).\n",
6197 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);
6198 break;
6200 case D3DDECLTYPE_D3DCOLOR:
6202 BYTE *got = got_ptr + decl_ptr->Offset;
6203 const BYTE *exp = exp_ptr + decl_ptr->Offset;
6204 BOOL same_color = got[0] == exp[0] && got[1] == exp[1]
6205 && got[2] == exp[2] && got[3] == exp[3];
6206 const char *color_types[] = {"diffuse", "specular", "undefined color"};
6207 BYTE usage_index = decl_ptr->UsageIndex;
6208 if (usage_index > 1) usage_index = 2;
6209 ok_(__FILE__,line)(same_color, "Mesh %d: Got (%u, %u, %u, %u) for vertex %d %s, expected (%u, %u, %u, %u).\n",
6210 mesh_number, got[0], got[1], got[2], got[3], vertex_number, color_types[usage_index], exp[0], exp[1], exp[2], exp[3]);
6211 break;
6213 case D3DDECLTYPE_UBYTE4:
6214 case D3DDECLTYPE_UBYTE4N:
6216 BYTE *got = got_ptr + decl_ptr->Offset;
6217 const BYTE *exp = exp_ptr + decl_ptr->Offset;
6218 BOOL same = got[0] == exp[0] && got[1] == exp[1]
6219 && got[2] == exp[2] && got[3] == exp[3];
6220 ok_(__FILE__,line)(same, "Mesh %d: Got (%u, %u, %u, %u) for vertex %d %s, expected (%u, %u, %u, %u).\n",
6221 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]);
6222 break;
6224 case D3DDECLTYPE_SHORT2:
6225 case D3DDECLTYPE_SHORT2N:
6227 SHORT *got = (SHORT*)(got_ptr + decl_ptr->Offset);
6228 SHORT *exp = (SHORT*)(exp_ptr + decl_ptr->Offset);
6229 BOOL same = got[0] == exp[0] && got[1] == exp[1];
6230 ok_(__FILE__,line)(same, "Mesh %d: Got (%hd, %hd) for vertex %d %s, expected (%hd, %hd).\n",
6231 mesh_number, got[0], got[1], vertex_number, usage_strings[decl_ptr->Usage], exp[0], exp[1]);
6232 break;
6234 case D3DDECLTYPE_SHORT4:
6235 case D3DDECLTYPE_SHORT4N:
6237 SHORT *got = (SHORT*)(got_ptr + decl_ptr->Offset);
6238 SHORT *exp = (SHORT*)(exp_ptr + decl_ptr->Offset);
6239 BOOL same = got[0] == exp[0] && got[1] == exp[1]
6240 && got[2] == exp[2] && got[3] == exp[3];
6241 ok_(__FILE__,line)(same, "Mesh %d: Got (%hd, %hd, %hd, %hd) for vertex %d %s, expected (%hd, %hd, %hd, %hd).\n",
6242 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]);
6243 break;
6245 case D3DDECLTYPE_USHORT2N:
6247 USHORT *got = (USHORT*)(got_ptr + decl_ptr->Offset);
6248 USHORT *exp = (USHORT*)(exp_ptr + decl_ptr->Offset);
6249 BOOL same = got[0] == exp[0] && got[1] == exp[1];
6250 ok_(__FILE__,line)(same, "Mesh %d: Got (%hu, %hu) for vertex %d %s, expected (%hu, %hu).\n",
6251 mesh_number, got[0], got[1], vertex_number, usage_strings[decl_ptr->Usage], exp[0], exp[1]);
6252 break;
6254 case D3DDECLTYPE_USHORT4N:
6256 USHORT *got = (USHORT*)(got_ptr + decl_ptr->Offset);
6257 USHORT *exp = (USHORT*)(exp_ptr + decl_ptr->Offset);
6258 BOOL same = got[0] == exp[0] && got[1] == exp[1]
6259 && got[2] == exp[2] && got[3] == exp[3];
6260 ok_(__FILE__,line)(same, "Mesh %d: Got (%hu, %hu, %hu, %hu) for vertex %d %s, expected (%hu, %hu, %hu, %hu).\n",
6261 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]);
6262 break;
6264 case D3DDECLTYPE_UDEC3:
6266 DWORD *got = (DWORD*)(got_ptr + decl_ptr->Offset);
6267 DWORD *exp = (DWORD*)(exp_ptr + decl_ptr->Offset);
6268 BOOL same = memcmp(got, exp, sizeof(*got)) == 0;
6269 struct udec3 got_udec3 = dword_to_udec3(*got);
6270 struct udec3 exp_udec3 = dword_to_udec3(*exp);
6271 ok_(__FILE__,line)(same, "Mesh %d: Got (%u, %u, %u, %u) for vertex %d %s, expected (%u, %u, %u, %u).\n",
6272 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);
6274 break;
6276 case D3DDECLTYPE_DEC3N:
6278 DWORD *got = (DWORD*)(got_ptr + decl_ptr->Offset);
6279 DWORD *exp = (DWORD*)(exp_ptr + decl_ptr->Offset);
6280 BOOL same = memcmp(got, exp, sizeof(*got)) == 0;
6281 struct dec3n got_dec3n = dword_to_dec3n(*got);
6282 struct dec3n exp_dec3n = dword_to_dec3n(*exp);
6283 ok_(__FILE__,line)(same, "Mesh %d: Got (%d, %d, %d, %d) for vertex %d %s, expected (%d, %d, %d, %d).\n",
6284 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);
6285 break;
6287 case D3DDECLTYPE_FLOAT16_2:
6289 WORD *got = (WORD*)(got_ptr + decl_ptr->Offset);
6290 WORD *exp = (WORD*)(exp_ptr + decl_ptr->Offset);
6291 BOOL same = got[0] == exp[0] && got[1] == exp[1];
6292 ok_(__FILE__,line)(same, "Mesh %d: Got (%hx, %hx) for vertex %d %s, expected (%hx, %hx).\n",
6293 mesh_number, got[0], got[1], vertex_number, usage_strings[decl_ptr->Usage], exp[0], exp[1]);
6294 break;
6296 case D3DDECLTYPE_FLOAT16_4:
6298 WORD *got = (WORD*)(got_ptr + decl_ptr->Offset);
6299 WORD *exp = (WORD*)(exp_ptr + decl_ptr->Offset);
6300 BOOL same = got[0] == exp[0] && got[1] == exp[1]
6301 && got[2] == exp[2] && got[3] == exp[3];
6302 ok_(__FILE__,line)(same, "Mesh %d: Got (%hx, %hx, %hx, %hx) for vertex %d %s, expected (%hx, %hx, %hx, %hx).\n",
6303 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]);
6304 break;
6306 default:
6307 break;
6312 static void test_weld_vertices(void)
6314 HRESULT hr;
6315 struct test_context *test_context = NULL;
6316 DWORD i;
6317 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
6318 const DWORD options_16bit = D3DXMESH_SYSTEMMEM;
6319 BYTE *vertices = NULL;
6320 DWORD *indices = NULL;
6321 WORD *indices_16bit = NULL;
6322 const UINT VERTS_PER_FACE = 3;
6323 const D3DXVECTOR3 up = {0.0f, 0.0f, 1.0f};
6324 struct vertex_normal
6326 D3DXVECTOR3 position;
6327 D3DXVECTOR3 normal;
6329 struct vertex_blendweight
6331 D3DXVECTOR3 position;
6332 FLOAT blendweight;
6334 struct vertex_texcoord
6336 D3DXVECTOR3 position;
6337 D3DXVECTOR2 texcoord;
6339 struct vertex_color
6341 D3DXVECTOR3 position;
6342 DWORD color;
6344 struct vertex_color_ubyte4
6346 D3DXVECTOR3 position;
6347 BYTE color[4];
6349 struct vertex_texcoord_short2
6351 D3DXVECTOR3 position;
6352 SHORT texcoord[2];
6354 struct vertex_texcoord_ushort2n
6356 D3DXVECTOR3 position;
6357 USHORT texcoord[2];
6359 struct vertex_normal_short4
6361 D3DXVECTOR3 position;
6362 SHORT normal[4];
6364 struct vertex_color_float4
6366 D3DXVECTOR3 position;
6367 D3DXVECTOR4 color;
6369 struct vertex_texcoord_float16_2
6371 D3DXVECTOR3 position;
6372 WORD texcoord[2];
6374 struct vertex_texcoord_float16_4
6376 D3DXVECTOR3 position;
6377 WORD texcoord[4];
6379 struct vertex_normal_udec3
6381 D3DXVECTOR3 position;
6382 DWORD normal;
6384 struct vertex_normal_dec3n
6386 D3DXVECTOR3 position;
6387 DWORD normal;
6389 UINT vertex_size_normal = sizeof(struct vertex_normal);
6390 UINT vertex_size_blendweight = sizeof(struct vertex_blendweight);
6391 UINT vertex_size_texcoord = sizeof(struct vertex_texcoord);
6392 UINT vertex_size_color = sizeof(struct vertex_color);
6393 UINT vertex_size_color_ubyte4 = sizeof(struct vertex_color_ubyte4);
6394 UINT vertex_size_texcoord_short2 = sizeof(struct vertex_texcoord_short2);
6395 UINT vertex_size_normal_short4 = sizeof(struct vertex_normal_short4);
6396 UINT vertex_size_color_float4 = sizeof(struct vertex_color_float4);
6397 UINT vertex_size_texcoord_float16_2 = sizeof(struct vertex_texcoord_float16_2);
6398 UINT vertex_size_texcoord_float16_4 = sizeof(struct vertex_texcoord_float16_4);
6399 UINT vertex_size_normal_udec3 = sizeof(struct vertex_normal_udec3);
6400 UINT vertex_size_normal_dec3n = sizeof(struct vertex_normal_dec3n);
6401 D3DVERTEXELEMENT9 declaration_normal[] =
6403 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6404 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6405 D3DDECL_END()
6407 D3DVERTEXELEMENT9 declaration_normal3[] =
6409 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 3},
6410 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6411 D3DDECL_END()
6413 D3DVERTEXELEMENT9 declaration_blendweight[] =
6415 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6416 {0, 12, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BLENDWEIGHT, 0},
6417 D3DDECL_END()
6419 D3DVERTEXELEMENT9 declaration_texcoord[] =
6421 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6422 {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6423 D3DDECL_END()
6425 D3DVERTEXELEMENT9 declaration_color[] =
6427 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6428 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
6429 D3DDECL_END()
6431 D3DVERTEXELEMENT9 declaration_color_ubyte4n[] =
6433 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6434 {0, 12, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
6435 D3DDECL_END()
6437 D3DVERTEXELEMENT9 declaration_color_ubyte4[] =
6439 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6440 {0, 12, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
6441 D3DDECL_END()
6443 D3DVERTEXELEMENT9 declaration_texcoord_short2[] =
6445 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6446 {0, 12, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6447 D3DDECL_END()
6449 D3DVERTEXELEMENT9 declaration_texcoord_short2n[] =
6451 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6452 {0, 12, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6453 D3DDECL_END()
6455 D3DVERTEXELEMENT9 declaration_texcoord_ushort2n[] =
6457 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6458 {0, 12, D3DDECLTYPE_USHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6459 D3DDECL_END()
6461 D3DVERTEXELEMENT9 declaration_normal_short4[] =
6463 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6464 {0, 12, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6465 D3DDECL_END()
6467 D3DVERTEXELEMENT9 declaration_normal_short4n[] =
6469 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6470 {0, 12, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6471 D3DDECL_END()
6473 D3DVERTEXELEMENT9 declaration_normal_ushort4n[] =
6475 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6476 {0, 12, D3DDECLTYPE_USHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6477 D3DDECL_END()
6479 D3DVERTEXELEMENT9 declaration_texcoord10[] =
6481 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6482 {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 10},
6483 D3DDECL_END()
6485 D3DVERTEXELEMENT9 declaration_color2[] =
6487 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6488 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 2},
6489 D3DDECL_END()
6491 D3DVERTEXELEMENT9 declaration_color2_float4[] =
6493 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6494 {0, 12, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 2},
6495 D3DDECL_END()
6497 D3DVERTEXELEMENT9 declaration_texcoord_float16_2[] =
6499 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6500 {0, 12, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6501 D3DDECL_END()
6503 D3DVERTEXELEMENT9 declaration_texcoord_float16_4[] =
6505 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6506 {0, 12, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6507 D3DDECL_END()
6509 D3DVERTEXELEMENT9 declaration_normal_udec3[] =
6511 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6512 {0, 12, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6513 D3DDECL_END()
6515 D3DVERTEXELEMENT9 declaration_normal_dec3n[] =
6517 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6518 {0, 12, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6519 D3DDECL_END()
6521 /* Test 0. One face and no welding.
6523 * 0--1
6524 * | /
6525 * |/
6528 const struct vertex vertices0[] =
6530 {{ 0.0f, 3.0f, 0.f}, up},
6531 {{ 2.0f, 3.0f, 0.f}, up},
6532 {{ 0.0f, 0.0f, 0.f}, up},
6534 const DWORD indices0[] = {0, 1, 2};
6535 const DWORD attributes0[] = {0};
6536 const DWORD exp_indices0[] = {0, 1, 2};
6537 const UINT num_vertices0 = ARRAY_SIZE(vertices0);
6538 const UINT num_faces0 = ARRAY_SIZE(indices0) / VERTS_PER_FACE;
6539 const DWORD flags0 = D3DXWELDEPSILONS_WELDALL;
6540 /* epsilons0 is NULL */
6541 const DWORD adjacency0[] = {-1, -1, -1};
6542 const struct vertex exp_vertices0[] =
6544 {{ 0.0f, 3.0f, 0.f}, up},
6545 {{ 2.0f, 3.0f, 0.f}, up},
6546 {{ 0.0f, 0.0f, 0.f}, up},
6548 const DWORD exp_face_remap0[] = {0};
6549 const DWORD exp_vertex_remap0[] = {0, 1, 2};
6550 const DWORD exp_new_num_vertices0 = ARRAY_SIZE(exp_vertices0);
6551 /* Test 1. Two vertices should be removed without regard to epsilon.
6553 * 0--1 3
6554 * | / /|
6555 * |/ / |
6556 * 2 5--4
6558 const struct vertex_normal vertices1[] =
6560 {{ 0.0f, 3.0f, 0.f}, up},
6561 {{ 2.0f, 3.0f, 0.f}, up},
6562 {{ 0.0f, 0.0f, 0.f}, up},
6564 {{ 3.0f, 3.0f, 0.f}, up},
6565 {{ 3.0f, 0.0f, 0.f}, up},
6566 {{ 1.0f, 0.0f, 0.f}, up},
6568 const DWORD indices1[] = {0, 1, 2, 3, 4, 5};
6569 const DWORD attributes1[] = {0, 0};
6570 const UINT num_vertices1 = ARRAY_SIZE(vertices1);
6571 const UINT num_faces1 = ARRAY_SIZE(indices1) / VERTS_PER_FACE;
6572 const DWORD flags1 = D3DXWELDEPSILONS_WELDALL;
6573 /* epsilons1 is NULL */
6574 const DWORD adjacency1[] = {-1, 1, -1, -1, -1, 0};
6575 const struct vertex_normal exp_vertices1[] =
6577 {{ 0.0f, 3.0f, 0.f}, up},
6578 {{ 2.0f, 3.0f, 0.f}, up},
6579 {{ 0.0f, 0.0f, 0.f}, up},
6581 {{ 3.0f, 0.0f, 0.f}, up}
6583 const DWORD exp_indices1[] = {0, 1, 2, 1, 3, 2};
6584 const DWORD exp_face_remap1[] = {0, 1};
6585 const DWORD exp_vertex_remap1[] = {0, 1, 2, 4, -1, -1};
6586 const DWORD exp_new_num_vertices1 = ARRAY_SIZE(exp_vertices1);
6587 /* Test 2. Two faces. No vertices should be removed because of normal
6588 * epsilon, but the positions should be replaced. */
6589 const struct vertex_normal vertices2[] =
6591 {{ 0.0f, 3.0f, 0.f}, up},
6592 {{ 2.0f, 3.0f, 0.f}, up},
6593 {{ 0.0f, 0.0f, 0.f}, up},
6595 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
6596 {{ 3.0f, 0.0f, 0.f}, up},
6597 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6599 const DWORD indices2[] = {0, 1, 2, 3, 4, 5};
6600 const DWORD attributes2[] = {0, 0};
6601 const UINT num_vertices2 = ARRAY_SIZE(vertices2);
6602 const UINT num_faces2 = ARRAY_SIZE(indices2) / VERTS_PER_FACE;
6603 DWORD flags2 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
6604 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};
6605 const DWORD adjacency2[] = {-1, 1, -1, -1, -1, 0};
6606 const struct vertex_normal exp_vertices2[] =
6608 {{ 0.0f, 3.0f, 0.f}, up},
6609 {{ 2.0f, 3.0f, 0.f}, up},
6610 {{ 0.0f, 0.0f, 0.f}, up},
6612 {{ 2.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
6613 {{ 3.0f, 0.0f, 0.f}, up},
6614 {{ 0.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6616 const DWORD exp_indices2[] = {0, 1, 2, 3, 4, 5};
6617 const DWORD exp_face_remap2[] = {0, 1};
6618 const DWORD exp_vertex_remap2[] = {0, 1, 2, 3, 4, 5};
6619 const DWORD exp_new_num_vertices2 = ARRAY_SIZE(exp_vertices2);
6620 /* Test 3. Two faces. One vertex should be removed because of normal epsilon. */
6621 const struct vertex_normal vertices3[] =
6623 {{ 0.0f, 3.0f, 0.f}, up},
6624 {{ 2.0f, 3.0f, 0.f}, up},
6625 {{ 0.0f, 0.0f, 0.f}, up},
6627 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
6628 {{ 3.0f, 0.0f, 0.f}, up},
6629 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6631 const DWORD indices3[] = {0, 1, 2, 3, 4, 5};
6632 const DWORD attributes3[] = {0, 0};
6633 const UINT num_vertices3 = ARRAY_SIZE(vertices3);
6634 const UINT num_faces3 = ARRAY_SIZE(indices3) / VERTS_PER_FACE;
6635 DWORD flags3 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
6636 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};
6637 const DWORD adjacency3[] = {-1, 1, -1, -1, -1, 0};
6638 const struct vertex_normal exp_vertices3[] =
6640 {{ 0.0f, 3.0f, 0.f}, up},
6641 {{ 2.0f, 3.0f, 0.f}, up},
6642 {{ 0.0f, 0.0f, 0.f}, up},
6644 {{ 3.0f, 0.0f, 0.f}, up},
6645 {{ 0.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6647 const DWORD exp_indices3[] = {0, 1, 2, 1, 3, 4};
6648 const DWORD exp_face_remap3[] = {0, 1};
6649 const DWORD exp_vertex_remap3[] = {0, 1, 2, 4, 5, -1};
6650 const DWORD exp_new_num_vertices3 = ARRAY_SIZE(exp_vertices3);
6651 /* Test 4 Two faces. Two vertices should be removed. */
6652 const struct vertex_normal vertices4[] =
6654 {{ 0.0f, 3.0f, 0.f}, up},
6655 {{ 2.0f, 3.0f, 0.f}, up},
6656 {{ 0.0f, 0.0f, 0.f}, up},
6658 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
6659 {{ 3.0f, 0.0f, 0.f}, up},
6660 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6662 const DWORD indices4[] = {0, 1, 2, 3, 4, 5};
6663 const DWORD attributes4[] = {0, 0};
6664 const UINT num_vertices4 = ARRAY_SIZE(vertices4);
6665 const UINT num_faces4 = ARRAY_SIZE(indices4) / VERTS_PER_FACE;
6666 DWORD flags4 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
6667 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};
6668 const DWORD adjacency4[] = {-1, 1, -1, -1, -1, 0};
6669 const struct vertex_normal exp_vertices4[] =
6671 {{ 0.0f, 3.0f, 0.f}, up},
6672 {{ 2.0f, 3.0f, 0.f}, up},
6673 {{ 0.0f, 0.0f, 0.f}, up},
6675 {{ 3.0f, 0.0f, 0.f}, up},
6677 const DWORD exp_indices4[] = {0, 1, 2, 1, 3, 2};
6678 const DWORD exp_face_remap4[] = {0, 1};
6679 const DWORD exp_vertex_remap4[] = {0, 1, 2, 4, -1, -1};
6680 const DWORD exp_new_num_vertices4 = ARRAY_SIZE(exp_vertices4);
6681 /* Test 5. Odd face ordering.
6683 * 0--1 6 3
6684 * | / /| |\
6685 * |/ / | | \
6686 * 2 8--7 5--4
6688 const struct vertex_normal vertices5[] =
6690 {{ 0.0f, 3.0f, 0.f}, up},
6691 {{ 2.0f, 3.0f, 0.f}, up},
6692 {{ 0.0f, 0.0f, 0.f}, up},
6694 {{ 3.0f, 3.0f, 0.f}, up},
6695 {{ 3.0f, 0.0f, 0.f}, up},
6696 {{ 1.0f, 0.0f, 0.f}, up},
6698 {{ 4.0f, 3.0f, 0.f}, up},
6699 {{ 6.0f, 0.0f, 0.f}, up},
6700 {{ 4.0f, 0.0f, 0.f}, up},
6702 const DWORD indices5[] = {0, 1, 2, 6, 7, 8, 3, 4, 5};
6703 const DWORD exp_indices5[] = {0, 1, 2, 1, 4, 2, 1, 3, 4};
6704 const DWORD attributes5[] = {0, 0, 0};
6705 const UINT num_vertices5 = ARRAY_SIZE(vertices5);
6706 const UINT num_faces5 = ARRAY_SIZE(indices5) / VERTS_PER_FACE;
6707 DWORD flags5 = D3DXWELDEPSILONS_WELDALL;
6708 const DWORD adjacency5[] = {-1, 1, -1, 2, -1, 0, -1, -1, 1};
6709 const struct vertex_normal exp_vertices5[] =
6711 {{ 0.0f, 3.0f, 0.f}, up},
6712 {{ 2.0f, 3.0f, 0.f}, up},
6713 {{ 0.0f, 0.0f, 0.f}, up},
6715 {{ 3.0f, 0.0f, 0.f}, up},
6716 {{ 1.0f, 0.0f, 0.f}, up},
6718 const DWORD exp_face_remap5[] = {0, 1, 2};
6719 const DWORD exp_vertex_remap5[] = {0, 1, 2, 4, 5, -1, -1, -1, -1};
6720 const DWORD exp_new_num_vertices5 = ARRAY_SIZE(exp_vertices5);
6721 /* Test 6. Two faces. Do not remove flag is used, so no vertices should be
6722 * removed. */
6723 const struct vertex_normal vertices6[] =
6725 {{ 0.0f, 3.0f, 0.f}, up},
6726 {{ 2.0f, 3.0f, 0.f}, up},
6727 {{ 0.0f, 0.0f, 0.f}, up},
6729 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
6730 {{ 3.0f, 0.0f, 0.f}, up},
6731 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6733 const DWORD indices6[] = {0, 1, 2, 3, 4, 5};
6734 const DWORD attributes6[] = {0, 0};
6735 const UINT num_vertices6 = ARRAY_SIZE(vertices6);
6736 const UINT num_faces6 = ARRAY_SIZE(indices6) / VERTS_PER_FACE;
6737 DWORD flags6 = D3DXWELDEPSILONS_WELDPARTIALMATCHES | D3DXWELDEPSILONS_DONOTREMOVEVERTICES;
6738 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};
6739 const DWORD adjacency6[] = {-1, 1, -1, -1, -1, 0};
6740 const struct vertex_normal exp_vertices6[] =
6742 {{ 0.0f, 3.0f, 0.f}, up},
6743 {{ 2.0f, 3.0f, 0.f}, up},
6744 {{ 0.0f, 0.0f, 0.f}, up},
6746 {{ 2.0f, 3.0f, 0.f}, up},
6747 {{ 3.0f, 0.0f, 0.f}, up},
6748 {{ 0.0f, 0.0f, 0.f}, up},
6751 const DWORD exp_indices6[] = {0, 1, 2, 3, 4, 5};
6752 const DWORD exp_face_remap6[] = {0, 1};
6753 const DWORD exp_vertex_remap6[] = {0, 1, 2, 3, 4, 5};
6754 const DWORD exp_new_num_vertices6 = ARRAY_SIZE(exp_vertices6);
6755 /* Test 7. Same as test 6 but with 16 bit indices. */
6756 const WORD indices6_16bit[] = {0, 1, 2, 3, 4, 5};
6757 /* Test 8. No flags. Same result as D3DXWELDEPSILONS_WELDPARTIALMATCHES. */
6758 const struct vertex_normal vertices8[] =
6760 {{ 0.0f, 3.0f, 0.f}, up},
6761 {{ 2.0f, 3.0f, 0.f}, up},
6762 {{ 0.0f, 0.0f, 0.f}, up},
6764 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
6765 {{ 3.0f, 0.0f, 0.f}, up},
6766 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6768 const DWORD indices8[] = {0, 1, 2, 1, 3, 4};
6769 const DWORD attributes8[] = {0, 0};
6770 const UINT num_vertices8 = ARRAY_SIZE(vertices8);
6771 const UINT num_faces8 = ARRAY_SIZE(indices8) / VERTS_PER_FACE;
6772 DWORD flags8 = 0;
6773 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};
6774 const DWORD adjacency8[] = {-1, 1, -1, -1, -1, 0};
6775 const struct vertex_normal exp_vertices8[] =
6777 {{ 0.0f, 3.0f, 0.f}, up},
6778 {{ 2.0f, 3.0f, 0.f}, up},
6779 {{ 0.0f, 0.0f, 0.f}, up},
6781 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
6782 {{ 3.0f, 0.0f, 0.f}, up},
6784 const DWORD exp_indices8[] = {0, 1, 2, 1, 3, 4};
6785 const DWORD exp_face_remap8[] = {0, 1};
6786 const DWORD exp_vertex_remap8[] = {0, 1, 2, 3, 4, -1};
6787 const DWORD exp_new_num_vertices8 = ARRAY_SIZE(exp_vertices8);
6788 /* Test 9. Vertices are removed even though they belong to separate
6789 * attribute groups if D3DXWELDEPSILONS_DONOTSPLIT is set. */
6790 const struct vertex_normal vertices9[] =
6792 {{ 0.0f, 3.0f, 0.f}, up},
6793 {{ 2.0f, 3.0f, 0.f}, up},
6794 {{ 0.0f, 0.0f, 0.f}, up},
6796 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
6797 {{ 3.0f, 0.0f, 0.f}, up},
6798 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6800 const DWORD indices9[] = {0, 1, 2, 3, 4, 5};
6801 const DWORD attributes9[] = {0, 1};
6802 const UINT num_vertices9 = ARRAY_SIZE(vertices9);
6803 const UINT num_faces9 = ARRAY_SIZE(indices9) / VERTS_PER_FACE;
6804 DWORD flags9 = D3DXWELDEPSILONS_WELDPARTIALMATCHES | D3DXWELDEPSILONS_DONOTSPLIT;
6805 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};
6806 const DWORD adjacency9[] = {-1, 1, -1, -1, -1, 0};
6807 const struct vertex_normal exp_vertices9[] =
6809 {{ 0.0f, 3.0f, 0.f}, up},
6810 {{ 2.0f, 3.0f, 0.f}, up},
6811 {{ 0.0f, 0.0f, 0.f}, up},
6813 {{ 3.0f, 0.0f, 0.f}, up},
6815 const DWORD exp_indices9[] = {0, 1, 2, 1, 3, 2};
6816 const DWORD exp_face_remap9[] = {0, 1};
6817 const DWORD exp_vertex_remap9[] = {0, 1, 2, 4, -1, -1};
6818 const DWORD exp_new_num_vertices9 = ARRAY_SIZE(exp_vertices9);
6819 /* Test 10. Weld blendweight (FLOAT1). */
6820 const struct vertex_blendweight vertices10[] =
6822 {{ 0.0f, 3.0f, 0.f}, 1.0f},
6823 {{ 2.0f, 3.0f, 0.f}, 1.0f},
6824 {{ 0.0f, 0.0f, 0.f}, 1.0f},
6826 {{ 3.0f, 3.0f, 0.f}, 0.9},
6827 {{ 3.0f, 0.0f, 0.f}, 1.0},
6828 {{ 1.0f, 0.0f, 0.f}, 0.4},
6830 const DWORD indices10[] = {0, 1, 2, 3, 4, 5};
6831 const DWORD attributes10[] = {0, 0};
6832 const UINT num_vertices10 = ARRAY_SIZE(vertices10);
6833 const UINT num_faces10 = ARRAY_SIZE(indices10) / VERTS_PER_FACE;
6834 DWORD flags10 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
6835 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};
6836 const DWORD adjacency10[] = {-1, 1, -1, -1, -1, 0};
6837 const struct vertex_blendweight exp_vertices10[] =
6839 {{ 0.0f, 3.0f, 0.f}, 1.0f},
6840 {{ 2.0f, 3.0f, 0.f}, 1.0f},
6841 {{ 0.0f, 0.0f, 0.f}, 1.0f},
6843 {{ 3.0f, 0.0f, 0.f}, 1.0},
6844 {{ 0.0f, 0.0f, 0.f}, 0.4},
6846 const DWORD exp_indices10[] = {0, 1, 2, 1, 3, 4};
6847 const DWORD exp_face_remap10[] = {0, 1};
6848 const DWORD exp_vertex_remap10[] = {0, 1, 2, 4, 5, -1};
6849 const DWORD exp_new_num_vertices10 = ARRAY_SIZE(exp_vertices10);
6850 /* Test 11. Weld texture coordinates. */
6851 const struct vertex_texcoord vertices11[] =
6853 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f}},
6854 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.7f}},
6855 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
6857 {{ 3.0f, 3.0f, 0.f}, {0.2f, 0.3f}},
6858 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f}},
6859 {{ 1.0f, 0.0f, 0.f}, {0.1f, 0.2f}}
6861 const DWORD indices11[] = {0, 1, 2, 3, 4, 5};
6862 const DWORD attributes11[] = {0, 0};
6863 const UINT num_vertices11 = ARRAY_SIZE(vertices11);
6864 const UINT num_faces11 = ARRAY_SIZE(indices11) / VERTS_PER_FACE;
6865 DWORD flags11 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
6866 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};
6867 const DWORD adjacency11[] = {-1, 1, -1, -1, -1, 0};
6868 const struct vertex_texcoord exp_vertices11[] =
6870 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f}},
6871 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.7f}},
6872 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
6874 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f}},
6875 {{ 0.0f, 0.0f, 0.f}, {0.1f, 0.2f}},
6877 const DWORD exp_indices11[] = {0, 1, 2, 1, 3, 4};
6878 const DWORD exp_face_remap11[] = {0, 1};
6879 const DWORD exp_vertex_remap11[] = {0, 1, 2, 4, 5, -1};
6880 const DWORD exp_new_num_vertices11 = ARRAY_SIZE(exp_vertices11);
6881 /* Test 12. Weld with color. */
6882 const struct vertex_color vertices12[] =
6884 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
6885 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
6886 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
6888 {{ 3.0f, 3.0f, 0.f}, 0x00000000},
6889 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
6890 {{ 1.0f, 0.0f, 0.f}, 0x88888888},
6892 const DWORD indices12[] = {0, 1, 2, 3, 4, 5};
6893 const DWORD attributes12[] = {0, 0};
6894 const UINT num_vertices12 = ARRAY_SIZE(vertices12);
6895 const UINT num_faces12 = ARRAY_SIZE(indices12) / VERTS_PER_FACE;
6896 DWORD flags12 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
6897 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};
6898 const DWORD adjacency12[] = {-1, 1, -1, -1, -1, 0};
6899 const struct vertex_color exp_vertices12[] =
6901 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
6902 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
6903 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
6905 {{ 2.0f, 3.0f, 0.f}, 0x00000000},
6906 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
6908 const DWORD exp_indices12[] = {0, 1, 2, 3, 4, 2};
6909 const DWORD exp_face_remap12[] = {0, 1};
6910 const DWORD exp_vertex_remap12[] = {0, 1, 2, 3, 4, -1};
6911 const DWORD exp_new_num_vertices12 = ARRAY_SIZE(exp_vertices12);
6912 /* Test 13. Two faces. One vertex should be removed because of normal epsilon.
6913 * This is similar to test 3, but the declaration has been changed to NORMAL3.
6915 const struct vertex_normal vertices13[] =
6917 {{ 0.0f, 3.0f, 0.f}, up},
6918 {{ 2.0f, 3.0f, 0.f}, up},
6919 {{ 0.0f, 0.0f, 0.f}, up},
6921 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
6922 {{ 3.0f, 0.0f, 0.f}, up},
6923 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6925 const DWORD indices13[] = {0, 1, 2, 3, 4, 5};
6926 const DWORD attributes13[] = {0, 0};
6927 const UINT num_vertices13 = ARRAY_SIZE(vertices3);
6928 const UINT num_faces13 = ARRAY_SIZE(indices3) / VERTS_PER_FACE;
6929 DWORD flags13 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
6930 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};
6931 const DWORD adjacency13[] = {-1, 1, -1, -1, -1, 0};
6932 const struct vertex_normal exp_vertices13[] =
6934 {{ 0.0f, 3.0f, 0.f}, up},
6935 {{ 2.0f, 3.0f, 0.f}, up},
6936 {{ 0.0f, 0.0f, 0.f}, up},
6938 {{ 3.0f, 0.0f, 0.f}, up},
6939 {{ 0.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6941 const DWORD exp_indices13[] = {0, 1, 2, 1, 3, 4};
6942 const DWORD exp_face_remap13[] = {0, 1};
6943 const DWORD exp_vertex_remap13[] = {0, 1, 2, 4, 5, -1};
6944 const DWORD exp_new_num_vertices13 = ARRAY_SIZE(exp_vertices13);
6945 /* Test 14. Another test for welding with color. */
6946 const struct vertex_color vertices14[] =
6948 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
6949 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
6950 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
6952 {{ 3.0f, 3.0f, 0.f}, 0x00000000},
6953 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
6954 {{ 1.0f, 0.0f, 0.f}, 0x01010101},
6956 const DWORD indices14[] = {0, 1, 2, 3, 4, 5};
6957 const DWORD attributes14[] = {0, 0};
6958 const UINT num_vertices14 = ARRAY_SIZE(vertices14);
6959 const UINT num_faces14 = ARRAY_SIZE(indices14) / VERTS_PER_FACE;
6960 DWORD flags14 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
6961 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};
6962 const DWORD adjacency14[] = {-1, 1, -1, -1, -1, 0};
6963 const struct vertex_color exp_vertices14[] =
6965 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
6966 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
6967 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
6969 {{ 2.0f, 3.0f, 0.f}, 0x00000000},
6970 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
6972 const DWORD exp_indices14[] = {0, 1, 2, 3, 4, 2};
6973 const DWORD exp_face_remap14[] = {0, 1};
6974 const DWORD exp_vertex_remap14[] = {0, 1, 2, 3, 4, -1};
6975 const DWORD exp_new_num_vertices14 = ARRAY_SIZE(exp_vertices14);
6976 /* Test 15. Weld with color, but as UBYTE4N instead of D3DCOLOR. It shows
6977 * that UBYTE4N and D3DCOLOR are compared the same way.
6979 const struct vertex_color_ubyte4 vertices15[] =
6981 {{ 0.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
6982 {{ 2.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
6983 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
6985 {{ 3.0f, 3.0f, 0.f}, { 0, 0, 0, 0}},
6986 {{ 3.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
6987 {{ 1.0f, 0.0f, 0.f}, { 1, 1, 1, 1}},
6989 const DWORD indices15[] = {0, 1, 2, 3, 4, 5};
6990 const DWORD attributes15[] = {0, 0};
6991 const UINT num_vertices15 = ARRAY_SIZE(vertices15);
6992 const UINT num_faces15 = ARRAY_SIZE(indices15) / VERTS_PER_FACE;
6993 DWORD flags15 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
6994 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};
6995 const DWORD adjacency15[] = {-1, 1, -1, -1, -1, 0};
6996 const struct vertex_color_ubyte4 exp_vertices15[] =
6998 {{ 0.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
6999 {{ 2.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7000 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7002 {{ 2.0f, 3.0f, 0.f}, { 0, 0, 0, 0}},
7003 {{ 3.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7005 const DWORD exp_indices15[] = {0, 1, 2, 3, 4, 2};
7006 const DWORD exp_face_remap15[] = {0, 1};
7007 const DWORD exp_vertex_remap15[] = {0, 1, 2, 3, 4, -1};
7008 const DWORD exp_new_num_vertices15 = ARRAY_SIZE(exp_vertices15);
7009 /* Test 16. Weld with color, but as UBYTE4 instead of D3DCOLOR. It shows
7010 * that UBYTE4 is not normalized and that epsilon is truncated and compared
7011 * directly to each of the four bytes.
7013 const struct vertex_color_ubyte4 vertices16[] =
7015 {{ 0.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7016 {{ 2.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7017 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7019 {{ 3.0f, 3.0f, 0.f}, { 0, 0, 0, 0}},
7020 {{ 3.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7021 {{ 1.0f, 0.0f, 0.f}, { 1, 1, 1, 1}},
7023 const DWORD indices16[] = {0, 1, 2, 3, 4, 5};
7024 const DWORD attributes16[] = {0, 0};
7025 const UINT num_vertices16 = ARRAY_SIZE(vertices16);
7026 const UINT num_faces16 = ARRAY_SIZE(indices16) / VERTS_PER_FACE;
7027 DWORD flags16 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7028 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};
7029 const DWORD adjacency16[] = {-1, 1, -1, -1, -1, 0};
7030 const struct vertex_color_ubyte4 exp_vertices16[] =
7032 {{ 0.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7033 {{ 2.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7034 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7036 {{ 2.0f, 3.0f, 0.f}, { 0, 0, 0, 0}},
7037 {{ 3.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7039 const DWORD exp_indices16[] = {0, 1, 2, 3, 4, 2};
7040 const DWORD exp_face_remap16[] = {0, 1};
7041 const DWORD exp_vertex_remap16[] = {0, 1, 2, 3, 4, -1};
7042 const DWORD exp_new_num_vertices16 = ARRAY_SIZE(exp_vertices16);
7043 /* Test 17. Weld texture coordinates but as SHORT2 instead of D3DXVECTOR2.*/
7044 const struct vertex_texcoord_short2 vertices17[] =
7046 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7047 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7048 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7050 {{ 3.0f, 3.0f, 0.f}, {32767, 32767}},
7051 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7052 {{ 1.0f, 0.0f, 0.f}, {32766, 32766}},
7054 const DWORD indices17[] = {0, 1, 2, 3, 4, 5};
7055 const DWORD attributes17[] = {0, 0};
7056 const UINT num_vertices17 = ARRAY_SIZE(vertices17);
7057 const UINT num_faces17 = ARRAY_SIZE(indices17) / VERTS_PER_FACE;
7058 DWORD flags17 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7059 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};
7060 const DWORD adjacency17[] = {-1, 1, -1, -1, -1, 0};
7061 const struct vertex_texcoord_short2 exp_vertices17[] =
7063 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7064 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7065 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7067 {{ 2.0f, 3.0f, 0.f}, {32767, 32767}},
7068 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7070 const DWORD exp_indices17[] = {0, 1, 2, 3, 4, 2};
7071 const DWORD exp_face_remap17[] = {0, 1};
7072 const DWORD exp_vertex_remap17[] = {0, 1, 2, 3, 4, -1};
7073 const DWORD exp_new_num_vertices17 = ARRAY_SIZE(exp_vertices17);
7074 /* Test 18. Weld texture coordinates but as SHORT2N instead of D3DXVECTOR2. */
7075 const struct vertex_texcoord_short2 vertices18[] =
7077 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7078 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7079 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7081 {{ 3.0f, 3.0f, 0.f}, {32767, 32767}},
7082 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7083 {{ 1.0f, 0.0f, 0.f}, {32766, 32766}},
7085 const DWORD indices18[] = {0, 1, 2, 3, 4, 5};
7086 const DWORD attributes18[] = {0, 0};
7087 const UINT num_vertices18 = ARRAY_SIZE(vertices18);
7088 const UINT num_faces18 = ARRAY_SIZE(indices18) / VERTS_PER_FACE;
7089 DWORD flags18 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7090 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};
7091 const DWORD adjacency18[] = {-1, 1, -1, -1, -1, 0};
7092 const struct vertex_texcoord_short2 exp_vertices18[] =
7094 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7095 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7096 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7098 {{ 2.0f, 3.0f, 0.f}, {32767, 32767}},
7099 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7101 const DWORD exp_indices18[] = {0, 1, 2, 3, 4, 2};
7102 const DWORD exp_face_remap18[] = {0, 1};
7103 const DWORD exp_vertex_remap18[] = {0, 1, 2, 3, 4, -1};
7104 const DWORD exp_new_num_vertices18 = ARRAY_SIZE(exp_vertices18);
7105 /* Test 19. Weld texture coordinates but as USHORT2N instead of D3DXVECTOR2. */
7106 const struct vertex_texcoord_ushort2n vertices19[] =
7108 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7109 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7110 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7112 {{ 3.0f, 3.0f, 0.f}, {65535, 65535}},
7113 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7114 {{ 1.0f, 0.0f, 0.f}, {65534, 65534}},
7116 const DWORD indices19[] = {0, 1, 2, 3, 4, 5};
7117 const DWORD attributes19[] = {0, 0};
7118 const UINT num_vertices19 = ARRAY_SIZE(vertices19);
7119 const UINT num_faces19 = ARRAY_SIZE(indices19) / VERTS_PER_FACE;
7120 DWORD flags19 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7121 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};
7122 const DWORD adjacency19[] = {-1, 1, -1, -1, -1, 0};
7123 const struct vertex_texcoord_ushort2n exp_vertices19[] =
7125 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7126 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7127 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7129 {{ 2.0f, 3.0f, 0.f}, {65535, 65535}},
7130 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7132 const DWORD exp_indices19[] = {0, 1, 2, 3, 4, 2};
7133 const DWORD exp_face_remap19[] = {0, 1};
7134 const DWORD exp_vertex_remap19[] = {0, 1, 2, 3, 4, -1};
7135 const DWORD exp_new_num_vertices19 = ARRAY_SIZE(exp_vertices19);
7136 /* Test 20. Weld normal as SHORT4 instead of D3DXVECTOR3. */
7137 const struct vertex_normal_short4 vertices20[] =
7139 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7140 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7141 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7143 {{ 3.0f, 3.0f, 0.f}, {32767, 32767, 32767, 32767}},
7144 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7145 {{ 1.0f, 0.0f, 0.f}, {32766, 32766, 32766, 32766}},
7147 const DWORD indices20[] = {0, 1, 2, 3, 4, 5};
7148 const DWORD attributes20[] = {0, 0};
7149 const UINT num_vertices20 = ARRAY_SIZE(vertices20);
7150 const UINT num_faces20 = ARRAY_SIZE(indices20) / VERTS_PER_FACE;
7151 DWORD flags20 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7152 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};
7153 const DWORD adjacency20[] = {-1, 1, -1, -1, -1, 0};
7154 const struct vertex_normal_short4 exp_vertices20[] =
7156 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7157 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7158 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7160 {{ 2.0f, 3.0f, 0.f}, {32767, 32767, 32767, 32767}},
7161 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7163 const DWORD exp_indices20[] = {0, 1, 2, 3, 4, 2};
7164 const DWORD exp_face_remap20[] = {0, 1};
7165 const DWORD exp_vertex_remap20[] = {0, 1, 2, 3, 4, -1};
7166 const DWORD exp_new_num_vertices20 = ARRAY_SIZE(exp_vertices20);
7167 /* Test 21. Weld normal as SHORT4N instead of D3DXVECTOR3. */
7168 const struct vertex_normal_short4 vertices21[] =
7170 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7171 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7172 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7174 {{ 3.0f, 3.0f, 0.f}, {32767, 32767, 32767, 32767}},
7175 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7176 {{ 1.0f, 0.0f, 0.f}, {32766, 32766, 32766, 32766}},
7178 const DWORD indices21[] = {0, 1, 2, 3, 4, 5};
7179 const DWORD attributes21[] = {0, 0};
7180 const UINT num_vertices21 = ARRAY_SIZE(vertices21);
7181 const UINT num_faces21 = ARRAY_SIZE(indices21) / VERTS_PER_FACE;
7182 DWORD flags21 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7183 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};
7184 const DWORD adjacency21[] = {-1, 1, -1, -1, -1, 0};
7185 const struct vertex_normal_short4 exp_vertices21[] =
7187 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7188 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7189 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7191 {{ 2.0f, 3.0f, 0.f}, {32767, 32767, 32767, 32767}},
7192 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7194 const DWORD exp_indices21[] = {0, 1, 2, 3, 4, 2};
7195 const DWORD exp_face_remap21[] = {0, 1};
7196 const DWORD exp_vertex_remap21[] = {0, 1, 2, 3, 4, -1};
7197 const DWORD exp_new_num_vertices21 = ARRAY_SIZE(exp_vertices21);
7198 /* Test 22. Weld normal as USHORT4N instead of D3DXVECTOR3. */
7199 const struct vertex_normal_short4 vertices22[] =
7201 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7202 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7203 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7205 {{ 3.0f, 3.0f, 0.f}, {65535, 65535, 65535, 65535}},
7206 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7207 {{ 1.0f, 0.0f, 0.f}, {65534, 65534, 65534, 65534}},
7209 const DWORD indices22[] = {0, 1, 2, 3, 4, 5};
7210 const DWORD attributes22[] = {0, 0};
7211 const UINT num_vertices22 = ARRAY_SIZE(vertices22);
7212 const UINT num_faces22 = ARRAY_SIZE(indices22) / VERTS_PER_FACE;
7213 DWORD flags22 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7214 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};
7215 const DWORD adjacency22[] = {-1, 1, -1, -1, -1, 0};
7216 const struct vertex_normal_short4 exp_vertices22[] =
7218 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7219 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7220 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7222 {{ 2.0f, 3.0f, 0.f}, {65535, 65535, 65535, 65535}},
7223 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7225 const DWORD exp_indices22[] = {0, 1, 2, 3, 4, 2};
7226 const DWORD exp_face_remap22[] = {0, 1};
7227 const DWORD exp_vertex_remap22[] = {0, 1, 2, 3, 4, -1};
7228 const DWORD exp_new_num_vertices22 = ARRAY_SIZE(exp_vertices22);
7229 /* Test 23. Weld texture coordinates as FLOAT16_2. Similar to test 11, but
7230 * with texture coordinates converted to float16 in hex. */
7231 const struct vertex_texcoord_float16_2 vertices23[] =
7233 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
7234 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */
7235 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */
7237 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd}}, /* {0.2f, 0.3f} */
7238 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
7239 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */
7241 const DWORD indices23[] = {0, 1, 2, 3, 4, 5};
7242 const DWORD attributes23[] = {0, 0};
7243 const UINT num_vertices23 = ARRAY_SIZE(vertices23);
7244 const UINT num_faces23 = ARRAY_SIZE(indices23) / VERTS_PER_FACE;
7245 DWORD flags23 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7246 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};
7247 const DWORD adjacency23[] = {-1, 1, -1, -1, -1, 0};
7248 const struct vertex_texcoord_float16_2 exp_vertices23[] =
7250 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
7251 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */
7252 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */
7254 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
7255 {{ 0.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */
7257 const DWORD exp_indices23[] = {0, 1, 2, 1, 3, 4};
7258 const DWORD exp_face_remap23[] = {0, 1};
7259 const DWORD exp_vertex_remap23[] = {0, 1, 2, 4, 5, -1};
7260 const DWORD exp_new_num_vertices23 = ARRAY_SIZE(exp_vertices23);
7261 /* Test 24. Weld texture coordinates as FLOAT16_4. Similar to test 24. */
7262 const struct vertex_texcoord_float16_4 vertices24[] =
7264 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}},
7265 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a, 0x3800, 0x399a}},
7266 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd, 0xb266, 0xb4cd}},
7268 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd, 0x3266, 0x34cd}},
7269 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}},
7270 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266, 0x2e66, 0x3266}},
7272 const DWORD indices24[] = {0, 1, 2, 3, 4, 5};
7273 const DWORD attributes24[] = {0, 0};
7274 const UINT num_vertices24 = ARRAY_SIZE(vertices24);
7275 const UINT num_faces24 = ARRAY_SIZE(indices24) / VERTS_PER_FACE;
7276 DWORD flags24 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7277 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};
7278 const DWORD adjacency24[] = {-1, 1, -1, -1, -1, 0};
7279 const struct vertex_texcoord_float16_4 exp_vertices24[] =
7281 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}},
7282 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a, 0x3800, 0x399a}},
7283 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd, 0xb266, 0xb4cd}},
7285 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}},
7286 {{ 0.0f, 0.0f, 0.f}, {0x2e66, 0x3266, 0x2e66, 0x3266}},
7288 const DWORD exp_indices24[] = {0, 1, 2, 1, 3, 4};
7289 const DWORD exp_face_remap24[] = {0, 1};
7290 const DWORD exp_vertex_remap24[] = {0, 1, 2, 4, 5, -1};
7291 const DWORD exp_new_num_vertices24 = ARRAY_SIZE(exp_vertices24);
7292 /* Test 25. Weld texture coordinates with usage index 10 (TEXCOORD10). The
7293 * usage index is capped at 7, so the epsilon for TEXCOORD7 is used instead.
7295 const struct vertex_texcoord vertices25[] =
7297 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f}},
7298 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.7f}},
7299 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
7301 {{ 3.0f, 3.0f, 0.f}, {0.2f, 0.3f}},
7302 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f}},
7303 {{ 1.0f, 0.0f, 0.f}, {0.1f, 0.2f}}
7305 const DWORD indices25[] = {0, 1, 2, 3, 4, 5};
7306 const DWORD attributes25[] = {0, 0};
7307 const UINT num_vertices25 = ARRAY_SIZE(vertices25);
7308 const UINT num_faces25 = ARRAY_SIZE(indices25) / VERTS_PER_FACE;
7309 DWORD flags25 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7310 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};
7311 const DWORD adjacency25[] = {-1, 1, -1, -1, -1, 0};
7312 const struct vertex_texcoord exp_vertices25[] =
7314 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f}},
7315 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.7f}},
7316 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
7318 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f}},
7319 {{ 0.0f, 0.0f, 0.f}, {0.1f, 0.2f}},
7321 const DWORD exp_indices25[] = {0, 1, 2, 1, 3, 4};
7322 const DWORD exp_face_remap25[] = {0, 1};
7323 const DWORD exp_vertex_remap25[] = {0, 1, 2, 4, 5, -1};
7324 const DWORD exp_new_num_vertices25 = ARRAY_SIZE(exp_vertices25);
7325 /* Test 26. Weld color with usage index larger than 1. Shows that none of
7326 * the epsilon values are used. */
7327 const struct vertex_color vertices26[] =
7329 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7330 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7331 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7333 {{ 3.0f, 3.0f, 0.f}, 0x00000000},
7334 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7335 {{ 1.0f, 0.0f, 0.f}, 0x01010101},
7337 const DWORD indices26[] = {0, 1, 2, 3, 4, 5};
7338 const DWORD attributes26[] = {0, 0};
7339 const UINT num_vertices26 = ARRAY_SIZE(vertices26);
7340 const UINT num_faces26 = ARRAY_SIZE(indices26) / VERTS_PER_FACE;
7341 DWORD flags26 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7342 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};
7343 const DWORD adjacency26[] = {-1, 1, -1, -1, -1, 0};
7344 const struct vertex_color exp_vertices26[] =
7346 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7347 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7348 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7350 {{ 2.0f, 3.0f, 0.f}, 0x00000000},
7351 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7352 {{ 0.0f, 0.0f, 0.f}, 0x01010101},
7354 const DWORD exp_indices26[] = {0, 1, 2, 3, 4, 5};
7355 const DWORD exp_face_remap26[] = {0, 1};
7356 const DWORD exp_vertex_remap26[] = {0, 1, 2, 3, 4, 5};
7357 const DWORD exp_new_num_vertices26 = ARRAY_SIZE(exp_vertices26);
7358 /* Test 27. Weld color with usage index larger than 1. Check that the
7359 * default epsilon of 1e-6f is used. */
7360 D3DXVECTOR4 zero_float4 = {0.0f, 0.0f, 0.0f, 0.0f};
7361 D3DXVECTOR4 almost_zero_float4 = {0.0f + FLT_EPSILON, 0.0f + FLT_EPSILON, 0.0f + FLT_EPSILON, 0.0f + FLT_EPSILON};
7362 const struct vertex_color_float4 vertices27[] =
7364 {{ 0.0f, 3.0f, 0.f}, zero_float4},
7365 {{ 2.0f, 3.0f, 0.f}, zero_float4},
7366 {{ 0.0f, 0.0f, 0.f}, zero_float4},
7368 {{ 3.0f, 3.0f, 0.f}, almost_zero_float4},
7369 {{ 3.0f, 0.0f, 0.f}, zero_float4},
7370 {{ 1.0f, 0.0f, 0.f}, almost_zero_float4},
7372 const DWORD indices27[] = {0, 1, 2, 3, 4, 5};
7373 const DWORD attributes27[] = {0, 0};
7374 const UINT num_vertices27 = ARRAY_SIZE(vertices27);
7375 const UINT num_faces27 = ARRAY_SIZE(indices27) / VERTS_PER_FACE;
7376 DWORD flags27 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7377 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};
7378 const DWORD adjacency27[] = {-1, 1, -1, -1, -1, 0};
7379 const struct vertex_color_float4 exp_vertices27[] =
7381 {{ 0.0f, 3.0f, 0.f}, zero_float4},
7382 {{ 2.0f, 3.0f, 0.f}, zero_float4},
7383 {{ 0.0f, 0.0f, 0.f}, zero_float4},
7385 {{ 3.0f, 0.0f, 0.f}, zero_float4},
7387 const DWORD exp_indices27[] = {0, 1, 2, 1, 3, 2};
7388 const DWORD exp_face_remap27[] = {0, 1};
7389 const DWORD exp_vertex_remap27[] = {0, 1, 2, 4, -1, -1};
7390 const DWORD exp_new_num_vertices27 = ARRAY_SIZE(exp_vertices27);
7391 /* Test 28. Weld one normal with UDEC3. */
7392 const DWORD dword_udec3_zero = init_udec3_dword(0, 0, 0, 1);
7393 const DWORD dword_udec3_1023 = init_udec3_dword(1023, 1023, 1023, 1);
7394 const DWORD dword_udec3_1022 = init_udec3_dword(1022, 1022, 1022, 1);
7395 const struct vertex_normal_udec3 vertices28[] =
7397 {{ 0.0f, 3.0f, 0.f}, dword_udec3_zero},
7398 {{ 2.0f, 3.0f, 0.f}, dword_udec3_zero},
7399 {{ 0.0f, 0.0f, 0.f}, dword_udec3_zero},
7401 {{ 3.0f, 3.0f, 0.f}, dword_udec3_1023},
7402 {{ 3.0f, 0.0f, 0.f}, dword_udec3_zero},
7403 {{ 1.0f, 0.0f, 0.f}, dword_udec3_1022},
7405 const DWORD indices28[] = {0, 1, 2, 3, 4, 5};
7406 const DWORD attributes28[] = {0, 0};
7407 const UINT num_vertices28 = ARRAY_SIZE(vertices28);
7408 const UINT num_faces28 = ARRAY_SIZE(indices28) / VERTS_PER_FACE;
7409 DWORD flags28 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7410 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};
7411 const DWORD adjacency28[] = {-1, 1, -1, -1, -1, 0};
7412 const struct vertex_normal_udec3 exp_vertices28[] =
7414 {{ 0.0f, 3.0f, 0.f}, dword_udec3_zero},
7415 {{ 2.0f, 3.0f, 0.f}, dword_udec3_zero},
7416 {{ 0.0f, 0.0f, 0.f}, dword_udec3_zero},
7418 {{ 2.0f, 3.0f, 0.f}, dword_udec3_1023},
7419 {{ 3.0f, 0.0f, 0.f}, dword_udec3_zero},
7421 const DWORD exp_indices28[] = {0, 1, 2, 3, 4, 2};
7422 const DWORD exp_face_remap28[] = {0, 1};
7423 const DWORD exp_vertex_remap28[] = {0, 1, 2, 3, 4, -1};
7424 const DWORD exp_new_num_vertices28 = ARRAY_SIZE(exp_vertices28);
7425 /* Test 29. Weld one normal with DEC3N. */
7426 const DWORD dword_dec3n_zero = init_dec3n_dword(0, 0, 0, 1);
7427 const DWORD dword_dec3n_511 = init_dec3n_dword(511, 511, 511, 1);
7428 const DWORD dword_dec3n_510 = init_dec3n_dword(510, 510, 510, 1);
7429 const struct vertex_normal_dec3n vertices29[] =
7431 {{ 0.0f, 3.0f, 0.f}, dword_dec3n_zero},
7432 {{ 2.0f, 3.0f, 0.f}, dword_dec3n_zero},
7433 {{ 0.0f, 0.0f, 0.f}, dword_dec3n_zero},
7435 {{ 3.0f, 3.0f, 0.f}, dword_dec3n_511},
7436 {{ 3.0f, 0.0f, 0.f}, dword_dec3n_zero},
7437 {{ 1.0f, 0.0f, 0.f}, dword_dec3n_510},
7439 const DWORD indices29[] = {0, 1, 2, 3, 4, 5};
7440 const DWORD attributes29[] = {0, 0};
7441 const UINT num_vertices29 = ARRAY_SIZE(vertices29);
7442 const UINT num_faces29 = ARRAY_SIZE(indices29) / VERTS_PER_FACE;
7443 DWORD flags29 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7444 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};
7445 const DWORD adjacency29[] = {-1, 1, -1, -1, -1, 0};
7446 const struct vertex_normal_dec3n exp_vertices29[] =
7448 {{ 0.0f, 3.0f, 0.f}, dword_dec3n_zero},
7449 {{ 2.0f, 3.0f, 0.f}, dword_dec3n_zero},
7450 {{ 0.0f, 0.0f, 0.f}, dword_dec3n_zero},
7452 {{ 2.0f, 3.0f, 0.f}, dword_dec3n_511},
7453 {{ 3.0f, 0.0f, 0.f}, dword_dec3n_zero},
7455 const DWORD exp_indices29[] = {0, 1, 2, 3, 4, 2};
7456 const DWORD exp_face_remap29[] = {0, 1};
7457 const DWORD exp_vertex_remap29[] = {0, 1, 2, 3, 4, -1};
7458 const DWORD exp_new_num_vertices29 = ARRAY_SIZE(exp_vertices29);
7459 /* All mesh data */
7460 DWORD *adjacency_out = NULL;
7461 DWORD *face_remap = NULL;
7462 ID3DXMesh *mesh = NULL;
7463 ID3DXBuffer *vertex_remap = NULL;
7464 struct
7466 const BYTE *vertices;
7467 const DWORD *indices;
7468 const DWORD *attributes;
7469 const DWORD num_vertices;
7470 const DWORD num_faces;
7471 const DWORD options;
7472 D3DVERTEXELEMENT9 *declaration;
7473 const UINT vertex_size;
7474 const DWORD flags;
7475 const D3DXWELDEPSILONS *epsilons;
7476 const DWORD *adjacency;
7477 const BYTE *exp_vertices;
7478 const DWORD *exp_indices;
7479 const DWORD *exp_face_remap;
7480 const DWORD *exp_vertex_remap;
7481 const DWORD exp_new_num_vertices;
7483 tc[] =
7486 (BYTE*)vertices0,
7487 indices0,
7488 attributes0,
7489 num_vertices0,
7490 num_faces0,
7491 options,
7492 declaration_normal,
7493 vertex_size_normal,
7494 flags0,
7495 NULL,
7496 adjacency0,
7497 (BYTE*)exp_vertices0,
7498 exp_indices0,
7499 exp_face_remap0,
7500 exp_vertex_remap0,
7501 exp_new_num_vertices0
7504 (BYTE*)vertices1,
7505 indices1,
7506 attributes1,
7507 num_vertices1,
7508 num_faces1,
7509 options,
7510 declaration_normal,
7511 vertex_size_normal,
7512 flags1,
7513 NULL,
7514 adjacency1,
7515 (BYTE*)exp_vertices1,
7516 exp_indices1,
7517 exp_face_remap1,
7518 exp_vertex_remap1,
7519 exp_new_num_vertices1
7522 (BYTE*)vertices2,
7523 indices2,
7524 attributes2,
7525 num_vertices2,
7526 num_faces2,
7527 options,
7528 declaration_normal,
7529 vertex_size_normal,
7530 flags2,
7531 &epsilons2,
7532 adjacency2,
7533 (BYTE*)exp_vertices2,
7534 exp_indices2,
7535 exp_face_remap2,
7536 exp_vertex_remap2,
7537 exp_new_num_vertices2
7540 (BYTE*)vertices3,
7541 indices3,
7542 attributes3,
7543 num_vertices3,
7544 num_faces3,
7545 options,
7546 declaration_normal,
7547 vertex_size_normal,
7548 flags3,
7549 &epsilons3,
7550 adjacency3,
7551 (BYTE*)exp_vertices3,
7552 exp_indices3,
7553 exp_face_remap3,
7554 exp_vertex_remap3,
7555 exp_new_num_vertices3
7558 (BYTE*)vertices4,
7559 indices4,
7560 attributes4,
7561 num_vertices4,
7562 num_faces4,
7563 options,
7564 declaration_normal,
7565 vertex_size_normal,
7566 flags4,
7567 &epsilons4,
7568 adjacency4,
7569 (BYTE*)exp_vertices4,
7570 exp_indices4,
7571 exp_face_remap4,
7572 exp_vertex_remap4,
7573 exp_new_num_vertices4
7575 /* Unusual ordering. */
7577 (BYTE*)vertices5,
7578 indices5,
7579 attributes5,
7580 num_vertices5,
7581 num_faces5,
7582 options,
7583 declaration_normal,
7584 vertex_size_normal,
7585 flags5,
7586 NULL,
7587 adjacency5,
7588 (BYTE*)exp_vertices5,
7589 exp_indices5,
7590 exp_face_remap5,
7591 exp_vertex_remap5,
7592 exp_new_num_vertices5
7595 (BYTE*)vertices6,
7596 indices6,
7597 attributes6,
7598 num_vertices6,
7599 num_faces6,
7600 options,
7601 declaration_normal,
7602 vertex_size_normal,
7603 flags6,
7604 &epsilons6,
7605 adjacency6,
7606 (BYTE*)exp_vertices6,
7607 exp_indices6,
7608 exp_face_remap6,
7609 exp_vertex_remap6,
7610 exp_new_num_vertices6
7613 (BYTE*)vertices6,
7614 (DWORD*)indices6_16bit,
7615 attributes6,
7616 num_vertices6,
7617 num_faces6,
7618 options_16bit,
7619 declaration_normal,
7620 vertex_size_normal,
7621 flags6,
7622 &epsilons6,
7623 adjacency6,
7624 (BYTE*)exp_vertices6,
7625 exp_indices6,
7626 exp_face_remap6,
7627 exp_vertex_remap6,
7628 exp_new_num_vertices6
7631 (BYTE*)vertices8,
7632 indices8,
7633 attributes8,
7634 num_vertices8,
7635 num_faces8,
7636 options,
7637 declaration_normal,
7638 vertex_size_normal,
7639 flags8,
7640 &epsilons8,
7641 adjacency8,
7642 (BYTE*)exp_vertices8,
7643 exp_indices8,
7644 exp_face_remap8,
7645 exp_vertex_remap8,
7646 exp_new_num_vertices8
7649 (BYTE*)vertices9,
7650 indices9,
7651 attributes9,
7652 num_vertices9,
7653 num_faces9,
7654 options,
7655 declaration_normal,
7656 vertex_size_normal,
7657 flags9,
7658 &epsilons9,
7659 adjacency9,
7660 (BYTE*)exp_vertices9,
7661 exp_indices9,
7662 exp_face_remap9,
7663 exp_vertex_remap9,
7664 exp_new_num_vertices9
7667 (BYTE*)vertices10,
7668 indices10,
7669 attributes10,
7670 num_vertices10,
7671 num_faces10,
7672 options,
7673 declaration_blendweight,
7674 vertex_size_blendweight,
7675 flags10,
7676 &epsilons10,
7677 adjacency10,
7678 (BYTE*)exp_vertices10,
7679 exp_indices10,
7680 exp_face_remap10,
7681 exp_vertex_remap10,
7682 exp_new_num_vertices10
7685 (BYTE*)vertices11,
7686 indices11,
7687 attributes11,
7688 num_vertices11,
7689 num_faces11,
7690 options,
7691 declaration_texcoord,
7692 vertex_size_texcoord,
7693 flags11,
7694 &epsilons11,
7695 adjacency11,
7696 (BYTE*)exp_vertices11,
7697 exp_indices11,
7698 exp_face_remap11,
7699 exp_vertex_remap11,
7700 exp_new_num_vertices11
7703 (BYTE*)vertices12,
7704 indices12,
7705 attributes12,
7706 num_vertices12,
7707 num_faces12,
7708 options,
7709 declaration_color,
7710 vertex_size_color,
7711 flags12,
7712 &epsilons12,
7713 adjacency12,
7714 (BYTE*)exp_vertices12,
7715 exp_indices12,
7716 exp_face_remap12,
7717 exp_vertex_remap12,
7718 exp_new_num_vertices12
7721 (BYTE*)vertices13,
7722 indices13,
7723 attributes13,
7724 num_vertices13,
7725 num_faces13,
7726 options,
7727 declaration_normal3,
7728 vertex_size_normal,
7729 flags13,
7730 &epsilons13,
7731 adjacency13,
7732 (BYTE*)exp_vertices13,
7733 exp_indices13,
7734 exp_face_remap13,
7735 exp_vertex_remap13,
7736 exp_new_num_vertices13
7739 (BYTE*)vertices14,
7740 indices14,
7741 attributes14,
7742 num_vertices14,
7743 num_faces14,
7744 options,
7745 declaration_color,
7746 vertex_size_color,
7747 flags14,
7748 &epsilons14,
7749 adjacency14,
7750 (BYTE*)exp_vertices14,
7751 exp_indices14,
7752 exp_face_remap14,
7753 exp_vertex_remap14,
7754 exp_new_num_vertices14
7757 (BYTE*)vertices15,
7758 indices15,
7759 attributes15,
7760 num_vertices15,
7761 num_faces15,
7762 options,
7763 declaration_color_ubyte4n,
7764 vertex_size_color_ubyte4, /* UBYTE4 same size as UBYTE4N */
7765 flags15,
7766 &epsilons15,
7767 adjacency15,
7768 (BYTE*)exp_vertices15,
7769 exp_indices15,
7770 exp_face_remap15,
7771 exp_vertex_remap15,
7772 exp_new_num_vertices15
7775 (BYTE*)vertices16,
7776 indices16,
7777 attributes16,
7778 num_vertices16,
7779 num_faces16,
7780 options,
7781 declaration_color_ubyte4,
7782 vertex_size_color_ubyte4,
7783 flags16,
7784 &epsilons16,
7785 adjacency16,
7786 (BYTE*)exp_vertices16,
7787 exp_indices16,
7788 exp_face_remap16,
7789 exp_vertex_remap16,
7790 exp_new_num_vertices16
7793 (BYTE*)vertices17,
7794 indices17,
7795 attributes17,
7796 num_vertices17,
7797 num_faces17,
7798 options,
7799 declaration_texcoord_short2,
7800 vertex_size_texcoord_short2,
7801 flags17,
7802 &epsilons17,
7803 adjacency17,
7804 (BYTE*)exp_vertices17,
7805 exp_indices17,
7806 exp_face_remap17,
7807 exp_vertex_remap17,
7808 exp_new_num_vertices17
7811 (BYTE*)vertices18,
7812 indices18,
7813 attributes18,
7814 num_vertices18,
7815 num_faces18,
7816 options,
7817 declaration_texcoord_short2n,
7818 vertex_size_texcoord_short2, /* SHORT2 same size as SHORT2N */
7819 flags18,
7820 &epsilons18,
7821 adjacency18,
7822 (BYTE*)exp_vertices18,
7823 exp_indices18,
7824 exp_face_remap18,
7825 exp_vertex_remap18,
7826 exp_new_num_vertices18
7829 (BYTE*)vertices19,
7830 indices19,
7831 attributes19,
7832 num_vertices19,
7833 num_faces19,
7834 options,
7835 declaration_texcoord_ushort2n,
7836 vertex_size_texcoord_short2, /* SHORT2 same size as USHORT2N */
7837 flags19,
7838 &epsilons19,
7839 adjacency19,
7840 (BYTE*)exp_vertices19,
7841 exp_indices19,
7842 exp_face_remap19,
7843 exp_vertex_remap19,
7844 exp_new_num_vertices19
7847 (BYTE*)vertices20,
7848 indices20,
7849 attributes20,
7850 num_vertices20,
7851 num_faces20,
7852 options,
7853 declaration_normal_short4,
7854 vertex_size_normal_short4,
7855 flags20,
7856 &epsilons20,
7857 adjacency20,
7858 (BYTE*)exp_vertices20,
7859 exp_indices20,
7860 exp_face_remap20,
7861 exp_vertex_remap20,
7862 exp_new_num_vertices20
7865 (BYTE*)vertices21,
7866 indices21,
7867 attributes21,
7868 num_vertices21,
7869 num_faces21,
7870 options,
7871 declaration_normal_short4n,
7872 vertex_size_normal_short4, /* SHORT4 same size as SHORT4N */
7873 flags21,
7874 &epsilons21,
7875 adjacency21,
7876 (BYTE*)exp_vertices21,
7877 exp_indices21,
7878 exp_face_remap21,
7879 exp_vertex_remap21,
7880 exp_new_num_vertices21
7883 (BYTE*)vertices22,
7884 indices22,
7885 attributes22,
7886 num_vertices22,
7887 num_faces22,
7888 options,
7889 declaration_normal_ushort4n,
7890 vertex_size_normal_short4, /* SHORT4 same size as USHORT4N */
7891 flags22,
7892 &epsilons22,
7893 adjacency22,
7894 (BYTE*)exp_vertices22,
7895 exp_indices22,
7896 exp_face_remap22,
7897 exp_vertex_remap22,
7898 exp_new_num_vertices22
7901 (BYTE*)vertices23,
7902 indices23,
7903 attributes23,
7904 num_vertices23,
7905 num_faces23,
7906 options,
7907 declaration_texcoord_float16_2,
7908 vertex_size_texcoord_float16_2,
7909 flags23,
7910 &epsilons23,
7911 adjacency23,
7912 (BYTE*)exp_vertices23,
7913 exp_indices23,
7914 exp_face_remap23,
7915 exp_vertex_remap23,
7916 exp_new_num_vertices23
7919 (BYTE*)vertices24,
7920 indices24,
7921 attributes24,
7922 num_vertices24,
7923 num_faces24,
7924 options,
7925 declaration_texcoord_float16_4,
7926 vertex_size_texcoord_float16_4,
7927 flags24,
7928 &epsilons24,
7929 adjacency24,
7930 (BYTE*)exp_vertices24,
7931 exp_indices24,
7932 exp_face_remap24,
7933 exp_vertex_remap24,
7934 exp_new_num_vertices24
7937 (BYTE*)vertices25,
7938 indices25,
7939 attributes25,
7940 num_vertices25,
7941 num_faces25,
7942 options,
7943 declaration_texcoord10,
7944 vertex_size_texcoord,
7945 flags25,
7946 &epsilons25,
7947 adjacency25,
7948 (BYTE*)exp_vertices25,
7949 exp_indices25,
7950 exp_face_remap25,
7951 exp_vertex_remap25,
7952 exp_new_num_vertices25
7955 (BYTE*)vertices26,
7956 indices26,
7957 attributes26,
7958 num_vertices26,
7959 num_faces26,
7960 options,
7961 declaration_color2,
7962 vertex_size_color,
7963 flags26,
7964 &epsilons26,
7965 adjacency26,
7966 (BYTE*)exp_vertices26,
7967 exp_indices26,
7968 exp_face_remap26,
7969 exp_vertex_remap26,
7970 exp_new_num_vertices26
7973 (BYTE*)vertices27,
7974 indices27,
7975 attributes27,
7976 num_vertices27,
7977 num_faces27,
7978 options,
7979 declaration_color2_float4,
7980 vertex_size_color_float4,
7981 flags27,
7982 &epsilons27,
7983 adjacency27,
7984 (BYTE*)exp_vertices27,
7985 exp_indices27,
7986 exp_face_remap27,
7987 exp_vertex_remap27,
7988 exp_new_num_vertices27
7991 (BYTE*)vertices28,
7992 indices28,
7993 attributes28,
7994 num_vertices28,
7995 num_faces28,
7996 options,
7997 declaration_normal_udec3,
7998 vertex_size_normal_udec3,
7999 flags28,
8000 &epsilons28,
8001 adjacency28,
8002 (BYTE*)exp_vertices28,
8003 exp_indices28,
8004 exp_face_remap28,
8005 exp_vertex_remap28,
8006 exp_new_num_vertices28
8009 (BYTE*)vertices29,
8010 indices29,
8011 attributes29,
8012 num_vertices29,
8013 num_faces29,
8014 options,
8015 declaration_normal_dec3n,
8016 vertex_size_normal_dec3n,
8017 flags29,
8018 &epsilons29,
8019 adjacency29,
8020 (BYTE*)exp_vertices29,
8021 exp_indices29,
8022 exp_face_remap29,
8023 exp_vertex_remap29,
8024 exp_new_num_vertices29
8028 test_context = new_test_context();
8029 if (!test_context)
8031 skip("Couldn't create test context\n");
8032 goto cleanup;
8035 for (i = 0; i < ARRAY_SIZE(tc); i++)
8037 DWORD j;
8038 DWORD *vertex_remap_ptr;
8039 DWORD new_num_vertices;
8041 hr = init_test_mesh(tc[i].num_faces, tc[i].num_vertices, tc[i].options,
8042 tc[i].declaration, test_context->device, &mesh,
8043 tc[i].vertices, tc[i].vertex_size,
8044 tc[i].indices, tc[i].attributes);
8045 if (FAILED(hr))
8047 skip("Couldn't initialize test mesh %d.\n", i);
8048 goto cleanup;
8051 /* Allocate out parameters */
8052 adjacency_out = HeapAlloc(GetProcessHeap(), 0, VERTS_PER_FACE * tc[i].num_faces * sizeof(*adjacency_out));
8053 if (!adjacency_out)
8055 skip("Couldn't allocate adjacency_out array.\n");
8056 goto cleanup;
8058 face_remap = HeapAlloc(GetProcessHeap(), 0, tc[i].num_faces * sizeof(*face_remap));
8059 if (!adjacency_out)
8061 skip("Couldn't allocate face_remap array.\n");
8062 goto cleanup;
8064 hr = D3DXCreateBuffer(tc[i].num_vertices * sizeof(DWORD), &vertex_remap);
8065 if (FAILED(hr))
8067 skip("Couldn't create vertex_remap buffer.\n");
8068 goto cleanup;
8071 hr = D3DXWeldVertices(mesh, tc[i].flags, tc[i].epsilons, tc[i].adjacency,
8072 adjacency_out, face_remap, &vertex_remap);
8073 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
8074 /* Check number of vertices*/
8075 new_num_vertices = mesh->lpVtbl->GetNumVertices(mesh);
8076 ok(new_num_vertices == tc[i].exp_new_num_vertices,
8077 "Mesh %d: new_num_vertices == %d, expected %d.\n",
8078 i, new_num_vertices, tc[i].exp_new_num_vertices);
8079 /* Check index buffer */
8080 if (tc[i].options & D3DXMESH_32BIT)
8082 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, (void**)&indices);
8083 if (FAILED(hr))
8085 skip("Couldn't lock index buffer.\n");
8086 goto cleanup;
8088 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
8090 ok(indices[j] == tc[i].exp_indices[j],
8091 "Mesh %d: indices[%d] == %d, expected %d\n",
8092 i, j, indices[j], tc[i].exp_indices[j]);
8095 else
8097 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, (void**)&indices_16bit);
8098 if (FAILED(hr))
8100 skip("Couldn't lock index buffer.\n");
8101 goto cleanup;
8103 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
8105 ok(indices_16bit[j] == tc[i].exp_indices[j],
8106 "Mesh %d: indices_16bit[%d] == %d, expected %d\n",
8107 i, j, indices_16bit[j], tc[i].exp_indices[j]);
8110 mesh->lpVtbl->UnlockIndexBuffer(mesh);
8111 indices = NULL;
8112 indices_16bit = NULL;
8113 /* Check adjacency_out */
8114 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
8116 ok(adjacency_out[j] == tc[i].adjacency[j],
8117 "Mesh %d: adjacency_out[%d] == %d, expected %d\n",
8118 i, j, adjacency_out[j], tc[i].adjacency[j]);
8120 /* Check face_remap */
8121 for (j = 0; j < tc[i].num_faces; j++)
8123 ok(face_remap[j] == tc[i].exp_face_remap[j],
8124 "Mesh %d: face_remap[%d] == %d, expected %d\n",
8125 i, j, face_remap[j], tc[i].exp_face_remap[j]);
8127 /* Check vertex_remap */
8128 vertex_remap_ptr = vertex_remap->lpVtbl->GetBufferPointer(vertex_remap);
8129 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
8131 ok(vertex_remap_ptr[j] == tc[i].exp_vertex_remap[j],
8132 "Mesh %d: vertex_remap_ptr[%d] == %d, expected %d\n",
8133 i, j, vertex_remap_ptr[j], tc[i].exp_vertex_remap[j]);
8135 /* Check vertex buffer */
8136 hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, (void*)&vertices);
8137 if (FAILED(hr))
8139 skip("Couldn't lock vertex buffer.\n");
8140 goto cleanup;
8142 /* Check contents of re-ordered vertex buffer */
8143 for (j = 0; j < tc[i].exp_new_num_vertices; j++)
8145 int index = tc[i].vertex_size*j;
8146 check_vertex_components(__LINE__, i, j, &vertices[index], &tc[i].exp_vertices[index], tc[i].declaration);
8148 mesh->lpVtbl->UnlockVertexBuffer(mesh);
8149 vertices = NULL;
8151 /* Free mesh and output data */
8152 HeapFree(GetProcessHeap(), 0, adjacency_out);
8153 adjacency_out = NULL;
8154 HeapFree(GetProcessHeap(), 0, face_remap);
8155 face_remap = NULL;
8156 vertex_remap->lpVtbl->Release(vertex_remap);
8157 vertex_remap = NULL;
8158 mesh->lpVtbl->Release(mesh);
8159 mesh = NULL;
8162 cleanup:
8163 HeapFree(GetProcessHeap(), 0, adjacency_out);
8164 HeapFree(GetProcessHeap(), 0, face_remap);
8165 if (indices) mesh->lpVtbl->UnlockIndexBuffer(mesh);
8166 if (indices_16bit) mesh->lpVtbl->UnlockIndexBuffer(mesh);
8167 if (mesh) mesh->lpVtbl->Release(mesh);
8168 if (vertex_remap) vertex_remap->lpVtbl->Release(vertex_remap);
8169 if (vertices) mesh->lpVtbl->UnlockVertexBuffer(mesh);
8170 free_test_context(test_context);
8173 static void test_clone_mesh(void)
8175 HRESULT hr;
8176 struct test_context *test_context = NULL;
8177 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
8178 D3DVERTEXELEMENT9 declaration_pn[] =
8180 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8181 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
8182 D3DDECL_END()
8184 D3DVERTEXELEMENT9 declaration_pntc[] =
8186 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8187 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
8188 {0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8189 D3DDECL_END()
8191 D3DVERTEXELEMENT9 declaration_ptcn[] =
8193 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8194 {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8195 {0, 20, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
8196 D3DDECL_END()
8198 D3DVERTEXELEMENT9 declaration_ptc[] =
8200 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8201 {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8202 D3DDECL_END()
8204 D3DVERTEXELEMENT9 declaration_ptc_float16_2[] =
8206 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8207 {0, 12, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8208 D3DDECL_END()
8210 D3DVERTEXELEMENT9 declaration_ptc_float16_4[] =
8212 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8213 {0, 12, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8214 D3DDECL_END()
8216 D3DVERTEXELEMENT9 declaration_ptc_float1[] =
8218 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8219 {0, 12, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8220 D3DDECL_END()
8222 D3DVERTEXELEMENT9 declaration_ptc_float3[] =
8224 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8225 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8226 D3DDECL_END()
8228 D3DVERTEXELEMENT9 declaration_ptc_float4[] =
8230 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8231 {0, 12, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8232 D3DDECL_END()
8234 D3DVERTEXELEMENT9 declaration_ptc_d3dcolor[] =
8236 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8237 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8238 D3DDECL_END()
8240 D3DVERTEXELEMENT9 declaration_ptc_ubyte4[] =
8242 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8243 {0, 12, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8244 D3DDECL_END()
8246 D3DVERTEXELEMENT9 declaration_ptc_ubyte4n[] =
8248 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8249 {0, 12, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8250 D3DDECL_END()
8252 D3DVERTEXELEMENT9 declaration_ptc_short2[] =
8254 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8255 {0, 12, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8256 D3DDECL_END()
8258 D3DVERTEXELEMENT9 declaration_ptc_short4[] =
8260 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8261 {0, 12, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8262 D3DDECL_END()
8264 D3DVERTEXELEMENT9 declaration_ptc_short2n[] =
8266 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8267 {0, 12, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8268 D3DDECL_END()
8270 D3DVERTEXELEMENT9 declaration_ptc_short4n[] =
8272 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8273 {0, 12, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8274 D3DDECL_END()
8276 D3DVERTEXELEMENT9 declaration_ptc_ushort2n[] =
8278 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8279 {0, 12, D3DDECLTYPE_USHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8280 D3DDECL_END()
8282 D3DVERTEXELEMENT9 declaration_ptc_ushort4n[] =
8284 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8285 {0, 12, D3DDECLTYPE_USHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8286 D3DDECL_END()
8288 D3DVERTEXELEMENT9 declaration_ptc_float16_2_partialu[] =
8290 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8291 {0, 12, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_PARTIALU, D3DDECLUSAGE_TEXCOORD, 0},
8292 D3DDECL_END()
8294 D3DVERTEXELEMENT9 declaration_pntc1[] =
8296 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8297 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
8298 {0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
8299 D3DDECL_END()
8301 const unsigned int VERTS_PER_FACE = 3;
8302 BYTE *vertices = NULL;
8303 INT i;
8304 struct vertex_pn
8306 D3DXVECTOR3 position;
8307 D3DXVECTOR3 normal;
8309 struct vertex_pntc
8311 D3DXVECTOR3 position;
8312 D3DXVECTOR3 normal;
8313 D3DXVECTOR2 texcoords;
8315 struct vertex_ptcn
8317 D3DXVECTOR3 position;
8318 D3DXVECTOR2 texcoords;
8319 D3DXVECTOR3 normal;
8321 struct vertex_ptc
8323 D3DXVECTOR3 position;
8324 D3DXVECTOR2 texcoords;
8326 struct vertex_ptc_float16_2
8328 D3DXVECTOR3 position;
8329 WORD texcoords[2]; /* float16_2 */
8331 struct vertex_ptc_float16_4
8333 D3DXVECTOR3 position;
8334 WORD texcoords[4]; /* float16_4 */
8336 struct vertex_ptc_float1
8338 D3DXVECTOR3 position;
8339 FLOAT texcoords;
8341 struct vertex_ptc_float3
8343 D3DXVECTOR3 position;
8344 FLOAT texcoords[3];
8346 struct vertex_ptc_float4
8348 D3DXVECTOR3 position;
8349 FLOAT texcoords[4];
8351 struct vertex_ptc_d3dcolor
8353 D3DXVECTOR3 position;
8354 BYTE texcoords[4];
8356 struct vertex_ptc_ubyte4
8358 D3DXVECTOR3 position;
8359 BYTE texcoords[4];
8361 struct vertex_ptc_ubyte4n
8363 D3DXVECTOR3 position;
8364 BYTE texcoords[4];
8366 struct vertex_ptc_short2
8368 D3DXVECTOR3 position;
8369 SHORT texcoords[2];
8371 struct vertex_ptc_short4
8373 D3DXVECTOR3 position;
8374 SHORT texcoords[4];
8376 struct vertex_ptc_ushort2n
8378 D3DXVECTOR3 position;
8379 USHORT texcoords[2];
8381 struct vertex_ptc_ushort4n
8383 D3DXVECTOR3 position;
8384 USHORT texcoords[4];
8386 struct vertex_ptc_udec3
8388 D3DXVECTOR3 position;
8389 DWORD texcoords;
8391 struct vertex_ptc_dec3n
8393 D3DXVECTOR3 position;
8394 DWORD texcoords;
8396 D3DXVECTOR3 up = {0.0f, 0.0f, 1.0f};
8397 D3DXVECTOR2 zero_vec2 = {0.0f, 0.0f};
8398 /* Test 0. Check that a mesh can be cloned if the new declaration is the
8399 * same as the one used to create the mesh.
8401 * 0--1 3
8402 * | / /|
8403 * |/ / |
8404 * 2 5--4
8406 const struct vertex_pn vertices0[] =
8408 {{ 0.0f, 3.0f, 0.f}, up},
8409 {{ 2.0f, 3.0f, 0.f}, up},
8410 {{ 0.0f, 0.0f, 0.f}, up},
8412 {{ 3.0f, 3.0f, 0.f}, up},
8413 {{ 3.0f, 0.0f, 0.f}, up},
8414 {{ 1.0f, 0.0f, 0.f}, up},
8416 const UINT num_vertices0 = ARRAY_SIZE(vertices0);
8417 const UINT num_faces0 = ARRAY_SIZE(vertices0) / VERTS_PER_FACE;
8418 const UINT vertex_size0 = sizeof(*vertices0);
8419 /* Test 1. Check that 16-bit indices are handled. */
8420 const DWORD options_16bit = D3DXMESH_SYSTEMMEM;
8421 /* Test 2. Check that the size of each vertex is increased and the data
8422 * moved if the new declaration adds an element after the original elements.
8424 const struct vertex_pntc exp_vertices2[] =
8426 {{ 0.0f, 3.0f, 0.f}, up, zero_vec2},
8427 {{ 2.0f, 3.0f, 0.f}, up, zero_vec2},
8428 {{ 0.0f, 0.0f, 0.f}, up, zero_vec2},
8430 {{ 3.0f, 3.0f, 0.f}, up, zero_vec2},
8431 {{ 3.0f, 0.0f, 0.f}, up, zero_vec2},
8432 {{ 1.0f, 0.0f, 0.f}, up, zero_vec2},
8434 const UINT exp_vertex_size2 = sizeof(*exp_vertices2);
8435 /* Test 3. Check that the size of each vertex is increased and the data
8436 * moved if the new declaration adds an element between the original
8437 * elements.
8439 const struct vertex_ptcn exp_vertices3[] =
8441 {{ 0.0f, 3.0f, 0.f}, zero_vec2, up},
8442 {{ 2.0f, 3.0f, 0.f}, zero_vec2, up},
8443 {{ 0.0f, 0.0f, 0.f}, zero_vec2, up},
8445 {{ 3.0f, 3.0f, 0.f}, zero_vec2, up},
8446 {{ 3.0f, 0.0f, 0.f}, zero_vec2, up},
8447 {{ 1.0f, 0.0f, 0.f}, zero_vec2, up},
8449 const UINT exp_vertex_size3 = sizeof(*exp_vertices3);
8450 /* Test 4. Test that data types can be converted, e.g. FLOAT2 to FLOAT16_2. */
8451 const struct vertex_ptc vertices4[] =
8453 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8454 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8455 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
8457 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8458 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
8459 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
8461 const UINT num_vertices4 = ARRAY_SIZE(vertices4);
8462 const UINT num_faces4 = ARRAY_SIZE(vertices4) / VERTS_PER_FACE;
8463 const UINT vertex_size4 = sizeof(*vertices4);
8464 const struct vertex_ptc_float16_2 exp_vertices4[] =
8466 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
8467 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */
8468 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */
8470 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd}}, /* {0.2f, 0.3f} */
8471 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
8472 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */
8474 const UINT exp_vertex_size4 = sizeof(*exp_vertices4);
8475 /* Test 5. Convert FLOAT2 to FLOAT16_4. */
8476 const struct vertex_ptc vertices5[] =
8478 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8479 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8480 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
8482 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8483 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
8484 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
8486 const UINT num_vertices5 = ARRAY_SIZE(vertices5);
8487 const UINT num_faces5 = ARRAY_SIZE(vertices5) / VERTS_PER_FACE;
8488 const UINT vertex_size5 = sizeof(*vertices5);
8489 const struct vertex_ptc_float16_4 exp_vertices5[] =
8491 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00, 0, 0x3c00}}, /* {1.0f, 1.0f, 0.0f, 1.0f} */
8492 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a, 0, 0x3c00}}, /* {0.5f, 0.7f, 0.0f, 1.0f} */
8493 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd, 0, 0x3c00}}, /* {-0.2f, -0.3f, 0.0f, 1.0f} */
8495 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd, 0, 0x3c00}}, /* {0.2f, 0.3f, 0.0f, 1.0f} */
8496 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00, 0, 0x3c00}}, /* {1.0f, 1.0f, 0.0f, 1.0f} */
8497 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266, 0, 0x3c00}}, /* {0.1f, 0.2f, 0.0f, 1.0f} */
8499 const UINT exp_vertex_size5 = sizeof(*exp_vertices5);
8500 /* Test 6. Convert FLOAT2 to FLOAT1. */
8501 const struct vertex_ptc vertices6[] =
8503 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8504 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8505 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
8507 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8508 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
8509 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
8511 const UINT num_vertices6 = ARRAY_SIZE(vertices6);
8512 const UINT num_faces6 = ARRAY_SIZE(vertices6) / VERTS_PER_FACE;
8513 const UINT vertex_size6 = sizeof(*vertices6);
8514 const struct vertex_ptc_float1 exp_vertices6[] =
8516 {{ 0.0f, 3.0f, 0.f}, 1.0f},
8517 {{ 2.0f, 3.0f, 0.f}, 0.5f},
8518 {{ 0.0f, 0.0f, 0.f}, -0.2f},
8520 {{ 3.0f, 3.0f, 0.f}, 0.2f},
8521 {{ 3.0f, 0.0f, 0.f}, 1.0f},
8522 {{ 1.0f, 0.0f, 0.f}, 0.1f},
8524 const UINT exp_vertex_size6 = sizeof(*exp_vertices6);
8525 /* Test 7. Convert FLOAT2 to FLOAT3. */
8526 const struct vertex_ptc vertices7[] =
8528 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8529 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8530 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
8532 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8533 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
8534 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
8536 const UINT num_vertices7 = ARRAY_SIZE(vertices7);
8537 const UINT num_faces7 = ARRAY_SIZE(vertices7) / VERTS_PER_FACE;
8538 const UINT vertex_size7 = sizeof(*vertices7);
8539 const struct vertex_ptc_float3 exp_vertices7[] =
8541 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f, 0.0f}},
8542 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f, 0.0f}},
8543 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f, 0.0f}},
8545 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f, 0.0f}},
8546 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f, 0.0f}},
8547 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f, 0.0f}},
8549 const UINT exp_vertex_size7 = sizeof(*exp_vertices7);
8550 /* Test 8. Convert FLOAT2 to FLOAT4. */
8551 const struct vertex_ptc vertices8[] =
8553 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8554 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8555 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
8557 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8558 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
8559 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
8561 const UINT num_vertices8 = ARRAY_SIZE(vertices8);
8562 const UINT num_faces8 = ARRAY_SIZE(vertices8) / VERTS_PER_FACE;
8563 const UINT vertex_size8 = sizeof(*vertices8);
8564 const struct vertex_ptc_float4 exp_vertices8[] =
8566 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f, 0.0f, 1.0f}},
8567 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f, 0.0f, 1.0f}},
8568 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f, 0.0f, 1.0f}},
8570 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f, 0.0f, 1.0f}},
8571 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f, 0.0f, 1.0f}},
8572 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f, 0.0f, 1.0f}},
8574 const UINT exp_vertex_size8 = sizeof(*exp_vertices8);
8575 /* Test 9. Convert FLOAT2 to D3DCOLOR. */
8576 const struct vertex_ptc vertices9[] =
8578 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8579 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8580 {{ 0.0f, 0.0f, 0.f}, {-0.4f, -0.6f}},
8582 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8583 {{ 3.0f, 0.0f, 0.f}, { 2.0f, 256.0f}},
8584 {{ 1.0f, 0.0f, 0.f}, { 0.11f, 0.2f}},
8586 const UINT num_vertices9 = ARRAY_SIZE(vertices9);
8587 const UINT num_faces9 = ARRAY_SIZE(vertices9) / VERTS_PER_FACE;
8588 const UINT vertex_size9 = sizeof(*vertices9);
8589 const struct vertex_ptc_d3dcolor exp_vertices9[] =
8591 {{ 0.0f, 3.0f, 0.f}, {0, 255, 255, 255}},
8592 {{ 2.0f, 3.0f, 0.f}, {0, 179, 128, 255}},
8593 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 255}},
8595 {{ 3.0f, 3.0f, 0.f}, {0, 77, 51, 255}},
8596 {{ 3.0f, 0.0f, 0.f}, {0, 255, 255, 255}},
8597 {{ 1.0f, 0.0f, 0.f}, {0, 51, 28, 255}},
8599 const UINT exp_vertex_size9 = sizeof(*exp_vertices9);
8600 /* Test 10. Convert FLOAT2 to UBYTE4. */
8601 const struct vertex_ptc vertices10[] =
8603 {{ 0.0f, 3.0f, 0.f}, { 0.0f, 1.0f}},
8604 {{ 2.0f, 3.0f, 0.f}, { 2.0f, 3.0f}},
8605 {{ 0.0f, 0.0f, 0.f}, { 254.0f, 255.0f}},
8607 {{ 3.0f, 3.0f, 0.f}, { 256.0f, 257.0f}},
8608 {{ 3.0f, 0.0f, 0.f}, { 1.4f, 1.5f}},
8609 {{ 1.0f, 0.0f, 0.f}, {-4.0f, -5.0f}},
8611 const UINT num_vertices10 = ARRAY_SIZE(vertices10);
8612 const UINT num_faces10 = ARRAY_SIZE(vertices10) / VERTS_PER_FACE;
8613 const UINT vertex_size10 = sizeof(*vertices10);
8614 const struct vertex_ptc_ubyte4 exp_vertices10[] =
8616 {{ 0.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
8617 {{ 2.0f, 3.0f, 0.f}, {2, 3, 0, 1}},
8618 {{ 0.0f, 0.0f, 0.f}, {254, 255, 0, 1}},
8620 {{ 3.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
8621 {{ 3.0f, 0.0f, 0.f}, {1, 2, 0, 1}},
8622 {{ 1.0f, 0.0f, 0.f}, {0, 0, 0, 1}},
8624 const UINT exp_vertex_size10 = sizeof(*exp_vertices10);
8625 /* Test 11. Convert FLOAT2 to SHORT2. */
8626 const struct vertex_ptc vertices11[] =
8628 {{ 0.0f, 3.0f, 0.f}, { 1.0f, -1.0f}},
8629 {{ 2.0f, 3.0f, 0.f}, { 0.4f, 0.5f}},
8630 {{ 0.0f, 0.0f, 0.f}, {-0.5f, -5.0f}},
8632 {{ 3.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MIN}},
8633 {{ 3.0f, 0.0f, 0.f}, {SHRT_MAX + 1.0f, SHRT_MIN - 1.0f}},
8634 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX + 2.0f, SHRT_MIN - 2.0f}},
8636 {{ 4.0f, 3.0f, 0.f}, {2 * SHRT_MAX, 2 * SHRT_MIN}},
8637 {{ 6.0f, 0.0f, 0.f}, {3 * SHRT_MAX, 3 * SHRT_MIN}},
8638 {{ 4.0f, 0.0f, 0.f}, {4 * SHRT_MAX, 4 * SHRT_MIN}},
8640 const UINT num_vertices11 = ARRAY_SIZE(vertices11);
8641 const UINT num_faces11 = ARRAY_SIZE(vertices11) / VERTS_PER_FACE;
8642 const UINT vertex_size11 = sizeof(*vertices11);
8643 const struct vertex_ptc_short2 exp_vertices11[] =
8645 {{ 0.0f, 3.0f, 0.f}, {1, 0}},
8646 {{ 2.0f, 3.0f, 0.f}, {0, 1}},
8647 {{ 0.0f, 0.0f, 0.f}, {0, -4}},
8649 {{ 3.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MIN + 1}},
8650 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MIN}},
8651 {{ 1.0f, 0.0f, 0.f}, {SHRT_MIN + 1, SHRT_MAX}},
8653 {{ 4.0f, 3.0f, 0.f}, {-2, 1}},
8654 {{ 6.0f, 0.0f, 0.f}, {32765, -32767}},
8655 {{ 4.0f, 0.0f, 0.f}, {-4, 1}},
8657 const UINT exp_vertex_size11 = sizeof(*exp_vertices11);
8658 /* Test 12. Convert FLOAT2 to SHORT4. */
8659 const struct vertex_ptc vertices12[] =
8661 {{ 0.0f, 3.0f, 0.f}, { 1.0f, -1.0f}},
8662 {{ 2.0f, 3.0f, 0.f}, { 0.4f, 0.5f}},
8663 {{ 0.0f, 0.0f, 0.f}, {-0.5f, -5.0f}},
8665 {{ 3.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MIN}},
8666 {{ 3.0f, 0.0f, 0.f}, {SHRT_MAX + 1.0f, SHRT_MIN - 1.0f}},
8667 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX + 2.0f, SHRT_MIN - 2.0f}},
8669 {{ 4.0f, 3.0f, 0.f}, {2 * SHRT_MAX, 2 * SHRT_MIN}},
8670 {{ 6.0f, 0.0f, 0.f}, {3 * SHRT_MAX, 3 * SHRT_MIN}},
8671 {{ 4.0f, 0.0f, 0.f}, {4 * SHRT_MAX, 4 * SHRT_MIN}},
8673 const UINT num_vertices12 = ARRAY_SIZE(vertices12);
8674 const UINT num_faces12 = ARRAY_SIZE(vertices12) / VERTS_PER_FACE;
8675 const UINT vertex_size12 = sizeof(*vertices12);
8676 const struct vertex_ptc_short4 exp_vertices12[] =
8678 {{ 0.0f, 3.0f, 0.f}, {1, 0, 0, 1}},
8679 {{ 2.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
8680 {{ 0.0f, 0.0f, 0.f}, {0, -4, 0, 1}},
8682 {{ 3.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MIN + 1, 0, 1}},
8683 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MIN, 0, 1}},
8684 {{ 1.0f, 0.0f, 0.f}, {SHRT_MIN + 1, SHRT_MAX, 0, 1}},
8686 {{ 4.0f, 3.0f, 0.f}, {-2, 1, 0, 1}},
8687 {{ 6.0f, 0.0f, 0.f}, {32765, -32767, 0, 1}},
8688 {{ 4.0f, 0.0f, 0.f}, {-4, 1, 0, 1}},
8690 const UINT exp_vertex_size12 = sizeof(*exp_vertices12);
8691 /* Test 13. Convert FLOAT2 to UBYTE4N. */
8692 const struct vertex_ptc vertices13[] =
8694 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 2.0f}},
8695 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8696 {{ 0.0f, 0.0f, 0.f}, {-0.4f, -0.5f}},
8698 {{ 3.0f, 3.0f, 0.f}, {-0.6f, -1.0f}},
8699 {{ 3.0f, 0.0f, 0.f}, {UCHAR_MAX, UCHAR_MAX + 1}},
8700 {{ 1.0f, 0.0f, 0.f}, {2 * UCHAR_MAX, -UCHAR_MAX}},
8702 const UINT num_vertices13 = ARRAY_SIZE(vertices13);
8703 const UINT num_faces13 = ARRAY_SIZE(vertices13) / VERTS_PER_FACE;
8704 const UINT vertex_size13 = sizeof(*vertices13);
8705 const struct vertex_ptc_ubyte4n exp_vertices13[] =
8707 {{ 0.0f, 3.0f, 0.f}, {255, 255, 0, 255}},
8708 {{ 2.0f, 3.0f, 0.f}, {128, 179, 0, 255}},
8709 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 255}},
8711 {{ 3.0f, 3.0f, 0.f}, {0, 0, 0, 255}},
8712 {{ 3.0f, 0.0f, 0.f}, {255, 255, 0, 255}},
8713 {{ 1.0f, 0.0f, 0.f}, {255, 0, 0, 255}},
8715 const UINT exp_vertex_size13 = sizeof(*exp_vertices13);
8716 /* Test 14. Convert FLOAT2 to SHORT2N. */
8717 const struct vertex_ptc vertices14[] =
8719 {{ 0.0f, 3.0f, 0.f}, {1.0f, 2.0f}},
8720 {{ 2.0f, 3.0f, 0.f}, {0.4f, 0.5f}},
8721 {{ 0.0f, 0.0f, 0.f}, {0.6f, -1.0f}},
8723 {{ 3.0f, 3.0f, 0.f}, {-0.4f, -0.5f}},
8724 {{ 3.0f, 0.0f, 0.f}, {-0.9f, -0.99997}},
8725 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX, SHRT_MIN}},
8727 const UINT num_vertices14 = ARRAY_SIZE(vertices14);
8728 const UINT num_faces14 = ARRAY_SIZE(vertices14) / VERTS_PER_FACE;
8729 const UINT vertex_size14 = sizeof(*vertices14);
8730 const struct vertex_ptc_short2 exp_vertices14[] =
8732 {{ 0.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MAX}},
8733 {{ 2.0f, 3.0f, 0.f}, {13107, 16384}},
8734 {{ 0.0f, 0.0f, 0.f}, {19660, SHRT_MIN + 2}},
8736 {{ 3.0f, 3.0f, 0.f}, {-13106, -16383}},
8737 {{ 3.0f, 0.0f, 0.f}, {-29489, SHRT_MIN + 3}},
8738 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX, SHRT_MIN + 2}},
8740 const UINT exp_vertex_size14 = sizeof(*exp_vertices14);
8741 /* Test 15. Convert FLOAT2 to SHORT4N. */
8742 const struct vertex_ptc vertices15[] =
8744 {{ 0.0f, 3.0f, 0.f}, {1.0f, 2.0f}},
8745 {{ 2.0f, 3.0f, 0.f}, {0.4f, 0.5f}},
8746 {{ 0.0f, 0.0f, 0.f}, {0.6f, -1.0f}},
8748 {{ 3.0f, 3.0f, 0.f}, {-0.4f, -0.5f}},
8749 {{ 3.0f, 0.0f, 0.f}, {-0.9f, -0.99997}},
8750 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX, SHRT_MIN}},
8752 const UINT num_vertices15 = ARRAY_SIZE(vertices15);
8753 const UINT num_faces15 = ARRAY_SIZE(vertices15) / VERTS_PER_FACE;
8754 const UINT vertex_size15 = sizeof(*vertices15);
8755 const struct vertex_ptc_short4 exp_vertices15[] =
8757 {{ 0.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MAX, 0, SHRT_MAX}},
8758 {{ 2.0f, 3.0f, 0.f}, {13107, 16384, 0, SHRT_MAX}},
8759 {{ 0.0f, 0.0f, 0.f}, {19660, SHRT_MIN + 2, 0, SHRT_MAX}},
8761 {{ 3.0f, 3.0f, 0.f}, {-13106, -16383, 0, SHRT_MAX}},
8762 {{ 3.0f, 0.0f, 0.f}, {-29489, SHRT_MIN + 3, 0, SHRT_MAX}},
8763 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX, SHRT_MIN + 2, 0, SHRT_MAX}},
8765 const UINT exp_vertex_size15 = sizeof(*exp_vertices15);
8766 /* Test 16. Convert FLOAT2 to USHORT2N. */
8767 const struct vertex_ptc vertices16[] =
8769 {{ 0.0f, 3.0f, 0.f}, {1.0f, 2.0f}},
8770 {{ 2.0f, 3.0f, 0.f}, {0.4f, 0.5f}},
8771 {{ 0.0f, 0.0f, 0.f}, {0.6f, -1.0f}},
8773 {{ 3.0f, 3.0f, 0.f}, {-0.4f, -0.5f}},
8774 {{ 3.0f, 0.0f, 0.f}, {-0.9f, 0.99998f}},
8775 {{ 1.0f, 0.0f, 0.f}, {USHRT_MAX, 0.0f}},
8777 const UINT num_vertices16 = ARRAY_SIZE(vertices16);
8778 const UINT num_faces16 = ARRAY_SIZE(vertices16) / VERTS_PER_FACE;
8779 const UINT vertex_size16 = sizeof(*vertices16);
8780 const struct vertex_ptc_ushort2n exp_vertices16[] =
8782 {{ 0.0f, 3.0f, 0.f}, {USHRT_MAX, USHRT_MAX}},
8783 {{ 2.0f, 3.0f, 0.f}, {26214, 32768}},
8784 {{ 0.0f, 0.0f, 0.f}, {39321, 0}},
8786 {{ 3.0f, 3.0f, 0.f}, {0, 0}},
8787 {{ 3.0f, 0.0f, 0.f}, {0, USHRT_MAX - 1}},
8788 {{ 1.0f, 0.0f, 0.f}, {USHRT_MAX, 0}},
8790 const UINT exp_vertex_size16 = sizeof(*exp_vertices16);
8791 /* Test 17. Convert FLOAT2 to USHORT4N. */
8792 const struct vertex_ptc vertices17[] =
8794 {{ 0.0f, 3.0f, 0.f}, {1.0f, 2.0f}},
8795 {{ 2.0f, 3.0f, 0.f}, {0.4f, 0.5f}},
8796 {{ 0.0f, 0.0f, 0.f}, {0.6f, -1.0f}},
8798 {{ 3.0f, 3.0f, 0.f}, {-0.4f, -0.5f}},
8799 {{ 3.0f, 0.0f, 0.f}, {-0.9f, 0.99998f}},
8800 {{ 1.0f, 0.0f, 0.f}, {USHRT_MAX, 0.0f}},
8802 const UINT num_vertices17 = ARRAY_SIZE(vertices17);
8803 const UINT num_faces17 = ARRAY_SIZE(vertices17) / VERTS_PER_FACE;
8804 const UINT vertex_size17 = sizeof(*vertices17);
8805 const struct vertex_ptc_ushort4n exp_vertices17[] =
8807 {{ 0.0f, 3.0f, 0.f}, {USHRT_MAX, USHRT_MAX, 0, USHRT_MAX}},
8808 {{ 2.0f, 3.0f, 0.f}, {26214, 32768, 0, USHRT_MAX}},
8809 {{ 0.0f, 0.0f, 0.f}, {39321, 0, 0, USHRT_MAX}},
8811 {{ 3.0f, 3.0f, 0.f}, {0, 0, 0, USHRT_MAX}},
8812 {{ 3.0f, 0.0f, 0.f}, {0, USHRT_MAX - 1, 0, USHRT_MAX}},
8813 {{ 1.0f, 0.0f, 0.f}, {USHRT_MAX, 0, 0, USHRT_MAX}},
8815 const UINT exp_vertex_size17 = sizeof(*exp_vertices17);
8816 /* Test 18. Test that the method field is compared by converting a FLOAT2 to
8817 * FLOAT16_2. where the method field has been change from
8818 * D3DDECLMETHOD_DEFAULT to D3DDECLMETHOD_PARTIALU. */
8819 const struct vertex_ptc vertices18[] =
8821 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8822 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8823 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
8825 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8826 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
8827 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
8829 const UINT num_vertices18 = ARRAY_SIZE(vertices18);
8830 const UINT num_faces18 = ARRAY_SIZE(vertices18) / VERTS_PER_FACE;
8831 const UINT vertex_size18 = sizeof(*vertices18);
8832 const struct vertex_ptc_float16_2 exp_vertices18[] =
8834 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
8835 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */
8836 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */
8838 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd}}, /* {0.2f, 0.3f} */
8839 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
8840 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */
8842 const UINT exp_vertex_size18 = sizeof(*exp_vertices18);
8843 /* Test 19. Test that data is lost if usage index changes, e.g. TEXCOORD0
8844 * TEXCOORD1. */
8845 const struct vertex_pntc vertices19[] =
8847 {{ 0.0f, 3.0f, 0.f}, up, { 1.0f, 1.0f}},
8848 {{ 2.0f, 3.0f, 0.f}, up, { 0.5f, 0.7f}},
8849 {{ 0.0f, 0.0f, 0.f}, up, {-0.2f, -0.3f}},
8851 {{ 3.0f, 3.0f, 0.f}, up, { 0.2f, 0.3f}},
8852 {{ 3.0f, 0.0f, 0.f}, up, { 1.0f, 1.0f}},
8853 {{ 1.0f, 0.0f, 0.f}, up, { 0.1f, 0.2f}},
8855 const UINT num_vertices19 = ARRAY_SIZE(vertices19);
8856 const UINT num_faces19 = ARRAY_SIZE(vertices19) / VERTS_PER_FACE;
8857 const UINT vertex_size19 = sizeof(*vertices19);
8858 const struct vertex_pntc exp_vertices19[] =
8860 {{ 0.0f, 3.0f, 0.f}, up, zero_vec2},
8861 {{ 2.0f, 3.0f, 0.f}, up, zero_vec2},
8862 {{ 0.0f, 0.0f, 0.f}, up, zero_vec2},
8864 {{ 3.0f, 3.0f, 0.f}, up, zero_vec2},
8865 {{ 3.0f, 0.0f, 0.f}, up, zero_vec2},
8866 {{ 1.0f, 0.0f, 0.f}, up, zero_vec2},
8868 const UINT exp_vertex_size19 = sizeof(*exp_vertices19);
8869 /* Test 20. Another test that data is lost if usage index changes, e.g.
8870 * TEXCOORD1 to TEXCOORD0. */
8871 const struct vertex_pntc vertices20[] =
8873 {{ 0.0f, 3.0f, 0.f}, up, { 1.0f, 1.0f}},
8874 {{ 2.0f, 3.0f, 0.f}, up, { 0.5f, 0.7f}},
8875 {{ 0.0f, 0.0f, 0.f}, up, {-0.2f, -0.3f}},
8877 {{ 3.0f, 3.0f, 0.f}, up, { 0.2f, 0.3f}},
8878 {{ 3.0f, 0.0f, 0.f}, up, { 1.0f, 1.0f}},
8879 {{ 1.0f, 0.0f, 0.f}, up, { 0.1f, 0.2f}},
8881 const UINT num_vertices20 = ARRAY_SIZE(vertices20);
8882 const UINT num_faces20 = ARRAY_SIZE(vertices20) / VERTS_PER_FACE;
8883 const UINT vertex_size20 = sizeof(*vertices20);
8884 const struct vertex_pntc exp_vertices20[] =
8886 {{ 0.0f, 3.0f, 0.f}, up, zero_vec2},
8887 {{ 2.0f, 3.0f, 0.f}, up, zero_vec2},
8888 {{ 0.0f, 0.0f, 0.f}, up, zero_vec2},
8890 {{ 3.0f, 3.0f, 0.f}, up, zero_vec2},
8891 {{ 3.0f, 0.0f, 0.f}, up, zero_vec2},
8892 {{ 1.0f, 0.0f, 0.f}, up, zero_vec2},
8894 const UINT exp_vertex_size20 = sizeof(*exp_vertices20);
8895 /* Test 21. Convert FLOAT1 to FLOAT2. */
8896 const struct vertex_ptc_float1 vertices21[] =
8898 {{ 0.0f, 3.0f, 0.f}, 1.0f},
8899 {{ 2.0f, 3.0f, 0.f}, 0.5f},
8900 {{ 0.0f, 0.0f, 0.f}, -0.2f},
8902 {{ 3.0f, 3.0f, 0.f}, 0.2f},
8903 {{ 3.0f, 0.0f, 0.f}, 1.0f},
8904 {{ 1.0f, 0.0f, 0.f}, 0.1f},
8906 const UINT num_vertices21 = ARRAY_SIZE(vertices21);
8907 const UINT num_faces21 = ARRAY_SIZE(vertices21) / VERTS_PER_FACE;
8908 const UINT vertex_size21 = sizeof(*vertices21);
8909 const struct vertex_ptc exp_vertices21[] =
8911 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 0.0f}},
8912 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.0f}},
8913 {{ 0.0f, 0.0f, 0.f}, {-0.2f, 0.0f}},
8915 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.0f}},
8916 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 0.0f}},
8917 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.0f}},
8919 const UINT exp_vertex_size21 = sizeof(*exp_vertices21);
8920 /* Test 22. Convert FLOAT1 to FLOAT3. */
8921 const struct vertex_ptc_float1 vertices22[] =
8923 {{ 0.0f, 3.0f, 0.f}, 1.0f},
8924 {{ 2.0f, 3.0f, 0.f}, 0.5f},
8925 {{ 0.0f, 0.0f, 0.f}, -0.2f},
8927 {{ 3.0f, 3.0f, 0.f}, 0.2f},
8928 {{ 3.0f, 0.0f, 0.f}, 1.0f},
8929 {{ 1.0f, 0.0f, 0.f}, 0.1f},
8931 const UINT num_vertices22 = ARRAY_SIZE(vertices22);
8932 const UINT num_faces22 = ARRAY_SIZE(vertices22) / VERTS_PER_FACE;
8933 const UINT vertex_size22 = sizeof(*vertices22);
8934 const struct vertex_ptc_float3 exp_vertices22[] =
8936 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 0.0f, 0.0f}},
8937 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.0f, 0.0f}},
8938 {{ 0.0f, 0.0f, 0.f}, {-0.2f, 0.0f, 0.0f}},
8940 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.0f, 0.0f}},
8941 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 0.0f, 0.0f}},
8942 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.0f, 0.0f}},
8944 const UINT exp_vertex_size22 = sizeof(*exp_vertices22);
8945 /* Test 23. Convert FLOAT1 to FLOAT4. */
8946 const struct vertex_ptc_float1 vertices23[] =
8948 {{ 0.0f, 3.0f, 0.f}, 1.0f},
8949 {{ 2.0f, 3.0f, 0.f}, 0.5f},
8950 {{ 0.0f, 0.0f, 0.f}, -0.2f},
8952 {{ 3.0f, 3.0f, 0.f}, 0.2f},
8953 {{ 3.0f, 0.0f, 0.f}, 1.0f},
8954 {{ 1.0f, 0.0f, 0.f}, 0.1f},
8956 const UINT num_vertices23 = ARRAY_SIZE(vertices23);
8957 const UINT num_faces23 = ARRAY_SIZE(vertices23) / VERTS_PER_FACE;
8958 const UINT vertex_size23 = sizeof(*vertices23);
8959 const struct vertex_ptc_float4 exp_vertices23[] =
8961 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 0.0f, 0.0f, 1.0f}},
8962 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.0f, 0.0f, 1.0f}},
8963 {{ 0.0f, 0.0f, 0.f}, {-0.2f, 0.0f, 0.0f, 1.0f}},
8965 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.0f, 0.0f, 1.0f}},
8966 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 0.0f, 0.0f, 1.0f}},
8967 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.0f, 0.0f, 1.0f}},
8969 const UINT exp_vertex_size23 = sizeof(*exp_vertices23);
8970 /* Test 24. Convert FLOAT1 to D3DCOLOR. */
8971 const struct vertex_ptc_float1 vertices24[] =
8973 {{ 0.0f, 3.0f, 0.f}, 1.0f},
8974 {{ 2.0f, 3.0f, 0.f}, 0.5f},
8975 {{ 0.0f, 0.0f, 0.f}, -0.2f},
8977 {{ 3.0f, 3.0f, 0.f}, 0.2f},
8978 {{ 3.0f, 0.0f, 0.f}, 1.0f},
8979 {{ 1.0f, 0.0f, 0.f}, 0.11f},
8981 const UINT num_vertices24 = ARRAY_SIZE(vertices24);
8982 const UINT num_faces24 = ARRAY_SIZE(vertices24) / VERTS_PER_FACE;
8983 const UINT vertex_size24 = sizeof(*vertices24);
8984 const struct vertex_ptc_d3dcolor exp_vertices24[] =
8986 {{ 0.0f, 3.0f, 0.f}, {0, 0, 255, 255}},
8987 {{ 2.0f, 3.0f, 0.f}, {0, 0, 128, 255}},
8988 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 255}},
8990 {{ 3.0f, 3.0f, 0.f}, {0, 0, 51, 255}},
8991 {{ 3.0f, 0.0f, 0.f}, {0, 0, 255, 255}},
8992 {{ 1.0f, 0.0f, 0.f}, {0, 0, 28, 255}},
8994 const UINT exp_vertex_size24 = sizeof(*exp_vertices24);
8995 /* Test 25. Convert FLOAT1 to ubyte4. */
8996 const struct vertex_ptc_float1 vertices25[] =
8998 {{ 0.0f, 3.0f, 0.f}, 0.0f},
8999 {{ 2.0f, 3.0f, 0.f}, 1.4f},
9000 {{ 0.0f, 0.0f, 0.f}, 1.5f},
9002 {{ 3.0f, 3.0f, 0.f}, 255.0f},
9003 {{ 3.0f, 0.0f, 0.f}, 256.0f},
9004 {{ 1.0f, 0.0f, 0.f}, -1.0f},
9006 const UINT num_vertices25 = ARRAY_SIZE(vertices25);
9007 const UINT num_faces25 = ARRAY_SIZE(vertices25) / VERTS_PER_FACE;
9008 const UINT vertex_size25 = sizeof(*vertices25);
9009 const struct vertex_ptc_ubyte4 exp_vertices25[] =
9011 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 1}},
9012 {{ 2.0f, 3.0f, 0.f}, {1, 0, 0, 1}},
9013 {{ 0.0f, 0.0f, 0.f}, {2, 0, 0, 1}},
9015 {{ 3.0f, 3.0f, 0.f}, {255, 0, 0, 1}},
9016 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 1}},
9017 {{ 1.0f, 0.0f, 0.f}, {0, 0, 0, 1}},
9019 const UINT exp_vertex_size25 = sizeof(*exp_vertices25);
9020 /* Test 26. Convert FLOAT4 to D3DCOLOR. */
9021 const struct vertex_ptc_float4 vertices26[] =
9023 {{ 0.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.4f, 0.5f}},
9024 {{ 2.0f, 3.0f, 0.f}, {-0.4f, -0.5f, -1.0f, -2.0f}},
9025 {{ 0.0f, 0.0f, 0.f}, {254.0f, 255.0f, 256.0f, 257.0f}},
9027 {{ 3.0f, 3.0f, 0.f}, {0.1f, 0.2f, 0.3f, 0.4f}},
9028 {{ 3.0f, 0.0f, 0.f}, {0.5f, 0.6f, 0.7f, 0.8f}},
9029 {{ 1.0f, 0.0f, 0.f}, {0.9f, 0.99f, 0.995f, 0.999f}},
9031 const UINT num_vertices26 = ARRAY_SIZE(vertices26);
9032 const UINT num_faces26 = ARRAY_SIZE(vertices26) / VERTS_PER_FACE;
9033 const UINT vertex_size26 = sizeof(*vertices26);
9034 const struct vertex_ptc_d3dcolor exp_vertices26[] =
9036 {{ 0.0f, 3.0f, 0.f}, {102, 255, 0, 128}},
9037 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9038 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
9040 {{ 3.0f, 3.0f, 0.f}, {77, 51, 26, 102}},
9041 {{ 3.0f, 0.0f, 0.f}, {179, 153, 128, 204}},
9042 {{ 1.0f, 0.0f, 0.f}, {254, 252, 230, 255}},
9044 const UINT exp_vertex_size26 = sizeof(*exp_vertices26);
9045 /* Test 27. Convert D3DCOLOR to FLOAT4. */
9046 const struct vertex_ptc_d3dcolor vertices27[] =
9048 {{ 0.0f, 3.0f, 0.f}, {102, 255, 0, 128}},
9049 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9050 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
9052 {{ 3.0f, 3.0f, 0.f}, {77, 51, 26, 102}},
9053 {{ 3.0f, 0.0f, 0.f}, {179, 153, 128, 204}},
9054 {{ 1.0f, 0.0f, 0.f}, {254, 252, 230, 255}},
9056 const UINT num_vertices27 = ARRAY_SIZE(vertices27);
9057 const UINT num_faces27 = ARRAY_SIZE(vertices27) / VERTS_PER_FACE;
9058 const UINT vertex_size27 = sizeof(*vertices27);
9059 const struct vertex_ptc_float4 exp_vertices27[] =
9061 {{ 0.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.4f, 0.501961f}},
9062 {{ 2.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9063 {{ 0.0f, 0.0f, 0.f}, {1.0f, 1.0f, 1.0f, 1.0f}},
9065 {{ 3.0f, 3.0f, 0.f}, {0.101961f, 0.2f, 0.301961f, 0.4f}},
9066 {{ 3.0f, 0.0f, 0.f}, {0.501961f, 0.6f, 0.701961f, 0.8f}},
9067 {{ 1.0f, 0.0f, 0.f}, {0.901961f, 0.988235f, 0.996078f, 1.0f}},
9069 const UINT exp_vertex_size27 = sizeof(*exp_vertices27);
9070 /* Test 28. Convert UBYTE4 to FLOAT4. */
9071 const struct vertex_ptc_ubyte4 vertices28[] =
9073 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9074 {{ 2.0f, 3.0f, 0.f}, {1, 1, 1, 1}},
9075 {{ 0.0f, 0.0f, 0.f}, {1, 0, 1, 0}},
9077 {{ 3.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
9078 {{ 3.0f, 0.0f, 0.f}, {10, 20, 30, 40}},
9079 {{ 1.0f, 0.0f, 0.f}, {50, 60, 127, 255}},
9081 const UINT num_vertices28 = ARRAY_SIZE(vertices28);
9082 const UINT num_faces28 = ARRAY_SIZE(vertices28) / VERTS_PER_FACE;
9083 const UINT vertex_size28 = sizeof(*vertices28);
9084 const struct vertex_ptc_float4 exp_vertices28[] =
9086 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9087 {{ 2.0f, 3.0f, 0.f}, {1.0f, 1.0f, 1.0f, 1.0f}},
9088 {{ 0.0f, 0.0f, 0.f}, {1.0f, 0.0f, 1.0f, 0.0f}},
9090 {{ 3.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.0f, 1.0f}},
9091 {{ 3.0f, 0.0f, 0.f}, {10.0f, 20.0f, 30.0f, 40.0f}},
9092 {{ 1.0f, 0.0f, 0.f}, {50.0f, 60.0f, 127.0f, 255.0f}},
9094 const UINT exp_vertex_size28 = sizeof(*exp_vertices28);
9095 /* Test 29. Convert SHORT2 to FLOAT4. */
9096 const struct vertex_ptc_short2 vertices29[] =
9098 {{ 0.0f, 3.0f, 0.f}, {0, 0}},
9099 {{ 2.0f, 3.0f, 0.f}, {0, 1}},
9100 {{ 0.0f, 0.0f, 0.f}, {1, 0}},
9102 {{ 3.0f, 3.0f, 0.f}, {1, 1}},
9103 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MAX}},
9104 {{ 1.0f, 0.0f, 0.f}, {-42, 42}},
9106 const UINT num_vertices29 = ARRAY_SIZE(vertices29);
9107 const UINT num_faces29 = ARRAY_SIZE(vertices29) / VERTS_PER_FACE;
9108 const UINT vertex_size29 = sizeof(*vertices29);
9109 const struct vertex_ptc_float4 exp_vertices29[] =
9111 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 1.0f}},
9112 {{ 2.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.0f, 1.0f }},
9113 {{ 0.0f, 0.0f, 0.f}, {1.0f, 0.0f, 0.0f, 1.0f}},
9115 {{ 3.0f, 3.0f, 0.f}, {1.0f, 1.0f, 0.0f, 1.0f}},
9116 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MAX, 0.0f, 1.0f}},
9117 {{ 1.0f, 0.0f, 0.f}, {-42.0f, 42.0f, 0.0f, 1.0f}},
9119 const UINT exp_vertex_size29 = sizeof(*exp_vertices29);
9120 /* Test 29. Convert SHORT4 to FLOAT4. */
9121 const struct vertex_ptc_short4 vertices30[] =
9123 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9124 {{ 2.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
9125 {{ 0.0f, 0.0f, 0.f}, {1, 0, 1, 0}},
9127 {{ 3.0f, 3.0f, 0.f}, {1, 1, 1, 1}},
9128 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MAX, 1, 0}},
9129 {{ 1.0f, 0.0f, 0.f}, {-42, 42, SHRT_MAX, SHRT_MIN}},
9131 const UINT num_vertices30 = ARRAY_SIZE(vertices30);
9132 const UINT num_faces30 = ARRAY_SIZE(vertices30) / VERTS_PER_FACE;
9133 const UINT vertex_size30 = sizeof(*vertices30);
9134 const struct vertex_ptc_float4 exp_vertices30[] =
9136 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9137 {{ 2.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.0f, 1.0f }},
9138 {{ 0.0f, 0.0f, 0.f}, {1.0f, 0.0f, 1.0f, 0.0f}},
9140 {{ 3.0f, 3.0f, 0.f}, {1.0f, 1.0f, 1.0f, 1.0f}},
9141 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MAX, 1.0f, 0.0f}},
9142 {{ 1.0f, 0.0f, 0.f}, {-42.0f, 42.0f, SHRT_MAX, SHRT_MIN}},
9144 const UINT exp_vertex_size30 = sizeof(*exp_vertices30);
9145 /* Test 31. Convert UBYTE4N to FLOAT4. */
9146 const struct vertex_ptc_ubyte4n vertices31[] =
9148 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9149 {{ 2.0f, 3.0f, 0.f}, {1, 1, 1, 1}},
9150 {{ 0.0f, 0.0f, 0.f}, {1, 0, 1, 0}},
9152 {{ 3.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
9153 {{ 3.0f, 0.0f, 0.f}, {10, 20, 30, 40}},
9154 {{ 1.0f, 0.0f, 0.f}, {50, 60, 70, UCHAR_MAX}},
9156 const UINT num_vertices31 = ARRAY_SIZE(vertices31);
9157 const UINT num_faces31 = ARRAY_SIZE(vertices31) / VERTS_PER_FACE;
9158 const UINT vertex_size31 = sizeof(*vertices31);
9159 const struct vertex_ptc_float4 exp_vertices31[] =
9161 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9162 {{ 2.0f, 3.0f, 0.f}, {(FLOAT)1/UCHAR_MAX, (FLOAT)1/UCHAR_MAX, (FLOAT)1/UCHAR_MAX, (FLOAT)1/UCHAR_MAX}},
9163 {{ 0.0f, 0.0f, 0.f}, {(FLOAT)1/UCHAR_MAX, 0.0f, (FLOAT)1/UCHAR_MAX, 0.0f}},
9165 {{ 3.0f, 3.0f, 0.f}, {0.0f, (FLOAT)1/UCHAR_MAX, 0.0f, (FLOAT)1/UCHAR_MAX}},
9166 {{ 3.0f, 0.0f, 0.f}, {(FLOAT)10/UCHAR_MAX, (FLOAT)20/UCHAR_MAX, (FLOAT)30/UCHAR_MAX, (FLOAT)40/UCHAR_MAX}},
9167 {{ 1.0f, 0.0f, 0.f}, {(FLOAT)50/UCHAR_MAX, (FLOAT)60/UCHAR_MAX, (FLOAT)70/UCHAR_MAX, 1.0f}},
9169 const UINT exp_vertex_size31 = sizeof(*exp_vertices31);
9170 /* Test 32. Convert SHORT2N to FLOAT4. */
9171 const struct vertex_ptc_short2 vertices32[] =
9173 {{ 0.0f, 3.0f, 0.f}, {0, 0}},
9174 {{ 2.0f, 3.0f, 0.f}, {0, 1}},
9175 {{ 0.0f, 0.0f, 0.f}, {1, 0}},
9177 {{ 3.0f, 3.0f, 0.f}, {1, 1}},
9178 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN + 1, SHRT_MAX}},
9179 {{ 1.0f, 0.0f, 0.f}, {-42, 42}},
9181 const UINT num_vertices32 = ARRAY_SIZE(vertices32);
9182 const UINT num_faces32 = ARRAY_SIZE(vertices32) / VERTS_PER_FACE;
9183 const UINT vertex_size32 = sizeof(*vertices32);
9184 const struct vertex_ptc_float4 exp_vertices32[] =
9186 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 1.0f}},
9187 {{ 2.0f, 3.0f, 0.f}, {0.0f, 1.0f/SHRT_MAX, 0.0f, 1.0f}},
9188 {{ 0.0f, 0.0f, 0.f}, {1.0f/SHRT_MAX, 0.0f, 0.0f, 1.0f}},
9190 {{ 3.0f, 3.0f, 0.f}, {1.0f/SHRT_MAX, 1.0f/SHRT_MAX, 0.0f, 1.0f}},
9191 {{ 3.0f, 0.0f, 0.f}, {-1.0f, 1.0f, 0.0f, 1.0f}},
9192 {{ 1.0f, 0.0f, 0.f}, {-42.0f/SHRT_MAX, 42.0f/SHRT_MAX, 0.0f, 1.0f}},
9194 const UINT exp_vertex_size32 = sizeof(*exp_vertices32);
9195 /* Test 33. Convert SHORT4N to FLOAT4. */
9196 const struct vertex_ptc_short4 vertices33[] =
9198 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9199 {{ 2.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
9200 {{ 0.0f, 0.0f, 0.f}, {1, 0, 1, 0}},
9202 {{ 3.0f, 3.0f, 0.f}, {1, 1, 1, 1}},
9203 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN + 1, SHRT_MAX, SHRT_MIN + 1, SHRT_MAX}},
9204 {{ 1.0f, 0.0f, 0.f}, {-42, 42, 1, 1}},
9206 const UINT num_vertices33 = ARRAY_SIZE(vertices33);
9207 const UINT num_faces33 = ARRAY_SIZE(vertices33) / VERTS_PER_FACE;
9208 const UINT vertex_size33 = sizeof(*vertices33);
9209 const struct vertex_ptc_float4 exp_vertices33[] =
9211 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9212 {{ 2.0f, 3.0f, 0.f}, {0.0f, 1.0f/SHRT_MAX, 0.0f, 1.0f/SHRT_MAX}},
9213 {{ 0.0f, 0.0f, 0.f}, {1.0f/SHRT_MAX, 0.0f, 1.0f/SHRT_MAX, 0.0f}},
9215 {{ 3.0f, 3.0f, 0.f}, {1.0f/SHRT_MAX, 1.0f/SHRT_MAX, 1.0f/SHRT_MAX, 1.0f/SHRT_MAX}},
9216 {{ 3.0f, 0.0f, 0.f}, {-1.0f, 1.0f, -1.0f, 1.0f}},
9217 {{ 1.0f, 0.0f, 0.f}, {-42.0f/SHRT_MAX, 42.0f/SHRT_MAX, 1.0f/SHRT_MAX, 1.0f/SHRT_MAX}},
9219 const UINT exp_vertex_size33 = sizeof(*exp_vertices33);
9220 /* Test 34. Convert FLOAT16_2 to FLOAT4. */
9221 const struct vertex_ptc_float16_2 vertices34[] =
9223 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
9224 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */
9225 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */
9227 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd}}, /* {0.2f, 0.3f} */
9228 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
9229 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */
9231 const UINT num_vertices34 = ARRAY_SIZE(vertices34);
9232 const UINT num_faces34 = ARRAY_SIZE(vertices34) / VERTS_PER_FACE;
9233 const UINT vertex_size34 = sizeof(*vertices34);
9234 const struct vertex_ptc_float4 exp_vertices34[] =
9236 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f, 0.0f, 1.0f}},
9237 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.700195f, 0.0f, 1.0f}},
9238 {{ 0.0f, 0.0f, 0.f}, {-0.199951f, -0.300049f, 0.0f, 1.0f}},
9240 {{ 3.0f, 3.0f, 0.f}, {0.199951f, 0.300049f, 0.0f, 1.0f}},
9241 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f, 0.0f, 1.0f}},
9242 {{ 1.0f, 0.0f, 0.f}, {0.099976f, 0.199951f, 0.0f, 1.0f}},
9244 const UINT exp_vertex_size34 = sizeof(*exp_vertices34);
9245 /* Test 35. Convert FLOAT16_4 to FLOAT4. */
9246 const struct vertex_ptc_float16_4 vertices35[] =
9248 {{ 0.0f, 3.0f, 0.f}, {0x0000, 0x0000, 0x0000, 0x0000}},
9249 {{ 2.0f, 3.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}},
9250 {{ 0.0f, 0.0f, 0.f}, {0x3c00, 0x0000, 0x3c00, 0x0000}},
9252 {{ 3.0f, 3.0f, 0.f}, {0x0000, 0x3c00, 0x0000, 0x3c00}},
9253 {{ 3.0f, 0.0f, 0.f}, {0x3800, 0x399a, 0xb266, 0xb4cd}},
9254 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266, 0x2e66, 0x3266}},
9256 const UINT num_vertices35 = ARRAY_SIZE(vertices35);
9257 const UINT num_faces35 = ARRAY_SIZE(vertices35) / VERTS_PER_FACE;
9258 const UINT vertex_size35 = sizeof(*vertices35);
9259 const struct vertex_ptc_float4 exp_vertices35[] =
9261 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9262 {{ 2.0f, 3.0f, 0.f}, {1.0f, 1.0f, 1.0f, 1.0f}},
9263 {{ 0.0f, 0.0f, 0.f}, {1.0f, 0.0f, 1.0f, 0.0f}},
9265 {{ 3.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.0f, 1.0f}},
9266 {{ 3.0f, 0.0f, 0.f}, {0.5f, 0.700195f, -0.199951f, -0.300049f}},
9267 {{ 1.0f, 0.0f, 0.f}, {0.099976f, 0.199951f, 0.099976f, 0.199951f}},
9269 const UINT exp_vertex_size35 = sizeof(*exp_vertices35);
9270 /* Test 36. Check that vertex buffer sharing is ok. */
9271 const struct vertex_pn vertices36[] =
9273 {{ 0.0f, 3.0f, 0.f}, up},
9274 {{ 2.0f, 3.0f, 0.f}, up},
9275 {{ 0.0f, 0.0f, 0.f}, up},
9277 const UINT num_vertices36 = ARRAY_SIZE(vertices36);
9278 const UINT num_faces36 = ARRAY_SIZE(vertices36) / VERTS_PER_FACE;
9279 const UINT vertex_size36 = sizeof(*vertices36);
9280 const DWORD clone_options36 = options | D3DXMESH_VB_SHARE;
9281 /* Common mesh data */
9282 ID3DXMesh *mesh = NULL;
9283 ID3DXMesh *mesh_clone = NULL;
9284 struct
9286 const BYTE *vertices;
9287 const DWORD *indices;
9288 const DWORD *attributes;
9289 const UINT num_vertices;
9290 const UINT num_faces;
9291 const UINT vertex_size;
9292 const DWORD create_options;
9293 const DWORD clone_options;
9294 D3DVERTEXELEMENT9 *declaration;
9295 D3DVERTEXELEMENT9 *new_declaration;
9296 const BYTE *exp_vertices;
9297 const UINT exp_vertex_size;
9299 tc[] =
9302 (BYTE*)vertices0,
9303 NULL,
9304 NULL,
9305 num_vertices0,
9306 num_faces0,
9307 vertex_size0,
9308 options,
9309 options,
9310 declaration_pn,
9311 declaration_pn,
9312 (BYTE*)vertices0,
9313 vertex_size0
9316 (BYTE*)vertices0,
9317 NULL,
9318 NULL,
9319 num_vertices0,
9320 num_faces0,
9321 vertex_size0,
9322 options_16bit,
9323 options_16bit,
9324 declaration_pn,
9325 declaration_pn,
9326 (BYTE*)vertices0,
9327 vertex_size0
9330 (BYTE*)vertices0,
9331 NULL,
9332 NULL,
9333 num_vertices0,
9334 num_faces0,
9335 vertex_size0,
9336 options,
9337 options,
9338 declaration_pn,
9339 declaration_pntc,
9340 (BYTE*)exp_vertices2,
9341 exp_vertex_size2
9344 (BYTE*)vertices0,
9345 NULL,
9346 NULL,
9347 num_vertices0,
9348 num_faces0,
9349 vertex_size0,
9350 options,
9351 options,
9352 declaration_pn,
9353 declaration_ptcn,
9354 (BYTE*)exp_vertices3,
9355 exp_vertex_size3
9358 (BYTE*)vertices4,
9359 NULL,
9360 NULL,
9361 num_vertices4,
9362 num_faces4,
9363 vertex_size4,
9364 options,
9365 options,
9366 declaration_ptc,
9367 declaration_ptc_float16_2,
9368 (BYTE*)exp_vertices4,
9369 exp_vertex_size4
9372 (BYTE*)vertices5,
9373 NULL,
9374 NULL,
9375 num_vertices5,
9376 num_faces5,
9377 vertex_size5,
9378 options,
9379 options,
9380 declaration_ptc,
9381 declaration_ptc_float16_4,
9382 (BYTE*)exp_vertices5,
9383 exp_vertex_size5
9386 (BYTE*)vertices6,
9387 NULL,
9388 NULL,
9389 num_vertices6,
9390 num_faces6,
9391 vertex_size6,
9392 options,
9393 options,
9394 declaration_ptc,
9395 declaration_ptc_float1,
9396 (BYTE*)exp_vertices6,
9397 exp_vertex_size6
9400 (BYTE*)vertices7,
9401 NULL,
9402 NULL,
9403 num_vertices7,
9404 num_faces7,
9405 vertex_size7,
9406 options,
9407 options,
9408 declaration_ptc,
9409 declaration_ptc_float3,
9410 (BYTE*)exp_vertices7,
9411 exp_vertex_size7
9414 (BYTE*)vertices8,
9415 NULL,
9416 NULL,
9417 num_vertices8,
9418 num_faces8,
9419 vertex_size8,
9420 options,
9421 options,
9422 declaration_ptc,
9423 declaration_ptc_float4,
9424 (BYTE*)exp_vertices8,
9425 exp_vertex_size8
9428 (BYTE*)vertices9,
9429 NULL,
9430 NULL,
9431 num_vertices9,
9432 num_faces9,
9433 vertex_size9,
9434 options,
9435 options,
9436 declaration_ptc,
9437 declaration_ptc_d3dcolor,
9438 (BYTE*)exp_vertices9,
9439 exp_vertex_size9
9442 (BYTE*)vertices10,
9443 NULL,
9444 NULL,
9445 num_vertices10,
9446 num_faces10,
9447 vertex_size10,
9448 options,
9449 options,
9450 declaration_ptc,
9451 declaration_ptc_ubyte4,
9452 (BYTE*)exp_vertices10,
9453 exp_vertex_size10
9456 (BYTE*)vertices11,
9457 NULL,
9458 NULL,
9459 num_vertices11,
9460 num_faces11,
9461 vertex_size11,
9462 options,
9463 options,
9464 declaration_ptc,
9465 declaration_ptc_short2,
9466 (BYTE*)exp_vertices11,
9467 exp_vertex_size11
9470 (BYTE*)vertices12,
9471 NULL,
9472 NULL,
9473 num_vertices12,
9474 num_faces12,
9475 vertex_size12,
9476 options,
9477 options,
9478 declaration_ptc,
9479 declaration_ptc_short4,
9480 (BYTE*)exp_vertices12,
9481 exp_vertex_size12
9484 (BYTE*)vertices13,
9485 NULL,
9486 NULL,
9487 num_vertices13,
9488 num_faces13,
9489 vertex_size13,
9490 options,
9491 options,
9492 declaration_ptc,
9493 declaration_ptc_ubyte4n,
9494 (BYTE*)exp_vertices13,
9495 exp_vertex_size13
9498 (BYTE*)vertices14,
9499 NULL,
9500 NULL,
9501 num_vertices14,
9502 num_faces14,
9503 vertex_size14,
9504 options,
9505 options,
9506 declaration_ptc,
9507 declaration_ptc_short2n,
9508 (BYTE*)exp_vertices14,
9509 exp_vertex_size14
9512 (BYTE*)vertices15,
9513 NULL,
9514 NULL,
9515 num_vertices15,
9516 num_faces15,
9517 vertex_size15,
9518 options,
9519 options,
9520 declaration_ptc,
9521 declaration_ptc_short4n,
9522 (BYTE*)exp_vertices15,
9523 exp_vertex_size15
9526 (BYTE*)vertices16,
9527 NULL,
9528 NULL,
9529 num_vertices16,
9530 num_faces16,
9531 vertex_size16,
9532 options,
9533 options,
9534 declaration_ptc,
9535 declaration_ptc_ushort2n,
9536 (BYTE*)exp_vertices16,
9537 exp_vertex_size16
9540 (BYTE*)vertices17,
9541 NULL,
9542 NULL,
9543 num_vertices17,
9544 num_faces17,
9545 vertex_size17,
9546 options,
9547 options,
9548 declaration_ptc,
9549 declaration_ptc_ushort4n,
9550 (BYTE*)exp_vertices17,
9551 exp_vertex_size17
9554 (BYTE*)vertices18,
9555 NULL,
9556 NULL,
9557 num_vertices18,
9558 num_faces18,
9559 vertex_size18,
9560 options,
9561 options,
9562 declaration_ptc,
9563 declaration_ptc_float16_2_partialu,
9564 (BYTE*)exp_vertices18,
9565 exp_vertex_size18
9568 (BYTE*)vertices19,
9569 NULL,
9570 NULL,
9571 num_vertices19,
9572 num_faces19,
9573 vertex_size19,
9574 options,
9575 options,
9576 declaration_pntc,
9577 declaration_pntc1,
9578 (BYTE*)exp_vertices19,
9579 exp_vertex_size19
9582 (BYTE*)vertices20,
9583 NULL,
9584 NULL,
9585 num_vertices20,
9586 num_faces20,
9587 vertex_size20,
9588 options,
9589 options,
9590 declaration_pntc1,
9591 declaration_pntc,
9592 (BYTE*)exp_vertices20,
9593 exp_vertex_size20
9596 (BYTE*)vertices21,
9597 NULL,
9598 NULL,
9599 num_vertices21,
9600 num_faces21,
9601 vertex_size21,
9602 options,
9603 options,
9604 declaration_ptc_float1,
9605 declaration_ptc,
9606 (BYTE*)exp_vertices21,
9607 exp_vertex_size21
9610 (BYTE*)vertices22,
9611 NULL,
9612 NULL,
9613 num_vertices22,
9614 num_faces22,
9615 vertex_size22,
9616 options,
9617 options,
9618 declaration_ptc_float1,
9619 declaration_ptc_float3,
9620 (BYTE*)exp_vertices22,
9621 exp_vertex_size22
9624 (BYTE*)vertices23,
9625 NULL,
9626 NULL,
9627 num_vertices23,
9628 num_faces23,
9629 vertex_size23,
9630 options,
9631 options,
9632 declaration_ptc_float1,
9633 declaration_ptc_float4,
9634 (BYTE*)exp_vertices23,
9635 exp_vertex_size23
9638 (BYTE*)vertices24,
9639 NULL,
9640 NULL,
9641 num_vertices24,
9642 num_faces24,
9643 vertex_size24,
9644 options,
9645 options,
9646 declaration_ptc_float1,
9647 declaration_ptc_d3dcolor,
9648 (BYTE*)exp_vertices24,
9649 exp_vertex_size24
9652 (BYTE*)vertices25,
9653 NULL,
9654 NULL,
9655 num_vertices25,
9656 num_faces25,
9657 vertex_size25,
9658 options,
9659 options,
9660 declaration_ptc_float1,
9661 declaration_ptc_ubyte4,
9662 (BYTE*)exp_vertices25,
9663 exp_vertex_size25
9666 (BYTE*)vertices26,
9667 NULL,
9668 NULL,
9669 num_vertices26,
9670 num_faces26,
9671 vertex_size26,
9672 options,
9673 options,
9674 declaration_ptc_float4,
9675 declaration_ptc_d3dcolor,
9676 (BYTE*)exp_vertices26,
9677 exp_vertex_size26
9680 (BYTE*)vertices27,
9681 NULL,
9682 NULL,
9683 num_vertices27,
9684 num_faces27,
9685 vertex_size27,
9686 options,
9687 options,
9688 declaration_ptc_d3dcolor,
9689 declaration_ptc_float4,
9690 (BYTE*)exp_vertices27,
9691 exp_vertex_size27
9694 (BYTE*)vertices28,
9695 NULL,
9696 NULL,
9697 num_vertices28,
9698 num_faces28,
9699 vertex_size28,
9700 options,
9701 options,
9702 declaration_ptc_ubyte4,
9703 declaration_ptc_float4,
9704 (BYTE*)exp_vertices28,
9705 exp_vertex_size28
9708 (BYTE*)vertices29,
9709 NULL,
9710 NULL,
9711 num_vertices29,
9712 num_faces29,
9713 vertex_size29,
9714 options,
9715 options,
9716 declaration_ptc_short2,
9717 declaration_ptc_float4,
9718 (BYTE*)exp_vertices29,
9719 exp_vertex_size29
9722 (BYTE*)vertices30,
9723 NULL,
9724 NULL,
9725 num_vertices30,
9726 num_faces30,
9727 vertex_size30,
9728 options,
9729 options,
9730 declaration_ptc_short4,
9731 declaration_ptc_float4,
9732 (BYTE*)exp_vertices30,
9733 exp_vertex_size30
9736 (BYTE*)vertices31,
9737 NULL,
9738 NULL,
9739 num_vertices31,
9740 num_faces31,
9741 vertex_size31,
9742 options,
9743 options,
9744 declaration_ptc_ubyte4n,
9745 declaration_ptc_float4,
9746 (BYTE*)exp_vertices31,
9747 exp_vertex_size31
9750 (BYTE*)vertices32,
9751 NULL,
9752 NULL,
9753 num_vertices32,
9754 num_faces32,
9755 vertex_size32,
9756 options,
9757 options,
9758 declaration_ptc_short2n,
9759 declaration_ptc_float4,
9760 (BYTE*)exp_vertices32,
9761 exp_vertex_size32
9764 (BYTE*)vertices33,
9765 NULL,
9766 NULL,
9767 num_vertices33,
9768 num_faces33,
9769 vertex_size33,
9770 options,
9771 options,
9772 declaration_ptc_short4n,
9773 declaration_ptc_float4,
9774 (BYTE*)exp_vertices33,
9775 exp_vertex_size33
9778 (BYTE*)vertices34,
9779 NULL,
9780 NULL,
9781 num_vertices34,
9782 num_faces34,
9783 vertex_size34,
9784 options,
9785 options,
9786 declaration_ptc_float16_2,
9787 declaration_ptc_float4,
9788 (BYTE*)exp_vertices34,
9789 exp_vertex_size34
9792 (BYTE*)vertices35,
9793 NULL,
9794 NULL,
9795 num_vertices35,
9796 num_faces35,
9797 vertex_size35,
9798 options,
9799 options,
9800 declaration_ptc_float16_4,
9801 declaration_ptc_float4,
9802 (BYTE*)exp_vertices35,
9803 exp_vertex_size35
9806 (BYTE*)vertices36,
9807 NULL,
9808 NULL,
9809 num_vertices36,
9810 num_faces36,
9811 vertex_size36,
9812 options,
9813 clone_options36,
9814 declaration_pn,
9815 declaration_pn,
9816 (BYTE*)vertices36,
9817 vertex_size36
9821 test_context = new_test_context();
9822 if (!test_context)
9824 skip("Couldn't create test context\n");
9825 goto cleanup;
9828 for (i = 0; i < ARRAY_SIZE(tc); i++)
9830 UINT j;
9831 D3DVERTEXELEMENT9 new_declaration[MAX_FVF_DECL_SIZE];
9832 UINT exp_new_decl_length, new_decl_length;
9833 UINT exp_new_decl_size, new_decl_size;
9835 hr = init_test_mesh(tc[i].num_faces, tc[i].num_vertices,
9836 tc[i].create_options,
9837 tc[i].declaration,
9838 test_context->device, &mesh,
9839 tc[i].vertices, tc[i].vertex_size,
9840 tc[i].indices, tc[i].attributes);
9841 if (FAILED(hr))
9843 skip("Couldn't initialize test mesh %d. Got %x expected D3D_OK\n", i, hr);
9844 goto cleanup;
9847 hr = mesh->lpVtbl->CloneMesh(mesh, tc[i].clone_options, tc[i].new_declaration,
9848 test_context->device, &mesh_clone);
9849 ok(hr == D3D_OK, "CloneMesh test case %d failed. Got %x\n, expected D3D_OK\n", i, hr);
9851 hr = mesh_clone->lpVtbl->GetDeclaration(mesh_clone, new_declaration);
9852 ok(hr == D3D_OK, "GetDeclaration test case %d failed. Got %x\n, expected D3D_OK\n", i, hr);
9853 /* Check declaration elements */
9854 for (j = 0; tc[i].new_declaration[j].Stream != 0xFF; j++)
9856 ok(memcmp(&tc[i].new_declaration[j], &new_declaration[j], sizeof(*new_declaration)) == 0,
9857 "Test case %d failed. Declaration element %d did not match.\n", i, j);
9860 /* Check declaration length */
9861 exp_new_decl_length = D3DXGetDeclLength(tc[i].new_declaration);
9862 new_decl_length = D3DXGetDeclLength(new_declaration);
9863 ok(new_decl_length == exp_new_decl_length,
9864 "Test case %d failed. Got new declaration length %d, expected %d\n",
9865 i, new_decl_length, exp_new_decl_length);
9867 /* Check declaration size */
9868 exp_new_decl_size = D3DXGetDeclVertexSize(tc[i].new_declaration, 0);
9869 new_decl_size = D3DXGetDeclVertexSize(new_declaration, 0);
9870 ok(new_decl_size == exp_new_decl_size,
9871 "Test case %d failed. Got new declaration size %d, expected %d\n",
9872 i, new_decl_size, exp_new_decl_size);
9874 /* Check vertex data in cloned mesh */
9875 hr = mesh_clone->lpVtbl->LockVertexBuffer(mesh_clone, 0, (void**)&vertices);
9876 if (FAILED(hr))
9878 skip("Couldn't lock cloned vertex buffer.\n");
9879 goto cleanup;
9881 for (j = 0; j < tc[i].num_vertices; j++)
9883 UINT index = tc[i].exp_vertex_size * j;
9884 check_vertex_components(__LINE__, i, j, &vertices[index], &tc[i].exp_vertices[index], tc[i].new_declaration);
9886 hr = mesh_clone->lpVtbl->UnlockVertexBuffer(mesh_clone);
9887 if (FAILED(hr))
9889 skip("Couldn't unlock vertex buffer.\n");
9890 goto cleanup;
9892 vertices = NULL;
9893 mesh->lpVtbl->Release(mesh);
9894 mesh = NULL;
9895 mesh_clone->lpVtbl->Release(mesh_clone);
9896 mesh_clone = NULL;
9899 /* The following test shows that it is not possible to share a vertex buffer
9900 * with D3DXMESH_VB_SHARE and change the vertex declaration at the same
9901 * time. It reuses the test data from test 2.
9903 hr = init_test_mesh(tc[2].num_faces, tc[2].num_vertices,
9904 tc[2].create_options,
9905 tc[2].declaration,
9906 test_context->device, &mesh,
9907 tc[2].vertices, tc[2].vertex_size,
9908 tc[2].indices, tc[2].attributes);
9909 if (FAILED(hr))
9911 skip("Couldn't initialize test mesh for D3DXMESH_VB_SHARE case."
9912 " Got %x expected D3D_OK\n", hr);
9913 goto cleanup;
9916 hr = mesh->lpVtbl->CloneMesh(mesh, tc[2].create_options | D3DXMESH_VB_SHARE,
9917 tc[2].new_declaration, test_context->device,
9918 &mesh_clone);
9919 ok(hr == D3DERR_INVALIDCALL, "CloneMesh D3DXMESH_VB_SHARE with new"
9920 " declaration. Got %x, expected D3DERR_INVALIDCALL\n",
9921 hr);
9922 mesh->lpVtbl->Release(mesh);
9923 mesh = NULL;
9924 mesh_clone = NULL;
9926 cleanup:
9927 if (vertices) mesh->lpVtbl->UnlockVertexBuffer(mesh);
9928 if (mesh) mesh->lpVtbl->Release(mesh);
9929 if (mesh_clone) mesh_clone->lpVtbl->Release(mesh_clone);
9930 free_test_context(test_context);
9933 static void test_valid_mesh(void)
9935 HRESULT hr;
9936 struct test_context *test_context = NULL;
9937 UINT i;
9938 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
9939 const D3DVERTEXELEMENT9 declaration[] =
9941 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
9942 D3DDECL_END()
9944 const unsigned int VERTS_PER_FACE = 3;
9945 /* mesh0 (one face)
9947 * 0--1
9948 * | /
9949 * |/
9952 const D3DXVECTOR3 vertices0[] =
9954 { 0.0f, 3.0f, 0.f},
9955 { 2.0f, 3.0f, 0.f},
9956 { 0.0f, 0.0f, 0.f},
9958 const DWORD indices0[] = {0, 1, 2};
9959 const unsigned int num_vertices0 = ARRAY_SIZE(vertices0);
9960 const unsigned int num_faces0 = ARRAY_SIZE(indices0) / VERTS_PER_FACE;
9961 const DWORD adjacency0[] = {-1, -1, -1};
9962 const HRESULT exp_hr0 = D3D_OK;
9963 /* mesh1 (Simple bow-tie)
9965 * 0--1 1--3
9966 * | / \ |
9967 * |/ \|
9968 * 2 4
9970 const D3DXVECTOR3 vertices1[] =
9972 { 0.0f, 3.0f, 0.f},
9973 { 2.0f, 3.0f, 0.f},
9974 { 0.0f, 0.0f, 0.f},
9976 { 4.0f, 3.0f, 0.f},
9977 { 4.0f, 0.0f, 0.f},
9979 const DWORD indices1[] = {0, 1, 2, 1, 3, 4};
9980 const unsigned int num_vertices1 = ARRAY_SIZE(vertices1);
9981 const unsigned int num_faces1 = ARRAY_SIZE(indices1) / VERTS_PER_FACE;
9982 const DWORD adjacency1[] = {-1, -1, -1, -1, -1, -1};
9983 const HRESULT exp_hr1 = D3DXERR_INVALIDMESH;
9984 /* Common mesh data */
9985 ID3DXMesh *mesh = NULL;
9986 UINT vertex_size = sizeof(D3DXVECTOR3);
9987 ID3DXBuffer *errors_and_warnings = NULL;
9988 struct
9990 const D3DXVECTOR3 *vertices;
9991 const DWORD *indices;
9992 const UINT num_vertices;
9993 const UINT num_faces;
9994 const DWORD *adjacency;
9995 const HRESULT exp_hr;
9997 tc[] =
10000 vertices0,
10001 indices0,
10002 num_vertices0,
10003 num_faces0,
10004 adjacency0,
10005 exp_hr0,
10008 vertices1,
10009 indices1,
10010 num_vertices1,
10011 num_faces1,
10012 adjacency1,
10013 exp_hr1,
10017 test_context = new_test_context();
10018 if (!test_context)
10020 skip("Couldn't create test context\n");
10021 goto cleanup;
10024 for (i = 0; i < ARRAY_SIZE(tc); i++)
10026 hr = init_test_mesh(tc[i].num_faces, tc[i].num_vertices,
10027 options, declaration,
10028 test_context->device, &mesh,
10029 tc[i].vertices, vertex_size,
10030 tc[i].indices, NULL);
10031 if (FAILED(hr))
10033 skip("Couldn't initialize test mesh %d. Got %x expected D3D_OK\n", i, hr);
10034 goto cleanup;
10037 hr = D3DXValidMesh(mesh, tc[i].adjacency, &errors_and_warnings);
10038 todo_wine ok(hr == tc[i].exp_hr, "D3DXValidMesh test case %d failed. "
10039 "Got %x\n, expected %x\n", i, hr, tc[i].exp_hr);
10041 /* Note errors_and_warnings is deliberately not checked because that
10042 * would require copying wast amounts of the text output. */
10043 if (errors_and_warnings)
10045 ID3DXBuffer_Release(errors_and_warnings);
10046 errors_and_warnings = NULL;
10048 mesh->lpVtbl->Release(mesh);
10049 mesh = NULL;
10052 cleanup:
10053 if (mesh) mesh->lpVtbl->Release(mesh);
10054 free_test_context(test_context);
10057 START_TEST(mesh)
10059 D3DXBoundProbeTest();
10060 D3DXComputeBoundingBoxTest();
10061 D3DXComputeBoundingSphereTest();
10062 D3DXGetFVFVertexSizeTest();
10063 D3DXIntersectTriTest();
10064 D3DXCreateMeshTest();
10065 D3DXCreateMeshFVFTest();
10066 D3DXLoadMeshTest();
10067 D3DXCreateBoxTest();
10068 D3DXCreateSphereTest();
10069 D3DXCreateCylinderTest();
10070 D3DXCreateTextTest();
10071 test_get_decl_length();
10072 test_get_decl_vertex_size();
10073 test_fvf_decl_conversion();
10074 D3DXGenerateAdjacencyTest();
10075 test_update_semantics();
10076 test_create_skin_info();
10077 test_convert_adjacency_to_point_reps();
10078 test_convert_point_reps_to_adjacency();
10079 test_weld_vertices();
10080 test_clone_mesh();
10081 test_valid_mesh();