d3dx9: Implement D3DXCreateBox().
[wine/multimedia.git] / dlls / d3dx9_36 / tests / mesh.c
blobd32f1595de901f713082d23e062a9848b8c146da
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 #ifndef NAN
30 /* From wine/port.h */
31 static inline float __port_nan(void)
33 static const unsigned __nan_bytes = 0x7fc00000;
34 return *(const float *)&__nan_bytes;
36 #define NAN __port_nan()
37 #endif
39 /* Set the WINETEST_DEBUG environment variable to be greater than 1 for verbose
40 * function call traces of ID3DXAllocateHierarchy callbacks. */
41 #define TRACECALLBACK if(winetest_debug > 1) trace
43 #define admitted_error 0.0001f
45 #define ARRAY_SIZE(array) (sizeof(array)/sizeof(*array))
47 #define compare_vertex_sizes(type, exp) \
48 got=D3DXGetFVFVertexSize(type); \
49 ok(got==exp, "Expected: %d, Got: %d\n", exp, got);
51 #define compare_float(got, exp) \
52 do { \
53 float _got = (got); \
54 float _exp = (exp); \
55 ok(_got == _exp, "Expected: %g, Got: %g\n", _exp, _got); \
56 } while (0)
58 static BOOL compare(FLOAT u, FLOAT v)
60 return (fabs(u-v) < admitted_error);
63 static BOOL compare_vec3(D3DXVECTOR3 u, D3DXVECTOR3 v)
65 return ( compare(u.x, v.x) && compare(u.y, v.y) && compare(u.z, v.z) );
68 #define check_floats(got, exp, dim) check_floats_(__LINE__, "", got, exp, dim)
69 static void check_floats_(int line, const char *prefix, const float *got, const float *exp, int dim)
71 int i;
72 char exp_buffer[256] = "";
73 char got_buffer[256] = "";
74 char *exp_buffer_ptr = exp_buffer;
75 char *got_buffer_ptr = got_buffer;
76 BOOL equal = TRUE;
78 for (i = 0; i < dim; i++) {
79 if (i) {
80 exp_buffer_ptr += sprintf(exp_buffer_ptr, ", ");
81 got_buffer_ptr += sprintf(got_buffer_ptr, ", ");
83 equal = equal && compare(*exp, *got);
84 exp_buffer_ptr += sprintf(exp_buffer_ptr, "%g", *exp);
85 got_buffer_ptr += sprintf(got_buffer_ptr, "%g", *got);
86 exp++, got++;
88 ok_(__FILE__,line)(equal, "%sExpected (%s), got (%s)", prefix, exp_buffer, got_buffer);
91 struct vertex
93 D3DXVECTOR3 position;
94 D3DXVECTOR3 normal;
97 typedef WORD face[3];
99 static BOOL compare_face(face a, face b)
101 return (a[0]==b[0] && a[1] == b[1] && a[2] == b[2]);
104 struct test_context
106 HWND hwnd;
107 IDirect3D9 *d3d;
108 IDirect3DDevice9 *device;
111 /* Initializes a test context struct. Use it to initialize DirectX.
113 * Returns NULL if an error occurred.
115 static struct test_context *new_test_context(void)
117 HRESULT hr;
118 HWND hwnd = NULL;
119 IDirect3D9 *d3d = NULL;
120 IDirect3DDevice9 *device = NULL;
121 D3DPRESENT_PARAMETERS d3dpp = {0};
122 struct test_context *test_context;
124 if (!(hwnd = CreateWindowA("static", "d3dx9_test", WS_OVERLAPPEDWINDOW, 0, 0,
125 640, 480, NULL, NULL, NULL, NULL)))
127 skip("Couldn't create application window\n");
128 goto error;
131 d3d = Direct3DCreate9(D3D_SDK_VERSION);
132 if (!d3d)
134 skip("Couldn't create IDirect3D9 object\n");
135 goto error;
138 memset(&d3dpp, 0, sizeof(d3dpp));
139 d3dpp.Windowed = TRUE;
140 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
141 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
142 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device);
143 if (FAILED(hr))
145 skip("Couldn't create IDirect3DDevice9 object %#x\n", hr);
146 goto error;
149 test_context = HeapAlloc(GetProcessHeap(), 0, sizeof(*test_context));
150 if (!test_context)
152 skip("Couldn't allocate memory for test_context\n");
153 goto error;
155 test_context->hwnd = hwnd;
156 test_context->d3d = d3d;
157 test_context->device = device;
159 return test_context;
161 error:
162 if (device)
163 IDirect3DDevice9_Release(device);
165 if (d3d)
166 IDirect3D9_Release(d3d);
168 if (hwnd)
169 DestroyWindow(hwnd);
171 return NULL;
174 static void free_test_context(struct test_context *test_context)
176 if (!test_context)
177 return;
179 if (test_context->device)
180 IDirect3DDevice9_Release(test_context->device);
182 if (test_context->d3d)
183 IDirect3D9_Release(test_context->d3d);
185 if (test_context->hwnd)
186 DestroyWindow(test_context->hwnd);
188 HeapFree(GetProcessHeap(), 0, test_context);
191 struct mesh
193 DWORD number_of_vertices;
194 struct vertex *vertices;
196 DWORD number_of_faces;
197 face *faces;
199 DWORD fvf;
200 UINT vertex_size;
203 static void free_mesh(struct mesh *mesh)
205 HeapFree(GetProcessHeap(), 0, mesh->faces);
206 HeapFree(GetProcessHeap(), 0, mesh->vertices);
209 static BOOL new_mesh(struct mesh *mesh, DWORD number_of_vertices, DWORD number_of_faces)
211 mesh->vertices = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, number_of_vertices * sizeof(*mesh->vertices));
212 if (!mesh->vertices)
214 return FALSE;
216 mesh->number_of_vertices = number_of_vertices;
218 mesh->faces = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, number_of_faces * sizeof(*mesh->faces));
219 if (!mesh->faces)
221 HeapFree(GetProcessHeap(), 0, mesh->vertices);
222 return FALSE;
224 mesh->number_of_faces = number_of_faces;
226 return TRUE;
229 static void compare_mesh(const char *name, ID3DXMesh *d3dxmesh, struct mesh *mesh)
231 HRESULT hr;
232 DWORD number_of_vertices, number_of_faces;
233 IDirect3DVertexBuffer9 *vertex_buffer;
234 IDirect3DIndexBuffer9 *index_buffer;
235 D3DVERTEXBUFFER_DESC vertex_buffer_description;
236 D3DINDEXBUFFER_DESC index_buffer_description;
237 struct vertex *vertices;
238 face *faces;
239 int expected, i;
241 number_of_vertices = d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh);
242 ok(number_of_vertices == mesh->number_of_vertices, "Test %s, result %u, expected %d\n",
243 name, number_of_vertices, mesh->number_of_vertices);
245 number_of_faces = d3dxmesh->lpVtbl->GetNumFaces(d3dxmesh);
246 ok(number_of_faces == mesh->number_of_faces, "Test %s, result %u, expected %d\n",
247 name, number_of_faces, mesh->number_of_faces);
249 /* vertex buffer */
250 hr = d3dxmesh->lpVtbl->GetVertexBuffer(d3dxmesh, &vertex_buffer);
251 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
253 if (hr != D3D_OK)
255 skip("Couldn't get vertex buffer\n");
257 else
259 hr = IDirect3DVertexBuffer9_GetDesc(vertex_buffer, &vertex_buffer_description);
260 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
262 if (hr != D3D_OK)
264 skip("Couldn't get vertex buffer description\n");
266 else
268 ok(vertex_buffer_description.Format == D3DFMT_VERTEXDATA, "Test %s, result %x, expected %x (D3DFMT_VERTEXDATA)\n",
269 name, vertex_buffer_description.Format, D3DFMT_VERTEXDATA);
270 ok(vertex_buffer_description.Type == D3DRTYPE_VERTEXBUFFER, "Test %s, result %x, expected %x (D3DRTYPE_VERTEXBUFFER)\n",
271 name, vertex_buffer_description.Type, D3DRTYPE_VERTEXBUFFER);
272 ok(vertex_buffer_description.Usage == 0, "Test %s, result %x, expected %x\n", name, vertex_buffer_description.Usage, 0);
273 ok(vertex_buffer_description.Pool == D3DPOOL_MANAGED, "Test %s, result %x, expected %x (D3DPOOL_MANAGED)\n",
274 name, vertex_buffer_description.Pool, D3DPOOL_MANAGED);
275 ok(vertex_buffer_description.FVF == mesh->fvf, "Test %s, result %x, expected %x\n",
276 name, vertex_buffer_description.FVF, mesh->fvf);
277 if (mesh->fvf == 0)
279 expected = number_of_vertices * mesh->vertex_size;
281 else
283 expected = number_of_vertices * D3DXGetFVFVertexSize(mesh->fvf);
285 ok(vertex_buffer_description.Size == expected, "Test %s, result %x, expected %x\n",
286 name, vertex_buffer_description.Size, expected);
289 /* specify offset and size to avoid potential overruns */
290 hr = IDirect3DVertexBuffer9_Lock(vertex_buffer, 0, number_of_vertices * sizeof(D3DXVECTOR3) * 2,
291 (void **)&vertices, D3DLOCK_DISCARD);
292 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
294 if (hr != D3D_OK)
296 skip("Couldn't lock vertex buffer\n");
298 else
300 for (i = 0; i < number_of_vertices; i++)
302 ok(compare_vec3(vertices[i].position, mesh->vertices[i].position),
303 "Test %s, vertex position %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i,
304 vertices[i].position.x, vertices[i].position.y, vertices[i].position.z,
305 mesh->vertices[i].position.x, mesh->vertices[i].position.y, mesh->vertices[i].position.z);
306 ok(compare_vec3(vertices[i].normal, mesh->vertices[i].normal),
307 "Test %s, vertex normal %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i,
308 vertices[i].normal.x, vertices[i].normal.y, vertices[i].normal.z,
309 mesh->vertices[i].normal.x, mesh->vertices[i].normal.y, mesh->vertices[i].normal.z);
312 IDirect3DVertexBuffer9_Unlock(vertex_buffer);
315 IDirect3DVertexBuffer9_Release(vertex_buffer);
318 /* index buffer */
319 hr = d3dxmesh->lpVtbl->GetIndexBuffer(d3dxmesh, &index_buffer);
320 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
322 if (!index_buffer)
324 skip("Couldn't get index buffer\n");
326 else
328 hr = IDirect3DIndexBuffer9_GetDesc(index_buffer, &index_buffer_description);
329 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
331 if (hr != D3D_OK)
333 skip("Couldn't get index buffer description\n");
335 else
337 ok(index_buffer_description.Format == D3DFMT_INDEX16, "Test %s, result %x, expected %x (D3DFMT_INDEX16)\n",
338 name, index_buffer_description.Format, D3DFMT_INDEX16);
339 ok(index_buffer_description.Type == D3DRTYPE_INDEXBUFFER, "Test %s, result %x, expected %x (D3DRTYPE_INDEXBUFFER)\n",
340 name, index_buffer_description.Type, D3DRTYPE_INDEXBUFFER);
341 ok(index_buffer_description.Usage == 0, "Test %s, result %#x, expected %#x.\n",
342 name, index_buffer_description.Usage, 0);
343 ok(index_buffer_description.Pool == D3DPOOL_MANAGED, "Test %s, result %x, expected %x (D3DPOOL_MANAGED)\n",
344 name, index_buffer_description.Pool, D3DPOOL_MANAGED);
345 expected = number_of_faces * sizeof(WORD) * 3;
346 ok(index_buffer_description.Size == expected, "Test %s, result %x, expected %x\n",
347 name, index_buffer_description.Size, expected);
350 /* specify offset and size to avoid potential overruns */
351 hr = IDirect3DIndexBuffer9_Lock(index_buffer, 0, number_of_faces * sizeof(WORD) * 3,
352 (void **)&faces, D3DLOCK_DISCARD);
353 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
355 if (hr != D3D_OK)
357 skip("Couldn't lock index buffer\n");
359 else
361 for (i = 0; i < number_of_faces; i++)
363 ok(compare_face(faces[i], mesh->faces[i]),
364 "Test %s, face %d, result (%u, %u, %u), expected (%u, %u, %u)\n", name, i,
365 faces[i][0], faces[i][1], faces[i][2],
366 mesh->faces[i][0], mesh->faces[i][1], mesh->faces[i][2]);
369 IDirect3DIndexBuffer9_Unlock(index_buffer);
372 IDirect3DIndexBuffer9_Release(index_buffer);
376 static void D3DXBoundProbeTest(void)
378 BOOL result;
379 D3DXVECTOR3 bottom_point, center, top_point, raydirection, rayposition;
380 FLOAT radius;
382 /*____________Test the Box case___________________________*/
383 bottom_point.x = -3.0f; bottom_point.y = -2.0f; bottom_point.z = -1.0f;
384 top_point.x = 7.0f; top_point.y = 8.0f; top_point.z = 9.0f;
386 raydirection.x = -4.0f; raydirection.y = -5.0f; raydirection.z = -6.0f;
387 rayposition.x = 5.0f; rayposition.y = 5.0f; rayposition.z = 11.0f;
388 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection);
389 ok(result == TRUE, "expected TRUE, received FALSE\n");
391 raydirection.x = 4.0f; raydirection.y = 5.0f; raydirection.z = 6.0f;
392 rayposition.x = 5.0f; rayposition.y = 5.0f; rayposition.z = 11.0f;
393 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection);
394 ok(result == FALSE, "expected FALSE, received TRUE\n");
396 rayposition.x = -4.0f; rayposition.y = 1.0f; rayposition.z = -2.0f;
397 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection);
398 ok(result == TRUE, "expected TRUE, received FALSE\n");
400 bottom_point.x = 1.0f; bottom_point.y = 0.0f; bottom_point.z = 0.0f;
401 top_point.x = 1.0f; top_point.y = 0.0f; top_point.z = 0.0f;
402 rayposition.x = 0.0f; rayposition.y = 1.0f; rayposition.z = 0.0f;
403 raydirection.x = 0.0f; raydirection.y = 3.0f; raydirection.z = 0.0f;
404 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection);
405 ok(result == FALSE, "expected FALSE, received TRUE\n");
407 bottom_point.x = 1.0f; bottom_point.y = 2.0f; bottom_point.z = 3.0f;
408 top_point.x = 10.0f; top_point.y = 15.0f; top_point.z = 20.0f;
410 raydirection.x = 7.0f; raydirection.y = 8.0f; raydirection.z = 9.0f;
411 rayposition.x = 3.0f; rayposition.y = 7.0f; rayposition.z = -6.0f;
412 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection);
413 ok(result == TRUE, "expected TRUE, received FALSE\n");
415 bottom_point.x = 0.0f; bottom_point.y = 0.0f; bottom_point.z = 0.0f;
416 top_point.x = 1.0f; top_point.y = 1.0f; top_point.z = 1.0f;
418 raydirection.x = 0.0f; raydirection.y = 1.0f; raydirection.z = .0f;
419 rayposition.x = -3.0f; rayposition.y = 0.0f; rayposition.z = 0.0f;
420 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection);
421 ok(result == FALSE, "expected FALSE, received TRUE\n");
423 raydirection.x = 1.0f; raydirection.y = 0.0f; raydirection.z = .0f;
424 rayposition.x = -3.0f; rayposition.y = 0.0f; rayposition.z = 0.0f;
425 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection);
426 ok(result == TRUE, "expected TRUE, received FALSE\n");
428 /*____________Test the Sphere case________________________*/
429 radius = sqrt(77.0f);
430 center.x = 1.0f; center.y = 2.0f; center.z = 3.0f;
431 raydirection.x = 2.0f; raydirection.y = -4.0f; raydirection.z = 2.0f;
433 rayposition.x = 5.0f; rayposition.y = 5.0f; rayposition.z = 9.0f;
434 result = D3DXSphereBoundProbe(&center, radius, &rayposition, &raydirection);
435 ok(result == TRUE, "expected TRUE, received FALSE\n");
437 rayposition.x = 45.0f; rayposition.y = -75.0f; rayposition.z = 49.0f;
438 result = D3DXSphereBoundProbe(&center, radius, &rayposition, &raydirection);
439 ok(result == FALSE, "expected FALSE, received TRUE\n");
441 rayposition.x = 5.0f; rayposition.y = 11.0f; rayposition.z = 9.0f;
442 result = D3DXSphereBoundProbe(&center, radius, &rayposition, &raydirection);
443 ok(result == FALSE, "expected FALSE, received TRUE\n");
446 static void D3DXComputeBoundingBoxTest(void)
448 D3DXVECTOR3 exp_max, exp_min, got_max, got_min, vertex[5];
449 HRESULT hr;
451 vertex[0].x = 1.0f; vertex[0].y = 1.0f; vertex[0].z = 1.0f;
452 vertex[1].x = 1.0f; vertex[1].y = 1.0f; vertex[1].z = 1.0f;
453 vertex[2].x = 1.0f; vertex[2].y = 1.0f; vertex[2].z = 1.0f;
454 vertex[3].x = 1.0f; vertex[3].y = 1.0f; vertex[3].z = 1.0f;
455 vertex[4].x = 9.0f; vertex[4].y = 9.0f; vertex[4].z = 9.0f;
457 exp_min.x = 1.0f; exp_min.y = 1.0f; exp_min.z = 1.0f;
458 exp_max.x = 9.0f; exp_max.y = 9.0f; exp_max.z = 9.0f;
460 hr = D3DXComputeBoundingBox(&vertex[3],2,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_min,&got_max);
462 ok( hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
463 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);
464 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);
466 /*________________________*/
468 vertex[0].x = 2.0f; vertex[0].y = 5.9f; vertex[0].z = -1.2f;
469 vertex[1].x = -1.87f; vertex[1].y = 7.9f; vertex[1].z = 7.4f;
470 vertex[2].x = 7.43f; vertex[2].y = -0.9f; vertex[2].z = 11.9f;
471 vertex[3].x = -6.92f; vertex[3].y = 6.3f; vertex[3].z = -3.8f;
472 vertex[4].x = 11.4f; vertex[4].y = -8.1f; vertex[4].z = 4.5f;
474 exp_min.x = -6.92f; exp_min.y = -8.1f; exp_min.z = -3.80f;
475 exp_max.x = 11.4f; exp_max.y = 7.90f; exp_max.z = 11.9f;
477 hr = D3DXComputeBoundingBox(&vertex[0],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_min,&got_max);
479 ok( hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
480 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);
481 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);
483 /*________________________*/
485 vertex[0].x = 2.0f; vertex[0].y = 5.9f; vertex[0].z = -1.2f;
486 vertex[1].x = -1.87f; vertex[1].y = 7.9f; vertex[1].z = 7.4f;
487 vertex[2].x = 7.43f; vertex[2].y = -0.9f; vertex[2].z = 11.9f;
488 vertex[3].x = -6.92f; vertex[3].y = 6.3f; vertex[3].z = -3.8f;
489 vertex[4].x = 11.4f; vertex[4].y = -8.1f; vertex[4].z = 4.5f;
491 exp_min.x = -6.92f; exp_min.y = -0.9f; exp_min.z = -3.8f;
492 exp_max.x = 7.43f; exp_max.y = 7.90f; exp_max.z = 11.9f;
494 hr = D3DXComputeBoundingBox(&vertex[0],4,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_min,&got_max);
496 ok( hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
497 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);
498 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);
500 /*________________________*/
501 hr = D3DXComputeBoundingBox(NULL,5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_min,&got_max);
502 ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
504 /*________________________*/
505 hr = D3DXComputeBoundingBox(&vertex[3],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),NULL,&got_max);
506 ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
508 /*________________________*/
509 hr = D3DXComputeBoundingBox(&vertex[3],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_min,NULL);
510 ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
513 static void D3DXComputeBoundingSphereTest(void)
515 D3DXVECTOR3 exp_cen, got_cen, vertex[5];
516 FLOAT exp_rad, got_rad;
517 HRESULT hr;
519 vertex[0].x = 1.0f; vertex[0].y = 1.0f; vertex[0].z = 1.0f;
520 vertex[1].x = 1.0f; vertex[1].y = 1.0f; vertex[1].z = 1.0f;
521 vertex[2].x = 1.0f; vertex[2].y = 1.0f; vertex[2].z = 1.0f;
522 vertex[3].x = 1.0f; vertex[3].y = 1.0f; vertex[3].z = 1.0f;
523 vertex[4].x = 9.0f; vertex[4].y = 9.0f; vertex[4].z = 9.0f;
525 exp_rad = 6.928203f;
526 exp_cen.x = 5.0; exp_cen.y = 5.0; exp_cen.z = 5.0;
528 hr = D3DXComputeBoundingSphere(&vertex[3],2,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_cen,&got_rad);
530 ok( hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
531 ok( compare(exp_rad, got_rad), "Expected radius: %f, got radius: %f\n", exp_rad, got_rad);
532 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);
534 /*________________________*/
536 vertex[0].x = 2.0f; vertex[0].y = 5.9f; vertex[0].z = -1.2f;
537 vertex[1].x = -1.87f; vertex[1].y = 7.9f; vertex[1].z = 7.4f;
538 vertex[2].x = 7.43f; vertex[2].y = -0.9f; vertex[2].z = 11.9f;
539 vertex[3].x = -6.92f; vertex[3].y = 6.3f; vertex[3].z = -3.8f;
540 vertex[4].x = 11.4f; vertex[4].y = -8.1f; vertex[4].z = 4.5f;
542 exp_rad = 13.707883f;
543 exp_cen.x = 2.408f; exp_cen.y = 2.22f; exp_cen.z = 3.76f;
545 hr = D3DXComputeBoundingSphere(&vertex[0],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_cen,&got_rad);
547 ok( hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
548 ok( compare(exp_rad, got_rad), "Expected radius: %f, got radius: %f\n", exp_rad, got_rad);
549 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);
551 /*________________________*/
552 hr = D3DXComputeBoundingSphere(NULL,5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_cen,&got_rad);
553 ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
555 /*________________________*/
556 hr = D3DXComputeBoundingSphere(&vertex[3],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),NULL,&got_rad);
557 ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
559 /*________________________*/
560 hr = D3DXComputeBoundingSphere(&vertex[3],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_cen,NULL);
561 ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
564 static void print_elements(const D3DVERTEXELEMENT9 *elements)
566 D3DVERTEXELEMENT9 last = D3DDECL_END();
567 const D3DVERTEXELEMENT9 *ptr = elements;
568 int count = 0;
570 while (memcmp(ptr, &last, sizeof(D3DVERTEXELEMENT9)))
572 trace(
573 "[Element %d] Stream = %d, Offset = %d, Type = %d, Method = %d, Usage = %d, UsageIndex = %d\n",
574 count, ptr->Stream, ptr->Offset, ptr->Type, ptr->Method, ptr->Usage, ptr->UsageIndex);
575 ptr++;
576 count++;
580 static void compare_elements(const D3DVERTEXELEMENT9 *elements, const D3DVERTEXELEMENT9 *expected_elements,
581 unsigned int line, unsigned int test_id)
583 D3DVERTEXELEMENT9 last = D3DDECL_END();
584 unsigned int i;
586 for (i = 0; i < MAX_FVF_DECL_SIZE; i++)
588 int end1 = memcmp(&elements[i], &last, sizeof(last));
589 int end2 = memcmp(&expected_elements[i], &last, sizeof(last));
590 int status;
592 if (!end1 && !end2) break;
594 status = !end1 ^ !end2;
595 ok(!status, "Line %u, test %u: Mismatch in size, test declaration is %s than expected.\n",
596 line, test_id, end1 ? "shorter" : "longer");
597 if (status)
599 print_elements(elements);
600 break;
603 status = memcmp(&elements[i], &expected_elements[i], sizeof(D3DVERTEXELEMENT9));
604 ok(!status, "Line %u, test %u: Mismatch in element %u.\n", line, test_id, i);
605 if (status)
607 print_elements(elements);
608 break;
613 static void test_fvf_to_decl(DWORD test_fvf, const D3DVERTEXELEMENT9 expected_elements[],
614 HRESULT expected_hr, unsigned int line, unsigned int test_id)
616 HRESULT hr;
617 D3DVERTEXELEMENT9 decl[MAX_FVF_DECL_SIZE];
619 hr = D3DXDeclaratorFromFVF(test_fvf, decl);
620 ok(hr == expected_hr,
621 "Line %u, test %u: D3DXDeclaratorFromFVF returned %#x, expected %#x.\n",
622 line, test_id, hr, expected_hr);
623 if (SUCCEEDED(hr)) compare_elements(decl, expected_elements, line, test_id);
626 static void test_decl_to_fvf(const D3DVERTEXELEMENT9 *decl, DWORD expected_fvf,
627 HRESULT expected_hr, unsigned int line, unsigned int test_id)
629 HRESULT hr;
630 DWORD result_fvf = 0xdeadbeef;
632 hr = D3DXFVFFromDeclarator(decl, &result_fvf);
633 ok(hr == expected_hr,
634 "Line %u, test %u: D3DXFVFFromDeclarator returned %#x, expected %#x.\n",
635 line, test_id, hr, expected_hr);
636 if (SUCCEEDED(hr))
638 ok(expected_fvf == result_fvf, "Line %u, test %u: Got FVF %#x, expected %#x.\n",
639 line, test_id, result_fvf, expected_fvf);
643 static void test_fvf_decl_conversion(void)
645 static const struct
647 D3DVERTEXELEMENT9 decl[MAXD3DDECLLENGTH + 1];
648 DWORD fvf;
650 test_data[] =
653 D3DDECL_END(),
654 }, 0},
656 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
657 D3DDECL_END(),
658 }, D3DFVF_XYZ},
660 {0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITIONT, 0},
661 D3DDECL_END(),
662 }, D3DFVF_XYZRHW},
664 {0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITIONT, 0},
665 D3DDECL_END(),
666 }, D3DFVF_XYZRHW},
668 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
669 {0, 12, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
670 D3DDECL_END(),
671 }, D3DFVF_XYZB1},
673 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
674 {0, 12, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
675 D3DDECL_END(),
676 }, D3DFVF_XYZB1 | D3DFVF_LASTBETA_UBYTE4},
678 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
679 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
680 D3DDECL_END(),
681 }, D3DFVF_XYZB1 | D3DFVF_LASTBETA_D3DCOLOR},
683 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
684 {0, 12, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
685 D3DDECL_END(),
686 }, D3DFVF_XYZB2},
688 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
689 {0, 12, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
690 {0, 16, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
691 D3DDECL_END(),
692 }, D3DFVF_XYZB2 | D3DFVF_LASTBETA_UBYTE4},
694 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
695 {0, 12, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
696 {0, 16, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
697 D3DDECL_END(),
698 }, D3DFVF_XYZB2 | D3DFVF_LASTBETA_D3DCOLOR},
700 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
701 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
702 D3DDECL_END(),
703 }, D3DFVF_XYZB3},
705 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
706 {0, 12, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
707 {0, 20, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
708 D3DDECL_END(),
709 }, D3DFVF_XYZB3 | D3DFVF_LASTBETA_UBYTE4},
711 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
712 {0, 12, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
713 {0, 20, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
714 D3DDECL_END(),
715 }, D3DFVF_XYZB3 | D3DFVF_LASTBETA_D3DCOLOR},
717 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
718 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
719 D3DDECL_END(),
720 }, D3DFVF_XYZB4},
722 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
723 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
724 {0, 24, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
725 D3DDECL_END(),
726 }, D3DFVF_XYZB4 | D3DFVF_LASTBETA_UBYTE4},
728 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
729 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
730 {0, 24, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
731 D3DDECL_END(),
732 }, D3DFVF_XYZB4 | D3DFVF_LASTBETA_D3DCOLOR},
734 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
735 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
736 {0, 28, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
737 D3DDECL_END(),
738 }, D3DFVF_XYZB5 | D3DFVF_LASTBETA_UBYTE4},
740 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
741 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
742 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
743 D3DDECL_END(),
744 }, D3DFVF_XYZB5 | D3DFVF_LASTBETA_D3DCOLOR},
746 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
747 D3DDECL_END(),
748 }, D3DFVF_NORMAL},
750 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
751 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
752 D3DDECL_END(),
753 }, D3DFVF_NORMAL | D3DFVF_DIFFUSE},
755 {0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_PSIZE, 0},
756 D3DDECL_END(),
757 }, D3DFVF_PSIZE},
759 {0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
760 D3DDECL_END(),
761 }, D3DFVF_DIFFUSE},
763 {0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1},
764 D3DDECL_END(),
765 }, D3DFVF_SPECULAR},
766 /* Make sure textures of different sizes work. */
768 {0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
769 D3DDECL_END(),
770 }, D3DFVF_TEXCOORDSIZE1(0) | D3DFVF_TEX1},
772 {0, 0, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 0},
773 D3DDECL_END(),
774 }, D3DFVF_TEXCOORDSIZE2(0) | D3DFVF_TEX1},
776 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 0},
777 D3DDECL_END(),
778 }, D3DFVF_TEXCOORDSIZE3(0) | D3DFVF_TEX1},
780 {0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 0},
781 D3DDECL_END(),
782 }, D3DFVF_TEXCOORDSIZE4(0) | D3DFVF_TEX1},
783 /* Make sure the TEXCOORD index works correctly - try several textures. */
785 {0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
786 {0, 4, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 1},
787 {0, 16, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 2},
788 {0, 24, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 3},
789 D3DDECL_END(),
790 }, D3DFVF_TEX4 | D3DFVF_TEXCOORDSIZE1(0) | D3DFVF_TEXCOORDSIZE3(1)
791 | D3DFVF_TEXCOORDSIZE2(2) | D3DFVF_TEXCOORDSIZE4(3)},
792 /* Now try some combination tests. */
794 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
795 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
796 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
797 {0, 32, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1},
798 {0, 36, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 0},
799 {0, 44, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 1},
800 D3DDECL_END(),
801 }, D3DFVF_XYZB4 | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_TEX2
802 | D3DFVF_TEXCOORDSIZE2(0) | D3DFVF_TEXCOORDSIZE3(1)},
804 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
805 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
806 {0, 24, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_PSIZE, 0},
807 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1},
808 {0, 32, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
809 {0, 36, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 1},
810 D3DDECL_END(),
811 }, D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_PSIZE | D3DFVF_SPECULAR | D3DFVF_TEX2
812 | D3DFVF_TEXCOORDSIZE1(0) | D3DFVF_TEXCOORDSIZE4(1)},
814 unsigned int i;
816 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
818 test_decl_to_fvf(test_data[i].decl, test_data[i].fvf, D3D_OK, __LINE__, i);
819 test_fvf_to_decl(test_data[i].fvf, test_data[i].decl, D3D_OK, __LINE__, i);
822 /* Usage indices for position and normal are apparently ignored. */
824 const D3DVERTEXELEMENT9 decl[] =
826 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 1},
827 D3DDECL_END(),
829 test_decl_to_fvf(decl, D3DFVF_XYZ, D3D_OK, __LINE__, 0);
832 const D3DVERTEXELEMENT9 decl[] =
834 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 1},
835 D3DDECL_END(),
837 test_decl_to_fvf(decl, D3DFVF_NORMAL, D3D_OK, __LINE__, 0);
839 /* D3DFVF_LASTBETA_UBYTE4 and D3DFVF_LASTBETA_D3DCOLOR are ignored if
840 * there are no blend matrices. */
842 const D3DVERTEXELEMENT9 decl[] =
844 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
845 D3DDECL_END(),
847 test_fvf_to_decl(D3DFVF_XYZ | D3DFVF_LASTBETA_UBYTE4, decl, D3D_OK, __LINE__, 0);
850 const D3DVERTEXELEMENT9 decl[] =
852 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
853 D3DDECL_END(),
855 test_fvf_to_decl(D3DFVF_XYZ | D3DFVF_LASTBETA_D3DCOLOR, decl, D3D_OK, __LINE__, 0);
857 /* D3DFVF_LASTBETA_UBYTE4 takes precedence over D3DFVF_LASTBETA_D3DCOLOR. */
859 const D3DVERTEXELEMENT9 decl[] =
861 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
862 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
863 {0, 28, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
864 D3DDECL_END(),
866 test_fvf_to_decl(D3DFVF_XYZB5 | D3DFVF_LASTBETA_D3DCOLOR | D3DFVF_LASTBETA_UBYTE4,
867 decl, D3D_OK, __LINE__, 0);
869 /* These are supposed to fail, both ways. */
871 const D3DVERTEXELEMENT9 decl[] =
873 {0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITION, 0},
874 D3DDECL_END(),
876 test_decl_to_fvf(decl, D3DFVF_XYZW, D3DERR_INVALIDCALL, __LINE__, 0);
877 test_fvf_to_decl(D3DFVF_XYZW, decl, D3DERR_INVALIDCALL, __LINE__, 0);
880 const D3DVERTEXELEMENT9 decl[] =
882 {0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITION, 0},
883 {0, 16, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
884 D3DDECL_END(),
886 test_decl_to_fvf(decl, D3DFVF_XYZW | D3DFVF_NORMAL, D3DERR_INVALIDCALL, __LINE__, 0);
887 test_fvf_to_decl(D3DFVF_XYZW | D3DFVF_NORMAL, decl, D3DERR_INVALIDCALL, __LINE__, 0);
890 const D3DVERTEXELEMENT9 decl[] =
892 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
893 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
894 {0, 28, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDINDICES, 0},
895 D3DDECL_END(),
897 test_decl_to_fvf(decl, D3DFVF_XYZB5, D3DERR_INVALIDCALL, __LINE__, 0);
898 test_fvf_to_decl(D3DFVF_XYZB5, decl, D3DERR_INVALIDCALL, __LINE__, 0);
900 /* Test a declaration that can't be converted to an FVF. */
902 const D3DVERTEXELEMENT9 decl[] =
904 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
905 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
906 {0, 24, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_PSIZE, 0},
907 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1},
908 {0, 32, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
909 /* 8 bytes padding */
910 {0, 44, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 1},
911 D3DDECL_END(),
913 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0);
915 /* Elements must be ordered by offset. */
917 const D3DVERTEXELEMENT9 decl[] =
919 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
920 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
921 D3DDECL_END(),
923 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0);
925 /* Basic tests for element order. */
927 const D3DVERTEXELEMENT9 decl[] =
929 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
930 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
931 {0, 16, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
932 D3DDECL_END(),
934 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0);
937 const D3DVERTEXELEMENT9 decl[] =
939 {0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
940 {0, 4, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
941 D3DDECL_END(),
943 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0);
946 const D3DVERTEXELEMENT9 decl[] =
948 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
949 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
950 D3DDECL_END(),
952 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0);
954 /* Textures must be ordered by texcoords. */
956 const D3DVERTEXELEMENT9 decl[] =
958 {0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
959 {0, 4, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 2},
960 {0, 16, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 1},
961 {0, 24, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 3},
962 D3DDECL_END(),
964 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0);
966 /* Duplicate elements are not allowed. */
968 const D3DVERTEXELEMENT9 decl[] =
970 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
971 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
972 {0, 16, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
973 D3DDECL_END(),
975 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0);
977 /* Invalid FVFs cannot be converted to a declarator. */
978 test_fvf_to_decl(0xdeadbeef, NULL, D3DERR_INVALIDCALL, __LINE__, 0);
981 static void D3DXGetFVFVertexSizeTest(void)
983 UINT got;
985 compare_vertex_sizes (D3DFVF_XYZ, 12);
987 compare_vertex_sizes (D3DFVF_XYZB3, 24);
989 compare_vertex_sizes (D3DFVF_XYZB5, 32);
991 compare_vertex_sizes (D3DFVF_XYZ | D3DFVF_NORMAL, 24);
993 compare_vertex_sizes (D3DFVF_XYZ | D3DFVF_DIFFUSE, 16);
995 compare_vertex_sizes (
996 D3DFVF_XYZ |
997 D3DFVF_TEX1 |
998 D3DFVF_TEXCOORDSIZE1(0), 16);
999 compare_vertex_sizes (
1000 D3DFVF_XYZ |
1001 D3DFVF_TEX2 |
1002 D3DFVF_TEXCOORDSIZE1(0) |
1003 D3DFVF_TEXCOORDSIZE1(1), 20);
1005 compare_vertex_sizes (
1006 D3DFVF_XYZ |
1007 D3DFVF_TEX1 |
1008 D3DFVF_TEXCOORDSIZE2(0), 20);
1010 compare_vertex_sizes (
1011 D3DFVF_XYZ |
1012 D3DFVF_TEX2 |
1013 D3DFVF_TEXCOORDSIZE2(0) |
1014 D3DFVF_TEXCOORDSIZE2(1), 28);
1016 compare_vertex_sizes (
1017 D3DFVF_XYZ |
1018 D3DFVF_TEX6 |
1019 D3DFVF_TEXCOORDSIZE2(0) |
1020 D3DFVF_TEXCOORDSIZE2(1) |
1021 D3DFVF_TEXCOORDSIZE2(2) |
1022 D3DFVF_TEXCOORDSIZE2(3) |
1023 D3DFVF_TEXCOORDSIZE2(4) |
1024 D3DFVF_TEXCOORDSIZE2(5), 60);
1026 compare_vertex_sizes (
1027 D3DFVF_XYZ |
1028 D3DFVF_TEX8 |
1029 D3DFVF_TEXCOORDSIZE2(0) |
1030 D3DFVF_TEXCOORDSIZE2(1) |
1031 D3DFVF_TEXCOORDSIZE2(2) |
1032 D3DFVF_TEXCOORDSIZE2(3) |
1033 D3DFVF_TEXCOORDSIZE2(4) |
1034 D3DFVF_TEXCOORDSIZE2(5) |
1035 D3DFVF_TEXCOORDSIZE2(6) |
1036 D3DFVF_TEXCOORDSIZE2(7), 76);
1038 compare_vertex_sizes (
1039 D3DFVF_XYZ |
1040 D3DFVF_TEX1 |
1041 D3DFVF_TEXCOORDSIZE3(0), 24);
1043 compare_vertex_sizes (
1044 D3DFVF_XYZ |
1045 D3DFVF_TEX4 |
1046 D3DFVF_TEXCOORDSIZE3(0) |
1047 D3DFVF_TEXCOORDSIZE3(1) |
1048 D3DFVF_TEXCOORDSIZE3(2) |
1049 D3DFVF_TEXCOORDSIZE3(3), 60);
1051 compare_vertex_sizes (
1052 D3DFVF_XYZ |
1053 D3DFVF_TEX1 |
1054 D3DFVF_TEXCOORDSIZE4(0), 28);
1056 compare_vertex_sizes (
1057 D3DFVF_XYZ |
1058 D3DFVF_TEX2 |
1059 D3DFVF_TEXCOORDSIZE4(0) |
1060 D3DFVF_TEXCOORDSIZE4(1), 44);
1062 compare_vertex_sizes (
1063 D3DFVF_XYZ |
1064 D3DFVF_TEX3 |
1065 D3DFVF_TEXCOORDSIZE4(0) |
1066 D3DFVF_TEXCOORDSIZE4(1) |
1067 D3DFVF_TEXCOORDSIZE4(2), 60);
1069 compare_vertex_sizes (
1070 D3DFVF_XYZB5 |
1071 D3DFVF_NORMAL |
1072 D3DFVF_DIFFUSE |
1073 D3DFVF_SPECULAR |
1074 D3DFVF_TEX8 |
1075 D3DFVF_TEXCOORDSIZE4(0) |
1076 D3DFVF_TEXCOORDSIZE4(1) |
1077 D3DFVF_TEXCOORDSIZE4(2) |
1078 D3DFVF_TEXCOORDSIZE4(3) |
1079 D3DFVF_TEXCOORDSIZE4(4) |
1080 D3DFVF_TEXCOORDSIZE4(5) |
1081 D3DFVF_TEXCOORDSIZE4(6) |
1082 D3DFVF_TEXCOORDSIZE4(7), 180);
1085 static void D3DXIntersectTriTest(void)
1087 BOOL exp_res, got_res;
1088 D3DXVECTOR3 position, ray, vertex[3];
1089 FLOAT exp_dist, got_dist, exp_u, got_u, exp_v, got_v;
1091 vertex[0].x = 1.0f; vertex[0].y = 0.0f; vertex[0].z = 0.0f;
1092 vertex[1].x = 2.0f; vertex[1].y = 0.0f; vertex[1].z = 0.0f;
1093 vertex[2].x = 1.0f; vertex[2].y = 1.0f; vertex[2].z = 0.0f;
1095 position.x = -14.5f; position.y = -23.75f; position.z = -32.0f;
1097 ray.x = 2.0f; ray.y = 3.0f; ray.z = 4.0f;
1099 exp_res = TRUE; exp_u = 0.5f; exp_v = 0.25f; exp_dist = 8.0f;
1101 got_res = D3DXIntersectTri(&vertex[0],&vertex[1],&vertex[2],&position,&ray,&got_u,&got_v,&got_dist);
1102 ok( got_res == exp_res, "Expected result = %d, got %d\n",exp_res,got_res);
1103 ok( compare(exp_u,got_u), "Expected u = %f, got %f\n",exp_u,got_u);
1104 ok( compare(exp_v,got_v), "Expected v = %f, got %f\n",exp_v,got_v);
1105 ok( compare(exp_dist,got_dist), "Expected distance = %f, got %f\n",exp_dist,got_dist);
1107 /*Only positive ray is taken in account*/
1109 vertex[0].x = 1.0f; vertex[0].y = 0.0f; vertex[0].z = 0.0f;
1110 vertex[1].x = 2.0f; vertex[1].y = 0.0f; vertex[1].z = 0.0f;
1111 vertex[2].x = 1.0f; vertex[2].y = 1.0f; vertex[2].z = 0.0f;
1113 position.x = 17.5f; position.y = 24.25f; position.z = 32.0f;
1115 ray.x = 2.0f; ray.y = 3.0f; ray.z = 4.0f;
1117 exp_res = FALSE;
1119 got_res = D3DXIntersectTri(&vertex[0],&vertex[1],&vertex[2],&position,&ray,&got_u,&got_v,&got_dist);
1120 ok( got_res == exp_res, "Expected result = %d, got %d\n",exp_res,got_res);
1122 /*Intersection between ray and triangle in a same plane is considered as empty*/
1124 vertex[0].x = 4.0f; vertex[0].y = 0.0f; vertex[0].z = 0.0f;
1125 vertex[1].x = 6.0f; vertex[1].y = 0.0f; vertex[1].z = 0.0f;
1126 vertex[2].x = 4.0f; vertex[2].y = 2.0f; vertex[2].z = 0.0f;
1128 position.x = 1.0f; position.y = 1.0f; position.z = 0.0f;
1130 ray.x = 1.0f; ray.y = 0.0f; ray.z = 0.0f;
1132 exp_res = FALSE;
1134 got_res = D3DXIntersectTri(&vertex[0],&vertex[1],&vertex[2],&position,&ray,&got_u,&got_v,&got_dist);
1135 ok( got_res == exp_res, "Expected result = %d, got %d\n",exp_res,got_res);
1138 static void D3DXCreateMeshTest(void)
1140 HRESULT hr;
1141 HWND wnd;
1142 IDirect3D9 *d3d;
1143 IDirect3DDevice9 *device, *test_device;
1144 D3DPRESENT_PARAMETERS d3dpp;
1145 ID3DXMesh *d3dxmesh;
1146 int i, size;
1147 D3DVERTEXELEMENT9 test_decl[MAX_FVF_DECL_SIZE];
1148 DWORD options;
1149 struct mesh mesh;
1151 static const D3DVERTEXELEMENT9 decl1[3] = {
1152 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1153 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
1154 D3DDECL_END(), };
1156 static const D3DVERTEXELEMENT9 decl2[] = {
1157 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1158 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
1159 {0, 24, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_PSIZE, 0},
1160 {0, 28, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 1},
1161 {0, 32, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
1162 /* 8 bytes padding */
1163 {0, 44, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
1164 D3DDECL_END(),
1167 static const D3DVERTEXELEMENT9 decl3[] = {
1168 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1169 {1, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
1170 D3DDECL_END(),
1173 hr = D3DXCreateMesh(0, 0, 0, NULL, NULL, NULL);
1174 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1176 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl1, NULL, &d3dxmesh);
1177 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1179 if (!(wnd = CreateWindowA("static", "d3dx9_test", WS_OVERLAPPEDWINDOW, 0, 0,
1180 640, 480, NULL, NULL, NULL, NULL)))
1182 skip("Couldn't create application window\n");
1183 return;
1185 d3d = Direct3DCreate9(D3D_SDK_VERSION);
1186 if (!d3d)
1188 skip("Couldn't create IDirect3D9 object\n");
1189 DestroyWindow(wnd);
1190 return;
1193 ZeroMemory(&d3dpp, sizeof(d3dpp));
1194 d3dpp.Windowed = TRUE;
1195 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1196 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, wnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device);
1197 if (FAILED(hr))
1199 skip("Failed to create IDirect3DDevice9 object %#x\n", hr);
1200 IDirect3D9_Release(d3d);
1201 DestroyWindow(wnd);
1202 return;
1205 hr = D3DXCreateMesh(0, 3, D3DXMESH_MANAGED, decl1, device, &d3dxmesh);
1206 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1208 hr = D3DXCreateMesh(1, 0, D3DXMESH_MANAGED, decl1, device, &d3dxmesh);
1209 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1211 hr = D3DXCreateMesh(1, 3, 0, decl1, device, &d3dxmesh);
1212 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
1214 if (hr == D3D_OK)
1216 d3dxmesh->lpVtbl->Release(d3dxmesh);
1219 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, 0, device, &d3dxmesh);
1220 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1222 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl1, device, NULL);
1223 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1225 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl1, device, &d3dxmesh);
1226 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
1228 if (hr == D3D_OK)
1230 /* device */
1231 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, NULL);
1232 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1234 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, &test_device);
1235 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
1236 ok(test_device == device, "Got result %p, expected %p\n", test_device, device);
1238 if (hr == D3D_OK)
1240 IDirect3DDevice9_Release(device);
1243 /* declaration */
1244 hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, NULL);
1245 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1247 hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, test_decl);
1248 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
1250 if (hr == D3D_OK)
1252 size = sizeof(decl1) / sizeof(decl1[0]);
1253 for (i = 0; i < size - 1; i++)
1255 ok(test_decl[i].Stream == decl1[i].Stream, "Returned stream %d, expected %d\n", test_decl[i].Stream, decl1[i].Stream);
1256 ok(test_decl[i].Type == decl1[i].Type, "Returned type %d, expected %d\n", test_decl[i].Type, decl1[i].Type);
1257 ok(test_decl[i].Method == decl1[i].Method, "Returned method %d, expected %d\n", test_decl[i].Method, decl1[i].Method);
1258 ok(test_decl[i].Usage == decl1[i].Usage, "Returned usage %d, expected %d\n", test_decl[i].Usage, decl1[i].Usage);
1259 ok(test_decl[i].UsageIndex == decl1[i].UsageIndex, "Returned usage index %d, expected %d\n", test_decl[i].UsageIndex, decl1[i].UsageIndex);
1260 ok(test_decl[i].Offset == decl1[i].Offset, "Returned offset %d, expected %d\n", test_decl[i].Offset, decl1[i].Offset);
1262 ok(decl1[size-1].Stream == 0xFF, "Returned too long vertex declaration\n"); /* end element */
1265 /* options */
1266 options = d3dxmesh->lpVtbl->GetOptions(d3dxmesh);
1267 ok(options == D3DXMESH_MANAGED, "Got result %x, expected %x (D3DXMESH_MANAGED)\n", options, D3DXMESH_MANAGED);
1269 /* rest */
1270 if (!new_mesh(&mesh, 3, 1))
1272 skip("Couldn't create mesh\n");
1274 else
1276 memset(mesh.vertices, 0, mesh.number_of_vertices * sizeof(*mesh.vertices));
1277 memset(mesh.faces, 0, mesh.number_of_faces * sizeof(*mesh.faces));
1278 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
1280 compare_mesh("createmesh1", d3dxmesh, &mesh);
1282 free_mesh(&mesh);
1285 d3dxmesh->lpVtbl->Release(d3dxmesh);
1288 /* Test a declaration that can't be converted to an FVF. */
1289 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl2, device, &d3dxmesh);
1290 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
1292 if (hr == D3D_OK)
1294 /* device */
1295 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, NULL);
1296 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1298 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, &test_device);
1299 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
1300 ok(test_device == device, "Got result %p, expected %p\n", test_device, device);
1302 if (hr == D3D_OK)
1304 IDirect3DDevice9_Release(device);
1307 /* declaration */
1308 hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, test_decl);
1309 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
1311 if (hr == D3D_OK)
1313 size = sizeof(decl2) / sizeof(decl2[0]);
1314 for (i = 0; i < size - 1; i++)
1316 ok(test_decl[i].Stream == decl2[i].Stream, "Returned stream %d, expected %d\n", test_decl[i].Stream, decl2[i].Stream);
1317 ok(test_decl[i].Type == decl2[i].Type, "Returned type %d, expected %d\n", test_decl[i].Type, decl2[i].Type);
1318 ok(test_decl[i].Method == decl2[i].Method, "Returned method %d, expected %d\n", test_decl[i].Method, decl2[i].Method);
1319 ok(test_decl[i].Usage == decl2[i].Usage, "Returned usage %d, expected %d\n", test_decl[i].Usage, decl2[i].Usage);
1320 ok(test_decl[i].UsageIndex == decl2[i].UsageIndex, "Returned usage index %d, expected %d\n", test_decl[i].UsageIndex, decl2[i].UsageIndex);
1321 ok(test_decl[i].Offset == decl2[i].Offset, "Returned offset %d, expected %d\n", test_decl[i].Offset, decl2[i].Offset);
1323 ok(decl2[size-1].Stream == 0xFF, "Returned too long vertex declaration\n"); /* end element */
1326 /* options */
1327 options = d3dxmesh->lpVtbl->GetOptions(d3dxmesh);
1328 ok(options == D3DXMESH_MANAGED, "Got result %x, expected %x (D3DXMESH_MANAGED)\n", options, D3DXMESH_MANAGED);
1330 /* rest */
1331 if (!new_mesh(&mesh, 3, 1))
1333 skip("Couldn't create mesh\n");
1335 else
1337 memset(mesh.vertices, 0, mesh.number_of_vertices * sizeof(*mesh.vertices));
1338 memset(mesh.faces, 0, mesh.number_of_faces * sizeof(*mesh.faces));
1339 mesh.fvf = 0;
1340 mesh.vertex_size = 60;
1342 compare_mesh("createmesh2", d3dxmesh, &mesh);
1344 free_mesh(&mesh);
1347 mesh.vertex_size = d3dxmesh->lpVtbl->GetNumBytesPerVertex(d3dxmesh);
1348 ok(mesh.vertex_size == 60, "Got vertex size %u, expected %u\n", mesh.vertex_size, 60);
1350 d3dxmesh->lpVtbl->Release(d3dxmesh);
1353 /* Test a declaration with multiple streams. */
1354 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl3, device, &d3dxmesh);
1355 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1357 IDirect3DDevice9_Release(device);
1358 IDirect3D9_Release(d3d);
1359 DestroyWindow(wnd);
1362 static void D3DXCreateMeshFVFTest(void)
1364 HRESULT hr;
1365 HWND wnd;
1366 IDirect3D9 *d3d;
1367 IDirect3DDevice9 *device, *test_device;
1368 D3DPRESENT_PARAMETERS d3dpp;
1369 ID3DXMesh *d3dxmesh;
1370 int i, size;
1371 D3DVERTEXELEMENT9 test_decl[MAX_FVF_DECL_SIZE];
1372 DWORD options;
1373 struct mesh mesh;
1375 static const D3DVERTEXELEMENT9 decl[3] = {
1376 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1377 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
1378 D3DDECL_END(), };
1380 hr = D3DXCreateMeshFVF(0, 0, 0, 0, NULL, NULL);
1381 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1383 hr = D3DXCreateMeshFVF(1, 3, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, NULL, &d3dxmesh);
1384 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1386 if (!(wnd = CreateWindowA("static", "d3dx9_test", WS_OVERLAPPEDWINDOW, 0, 0,
1387 640, 480, NULL, NULL, NULL, NULL)))
1389 skip("Couldn't create application window\n");
1390 return;
1392 d3d = Direct3DCreate9(D3D_SDK_VERSION);
1393 if (!d3d)
1395 skip("Couldn't create IDirect3D9 object\n");
1396 DestroyWindow(wnd);
1397 return;
1400 ZeroMemory(&d3dpp, sizeof(d3dpp));
1401 d3dpp.Windowed = TRUE;
1402 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1403 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, wnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device);
1404 if (FAILED(hr))
1406 skip("Failed to create IDirect3DDevice9 object %#x\n", hr);
1407 IDirect3D9_Release(d3d);
1408 DestroyWindow(wnd);
1409 return;
1412 hr = D3DXCreateMeshFVF(0, 3, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, device, &d3dxmesh);
1413 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1415 hr = D3DXCreateMeshFVF(1, 0, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, device, &d3dxmesh);
1416 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1418 hr = D3DXCreateMeshFVF(1, 3, 0, D3DFVF_XYZ | D3DFVF_NORMAL, device, &d3dxmesh);
1419 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
1421 if (hr == D3D_OK)
1423 d3dxmesh->lpVtbl->Release(d3dxmesh);
1426 hr = D3DXCreateMeshFVF(1, 3, D3DXMESH_MANAGED, 0xdeadbeef, device, &d3dxmesh);
1427 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1429 hr = D3DXCreateMeshFVF(1, 3, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, device, NULL);
1430 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1432 hr = D3DXCreateMeshFVF(1, 3, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, device, &d3dxmesh);
1433 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
1435 if (hr == D3D_OK)
1437 /* device */
1438 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, NULL);
1439 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1441 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, &test_device);
1442 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
1443 ok(test_device == device, "Got result %p, expected %p\n", test_device, device);
1445 if (hr == D3D_OK)
1447 IDirect3DDevice9_Release(device);
1450 /* declaration */
1451 hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, NULL);
1452 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1454 hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, test_decl);
1455 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
1457 if (hr == D3D_OK)
1459 size = sizeof(decl) / sizeof(decl[0]);
1460 for (i = 0; i < size - 1; i++)
1462 ok(test_decl[i].Stream == decl[i].Stream, "Returned stream %d, expected %d\n", test_decl[i].Stream, decl[i].Stream);
1463 ok(test_decl[i].Type == decl[i].Type, "Returned type %d, expected %d\n", test_decl[i].Type, decl[i].Type);
1464 ok(test_decl[i].Method == decl[i].Method, "Returned method %d, expected %d\n", test_decl[i].Method, decl[i].Method);
1465 ok(test_decl[i].Usage == decl[i].Usage, "Returned usage %d, expected %d\n", test_decl[i].Usage, decl[i].Usage);
1466 ok(test_decl[i].UsageIndex == decl[i].UsageIndex, "Returned usage index %d, expected %d\n",
1467 test_decl[i].UsageIndex, decl[i].UsageIndex);
1468 ok(test_decl[i].Offset == decl[i].Offset, "Returned offset %d, expected %d\n", test_decl[i].Offset, decl[i].Offset);
1470 ok(decl[size-1].Stream == 0xFF, "Returned too long vertex declaration\n"); /* end element */
1473 /* options */
1474 options = d3dxmesh->lpVtbl->GetOptions(d3dxmesh);
1475 ok(options == D3DXMESH_MANAGED, "Got result %x, expected %x (D3DXMESH_MANAGED)\n", options, D3DXMESH_MANAGED);
1477 /* rest */
1478 if (!new_mesh(&mesh, 3, 1))
1480 skip("Couldn't create mesh\n");
1482 else
1484 memset(mesh.vertices, 0, mesh.number_of_vertices * sizeof(*mesh.vertices));
1485 memset(mesh.faces, 0, mesh.number_of_faces * sizeof(*mesh.faces));
1486 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
1488 compare_mesh("createmeshfvf", d3dxmesh, &mesh);
1490 free_mesh(&mesh);
1493 d3dxmesh->lpVtbl->Release(d3dxmesh);
1496 IDirect3DDevice9_Release(device);
1497 IDirect3D9_Release(d3d);
1498 DestroyWindow(wnd);
1501 #define check_vertex_buffer(mesh, vertices, num_vertices, fvf) \
1502 check_vertex_buffer_(__LINE__, mesh, vertices, num_vertices, fvf)
1503 static void check_vertex_buffer_(int line, ID3DXMesh *mesh, const void *vertices, DWORD num_vertices, DWORD fvf)
1505 DWORD mesh_num_vertices = mesh->lpVtbl->GetNumVertices(mesh);
1506 DWORD mesh_fvf = mesh->lpVtbl->GetFVF(mesh);
1507 const void *mesh_vertices;
1508 HRESULT hr;
1510 ok_(__FILE__,line)(fvf == mesh_fvf, "expected FVF %x, got %x\n", fvf, mesh_fvf);
1511 ok_(__FILE__,line)(num_vertices == mesh_num_vertices,
1512 "Expected %u vertices, got %u\n", num_vertices, mesh_num_vertices);
1514 hr = mesh->lpVtbl->LockVertexBuffer(mesh, D3DLOCK_READONLY, (void**)&mesh_vertices);
1515 ok_(__FILE__,line)(hr == D3D_OK, "LockVertexBuffer returned %x, expected %x (D3D_OK)\n", hr, D3D_OK);
1516 if (FAILED(hr))
1517 return;
1519 if (mesh_fvf == fvf) {
1520 DWORD vertex_size = D3DXGetFVFVertexSize(fvf);
1521 int i;
1522 for (i = 0; i < min(num_vertices, mesh_num_vertices); i++)
1524 const FLOAT *exp_float = vertices;
1525 const FLOAT *got_float = mesh_vertices;
1526 DWORD texcount;
1527 DWORD pos_dim = 0;
1528 int j;
1529 BOOL last_beta_dword = FALSE;
1530 char prefix[128];
1532 switch (fvf & D3DFVF_POSITION_MASK) {
1533 case D3DFVF_XYZ: pos_dim = 3; break;
1534 case D3DFVF_XYZRHW: pos_dim = 4; break;
1535 case D3DFVF_XYZB1:
1536 case D3DFVF_XYZB2:
1537 case D3DFVF_XYZB3:
1538 case D3DFVF_XYZB4:
1539 case D3DFVF_XYZB5:
1540 pos_dim = (fvf & D3DFVF_POSITION_MASK) - D3DFVF_XYZB1 + 1;
1541 if (fvf & (D3DFVF_LASTBETA_UBYTE4 | D3DFVF_LASTBETA_D3DCOLOR))
1543 pos_dim--;
1544 last_beta_dword = TRUE;
1546 break;
1547 case D3DFVF_XYZW: pos_dim = 4; break;
1549 sprintf(prefix, "vertex[%u] position, ", i);
1550 check_floats_(line, prefix, got_float, exp_float, pos_dim);
1551 exp_float += pos_dim;
1552 got_float += pos_dim;
1554 if (last_beta_dword) {
1555 ok_(__FILE__,line)(*(DWORD*)exp_float == *(DWORD*)got_float,
1556 "Vertex[%u]: Expected last beta %08x, got %08x\n", i, *(DWORD*)exp_float, *(DWORD*)got_float);
1557 exp_float++;
1558 got_float++;
1561 if (fvf & D3DFVF_NORMAL) {
1562 sprintf(prefix, "vertex[%u] normal, ", i);
1563 check_floats_(line, prefix, got_float, exp_float, 3);
1564 exp_float += 3;
1565 got_float += 3;
1567 if (fvf & D3DFVF_PSIZE) {
1568 ok_(__FILE__,line)(compare(*exp_float, *got_float),
1569 "Vertex[%u]: Expected psize %g, got %g\n", i, *exp_float, *got_float);
1570 exp_float++;
1571 got_float++;
1573 if (fvf & D3DFVF_DIFFUSE) {
1574 ok_(__FILE__,line)(*(DWORD*)exp_float == *(DWORD*)got_float,
1575 "Vertex[%u]: Expected diffuse %08x, got %08x\n", i, *(DWORD*)exp_float, *(DWORD*)got_float);
1576 exp_float++;
1577 got_float++;
1579 if (fvf & D3DFVF_SPECULAR) {
1580 ok_(__FILE__,line)(*(DWORD*)exp_float == *(DWORD*)got_float,
1581 "Vertex[%u]: Expected specular %08x, got %08x\n", i, *(DWORD*)exp_float, *(DWORD*)got_float);
1582 exp_float++;
1583 got_float++;
1586 texcount = (fvf & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
1587 for (j = 0; j < texcount; j++) {
1588 DWORD dim = (((fvf >> (16 + 2 * j)) + 1) & 0x03) + 1;
1589 sprintf(prefix, "vertex[%u] texture, ", i);
1590 check_floats_(line, prefix, got_float, exp_float, dim);
1591 exp_float += dim;
1592 got_float += dim;
1595 vertices = (BYTE*)vertices + vertex_size;
1596 mesh_vertices = (BYTE*)mesh_vertices + vertex_size;
1600 mesh->lpVtbl->UnlockVertexBuffer(mesh);
1603 #define check_index_buffer(mesh, indices, num_indices, index_size) \
1604 check_index_buffer_(__LINE__, mesh, indices, num_indices, index_size)
1605 static void check_index_buffer_(int line, ID3DXMesh *mesh, const void *indices, DWORD num_indices, DWORD index_size)
1607 DWORD mesh_index_size = (mesh->lpVtbl->GetOptions(mesh) & D3DXMESH_32BIT) ? 4 : 2;
1608 DWORD mesh_num_indices = mesh->lpVtbl->GetNumFaces(mesh) * 3;
1609 const void *mesh_indices;
1610 HRESULT hr;
1611 DWORD i;
1613 ok_(__FILE__,line)(index_size == mesh_index_size,
1614 "Expected index size %u, got %u\n", index_size, mesh_index_size);
1615 ok_(__FILE__,line)(num_indices == mesh_num_indices,
1616 "Expected %u indices, got %u\n", num_indices, mesh_num_indices);
1618 hr = mesh->lpVtbl->LockIndexBuffer(mesh, D3DLOCK_READONLY, (void**)&mesh_indices);
1619 ok_(__FILE__,line)(hr == D3D_OK, "LockIndexBuffer returned %x, expected %x (D3D_OK)\n", hr, D3D_OK);
1620 if (FAILED(hr))
1621 return;
1623 if (mesh_index_size == index_size) {
1624 for (i = 0; i < min(num_indices, mesh_num_indices); i++)
1626 if (index_size == 4)
1627 ok_(__FILE__,line)(*(DWORD*)indices == *(DWORD*)mesh_indices,
1628 "Index[%u]: expected %u, got %u\n", i, *(DWORD*)indices, *(DWORD*)mesh_indices);
1629 else
1630 ok_(__FILE__,line)(*(WORD*)indices == *(WORD*)mesh_indices,
1631 "Index[%u]: expected %u, got %u\n", i, *(WORD*)indices, *(WORD*)mesh_indices);
1632 indices = (BYTE*)indices + index_size;
1633 mesh_indices = (BYTE*)mesh_indices + index_size;
1636 mesh->lpVtbl->UnlockIndexBuffer(mesh);
1639 #define check_matrix(got, expected) check_matrix_(__LINE__, got, expected)
1640 static void check_matrix_(int line, const D3DXMATRIX *got, const D3DXMATRIX *expected)
1642 int i, j;
1643 for (i = 0; i < 4; i++) {
1644 for (j = 0; j < 4; j++) {
1645 ok_(__FILE__,line)(compare(U(*expected).m[i][j], U(*got).m[i][j]),
1646 "matrix[%u][%u]: expected %g, got %g\n",
1647 i, j, U(*expected).m[i][j], U(*got).m[i][j]);
1652 static void check_colorvalue_(int line, const char *prefix, const D3DCOLORVALUE got, const D3DCOLORVALUE expected)
1654 ok_(__FILE__,line)(expected.r == got.r && expected.g == got.g && expected.b == got.b && expected.a == got.a,
1655 "%sExpected (%g, %g, %g, %g), got (%g, %g, %g, %g)\n", prefix,
1656 expected.r, expected.g, expected.b, expected.a, got.r, got.g, got.b, got.a);
1659 #define check_materials(got, got_count, expected, expected_count) \
1660 check_materials_(__LINE__, got, got_count, expected, expected_count)
1661 static void check_materials_(int line, const D3DXMATERIAL *got, DWORD got_count, const D3DXMATERIAL *expected, DWORD expected_count)
1663 int i;
1664 ok_(__FILE__,line)(expected_count == got_count, "Expected %u materials, got %u\n", expected_count, got_count);
1665 if (!expected) {
1666 ok_(__FILE__,line)(got == NULL, "Expected NULL material ptr, got %p\n", got);
1667 return;
1669 for (i = 0; i < min(expected_count, got_count); i++)
1671 if (!expected[i].pTextureFilename)
1672 ok_(__FILE__,line)(got[i].pTextureFilename == NULL,
1673 "Expected NULL pTextureFilename, got %p\n", got[i].pTextureFilename);
1674 else
1675 ok_(__FILE__,line)(!strcmp(expected[i].pTextureFilename, got[i].pTextureFilename),
1676 "Expected '%s' for pTextureFilename, got '%s'\n", expected[i].pTextureFilename, got[i].pTextureFilename);
1677 check_colorvalue_(line, "Diffuse: ", got[i].MatD3D.Diffuse, expected[i].MatD3D.Diffuse);
1678 check_colorvalue_(line, "Ambient: ", got[i].MatD3D.Ambient, expected[i].MatD3D.Ambient);
1679 check_colorvalue_(line, "Specular: ", got[i].MatD3D.Specular, expected[i].MatD3D.Specular);
1680 check_colorvalue_(line, "Emissive: ", got[i].MatD3D.Emissive, expected[i].MatD3D.Emissive);
1681 ok_(__FILE__,line)(expected[i].MatD3D.Power == got[i].MatD3D.Power,
1682 "Power: Expected %g, got %g\n", expected[i].MatD3D.Power, got[i].MatD3D.Power);
1686 #define check_generated_adjacency(mesh, got, epsilon) check_generated_adjacency_(__LINE__, mesh, got, epsilon)
1687 static void check_generated_adjacency_(int line, ID3DXMesh *mesh, const DWORD *got, FLOAT epsilon)
1689 DWORD *expected;
1690 DWORD num_faces = mesh->lpVtbl->GetNumFaces(mesh);
1691 HRESULT hr;
1693 expected = HeapAlloc(GetProcessHeap(), 0, num_faces * sizeof(DWORD) * 3);
1694 if (!expected) {
1695 skip_(__FILE__, line)("Out of memory\n");
1696 return;
1698 hr = mesh->lpVtbl->GenerateAdjacency(mesh, epsilon, expected);
1699 ok_(__FILE__, line)(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
1700 if (SUCCEEDED(hr))
1702 int i;
1703 for (i = 0; i < num_faces; i++)
1705 ok_(__FILE__, line)(expected[i * 3] == got[i * 3] &&
1706 expected[i * 3 + 1] == got[i * 3 + 1] &&
1707 expected[i * 3 + 2] == got[i * 3 + 2],
1708 "Face %u adjacencies: Expected (%u, %u, %u), got (%u, %u, %u)\n", i,
1709 expected[i * 3], expected[i * 3 + 1], expected[i * 3 + 2],
1710 got[i * 3], got[i * 3 + 1], got[i * 3 + 2]);
1713 HeapFree(GetProcessHeap(), 0, expected);
1716 #define check_generated_effects(materials, num_materials, effects) \
1717 check_generated_effects_(__LINE__, materials, num_materials, effects)
1718 static void check_generated_effects_(int line, const D3DXMATERIAL *materials, DWORD num_materials, const D3DXEFFECTINSTANCE *effects)
1720 int i;
1721 static const struct {
1722 const char *name;
1723 DWORD name_size;
1724 DWORD num_bytes;
1725 DWORD value_offset;
1726 } params[] = {
1727 #define EFFECT_TABLE_ENTRY(str, field) \
1728 {str, sizeof(str), sizeof(materials->MatD3D.field), offsetof(D3DXMATERIAL, MatD3D.field)}
1729 EFFECT_TABLE_ENTRY("Diffuse", Diffuse),
1730 EFFECT_TABLE_ENTRY("Power", Power),
1731 EFFECT_TABLE_ENTRY("Specular", Specular),
1732 EFFECT_TABLE_ENTRY("Emissive", Emissive),
1733 EFFECT_TABLE_ENTRY("Ambient", Ambient),
1734 #undef EFFECT_TABLE_ENTRY
1737 if (!num_materials) {
1738 ok_(__FILE__, line)(effects == NULL, "Expected NULL effects, got %p\n", effects);
1739 return;
1741 for (i = 0; i < num_materials; i++)
1743 int j;
1744 DWORD expected_num_defaults = ARRAY_SIZE(params) + (materials[i].pTextureFilename ? 1 : 0);
1746 ok_(__FILE__,line)(expected_num_defaults == effects[i].NumDefaults,
1747 "effect[%u] NumDefaults: Expected %u, got %u\n", i,
1748 expected_num_defaults, effects[i].NumDefaults);
1749 for (j = 0; j < min(ARRAY_SIZE(params), effects[i].NumDefaults); j++)
1751 int k;
1752 D3DXEFFECTDEFAULT *got_param = &effects[i].pDefaults[j];
1753 ok_(__FILE__,line)(!strcmp(params[j].name, got_param->pParamName),
1754 "effect[%u].pDefaults[%u].pParamName: Expected '%s', got '%s'\n", i, j,
1755 params[j].name, got_param->pParamName);
1756 ok_(__FILE__,line)(D3DXEDT_FLOATS == got_param->Type,
1757 "effect[%u].pDefaults[%u].Type: Expected %u, got %u\n", i, j,
1758 D3DXEDT_FLOATS, got_param->Type);
1759 ok_(__FILE__,line)(params[j].num_bytes == got_param->NumBytes,
1760 "effect[%u].pDefaults[%u].NumBytes: Expected %u, got %u\n", i, j,
1761 params[j].num_bytes, got_param->NumBytes);
1762 for (k = 0; k < min(params[j].num_bytes, got_param->NumBytes) / 4; k++)
1764 FLOAT expected = ((FLOAT*)((BYTE*)&materials[i] + params[j].value_offset))[k];
1765 FLOAT got = ((FLOAT*)got_param->pValue)[k];
1766 ok_(__FILE__,line)(compare(expected, got),
1767 "effect[%u].pDefaults[%u] float value %u: Expected %g, got %g\n", i, j, k, expected, got);
1770 if (effects[i].NumDefaults > ARRAY_SIZE(params)) {
1771 D3DXEFFECTDEFAULT *got_param = &effects[i].pDefaults[j];
1772 static const char *expected_name = "Texture0@Name";
1774 ok_(__FILE__,line)(!strcmp(expected_name, got_param->pParamName),
1775 "effect[%u].pDefaults[%u].pParamName: Expected '%s', got '%s'\n", i, j,
1776 expected_name, got_param->pParamName);
1777 ok_(__FILE__,line)(D3DXEDT_STRING == got_param->Type,
1778 "effect[%u].pDefaults[%u].Type: Expected %u, got %u\n", i, j,
1779 D3DXEDT_STRING, got_param->Type);
1780 if (materials[i].pTextureFilename) {
1781 ok_(__FILE__,line)(strlen(materials[i].pTextureFilename) + 1 == got_param->NumBytes,
1782 "effect[%u] texture filename length: Expected %u, got %u\n", i,
1783 (DWORD)strlen(materials[i].pTextureFilename) + 1, got_param->NumBytes);
1784 ok_(__FILE__,line)(!strcmp(materials[i].pTextureFilename, got_param->pValue),
1785 "effect[%u] texture filename: Expected '%s', got '%s'\n", i,
1786 materials[i].pTextureFilename, (char*)got_param->pValue);
1792 static char *strdupA(const char *p)
1794 char *ret;
1795 if (!p) return NULL;
1796 ret = HeapAlloc(GetProcessHeap(), 0, strlen(p) + 1);
1797 if (ret) strcpy(ret, p);
1798 return ret;
1801 static HRESULT CALLBACK ID3DXAllocateHierarchyImpl_DestroyFrame(ID3DXAllocateHierarchy *iface, LPD3DXFRAME frame)
1803 TRACECALLBACK("ID3DXAllocateHierarchyImpl_DestroyFrame(%p, %p)\n", iface, frame);
1804 if (frame) {
1805 HeapFree(GetProcessHeap(), 0, frame->Name);
1806 HeapFree(GetProcessHeap(), 0, frame);
1808 return D3D_OK;
1811 static HRESULT CALLBACK ID3DXAllocateHierarchyImpl_CreateFrame(ID3DXAllocateHierarchy *iface,
1812 const char *name, D3DXFRAME **new_frame)
1814 D3DXFRAME *frame;
1816 TRACECALLBACK("ID3DXAllocateHierarchyImpl_CreateFrame(%p, '%s', %p)\n", iface, name, new_frame);
1817 frame = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*frame));
1818 if (!frame)
1819 return E_OUTOFMEMORY;
1820 if (name) {
1821 frame->Name = strdupA(name);
1822 if (!frame->Name) {
1823 HeapFree(GetProcessHeap(), 0, frame);
1824 return E_OUTOFMEMORY;
1827 *new_frame = frame;
1828 return D3D_OK;
1831 static HRESULT destroy_mesh_container(LPD3DXMESHCONTAINER mesh_container)
1833 int i;
1835 if (!mesh_container)
1836 return D3D_OK;
1837 HeapFree(GetProcessHeap(), 0, mesh_container->Name);
1838 if (U(mesh_container->MeshData).pMesh)
1839 IUnknown_Release(U(mesh_container->MeshData).pMesh);
1840 if (mesh_container->pMaterials) {
1841 for (i = 0; i < mesh_container->NumMaterials; i++)
1842 HeapFree(GetProcessHeap(), 0, mesh_container->pMaterials[i].pTextureFilename);
1843 HeapFree(GetProcessHeap(), 0, mesh_container->pMaterials);
1845 if (mesh_container->pEffects) {
1846 for (i = 0; i < mesh_container->NumMaterials; i++) {
1847 HeapFree(GetProcessHeap(), 0, mesh_container->pEffects[i].pEffectFilename);
1848 if (mesh_container->pEffects[i].pDefaults) {
1849 int j;
1850 for (j = 0; j < mesh_container->pEffects[i].NumDefaults; j++) {
1851 HeapFree(GetProcessHeap(), 0, mesh_container->pEffects[i].pDefaults[j].pParamName);
1852 HeapFree(GetProcessHeap(), 0, mesh_container->pEffects[i].pDefaults[j].pValue);
1854 HeapFree(GetProcessHeap(), 0, mesh_container->pEffects[i].pDefaults);
1857 HeapFree(GetProcessHeap(), 0, mesh_container->pEffects);
1859 HeapFree(GetProcessHeap(), 0, mesh_container->pAdjacency);
1860 if (mesh_container->pSkinInfo)
1861 IUnknown_Release(mesh_container->pSkinInfo);
1862 HeapFree(GetProcessHeap(), 0, mesh_container);
1863 return D3D_OK;
1866 static HRESULT CALLBACK ID3DXAllocateHierarchyImpl_DestroyMeshContainer(ID3DXAllocateHierarchy *iface, LPD3DXMESHCONTAINER mesh_container)
1868 TRACECALLBACK("ID3DXAllocateHierarchyImpl_DestroyMeshContainer(%p, %p)\n", iface, mesh_container);
1869 return destroy_mesh_container(mesh_container);
1872 static HRESULT CALLBACK ID3DXAllocateHierarchyImpl_CreateMeshContainer(ID3DXAllocateHierarchy *iface,
1873 const char *name, const D3DXMESHDATA *mesh_data, const D3DXMATERIAL *materials,
1874 const D3DXEFFECTINSTANCE *effects, DWORD num_materials, const DWORD *adjacency,
1875 ID3DXSkinInfo *skin_info, D3DXMESHCONTAINER **new_mesh_container)
1877 LPD3DXMESHCONTAINER mesh_container = NULL;
1878 int i;
1880 TRACECALLBACK("ID3DXAllocateHierarchyImpl_CreateMeshContainer(%p, '%s', %u, %p, %p, %p, %d, %p, %p, %p)\n",
1881 iface, name, mesh_data->Type, U(*mesh_data).pMesh, materials, effects,
1882 num_materials, adjacency, skin_info, *new_mesh_container);
1884 mesh_container = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*mesh_container));
1885 if (!mesh_container)
1886 return E_OUTOFMEMORY;
1888 if (name) {
1889 mesh_container->Name = strdupA(name);
1890 if (!mesh_container->Name)
1891 goto error;
1894 mesh_container->NumMaterials = num_materials;
1895 if (num_materials) {
1896 mesh_container->pMaterials = HeapAlloc(GetProcessHeap(), 0, num_materials * sizeof(*materials));
1897 if (!mesh_container->pMaterials)
1898 goto error;
1900 memcpy(mesh_container->pMaterials, materials, num_materials * sizeof(*materials));
1901 for (i = 0; i < num_materials; i++)
1902 mesh_container->pMaterials[i].pTextureFilename = NULL;
1903 for (i = 0; i < num_materials; i++) {
1904 if (materials[i].pTextureFilename) {
1905 mesh_container->pMaterials[i].pTextureFilename = strdupA(materials[i].pTextureFilename);
1906 if (!mesh_container->pMaterials[i].pTextureFilename)
1907 goto error;
1911 mesh_container->pEffects = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, num_materials * sizeof(*effects));
1912 if (!mesh_container->pEffects)
1913 goto error;
1914 for (i = 0; i < num_materials; i++) {
1915 int j;
1916 const D3DXEFFECTINSTANCE *effect_src = &effects[i];
1917 D3DXEFFECTINSTANCE *effect_dest = &mesh_container->pEffects[i];
1919 if (effect_src->pEffectFilename) {
1920 effect_dest->pEffectFilename = strdupA(effect_src->pEffectFilename);
1921 if (!effect_dest->pEffectFilename)
1922 goto error;
1924 effect_dest->pDefaults = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1925 effect_src->NumDefaults * sizeof(*effect_src->pDefaults));
1926 if (!effect_dest->pDefaults)
1927 goto error;
1928 effect_dest->NumDefaults = effect_src->NumDefaults;
1929 for (j = 0; j < effect_src->NumDefaults; j++) {
1930 const D3DXEFFECTDEFAULT *default_src = &effect_src->pDefaults[j];
1931 D3DXEFFECTDEFAULT *default_dest = &effect_dest->pDefaults[j];
1933 if (default_src->pParamName) {
1934 default_dest->pParamName = strdupA(default_src->pParamName);
1935 if (!default_dest->pParamName)
1936 goto error;
1938 default_dest->NumBytes = default_src->NumBytes;
1939 default_dest->Type = default_src->Type;
1940 default_dest->pValue = HeapAlloc(GetProcessHeap(), 0, default_src->NumBytes);
1941 memcpy(default_dest->pValue, default_src->pValue, default_src->NumBytes);
1946 ok(adjacency != NULL, "Expected non-NULL adjacency, got NULL\n");
1947 if (adjacency) {
1948 if (mesh_data->Type == D3DXMESHTYPE_MESH || mesh_data->Type == D3DXMESHTYPE_PMESH) {
1949 ID3DXBaseMesh *basemesh = (ID3DXBaseMesh*)U(*mesh_data).pMesh;
1950 DWORD num_faces = basemesh->lpVtbl->GetNumFaces(basemesh);
1951 size_t size = num_faces * sizeof(DWORD) * 3;
1952 mesh_container->pAdjacency = HeapAlloc(GetProcessHeap(), 0, size);
1953 if (!mesh_container->pAdjacency)
1954 goto error;
1955 memcpy(mesh_container->pAdjacency, adjacency, size);
1956 } else {
1957 ok(mesh_data->Type == D3DXMESHTYPE_PATCHMESH, "Unknown mesh type %u\n", mesh_data->Type);
1958 if (mesh_data->Type == D3DXMESHTYPE_PATCHMESH)
1959 trace("FIXME: copying adjacency data for patch mesh not implemented\n");
1963 memcpy(&mesh_container->MeshData, mesh_data, sizeof(*mesh_data));
1964 if (U(*mesh_data).pMesh)
1965 IUnknown_AddRef(U(*mesh_data).pMesh);
1966 if (skin_info) {
1967 mesh_container->pSkinInfo = skin_info;
1968 skin_info->lpVtbl->AddRef(skin_info);
1970 *new_mesh_container = mesh_container;
1972 return S_OK;
1973 error:
1974 destroy_mesh_container(mesh_container);
1975 return E_OUTOFMEMORY;
1978 static ID3DXAllocateHierarchyVtbl ID3DXAllocateHierarchyImpl_Vtbl = {
1979 ID3DXAllocateHierarchyImpl_CreateFrame,
1980 ID3DXAllocateHierarchyImpl_CreateMeshContainer,
1981 ID3DXAllocateHierarchyImpl_DestroyFrame,
1982 ID3DXAllocateHierarchyImpl_DestroyMeshContainer,
1984 static ID3DXAllocateHierarchy alloc_hier = { &ID3DXAllocateHierarchyImpl_Vtbl };
1986 #define test_LoadMeshFromX(device, xfile_str, vertex_array, fvf, index_array, materials_array, check_adjacency) \
1987 test_LoadMeshFromX_(__LINE__, device, xfile_str, sizeof(xfile_str) - 1, vertex_array, ARRAY_SIZE(vertex_array), fvf, \
1988 index_array, ARRAY_SIZE(index_array), sizeof(*index_array), materials_array, ARRAY_SIZE(materials_array), \
1989 check_adjacency);
1990 static void test_LoadMeshFromX_(int line, IDirect3DDevice9 *device, const char *xfile_str, size_t xfile_strlen,
1991 const void *vertices, DWORD num_vertices, DWORD fvf, const void *indices, DWORD num_indices, size_t index_size,
1992 const D3DXMATERIAL *expected_materials, DWORD expected_num_materials, BOOL check_adjacency)
1994 HRESULT hr;
1995 ID3DXBuffer *materials = NULL;
1996 ID3DXBuffer *effects = NULL;
1997 ID3DXBuffer *adjacency = NULL;
1998 ID3DXMesh *mesh = NULL;
1999 DWORD num_materials = 0;
2001 /* Adjacency is not checked when the X file contains multiple meshes,
2002 * since calling GenerateAdjacency on the merged mesh is not equivalent
2003 * to calling GenerateAdjacency on the individual meshes and then merging
2004 * the adjacency data. */
2005 hr = D3DXLoadMeshFromXInMemory(xfile_str, xfile_strlen, D3DXMESH_MANAGED, device,
2006 check_adjacency ? &adjacency : NULL, &materials, &effects, &num_materials, &mesh);
2007 ok_(__FILE__,line)(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2008 if (SUCCEEDED(hr)) {
2009 D3DXMATERIAL *materials_ptr = materials ? ID3DXBuffer_GetBufferPointer(materials) : NULL;
2010 D3DXEFFECTINSTANCE *effects_ptr = effects ? ID3DXBuffer_GetBufferPointer(effects) : NULL;
2011 DWORD *adjacency_ptr = check_adjacency ? ID3DXBuffer_GetBufferPointer(adjacency) : NULL;
2013 check_vertex_buffer_(line, mesh, vertices, num_vertices, fvf);
2014 check_index_buffer_(line, mesh, indices, num_indices, index_size);
2015 check_materials_(line, materials_ptr, num_materials, expected_materials, expected_num_materials);
2016 check_generated_effects_(line, materials_ptr, num_materials, effects_ptr);
2017 if (check_adjacency)
2018 check_generated_adjacency_(line, mesh, adjacency_ptr, 0.0f);
2020 if (materials) ID3DXBuffer_Release(materials);
2021 if (effects) ID3DXBuffer_Release(effects);
2022 if (adjacency) ID3DXBuffer_Release(adjacency);
2023 IUnknown_Release(mesh);
2027 static void D3DXLoadMeshTest(void)
2029 static const char empty_xfile[] = "xof 0303txt 0032";
2030 /*________________________*/
2031 static const char simple_xfile[] =
2032 "xof 0303txt 0032"
2033 "Mesh {"
2034 "3;"
2035 "0.0; 0.0; 0.0;,"
2036 "0.0; 1.0; 0.0;,"
2037 "1.0; 1.0; 0.0;;"
2038 "1;"
2039 "3; 0, 1, 2;;"
2040 "}";
2041 static const WORD simple_index_buffer[] = {0, 1, 2};
2042 static const D3DXVECTOR3 simple_vertex_buffer[] = {
2043 {0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {1.0, 1.0, 0.0}
2045 const DWORD simple_fvf = D3DFVF_XYZ;
2046 static const char framed_xfile[] =
2047 "xof 0303txt 0032"
2048 "Frame {"
2049 "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;; }"
2050 "FrameTransformMatrix {" /* translation (0.0, 0.0, 2.0) */
2051 "1.0, 0.0, 0.0, 0.0,"
2052 "0.0, 1.0, 0.0, 0.0,"
2053 "0.0, 0.0, 1.0, 0.0,"
2054 "0.0, 0.0, 2.0, 1.0;;"
2056 "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;; }"
2057 "FrameTransformMatrix {" /* translation (0.0, 0.0, 3.0) */
2058 "1.0, 0.0, 0.0, 0.0,"
2059 "0.0, 1.0, 0.0, 0.0,"
2060 "0.0, 0.0, 1.0, 0.0,"
2061 "0.0, 0.0, 3.0, 1.0;;"
2063 "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;; }"
2064 "}";
2065 static const WORD framed_index_buffer[] = { 0, 1, 2 };
2066 static const D3DXVECTOR3 framed_vertex_buffers[3][3] = {
2067 {{0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {1.0, 1.0, 0.0}},
2068 {{0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {2.0, 1.0, 0.0}},
2069 {{0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {3.0, 1.0, 0.0}},
2071 static const WORD merged_index_buffer[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
2072 /* frame transforms accumulates for D3DXLoadMeshFromX */
2073 static const D3DXVECTOR3 merged_vertex_buffer[] = {
2074 {0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {1.0, 1.0, 0.0},
2075 {0.0, 0.0, 2.0}, {0.0, 1.0, 2.0}, {2.0, 1.0, 2.0},
2076 {0.0, 0.0, 5.0}, {0.0, 1.0, 5.0}, {3.0, 1.0, 5.0},
2078 const DWORD framed_fvf = D3DFVF_XYZ;
2079 /*________________________*/
2080 static const char box_xfile[] =
2081 "xof 0303txt 0032"
2082 "Mesh {"
2083 "8;" /* DWORD nVertices; */
2084 /* array Vector vertices[nVertices]; */
2085 "0.0; 0.0; 0.0;,"
2086 "0.0; 0.0; 1.0;,"
2087 "0.0; 1.0; 0.0;,"
2088 "0.0; 1.0; 1.0;,"
2089 "1.0; 0.0; 0.0;,"
2090 "1.0; 0.0; 1.0;,"
2091 "1.0; 1.0; 0.0;,"
2092 "1.0; 1.0; 1.0;;"
2093 "6;" /* DWORD nFaces; */
2094 /* array MeshFace faces[nFaces]; */
2095 "4; 0, 1, 3, 2;," /* (left side) */
2096 "4; 2, 3, 7, 6;," /* (top side) */
2097 "4; 6, 7, 5, 4;," /* (right side) */
2098 "4; 1, 0, 4, 5;," /* (bottom side) */
2099 "4; 1, 5, 7, 3;," /* (back side) */
2100 "4; 0, 2, 6, 4;;" /* (front side) */
2101 "MeshNormals {"
2102 "6;" /* DWORD nNormals; */
2103 /* array Vector normals[nNormals]; */
2104 "-1.0; 0.0; 0.0;,"
2105 "0.0; 1.0; 0.0;,"
2106 "1.0; 0.0; 0.0;,"
2107 "0.0; -1.0; 0.0;,"
2108 "0.0; 0.0; 1.0;,"
2109 "0.0; 0.0; -1.0;;"
2110 "6;" /* DWORD nFaceNormals; */
2111 /* array MeshFace faceNormals[nFaceNormals]; */
2112 "4; 0, 0, 0, 0;,"
2113 "4; 1, 1, 1, 1;,"
2114 "4; 2, 2, 2, 2;,"
2115 "4; 3, 3, 3, 3;,"
2116 "4; 4, 4, 4, 4;,"
2117 "4; 5, 5, 5, 5;;"
2119 "MeshMaterialList materials {"
2120 "2;" /* DWORD nMaterials; */
2121 "6;" /* DWORD nFaceIndexes; */
2122 /* array DWORD faceIndexes[nFaceIndexes]; */
2123 "0, 0, 0, 1, 1, 1;;"
2124 "Material {"
2125 /* ColorRGBA faceColor; */
2126 "0.0; 0.0; 1.0; 1.0;;"
2127 /* FLOAT power; */
2128 "0.5;"
2129 /* ColorRGB specularColor; */
2130 "1.0; 1.0; 1.0;;"
2131 /* ColorRGB emissiveColor; */
2132 "0.0; 0.0; 0.0;;"
2134 "Material {"
2135 /* ColorRGBA faceColor; */
2136 "1.0; 1.0; 1.0; 1.0;;"
2137 /* FLOAT power; */
2138 "1.0;"
2139 /* ColorRGB specularColor; */
2140 "1.0; 1.0; 1.0;;"
2141 /* ColorRGB emissiveColor; */
2142 "0.0; 0.0; 0.0;;"
2143 "TextureFilename { \"texture.jpg\"; }"
2146 "MeshVertexColors {"
2147 "8;" /* DWORD nVertexColors; */
2148 /* array IndexedColor vertexColors[nVertexColors]; */
2149 "0; 0.0; 0.0; 0.0; 0.0;;"
2150 "1; 0.0; 0.0; 1.0; 0.1;;"
2151 "2; 0.0; 1.0; 0.0; 0.2;;"
2152 "3; 0.0; 1.0; 1.0; 0.3;;"
2153 "4; 1.0; 0.0; 0.0; 0.4;;"
2154 "5; 1.0; 0.0; 1.0; 0.5;;"
2155 "6; 1.0; 1.0; 0.0; 0.6;;"
2156 "7; 1.0; 1.0; 1.0; 0.7;;"
2158 "MeshTextureCoords {"
2159 "8;" /* DWORD nTextureCoords; */
2160 /* array Coords2d textureCoords[nTextureCoords]; */
2161 "0.0; 1.0;,"
2162 "1.0; 1.0;,"
2163 "0.0; 0.0;,"
2164 "1.0; 0.0;,"
2165 "1.0; 1.0;,"
2166 "0.0; 1.0;,"
2167 "1.0; 0.0;,"
2168 "0.0; 0.0;;"
2170 "}";
2171 static const WORD box_index_buffer[] = {
2172 0, 1, 3,
2173 0, 3, 2,
2174 8, 9, 7,
2175 8, 7, 6,
2176 10, 11, 5,
2177 10, 5, 4,
2178 12, 13, 14,
2179 12, 14, 15,
2180 16, 17, 18,
2181 16, 18, 19,
2182 20, 21, 22,
2183 20, 22, 23,
2185 static const struct {
2186 D3DXVECTOR3 position;
2187 D3DXVECTOR3 normal;
2188 D3DCOLOR diffuse;
2189 D3DXVECTOR2 tex_coords;
2190 } box_vertex_buffer[] = {
2191 {{0.0, 0.0, 0.0}, {-1.0, 0.0, 0.0}, 0x00000000, {0.0, 1.0}},
2192 {{0.0, 0.0, 1.0}, {-1.0, 0.0, 0.0}, 0x1a0000ff, {1.0, 1.0}},
2193 {{0.0, 1.0, 0.0}, {-1.0, 0.0, 0.0}, 0x3300ff00, {0.0, 0.0}},
2194 {{0.0, 1.0, 1.0}, {-1.0, 0.0, 0.0}, 0x4d00ffff, {1.0, 0.0}},
2195 {{1.0, 0.0, 0.0}, {1.0, 0.0, 0.0}, 0x66ff0000, {1.0, 1.0}},
2196 {{1.0, 0.0, 1.0}, {1.0, 0.0, 0.0}, 0x80ff00ff, {0.0, 1.0}},
2197 {{1.0, 1.0, 0.0}, {0.0, 1.0, 0.0}, 0x99ffff00, {1.0, 0.0}},
2198 {{1.0, 1.0, 1.0}, {0.0, 1.0, 0.0}, 0xb3ffffff, {0.0, 0.0}},
2199 {{0.0, 1.0, 0.0}, {0.0, 1.0, 0.0}, 0x3300ff00, {0.0, 0.0}},
2200 {{0.0, 1.0, 1.0}, {0.0, 1.0, 0.0}, 0x4d00ffff, {1.0, 0.0}},
2201 {{1.0, 1.0, 0.0}, {1.0, 0.0, 0.0}, 0x99ffff00, {1.0, 0.0}},
2202 {{1.0, 1.0, 1.0}, {1.0, 0.0, 0.0}, 0xb3ffffff, {0.0, 0.0}},
2203 {{0.0, 0.0, 1.0}, {0.0, -1.0, 0.0}, 0x1a0000ff, {1.0, 1.0}},
2204 {{0.0, 0.0, 0.0}, {0.0, -1.0, 0.0}, 0x00000000, {0.0, 1.0}},
2205 {{1.0, 0.0, 0.0}, {0.0, -1.0, 0.0}, 0x66ff0000, {1.0, 1.0}},
2206 {{1.0, 0.0, 1.0}, {0.0, -1.0, 0.0}, 0x80ff00ff, {0.0, 1.0}},
2207 {{0.0, 0.0, 1.0}, {0.0, 0.0, 1.0}, 0x1a0000ff, {1.0, 1.0}},
2208 {{1.0, 0.0, 1.0}, {0.0, 0.0, 1.0}, 0x80ff00ff, {0.0, 1.0}},
2209 {{1.0, 1.0, 1.0}, {0.0, 0.0, 1.0}, 0xb3ffffff, {0.0, 0.0}},
2210 {{0.0, 1.0, 1.0}, {0.0, 0.0, 1.0}, 0x4d00ffff, {1.0, 0.0}},
2211 {{0.0, 0.0, 0.0}, {0.0, 0.0, -1.0}, 0x00000000, {0.0, 1.0}},
2212 {{0.0, 1.0, 0.0}, {0.0, 0.0, -1.0}, 0x3300ff00, {0.0, 0.0}},
2213 {{1.0, 1.0, 0.0}, {0.0, 0.0, -1.0}, 0x99ffff00, {1.0, 0.0}},
2214 {{1.0, 0.0, 0.0}, {0.0, 0.0, -1.0}, 0x66ff0000, {1.0, 1.0}},
2216 static const D3DXMATERIAL box_materials[] = {
2219 {0.0, 0.0, 1.0, 1.0}, /* Diffuse */
2220 {0.0, 0.0, 0.0, 1.0}, /* Ambient */
2221 {1.0, 1.0, 1.0, 1.0}, /* Specular */
2222 {0.0, 0.0, 0.0, 1.0}, /* Emissive */
2223 0.5, /* Power */
2225 NULL, /* pTextureFilename */
2229 {1.0, 1.0, 1.0, 1.0}, /* Diffuse */
2230 {0.0, 0.0, 0.0, 1.0}, /* Ambient */
2231 {1.0, 1.0, 1.0, 1.0}, /* Specular */
2232 {0.0, 0.0, 0.0, 1.0}, /* Emissive */
2233 1.0, /* Power */
2235 (char *)"texture.jpg", /* pTextureFilename */
2238 const DWORD box_fvf = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_TEX1;
2239 /*________________________*/
2240 static const D3DXMATERIAL default_materials[] = {
2243 {0.5, 0.5, 0.5, 0.0}, /* Diffuse */
2244 {0.0, 0.0, 0.0, 0.0}, /* Ambient */
2245 {0.5, 0.5, 0.5, 0.0}, /* Specular */
2246 {0.0, 0.0, 0.0, 0.0}, /* Emissive */
2247 0.0, /* Power */
2249 NULL, /* pTextureFilename */
2252 HRESULT hr;
2253 HWND wnd = NULL;
2254 IDirect3D9 *d3d = NULL;
2255 IDirect3DDevice9 *device = NULL;
2256 D3DPRESENT_PARAMETERS d3dpp;
2257 ID3DXMesh *mesh = NULL;
2258 D3DXFRAME *frame_hier = NULL;
2259 D3DXMATRIX transform;
2261 if (!(wnd = CreateWindowA("static", "d3dx9_test", WS_POPUP, 0, 0, 1000, 1000, NULL, NULL, NULL, NULL)))
2263 skip("Couldn't create application window\n");
2264 return;
2266 d3d = Direct3DCreate9(D3D_SDK_VERSION);
2267 if (!d3d)
2269 skip("Couldn't create IDirect3D9 object\n");
2270 goto cleanup;
2273 ZeroMemory(&d3dpp, sizeof(d3dpp));
2274 d3dpp.Windowed = TRUE;
2275 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2276 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, wnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device);
2277 if (FAILED(hr))
2279 skip("Failed to create IDirect3DDevice9 object %#x\n", hr);
2280 goto cleanup;
2283 hr = D3DXLoadMeshHierarchyFromXInMemory(NULL, sizeof(simple_xfile) - 1,
2284 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
2285 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2287 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, 0,
2288 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
2289 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2291 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1,
2292 D3DXMESH_MANAGED, NULL, &alloc_hier, NULL, &frame_hier, NULL);
2293 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2295 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1,
2296 D3DXMESH_MANAGED, device, NULL, NULL, &frame_hier, NULL);
2297 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2299 hr = D3DXLoadMeshHierarchyFromXInMemory(empty_xfile, sizeof(empty_xfile) - 1,
2300 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
2301 ok(hr == E_FAIL, "Expected E_FAIL, got %#x\n", hr);
2303 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1,
2304 D3DXMESH_MANAGED, device, &alloc_hier, NULL, NULL, NULL);
2305 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2307 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1,
2308 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
2309 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2310 if (SUCCEEDED(hr)) {
2311 D3DXMESHCONTAINER *container = frame_hier->pMeshContainer;
2313 ok(frame_hier->Name == NULL, "Expected NULL, got '%s'\n", frame_hier->Name);
2314 D3DXMatrixIdentity(&transform);
2315 check_matrix(&frame_hier->TransformationMatrix, &transform);
2317 ok(!strcmp(container->Name, ""), "Expected '', got '%s'\n", container->Name);
2318 ok(container->MeshData.Type == D3DXMESHTYPE_MESH, "Expected %d, got %d\n",
2319 D3DXMESHTYPE_MESH, container->MeshData.Type);
2320 mesh = U(container->MeshData).pMesh;
2321 check_vertex_buffer(mesh, simple_vertex_buffer, ARRAY_SIZE(simple_vertex_buffer), simple_fvf);
2322 check_index_buffer(mesh, simple_index_buffer, ARRAY_SIZE(simple_index_buffer), sizeof(*simple_index_buffer));
2323 check_materials(container->pMaterials, container->NumMaterials, NULL, 0);
2324 check_generated_effects(container->pMaterials, container->NumMaterials, container->pEffects);
2325 check_generated_adjacency(mesh, container->pAdjacency, 0.0f);
2326 hr = D3DXFrameDestroy(frame_hier, &alloc_hier);
2327 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2328 frame_hier = NULL;
2331 hr = D3DXLoadMeshHierarchyFromXInMemory(box_xfile, sizeof(box_xfile) - 1,
2332 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
2333 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2334 if (SUCCEEDED(hr)) {
2335 D3DXMESHCONTAINER *container = frame_hier->pMeshContainer;
2337 ok(frame_hier->Name == NULL, "Expected NULL, got '%s'\n", frame_hier->Name);
2338 D3DXMatrixIdentity(&transform);
2339 check_matrix(&frame_hier->TransformationMatrix, &transform);
2341 ok(!strcmp(container->Name, ""), "Expected '', got '%s'\n", container->Name);
2342 ok(container->MeshData.Type == D3DXMESHTYPE_MESH, "Expected %d, got %d\n",
2343 D3DXMESHTYPE_MESH, container->MeshData.Type);
2344 mesh = U(container->MeshData).pMesh;
2345 check_vertex_buffer(mesh, box_vertex_buffer, ARRAY_SIZE(box_vertex_buffer), box_fvf);
2346 check_index_buffer(mesh, box_index_buffer, ARRAY_SIZE(box_index_buffer), sizeof(*box_index_buffer));
2347 check_materials(container->pMaterials, container->NumMaterials, box_materials, ARRAY_SIZE(box_materials));
2348 check_generated_effects(container->pMaterials, container->NumMaterials, container->pEffects);
2349 check_generated_adjacency(mesh, container->pAdjacency, 0.0f);
2350 hr = D3DXFrameDestroy(frame_hier, &alloc_hier);
2351 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2352 frame_hier = NULL;
2355 hr = D3DXLoadMeshHierarchyFromXInMemory(framed_xfile, sizeof(framed_xfile) - 1,
2356 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
2357 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2358 if (SUCCEEDED(hr)) {
2359 D3DXMESHCONTAINER *container = frame_hier->pMeshContainer;
2360 int i;
2362 ok(!strcmp(frame_hier->Name, ""), "Expected '', got '%s'\n", frame_hier->Name);
2363 /* last frame transform replaces the first */
2364 D3DXMatrixIdentity(&transform);
2365 U(transform).m[3][2] = 3.0;
2366 check_matrix(&frame_hier->TransformationMatrix, &transform);
2368 for (i = 0; i < 3; i++) {
2369 ok(!strcmp(container->Name, ""), "Expected '', got '%s'\n", container->Name);
2370 ok(container->MeshData.Type == D3DXMESHTYPE_MESH, "Expected %d, got %d\n",
2371 D3DXMESHTYPE_MESH, container->MeshData.Type);
2372 mesh = U(container->MeshData).pMesh;
2373 check_vertex_buffer(mesh, framed_vertex_buffers[i], ARRAY_SIZE(framed_vertex_buffers[0]), framed_fvf);
2374 check_index_buffer(mesh, framed_index_buffer, ARRAY_SIZE(framed_index_buffer), sizeof(*framed_index_buffer));
2375 check_materials(container->pMaterials, container->NumMaterials, NULL, 0);
2376 check_generated_effects(container->pMaterials, container->NumMaterials, container->pEffects);
2377 check_generated_adjacency(mesh, container->pAdjacency, 0.0f);
2378 container = container->pNextMeshContainer;
2380 ok(container == NULL, "Expected NULL, got %p\n", container);
2381 hr = D3DXFrameDestroy(frame_hier, &alloc_hier);
2382 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2383 frame_hier = NULL;
2387 hr = D3DXLoadMeshFromXInMemory(NULL, 0, D3DXMESH_MANAGED,
2388 device, NULL, NULL, NULL, NULL, &mesh);
2389 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2391 hr = D3DXLoadMeshFromXInMemory(NULL, sizeof(simple_xfile) - 1, D3DXMESH_MANAGED,
2392 device, NULL, NULL, NULL, NULL, &mesh);
2393 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2395 hr = D3DXLoadMeshFromXInMemory(simple_xfile, 0, D3DXMESH_MANAGED,
2396 device, NULL, NULL, NULL, NULL, &mesh);
2397 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2399 hr = D3DXLoadMeshFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1, D3DXMESH_MANAGED,
2400 device, NULL, NULL, NULL, NULL, NULL);
2401 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2403 hr = D3DXLoadMeshFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1, D3DXMESH_MANAGED,
2404 NULL, NULL, NULL, NULL, NULL, &mesh);
2405 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2407 hr = D3DXLoadMeshFromXInMemory(empty_xfile, sizeof(empty_xfile) - 1, D3DXMESH_MANAGED,
2408 device, NULL, NULL, NULL, NULL, &mesh);
2409 ok(hr == E_FAIL, "Expected E_FAIL, got %#x\n", hr);
2411 hr = D3DXLoadMeshFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1, D3DXMESH_MANAGED,
2412 device, NULL, NULL, NULL, NULL, &mesh);
2413 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2414 if (SUCCEEDED(hr))
2415 IUnknown_Release(mesh);
2417 test_LoadMeshFromX(device, simple_xfile, simple_vertex_buffer, simple_fvf, simple_index_buffer, default_materials, TRUE);
2418 test_LoadMeshFromX(device, box_xfile, box_vertex_buffer, box_fvf, box_index_buffer, box_materials, TRUE);
2419 test_LoadMeshFromX(device, framed_xfile, merged_vertex_buffer, framed_fvf, merged_index_buffer, default_materials, FALSE);
2421 cleanup:
2422 if (device) IDirect3DDevice9_Release(device);
2423 if (d3d) IDirect3D9_Release(d3d);
2424 if (wnd) DestroyWindow(wnd);
2427 static void D3DXCreateBoxTest(void)
2429 HRESULT hr;
2430 HWND wnd;
2431 WNDCLASSA wc = {0};
2432 IDirect3D9* d3d;
2433 IDirect3DDevice9* device;
2434 D3DPRESENT_PARAMETERS d3dpp;
2435 ID3DXMesh* box;
2436 ID3DXBuffer* ppBuffer;
2437 DWORD *buffer;
2438 static const DWORD adjacency[36]=
2439 {6, 9, 1, 2, 10, 0,
2440 1, 9, 3, 4, 10, 2,
2441 3, 8, 5, 7, 11, 4,
2442 0, 11, 7, 5, 8, 6,
2443 7, 4, 9, 2, 0, 8,
2444 1, 3, 11, 5, 6, 10};
2445 unsigned int i;
2447 wc.lpfnWndProc = DefWindowProcA;
2448 wc.lpszClassName = "d3dx9_test_wc";
2449 if (!RegisterClassA(&wc))
2451 skip("RegisterClass failed\n");
2452 return;
2455 wnd = CreateWindowA("d3dx9_test_wc", "d3dx9_test", WS_OVERLAPPEDWINDOW,
2456 0, 0, 640, 480, 0, 0, 0, 0);
2457 ok(wnd != NULL, "Expected to have a window, received NULL\n");
2458 if (!wnd)
2460 skip("Couldn't create application window\n");
2461 return;
2464 d3d = Direct3DCreate9(D3D_SDK_VERSION);
2465 if (!d3d)
2467 skip("Couldn't create IDirect3D9 object\n");
2468 DestroyWindow(wnd);
2469 return;
2472 memset(&d3dpp, 0, sizeof(d3dpp));
2473 d3dpp.Windowed = TRUE;
2474 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2475 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, wnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device);
2476 if (FAILED(hr))
2478 skip("Failed to create IDirect3DDevice9 object %#x\n", hr);
2479 IDirect3D9_Release(d3d);
2480 DestroyWindow(wnd);
2481 return;
2484 hr = D3DXCreateBox(device,2.0f,20.0f,4.9f,NULL, &ppBuffer);
2485 ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2487 hr = D3DXCreateBox(NULL,22.0f,20.0f,4.9f,&box, &ppBuffer);
2488 ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2490 hr = D3DXCreateBox(device,-2.0f,20.0f,4.9f,&box, &ppBuffer);
2491 ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2493 hr = D3DXCreateBox(device,22.0f,-20.0f,4.9f,&box, &ppBuffer);
2494 ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2496 hr = D3DXCreateBox(device,22.0f,20.0f,-4.9f,&box, &ppBuffer);
2497 ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2499 ppBuffer = NULL;
2500 hr = D3DXCreateBox(device,10.9f,20.0f,4.9f,&box, &ppBuffer);
2501 ok(hr==D3D_OK, "Expected D3D_OK, received %#x\n", hr);
2503 if (FAILED(hr))
2505 skip("D3DXCreateBox failed\n");
2506 goto end;
2509 buffer = ID3DXBuffer_GetBufferPointer(ppBuffer);
2510 for(i=0; i<36; i++)
2511 ok(adjacency[i]==buffer[i], "expected adjacency %d: %#x, received %#x\n",i,adjacency[i], buffer[i]);
2513 box->lpVtbl->Release(box);
2515 end:
2516 IDirect3DDevice9_Release(device);
2517 IDirect3D9_Release(d3d);
2518 if (ppBuffer) ID3DXBuffer_Release(ppBuffer);
2519 DestroyWindow(wnd);
2522 struct sincos_table
2524 float *sin;
2525 float *cos;
2528 static void free_sincos_table(struct sincos_table *sincos_table)
2530 HeapFree(GetProcessHeap(), 0, sincos_table->cos);
2531 HeapFree(GetProcessHeap(), 0, sincos_table->sin);
2534 /* pre compute sine and cosine tables; caller must free */
2535 static BOOL compute_sincos_table(struct sincos_table *sincos_table, float angle_start, float angle_step, int n)
2537 float angle;
2538 int i;
2540 sincos_table->sin = HeapAlloc(GetProcessHeap(), 0, n * sizeof(*sincos_table->sin));
2541 if (!sincos_table->sin)
2543 return FALSE;
2545 sincos_table->cos = HeapAlloc(GetProcessHeap(), 0, n * sizeof(*sincos_table->cos));
2546 if (!sincos_table->cos)
2548 HeapFree(GetProcessHeap(), 0, sincos_table->sin);
2549 return FALSE;
2552 angle = angle_start;
2553 for (i = 0; i < n; i++)
2555 sincos_table->sin[i] = sin(angle);
2556 sincos_table->cos[i] = cos(angle);
2557 angle += angle_step;
2560 return TRUE;
2563 static WORD vertex_index(UINT slices, int slice, int stack)
2565 return stack*slices+slice+1;
2568 /* slices = subdivisions along xy plane, stacks = subdivisions along z axis */
2569 static BOOL compute_sphere(struct mesh *mesh, FLOAT radius, UINT slices, UINT stacks)
2571 float theta_step, theta_start;
2572 struct sincos_table theta;
2573 float phi_step, phi_start;
2574 struct sincos_table phi;
2575 DWORD number_of_vertices, number_of_faces;
2576 DWORD vertex, face;
2577 int slice, stack;
2579 /* theta = angle on xy plane wrt x axis */
2580 theta_step = D3DX_PI / stacks;
2581 theta_start = theta_step;
2583 /* phi = angle on xz plane wrt z axis */
2584 phi_step = -2 * D3DX_PI / slices;
2585 phi_start = D3DX_PI / 2;
2587 if (!compute_sincos_table(&theta, theta_start, theta_step, stacks))
2589 return FALSE;
2591 if (!compute_sincos_table(&phi, phi_start, phi_step, slices))
2593 free_sincos_table(&theta);
2594 return FALSE;
2597 number_of_vertices = 2 + slices * (stacks-1);
2598 number_of_faces = 2 * slices + (stacks - 2) * (2 * slices);
2600 if (!new_mesh(mesh, number_of_vertices, number_of_faces))
2602 free_sincos_table(&phi);
2603 free_sincos_table(&theta);
2604 return FALSE;
2607 vertex = 0;
2608 face = 0;
2610 mesh->vertices[vertex].normal.x = 0.0f;
2611 mesh->vertices[vertex].normal.y = 0.0f;
2612 mesh->vertices[vertex].normal.z = 1.0f;
2613 mesh->vertices[vertex].position.x = 0.0f;
2614 mesh->vertices[vertex].position.y = 0.0f;
2615 mesh->vertices[vertex].position.z = radius;
2616 vertex++;
2618 for (stack = 0; stack < stacks - 1; stack++)
2620 for (slice = 0; slice < slices; slice++)
2622 mesh->vertices[vertex].normal.x = theta.sin[stack] * phi.cos[slice];
2623 mesh->vertices[vertex].normal.y = theta.sin[stack] * phi.sin[slice];
2624 mesh->vertices[vertex].normal.z = theta.cos[stack];
2625 mesh->vertices[vertex].position.x = radius * theta.sin[stack] * phi.cos[slice];
2626 mesh->vertices[vertex].position.y = radius * theta.sin[stack] * phi.sin[slice];
2627 mesh->vertices[vertex].position.z = radius * theta.cos[stack];
2628 vertex++;
2630 if (slice > 0)
2632 if (stack == 0)
2634 /* top stack is triangle fan */
2635 mesh->faces[face][0] = 0;
2636 mesh->faces[face][1] = slice + 1;
2637 mesh->faces[face][2] = slice;
2638 face++;
2640 else
2642 /* stacks in between top and bottom are quad strips */
2643 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
2644 mesh->faces[face][1] = vertex_index(slices, slice, stack-1);
2645 mesh->faces[face][2] = vertex_index(slices, slice-1, stack);
2646 face++;
2648 mesh->faces[face][0] = vertex_index(slices, slice, stack-1);
2649 mesh->faces[face][1] = vertex_index(slices, slice, stack);
2650 mesh->faces[face][2] = vertex_index(slices, slice-1, stack);
2651 face++;
2656 if (stack == 0)
2658 mesh->faces[face][0] = 0;
2659 mesh->faces[face][1] = 1;
2660 mesh->faces[face][2] = slice;
2661 face++;
2663 else
2665 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
2666 mesh->faces[face][1] = vertex_index(slices, 0, stack-1);
2667 mesh->faces[face][2] = vertex_index(slices, slice-1, stack);
2668 face++;
2670 mesh->faces[face][0] = vertex_index(slices, 0, stack-1);
2671 mesh->faces[face][1] = vertex_index(slices, 0, stack);
2672 mesh->faces[face][2] = vertex_index(slices, slice-1, stack);
2673 face++;
2677 mesh->vertices[vertex].position.x = 0.0f;
2678 mesh->vertices[vertex].position.y = 0.0f;
2679 mesh->vertices[vertex].position.z = -radius;
2680 mesh->vertices[vertex].normal.x = 0.0f;
2681 mesh->vertices[vertex].normal.y = 0.0f;
2682 mesh->vertices[vertex].normal.z = -1.0f;
2684 /* bottom stack is triangle fan */
2685 for (slice = 1; slice < slices; slice++)
2687 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
2688 mesh->faces[face][1] = vertex_index(slices, slice, stack-1);
2689 mesh->faces[face][2] = vertex;
2690 face++;
2693 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
2694 mesh->faces[face][1] = vertex_index(slices, 0, stack-1);
2695 mesh->faces[face][2] = vertex;
2697 free_sincos_table(&phi);
2698 free_sincos_table(&theta);
2700 return TRUE;
2703 static void test_sphere(IDirect3DDevice9 *device, FLOAT radius, UINT slices, UINT stacks)
2705 HRESULT hr;
2706 ID3DXMesh *sphere;
2707 struct mesh mesh;
2708 char name[256];
2710 hr = D3DXCreateSphere(device, radius, slices, stacks, &sphere, NULL);
2711 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
2712 if (hr != D3D_OK)
2714 skip("Couldn't create sphere\n");
2715 return;
2718 if (!compute_sphere(&mesh, radius, slices, stacks))
2720 skip("Couldn't create mesh\n");
2721 sphere->lpVtbl->Release(sphere);
2722 return;
2725 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
2727 sprintf(name, "sphere (%g, %u, %u)", radius, slices, stacks);
2728 compare_mesh(name, sphere, &mesh);
2730 free_mesh(&mesh);
2732 sphere->lpVtbl->Release(sphere);
2735 static void D3DXCreateSphereTest(void)
2737 HRESULT hr;
2738 HWND wnd;
2739 IDirect3D9* d3d;
2740 IDirect3DDevice9* device;
2741 D3DPRESENT_PARAMETERS d3dpp;
2742 ID3DXMesh* sphere = NULL;
2744 hr = D3DXCreateSphere(NULL, 0.0f, 0, 0, NULL, NULL);
2745 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
2747 hr = D3DXCreateSphere(NULL, 0.1f, 0, 0, NULL, NULL);
2748 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
2750 hr = D3DXCreateSphere(NULL, 0.0f, 1, 0, NULL, NULL);
2751 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
2753 hr = D3DXCreateSphere(NULL, 0.0f, 0, 1, NULL, NULL);
2754 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
2756 if (!(wnd = CreateWindowA("static", "d3dx9_test", WS_OVERLAPPEDWINDOW, 0, 0,
2757 640, 480, NULL, NULL, NULL, NULL)))
2759 skip("Couldn't create application window\n");
2760 return;
2762 if (!(d3d = Direct3DCreate9(D3D_SDK_VERSION)))
2764 skip("Couldn't create IDirect3D9 object\n");
2765 DestroyWindow(wnd);
2766 return;
2769 ZeroMemory(&d3dpp, sizeof(d3dpp));
2770 d3dpp.Windowed = TRUE;
2771 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2772 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, wnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device);
2773 if (FAILED(hr))
2775 skip("Failed to create IDirect3DDevice9 object %#x\n", hr);
2776 IDirect3D9_Release(d3d);
2777 DestroyWindow(wnd);
2778 return;
2781 hr = D3DXCreateSphere(device, 1.0f, 1, 1, &sphere, NULL);
2782 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
2784 hr = D3DXCreateSphere(device, 1.0f, 2, 1, &sphere, NULL);
2785 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
2787 hr = D3DXCreateSphere(device, 1.0f, 1, 2, &sphere, NULL);
2788 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
2790 hr = D3DXCreateSphere(device, -0.1f, 1, 2, &sphere, NULL);
2791 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
2793 test_sphere(device, 0.0f, 2, 2);
2794 test_sphere(device, 1.0f, 2, 2);
2795 test_sphere(device, 1.0f, 3, 2);
2796 test_sphere(device, 1.0f, 4, 4);
2797 test_sphere(device, 1.0f, 3, 4);
2798 test_sphere(device, 5.0f, 6, 7);
2799 test_sphere(device, 10.0f, 11, 12);
2801 IDirect3DDevice9_Release(device);
2802 IDirect3D9_Release(d3d);
2803 DestroyWindow(wnd);
2806 static BOOL compute_cylinder(struct mesh *mesh, FLOAT radius1, FLOAT radius2, FLOAT length, UINT slices, UINT stacks)
2808 float theta_step, theta_start;
2809 struct sincos_table theta;
2810 FLOAT delta_radius, radius, radius_step;
2811 FLOAT z, z_step, z_normal;
2812 DWORD number_of_vertices, number_of_faces;
2813 DWORD vertex, face;
2814 int slice, stack;
2816 /* theta = angle on xy plane wrt x axis */
2817 theta_step = -2 * D3DX_PI / slices;
2818 theta_start = D3DX_PI / 2;
2820 if (!compute_sincos_table(&theta, theta_start, theta_step, slices))
2822 return FALSE;
2825 number_of_vertices = 2 + (slices * (3 + stacks));
2826 number_of_faces = 2 * slices + stacks * (2 * slices);
2828 if (!new_mesh(mesh, number_of_vertices, number_of_faces))
2830 free_sincos_table(&theta);
2831 return FALSE;
2834 vertex = 0;
2835 face = 0;
2837 delta_radius = radius1 - radius2;
2838 radius = radius1;
2839 radius_step = delta_radius / stacks;
2841 z = -length / 2;
2842 z_step = length / stacks;
2843 z_normal = delta_radius / length;
2844 if (isnan(z_normal))
2846 z_normal = 0.0f;
2849 mesh->vertices[vertex].normal.x = 0.0f;
2850 mesh->vertices[vertex].normal.y = 0.0f;
2851 mesh->vertices[vertex].normal.z = -1.0f;
2852 mesh->vertices[vertex].position.x = 0.0f;
2853 mesh->vertices[vertex].position.y = 0.0f;
2854 mesh->vertices[vertex++].position.z = z;
2856 for (slice = 0; slice < slices; slice++, vertex++)
2858 mesh->vertices[vertex].normal.x = 0.0f;
2859 mesh->vertices[vertex].normal.y = 0.0f;
2860 mesh->vertices[vertex].normal.z = -1.0f;
2861 mesh->vertices[vertex].position.x = radius * theta.cos[slice];
2862 mesh->vertices[vertex].position.y = radius * theta.sin[slice];
2863 mesh->vertices[vertex].position.z = z;
2865 if (slice > 0)
2867 mesh->faces[face][0] = 0;
2868 mesh->faces[face][1] = slice;
2869 mesh->faces[face++][2] = slice + 1;
2873 mesh->faces[face][0] = 0;
2874 mesh->faces[face][1] = slice;
2875 mesh->faces[face++][2] = 1;
2877 for (stack = 1; stack <= stacks+1; stack++)
2879 for (slice = 0; slice < slices; slice++, vertex++)
2881 mesh->vertices[vertex].normal.x = theta.cos[slice];
2882 mesh->vertices[vertex].normal.y = theta.sin[slice];
2883 mesh->vertices[vertex].normal.z = z_normal;
2884 D3DXVec3Normalize(&mesh->vertices[vertex].normal, &mesh->vertices[vertex].normal);
2885 mesh->vertices[vertex].position.x = radius * theta.cos[slice];
2886 mesh->vertices[vertex].position.y = radius * theta.sin[slice];
2887 mesh->vertices[vertex].position.z = z;
2889 if (stack > 1 && slice > 0)
2891 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
2892 mesh->faces[face][1] = vertex_index(slices, slice-1, stack);
2893 mesh->faces[face++][2] = vertex_index(slices, slice, stack-1);
2895 mesh->faces[face][0] = vertex_index(slices, slice, stack-1);
2896 mesh->faces[face][1] = vertex_index(slices, slice-1, stack);
2897 mesh->faces[face++][2] = vertex_index(slices, slice, stack);
2901 if (stack > 1)
2903 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
2904 mesh->faces[face][1] = vertex_index(slices, slice-1, stack);
2905 mesh->faces[face++][2] = vertex_index(slices, 0, stack-1);
2907 mesh->faces[face][0] = vertex_index(slices, 0, stack-1);
2908 mesh->faces[face][1] = vertex_index(slices, slice-1, stack);
2909 mesh->faces[face++][2] = vertex_index(slices, 0, stack);
2912 if (stack < stacks + 1)
2914 z += z_step;
2915 radius -= radius_step;
2919 for (slice = 0; slice < slices; slice++, vertex++)
2921 mesh->vertices[vertex].normal.x = 0.0f;
2922 mesh->vertices[vertex].normal.y = 0.0f;
2923 mesh->vertices[vertex].normal.z = 1.0f;
2924 mesh->vertices[vertex].position.x = radius * theta.cos[slice];
2925 mesh->vertices[vertex].position.y = radius * theta.sin[slice];
2926 mesh->vertices[vertex].position.z = z;
2928 if (slice > 0)
2930 mesh->faces[face][0] = vertex_index(slices, slice-1, stack);
2931 mesh->faces[face][1] = number_of_vertices - 1;
2932 mesh->faces[face++][2] = vertex_index(slices, slice, stack);
2936 mesh->vertices[vertex].position.x = 0.0f;
2937 mesh->vertices[vertex].position.y = 0.0f;
2938 mesh->vertices[vertex].position.z = z;
2939 mesh->vertices[vertex].normal.x = 0.0f;
2940 mesh->vertices[vertex].normal.y = 0.0f;
2941 mesh->vertices[vertex].normal.z = 1.0f;
2943 mesh->faces[face][0] = vertex_index(slices, slice-1, stack);
2944 mesh->faces[face][1] = number_of_vertices - 1;
2945 mesh->faces[face][2] = vertex_index(slices, 0, stack);
2947 free_sincos_table(&theta);
2949 return TRUE;
2952 static void test_cylinder(IDirect3DDevice9 *device, FLOAT radius1, FLOAT radius2, FLOAT length, UINT slices, UINT stacks)
2954 HRESULT hr;
2955 ID3DXMesh *cylinder;
2956 struct mesh mesh;
2957 char name[256];
2959 hr = D3DXCreateCylinder(device, radius1, radius2, length, slices, stacks, &cylinder, NULL);
2960 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
2961 if (hr != D3D_OK)
2963 skip("Couldn't create cylinder\n");
2964 return;
2967 if (!compute_cylinder(&mesh, radius1, radius2, length, slices, stacks))
2969 skip("Couldn't create mesh\n");
2970 cylinder->lpVtbl->Release(cylinder);
2971 return;
2974 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
2976 sprintf(name, "cylinder (%g, %g, %g, %u, %u)", radius1, radius2, length, slices, stacks);
2977 compare_mesh(name, cylinder, &mesh);
2979 free_mesh(&mesh);
2981 cylinder->lpVtbl->Release(cylinder);
2984 static void D3DXCreateCylinderTest(void)
2986 HRESULT hr;
2987 HWND wnd;
2988 IDirect3D9* d3d;
2989 IDirect3DDevice9* device;
2990 D3DPRESENT_PARAMETERS d3dpp;
2991 ID3DXMesh* cylinder = NULL;
2993 hr = D3DXCreateCylinder(NULL, 0.0f, 0.0f, 0.0f, 0, 0, NULL, NULL);
2994 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
2996 hr = D3DXCreateCylinder(NULL, 1.0f, 1.0f, 1.0f, 2, 1, &cylinder, NULL);
2997 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
2999 if (!(wnd = CreateWindowA("static", "d3dx9_test", WS_OVERLAPPEDWINDOW, 0, 0,
3000 640, 480, NULL, NULL, NULL, NULL)))
3002 skip("Couldn't create application window\n");
3003 return;
3005 if (!(d3d = Direct3DCreate9(D3D_SDK_VERSION)))
3007 skip("Couldn't create IDirect3D9 object\n");
3008 DestroyWindow(wnd);
3009 return;
3012 ZeroMemory(&d3dpp, sizeof(d3dpp));
3013 d3dpp.Windowed = TRUE;
3014 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
3015 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, wnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device);
3016 if (FAILED(hr))
3018 skip("Failed to create IDirect3DDevice9 object %#x\n", hr);
3019 IDirect3D9_Release(d3d);
3020 DestroyWindow(wnd);
3021 return;
3024 hr = D3DXCreateCylinder(device, -0.1f, 1.0f, 1.0f, 2, 1, &cylinder, NULL);
3025 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3027 hr = D3DXCreateCylinder(device, 0.0f, 1.0f, 1.0f, 2, 1, &cylinder, NULL);
3028 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n",hr);
3030 if (SUCCEEDED(hr) && cylinder)
3032 cylinder->lpVtbl->Release(cylinder);
3035 hr = D3DXCreateCylinder(device, 1.0f, -0.1f, 1.0f, 2, 1, &cylinder, NULL);
3036 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3038 hr = D3DXCreateCylinder(device, 1.0f, 0.0f, 1.0f, 2, 1, &cylinder, NULL);
3039 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n",hr);
3041 if (SUCCEEDED(hr) && cylinder)
3043 cylinder->lpVtbl->Release(cylinder);
3046 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, -0.1f, 2, 1, &cylinder, NULL);
3047 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3049 /* Test with length == 0.0f succeeds */
3050 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, 0.0f, 2, 1, &cylinder, NULL);
3051 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n",hr);
3053 if (SUCCEEDED(hr) && cylinder)
3055 cylinder->lpVtbl->Release(cylinder);
3058 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, 1.0f, 1, 1, &cylinder, NULL);
3059 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3061 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, 1.0f, 2, 0, &cylinder, NULL);
3062 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3064 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, 1.0f, 2, 1, NULL, NULL);
3065 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3067 test_cylinder(device, 0.0f, 0.0f, 0.0f, 2, 1);
3068 test_cylinder(device, 1.0f, 1.0f, 1.0f, 2, 1);
3069 test_cylinder(device, 1.0f, 1.0f, 2.0f, 3, 4);
3070 test_cylinder(device, 3.0f, 2.0f, 4.0f, 3, 4);
3071 test_cylinder(device, 2.0f, 3.0f, 4.0f, 3, 4);
3072 test_cylinder(device, 3.0f, 4.0f, 5.0f, 11, 20);
3074 IDirect3DDevice9_Release(device);
3075 IDirect3D9_Release(d3d);
3076 DestroyWindow(wnd);
3079 struct dynamic_array
3081 int count, capacity;
3082 void *items;
3085 enum pointtype {
3086 POINTTYPE_CURVE = 0,
3087 POINTTYPE_CORNER,
3088 POINTTYPE_CURVE_START,
3089 POINTTYPE_CURVE_END,
3090 POINTTYPE_CURVE_MIDDLE,
3093 struct point2d
3095 D3DXVECTOR2 pos;
3096 enum pointtype corner;
3099 /* is a dynamic_array */
3100 struct outline
3102 int count, capacity;
3103 struct point2d *items;
3106 /* is a dynamic_array */
3107 struct outline_array
3109 int count, capacity;
3110 struct outline *items;
3113 struct glyphinfo
3115 struct outline_array outlines;
3116 float offset_x;
3119 static BOOL reserve(struct dynamic_array *array, int count, int itemsize)
3121 if (count > array->capacity) {
3122 void *new_buffer;
3123 int new_capacity;
3124 if (array->items && array->capacity) {
3125 new_capacity = max(array->capacity * 2, count);
3126 new_buffer = HeapReAlloc(GetProcessHeap(), 0, array->items, new_capacity * itemsize);
3127 } else {
3128 new_capacity = max(16, count);
3129 new_buffer = HeapAlloc(GetProcessHeap(), 0, new_capacity * itemsize);
3131 if (!new_buffer)
3132 return FALSE;
3133 array->items = new_buffer;
3134 array->capacity = new_capacity;
3136 return TRUE;
3139 static struct point2d *add_point(struct outline *array)
3141 struct point2d *item;
3143 if (!reserve((struct dynamic_array *)array, array->count + 1, sizeof(array->items[0])))
3144 return NULL;
3146 item = &array->items[array->count++];
3147 ZeroMemory(item, sizeof(*item));
3148 return item;
3151 static struct outline *add_outline(struct outline_array *array)
3153 struct outline *item;
3155 if (!reserve((struct dynamic_array *)array, array->count + 1, sizeof(array->items[0])))
3156 return NULL;
3158 item = &array->items[array->count++];
3159 ZeroMemory(item, sizeof(*item));
3160 return item;
3163 static inline D3DXVECTOR2 *convert_fixed_to_float(POINTFX *pt, int count, float emsquare)
3165 D3DXVECTOR2 *ret = (D3DXVECTOR2*)pt;
3166 while (count--) {
3167 D3DXVECTOR2 *pt_flt = (D3DXVECTOR2*)pt;
3168 pt_flt->x = (pt->x.value + pt->x.fract / (float)0x10000) / emsquare;
3169 pt_flt->y = (pt->y.value + pt->y.fract / (float)0x10000) / emsquare;
3170 pt++;
3172 return ret;
3175 static HRESULT add_bezier_points(struct outline *outline, const D3DXVECTOR2 *p1,
3176 const D3DXVECTOR2 *p2, const D3DXVECTOR2 *p3,
3177 float max_deviation)
3179 D3DXVECTOR2 split1 = {0, 0}, split2 = {0, 0}, middle, vec;
3180 float deviation;
3182 D3DXVec2Scale(&split1, D3DXVec2Add(&split1, p1, p2), 0.5f);
3183 D3DXVec2Scale(&split2, D3DXVec2Add(&split2, p2, p3), 0.5f);
3184 D3DXVec2Scale(&middle, D3DXVec2Add(&middle, &split1, &split2), 0.5f);
3186 deviation = D3DXVec2Length(D3DXVec2Subtract(&vec, &middle, p2));
3187 if (deviation < max_deviation) {
3188 struct point2d *pt = add_point(outline);
3189 if (!pt) return E_OUTOFMEMORY;
3190 pt->pos = *p2;
3191 pt->corner = POINTTYPE_CURVE;
3192 /* the end point is omitted because the end line merges into the next segment of
3193 * the split bezier curve, and the end of the split bezier curve is added outside
3194 * this recursive function. */
3195 } else {
3196 HRESULT hr = add_bezier_points(outline, p1, &split1, &middle, max_deviation);
3197 if (hr != S_OK) return hr;
3198 hr = add_bezier_points(outline, &middle, &split2, p3, max_deviation);
3199 if (hr != S_OK) return hr;
3202 return S_OK;
3205 static inline BOOL is_direction_similar(D3DXVECTOR2 *dir1, D3DXVECTOR2 *dir2, float cos_theta)
3207 /* dot product = cos(theta) */
3208 return D3DXVec2Dot(dir1, dir2) > cos_theta;
3211 static inline D3DXVECTOR2 *unit_vec2(D3DXVECTOR2 *dir, const D3DXVECTOR2 *pt1, const D3DXVECTOR2 *pt2)
3213 return D3DXVec2Normalize(D3DXVec2Subtract(dir, pt2, pt1), dir);
3216 static BOOL attempt_line_merge(struct outline *outline,
3217 int pt_index,
3218 const D3DXVECTOR2 *nextpt,
3219 BOOL to_curve)
3221 D3DXVECTOR2 curdir, lastdir;
3222 struct point2d *prevpt, *pt;
3223 BOOL ret = FALSE;
3224 const float cos_half = cos(D3DXToRadian(0.5f));
3226 pt = &outline->items[pt_index];
3227 pt_index = (pt_index - 1 + outline->count) % outline->count;
3228 prevpt = &outline->items[pt_index];
3230 if (to_curve)
3231 pt->corner = pt->corner != POINTTYPE_CORNER ? POINTTYPE_CURVE_MIDDLE : POINTTYPE_CURVE_START;
3233 if (outline->count < 2)
3234 return FALSE;
3236 /* remove last point if the next line continues the last line */
3237 unit_vec2(&lastdir, &prevpt->pos, &pt->pos);
3238 unit_vec2(&curdir, &pt->pos, nextpt);
3239 if (is_direction_similar(&lastdir, &curdir, cos_half))
3241 outline->count--;
3242 if (pt->corner == POINTTYPE_CURVE_END)
3243 prevpt->corner = pt->corner;
3244 if (prevpt->corner == POINTTYPE_CURVE_END && to_curve)
3245 prevpt->corner = POINTTYPE_CURVE_MIDDLE;
3246 pt = prevpt;
3248 ret = TRUE;
3249 if (outline->count < 2)
3250 return ret;
3252 pt_index = (pt_index - 1 + outline->count) % outline->count;
3253 prevpt = &outline->items[pt_index];
3254 unit_vec2(&lastdir, &prevpt->pos, &pt->pos);
3255 unit_vec2(&curdir, &pt->pos, nextpt);
3257 return ret;
3260 static HRESULT create_outline(struct glyphinfo *glyph, void *raw_outline, int datasize,
3261 float max_deviation, float emsquare)
3263 const float cos_45 = cos(D3DXToRadian(45.0f));
3264 const float cos_90 = cos(D3DXToRadian(90.0f));
3265 TTPOLYGONHEADER *header = (TTPOLYGONHEADER *)raw_outline;
3267 while ((char *)header < (char *)raw_outline + datasize)
3269 TTPOLYCURVE *curve = (TTPOLYCURVE *)(header + 1);
3270 struct point2d *lastpt, *pt;
3271 D3DXVECTOR2 lastdir;
3272 D3DXVECTOR2 *pt_flt;
3273 int j;
3274 struct outline *outline = add_outline(&glyph->outlines);
3276 if (!outline)
3277 return E_OUTOFMEMORY;
3279 pt = add_point(outline);
3280 if (!pt)
3281 return E_OUTOFMEMORY;
3282 pt_flt = convert_fixed_to_float(&header->pfxStart, 1, emsquare);
3283 pt->pos = *pt_flt;
3284 pt->corner = POINTTYPE_CORNER;
3286 if (header->dwType != TT_POLYGON_TYPE)
3287 trace("Unknown header type %d\n", header->dwType);
3289 while ((char *)curve < (char *)header + header->cb)
3291 D3DXVECTOR2 bezier_start = outline->items[outline->count - 1].pos;
3292 BOOL to_curve = curve->wType != TT_PRIM_LINE && curve->cpfx > 1;
3294 if (!curve->cpfx) {
3295 curve = (TTPOLYCURVE *)&curve->apfx[curve->cpfx];
3296 continue;
3299 pt_flt = convert_fixed_to_float(curve->apfx, curve->cpfx, emsquare);
3301 attempt_line_merge(outline, outline->count - 1, &pt_flt[0], to_curve);
3303 if (to_curve)
3305 HRESULT hr;
3306 int count = curve->cpfx;
3307 j = 0;
3309 while (count > 2)
3311 D3DXVECTOR2 bezier_end;
3313 D3DXVec2Scale(&bezier_end, D3DXVec2Add(&bezier_end, &pt_flt[j], &pt_flt[j+1]), 0.5f);
3314 hr = add_bezier_points(outline, &bezier_start, &pt_flt[j], &bezier_end, max_deviation);
3315 if (hr != S_OK)
3316 return hr;
3317 bezier_start = bezier_end;
3318 count--;
3319 j++;
3321 hr = add_bezier_points(outline, &bezier_start, &pt_flt[j], &pt_flt[j+1], max_deviation);
3322 if (hr != S_OK)
3323 return hr;
3325 pt = add_point(outline);
3326 if (!pt)
3327 return E_OUTOFMEMORY;
3328 j++;
3329 pt->pos = pt_flt[j];
3330 pt->corner = POINTTYPE_CURVE_END;
3331 } else {
3332 for (j = 0; j < curve->cpfx; j++)
3334 pt = add_point(outline);
3335 if (!pt)
3336 return E_OUTOFMEMORY;
3337 pt->pos = pt_flt[j];
3338 pt->corner = POINTTYPE_CORNER;
3342 curve = (TTPOLYCURVE *)&curve->apfx[curve->cpfx];
3345 /* remove last point if the next line continues the last line */
3346 if (outline->count >= 3) {
3347 BOOL to_curve;
3349 lastpt = &outline->items[outline->count - 1];
3350 pt = &outline->items[0];
3351 if (pt->pos.x == lastpt->pos.x && pt->pos.y == lastpt->pos.y) {
3352 if (lastpt->corner == POINTTYPE_CURVE_END)
3354 if (pt->corner == POINTTYPE_CURVE_START)
3355 pt->corner = POINTTYPE_CURVE_MIDDLE;
3356 else
3357 pt->corner = POINTTYPE_CURVE_END;
3359 outline->count--;
3360 lastpt = &outline->items[outline->count - 1];
3361 } else {
3362 /* outline closed with a line from end to start point */
3363 attempt_line_merge(outline, outline->count - 1, &pt->pos, FALSE);
3365 lastpt = &outline->items[0];
3366 to_curve = lastpt->corner != POINTTYPE_CORNER && lastpt->corner != POINTTYPE_CURVE_END;
3367 if (lastpt->corner == POINTTYPE_CURVE_START)
3368 lastpt->corner = POINTTYPE_CORNER;
3369 pt = &outline->items[1];
3370 if (attempt_line_merge(outline, 0, &pt->pos, to_curve))
3371 *lastpt = outline->items[outline->count];
3374 lastpt = &outline->items[outline->count - 1];
3375 pt = &outline->items[0];
3376 unit_vec2(&lastdir, &lastpt->pos, &pt->pos);
3377 for (j = 0; j < outline->count; j++)
3379 D3DXVECTOR2 curdir;
3381 lastpt = pt;
3382 pt = &outline->items[(j + 1) % outline->count];
3383 unit_vec2(&curdir, &lastpt->pos, &pt->pos);
3385 switch (lastpt->corner)
3387 case POINTTYPE_CURVE_START:
3388 case POINTTYPE_CURVE_END:
3389 if (!is_direction_similar(&lastdir, &curdir, cos_45))
3390 lastpt->corner = POINTTYPE_CORNER;
3391 break;
3392 case POINTTYPE_CURVE_MIDDLE:
3393 if (!is_direction_similar(&lastdir, &curdir, cos_90))
3394 lastpt->corner = POINTTYPE_CORNER;
3395 else
3396 lastpt->corner = POINTTYPE_CURVE;
3397 break;
3398 default:
3399 break;
3401 lastdir = curdir;
3404 header = (TTPOLYGONHEADER *)((char *)header + header->cb);
3406 return S_OK;
3409 static BOOL compute_text_mesh(struct mesh *mesh, HDC hdc, const char *text,
3410 float deviation, float extrusion, float otmEMSquare)
3412 HRESULT hr = E_FAIL;
3413 DWORD nb_vertices, nb_faces;
3414 DWORD nb_corners, nb_outline_points;
3415 int textlen = 0;
3416 float offset_x;
3417 char *raw_outline = NULL;
3418 struct glyphinfo *glyphs = NULL;
3419 GLYPHMETRICS gm;
3420 int i;
3421 struct vertex *vertex_ptr;
3422 face *face_ptr;
3424 if (deviation == 0.0f)
3425 deviation = 1.0f / otmEMSquare;
3427 textlen = strlen(text);
3428 glyphs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, textlen * sizeof(*glyphs));
3429 if (!glyphs) {
3430 hr = E_OUTOFMEMORY;
3431 goto error;
3434 offset_x = 0.0f;
3435 for (i = 0; i < textlen; i++)
3437 /* get outline points from data returned from GetGlyphOutline */
3438 const MAT2 identity = {{0, 1}, {0, 0}, {0, 0}, {0, 1}};
3439 int datasize;
3441 glyphs[i].offset_x = offset_x;
3443 datasize = GetGlyphOutlineA(hdc, text[i], GGO_NATIVE, &gm, 0, NULL, &identity);
3444 if (datasize < 0) {
3445 hr = E_FAIL;
3446 goto error;
3448 HeapFree(GetProcessHeap(), 0, raw_outline);
3449 raw_outline = HeapAlloc(GetProcessHeap(), 0, datasize);
3450 if (!glyphs) {
3451 hr = E_OUTOFMEMORY;
3452 goto error;
3454 datasize = GetGlyphOutlineA(hdc, text[i], GGO_NATIVE, &gm, datasize, raw_outline, &identity);
3456 create_outline(&glyphs[i], raw_outline, datasize, deviation, otmEMSquare);
3458 offset_x += gm.gmCellIncX / (float)otmEMSquare;
3461 /* corner points need an extra vertex for the different side faces normals */
3462 nb_corners = 0;
3463 nb_outline_points = 0;
3464 for (i = 0; i < textlen; i++)
3466 int j;
3467 for (j = 0; j < glyphs[i].outlines.count; j++)
3469 int k;
3470 struct outline *outline = &glyphs[i].outlines.items[j];
3471 nb_outline_points += outline->count;
3472 nb_corners++; /* first outline point always repeated as a corner */
3473 for (k = 1; k < outline->count; k++)
3474 if (outline->items[k].corner)
3475 nb_corners++;
3479 nb_vertices = (nb_outline_points + nb_corners) * 2 + textlen;
3480 nb_faces = nb_outline_points * 2;
3482 if (!new_mesh(mesh, nb_vertices, nb_faces))
3483 goto error;
3485 /* convert 2D vertices and faces into 3D mesh */
3486 vertex_ptr = mesh->vertices;
3487 face_ptr = mesh->faces;
3488 for (i = 0; i < textlen; i++)
3490 int j;
3492 /* side vertices and faces */
3493 for (j = 0; j < glyphs[i].outlines.count; j++)
3495 struct vertex *outline_vertices = vertex_ptr;
3496 struct outline *outline = &glyphs[i].outlines.items[j];
3497 int k;
3498 struct point2d *prevpt = &outline->items[outline->count - 1];
3499 struct point2d *pt = &outline->items[0];
3501 for (k = 1; k <= outline->count; k++)
3503 struct vertex vtx;
3504 struct point2d *nextpt = &outline->items[k % outline->count];
3505 WORD vtx_idx = vertex_ptr - mesh->vertices;
3506 D3DXVECTOR2 vec;
3508 if (pt->corner == POINTTYPE_CURVE_START)
3509 D3DXVec2Subtract(&vec, &pt->pos, &prevpt->pos);
3510 else if (pt->corner)
3511 D3DXVec2Subtract(&vec, &nextpt->pos, &pt->pos);
3512 else
3513 D3DXVec2Subtract(&vec, &nextpt->pos, &prevpt->pos);
3514 D3DXVec2Normalize(&vec, &vec);
3515 vtx.normal.x = -vec.y;
3516 vtx.normal.y = vec.x;
3517 vtx.normal.z = 0;
3519 vtx.position.x = pt->pos.x + glyphs[i].offset_x;
3520 vtx.position.y = pt->pos.y;
3521 vtx.position.z = 0;
3522 *vertex_ptr++ = vtx;
3524 vtx.position.z = -extrusion;
3525 *vertex_ptr++ = vtx;
3527 vtx.position.x = nextpt->pos.x + glyphs[i].offset_x;
3528 vtx.position.y = nextpt->pos.y;
3529 if (pt->corner && nextpt->corner && nextpt->corner != POINTTYPE_CURVE_END) {
3530 vtx.position.z = -extrusion;
3531 *vertex_ptr++ = vtx;
3532 vtx.position.z = 0;
3533 *vertex_ptr++ = vtx;
3535 (*face_ptr)[0] = vtx_idx;
3536 (*face_ptr)[1] = vtx_idx + 2;
3537 (*face_ptr)[2] = vtx_idx + 1;
3538 face_ptr++;
3540 (*face_ptr)[0] = vtx_idx;
3541 (*face_ptr)[1] = vtx_idx + 3;
3542 (*face_ptr)[2] = vtx_idx + 2;
3543 face_ptr++;
3544 } else {
3545 if (nextpt->corner) {
3546 if (nextpt->corner == POINTTYPE_CURVE_END) {
3547 struct point2d *nextpt2 = &outline->items[(k + 1) % outline->count];
3548 D3DXVec2Subtract(&vec, &nextpt2->pos, &nextpt->pos);
3549 } else {
3550 D3DXVec2Subtract(&vec, &nextpt->pos, &pt->pos);
3552 D3DXVec2Normalize(&vec, &vec);
3553 vtx.normal.x = -vec.y;
3554 vtx.normal.y = vec.x;
3556 vtx.position.z = 0;
3557 *vertex_ptr++ = vtx;
3558 vtx.position.z = -extrusion;
3559 *vertex_ptr++ = vtx;
3562 (*face_ptr)[0] = vtx_idx;
3563 (*face_ptr)[1] = vtx_idx + 3;
3564 (*face_ptr)[2] = vtx_idx + 1;
3565 face_ptr++;
3567 (*face_ptr)[0] = vtx_idx;
3568 (*face_ptr)[1] = vtx_idx + 2;
3569 (*face_ptr)[2] = vtx_idx + 3;
3570 face_ptr++;
3573 prevpt = pt;
3574 pt = nextpt;
3576 if (!pt->corner) {
3577 *vertex_ptr++ = *outline_vertices++;
3578 *vertex_ptr++ = *outline_vertices++;
3582 /* FIXME: compute expected faces */
3583 /* Add placeholder to separate glyph outlines */
3584 vertex_ptr->position.x = 0;
3585 vertex_ptr->position.y = 0;
3586 vertex_ptr->position.z = 0;
3587 vertex_ptr->normal.x = 0;
3588 vertex_ptr->normal.y = 0;
3589 vertex_ptr->normal.z = 1;
3590 vertex_ptr++;
3593 hr = D3D_OK;
3594 error:
3595 if (glyphs) {
3596 for (i = 0; i < textlen; i++)
3598 int j;
3599 for (j = 0; j < glyphs[i].outlines.count; j++)
3600 HeapFree(GetProcessHeap(), 0, glyphs[i].outlines.items[j].items);
3601 HeapFree(GetProcessHeap(), 0, glyphs[i].outlines.items);
3603 HeapFree(GetProcessHeap(), 0, glyphs);
3605 HeapFree(GetProcessHeap(), 0, raw_outline);
3607 return hr == D3D_OK;
3610 static void compare_text_outline_mesh(const char *name, ID3DXMesh *d3dxmesh, struct mesh *mesh, int textlen, float extrusion)
3612 HRESULT hr;
3613 DWORD number_of_vertices, number_of_faces;
3614 IDirect3DVertexBuffer9 *vertex_buffer = NULL;
3615 IDirect3DIndexBuffer9 *index_buffer = NULL;
3616 D3DVERTEXBUFFER_DESC vertex_buffer_description;
3617 D3DINDEXBUFFER_DESC index_buffer_description;
3618 struct vertex *vertices = NULL;
3619 face *faces = NULL;
3620 int expected, i;
3621 int vtx_idx1, face_idx1, vtx_idx2, face_idx2;
3623 number_of_vertices = d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh);
3624 number_of_faces = d3dxmesh->lpVtbl->GetNumFaces(d3dxmesh);
3626 /* vertex buffer */
3627 hr = d3dxmesh->lpVtbl->GetVertexBuffer(d3dxmesh, &vertex_buffer);
3628 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
3629 if (hr != D3D_OK)
3631 skip("Couldn't get vertex buffers\n");
3632 goto error;
3635 hr = IDirect3DVertexBuffer9_GetDesc(vertex_buffer, &vertex_buffer_description);
3636 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
3638 if (hr != D3D_OK)
3640 skip("Couldn't get vertex buffer description\n");
3642 else
3644 ok(vertex_buffer_description.Format == D3DFMT_VERTEXDATA, "Test %s, result %x, expected %x (D3DFMT_VERTEXDATA)\n",
3645 name, vertex_buffer_description.Format, D3DFMT_VERTEXDATA);
3646 ok(vertex_buffer_description.Type == D3DRTYPE_VERTEXBUFFER, "Test %s, result %x, expected %x (D3DRTYPE_VERTEXBUFFER)\n",
3647 name, vertex_buffer_description.Type, D3DRTYPE_VERTEXBUFFER);
3648 ok(vertex_buffer_description.Usage == 0, "Test %s, result %x, expected %x\n", name, vertex_buffer_description.Usage, 0);
3649 ok(vertex_buffer_description.Pool == D3DPOOL_MANAGED, "Test %s, result %x, expected %x (D3DPOOL_MANAGED)\n",
3650 name, vertex_buffer_description.Pool, D3DPOOL_MANAGED);
3651 ok(vertex_buffer_description.FVF == mesh->fvf, "Test %s, result %x, expected %x\n",
3652 name, vertex_buffer_description.FVF, mesh->fvf);
3653 if (mesh->fvf == 0)
3655 expected = number_of_vertices * mesh->vertex_size;
3657 else
3659 expected = number_of_vertices * D3DXGetFVFVertexSize(mesh->fvf);
3661 ok(vertex_buffer_description.Size == expected, "Test %s, result %x, expected %x\n",
3662 name, vertex_buffer_description.Size, expected);
3665 hr = d3dxmesh->lpVtbl->GetIndexBuffer(d3dxmesh, &index_buffer);
3666 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
3667 if (hr != D3D_OK)
3669 skip("Couldn't get index buffer\n");
3670 goto error;
3673 hr = IDirect3DIndexBuffer9_GetDesc(index_buffer, &index_buffer_description);
3674 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
3676 if (hr != D3D_OK)
3678 skip("Couldn't get index buffer description\n");
3680 else
3682 ok(index_buffer_description.Format == D3DFMT_INDEX16, "Test %s, result %x, expected %x (D3DFMT_INDEX16)\n",
3683 name, index_buffer_description.Format, D3DFMT_INDEX16);
3684 ok(index_buffer_description.Type == D3DRTYPE_INDEXBUFFER, "Test %s, result %x, expected %x (D3DRTYPE_INDEXBUFFER)\n",
3685 name, index_buffer_description.Type, D3DRTYPE_INDEXBUFFER);
3686 ok(index_buffer_description.Usage == 0, "Test %s, result %#x, expected %#x.\n",
3687 name, index_buffer_description.Usage, 0);
3688 ok(index_buffer_description.Pool == D3DPOOL_MANAGED, "Test %s, result %x, expected %x (D3DPOOL_MANAGED)\n",
3689 name, index_buffer_description.Pool, D3DPOOL_MANAGED);
3690 expected = number_of_faces * sizeof(WORD) * 3;
3691 ok(index_buffer_description.Size == expected, "Test %s, result %x, expected %x\n",
3692 name, index_buffer_description.Size, expected);
3695 /* specify offset and size to avoid potential overruns */
3696 hr = IDirect3DVertexBuffer9_Lock(vertex_buffer, 0, number_of_vertices * sizeof(D3DXVECTOR3) * 2,
3697 (void **)&vertices, 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 vertex buffer\n");
3702 goto error;
3704 hr = IDirect3DIndexBuffer9_Lock(index_buffer, 0, number_of_faces * sizeof(WORD) * 3,
3705 (void **)&faces, D3DLOCK_DISCARD);
3706 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
3707 if (hr != D3D_OK)
3709 skip("Couldn't lock index buffer\n");
3710 goto error;
3713 face_idx1 = 0;
3714 vtx_idx2 = 0;
3715 face_idx2 = 0;
3716 vtx_idx1 = 0;
3717 for (i = 0; i < textlen; i++)
3719 int nb_outline_vertices1, nb_outline_faces1;
3720 int nb_outline_vertices2, nb_outline_faces2;
3721 int nb_back_vertices, nb_back_faces;
3722 int first_vtx1, first_vtx2;
3723 int first_face1, first_face2;
3724 int j;
3726 first_vtx1 = vtx_idx1;
3727 first_vtx2 = vtx_idx2;
3728 for (; vtx_idx1 < number_of_vertices; vtx_idx1++) {
3729 if (vertices[vtx_idx1].normal.z != 0)
3730 break;
3732 for (; vtx_idx2 < mesh->number_of_vertices; vtx_idx2++) {
3733 if (mesh->vertices[vtx_idx2].normal.z != 0)
3734 break;
3736 nb_outline_vertices1 = vtx_idx1 - first_vtx1;
3737 nb_outline_vertices2 = vtx_idx2 - first_vtx2;
3738 ok(nb_outline_vertices1 == nb_outline_vertices2,
3739 "Test %s, glyph %d, outline vertex count result %d, expected %d\n", name, i,
3740 nb_outline_vertices1, nb_outline_vertices2);
3742 for (j = 0; j < min(nb_outline_vertices1, nb_outline_vertices2); j++)
3744 vtx_idx1 = first_vtx1 + j;
3745 vtx_idx2 = first_vtx2 + j;
3746 ok(compare_vec3(vertices[vtx_idx1].position, mesh->vertices[vtx_idx2].position),
3747 "Test %s, glyph %d, vertex position %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1,
3748 vertices[vtx_idx1].position.x, vertices[vtx_idx1].position.y, vertices[vtx_idx1].position.z,
3749 mesh->vertices[vtx_idx2].position.x, mesh->vertices[vtx_idx2].position.y, mesh->vertices[vtx_idx2].position.z);
3750 ok(compare_vec3(vertices[vtx_idx1].normal, mesh->vertices[first_vtx2 + j].normal),
3751 "Test %s, glyph %d, vertex normal %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1,
3752 vertices[vtx_idx1].normal.x, vertices[vtx_idx1].normal.y, vertices[vtx_idx1].normal.z,
3753 mesh->vertices[vtx_idx2].normal.x, mesh->vertices[vtx_idx2].normal.y, mesh->vertices[vtx_idx2].normal.z);
3755 vtx_idx1 = first_vtx1 + nb_outline_vertices1;
3756 vtx_idx2 = first_vtx2 + nb_outline_vertices2;
3758 first_face1 = face_idx1;
3759 first_face2 = face_idx2;
3760 for (; face_idx1 < number_of_faces; face_idx1++)
3762 if (faces[face_idx1][0] >= vtx_idx1 ||
3763 faces[face_idx1][1] >= vtx_idx1 ||
3764 faces[face_idx1][2] >= vtx_idx1)
3765 break;
3767 for (; face_idx2 < mesh->number_of_faces; face_idx2++)
3769 if (mesh->faces[face_idx2][0] >= vtx_idx2 ||
3770 mesh->faces[face_idx2][1] >= vtx_idx2 ||
3771 mesh->faces[face_idx2][2] >= vtx_idx2)
3772 break;
3774 nb_outline_faces1 = face_idx1 - first_face1;
3775 nb_outline_faces2 = face_idx2 - first_face2;
3776 ok(nb_outline_faces1 == nb_outline_faces2,
3777 "Test %s, glyph %d, outline face count result %d, expected %d\n", name, i,
3778 nb_outline_faces1, nb_outline_faces2);
3780 for (j = 0; j < min(nb_outline_faces1, nb_outline_faces2); j++)
3782 face_idx1 = first_face1 + j;
3783 face_idx2 = first_face2 + j;
3784 ok(faces[face_idx1][0] - first_vtx1 == mesh->faces[face_idx2][0] - first_vtx2 &&
3785 faces[face_idx1][1] - first_vtx1 == mesh->faces[face_idx2][1] - first_vtx2 &&
3786 faces[face_idx1][2] - first_vtx1 == mesh->faces[face_idx2][2] - first_vtx2,
3787 "Test %s, glyph %d, face %d, result (%d, %d, %d), expected (%d, %d, %d)\n", name, i, face_idx1,
3788 faces[face_idx1][0], faces[face_idx1][1], faces[face_idx1][2],
3789 mesh->faces[face_idx2][0] - first_vtx2 + first_vtx1,
3790 mesh->faces[face_idx2][1] - first_vtx2 + first_vtx1,
3791 mesh->faces[face_idx2][2] - first_vtx2 + first_vtx1);
3793 face_idx1 = first_face1 + nb_outline_faces1;
3794 face_idx2 = first_face2 + nb_outline_faces2;
3796 /* partial test on back vertices and faces */
3797 first_vtx1 = vtx_idx1;
3798 for (; vtx_idx1 < number_of_vertices; vtx_idx1++) {
3799 struct vertex vtx;
3801 if (vertices[vtx_idx1].normal.z != 1.0f)
3802 break;
3804 vtx.position.z = 0.0f;
3805 vtx.normal.x = 0.0f;
3806 vtx.normal.y = 0.0f;
3807 vtx.normal.z = 1.0f;
3808 ok(compare(vertices[vtx_idx1].position.z, vtx.position.z),
3809 "Test %s, glyph %d, vertex position.z %d, result %g, expected %g\n", name, i, vtx_idx1,
3810 vertices[vtx_idx1].position.z, vtx.position.z);
3811 ok(compare_vec3(vertices[vtx_idx1].normal, vtx.normal),
3812 "Test %s, glyph %d, vertex normal %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1,
3813 vertices[vtx_idx1].normal.x, vertices[vtx_idx1].normal.y, vertices[vtx_idx1].normal.z,
3814 vtx.normal.x, vtx.normal.y, vtx.normal.z);
3816 nb_back_vertices = vtx_idx1 - first_vtx1;
3817 first_face1 = face_idx1;
3818 for (; face_idx1 < number_of_faces; face_idx1++)
3820 const D3DXVECTOR3 *vtx1, *vtx2, *vtx3;
3821 D3DXVECTOR3 normal;
3822 D3DXVECTOR3 v1 = {0, 0, 0};
3823 D3DXVECTOR3 v2 = {0, 0, 0};
3824 D3DXVECTOR3 forward = {0.0f, 0.0f, 1.0f};
3826 if (faces[face_idx1][0] >= vtx_idx1 ||
3827 faces[face_idx1][1] >= vtx_idx1 ||
3828 faces[face_idx1][2] >= vtx_idx1)
3829 break;
3831 vtx1 = &vertices[faces[face_idx1][0]].position;
3832 vtx2 = &vertices[faces[face_idx1][1]].position;
3833 vtx3 = &vertices[faces[face_idx1][2]].position;
3835 D3DXVec3Subtract(&v1, vtx2, vtx1);
3836 D3DXVec3Subtract(&v2, vtx3, vtx2);
3837 D3DXVec3Cross(&normal, &v1, &v2);
3838 D3DXVec3Normalize(&normal, &normal);
3839 ok(!D3DXVec3Length(&normal) || compare_vec3(normal, forward),
3840 "Test %s, glyph %d, face %d normal, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, face_idx1,
3841 normal.x, normal.y, normal.z, forward.x, forward.y, forward.z);
3843 nb_back_faces = face_idx1 - first_face1;
3845 /* compare front and back faces & vertices */
3846 if (extrusion == 0.0f) {
3847 /* Oddly there are only back faces in this case */
3848 nb_back_vertices /= 2;
3849 nb_back_faces /= 2;
3850 face_idx1 -= nb_back_faces;
3851 vtx_idx1 -= nb_back_vertices;
3853 for (j = 0; j < nb_back_vertices; j++)
3855 struct vertex vtx = vertices[first_vtx1];
3856 vtx.position.z = -extrusion;
3857 vtx.normal.x = 0.0f;
3858 vtx.normal.y = 0.0f;
3859 vtx.normal.z = extrusion == 0.0f ? 1.0f : -1.0f;
3860 ok(compare_vec3(vertices[vtx_idx1].position, vtx.position),
3861 "Test %s, glyph %d, vertex position %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1,
3862 vertices[vtx_idx1].position.x, vertices[vtx_idx1].position.y, vertices[vtx_idx1].position.z,
3863 vtx.position.x, vtx.position.y, vtx.position.z);
3864 ok(compare_vec3(vertices[vtx_idx1].normal, vtx.normal),
3865 "Test %s, glyph %d, vertex normal %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1,
3866 vertices[vtx_idx1].normal.x, vertices[vtx_idx1].normal.y, vertices[vtx_idx1].normal.z,
3867 vtx.normal.x, vtx.normal.y, vtx.normal.z);
3868 vtx_idx1++;
3869 first_vtx1++;
3871 for (j = 0; j < nb_back_faces; j++)
3873 int f1, f2;
3874 if (extrusion == 0.0f) {
3875 f1 = 1;
3876 f2 = 2;
3877 } else {
3878 f1 = 2;
3879 f2 = 1;
3881 ok(faces[face_idx1][0] == faces[first_face1][0] + nb_back_vertices &&
3882 faces[face_idx1][1] == faces[first_face1][f1] + nb_back_vertices &&
3883 faces[face_idx1][2] == faces[first_face1][f2] + nb_back_vertices,
3884 "Test %s, glyph %d, face %d, result (%d, %d, %d), expected (%d, %d, %d)\n", name, i, face_idx1,
3885 faces[face_idx1][0], faces[face_idx1][1], faces[face_idx1][2],
3886 faces[first_face1][0] - nb_back_faces,
3887 faces[first_face1][f1] - nb_back_faces,
3888 faces[first_face1][f2] - nb_back_faces);
3889 first_face1++;
3890 face_idx1++;
3893 /* skip to the outline for the next glyph */
3894 for (; vtx_idx2 < mesh->number_of_vertices; vtx_idx2++) {
3895 if (mesh->vertices[vtx_idx2].normal.z == 0)
3896 break;
3898 for (; face_idx2 < mesh->number_of_faces; face_idx2++)
3900 if (mesh->faces[face_idx2][0] >= vtx_idx2 ||
3901 mesh->faces[face_idx2][1] >= vtx_idx2 ||
3902 mesh->faces[face_idx2][2] >= vtx_idx2) break;
3906 error:
3907 if (vertices) IDirect3DVertexBuffer9_Unlock(vertex_buffer);
3908 if (faces) IDirect3DIndexBuffer9_Unlock(index_buffer);
3909 if (index_buffer) IDirect3DIndexBuffer9_Release(index_buffer);
3910 if (vertex_buffer) IDirect3DVertexBuffer9_Release(vertex_buffer);
3913 static void test_createtext(IDirect3DDevice9 *device, HDC hdc, const char *text, float deviation, float extrusion)
3915 HRESULT hr;
3916 ID3DXMesh *d3dxmesh;
3917 struct mesh mesh;
3918 char name[256];
3919 OUTLINETEXTMETRICA otm;
3920 GLYPHMETRICS gm;
3921 GLYPHMETRICSFLOAT *glyphmetrics_float = HeapAlloc(GetProcessHeap(), 0, sizeof(GLYPHMETRICSFLOAT) * strlen(text));
3922 int i;
3923 LOGFONTA lf;
3924 HFONT font = NULL, oldfont = NULL;
3926 sprintf(name, "text ('%s', %f, %f)", text, deviation, extrusion);
3928 hr = D3DXCreateTextA(device, hdc, text, deviation, extrusion, &d3dxmesh, NULL, glyphmetrics_float);
3929 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
3930 if (hr != D3D_OK)
3932 skip("Couldn't create text with D3DXCreateText\n");
3933 return;
3936 /* must select a modified font having lfHeight = otm.otmEMSquare before
3937 * calling GetGlyphOutline to get the expected values */
3938 if (!GetObjectA(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf)
3939 || !GetOutlineTextMetricsA(hdc, sizeof(otm), &otm))
3941 d3dxmesh->lpVtbl->Release(d3dxmesh);
3942 skip("Couldn't get text outline\n");
3943 return;
3945 lf.lfHeight = otm.otmEMSquare;
3946 lf.lfWidth = 0;
3947 if (!(font = CreateFontIndirectA(&lf)))
3949 d3dxmesh->lpVtbl->Release(d3dxmesh);
3950 skip("Couldn't create the modified font\n");
3951 return;
3953 oldfont = SelectObject(hdc, font);
3955 for (i = 0; i < strlen(text); i++)
3957 const MAT2 identity = {{0, 1}, {0, 0}, {0, 0}, {0, 1}};
3958 GetGlyphOutlineA(hdc, text[i], GGO_NATIVE, &gm, 0, NULL, &identity);
3959 compare_float(glyphmetrics_float[i].gmfBlackBoxX, gm.gmBlackBoxX / (float)otm.otmEMSquare);
3960 compare_float(glyphmetrics_float[i].gmfBlackBoxY, gm.gmBlackBoxY / (float)otm.otmEMSquare);
3961 compare_float(glyphmetrics_float[i].gmfptGlyphOrigin.x, gm.gmptGlyphOrigin.x / (float)otm.otmEMSquare);
3962 compare_float(glyphmetrics_float[i].gmfptGlyphOrigin.y, gm.gmptGlyphOrigin.y / (float)otm.otmEMSquare);
3963 compare_float(glyphmetrics_float[i].gmfCellIncX, gm.gmCellIncX / (float)otm.otmEMSquare);
3964 compare_float(glyphmetrics_float[i].gmfCellIncY, gm.gmCellIncY / (float)otm.otmEMSquare);
3967 ZeroMemory(&mesh, sizeof(mesh));
3968 if (!compute_text_mesh(&mesh, hdc, text, deviation, extrusion, otm.otmEMSquare))
3970 skip("Couldn't create mesh\n");
3971 d3dxmesh->lpVtbl->Release(d3dxmesh);
3972 return;
3974 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
3976 compare_text_outline_mesh(name, d3dxmesh, &mesh, strlen(text), extrusion);
3978 free_mesh(&mesh);
3980 d3dxmesh->lpVtbl->Release(d3dxmesh);
3981 SelectObject(hdc, oldfont);
3982 HeapFree(GetProcessHeap(), 0, glyphmetrics_float);
3985 static void D3DXCreateTextTest(void)
3987 HRESULT hr;
3988 HWND wnd;
3989 HDC hdc;
3990 IDirect3D9* d3d;
3991 IDirect3DDevice9* device;
3992 D3DPRESENT_PARAMETERS d3dpp;
3993 ID3DXMesh* d3dxmesh = NULL;
3994 HFONT hFont;
3995 OUTLINETEXTMETRICA otm;
3996 int number_of_vertices;
3997 int number_of_faces;
3999 if (!(wnd = CreateWindowA("static", "d3dx9_test", WS_POPUP, 0, 0, 1000, 1000, NULL, NULL, NULL, NULL)))
4001 skip("Couldn't create application window\n");
4002 return;
4004 if (!(d3d = Direct3DCreate9(D3D_SDK_VERSION)))
4006 skip("Couldn't create IDirect3D9 object\n");
4007 DestroyWindow(wnd);
4008 return;
4011 ZeroMemory(&d3dpp, sizeof(d3dpp));
4012 d3dpp.Windowed = TRUE;
4013 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
4014 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, wnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device);
4015 if (FAILED(hr))
4017 skip("Failed to create IDirect3DDevice9 object %#x\n", hr);
4018 IDirect3D9_Release(d3d);
4019 DestroyWindow(wnd);
4020 return;
4023 hdc = CreateCompatibleDC(NULL);
4025 hFont = CreateFontA(12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
4026 CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, "Arial");
4027 SelectObject(hdc, hFont);
4028 GetOutlineTextMetricsA(hdc, sizeof(otm), &otm);
4030 hr = D3DXCreateTextA(device, hdc, "wine", 0.001f, 0.4f, NULL, NULL, NULL);
4031 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4033 /* D3DXCreateTextA page faults from passing NULL text */
4035 hr = D3DXCreateTextW(device, hdc, NULL, 0.001f, 0.4f, &d3dxmesh, NULL, NULL);
4036 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4038 hr = D3DXCreateTextA(device, hdc, "", 0.001f, 0.4f, &d3dxmesh, NULL, NULL);
4039 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4041 hr = D3DXCreateTextA(device, hdc, " ", 0.001f, 0.4f, &d3dxmesh, NULL, NULL);
4042 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4044 hr = D3DXCreateTextA(NULL, hdc, "wine", 0.001f, 0.4f, &d3dxmesh, NULL, NULL);
4045 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4047 hr = D3DXCreateTextA(device, NULL, "wine", 0.001f, 0.4f, &d3dxmesh, NULL, NULL);
4048 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4050 hr = D3DXCreateTextA(device, hdc, "wine", -FLT_MIN, 0.4f, &d3dxmesh, NULL, NULL);
4051 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4053 hr = D3DXCreateTextA(device, hdc, "wine", 0.001f, -FLT_MIN, &d3dxmesh, NULL, NULL);
4054 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4056 /* deviation = 0.0f treated as if deviation = 1.0f / otm.otmEMSquare */
4057 hr = D3DXCreateTextA(device, hdc, "wine", 1.0f / otm.otmEMSquare, 0.4f, &d3dxmesh, NULL, NULL);
4058 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
4059 number_of_vertices = d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh);
4060 number_of_faces = d3dxmesh->lpVtbl->GetNumFaces(d3dxmesh);
4061 if (SUCCEEDED(hr) && d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh);
4063 hr = D3DXCreateTextA(device, hdc, "wine", 0.0f, 0.4f, &d3dxmesh, NULL, NULL);
4064 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
4065 ok(number_of_vertices == d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh),
4066 "Got %d vertices, expected %d\n",
4067 d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh), number_of_vertices);
4068 ok(number_of_faces == d3dxmesh->lpVtbl->GetNumFaces(d3dxmesh),
4069 "Got %d faces, expected %d\n",
4070 d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh), number_of_faces);
4071 if (SUCCEEDED(hr) && d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh);
4073 if (0)
4075 /* too much detail requested, so will appear to hang */
4076 trace("Waiting for D3DXCreateText to finish with deviation = FLT_MIN ...\n");
4077 hr = D3DXCreateTextA(device, hdc, "wine", FLT_MIN, 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);
4080 trace("D3DXCreateText finish with deviation = FLT_MIN\n");
4083 hr = D3DXCreateTextA(device, hdc, "wine", 0.001f, 0.4f, &d3dxmesh, NULL, NULL);
4084 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
4085 if (SUCCEEDED(hr) && d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh);
4087 test_createtext(device, hdc, "wine", FLT_MAX, 0.4f);
4088 test_createtext(device, hdc, "wine", 0.001f, FLT_MIN);
4089 test_createtext(device, hdc, "wine", 0.001f, 0.0f);
4090 test_createtext(device, hdc, "wine", 0.001f, FLT_MAX);
4091 test_createtext(device, hdc, "wine", 0.0f, 1.0f);
4093 DeleteDC(hdc);
4095 IDirect3DDevice9_Release(device);
4096 IDirect3D9_Release(d3d);
4097 DestroyWindow(wnd);
4100 static void test_get_decl_length(void)
4102 static const D3DVERTEXELEMENT9 declaration1[] =
4104 {0, 0, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4105 {1, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4106 {2, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4107 {3, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4108 {4, 0, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4109 {5, 0, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4110 {6, 0, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4111 {7, 0, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4112 {8, 0, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4113 {9, 0, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4114 {10, 0, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4115 {11, 0, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4116 {12, 0, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4117 {13, 0, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4118 {14, 0, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4119 D3DDECL_END(),
4121 static const D3DVERTEXELEMENT9 declaration2[] =
4123 {0, 8, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4124 {1, 8, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4125 {2, 8, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4126 {3, 8, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4127 {4, 8, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4128 {5, 8, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4129 {6, 8, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4130 {7, 8, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4131 {0, 8, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4132 {1, 8, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4133 {2, 8, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4134 {3, 8, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4135 {4, 8, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4136 {5, 8, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4137 {6, 8, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4138 {7, 8, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4139 D3DDECL_END(),
4141 UINT size;
4143 size = D3DXGetDeclLength(declaration1);
4144 ok(size == 15, "Got size %u, expected 15.\n", size);
4146 size = D3DXGetDeclLength(declaration2);
4147 ok(size == 16, "Got size %u, expected 16.\n", size);
4150 static void test_get_decl_vertex_size(void)
4152 static const D3DVERTEXELEMENT9 declaration1[] =
4154 {0, 0, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4155 {1, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4156 {2, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4157 {3, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4158 {4, 0, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4159 {5, 0, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4160 {6, 0, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4161 {7, 0, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4162 {8, 0, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4163 {9, 0, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4164 {10, 0, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4165 {11, 0, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4166 {12, 0, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4167 {13, 0, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4168 {14, 0, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4169 D3DDECL_END(),
4171 static const D3DVERTEXELEMENT9 declaration2[] =
4173 {0, 8, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4174 {1, 8, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4175 {2, 8, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4176 {3, 8, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4177 {4, 8, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4178 {5, 8, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4179 {6, 8, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4180 {7, 8, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4181 {0, 8, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4182 {1, 8, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4183 {2, 8, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4184 {3, 8, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4185 {4, 8, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4186 {5, 8, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4187 {6, 8, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4188 {7, 8, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4189 D3DDECL_END(),
4191 static const UINT sizes1[] =
4193 4, 8, 12, 16,
4194 4, 4, 4, 8,
4195 4, 4, 8, 4,
4196 4, 4, 8, 0,
4198 static const UINT sizes2[] =
4200 12, 16, 20, 24,
4201 12, 12, 16, 16,
4203 unsigned int i;
4204 UINT size;
4206 size = D3DXGetDeclVertexSize(NULL, 0);
4207 ok(size == 0, "Got size %#x, expected 0.\n", size);
4209 for (i = 0; i < 16; ++i)
4211 size = D3DXGetDeclVertexSize(declaration1, i);
4212 ok(size == sizes1[i], "Got size %u for stream %u, expected %u.\n", size, i, sizes1[i]);
4215 for (i = 0; i < 8; ++i)
4217 size = D3DXGetDeclVertexSize(declaration2, i);
4218 ok(size == sizes2[i], "Got size %u for stream %u, expected %u.\n", size, i, sizes2[i]);
4222 static void D3DXGenerateAdjacencyTest(void)
4224 HRESULT hr;
4225 HWND wnd;
4226 IDirect3D9 *d3d;
4227 IDirect3DDevice9 *device;
4228 D3DPRESENT_PARAMETERS d3dpp;
4229 ID3DXMesh *d3dxmesh = NULL;
4230 D3DXVECTOR3 *vertices = NULL;
4231 WORD *indices = NULL;
4232 int i;
4233 struct {
4234 DWORD num_vertices;
4235 D3DXVECTOR3 vertices[6];
4236 DWORD num_faces;
4237 WORD indices[3 * 3];
4238 FLOAT epsilon;
4239 DWORD adjacency[3 * 3];
4240 } test_data[] = {
4241 { /* for epsilon < 0, indices must match for faces to be adjacent */
4242 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}},
4243 2, {0, 1, 2, 0, 2, 3},
4244 -1.0,
4245 {-1, -1, 1, 0, -1, -1},
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 -1.0,
4251 {-1, -1, -1, -1, -1, -1},
4253 { /* for epsilon == 0, indices or vertices must match for faces to be adjacent */
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.0}, {1.0, 1.0, 0.0}, {0.0, 1.0, 0.0}},
4255 2, {0, 1, 2, 3, 4, 5},
4256 0.0,
4257 {-1, -1, 1, 0, -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.25,
4263 {-1, -1, -1, -1, -1, -1},
4265 { /* for epsilon > 0, vertices must be less than (but NOT equal to) epsilon distance away */
4266 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}},
4267 2, {0, 1, 2, 3, 4, 5},
4268 0.250001,
4269 {-1, -1, 1, 0, -1, -1},
4271 { /* length between vertices are compared to epsilon, not the individual dimension deltas */
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.353, /* < sqrt(0.25*0.25 + 0.25*0.25) */
4275 {-1, -1, -1, -1, -1, -1},
4278 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}},
4279 2, {0, 1, 2, 3, 4, 5},
4280 0.354, /* > sqrt(0.25*0.25 + 0.25*0.25) */
4281 {-1, -1, 1, 0, -1, -1},
4283 { /* adjacent faces must have opposite winding orders at the shared edge */
4284 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}},
4285 2, {0, 1, 2, 0, 3, 2},
4286 0.0,
4287 {-1, -1, -1, -1, -1, -1},
4291 if (!(wnd = CreateWindowA("static", "d3dx9_test", WS_OVERLAPPEDWINDOW, 0, 0,
4292 640, 480, NULL, NULL, NULL, NULL)))
4294 skip("Couldn't create application window\n");
4295 return;
4297 d3d = Direct3DCreate9(D3D_SDK_VERSION);
4298 if (!d3d)
4300 skip("Couldn't create IDirect3D9 object\n");
4301 DestroyWindow(wnd);
4302 return;
4305 ZeroMemory(&d3dpp, sizeof(d3dpp));
4306 d3dpp.Windowed = TRUE;
4307 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
4308 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, wnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device);
4309 if (FAILED(hr))
4311 skip("Failed to create IDirect3DDevice9 object %#x\n", hr);
4312 IDirect3D9_Release(d3d);
4313 DestroyWindow(wnd);
4314 return;
4317 for (i = 0; i < ARRAY_SIZE(test_data); i++)
4319 DWORD adjacency[ARRAY_SIZE(test_data[0].adjacency)];
4320 int j;
4322 if (d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh);
4323 d3dxmesh = NULL;
4325 hr = D3DXCreateMeshFVF(test_data[i].num_faces, test_data[i].num_vertices, 0, D3DFVF_XYZ, device, &d3dxmesh);
4326 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
4328 hr = d3dxmesh->lpVtbl->LockVertexBuffer(d3dxmesh, D3DLOCK_DISCARD, (void**)&vertices);
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(vertices, test_data[i].vertices, test_data[i].num_vertices * sizeof(test_data[0].vertices[0]));
4332 d3dxmesh->lpVtbl->UnlockVertexBuffer(d3dxmesh);
4334 hr = d3dxmesh->lpVtbl->LockIndexBuffer(d3dxmesh, D3DLOCK_DISCARD, (void**)&indices);
4335 ok(hr == D3D_OK, "test %d: Got result %x, expected %x (D3D_OK)\n", i, hr, D3D_OK);
4336 if (FAILED(hr)) continue;
4337 CopyMemory(indices, test_data[i].indices, test_data[i].num_faces * 3 * sizeof(test_data[0].indices[0]));
4338 d3dxmesh->lpVtbl->UnlockIndexBuffer(d3dxmesh);
4340 if (i == 0) {
4341 hr = d3dxmesh->lpVtbl->GenerateAdjacency(d3dxmesh, 0.0f, NULL);
4342 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4345 hr = d3dxmesh->lpVtbl->GenerateAdjacency(d3dxmesh, test_data[i].epsilon, adjacency);
4346 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
4347 if (FAILED(hr)) continue;
4349 for (j = 0; j < test_data[i].num_faces * 3; j++)
4350 ok(adjacency[j] == test_data[i].adjacency[j],
4351 "Test %d adjacency %d: Got result %u, expected %u\n", i, j,
4352 adjacency[j], test_data[i].adjacency[j]);
4354 if (d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh);
4357 static void test_update_semantics(void)
4359 HRESULT hr;
4360 struct test_context *test_context = NULL;
4361 ID3DXMesh *mesh = NULL;
4362 D3DVERTEXELEMENT9 declaration0[] =
4364 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4365 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4366 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4367 D3DDECL_END()
4369 D3DVERTEXELEMENT9 declaration_pos_type_color[] =
4371 {0, 0, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4372 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4373 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4374 D3DDECL_END()
4376 D3DVERTEXELEMENT9 declaration_smaller[] =
4378 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4379 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4380 D3DDECL_END()
4382 D3DVERTEXELEMENT9 declaration_larger[] =
4384 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4385 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4386 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4387 {0, 40, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT, 0},
4388 D3DDECL_END()
4390 D3DVERTEXELEMENT9 declaration_multiple_streams[] =
4392 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4393 {1, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT, 0},
4394 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4395 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4397 D3DDECL_END()
4399 D3DVERTEXELEMENT9 declaration_double_usage[] =
4401 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4402 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4403 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4404 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4405 D3DDECL_END()
4407 D3DVERTEXELEMENT9 declaration_undefined_type[] =
4409 {0, 0, D3DDECLTYPE_UNUSED+1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4410 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4411 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4412 D3DDECL_END()
4414 D3DVERTEXELEMENT9 declaration_not_4_byte_aligned_offset[] =
4416 {0, 3, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4417 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4418 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4419 D3DDECL_END()
4421 static const struct
4423 D3DXVECTOR3 position0;
4424 D3DXVECTOR3 position1;
4425 D3DXVECTOR3 normal;
4426 DWORD color;
4428 vertices[] =
4430 { { 0.0f, 1.0f, 0.f}, { 1.0f, 0.0f, 0.f}, {0.0f, 0.0f, 1.0f}, 0xffff0000 },
4431 { { 1.0f, -1.0f, 0.f}, {-1.0f, -1.0f, 0.f}, {0.0f, 0.0f, 1.0f}, 0xff00ff00 },
4432 { {-1.0f, -1.0f, 0.f}, {-1.0f, 1.0f, 0.f}, {0.0f, 0.0f, 1.0f}, 0xff0000ff },
4434 unsigned int faces[] = {0, 1, 2};
4435 unsigned int attributes[] = {0};
4436 unsigned int num_faces = ARRAY_SIZE(faces) / 3;
4437 unsigned int num_vertices = ARRAY_SIZE(vertices);
4438 int offset = sizeof(D3DXVECTOR3);
4439 DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
4440 void *vertex_buffer;
4441 void *index_buffer;
4442 DWORD *attributes_buffer;
4443 D3DVERTEXELEMENT9 declaration[MAX_FVF_DECL_SIZE];
4444 D3DVERTEXELEMENT9 *decl_ptr;
4445 DWORD exp_vertex_size = sizeof(*vertices);
4446 DWORD vertex_size = 0;
4447 int equal;
4448 int i = 0;
4449 int *decl_mem;
4450 int filler_a = 0xaaaaaaaa;
4451 int filler_b = 0xbbbbbbbb;
4453 test_context = new_test_context();
4454 if (!test_context)
4456 skip("Couldn't create a test_context\n");
4457 goto cleanup;
4460 hr = D3DXCreateMesh(num_faces, num_vertices, options, declaration0,
4461 test_context->device, &mesh);
4462 if (FAILED(hr))
4464 skip("Couldn't create test mesh %#x\n", hr);
4465 goto cleanup;
4468 mesh->lpVtbl->LockVertexBuffer(mesh, 0, &vertex_buffer);
4469 memcpy(vertex_buffer, vertices, sizeof(vertices));
4470 mesh->lpVtbl->UnlockVertexBuffer(mesh);
4472 mesh->lpVtbl->LockIndexBuffer(mesh, 0, &index_buffer);
4473 memcpy(index_buffer, faces, sizeof(faces));
4474 mesh->lpVtbl->UnlockIndexBuffer(mesh);
4476 mesh->lpVtbl->LockAttributeBuffer(mesh, 0, &attributes_buffer);
4477 memcpy(attributes_buffer, attributes, sizeof(attributes));
4478 mesh->lpVtbl->UnlockAttributeBuffer(mesh);
4480 /* Get the declaration and try to change it */
4481 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4482 if (FAILED(hr))
4484 skip("Couldn't get vertex declaration %#x\n", hr);
4485 goto cleanup;
4487 equal = memcmp(declaration, declaration0, sizeof(declaration0));
4488 ok(equal == 0, "Vertex declarations were not equal\n");
4490 for (decl_ptr = declaration; decl_ptr->Stream != 0xFF; decl_ptr++)
4492 if (decl_ptr->Usage == D3DDECLUSAGE_POSITION)
4494 /* Use second vertex position instead of first */
4495 decl_ptr->Offset = offset;
4499 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration);
4500 ok(hr == D3D_OK, "Test UpdateSematics, got %#x expected %#x\n", hr, D3D_OK);
4502 /* Check that declaration was written by getting it again */
4503 memset(declaration, 0, sizeof(declaration));
4504 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4505 if (FAILED(hr))
4507 skip("Couldn't get vertex declaration %#x\n", hr);
4508 goto cleanup;
4511 for (decl_ptr = declaration; decl_ptr->Stream != 0xFF; decl_ptr++)
4513 if (decl_ptr->Usage == D3DDECLUSAGE_POSITION)
4515 ok(decl_ptr->Offset == offset, "Test UpdateSematics, got offset %d expected %d\n",
4516 decl_ptr->Offset, offset);
4520 /* Check that GetDeclaration only writes up to the D3DDECL_END() marker and
4521 * not the full MAX_FVF_DECL_SIZE elements.
4523 memset(declaration, filler_a, sizeof(declaration));
4524 memcpy(declaration, declaration0, sizeof(declaration0));
4525 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration);
4526 ok(hr == D3D_OK, "Test UpdateSematics, "
4527 "got %#x expected D3D_OK\n", hr);
4528 memset(declaration, filler_b, sizeof(declaration));
4529 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4530 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4531 decl_mem = (int*)declaration;
4532 for (i = sizeof(declaration0)/sizeof(*decl_mem); i < sizeof(declaration)/sizeof(*decl_mem); i++)
4534 equal = memcmp(&decl_mem[i], &filler_b, sizeof(filler_b));
4535 ok(equal == 0,
4536 "GetDeclaration wrote past the D3DDECL_END() marker. "
4537 "Got %#x, expected %#x\n", decl_mem[i], filler_b);
4538 if (equal != 0) break;
4541 /* UpdateSemantics does not check for overlapping fields */
4542 memset(declaration, 0, sizeof(declaration));
4543 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4544 if (FAILED(hr))
4546 skip("Couldn't get vertex declaration %#x\n", hr);
4547 goto cleanup;
4550 for (decl_ptr = declaration; decl_ptr->Stream != 0xFF; decl_ptr++)
4552 if (decl_ptr->Type == D3DDECLTYPE_FLOAT3)
4554 decl_ptr->Type = D3DDECLTYPE_FLOAT4;
4558 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration);
4559 ok(hr == D3D_OK, "Test UpdateSematics for overlapping fields, "
4560 "got %#x expected D3D_OK\n", hr);
4562 /* Set the position type to color instead of float3 */
4563 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_pos_type_color);
4564 ok(hr == D3D_OK, "Test UpdateSematics position type color, "
4565 "got %#x expected D3D_OK\n", hr);
4567 /* The following test cases show that NULL, smaller or larger declarations,
4568 * and declarations with non-zero Stream values are not accepted.
4569 * UpdateSemantics returns D3DERR_INVALIDCALL and the previously set
4570 * declaration will be used by DrawSubset, GetNumBytesPerVertex, and
4571 * GetDeclaration.
4574 /* Null declaration (invalid declaration) */
4575 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4576 hr = mesh->lpVtbl->UpdateSemantics(mesh, NULL);
4577 ok(hr == D3DERR_INVALIDCALL, "Test UpdateSematics null pointer declaration, "
4578 "got %#x expected D3DERR_INVALIDCALL\n", hr);
4579 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4580 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4581 vertex_size, exp_vertex_size);
4582 memset(declaration, 0, sizeof(declaration));
4583 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4584 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4585 equal = memcmp(declaration, declaration0, sizeof(declaration0));
4586 ok(equal == 0, "Vertex declarations were not equal\n");
4588 /* Smaller vertex declaration (invalid declaration) */
4589 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4590 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_smaller);
4591 ok(hr == D3DERR_INVALIDCALL, "Test UpdateSematics for smaller vertex declaration, "
4592 "got %#x expected D3DERR_INVALIDCALL\n", hr);
4593 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4594 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4595 vertex_size, exp_vertex_size);
4596 memset(declaration, 0, sizeof(declaration));
4597 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4598 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4599 equal = memcmp(declaration, declaration0, sizeof(declaration0));
4600 ok(equal == 0, "Vertex declarations were not equal\n");
4602 /* Larger vertex declaration (invalid declaration) */
4603 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4604 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_larger);
4605 ok(hr == D3DERR_INVALIDCALL, "Test UpdateSematics for larger vertex declaration, "
4606 "got %#x expected D3DERR_INVALIDCALL\n", hr);
4607 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4608 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4609 vertex_size, exp_vertex_size);
4610 memset(declaration, 0, sizeof(declaration));
4611 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4612 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4613 equal = memcmp(declaration, declaration0, sizeof(declaration0));
4614 ok(equal == 0, "Vertex declarations were not equal\n");
4616 /* Use multiple streams and keep the same vertex size (invalid declaration) */
4617 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4618 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_multiple_streams);
4619 ok(hr == D3DERR_INVALIDCALL, "Test UpdateSematics using multiple streams, "
4620 "got %#x expected D3DERR_INVALIDCALL\n", hr);
4621 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4622 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4623 vertex_size, exp_vertex_size);
4624 memset(declaration, 0, sizeof(declaration));
4625 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4626 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4627 equal = memcmp(declaration, declaration0, sizeof(declaration0));
4628 ok(equal == 0, "Vertex declarations were not equal\n");
4630 /* The next following test cases show that some invalid declarations are
4631 * accepted with a D3D_OK. An access violation is thrown on Windows if
4632 * DrawSubset is called. The methods GetNumBytesPerVertex and GetDeclaration
4633 * are not affected, which indicates that the declaration is cached.
4636 /* Double usage (invalid declaration) */
4637 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4638 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_double_usage);
4639 ok(hr == D3D_OK, "Test UpdateSematics double usage, "
4640 "got %#x expected D3D_OK\n", hr);
4641 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4642 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4643 vertex_size, exp_vertex_size);
4644 memset(declaration, 0, sizeof(declaration));
4645 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4646 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4647 equal = memcmp(declaration, declaration_double_usage, sizeof(declaration_double_usage));
4648 ok(equal == 0, "Vertex declarations were not equal\n");
4650 /* Set the position to an undefined type (invalid declaration) */
4651 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4652 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_undefined_type);
4653 ok(hr == D3D_OK, "Test UpdateSematics undefined type, "
4654 "got %#x expected D3D_OK\n", hr);
4655 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4656 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4657 vertex_size, exp_vertex_size);
4658 memset(declaration, 0, sizeof(declaration));
4659 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4660 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4661 equal = memcmp(declaration, declaration_undefined_type, sizeof(declaration_undefined_type));
4662 ok(equal == 0, "Vertex declarations were not equal\n");
4664 /* Use a not 4 byte aligned offset (invalid declaration) */
4665 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4666 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_not_4_byte_aligned_offset);
4667 ok(hr == D3D_OK, "Test UpdateSematics not 4 byte aligned offset, "
4668 "got %#x expected D3D_OK\n", hr);
4669 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4670 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4671 vertex_size, exp_vertex_size);
4672 memset(declaration, 0, sizeof(declaration));
4673 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4674 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4675 equal = memcmp(declaration, declaration_not_4_byte_aligned_offset,
4676 sizeof(declaration_not_4_byte_aligned_offset));
4677 ok(equal == 0, "Vertex declarations were not equal\n");
4679 cleanup:
4680 if (mesh)
4681 mesh->lpVtbl->Release(mesh);
4683 free_test_context(test_context);
4686 static void test_create_skin_info(void)
4688 HRESULT hr;
4689 ID3DXSkinInfo *skininfo = NULL;
4690 D3DVERTEXELEMENT9 empty_declaration[] = { D3DDECL_END() };
4691 D3DVERTEXELEMENT9 declaration_out[MAX_FVF_DECL_SIZE];
4692 const D3DVERTEXELEMENT9 declaration_with_nonzero_stream[] = {
4693 {1, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
4694 D3DDECL_END()
4697 hr = D3DXCreateSkinInfo(0, empty_declaration, 0, &skininfo);
4698 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4699 if (skininfo) IUnknown_Release(skininfo);
4700 skininfo = NULL;
4702 hr = D3DXCreateSkinInfo(1, NULL, 1, &skininfo);
4703 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4705 hr = D3DXCreateSkinInfo(1, declaration_with_nonzero_stream, 1, &skininfo);
4706 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4708 hr = D3DXCreateSkinInfoFVF(1, 0, 1, &skininfo);
4709 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4710 if (skininfo)
4712 DWORD dword_result;
4713 float flt_result;
4714 const char *string_result;
4715 D3DXMATRIX *transform;
4716 D3DXMATRIX identity_matrix;
4718 /* test initial values */
4719 hr = skininfo->lpVtbl->GetDeclaration(skininfo, declaration_out);
4720 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4721 if (SUCCEEDED(hr))
4722 compare_elements(declaration_out, empty_declaration, __LINE__, 0);
4724 dword_result = skininfo->lpVtbl->GetNumBones(skininfo);
4725 ok(dword_result == 1, "Expected 1, got %u\n", dword_result);
4727 flt_result = skininfo->lpVtbl->GetMinBoneInfluence(skininfo);
4728 ok(flt_result == 0.0f, "Expected 0.0, got %g\n", flt_result);
4730 string_result = skininfo->lpVtbl->GetBoneName(skininfo, 0);
4731 ok(string_result == NULL, "Expected NULL, got %p\n", string_result);
4733 dword_result = skininfo->lpVtbl->GetFVF(skininfo);
4734 ok(dword_result == 0, "Expected 0, got %u\n", dword_result);
4736 dword_result = skininfo->lpVtbl->GetNumBoneInfluences(skininfo, 0);
4737 ok(dword_result == 0, "Expected 0, got %u\n", dword_result);
4739 dword_result = skininfo->lpVtbl->GetNumBoneInfluences(skininfo, 1);
4740 ok(dword_result == 0, "Expected 0, got %u\n", dword_result);
4742 transform = skininfo->lpVtbl->GetBoneOffsetMatrix(skininfo, -1);
4743 ok(transform == NULL, "Expected NULL, got %p\n", transform);
4746 /* test [GS]etBoneOffsetMatrix */
4747 hr = skininfo->lpVtbl->SetBoneOffsetMatrix(skininfo, 1, &identity_matrix);
4748 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4750 hr = skininfo->lpVtbl->SetBoneOffsetMatrix(skininfo, 0, NULL);
4751 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4753 D3DXMatrixIdentity(&identity_matrix);
4754 hr = skininfo->lpVtbl->SetBoneOffsetMatrix(skininfo, 0, &identity_matrix);
4755 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4757 transform = skininfo->lpVtbl->GetBoneOffsetMatrix(skininfo, 0);
4758 check_matrix(transform, &identity_matrix);
4762 /* test [GS]etBoneName */
4763 const char *name_in = "testBoneName";
4764 const char *string_result2;
4766 hr = skininfo->lpVtbl->SetBoneName(skininfo, 1, name_in);
4767 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4769 hr = skininfo->lpVtbl->SetBoneName(skininfo, 0, NULL);
4770 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4772 hr = skininfo->lpVtbl->SetBoneName(skininfo, 0, name_in);
4773 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4775 string_result = skininfo->lpVtbl->GetBoneName(skininfo, 0);
4776 ok(string_result != NULL, "Expected non-NULL string, got %p\n", string_result);
4777 ok(!strcmp(string_result, name_in), "Expected '%s', got '%s'\n", name_in, string_result);
4779 string_result2 = skininfo->lpVtbl->GetBoneName(skininfo, 0);
4780 ok(string_result == string_result2, "Expected %p, got %p\n", string_result, string_result2);
4782 string_result = skininfo->lpVtbl->GetBoneName(skininfo, 1);
4783 ok(string_result == NULL, "Expected NULL, got %p\n", string_result);
4787 /* test [GS]etBoneInfluence */
4788 DWORD vertices[2];
4789 FLOAT weights[2];
4790 int i;
4791 DWORD num_influences;
4792 DWORD exp_vertices[2];
4793 FLOAT exp_weights[2];
4795 /* vertex and weight arrays untouched when num_influences is 0 */
4796 vertices[0] = 0xdeadbeef;
4797 weights[0] = FLT_MAX;
4798 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, vertices, weights);
4799 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4800 ok(vertices[0] == 0xdeadbeef, "expected 0xdeadbeef, got %#x\n", vertices[0]);
4801 ok(weights[0] == FLT_MAX, "expected %g, got %g\n", FLT_MAX, weights[0]);
4803 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 1, vertices, weights);
4804 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4806 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, NULL, NULL);
4807 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4809 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, vertices, NULL);
4810 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4812 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, NULL, weights);
4813 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4816 /* no vertex or weight value checking */
4817 exp_vertices[0] = 0;
4818 exp_vertices[1] = 0x87654321;
4819 exp_weights[0] = 0.5;
4820 exp_weights[1] = NAN;
4821 num_influences = 2;
4823 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 1, num_influences, vertices, weights);
4824 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4826 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, num_influences, NULL, weights);
4827 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4829 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, num_influences, vertices, NULL);
4830 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4832 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, num_influences, NULL, NULL);
4833 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4835 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, num_influences, exp_vertices, exp_weights);
4836 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4838 memset(vertices, 0, sizeof(vertices));
4839 memset(weights, 0, sizeof(weights));
4840 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, vertices, weights);
4841 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4842 for (i = 0; i < num_influences; i++) {
4843 ok(exp_vertices[i] == vertices[i],
4844 "influence[%d]: expected vertex %u, got %u\n", i, exp_vertices[i], vertices[i]);
4845 ok((isnan(exp_weights[i]) && isnan(weights[i])) || exp_weights[i] == weights[i],
4846 "influence[%d]: expected weights %g, got %g\n", i, exp_weights[i], weights[i]);
4849 /* vertices and weights aren't returned after setting num_influences to 0 */
4850 memset(vertices, 0, sizeof(vertices));
4851 memset(weights, 0, sizeof(weights));
4852 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, 0, vertices, weights);
4853 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4855 vertices[0] = 0xdeadbeef;
4856 weights[0] = FLT_MAX;
4857 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, vertices, weights);
4858 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4859 ok(vertices[0] == 0xdeadbeef, "expected vertex 0xdeadbeef, got %u\n", vertices[0]);
4860 ok(weights[0] == FLT_MAX, "expected weight %g, got %g\n", FLT_MAX, weights[0]);
4864 /* test [GS]etFVF and [GS]etDeclaration */
4865 D3DVERTEXELEMENT9 declaration_in[MAX_FVF_DECL_SIZE];
4866 DWORD fvf = D3DFVF_XYZ;
4867 DWORD got_fvf;
4869 hr = skininfo->lpVtbl->SetDeclaration(skininfo, NULL);
4870 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4872 hr = skininfo->lpVtbl->SetDeclaration(skininfo, declaration_with_nonzero_stream);
4873 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4875 hr = skininfo->lpVtbl->SetFVF(skininfo, 0);
4876 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4878 hr = D3DXDeclaratorFromFVF(fvf, declaration_in);
4879 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4880 hr = skininfo->lpVtbl->SetDeclaration(skininfo, declaration_in);
4881 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4882 got_fvf = skininfo->lpVtbl->GetFVF(skininfo);
4883 ok(fvf == got_fvf, "Expected %#x, got %#x\n", fvf, got_fvf);
4884 hr = skininfo->lpVtbl->GetDeclaration(skininfo, declaration_out);
4885 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4886 compare_elements(declaration_out, declaration_in, __LINE__, 0);
4888 hr = skininfo->lpVtbl->SetDeclaration(skininfo, empty_declaration);
4889 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4890 got_fvf = skininfo->lpVtbl->GetFVF(skininfo);
4891 ok(got_fvf == 0, "Expected 0, got %#x\n", got_fvf);
4892 hr = skininfo->lpVtbl->GetDeclaration(skininfo, declaration_out);
4893 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4894 compare_elements(declaration_out, empty_declaration, __LINE__, 0);
4896 hr = skininfo->lpVtbl->SetFVF(skininfo, fvf);
4897 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4898 got_fvf = skininfo->lpVtbl->GetFVF(skininfo);
4899 ok(fvf == got_fvf, "Expected %#x, got %#x\n", fvf, got_fvf);
4900 hr = skininfo->lpVtbl->GetDeclaration(skininfo, declaration_out);
4901 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4902 compare_elements(declaration_out, declaration_in, __LINE__, 0);
4905 if (skininfo) IUnknown_Release(skininfo);
4906 skininfo = NULL;
4908 hr = D3DXCreateSkinInfoFVF(1, D3DFVF_XYZ, 1, NULL);
4909 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4911 hr = D3DXCreateSkinInfo(1, NULL, 1, &skininfo);
4912 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4915 static void test_convert_adjacency_to_point_reps(void)
4917 HRESULT hr;
4918 struct test_context *test_context = NULL;
4919 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
4920 const DWORD options_16bit = D3DXMESH_SYSTEMMEM;
4921 const D3DVERTEXELEMENT9 declaration[] =
4923 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4924 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4925 {0, 24, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4926 D3DDECL_END()
4928 const unsigned int VERTS_PER_FACE = 3;
4929 void *vertex_buffer;
4930 void *index_buffer;
4931 DWORD *attributes_buffer;
4932 int i, j;
4933 enum color { RED = 0xffff0000, GREEN = 0xff00ff00, BLUE = 0xff0000ff};
4934 struct vertex_pnc
4936 D3DXVECTOR3 position;
4937 D3DXVECTOR3 normal;
4938 enum color color; /* In case of manual visual inspection */
4940 D3DXVECTOR3 up = {0.0f, 0.0f, 1.0f};
4941 /* mesh0 (one face)
4943 * 0--1
4944 * | /
4945 * |/
4948 const struct vertex_pnc vertices0[] =
4950 {{ 0.0f, 3.0f, 0.f}, up, RED},
4951 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
4952 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
4954 const DWORD indices0[] = {0, 1, 2};
4955 const unsigned int num_vertices0 = ARRAY_SIZE(vertices0);
4956 const unsigned int num_faces0 = ARRAY_SIZE(indices0) / VERTS_PER_FACE;
4957 const DWORD adjacency0[] = {-1, -1, -1};
4958 const DWORD exp_point_rep0[] = {0, 1, 2};
4959 /* mesh1 (right)
4961 * 0--1 3
4962 * | / /|
4963 * |/ / |
4964 * 2 5--4
4966 const struct vertex_pnc vertices1[] =
4968 {{ 0.0f, 3.0f, 0.f}, up, RED},
4969 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
4970 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
4972 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
4973 {{ 3.0f, 0.0f, 0.f}, up, RED},
4974 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
4976 const DWORD indices1[] = {0, 1, 2, 3, 4, 5};
4977 const unsigned int num_vertices1 = ARRAY_SIZE(vertices1);
4978 const unsigned int num_faces1 = ARRAY_SIZE(indices1) / VERTS_PER_FACE;
4979 const DWORD adjacency1[] = {-1, 1, -1, -1, -1, 0};
4980 const DWORD exp_point_rep1[] = {0, 1, 2, 1, 4, 2};
4981 /* mesh2 (left)
4983 * 3 0--1
4984 * /| | /
4985 * / | |/
4986 * 5--4 2
4988 const struct vertex_pnc vertices2[] =
4990 {{ 0.0f, 3.0f, 0.f}, up, RED},
4991 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
4992 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
4994 {{-1.0f, 3.0f, 0.f}, up, RED},
4995 {{-1.0f, 0.0f, 0.f}, up, GREEN},
4996 {{-3.0f, 0.0f, 0.f}, up, BLUE},
4998 const DWORD indices2[] = {0, 1, 2, 3, 4, 5};
4999 const unsigned int num_vertices2 = ARRAY_SIZE(vertices2);
5000 const unsigned int num_faces2 = ARRAY_SIZE(indices2) / VERTS_PER_FACE;
5001 const DWORD adjacency2[] = {-1, -1, 1, 0, -1, -1};
5002 const DWORD exp_point_rep2[] = {0, 1, 2, 0, 2, 5};
5003 /* mesh3 (above)
5006 * /|
5007 * / |
5008 * 5--4
5009 * 0--1
5010 * | /
5011 * |/
5014 struct vertex_pnc vertices3[] =
5016 {{ 0.0f, 3.0f, 0.f}, up, RED},
5017 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5018 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5020 {{ 2.0f, 7.0f, 0.f}, up, BLUE},
5021 {{ 2.0f, 4.0f, 0.f}, up, GREEN},
5022 {{ 0.0f, 4.0f, 0.f}, up, RED},
5024 const DWORD indices3[] = {0, 1, 2, 3, 4, 5};
5025 const unsigned int num_vertices3 = ARRAY_SIZE(vertices3);
5026 const unsigned int num_faces3 = ARRAY_SIZE(indices3) / VERTS_PER_FACE;
5027 const DWORD adjacency3[] = {1, -1, -1, -1, 0, -1};
5028 const DWORD exp_point_rep3[] = {0, 1, 2, 3, 1, 0};
5029 /* mesh4 (below, tip against tip)
5031 * 0--1
5032 * | /
5033 * |/
5036 * |\
5037 * | \
5038 * 5--4
5040 struct vertex_pnc vertices4[] =
5042 {{ 0.0f, 3.0f, 0.f}, up, RED},
5043 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5044 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5046 {{ 0.0f, -4.0f, 0.f}, up, BLUE},
5047 {{ 2.0f, -7.0f, 0.f}, up, GREEN},
5048 {{ 0.0f, -7.0f, 0.f}, up, RED},
5050 const DWORD indices4[] = {0, 1, 2, 3, 4, 5};
5051 const unsigned int num_vertices4 = ARRAY_SIZE(vertices4);
5052 const unsigned int num_faces4 = ARRAY_SIZE(indices4) / VERTS_PER_FACE;
5053 const DWORD adjacency4[] = {-1, -1, -1, -1, -1, -1};
5054 const DWORD exp_point_rep4[] = {0, 1, 2, 3, 4, 5};
5055 /* mesh5 (gap in mesh)
5057 * 0 3-----4 15
5058 * / \ \ / / \
5059 * / \ \ / / \
5060 * 2-----1 5 17-----16
5061 * 6-----7 9 12-----13
5062 * \ / / \ \ /
5063 * \ / / \ \ /
5064 * 8 10-----11 14
5067 const struct vertex_pnc vertices5[] =
5069 {{ 0.0f, 1.0f, 0.f}, up, RED},
5070 {{ 1.0f, -1.0f, 0.f}, up, GREEN},
5071 {{-1.0f, -1.0f, 0.f}, up, BLUE},
5073 {{ 0.1f, 1.0f, 0.f}, up, RED},
5074 {{ 2.1f, 1.0f, 0.f}, up, BLUE},
5075 {{ 1.1f, -1.0f, 0.f}, up, GREEN},
5077 {{-1.0f, -1.1f, 0.f}, up, BLUE},
5078 {{ 1.0f, -1.1f, 0.f}, up, GREEN},
5079 {{ 0.0f, -3.1f, 0.f}, up, RED},
5081 {{ 1.1f, -1.1f, 0.f}, up, GREEN},
5082 {{ 2.1f, -3.1f, 0.f}, up, BLUE},
5083 {{ 0.1f, -3.1f, 0.f}, up, RED},
5085 {{ 1.2f, -1.1f, 0.f}, up, GREEN},
5086 {{ 3.2f, -1.1f, 0.f}, up, RED},
5087 {{ 2.2f, -3.1f, 0.f}, up, BLUE},
5089 {{ 2.2f, 1.0f, 0.f}, up, BLUE},
5090 {{ 3.2f, -1.0f, 0.f}, up, RED},
5091 {{ 1.2f, -1.0f, 0.f}, up, GREEN},
5093 const DWORD indices5[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17};
5094 const unsigned int num_vertices5 = ARRAY_SIZE(vertices5);
5095 const unsigned int num_faces5 = ARRAY_SIZE(indices5) / VERTS_PER_FACE;
5096 const DWORD adjacency5[] = {-1, 2, -1, -1, 5, -1, 0, -1, -1, 4, -1, -1, 5, -1, 3, -1, 4, 1};
5097 const DWORD exp_point_rep5[] = {0, 1, 2, 3, 4, 5, 2, 1, 8, 5, 10, 11, 5, 13, 10, 4, 13, 5};
5098 const WORD indices5_16bit[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17};
5099 /* mesh6 (indices re-ordering)
5101 * 0--1 6 3
5102 * | / /| |\
5103 * |/ / | | \
5104 * 2 8--7 5--4
5106 const struct vertex_pnc vertices6[] =
5108 {{ 0.0f, 3.0f, 0.f}, up, RED},
5109 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5110 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5112 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5113 {{ 3.0f, 0.0f, 0.f}, up, RED},
5114 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5116 {{ 4.0f, 3.0f, 0.f}, up, GREEN},
5117 {{ 6.0f, 0.0f, 0.f}, up, BLUE},
5118 {{ 4.0f, 0.0f, 0.f}, up, RED},
5120 const DWORD indices6[] = {0, 1, 2, 6, 7, 8, 3, 4, 5};
5121 const unsigned int num_vertices6 = ARRAY_SIZE(vertices6);
5122 const unsigned int num_faces6 = ARRAY_SIZE(indices6) / VERTS_PER_FACE;
5123 const DWORD adjacency6[] = {-1, 1, -1, 2, -1, 0, -1, -1, 1};
5124 const DWORD exp_point_rep6[] = {0, 1, 2, 1, 4, 5, 1, 5, 2};
5125 /* mesh7 (expands collapsed triangle)
5127 * 0--1 3
5128 * | / /|
5129 * |/ / |
5130 * 2 5--4
5132 const struct vertex_pnc vertices7[] =
5134 {{ 0.0f, 3.0f, 0.f}, up, RED},
5135 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5136 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5138 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5139 {{ 3.0f, 0.0f, 0.f}, up, RED},
5140 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5142 const DWORD indices7[] = {0, 1, 2, 3, 3, 3}; /* Face 1 is collapsed*/
5143 const unsigned int num_vertices7 = ARRAY_SIZE(vertices7);
5144 const unsigned int num_faces7 = ARRAY_SIZE(indices7) / VERTS_PER_FACE;
5145 const DWORD adjacency7[] = {-1, -1, -1, -1, -1, -1};
5146 const DWORD exp_point_rep7[] = {0, 1, 2, 3, 4, 5};
5147 /* mesh8 (indices re-ordering and double replacement)
5149 * 0--1 9 6
5150 * | / /| |\
5151 * |/ / | | \
5152 * 2 11-10 8--7
5153 * 3--4
5154 * | /
5155 * |/
5158 const struct vertex_pnc vertices8[] =
5160 {{ 0.0f, 3.0f, 0.f}, up, RED},
5161 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5162 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5164 {{ 4.0, -4.0, 0.f}, up, RED},
5165 {{ 6.0, -4.0, 0.f}, up, BLUE},
5166 {{ 4.0, -7.0, 0.f}, up, GREEN},
5168 {{ 4.0f, 3.0f, 0.f}, up, GREEN},
5169 {{ 6.0f, 0.0f, 0.f}, up, BLUE},
5170 {{ 4.0f, 0.0f, 0.f}, up, RED},
5172 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5173 {{ 3.0f, 0.0f, 0.f}, up, RED},
5174 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5176 const DWORD indices8[] = {0, 1, 2, 9, 10, 11, 6, 7, 8, 3, 4, 5};
5177 const unsigned int num_vertices8 = ARRAY_SIZE(vertices8);
5178 const unsigned int num_faces8 = ARRAY_SIZE(indices8) / VERTS_PER_FACE;
5179 const DWORD adjacency8[] = {-1, 1, -1, 2, -1, 0, -1, 3, 1, 2, -1, -1};
5180 const DWORD exp_point_rep8[] = {0, 1, 2, 3, 4, 5, 1, 4, 3, 1, 3, 2};
5181 /* mesh9 (right, shared vertices)
5183 * 0--1
5184 * | /|
5185 * |/ |
5186 * 2--3
5188 const struct vertex_pnc vertices9[] =
5190 {{ 0.0f, 3.0f, 0.f}, up, RED},
5191 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5192 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5194 {{ 2.0f, 0.0f, 0.f}, up, RED},
5196 const DWORD indices9[] = {0, 1, 2, 1, 3, 2};
5197 const unsigned int num_vertices9 = ARRAY_SIZE(vertices9);
5198 const unsigned int num_faces9 = ARRAY_SIZE(indices9) / VERTS_PER_FACE;
5199 const DWORD adjacency9[] = {-1, 1, -1, -1, -1, 0};
5200 const DWORD exp_point_rep9[] = {0, 1, 2, 3};
5201 /* All mesh data */
5202 ID3DXMesh *mesh = NULL;
5203 ID3DXMesh *mesh_null_check = NULL;
5204 unsigned int attributes[] = {0};
5205 struct
5207 const struct vertex_pnc *vertices;
5208 const DWORD *indices;
5209 const DWORD num_vertices;
5210 const DWORD num_faces;
5211 const DWORD *adjacency;
5212 const DWORD *exp_point_reps;
5213 const DWORD options;
5215 tc[] =
5218 vertices0,
5219 indices0,
5220 num_vertices0,
5221 num_faces0,
5222 adjacency0,
5223 exp_point_rep0,
5224 options
5227 vertices1,
5228 indices1,
5229 num_vertices1,
5230 num_faces1,
5231 adjacency1,
5232 exp_point_rep1,
5233 options
5236 vertices2,
5237 indices2,
5238 num_vertices2,
5239 num_faces2,
5240 adjacency2,
5241 exp_point_rep2,
5242 options
5245 vertices3,
5246 indices3,
5247 num_vertices3,
5248 num_faces3,
5249 adjacency3,
5250 exp_point_rep3,
5251 options
5254 vertices4,
5255 indices4,
5256 num_vertices4,
5257 num_faces4,
5258 adjacency4,
5259 exp_point_rep4,
5260 options
5263 vertices5,
5264 indices5,
5265 num_vertices5,
5266 num_faces5,
5267 adjacency5,
5268 exp_point_rep5,
5269 options
5272 vertices6,
5273 indices6,
5274 num_vertices6,
5275 num_faces6,
5276 adjacency6,
5277 exp_point_rep6,
5278 options
5281 vertices7,
5282 indices7,
5283 num_vertices7,
5284 num_faces7,
5285 adjacency7,
5286 exp_point_rep7,
5287 options
5290 vertices8,
5291 indices8,
5292 num_vertices8,
5293 num_faces8,
5294 adjacency8,
5295 exp_point_rep8,
5296 options
5299 vertices9,
5300 indices9,
5301 num_vertices9,
5302 num_faces9,
5303 adjacency9,
5304 exp_point_rep9,
5305 options
5308 vertices5,
5309 (DWORD*)indices5_16bit,
5310 num_vertices5,
5311 num_faces5,
5312 adjacency5,
5313 exp_point_rep5,
5314 options_16bit
5317 DWORD *point_reps = NULL;
5319 test_context = new_test_context();
5320 if (!test_context)
5322 skip("Couldn't create test context\n");
5323 goto cleanup;
5326 for (i = 0; i < ARRAY_SIZE(tc); i++)
5328 hr = D3DXCreateMesh(tc[i].num_faces, tc[i].num_vertices, tc[i].options, declaration,
5329 test_context->device, &mesh);
5330 if (FAILED(hr))
5332 skip("Couldn't create mesh %d. Got %x expected D3D_OK\n", i, hr);
5333 goto cleanup;
5336 if (i == 0) /* Save first mesh for later NULL checks */
5337 mesh_null_check = mesh;
5339 point_reps = HeapAlloc(GetProcessHeap(), 0, tc[i].num_vertices * sizeof(*point_reps));
5340 if (!point_reps)
5342 skip("Couldn't allocate point reps array.\n");
5343 goto cleanup;
5346 hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, &vertex_buffer);
5347 if (FAILED(hr))
5349 skip("Couldn't lock vertex buffer.\n");
5350 goto cleanup;
5352 memcpy(vertex_buffer, tc[i].vertices, tc[i].num_vertices * sizeof(*tc[i].vertices));
5353 hr = mesh->lpVtbl->UnlockVertexBuffer(mesh);
5354 if (FAILED(hr))
5356 skip("Couldn't unlock vertex buffer.\n");
5357 goto cleanup;
5360 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, &index_buffer);
5361 if (FAILED(hr))
5363 skip("Couldn't lock index buffer.\n");
5364 goto cleanup;
5366 if (tc[i].options & D3DXMESH_32BIT)
5368 memcpy(index_buffer, tc[i].indices, VERTS_PER_FACE * tc[i].num_faces * sizeof(DWORD));
5370 else
5372 memcpy(index_buffer, tc[i].indices, VERTS_PER_FACE * tc[i].num_faces * sizeof(WORD));
5374 hr = mesh->lpVtbl->UnlockIndexBuffer(mesh);
5375 if (FAILED(hr)) {
5376 skip("Couldn't unlock index buffer.\n");
5377 goto cleanup;
5380 hr = mesh->lpVtbl->LockAttributeBuffer(mesh, 0, &attributes_buffer);
5381 if (FAILED(hr))
5383 skip("Couldn't lock attributes buffer.\n");
5384 goto cleanup;
5386 memcpy(attributes_buffer, attributes, sizeof(attributes));
5387 hr = mesh->lpVtbl->UnlockAttributeBuffer(mesh);
5388 if (FAILED(hr))
5390 skip("Couldn't unlock attributes buffer.\n");
5391 goto cleanup;
5394 /* Convert adjacency to point representation */
5395 for (j = 0; j < tc[i].num_vertices; j++) point_reps[j] = -1;
5396 hr = mesh->lpVtbl->ConvertAdjacencyToPointReps(mesh, tc[i].adjacency, point_reps);
5397 ok(hr == D3D_OK, "ConvertAdjacencyToPointReps failed case %d. "
5398 "Got %x expected D3D_OK\n", i, hr);
5400 /* Check point representation */
5401 for (j = 0; j < tc[i].num_vertices; j++)
5403 ok(point_reps[j] == tc[i].exp_point_reps[j],
5404 "Unexpected point representation at (%d, %d)."
5405 " Got %d expected %d\n",
5406 i, j, point_reps[j], tc[i].exp_point_reps[j]);
5409 HeapFree(GetProcessHeap(), 0, point_reps);
5410 point_reps = NULL;
5412 if (i != 0) /* First mesh will be freed during cleanup */
5413 mesh->lpVtbl->Release(mesh);
5416 /* NULL checks */
5417 hr = mesh_null_check->lpVtbl->ConvertAdjacencyToPointReps(mesh_null_check, tc[0].adjacency, NULL);
5418 ok(hr == D3DERR_INVALIDCALL, "ConvertAdjacencyToPointReps point_reps NULL. "
5419 "Got %x expected D3DERR_INVALIDCALL\n", hr);
5420 hr = mesh_null_check->lpVtbl->ConvertAdjacencyToPointReps(mesh_null_check, NULL, NULL);
5421 ok(hr == D3DERR_INVALIDCALL, "ConvertAdjacencyToPointReps adjacency and point_reps NULL. "
5422 "Got %x expected D3DERR_INVALIDCALL\n", hr);
5424 cleanup:
5425 if (mesh_null_check)
5426 mesh_null_check->lpVtbl->Release(mesh_null_check);
5427 HeapFree(GetProcessHeap(), 0, point_reps);
5428 free_test_context(test_context);
5431 static void test_convert_point_reps_to_adjacency(void)
5433 HRESULT hr;
5434 struct test_context *test_context = NULL;
5435 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
5436 const DWORD options_16bit = D3DXMESH_SYSTEMMEM;
5437 const D3DVERTEXELEMENT9 declaration[] =
5439 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
5440 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
5441 {0, 24, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
5442 D3DDECL_END()
5444 const unsigned int VERTS_PER_FACE = 3;
5445 void *vertex_buffer;
5446 void *index_buffer;
5447 DWORD *attributes_buffer;
5448 int i, j;
5449 enum color { RED = 0xffff0000, GREEN = 0xff00ff00, BLUE = 0xff0000ff};
5450 struct vertex_pnc
5452 D3DXVECTOR3 position;
5453 D3DXVECTOR3 normal;
5454 enum color color; /* In case of manual visual inspection */
5456 D3DXVECTOR3 up = {0.0f, 0.0f, 1.0f};
5457 /* mesh0 (one face)
5459 * 0--1
5460 * | /
5461 * |/
5464 const struct vertex_pnc vertices0[] =
5466 {{ 0.0f, 3.0f, 0.f}, up, RED},
5467 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5468 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5470 const DWORD indices0[] = {0, 1, 2};
5471 const unsigned int num_vertices0 = ARRAY_SIZE(vertices0);
5472 const unsigned int num_faces0 = num_vertices0 / VERTS_PER_FACE;
5473 const DWORD exp_adjacency0[] = {-1, -1, -1};
5474 const DWORD exp_id_adjacency0[] = {-1, -1, -1};
5475 const DWORD point_rep0[] = {0, 1, 2};
5476 /* mesh1 (right)
5478 * 0--1 3
5479 * | / /|
5480 * |/ / |
5481 * 2 5--4
5483 const struct vertex_pnc vertices1[] =
5485 {{ 0.0f, 3.0f, 0.f}, up, RED},
5486 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5487 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5489 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5490 {{ 3.0f, 0.0f, 0.f}, up, RED},
5491 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5493 const DWORD indices1[] = {0, 1, 2, 3, 4, 5};
5494 const unsigned int num_vertices1 = ARRAY_SIZE(vertices1);
5495 const unsigned int num_faces1 = num_vertices1 / VERTS_PER_FACE;
5496 const DWORD exp_adjacency1[] = {-1, 1, -1, -1, -1, 0};
5497 const DWORD exp_id_adjacency1[] = {-1, -1, -1, -1, -1, -1};
5498 const DWORD point_rep1[] = {0, 1, 2, 1, 4, 2};
5499 /* mesh2 (left)
5501 * 3 0--1
5502 * /| | /
5503 * / | |/
5504 * 5--4 2
5506 const struct vertex_pnc vertices2[] =
5508 {{ 0.0f, 3.0f, 0.f}, up, RED},
5509 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5510 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5512 {{-1.0f, 3.0f, 0.f}, up, RED},
5513 {{-1.0f, 0.0f, 0.f}, up, GREEN},
5514 {{-3.0f, 0.0f, 0.f}, up, BLUE},
5516 const DWORD indices2[] = {0, 1, 2, 3, 4, 5};
5517 const unsigned int num_vertices2 = ARRAY_SIZE(vertices2);
5518 const unsigned int num_faces2 = num_vertices2 / VERTS_PER_FACE;
5519 const DWORD exp_adjacency2[] = {-1, -1, 1, 0, -1, -1};
5520 const DWORD exp_id_adjacency2[] = {-1, -1, -1, -1, -1, -1};
5521 const DWORD point_rep2[] = {0, 1, 2, 0, 2, 5};
5522 /* mesh3 (above)
5525 * /|
5526 * / |
5527 * 5--4
5528 * 0--1
5529 * | /
5530 * |/
5533 struct vertex_pnc vertices3[] =
5535 {{ 0.0f, 3.0f, 0.f}, up, RED},
5536 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5537 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5539 {{ 2.0f, 7.0f, 0.f}, up, BLUE},
5540 {{ 2.0f, 4.0f, 0.f}, up, GREEN},
5541 {{ 0.0f, 4.0f, 0.f}, up, RED},
5543 const DWORD indices3[] = {0, 1, 2, 3, 4, 5};
5544 const unsigned int num_vertices3 = ARRAY_SIZE(vertices3);
5545 const unsigned int num_faces3 = num_vertices3 / VERTS_PER_FACE;
5546 const DWORD exp_adjacency3[] = {1, -1, -1, -1, 0, -1};
5547 const DWORD exp_id_adjacency3[] = {-1, -1, -1, -1, -1, -1};
5548 const DWORD point_rep3[] = {0, 1, 2, 3, 1, 0};
5549 /* mesh4 (below, tip against tip)
5551 * 0--1
5552 * | /
5553 * |/
5556 * |\
5557 * | \
5558 * 5--4
5560 struct vertex_pnc vertices4[] =
5562 {{ 0.0f, 3.0f, 0.f}, up, RED},
5563 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5564 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5566 {{ 0.0f, -4.0f, 0.f}, up, BLUE},
5567 {{ 2.0f, -7.0f, 0.f}, up, GREEN},
5568 {{ 0.0f, -7.0f, 0.f}, up, RED},
5570 const DWORD indices4[] = {0, 1, 2, 3, 4, 5};
5571 const unsigned int num_vertices4 = ARRAY_SIZE(vertices4);
5572 const unsigned int num_faces4 = num_vertices4 / VERTS_PER_FACE;
5573 const DWORD exp_adjacency4[] = {-1, -1, -1, -1, -1, -1};
5574 const DWORD exp_id_adjacency4[] = {-1, -1, -1, -1, -1, -1};
5575 const DWORD point_rep4[] = {0, 1, 2, 3, 4, 5};
5576 /* mesh5 (gap in mesh)
5578 * 0 3-----4 15
5579 * / \ \ / / \
5580 * / \ \ / / \
5581 * 2-----1 5 17-----16
5582 * 6-----7 9 12-----13
5583 * \ / / \ \ /
5584 * \ / / \ \ /
5585 * 8 10-----11 14
5588 const struct vertex_pnc vertices5[] =
5590 {{ 0.0f, 1.0f, 0.f}, up, RED},
5591 {{ 1.0f, -1.0f, 0.f}, up, GREEN},
5592 {{-1.0f, -1.0f, 0.f}, up, BLUE},
5594 {{ 0.1f, 1.0f, 0.f}, up, RED},
5595 {{ 2.1f, 1.0f, 0.f}, up, BLUE},
5596 {{ 1.1f, -1.0f, 0.f}, up, GREEN},
5598 {{-1.0f, -1.1f, 0.f}, up, BLUE},
5599 {{ 1.0f, -1.1f, 0.f}, up, GREEN},
5600 {{ 0.0f, -3.1f, 0.f}, up, RED},
5602 {{ 1.1f, -1.1f, 0.f}, up, GREEN},
5603 {{ 2.1f, -3.1f, 0.f}, up, BLUE},
5604 {{ 0.1f, -3.1f, 0.f}, up, RED},
5606 {{ 1.2f, -1.1f, 0.f}, up, GREEN},
5607 {{ 3.2f, -1.1f, 0.f}, up, RED},
5608 {{ 2.2f, -3.1f, 0.f}, up, BLUE},
5610 {{ 2.2f, 1.0f, 0.f}, up, BLUE},
5611 {{ 3.2f, -1.0f, 0.f}, up, RED},
5612 {{ 1.2f, -1.0f, 0.f}, up, GREEN},
5614 const DWORD indices5[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17};
5615 const unsigned int num_vertices5 = ARRAY_SIZE(vertices5);
5616 const unsigned int num_faces5 = num_vertices5 / VERTS_PER_FACE;
5617 const DWORD exp_adjacency5[] = {-1, 2, -1, -1, 5, -1, 0, -1, -1, 4, -1, -1, 5, -1, 3, -1, 4, 1};
5618 const DWORD exp_id_adjacency5[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
5619 const DWORD point_rep5[] = {0, 1, 2, 3, 4, 5, 2, 1, 8, 5, 10, 11, 5, 13, 10, 4, 13, 5};
5620 /* mesh6 (indices re-ordering)
5622 * 0--1 6 3
5623 * | / /| |\
5624 * |/ / | | \
5625 * 2 8--7 5--4
5627 const struct vertex_pnc vertices6[] =
5629 {{ 0.0f, 3.0f, 0.f}, up, RED},
5630 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5631 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5633 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5634 {{ 3.0f, 0.0f, 0.f}, up, RED},
5635 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5637 {{ 4.0f, 3.0f, 0.f}, up, GREEN},
5638 {{ 6.0f, 0.0f, 0.f}, up, BLUE},
5639 {{ 4.0f, 0.0f, 0.f}, up, RED},
5641 const DWORD indices6[] = {0, 1, 2, 6, 7, 8, 3, 4, 5};
5642 const unsigned int num_vertices6 = ARRAY_SIZE(vertices6);
5643 const unsigned int num_faces6 = num_vertices6 / VERTS_PER_FACE;
5644 const DWORD exp_adjacency6[] = {-1, 1, -1, 2, -1, 0, -1, -1, 1};
5645 const DWORD exp_id_adjacency6[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1};
5646 const DWORD point_rep6[] = {0, 1, 2, 1, 4, 5, 1, 5, 2};
5647 /* mesh7 (expands collapsed triangle)
5649 * 0--1 3
5650 * | / /|
5651 * |/ / |
5652 * 2 5--4
5654 const struct vertex_pnc vertices7[] =
5656 {{ 0.0f, 3.0f, 0.f}, up, RED},
5657 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5658 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5660 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5661 {{ 3.0f, 0.0f, 0.f}, up, RED},
5662 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5664 const DWORD indices7[] = {0, 1, 2, 3, 3, 3}; /* Face 1 is collapsed*/
5665 const unsigned int num_vertices7 = ARRAY_SIZE(vertices7);
5666 const unsigned int num_faces7 = num_vertices7 / VERTS_PER_FACE;
5667 const DWORD exp_adjacency7[] = {-1, -1, -1, -1, -1, -1};
5668 const DWORD exp_id_adjacency7[] = {-1, -1, -1, -1, -1, -1};
5669 const DWORD point_rep7[] = {0, 1, 2, 3, 4, 5};
5670 /* mesh8 (indices re-ordering and double replacement)
5672 * 0--1 9 6
5673 * | / /| |\
5674 * |/ / | | \
5675 * 2 11-10 8--7
5676 * 3--4
5677 * | /
5678 * |/
5681 const struct vertex_pnc vertices8[] =
5683 {{ 0.0f, 3.0f, 0.f}, up, RED},
5684 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5685 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5687 {{ 4.0, -4.0, 0.f}, up, RED},
5688 {{ 6.0, -4.0, 0.f}, up, BLUE},
5689 {{ 4.0, -7.0, 0.f}, up, GREEN},
5691 {{ 4.0f, 3.0f, 0.f}, up, GREEN},
5692 {{ 6.0f, 0.0f, 0.f}, up, BLUE},
5693 {{ 4.0f, 0.0f, 0.f}, up, RED},
5695 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5696 {{ 3.0f, 0.0f, 0.f}, up, RED},
5697 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5699 const DWORD indices8[] = {0, 1, 2, 9, 10, 11, 6, 7, 8, 3, 4, 5};
5700 const WORD indices8_16bit[] = {0, 1, 2, 9, 10, 11, 6, 7, 8, 3, 4, 5};
5701 const unsigned int num_vertices8 = ARRAY_SIZE(vertices8);
5702 const unsigned int num_faces8 = num_vertices8 / VERTS_PER_FACE;
5703 const DWORD exp_adjacency8[] = {-1, 1, -1, 2, -1, 0, -1, 3, 1, 2, -1, -1};
5704 const DWORD exp_id_adjacency8[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
5705 const DWORD point_rep8[] = {0, 1, 2, 3, 4, 5, 1, 4, 3, 1, 3, 2};
5706 /* mesh9 (right, shared vertices)
5708 * 0--1
5709 * | /|
5710 * |/ |
5711 * 2--3
5713 const struct vertex_pnc vertices9[] =
5715 {{ 0.0f, 3.0f, 0.f}, up, RED},
5716 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5717 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5719 {{ 2.0f, 0.0f, 0.f}, up, RED},
5721 const DWORD indices9[] = {0, 1, 2, 1, 3, 2};
5722 const unsigned int num_vertices9 = ARRAY_SIZE(vertices9);
5723 const unsigned int num_faces9 = 2;
5724 const DWORD exp_adjacency9[] = {-1, 1, -1, -1, -1, 0};
5725 const DWORD exp_id_adjacency9[] = {-1, 1, -1, -1, -1, 0};
5726 const DWORD point_rep9[] = {0, 1, 2, 3};
5727 /* All mesh data */
5728 ID3DXMesh *mesh = NULL;
5729 ID3DXMesh *mesh_null_check = NULL;
5730 unsigned int attributes[] = {0};
5731 struct
5733 const struct vertex_pnc *vertices;
5734 const DWORD *indices;
5735 const DWORD num_vertices;
5736 const DWORD num_faces;
5737 const DWORD *point_reps;
5738 const DWORD *exp_adjacency;
5739 const DWORD *exp_id_adjacency;
5740 const DWORD options;
5742 tc[] =
5745 vertices0,
5746 indices0,
5747 num_vertices0,
5748 num_faces0,
5749 point_rep0,
5750 exp_adjacency0,
5751 exp_id_adjacency0,
5752 options
5755 vertices1,
5756 indices1,
5757 num_vertices1,
5758 num_faces1,
5759 point_rep1,
5760 exp_adjacency1,
5761 exp_id_adjacency1,
5762 options
5765 vertices2,
5766 indices2,
5767 num_vertices2,
5768 num_faces2,
5769 point_rep2,
5770 exp_adjacency2,
5771 exp_id_adjacency2,
5772 options
5775 vertices3,
5776 indices3,
5777 num_vertices3,
5778 num_faces3,
5779 point_rep3,
5780 exp_adjacency3,
5781 exp_id_adjacency3,
5782 options
5785 vertices4,
5786 indices4,
5787 num_vertices4,
5788 num_faces4,
5789 point_rep4,
5790 exp_adjacency4,
5791 exp_id_adjacency4,
5792 options
5795 vertices5,
5796 indices5,
5797 num_vertices5,
5798 num_faces5,
5799 point_rep5,
5800 exp_adjacency5,
5801 exp_id_adjacency5,
5802 options
5805 vertices6,
5806 indices6,
5807 num_vertices6,
5808 num_faces6,
5809 point_rep6,
5810 exp_adjacency6,
5811 exp_id_adjacency6,
5812 options
5815 vertices7,
5816 indices7,
5817 num_vertices7,
5818 num_faces7,
5819 point_rep7,
5820 exp_adjacency7,
5821 exp_id_adjacency7,
5822 options
5825 vertices8,
5826 indices8,
5827 num_vertices8,
5828 num_faces8,
5829 point_rep8,
5830 exp_adjacency8,
5831 exp_id_adjacency8,
5832 options
5835 vertices9,
5836 indices9,
5837 num_vertices9,
5838 num_faces9,
5839 point_rep9,
5840 exp_adjacency9,
5841 exp_id_adjacency9,
5842 options
5845 vertices8,
5846 (DWORD*)indices8_16bit,
5847 num_vertices8,
5848 num_faces8,
5849 point_rep8,
5850 exp_adjacency8,
5851 exp_id_adjacency8,
5852 options_16bit
5855 DWORD *adjacency = NULL;
5857 test_context = new_test_context();
5858 if (!test_context)
5860 skip("Couldn't create test context\n");
5861 goto cleanup;
5864 for (i = 0; i < ARRAY_SIZE(tc); i++)
5866 hr = D3DXCreateMesh(tc[i].num_faces, tc[i].num_vertices, tc[i].options,
5867 declaration, test_context->device, &mesh);
5868 if (FAILED(hr))
5870 skip("Couldn't create mesh %d. Got %x expected D3D_OK\n", i, hr);
5871 goto cleanup;
5874 if (i == 0) /* Save first mesh for later NULL checks */
5875 mesh_null_check = mesh;
5877 adjacency = HeapAlloc(GetProcessHeap(), 0, VERTS_PER_FACE * tc[i].num_faces * sizeof(*adjacency));
5878 if (!adjacency)
5880 skip("Couldn't allocate adjacency array.\n");
5881 goto cleanup;
5884 hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, &vertex_buffer);
5885 if (FAILED(hr))
5887 skip("Couldn't lock vertex buffer.\n");
5888 goto cleanup;
5890 memcpy(vertex_buffer, tc[i].vertices, tc[i].num_vertices * sizeof(*tc[i].vertices));
5891 hr = mesh->lpVtbl->UnlockVertexBuffer(mesh);
5892 if (FAILED(hr))
5894 skip("Couldn't unlock vertex buffer.\n");
5895 goto cleanup;
5897 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, &index_buffer);
5898 if (FAILED(hr))
5900 skip("Couldn't lock index buffer.\n");
5901 goto cleanup;
5903 if (tc[i].options & D3DXMESH_32BIT)
5905 memcpy(index_buffer, tc[i].indices, VERTS_PER_FACE * tc[i].num_faces * sizeof(DWORD));
5907 else
5909 memcpy(index_buffer, tc[i].indices, VERTS_PER_FACE * tc[i].num_faces * sizeof(WORD));
5911 hr = mesh->lpVtbl->UnlockIndexBuffer(mesh);
5912 if (FAILED(hr)) {
5913 skip("Couldn't unlock index buffer.\n");
5914 goto cleanup;
5917 hr = mesh->lpVtbl->LockAttributeBuffer(mesh, 0, &attributes_buffer);
5918 if (FAILED(hr))
5920 skip("Couldn't lock attributes buffer.\n");
5921 goto cleanup;
5923 memcpy(attributes_buffer, attributes, sizeof(attributes));
5924 hr = mesh->lpVtbl->UnlockAttributeBuffer(mesh);
5925 if (FAILED(hr))
5927 skip("Couldn't unlock attributes buffer.\n");
5928 goto cleanup;
5931 /* Convert point representation to adjacency*/
5932 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++) adjacency[j] = -2;
5934 hr = mesh->lpVtbl->ConvertPointRepsToAdjacency(mesh, tc[i].point_reps, adjacency);
5935 ok(hr == D3D_OK, "ConvertPointRepsToAdjacency failed case %d. "
5936 "Got %x expected D3D_OK\n", i, hr);
5937 /* Check adjacency */
5938 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
5940 ok(adjacency[j] == tc[i].exp_adjacency[j],
5941 "Unexpected adjacency information at (%d, %d)."
5942 " Got %d expected %d\n",
5943 i, j, adjacency[j], tc[i].exp_adjacency[j]);
5946 /* NULL point representation is considered identity. */
5947 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++) adjacency[j] = -2;
5948 hr = mesh_null_check->lpVtbl->ConvertPointRepsToAdjacency(mesh, NULL, adjacency);
5949 ok(hr == D3D_OK, "ConvertPointRepsToAdjacency NULL point_reps. "
5950 "Got %x expected D3D_OK\n", hr);
5951 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
5953 ok(adjacency[j] == tc[i].exp_id_adjacency[j],
5954 "Unexpected adjacency information (id) at (%d, %d)."
5955 " Got %d expected %d\n",
5956 i, j, adjacency[j], tc[i].exp_id_adjacency[j]);
5959 HeapFree(GetProcessHeap(), 0, adjacency);
5960 adjacency = NULL;
5961 if (i != 0) /* First mesh will be freed during cleanup */
5962 mesh->lpVtbl->Release(mesh);
5965 /* NULL checks */
5966 hr = mesh_null_check->lpVtbl->ConvertPointRepsToAdjacency(mesh_null_check, tc[0].point_reps, NULL);
5967 ok(hr == D3DERR_INVALIDCALL, "ConvertPointRepsToAdjacency NULL adjacency. "
5968 "Got %x expected D3DERR_INVALIDCALL\n", hr);
5969 hr = mesh_null_check->lpVtbl->ConvertPointRepsToAdjacency(mesh_null_check, NULL, NULL);
5970 ok(hr == D3DERR_INVALIDCALL, "ConvertPointRepsToAdjacency NULL point_reps and adjacency. "
5971 "Got %x expected D3DERR_INVALIDCALL\n", hr);
5973 cleanup:
5974 if (mesh_null_check)
5975 mesh_null_check->lpVtbl->Release(mesh_null_check);
5976 HeapFree(GetProcessHeap(), 0, adjacency);
5977 free_test_context(test_context);
5980 static HRESULT init_test_mesh(const DWORD num_faces, const DWORD num_vertices,
5981 const DWORD options,
5982 const D3DVERTEXELEMENT9 *declaration,
5983 IDirect3DDevice9 *device, ID3DXMesh **mesh_ptr,
5984 const void *vertices, const DWORD vertex_size,
5985 const DWORD *indices, const DWORD *attributes)
5987 HRESULT hr;
5988 void *vertex_buffer;
5989 void *index_buffer;
5990 DWORD *attributes_buffer;
5991 ID3DXMesh *mesh = NULL;
5993 hr = D3DXCreateMesh(num_faces, num_vertices, options, declaration, device, mesh_ptr);
5994 if (FAILED(hr))
5996 skip("Couldn't create mesh. Got %x expected D3D_OK\n", hr);
5997 goto cleanup;
5999 mesh = *mesh_ptr;
6001 hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, &vertex_buffer);
6002 if (FAILED(hr))
6004 skip("Couldn't lock vertex buffer.\n");
6005 goto cleanup;
6007 memcpy(vertex_buffer, vertices, num_vertices * vertex_size);
6008 hr = mesh->lpVtbl->UnlockVertexBuffer(mesh);
6009 if (FAILED(hr))
6011 skip("Couldn't unlock vertex buffer.\n");
6012 goto cleanup;
6015 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, &index_buffer);
6016 if (FAILED(hr))
6018 skip("Couldn't lock index buffer.\n");
6019 goto cleanup;
6021 if (options & D3DXMESH_32BIT)
6023 if (indices)
6024 memcpy(index_buffer, indices, 3 * num_faces * sizeof(DWORD));
6025 else
6027 /* Fill index buffer with 0, 1, 2, ...*/
6028 DWORD *indices_32bit = (DWORD*)index_buffer;
6029 UINT i;
6030 for (i = 0; i < 3 * num_faces; i++)
6031 indices_32bit[i] = i;
6034 else
6036 if (indices)
6037 memcpy(index_buffer, indices, 3 * num_faces * sizeof(WORD));
6038 else
6040 /* Fill index buffer with 0, 1, 2, ...*/
6041 WORD *indices_16bit = (WORD*)index_buffer;
6042 UINT i;
6043 for (i = 0; i < 3 * num_faces; i++)
6044 indices_16bit[i] = i;
6047 hr = mesh->lpVtbl->UnlockIndexBuffer(mesh);
6048 if (FAILED(hr)) {
6049 skip("Couldn't unlock index buffer.\n");
6050 goto cleanup;
6053 hr = mesh->lpVtbl->LockAttributeBuffer(mesh, 0, &attributes_buffer);
6054 if (FAILED(hr))
6056 skip("Couldn't lock attributes buffer.\n");
6057 goto cleanup;
6060 if (attributes)
6061 memcpy(attributes_buffer, attributes, num_faces * sizeof(*attributes));
6062 else
6063 memset(attributes_buffer, 0, num_faces * sizeof(*attributes));
6065 hr = mesh->lpVtbl->UnlockAttributeBuffer(mesh);
6066 if (FAILED(hr))
6068 skip("Couldn't unlock attributes buffer.\n");
6069 goto cleanup;
6072 hr = D3D_OK;
6073 cleanup:
6074 return hr;
6077 /* Using structs instead of bit-fields in order to avoid compiler issues. */
6078 struct udec3
6080 UINT x;
6081 UINT y;
6082 UINT z;
6083 UINT w;
6086 struct dec3n
6088 INT x;
6089 INT y;
6090 INT z;
6091 INT w;
6094 static DWORD init_udec3_dword(UINT x, UINT y, UINT z, UINT w)
6096 DWORD d = 0;
6098 d |= x & 0x3ff;
6099 d |= (y << 10) & 0xffc00;
6100 d |= (z << 20) & 0x3ff00000;
6101 d |= (w << 30) & 0xc0000000;
6103 return d;
6106 static DWORD init_dec3n_dword(INT x, INT y, INT z, INT w)
6108 DWORD d = 0;
6110 d |= x & 0x3ff;
6111 d |= (y << 10) & 0xffc00;
6112 d |= (z << 20) & 0x3ff00000;
6113 d |= (w << 30) & 0xc0000000;
6115 return d;
6118 static struct udec3 dword_to_udec3(DWORD d)
6120 struct udec3 v;
6122 v.x = d & 0x3ff;
6123 v.y = (d & 0xffc00) >> 10;
6124 v.z = (d & 0x3ff00000) >> 20;
6125 v.w = (d & 0xc0000000) >> 30;
6127 return v;
6130 static struct dec3n dword_to_dec3n(DWORD d)
6132 struct dec3n v;
6134 v.x = d & 0x3ff;
6135 v.y = (d & 0xffc00) >> 10;
6136 v.z = (d & 0x3ff00000) >> 20;
6137 v.w = (d & 0xc0000000) >> 30;
6139 return v;
6142 static void check_vertex_components(int line, int mesh_number, int vertex_number, BYTE *got_ptr, const BYTE *exp_ptr, D3DVERTEXELEMENT9 *declaration)
6144 const char *usage_strings[] =
6146 "position",
6147 "blend weight",
6148 "blend indices",
6149 "normal",
6150 "point size",
6151 "texture coordinates",
6152 "tangent",
6153 "binormal",
6154 "tessellation factor",
6155 "position transformed",
6156 "color",
6157 "fog",
6158 "depth",
6159 "sample"
6161 D3DVERTEXELEMENT9 *decl_ptr;
6162 const float PRECISION = 1e-5f;
6164 for (decl_ptr = declaration; decl_ptr->Stream != 0xFF; decl_ptr++)
6166 switch (decl_ptr->Type)
6168 case D3DDECLTYPE_FLOAT1:
6170 FLOAT *got = (FLOAT*)(got_ptr + decl_ptr->Offset);
6171 FLOAT *exp = (FLOAT*)(exp_ptr + decl_ptr->Offset);
6172 FLOAT diff = fabsf(*got - *exp);
6173 ok_(__FILE__,line)(diff <= PRECISION, "Mesh %d: Got %f for vertex %d %s, expected %f.\n",
6174 mesh_number, *got, vertex_number, usage_strings[decl_ptr->Usage], *exp);
6175 break;
6177 case D3DDECLTYPE_FLOAT2:
6179 D3DXVECTOR2 *got = (D3DXVECTOR2*)(got_ptr + decl_ptr->Offset);
6180 D3DXVECTOR2 *exp = (D3DXVECTOR2*)(exp_ptr + decl_ptr->Offset);
6181 FLOAT diff = max(fabsf(got->x - exp->x), fabsf(got->y - exp->y));
6182 ok_(__FILE__,line)(diff <= PRECISION, "Mesh %d: Got (%f, %f) for vertex %d %s, expected (%f, %f).\n",
6183 mesh_number, got->x, got->y, vertex_number, usage_strings[decl_ptr->Usage], exp->x, exp->y);
6184 break;
6186 case D3DDECLTYPE_FLOAT3:
6188 D3DXVECTOR3 *got = (D3DXVECTOR3*)(got_ptr + decl_ptr->Offset);
6189 D3DXVECTOR3 *exp = (D3DXVECTOR3*)(exp_ptr + decl_ptr->Offset);
6190 FLOAT diff = max(fabsf(got->x - exp->x), fabsf(got->y - exp->y));
6191 diff = max(diff, fabsf(got->z - exp->z));
6192 ok_(__FILE__,line)(diff <= PRECISION, "Mesh %d: Got (%f, %f, %f) for vertex %d %s, expected (%f, %f, %f).\n",
6193 mesh_number, got->x, got->y, got->z, vertex_number, usage_strings[decl_ptr->Usage], exp->x, exp->y, exp->z);
6194 break;
6196 case D3DDECLTYPE_FLOAT4:
6198 D3DXVECTOR4 *got = (D3DXVECTOR4*)(got_ptr + decl_ptr->Offset);
6199 D3DXVECTOR4 *exp = (D3DXVECTOR4*)(exp_ptr + decl_ptr->Offset);
6200 FLOAT diff = max(fabsf(got->x - exp->x), fabsf(got->y - exp->y));
6201 diff = max(diff, fabsf(got->z - exp->z));
6202 diff = max(diff, fabsf(got->w - exp->w));
6203 ok_(__FILE__,line)(diff <= PRECISION, "Mesh %d: Got (%f, %f, %f, %f) for vertex %d %s, expected (%f, %f, %f, %f).\n",
6204 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);
6205 break;
6207 case D3DDECLTYPE_D3DCOLOR:
6209 BYTE *got = got_ptr + decl_ptr->Offset;
6210 const BYTE *exp = exp_ptr + decl_ptr->Offset;
6211 BOOL same_color = got[0] == exp[0] && got[1] == exp[1]
6212 && got[2] == exp[2] && got[3] == exp[3];
6213 const char *color_types[] = {"diffuse", "specular", "undefined color"};
6214 BYTE usage_index = decl_ptr->UsageIndex;
6215 if (usage_index > 1) usage_index = 2;
6216 ok_(__FILE__,line)(same_color, "Mesh %d: Got (%u, %u, %u, %u) for vertex %d %s, expected (%u, %u, %u, %u).\n",
6217 mesh_number, got[0], got[1], got[2], got[3], vertex_number, color_types[usage_index], exp[0], exp[1], exp[2], exp[3]);
6218 break;
6220 case D3DDECLTYPE_UBYTE4:
6221 case D3DDECLTYPE_UBYTE4N:
6223 BYTE *got = got_ptr + decl_ptr->Offset;
6224 const BYTE *exp = exp_ptr + decl_ptr->Offset;
6225 BOOL same = got[0] == exp[0] && got[1] == exp[1]
6226 && got[2] == exp[2] && got[3] == exp[3];
6227 ok_(__FILE__,line)(same, "Mesh %d: Got (%u, %u, %u, %u) for vertex %d %s, expected (%u, %u, %u, %u).\n",
6228 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]);
6229 break;
6231 case D3DDECLTYPE_SHORT2:
6232 case D3DDECLTYPE_SHORT2N:
6234 SHORT *got = (SHORT*)(got_ptr + decl_ptr->Offset);
6235 SHORT *exp = (SHORT*)(exp_ptr + decl_ptr->Offset);
6236 BOOL same = got[0] == exp[0] && got[1] == exp[1];
6237 ok_(__FILE__,line)(same, "Mesh %d: Got (%hd, %hd) for vertex %d %s, expected (%hd, %hd).\n",
6238 mesh_number, got[0], got[1], vertex_number, usage_strings[decl_ptr->Usage], exp[0], exp[1]);
6239 break;
6241 case D3DDECLTYPE_SHORT4:
6242 case D3DDECLTYPE_SHORT4N:
6244 SHORT *got = (SHORT*)(got_ptr + decl_ptr->Offset);
6245 SHORT *exp = (SHORT*)(exp_ptr + decl_ptr->Offset);
6246 BOOL same = got[0] == exp[0] && got[1] == exp[1]
6247 && got[2] == exp[2] && got[3] == exp[3];
6248 ok_(__FILE__,line)(same, "Mesh %d: Got (%hd, %hd, %hd, %hd) for vertex %d %s, expected (%hd, %hd, %hd, %hd).\n",
6249 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]);
6250 break;
6252 case D3DDECLTYPE_USHORT2N:
6254 USHORT *got = (USHORT*)(got_ptr + decl_ptr->Offset);
6255 USHORT *exp = (USHORT*)(exp_ptr + decl_ptr->Offset);
6256 BOOL same = got[0] == exp[0] && got[1] == exp[1];
6257 ok_(__FILE__,line)(same, "Mesh %d: Got (%hu, %hu) for vertex %d %s, expected (%hu, %hu).\n",
6258 mesh_number, got[0], got[1], vertex_number, usage_strings[decl_ptr->Usage], exp[0], exp[1]);
6259 break;
6261 case D3DDECLTYPE_USHORT4N:
6263 USHORT *got = (USHORT*)(got_ptr + decl_ptr->Offset);
6264 USHORT *exp = (USHORT*)(exp_ptr + decl_ptr->Offset);
6265 BOOL same = got[0] == exp[0] && got[1] == exp[1]
6266 && got[2] == exp[2] && got[3] == exp[3];
6267 ok_(__FILE__,line)(same, "Mesh %d: Got (%hu, %hu, %hu, %hu) for vertex %d %s, expected (%hu, %hu, %hu, %hu).\n",
6268 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]);
6269 break;
6271 case D3DDECLTYPE_UDEC3:
6273 DWORD *got = (DWORD*)(got_ptr + decl_ptr->Offset);
6274 DWORD *exp = (DWORD*)(exp_ptr + decl_ptr->Offset);
6275 BOOL same = memcmp(got, exp, sizeof(*got)) == 0;
6276 struct udec3 got_udec3 = dword_to_udec3(*got);
6277 struct udec3 exp_udec3 = dword_to_udec3(*exp);
6278 ok_(__FILE__,line)(same, "Mesh %d: Got (%u, %u, %u, %u) for vertex %d %s, expected (%u, %u, %u, %u).\n",
6279 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);
6281 break;
6283 case D3DDECLTYPE_DEC3N:
6285 DWORD *got = (DWORD*)(got_ptr + decl_ptr->Offset);
6286 DWORD *exp = (DWORD*)(exp_ptr + decl_ptr->Offset);
6287 BOOL same = memcmp(got, exp, sizeof(*got)) == 0;
6288 struct dec3n got_dec3n = dword_to_dec3n(*got);
6289 struct dec3n exp_dec3n = dword_to_dec3n(*exp);
6290 ok_(__FILE__,line)(same, "Mesh %d: Got (%d, %d, %d, %d) for vertex %d %s, expected (%d, %d, %d, %d).\n",
6291 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);
6292 break;
6294 case D3DDECLTYPE_FLOAT16_2:
6296 WORD *got = (WORD*)(got_ptr + decl_ptr->Offset);
6297 WORD *exp = (WORD*)(exp_ptr + decl_ptr->Offset);
6298 BOOL same = got[0] == exp[0] && got[1] == exp[1];
6299 ok_(__FILE__,line)(same, "Mesh %d: Got (%hx, %hx) for vertex %d %s, expected (%hx, %hx).\n",
6300 mesh_number, got[0], got[1], vertex_number, usage_strings[decl_ptr->Usage], exp[0], exp[1]);
6301 break;
6303 case D3DDECLTYPE_FLOAT16_4:
6305 WORD *got = (WORD*)(got_ptr + decl_ptr->Offset);
6306 WORD *exp = (WORD*)(exp_ptr + decl_ptr->Offset);
6307 BOOL same = got[0] == exp[0] && got[1] == exp[1]
6308 && got[2] == exp[2] && got[3] == exp[3];
6309 ok_(__FILE__,line)(same, "Mesh %d: Got (%hx, %hx, %hx, %hx) for vertex %d %s, expected (%hx, %hx, %hx, %hx).\n",
6310 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]);
6311 break;
6313 default:
6314 break;
6319 static void test_weld_vertices(void)
6321 HRESULT hr;
6322 struct test_context *test_context = NULL;
6323 DWORD i;
6324 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
6325 const DWORD options_16bit = D3DXMESH_SYSTEMMEM;
6326 BYTE *vertices = NULL;
6327 DWORD *indices = NULL;
6328 WORD *indices_16bit = NULL;
6329 const UINT VERTS_PER_FACE = 3;
6330 const D3DXVECTOR3 up = {0.0f, 0.0f, 1.0f};
6331 struct vertex_normal
6333 D3DXVECTOR3 position;
6334 D3DXVECTOR3 normal;
6336 struct vertex_blendweight
6338 D3DXVECTOR3 position;
6339 FLOAT blendweight;
6341 struct vertex_texcoord
6343 D3DXVECTOR3 position;
6344 D3DXVECTOR2 texcoord;
6346 struct vertex_color
6348 D3DXVECTOR3 position;
6349 DWORD color;
6351 struct vertex_color_ubyte4
6353 D3DXVECTOR3 position;
6354 BYTE color[4];
6356 struct vertex_texcoord_short2
6358 D3DXVECTOR3 position;
6359 SHORT texcoord[2];
6361 struct vertex_texcoord_ushort2n
6363 D3DXVECTOR3 position;
6364 USHORT texcoord[2];
6366 struct vertex_normal_short4
6368 D3DXVECTOR3 position;
6369 SHORT normal[4];
6371 struct vertex_color_float4
6373 D3DXVECTOR3 position;
6374 D3DXVECTOR4 color;
6376 struct vertex_texcoord_float16_2
6378 D3DXVECTOR3 position;
6379 WORD texcoord[2];
6381 struct vertex_texcoord_float16_4
6383 D3DXVECTOR3 position;
6384 WORD texcoord[4];
6386 struct vertex_normal_udec3
6388 D3DXVECTOR3 position;
6389 DWORD normal;
6391 struct vertex_normal_dec3n
6393 D3DXVECTOR3 position;
6394 DWORD normal;
6396 UINT vertex_size_normal = sizeof(struct vertex_normal);
6397 UINT vertex_size_blendweight = sizeof(struct vertex_blendweight);
6398 UINT vertex_size_texcoord = sizeof(struct vertex_texcoord);
6399 UINT vertex_size_color = sizeof(struct vertex_color);
6400 UINT vertex_size_color_ubyte4 = sizeof(struct vertex_color_ubyte4);
6401 UINT vertex_size_texcoord_short2 = sizeof(struct vertex_texcoord_short2);
6402 UINT vertex_size_normal_short4 = sizeof(struct vertex_normal_short4);
6403 UINT vertex_size_color_float4 = sizeof(struct vertex_color_float4);
6404 UINT vertex_size_texcoord_float16_2 = sizeof(struct vertex_texcoord_float16_2);
6405 UINT vertex_size_texcoord_float16_4 = sizeof(struct vertex_texcoord_float16_4);
6406 UINT vertex_size_normal_udec3 = sizeof(struct vertex_normal_udec3);
6407 UINT vertex_size_normal_dec3n = sizeof(struct vertex_normal_dec3n);
6408 D3DVERTEXELEMENT9 declaration_normal[] =
6410 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6411 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6412 D3DDECL_END()
6414 D3DVERTEXELEMENT9 declaration_normal3[] =
6416 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 3},
6417 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6418 D3DDECL_END()
6420 D3DVERTEXELEMENT9 declaration_blendweight[] =
6422 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6423 {0, 12, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BLENDWEIGHT, 0},
6424 D3DDECL_END()
6426 D3DVERTEXELEMENT9 declaration_texcoord[] =
6428 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6429 {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6430 D3DDECL_END()
6432 D3DVERTEXELEMENT9 declaration_color[] =
6434 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6435 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
6436 D3DDECL_END()
6438 D3DVERTEXELEMENT9 declaration_color_ubyte4n[] =
6440 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6441 {0, 12, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
6442 D3DDECL_END()
6444 D3DVERTEXELEMENT9 declaration_color_ubyte4[] =
6446 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6447 {0, 12, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
6448 D3DDECL_END()
6450 D3DVERTEXELEMENT9 declaration_texcoord_short2[] =
6452 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6453 {0, 12, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6454 D3DDECL_END()
6456 D3DVERTEXELEMENT9 declaration_texcoord_short2n[] =
6458 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6459 {0, 12, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6460 D3DDECL_END()
6462 D3DVERTEXELEMENT9 declaration_texcoord_ushort2n[] =
6464 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6465 {0, 12, D3DDECLTYPE_USHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6466 D3DDECL_END()
6468 D3DVERTEXELEMENT9 declaration_normal_short4[] =
6470 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6471 {0, 12, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6472 D3DDECL_END()
6474 D3DVERTEXELEMENT9 declaration_normal_short4n[] =
6476 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6477 {0, 12, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6478 D3DDECL_END()
6480 D3DVERTEXELEMENT9 declaration_normal_ushort4n[] =
6482 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6483 {0, 12, D3DDECLTYPE_USHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6484 D3DDECL_END()
6486 D3DVERTEXELEMENT9 declaration_texcoord10[] =
6488 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6489 {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 10},
6490 D3DDECL_END()
6492 D3DVERTEXELEMENT9 declaration_color2[] =
6494 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6495 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 2},
6496 D3DDECL_END()
6498 D3DVERTEXELEMENT9 declaration_color2_float4[] =
6500 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6501 {0, 12, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 2},
6502 D3DDECL_END()
6504 D3DVERTEXELEMENT9 declaration_texcoord_float16_2[] =
6506 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6507 {0, 12, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6508 D3DDECL_END()
6510 D3DVERTEXELEMENT9 declaration_texcoord_float16_4[] =
6512 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6513 {0, 12, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6514 D3DDECL_END()
6516 D3DVERTEXELEMENT9 declaration_normal_udec3[] =
6518 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6519 {0, 12, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6520 D3DDECL_END()
6522 D3DVERTEXELEMENT9 declaration_normal_dec3n[] =
6524 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6525 {0, 12, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6526 D3DDECL_END()
6528 /* Test 0. One face and no welding.
6530 * 0--1
6531 * | /
6532 * |/
6535 const struct vertex vertices0[] =
6537 {{ 0.0f, 3.0f, 0.f}, up},
6538 {{ 2.0f, 3.0f, 0.f}, up},
6539 {{ 0.0f, 0.0f, 0.f}, up},
6541 const DWORD indices0[] = {0, 1, 2};
6542 const DWORD attributes0[] = {0};
6543 const DWORD exp_indices0[] = {0, 1, 2};
6544 const UINT num_vertices0 = ARRAY_SIZE(vertices0);
6545 const UINT num_faces0 = ARRAY_SIZE(indices0) / VERTS_PER_FACE;
6546 const DWORD flags0 = D3DXWELDEPSILONS_WELDALL;
6547 /* epsilons0 is NULL */
6548 const DWORD adjacency0[] = {-1, -1, -1};
6549 const struct vertex exp_vertices0[] =
6551 {{ 0.0f, 3.0f, 0.f}, up},
6552 {{ 2.0f, 3.0f, 0.f}, up},
6553 {{ 0.0f, 0.0f, 0.f}, up},
6555 const DWORD exp_face_remap0[] = {0};
6556 const DWORD exp_vertex_remap0[] = {0, 1, 2};
6557 const DWORD exp_new_num_vertices0 = ARRAY_SIZE(exp_vertices0);
6558 /* Test 1. Two vertices should be removed without regard to epsilon.
6560 * 0--1 3
6561 * | / /|
6562 * |/ / |
6563 * 2 5--4
6565 const struct vertex_normal vertices1[] =
6567 {{ 0.0f, 3.0f, 0.f}, up},
6568 {{ 2.0f, 3.0f, 0.f}, up},
6569 {{ 0.0f, 0.0f, 0.f}, up},
6571 {{ 3.0f, 3.0f, 0.f}, up},
6572 {{ 3.0f, 0.0f, 0.f}, up},
6573 {{ 1.0f, 0.0f, 0.f}, up},
6575 const DWORD indices1[] = {0, 1, 2, 3, 4, 5};
6576 const DWORD attributes1[] = {0, 0};
6577 const UINT num_vertices1 = ARRAY_SIZE(vertices1);
6578 const UINT num_faces1 = ARRAY_SIZE(indices1) / VERTS_PER_FACE;
6579 const DWORD flags1 = D3DXWELDEPSILONS_WELDALL;
6580 /* epsilons1 is NULL */
6581 const DWORD adjacency1[] = {-1, 1, -1, -1, -1, 0};
6582 const struct vertex_normal exp_vertices1[] =
6584 {{ 0.0f, 3.0f, 0.f}, up},
6585 {{ 2.0f, 3.0f, 0.f}, up},
6586 {{ 0.0f, 0.0f, 0.f}, up},
6588 {{ 3.0f, 0.0f, 0.f}, up}
6590 const DWORD exp_indices1[] = {0, 1, 2, 1, 3, 2};
6591 const DWORD exp_face_remap1[] = {0, 1};
6592 const DWORD exp_vertex_remap1[] = {0, 1, 2, 4, -1, -1};
6593 const DWORD exp_new_num_vertices1 = ARRAY_SIZE(exp_vertices1);
6594 /* Test 2. Two faces. No vertices should be removed because of normal
6595 * epsilon, but the positions should be replaced. */
6596 const struct vertex_normal vertices2[] =
6598 {{ 0.0f, 3.0f, 0.f}, up},
6599 {{ 2.0f, 3.0f, 0.f}, up},
6600 {{ 0.0f, 0.0f, 0.f}, up},
6602 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
6603 {{ 3.0f, 0.0f, 0.f}, up},
6604 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6606 const DWORD indices2[] = {0, 1, 2, 3, 4, 5};
6607 const DWORD attributes2[] = {0, 0};
6608 const UINT num_vertices2 = ARRAY_SIZE(vertices2);
6609 const UINT num_faces2 = ARRAY_SIZE(indices2) / VERTS_PER_FACE;
6610 DWORD flags2 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
6611 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};
6612 const DWORD adjacency2[] = {-1, 1, -1, -1, -1, 0};
6613 const struct vertex_normal exp_vertices2[] =
6615 {{ 0.0f, 3.0f, 0.f}, up},
6616 {{ 2.0f, 3.0f, 0.f}, up},
6617 {{ 0.0f, 0.0f, 0.f}, up},
6619 {{ 2.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
6620 {{ 3.0f, 0.0f, 0.f}, up},
6621 {{ 0.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6623 const DWORD exp_indices2[] = {0, 1, 2, 3, 4, 5};
6624 const DWORD exp_face_remap2[] = {0, 1};
6625 const DWORD exp_vertex_remap2[] = {0, 1, 2, 3, 4, 5};
6626 const DWORD exp_new_num_vertices2 = ARRAY_SIZE(exp_vertices2);
6627 /* Test 3. Two faces. One vertex should be removed because of normal epsilon. */
6628 const struct vertex_normal vertices3[] =
6630 {{ 0.0f, 3.0f, 0.f}, up},
6631 {{ 2.0f, 3.0f, 0.f}, up},
6632 {{ 0.0f, 0.0f, 0.f}, up},
6634 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
6635 {{ 3.0f, 0.0f, 0.f}, up},
6636 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6638 const DWORD indices3[] = {0, 1, 2, 3, 4, 5};
6639 const DWORD attributes3[] = {0, 0};
6640 const UINT num_vertices3 = ARRAY_SIZE(vertices3);
6641 const UINT num_faces3 = ARRAY_SIZE(indices3) / VERTS_PER_FACE;
6642 DWORD flags3 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
6643 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};
6644 const DWORD adjacency3[] = {-1, 1, -1, -1, -1, 0};
6645 const struct vertex_normal exp_vertices3[] =
6647 {{ 0.0f, 3.0f, 0.f}, up},
6648 {{ 2.0f, 3.0f, 0.f}, up},
6649 {{ 0.0f, 0.0f, 0.f}, up},
6651 {{ 3.0f, 0.0f, 0.f}, up},
6652 {{ 0.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6654 const DWORD exp_indices3[] = {0, 1, 2, 1, 3, 4};
6655 const DWORD exp_face_remap3[] = {0, 1};
6656 const DWORD exp_vertex_remap3[] = {0, 1, 2, 4, 5, -1};
6657 const DWORD exp_new_num_vertices3 = ARRAY_SIZE(exp_vertices3);
6658 /* Test 4 Two faces. Two vertices should be removed. */
6659 const struct vertex_normal vertices4[] =
6661 {{ 0.0f, 3.0f, 0.f}, up},
6662 {{ 2.0f, 3.0f, 0.f}, up},
6663 {{ 0.0f, 0.0f, 0.f}, up},
6665 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
6666 {{ 3.0f, 0.0f, 0.f}, up},
6667 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6669 const DWORD indices4[] = {0, 1, 2, 3, 4, 5};
6670 const DWORD attributes4[] = {0, 0};
6671 const UINT num_vertices4 = ARRAY_SIZE(vertices4);
6672 const UINT num_faces4 = ARRAY_SIZE(indices4) / VERTS_PER_FACE;
6673 DWORD flags4 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
6674 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};
6675 const DWORD adjacency4[] = {-1, 1, -1, -1, -1, 0};
6676 const struct vertex_normal exp_vertices4[] =
6678 {{ 0.0f, 3.0f, 0.f}, up},
6679 {{ 2.0f, 3.0f, 0.f}, up},
6680 {{ 0.0f, 0.0f, 0.f}, up},
6682 {{ 3.0f, 0.0f, 0.f}, up},
6684 const DWORD exp_indices4[] = {0, 1, 2, 1, 3, 2};
6685 const DWORD exp_face_remap4[] = {0, 1};
6686 const DWORD exp_vertex_remap4[] = {0, 1, 2, 4, -1, -1};
6687 const DWORD exp_new_num_vertices4 = ARRAY_SIZE(exp_vertices4);
6688 /* Test 5. Odd face ordering.
6690 * 0--1 6 3
6691 * | / /| |\
6692 * |/ / | | \
6693 * 2 8--7 5--4
6695 const struct vertex_normal vertices5[] =
6697 {{ 0.0f, 3.0f, 0.f}, up},
6698 {{ 2.0f, 3.0f, 0.f}, up},
6699 {{ 0.0f, 0.0f, 0.f}, up},
6701 {{ 3.0f, 3.0f, 0.f}, up},
6702 {{ 3.0f, 0.0f, 0.f}, up},
6703 {{ 1.0f, 0.0f, 0.f}, up},
6705 {{ 4.0f, 3.0f, 0.f}, up},
6706 {{ 6.0f, 0.0f, 0.f}, up},
6707 {{ 4.0f, 0.0f, 0.f}, up},
6709 const DWORD indices5[] = {0, 1, 2, 6, 7, 8, 3, 4, 5};
6710 const DWORD exp_indices5[] = {0, 1, 2, 1, 4, 2, 1, 3, 4};
6711 const DWORD attributes5[] = {0, 0, 0};
6712 const UINT num_vertices5 = ARRAY_SIZE(vertices5);
6713 const UINT num_faces5 = ARRAY_SIZE(indices5) / VERTS_PER_FACE;
6714 DWORD flags5 = D3DXWELDEPSILONS_WELDALL;
6715 const DWORD adjacency5[] = {-1, 1, -1, 2, -1, 0, -1, -1, 1};
6716 const struct vertex_normal exp_vertices5[] =
6718 {{ 0.0f, 3.0f, 0.f}, up},
6719 {{ 2.0f, 3.0f, 0.f}, up},
6720 {{ 0.0f, 0.0f, 0.f}, up},
6722 {{ 3.0f, 0.0f, 0.f}, up},
6723 {{ 1.0f, 0.0f, 0.f}, up},
6725 const DWORD exp_face_remap5[] = {0, 1, 2};
6726 const DWORD exp_vertex_remap5[] = {0, 1, 2, 4, 5, -1, -1, -1, -1};
6727 const DWORD exp_new_num_vertices5 = ARRAY_SIZE(exp_vertices5);
6728 /* Test 6. Two faces. Do not remove flag is used, so no vertices should be
6729 * removed. */
6730 const struct vertex_normal vertices6[] =
6732 {{ 0.0f, 3.0f, 0.f}, up},
6733 {{ 2.0f, 3.0f, 0.f}, up},
6734 {{ 0.0f, 0.0f, 0.f}, up},
6736 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
6737 {{ 3.0f, 0.0f, 0.f}, up},
6738 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6740 const DWORD indices6[] = {0, 1, 2, 3, 4, 5};
6741 const DWORD attributes6[] = {0, 0};
6742 const UINT num_vertices6 = ARRAY_SIZE(vertices6);
6743 const UINT num_faces6 = ARRAY_SIZE(indices6) / VERTS_PER_FACE;
6744 DWORD flags6 = D3DXWELDEPSILONS_WELDPARTIALMATCHES | D3DXWELDEPSILONS_DONOTREMOVEVERTICES;
6745 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};
6746 const DWORD adjacency6[] = {-1, 1, -1, -1, -1, 0};
6747 const struct vertex_normal exp_vertices6[] =
6749 {{ 0.0f, 3.0f, 0.f}, up},
6750 {{ 2.0f, 3.0f, 0.f}, up},
6751 {{ 0.0f, 0.0f, 0.f}, up},
6753 {{ 2.0f, 3.0f, 0.f}, up},
6754 {{ 3.0f, 0.0f, 0.f}, up},
6755 {{ 0.0f, 0.0f, 0.f}, up},
6758 const DWORD exp_indices6[] = {0, 1, 2, 3, 4, 5};
6759 const DWORD exp_face_remap6[] = {0, 1};
6760 const DWORD exp_vertex_remap6[] = {0, 1, 2, 3, 4, 5};
6761 const DWORD exp_new_num_vertices6 = ARRAY_SIZE(exp_vertices6);
6762 /* Test 7. Same as test 6 but with 16 bit indices. */
6763 const WORD indices6_16bit[] = {0, 1, 2, 3, 4, 5};
6764 /* Test 8. No flags. Same result as D3DXWELDEPSILONS_WELDPARTIALMATCHES. */
6765 const struct vertex_normal vertices8[] =
6767 {{ 0.0f, 3.0f, 0.f}, up},
6768 {{ 2.0f, 3.0f, 0.f}, up},
6769 {{ 0.0f, 0.0f, 0.f}, up},
6771 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
6772 {{ 3.0f, 0.0f, 0.f}, up},
6773 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6775 const DWORD indices8[] = {0, 1, 2, 1, 3, 4};
6776 const DWORD attributes8[] = {0, 0};
6777 const UINT num_vertices8 = ARRAY_SIZE(vertices8);
6778 const UINT num_faces8 = ARRAY_SIZE(indices8) / VERTS_PER_FACE;
6779 DWORD flags8 = 0;
6780 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};
6781 const DWORD adjacency8[] = {-1, 1, -1, -1, -1, 0};
6782 const struct vertex_normal exp_vertices8[] =
6784 {{ 0.0f, 3.0f, 0.f}, up},
6785 {{ 2.0f, 3.0f, 0.f}, up},
6786 {{ 0.0f, 0.0f, 0.f}, up},
6788 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
6789 {{ 3.0f, 0.0f, 0.f}, up},
6791 const DWORD exp_indices8[] = {0, 1, 2, 1, 3, 4};
6792 const DWORD exp_face_remap8[] = {0, 1};
6793 const DWORD exp_vertex_remap8[] = {0, 1, 2, 3, 4, -1};
6794 const DWORD exp_new_num_vertices8 = ARRAY_SIZE(exp_vertices8);
6795 /* Test 9. Vertices are removed even though they belong to separate
6796 * attribute groups if D3DXWELDEPSILONS_DONOTSPLIT is set. */
6797 const struct vertex_normal vertices9[] =
6799 {{ 0.0f, 3.0f, 0.f}, up},
6800 {{ 2.0f, 3.0f, 0.f}, up},
6801 {{ 0.0f, 0.0f, 0.f}, up},
6803 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
6804 {{ 3.0f, 0.0f, 0.f}, up},
6805 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6807 const DWORD indices9[] = {0, 1, 2, 3, 4, 5};
6808 const DWORD attributes9[] = {0, 1};
6809 const UINT num_vertices9 = ARRAY_SIZE(vertices9);
6810 const UINT num_faces9 = ARRAY_SIZE(indices9) / VERTS_PER_FACE;
6811 DWORD flags9 = D3DXWELDEPSILONS_WELDPARTIALMATCHES | D3DXWELDEPSILONS_DONOTSPLIT;
6812 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};
6813 const DWORD adjacency9[] = {-1, 1, -1, -1, -1, 0};
6814 const struct vertex_normal exp_vertices9[] =
6816 {{ 0.0f, 3.0f, 0.f}, up},
6817 {{ 2.0f, 3.0f, 0.f}, up},
6818 {{ 0.0f, 0.0f, 0.f}, up},
6820 {{ 3.0f, 0.0f, 0.f}, up},
6822 const DWORD exp_indices9[] = {0, 1, 2, 1, 3, 2};
6823 const DWORD exp_face_remap9[] = {0, 1};
6824 const DWORD exp_vertex_remap9[] = {0, 1, 2, 4, -1, -1};
6825 const DWORD exp_new_num_vertices9 = ARRAY_SIZE(exp_vertices9);
6826 /* Test 10. Weld blendweight (FLOAT1). */
6827 const struct vertex_blendweight vertices10[] =
6829 {{ 0.0f, 3.0f, 0.f}, 1.0f},
6830 {{ 2.0f, 3.0f, 0.f}, 1.0f},
6831 {{ 0.0f, 0.0f, 0.f}, 1.0f},
6833 {{ 3.0f, 3.0f, 0.f}, 0.9},
6834 {{ 3.0f, 0.0f, 0.f}, 1.0},
6835 {{ 1.0f, 0.0f, 0.f}, 0.4},
6837 const DWORD indices10[] = {0, 1, 2, 3, 4, 5};
6838 const DWORD attributes10[] = {0, 0};
6839 const UINT num_vertices10 = ARRAY_SIZE(vertices10);
6840 const UINT num_faces10 = ARRAY_SIZE(indices10) / VERTS_PER_FACE;
6841 DWORD flags10 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
6842 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};
6843 const DWORD adjacency10[] = {-1, 1, -1, -1, -1, 0};
6844 const struct vertex_blendweight exp_vertices10[] =
6846 {{ 0.0f, 3.0f, 0.f}, 1.0f},
6847 {{ 2.0f, 3.0f, 0.f}, 1.0f},
6848 {{ 0.0f, 0.0f, 0.f}, 1.0f},
6850 {{ 3.0f, 0.0f, 0.f}, 1.0},
6851 {{ 0.0f, 0.0f, 0.f}, 0.4},
6853 const DWORD exp_indices10[] = {0, 1, 2, 1, 3, 4};
6854 const DWORD exp_face_remap10[] = {0, 1};
6855 const DWORD exp_vertex_remap10[] = {0, 1, 2, 4, 5, -1};
6856 const DWORD exp_new_num_vertices10 = ARRAY_SIZE(exp_vertices10);
6857 /* Test 11. Weld texture coordinates. */
6858 const struct vertex_texcoord vertices11[] =
6860 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f}},
6861 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.7f}},
6862 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
6864 {{ 3.0f, 3.0f, 0.f}, {0.2f, 0.3f}},
6865 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f}},
6866 {{ 1.0f, 0.0f, 0.f}, {0.1f, 0.2f}}
6868 const DWORD indices11[] = {0, 1, 2, 3, 4, 5};
6869 const DWORD attributes11[] = {0, 0};
6870 const UINT num_vertices11 = ARRAY_SIZE(vertices11);
6871 const UINT num_faces11 = ARRAY_SIZE(indices11) / VERTS_PER_FACE;
6872 DWORD flags11 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
6873 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};
6874 const DWORD adjacency11[] = {-1, 1, -1, -1, -1, 0};
6875 const struct vertex_texcoord exp_vertices11[] =
6877 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f}},
6878 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.7f}},
6879 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
6881 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f}},
6882 {{ 0.0f, 0.0f, 0.f}, {0.1f, 0.2f}},
6884 const DWORD exp_indices11[] = {0, 1, 2, 1, 3, 4};
6885 const DWORD exp_face_remap11[] = {0, 1};
6886 const DWORD exp_vertex_remap11[] = {0, 1, 2, 4, 5, -1};
6887 const DWORD exp_new_num_vertices11 = ARRAY_SIZE(exp_vertices11);
6888 /* Test 12. Weld with color. */
6889 const struct vertex_color vertices12[] =
6891 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
6892 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
6893 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
6895 {{ 3.0f, 3.0f, 0.f}, 0x00000000},
6896 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
6897 {{ 1.0f, 0.0f, 0.f}, 0x88888888},
6899 const DWORD indices12[] = {0, 1, 2, 3, 4, 5};
6900 const DWORD attributes12[] = {0, 0};
6901 const UINT num_vertices12 = ARRAY_SIZE(vertices12);
6902 const UINT num_faces12 = ARRAY_SIZE(indices12) / VERTS_PER_FACE;
6903 DWORD flags12 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
6904 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};
6905 const DWORD adjacency12[] = {-1, 1, -1, -1, -1, 0};
6906 const struct vertex_color exp_vertices12[] =
6908 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
6909 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
6910 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
6912 {{ 2.0f, 3.0f, 0.f}, 0x00000000},
6913 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
6915 const DWORD exp_indices12[] = {0, 1, 2, 3, 4, 2};
6916 const DWORD exp_face_remap12[] = {0, 1};
6917 const DWORD exp_vertex_remap12[] = {0, 1, 2, 3, 4, -1};
6918 const DWORD exp_new_num_vertices12 = ARRAY_SIZE(exp_vertices12);
6919 /* Test 13. Two faces. One vertex should be removed because of normal epsilon.
6920 * This is similar to test 3, but the declaration has been changed to NORMAL3.
6922 const struct vertex_normal vertices13[] =
6924 {{ 0.0f, 3.0f, 0.f}, up},
6925 {{ 2.0f, 3.0f, 0.f}, up},
6926 {{ 0.0f, 0.0f, 0.f}, up},
6928 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
6929 {{ 3.0f, 0.0f, 0.f}, up},
6930 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6932 const DWORD indices13[] = {0, 1, 2, 3, 4, 5};
6933 const DWORD attributes13[] = {0, 0};
6934 const UINT num_vertices13 = ARRAY_SIZE(vertices3);
6935 const UINT num_faces13 = ARRAY_SIZE(indices3) / VERTS_PER_FACE;
6936 DWORD flags13 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
6937 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};
6938 const DWORD adjacency13[] = {-1, 1, -1, -1, -1, 0};
6939 const struct vertex_normal exp_vertices13[] =
6941 {{ 0.0f, 3.0f, 0.f}, up},
6942 {{ 2.0f, 3.0f, 0.f}, up},
6943 {{ 0.0f, 0.0f, 0.f}, up},
6945 {{ 3.0f, 0.0f, 0.f}, up},
6946 {{ 0.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6948 const DWORD exp_indices13[] = {0, 1, 2, 1, 3, 4};
6949 const DWORD exp_face_remap13[] = {0, 1};
6950 const DWORD exp_vertex_remap13[] = {0, 1, 2, 4, 5, -1};
6951 const DWORD exp_new_num_vertices13 = ARRAY_SIZE(exp_vertices13);
6952 /* Test 14. Another test for welding with color. */
6953 const struct vertex_color vertices14[] =
6955 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
6956 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
6957 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
6959 {{ 3.0f, 3.0f, 0.f}, 0x00000000},
6960 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
6961 {{ 1.0f, 0.0f, 0.f}, 0x01010101},
6963 const DWORD indices14[] = {0, 1, 2, 3, 4, 5};
6964 const DWORD attributes14[] = {0, 0};
6965 const UINT num_vertices14 = ARRAY_SIZE(vertices14);
6966 const UINT num_faces14 = ARRAY_SIZE(indices14) / VERTS_PER_FACE;
6967 DWORD flags14 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
6968 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};
6969 const DWORD adjacency14[] = {-1, 1, -1, -1, -1, 0};
6970 const struct vertex_color exp_vertices14[] =
6972 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
6973 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
6974 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
6976 {{ 2.0f, 3.0f, 0.f}, 0x00000000},
6977 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
6979 const DWORD exp_indices14[] = {0, 1, 2, 3, 4, 2};
6980 const DWORD exp_face_remap14[] = {0, 1};
6981 const DWORD exp_vertex_remap14[] = {0, 1, 2, 3, 4, -1};
6982 const DWORD exp_new_num_vertices14 = ARRAY_SIZE(exp_vertices14);
6983 /* Test 15. Weld with color, but as UBYTE4N instead of D3DCOLOR. It shows
6984 * that UBYTE4N and D3DCOLOR are compared the same way.
6986 const struct vertex_color_ubyte4 vertices15[] =
6988 {{ 0.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
6989 {{ 2.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
6990 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
6992 {{ 3.0f, 3.0f, 0.f}, { 0, 0, 0, 0}},
6993 {{ 3.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
6994 {{ 1.0f, 0.0f, 0.f}, { 1, 1, 1, 1}},
6996 const DWORD indices15[] = {0, 1, 2, 3, 4, 5};
6997 const DWORD attributes15[] = {0, 0};
6998 const UINT num_vertices15 = ARRAY_SIZE(vertices15);
6999 const UINT num_faces15 = ARRAY_SIZE(indices15) / VERTS_PER_FACE;
7000 DWORD flags15 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7001 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};
7002 const DWORD adjacency15[] = {-1, 1, -1, -1, -1, 0};
7003 const struct vertex_color_ubyte4 exp_vertices15[] =
7005 {{ 0.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7006 {{ 2.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7007 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7009 {{ 2.0f, 3.0f, 0.f}, { 0, 0, 0, 0}},
7010 {{ 3.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7012 const DWORD exp_indices15[] = {0, 1, 2, 3, 4, 2};
7013 const DWORD exp_face_remap15[] = {0, 1};
7014 const DWORD exp_vertex_remap15[] = {0, 1, 2, 3, 4, -1};
7015 const DWORD exp_new_num_vertices15 = ARRAY_SIZE(exp_vertices15);
7016 /* Test 16. Weld with color, but as UBYTE4 instead of D3DCOLOR. It shows
7017 * that UBYTE4 is not normalized and that epsilon is truncated and compared
7018 * directly to each of the four bytes.
7020 const struct vertex_color_ubyte4 vertices16[] =
7022 {{ 0.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7023 {{ 2.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7024 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7026 {{ 3.0f, 3.0f, 0.f}, { 0, 0, 0, 0}},
7027 {{ 3.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7028 {{ 1.0f, 0.0f, 0.f}, { 1, 1, 1, 1}},
7030 const DWORD indices16[] = {0, 1, 2, 3, 4, 5};
7031 const DWORD attributes16[] = {0, 0};
7032 const UINT num_vertices16 = ARRAY_SIZE(vertices16);
7033 const UINT num_faces16 = ARRAY_SIZE(indices16) / VERTS_PER_FACE;
7034 DWORD flags16 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7035 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};
7036 const DWORD adjacency16[] = {-1, 1, -1, -1, -1, 0};
7037 const struct vertex_color_ubyte4 exp_vertices16[] =
7039 {{ 0.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7040 {{ 2.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7041 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7043 {{ 2.0f, 3.0f, 0.f}, { 0, 0, 0, 0}},
7044 {{ 3.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7046 const DWORD exp_indices16[] = {0, 1, 2, 3, 4, 2};
7047 const DWORD exp_face_remap16[] = {0, 1};
7048 const DWORD exp_vertex_remap16[] = {0, 1, 2, 3, 4, -1};
7049 const DWORD exp_new_num_vertices16 = ARRAY_SIZE(exp_vertices16);
7050 /* Test 17. Weld texture coordinates but as SHORT2 instead of D3DXVECTOR2.*/
7051 const struct vertex_texcoord_short2 vertices17[] =
7053 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7054 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7055 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7057 {{ 3.0f, 3.0f, 0.f}, {32767, 32767}},
7058 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7059 {{ 1.0f, 0.0f, 0.f}, {32766, 32766}},
7061 const DWORD indices17[] = {0, 1, 2, 3, 4, 5};
7062 const DWORD attributes17[] = {0, 0};
7063 const UINT num_vertices17 = ARRAY_SIZE(vertices17);
7064 const UINT num_faces17 = ARRAY_SIZE(indices17) / VERTS_PER_FACE;
7065 DWORD flags17 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7066 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};
7067 const DWORD adjacency17[] = {-1, 1, -1, -1, -1, 0};
7068 const struct vertex_texcoord_short2 exp_vertices17[] =
7070 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7071 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7072 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7074 {{ 2.0f, 3.0f, 0.f}, {32767, 32767}},
7075 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7077 const DWORD exp_indices17[] = {0, 1, 2, 3, 4, 2};
7078 const DWORD exp_face_remap17[] = {0, 1};
7079 const DWORD exp_vertex_remap17[] = {0, 1, 2, 3, 4, -1};
7080 const DWORD exp_new_num_vertices17 = ARRAY_SIZE(exp_vertices17);
7081 /* Test 18. Weld texture coordinates but as SHORT2N instead of D3DXVECTOR2. */
7082 const struct vertex_texcoord_short2 vertices18[] =
7084 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7085 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7086 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7088 {{ 3.0f, 3.0f, 0.f}, {32767, 32767}},
7089 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7090 {{ 1.0f, 0.0f, 0.f}, {32766, 32766}},
7092 const DWORD indices18[] = {0, 1, 2, 3, 4, 5};
7093 const DWORD attributes18[] = {0, 0};
7094 const UINT num_vertices18 = ARRAY_SIZE(vertices18);
7095 const UINT num_faces18 = ARRAY_SIZE(indices18) / VERTS_PER_FACE;
7096 DWORD flags18 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7097 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};
7098 const DWORD adjacency18[] = {-1, 1, -1, -1, -1, 0};
7099 const struct vertex_texcoord_short2 exp_vertices18[] =
7101 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7102 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7103 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7105 {{ 2.0f, 3.0f, 0.f}, {32767, 32767}},
7106 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7108 const DWORD exp_indices18[] = {0, 1, 2, 3, 4, 2};
7109 const DWORD exp_face_remap18[] = {0, 1};
7110 const DWORD exp_vertex_remap18[] = {0, 1, 2, 3, 4, -1};
7111 const DWORD exp_new_num_vertices18 = ARRAY_SIZE(exp_vertices18);
7112 /* Test 19. Weld texture coordinates but as USHORT2N instead of D3DXVECTOR2. */
7113 const struct vertex_texcoord_ushort2n vertices19[] =
7115 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7116 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7117 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7119 {{ 3.0f, 3.0f, 0.f}, {65535, 65535}},
7120 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7121 {{ 1.0f, 0.0f, 0.f}, {65534, 65534}},
7123 const DWORD indices19[] = {0, 1, 2, 3, 4, 5};
7124 const DWORD attributes19[] = {0, 0};
7125 const UINT num_vertices19 = ARRAY_SIZE(vertices19);
7126 const UINT num_faces19 = ARRAY_SIZE(indices19) / VERTS_PER_FACE;
7127 DWORD flags19 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7128 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};
7129 const DWORD adjacency19[] = {-1, 1, -1, -1, -1, 0};
7130 const struct vertex_texcoord_ushort2n exp_vertices19[] =
7132 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7133 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7134 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7136 {{ 2.0f, 3.0f, 0.f}, {65535, 65535}},
7137 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7139 const DWORD exp_indices19[] = {0, 1, 2, 3, 4, 2};
7140 const DWORD exp_face_remap19[] = {0, 1};
7141 const DWORD exp_vertex_remap19[] = {0, 1, 2, 3, 4, -1};
7142 const DWORD exp_new_num_vertices19 = ARRAY_SIZE(exp_vertices19);
7143 /* Test 20. Weld normal as SHORT4 instead of D3DXVECTOR3. */
7144 const struct vertex_normal_short4 vertices20[] =
7146 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7147 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7148 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7150 {{ 3.0f, 3.0f, 0.f}, {32767, 32767, 32767, 32767}},
7151 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7152 {{ 1.0f, 0.0f, 0.f}, {32766, 32766, 32766, 32766}},
7154 const DWORD indices20[] = {0, 1, 2, 3, 4, 5};
7155 const DWORD attributes20[] = {0, 0};
7156 const UINT num_vertices20 = ARRAY_SIZE(vertices20);
7157 const UINT num_faces20 = ARRAY_SIZE(indices20) / VERTS_PER_FACE;
7158 DWORD flags20 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7159 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};
7160 const DWORD adjacency20[] = {-1, 1, -1, -1, -1, 0};
7161 const struct vertex_normal_short4 exp_vertices20[] =
7163 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7164 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7165 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7167 {{ 2.0f, 3.0f, 0.f}, {32767, 32767, 32767, 32767}},
7168 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7170 const DWORD exp_indices20[] = {0, 1, 2, 3, 4, 2};
7171 const DWORD exp_face_remap20[] = {0, 1};
7172 const DWORD exp_vertex_remap20[] = {0, 1, 2, 3, 4, -1};
7173 const DWORD exp_new_num_vertices20 = ARRAY_SIZE(exp_vertices20);
7174 /* Test 21. Weld normal as SHORT4N instead of D3DXVECTOR3. */
7175 const struct vertex_normal_short4 vertices21[] =
7177 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7178 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7179 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7181 {{ 3.0f, 3.0f, 0.f}, {32767, 32767, 32767, 32767}},
7182 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7183 {{ 1.0f, 0.0f, 0.f}, {32766, 32766, 32766, 32766}},
7185 const DWORD indices21[] = {0, 1, 2, 3, 4, 5};
7186 const DWORD attributes21[] = {0, 0};
7187 const UINT num_vertices21 = ARRAY_SIZE(vertices21);
7188 const UINT num_faces21 = ARRAY_SIZE(indices21) / VERTS_PER_FACE;
7189 DWORD flags21 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7190 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};
7191 const DWORD adjacency21[] = {-1, 1, -1, -1, -1, 0};
7192 const struct vertex_normal_short4 exp_vertices21[] =
7194 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7195 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7196 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7198 {{ 2.0f, 3.0f, 0.f}, {32767, 32767, 32767, 32767}},
7199 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7201 const DWORD exp_indices21[] = {0, 1, 2, 3, 4, 2};
7202 const DWORD exp_face_remap21[] = {0, 1};
7203 const DWORD exp_vertex_remap21[] = {0, 1, 2, 3, 4, -1};
7204 const DWORD exp_new_num_vertices21 = ARRAY_SIZE(exp_vertices21);
7205 /* Test 22. Weld normal as USHORT4N instead of D3DXVECTOR3. */
7206 const struct vertex_normal_short4 vertices22[] =
7208 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7209 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7210 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7212 {{ 3.0f, 3.0f, 0.f}, {65535, 65535, 65535, 65535}},
7213 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7214 {{ 1.0f, 0.0f, 0.f}, {65534, 65534, 65534, 65534}},
7216 const DWORD indices22[] = {0, 1, 2, 3, 4, 5};
7217 const DWORD attributes22[] = {0, 0};
7218 const UINT num_vertices22 = ARRAY_SIZE(vertices22);
7219 const UINT num_faces22 = ARRAY_SIZE(indices22) / VERTS_PER_FACE;
7220 DWORD flags22 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7221 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};
7222 const DWORD adjacency22[] = {-1, 1, -1, -1, -1, 0};
7223 const struct vertex_normal_short4 exp_vertices22[] =
7225 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7226 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7227 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7229 {{ 2.0f, 3.0f, 0.f}, {65535, 65535, 65535, 65535}},
7230 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7232 const DWORD exp_indices22[] = {0, 1, 2, 3, 4, 2};
7233 const DWORD exp_face_remap22[] = {0, 1};
7234 const DWORD exp_vertex_remap22[] = {0, 1, 2, 3, 4, -1};
7235 const DWORD exp_new_num_vertices22 = ARRAY_SIZE(exp_vertices22);
7236 /* Test 23. Weld texture coordinates as FLOAT16_2. Similar to test 11, but
7237 * with texture coordinates converted to float16 in hex. */
7238 const struct vertex_texcoord_float16_2 vertices23[] =
7240 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
7241 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */
7242 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */
7244 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd}}, /* {0.2f, 0.3f} */
7245 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
7246 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */
7248 const DWORD indices23[] = {0, 1, 2, 3, 4, 5};
7249 const DWORD attributes23[] = {0, 0};
7250 const UINT num_vertices23 = ARRAY_SIZE(vertices23);
7251 const UINT num_faces23 = ARRAY_SIZE(indices23) / VERTS_PER_FACE;
7252 DWORD flags23 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7253 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};
7254 const DWORD adjacency23[] = {-1, 1, -1, -1, -1, 0};
7255 const struct vertex_texcoord_float16_2 exp_vertices23[] =
7257 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
7258 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */
7259 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */
7261 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
7262 {{ 0.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */
7264 const DWORD exp_indices23[] = {0, 1, 2, 1, 3, 4};
7265 const DWORD exp_face_remap23[] = {0, 1};
7266 const DWORD exp_vertex_remap23[] = {0, 1, 2, 4, 5, -1};
7267 const DWORD exp_new_num_vertices23 = ARRAY_SIZE(exp_vertices23);
7268 /* Test 24. Weld texture coordinates as FLOAT16_4. Similar to test 24. */
7269 const struct vertex_texcoord_float16_4 vertices24[] =
7271 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}},
7272 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a, 0x3800, 0x399a}},
7273 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd, 0xb266, 0xb4cd}},
7275 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd, 0x3266, 0x34cd}},
7276 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}},
7277 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266, 0x2e66, 0x3266}},
7279 const DWORD indices24[] = {0, 1, 2, 3, 4, 5};
7280 const DWORD attributes24[] = {0, 0};
7281 const UINT num_vertices24 = ARRAY_SIZE(vertices24);
7282 const UINT num_faces24 = ARRAY_SIZE(indices24) / VERTS_PER_FACE;
7283 DWORD flags24 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7284 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};
7285 const DWORD adjacency24[] = {-1, 1, -1, -1, -1, 0};
7286 const struct vertex_texcoord_float16_4 exp_vertices24[] =
7288 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}},
7289 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a, 0x3800, 0x399a}},
7290 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd, 0xb266, 0xb4cd}},
7292 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}},
7293 {{ 0.0f, 0.0f, 0.f}, {0x2e66, 0x3266, 0x2e66, 0x3266}},
7295 const DWORD exp_indices24[] = {0, 1, 2, 1, 3, 4};
7296 const DWORD exp_face_remap24[] = {0, 1};
7297 const DWORD exp_vertex_remap24[] = {0, 1, 2, 4, 5, -1};
7298 const DWORD exp_new_num_vertices24 = ARRAY_SIZE(exp_vertices24);
7299 /* Test 25. Weld texture coordinates with usage index 10 (TEXCOORD10). The
7300 * usage index is capped at 7, so the epsilon for TEXCOORD7 is used instead.
7302 const struct vertex_texcoord vertices25[] =
7304 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f}},
7305 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.7f}},
7306 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
7308 {{ 3.0f, 3.0f, 0.f}, {0.2f, 0.3f}},
7309 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f}},
7310 {{ 1.0f, 0.0f, 0.f}, {0.1f, 0.2f}}
7312 const DWORD indices25[] = {0, 1, 2, 3, 4, 5};
7313 const DWORD attributes25[] = {0, 0};
7314 const UINT num_vertices25 = ARRAY_SIZE(vertices25);
7315 const UINT num_faces25 = ARRAY_SIZE(indices25) / VERTS_PER_FACE;
7316 DWORD flags25 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7317 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};
7318 const DWORD adjacency25[] = {-1, 1, -1, -1, -1, 0};
7319 const struct vertex_texcoord exp_vertices25[] =
7321 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f}},
7322 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.7f}},
7323 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
7325 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f}},
7326 {{ 0.0f, 0.0f, 0.f}, {0.1f, 0.2f}},
7328 const DWORD exp_indices25[] = {0, 1, 2, 1, 3, 4};
7329 const DWORD exp_face_remap25[] = {0, 1};
7330 const DWORD exp_vertex_remap25[] = {0, 1, 2, 4, 5, -1};
7331 const DWORD exp_new_num_vertices25 = ARRAY_SIZE(exp_vertices25);
7332 /* Test 26. Weld color with usage index larger than 1. Shows that none of
7333 * the epsilon values are used. */
7334 const struct vertex_color vertices26[] =
7336 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7337 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7338 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7340 {{ 3.0f, 3.0f, 0.f}, 0x00000000},
7341 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7342 {{ 1.0f, 0.0f, 0.f}, 0x01010101},
7344 const DWORD indices26[] = {0, 1, 2, 3, 4, 5};
7345 const DWORD attributes26[] = {0, 0};
7346 const UINT num_vertices26 = ARRAY_SIZE(vertices26);
7347 const UINT num_faces26 = ARRAY_SIZE(indices26) / VERTS_PER_FACE;
7348 DWORD flags26 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7349 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};
7350 const DWORD adjacency26[] = {-1, 1, -1, -1, -1, 0};
7351 const struct vertex_color exp_vertices26[] =
7353 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7354 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7355 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7357 {{ 2.0f, 3.0f, 0.f}, 0x00000000},
7358 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7359 {{ 0.0f, 0.0f, 0.f}, 0x01010101},
7361 const DWORD exp_indices26[] = {0, 1, 2, 3, 4, 5};
7362 const DWORD exp_face_remap26[] = {0, 1};
7363 const DWORD exp_vertex_remap26[] = {0, 1, 2, 3, 4, 5};
7364 const DWORD exp_new_num_vertices26 = ARRAY_SIZE(exp_vertices26);
7365 /* Test 27. Weld color with usage index larger than 1. Check that the
7366 * default epsilon of 1e-6f is used. */
7367 D3DXVECTOR4 zero_float4 = {0.0f, 0.0f, 0.0f, 0.0f};
7368 D3DXVECTOR4 almost_zero_float4 = {0.0f + FLT_EPSILON, 0.0f + FLT_EPSILON, 0.0f + FLT_EPSILON, 0.0f + FLT_EPSILON};
7369 const struct vertex_color_float4 vertices27[] =
7371 {{ 0.0f, 3.0f, 0.f}, zero_float4},
7372 {{ 2.0f, 3.0f, 0.f}, zero_float4},
7373 {{ 0.0f, 0.0f, 0.f}, zero_float4},
7375 {{ 3.0f, 3.0f, 0.f}, almost_zero_float4},
7376 {{ 3.0f, 0.0f, 0.f}, zero_float4},
7377 {{ 1.0f, 0.0f, 0.f}, almost_zero_float4},
7379 const DWORD indices27[] = {0, 1, 2, 3, 4, 5};
7380 const DWORD attributes27[] = {0, 0};
7381 const UINT num_vertices27 = ARRAY_SIZE(vertices27);
7382 const UINT num_faces27 = ARRAY_SIZE(indices27) / VERTS_PER_FACE;
7383 DWORD flags27 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7384 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};
7385 const DWORD adjacency27[] = {-1, 1, -1, -1, -1, 0};
7386 const struct vertex_color_float4 exp_vertices27[] =
7388 {{ 0.0f, 3.0f, 0.f}, zero_float4},
7389 {{ 2.0f, 3.0f, 0.f}, zero_float4},
7390 {{ 0.0f, 0.0f, 0.f}, zero_float4},
7392 {{ 3.0f, 0.0f, 0.f}, zero_float4},
7394 const DWORD exp_indices27[] = {0, 1, 2, 1, 3, 2};
7395 const DWORD exp_face_remap27[] = {0, 1};
7396 const DWORD exp_vertex_remap27[] = {0, 1, 2, 4, -1, -1};
7397 const DWORD exp_new_num_vertices27 = ARRAY_SIZE(exp_vertices27);
7398 /* Test 28. Weld one normal with UDEC3. */
7399 const DWORD dword_udec3_zero = init_udec3_dword(0, 0, 0, 1);
7400 const DWORD dword_udec3_1023 = init_udec3_dword(1023, 1023, 1023, 1);
7401 const DWORD dword_udec3_1022 = init_udec3_dword(1022, 1022, 1022, 1);
7402 const struct vertex_normal_udec3 vertices28[] =
7404 {{ 0.0f, 3.0f, 0.f}, dword_udec3_zero},
7405 {{ 2.0f, 3.0f, 0.f}, dword_udec3_zero},
7406 {{ 0.0f, 0.0f, 0.f}, dword_udec3_zero},
7408 {{ 3.0f, 3.0f, 0.f}, dword_udec3_1023},
7409 {{ 3.0f, 0.0f, 0.f}, dword_udec3_zero},
7410 {{ 1.0f, 0.0f, 0.f}, dword_udec3_1022},
7412 const DWORD indices28[] = {0, 1, 2, 3, 4, 5};
7413 const DWORD attributes28[] = {0, 0};
7414 const UINT num_vertices28 = ARRAY_SIZE(vertices28);
7415 const UINT num_faces28 = ARRAY_SIZE(indices28) / VERTS_PER_FACE;
7416 DWORD flags28 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7417 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};
7418 const DWORD adjacency28[] = {-1, 1, -1, -1, -1, 0};
7419 const struct vertex_normal_udec3 exp_vertices28[] =
7421 {{ 0.0f, 3.0f, 0.f}, dword_udec3_zero},
7422 {{ 2.0f, 3.0f, 0.f}, dword_udec3_zero},
7423 {{ 0.0f, 0.0f, 0.f}, dword_udec3_zero},
7425 {{ 2.0f, 3.0f, 0.f}, dword_udec3_1023},
7426 {{ 3.0f, 0.0f, 0.f}, dword_udec3_zero},
7428 const DWORD exp_indices28[] = {0, 1, 2, 3, 4, 2};
7429 const DWORD exp_face_remap28[] = {0, 1};
7430 const DWORD exp_vertex_remap28[] = {0, 1, 2, 3, 4, -1};
7431 const DWORD exp_new_num_vertices28 = ARRAY_SIZE(exp_vertices28);
7432 /* Test 29. Weld one normal with DEC3N. */
7433 const DWORD dword_dec3n_zero = init_dec3n_dword(0, 0, 0, 1);
7434 const DWORD dword_dec3n_511 = init_dec3n_dword(511, 511, 511, 1);
7435 const DWORD dword_dec3n_510 = init_dec3n_dword(510, 510, 510, 1);
7436 const struct vertex_normal_dec3n vertices29[] =
7438 {{ 0.0f, 3.0f, 0.f}, dword_dec3n_zero},
7439 {{ 2.0f, 3.0f, 0.f}, dword_dec3n_zero},
7440 {{ 0.0f, 0.0f, 0.f}, dword_dec3n_zero},
7442 {{ 3.0f, 3.0f, 0.f}, dword_dec3n_511},
7443 {{ 3.0f, 0.0f, 0.f}, dword_dec3n_zero},
7444 {{ 1.0f, 0.0f, 0.f}, dword_dec3n_510},
7446 const DWORD indices29[] = {0, 1, 2, 3, 4, 5};
7447 const DWORD attributes29[] = {0, 0};
7448 const UINT num_vertices29 = ARRAY_SIZE(vertices29);
7449 const UINT num_faces29 = ARRAY_SIZE(indices29) / VERTS_PER_FACE;
7450 DWORD flags29 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7451 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};
7452 const DWORD adjacency29[] = {-1, 1, -1, -1, -1, 0};
7453 const struct vertex_normal_dec3n exp_vertices29[] =
7455 {{ 0.0f, 3.0f, 0.f}, dword_dec3n_zero},
7456 {{ 2.0f, 3.0f, 0.f}, dword_dec3n_zero},
7457 {{ 0.0f, 0.0f, 0.f}, dword_dec3n_zero},
7459 {{ 2.0f, 3.0f, 0.f}, dword_dec3n_511},
7460 {{ 3.0f, 0.0f, 0.f}, dword_dec3n_zero},
7462 const DWORD exp_indices29[] = {0, 1, 2, 3, 4, 2};
7463 const DWORD exp_face_remap29[] = {0, 1};
7464 const DWORD exp_vertex_remap29[] = {0, 1, 2, 3, 4, -1};
7465 const DWORD exp_new_num_vertices29 = ARRAY_SIZE(exp_vertices29);
7466 /* All mesh data */
7467 DWORD *adjacency_out = NULL;
7468 DWORD *face_remap = NULL;
7469 ID3DXMesh *mesh = NULL;
7470 ID3DXBuffer *vertex_remap = NULL;
7471 struct
7473 const BYTE *vertices;
7474 const DWORD *indices;
7475 const DWORD *attributes;
7476 const DWORD num_vertices;
7477 const DWORD num_faces;
7478 const DWORD options;
7479 D3DVERTEXELEMENT9 *declaration;
7480 const UINT vertex_size;
7481 const DWORD flags;
7482 const D3DXWELDEPSILONS *epsilons;
7483 const DWORD *adjacency;
7484 const BYTE *exp_vertices;
7485 const DWORD *exp_indices;
7486 const DWORD *exp_face_remap;
7487 const DWORD *exp_vertex_remap;
7488 const DWORD exp_new_num_vertices;
7490 tc[] =
7493 (BYTE*)vertices0,
7494 indices0,
7495 attributes0,
7496 num_vertices0,
7497 num_faces0,
7498 options,
7499 declaration_normal,
7500 vertex_size_normal,
7501 flags0,
7502 NULL,
7503 adjacency0,
7504 (BYTE*)exp_vertices0,
7505 exp_indices0,
7506 exp_face_remap0,
7507 exp_vertex_remap0,
7508 exp_new_num_vertices0
7511 (BYTE*)vertices1,
7512 indices1,
7513 attributes1,
7514 num_vertices1,
7515 num_faces1,
7516 options,
7517 declaration_normal,
7518 vertex_size_normal,
7519 flags1,
7520 NULL,
7521 adjacency1,
7522 (BYTE*)exp_vertices1,
7523 exp_indices1,
7524 exp_face_remap1,
7525 exp_vertex_remap1,
7526 exp_new_num_vertices1
7529 (BYTE*)vertices2,
7530 indices2,
7531 attributes2,
7532 num_vertices2,
7533 num_faces2,
7534 options,
7535 declaration_normal,
7536 vertex_size_normal,
7537 flags2,
7538 &epsilons2,
7539 adjacency2,
7540 (BYTE*)exp_vertices2,
7541 exp_indices2,
7542 exp_face_remap2,
7543 exp_vertex_remap2,
7544 exp_new_num_vertices2
7547 (BYTE*)vertices3,
7548 indices3,
7549 attributes3,
7550 num_vertices3,
7551 num_faces3,
7552 options,
7553 declaration_normal,
7554 vertex_size_normal,
7555 flags3,
7556 &epsilons3,
7557 adjacency3,
7558 (BYTE*)exp_vertices3,
7559 exp_indices3,
7560 exp_face_remap3,
7561 exp_vertex_remap3,
7562 exp_new_num_vertices3
7565 (BYTE*)vertices4,
7566 indices4,
7567 attributes4,
7568 num_vertices4,
7569 num_faces4,
7570 options,
7571 declaration_normal,
7572 vertex_size_normal,
7573 flags4,
7574 &epsilons4,
7575 adjacency4,
7576 (BYTE*)exp_vertices4,
7577 exp_indices4,
7578 exp_face_remap4,
7579 exp_vertex_remap4,
7580 exp_new_num_vertices4
7582 /* Unusual ordering. */
7584 (BYTE*)vertices5,
7585 indices5,
7586 attributes5,
7587 num_vertices5,
7588 num_faces5,
7589 options,
7590 declaration_normal,
7591 vertex_size_normal,
7592 flags5,
7593 NULL,
7594 adjacency5,
7595 (BYTE*)exp_vertices5,
7596 exp_indices5,
7597 exp_face_remap5,
7598 exp_vertex_remap5,
7599 exp_new_num_vertices5
7602 (BYTE*)vertices6,
7603 indices6,
7604 attributes6,
7605 num_vertices6,
7606 num_faces6,
7607 options,
7608 declaration_normal,
7609 vertex_size_normal,
7610 flags6,
7611 &epsilons6,
7612 adjacency6,
7613 (BYTE*)exp_vertices6,
7614 exp_indices6,
7615 exp_face_remap6,
7616 exp_vertex_remap6,
7617 exp_new_num_vertices6
7620 (BYTE*)vertices6,
7621 (DWORD*)indices6_16bit,
7622 attributes6,
7623 num_vertices6,
7624 num_faces6,
7625 options_16bit,
7626 declaration_normal,
7627 vertex_size_normal,
7628 flags6,
7629 &epsilons6,
7630 adjacency6,
7631 (BYTE*)exp_vertices6,
7632 exp_indices6,
7633 exp_face_remap6,
7634 exp_vertex_remap6,
7635 exp_new_num_vertices6
7638 (BYTE*)vertices8,
7639 indices8,
7640 attributes8,
7641 num_vertices8,
7642 num_faces8,
7643 options,
7644 declaration_normal,
7645 vertex_size_normal,
7646 flags8,
7647 &epsilons8,
7648 adjacency8,
7649 (BYTE*)exp_vertices8,
7650 exp_indices8,
7651 exp_face_remap8,
7652 exp_vertex_remap8,
7653 exp_new_num_vertices8
7656 (BYTE*)vertices9,
7657 indices9,
7658 attributes9,
7659 num_vertices9,
7660 num_faces9,
7661 options,
7662 declaration_normal,
7663 vertex_size_normal,
7664 flags9,
7665 &epsilons9,
7666 adjacency9,
7667 (BYTE*)exp_vertices9,
7668 exp_indices9,
7669 exp_face_remap9,
7670 exp_vertex_remap9,
7671 exp_new_num_vertices9
7674 (BYTE*)vertices10,
7675 indices10,
7676 attributes10,
7677 num_vertices10,
7678 num_faces10,
7679 options,
7680 declaration_blendweight,
7681 vertex_size_blendweight,
7682 flags10,
7683 &epsilons10,
7684 adjacency10,
7685 (BYTE*)exp_vertices10,
7686 exp_indices10,
7687 exp_face_remap10,
7688 exp_vertex_remap10,
7689 exp_new_num_vertices10
7692 (BYTE*)vertices11,
7693 indices11,
7694 attributes11,
7695 num_vertices11,
7696 num_faces11,
7697 options,
7698 declaration_texcoord,
7699 vertex_size_texcoord,
7700 flags11,
7701 &epsilons11,
7702 adjacency11,
7703 (BYTE*)exp_vertices11,
7704 exp_indices11,
7705 exp_face_remap11,
7706 exp_vertex_remap11,
7707 exp_new_num_vertices11
7710 (BYTE*)vertices12,
7711 indices12,
7712 attributes12,
7713 num_vertices12,
7714 num_faces12,
7715 options,
7716 declaration_color,
7717 vertex_size_color,
7718 flags12,
7719 &epsilons12,
7720 adjacency12,
7721 (BYTE*)exp_vertices12,
7722 exp_indices12,
7723 exp_face_remap12,
7724 exp_vertex_remap12,
7725 exp_new_num_vertices12
7728 (BYTE*)vertices13,
7729 indices13,
7730 attributes13,
7731 num_vertices13,
7732 num_faces13,
7733 options,
7734 declaration_normal3,
7735 vertex_size_normal,
7736 flags13,
7737 &epsilons13,
7738 adjacency13,
7739 (BYTE*)exp_vertices13,
7740 exp_indices13,
7741 exp_face_remap13,
7742 exp_vertex_remap13,
7743 exp_new_num_vertices13
7746 (BYTE*)vertices14,
7747 indices14,
7748 attributes14,
7749 num_vertices14,
7750 num_faces14,
7751 options,
7752 declaration_color,
7753 vertex_size_color,
7754 flags14,
7755 &epsilons14,
7756 adjacency14,
7757 (BYTE*)exp_vertices14,
7758 exp_indices14,
7759 exp_face_remap14,
7760 exp_vertex_remap14,
7761 exp_new_num_vertices14
7764 (BYTE*)vertices15,
7765 indices15,
7766 attributes15,
7767 num_vertices15,
7768 num_faces15,
7769 options,
7770 declaration_color_ubyte4n,
7771 vertex_size_color_ubyte4, /* UBYTE4 same size as UBYTE4N */
7772 flags15,
7773 &epsilons15,
7774 adjacency15,
7775 (BYTE*)exp_vertices15,
7776 exp_indices15,
7777 exp_face_remap15,
7778 exp_vertex_remap15,
7779 exp_new_num_vertices15
7782 (BYTE*)vertices16,
7783 indices16,
7784 attributes16,
7785 num_vertices16,
7786 num_faces16,
7787 options,
7788 declaration_color_ubyte4,
7789 vertex_size_color_ubyte4,
7790 flags16,
7791 &epsilons16,
7792 adjacency16,
7793 (BYTE*)exp_vertices16,
7794 exp_indices16,
7795 exp_face_remap16,
7796 exp_vertex_remap16,
7797 exp_new_num_vertices16
7800 (BYTE*)vertices17,
7801 indices17,
7802 attributes17,
7803 num_vertices17,
7804 num_faces17,
7805 options,
7806 declaration_texcoord_short2,
7807 vertex_size_texcoord_short2,
7808 flags17,
7809 &epsilons17,
7810 adjacency17,
7811 (BYTE*)exp_vertices17,
7812 exp_indices17,
7813 exp_face_remap17,
7814 exp_vertex_remap17,
7815 exp_new_num_vertices17
7818 (BYTE*)vertices18,
7819 indices18,
7820 attributes18,
7821 num_vertices18,
7822 num_faces18,
7823 options,
7824 declaration_texcoord_short2n,
7825 vertex_size_texcoord_short2, /* SHORT2 same size as SHORT2N */
7826 flags18,
7827 &epsilons18,
7828 adjacency18,
7829 (BYTE*)exp_vertices18,
7830 exp_indices18,
7831 exp_face_remap18,
7832 exp_vertex_remap18,
7833 exp_new_num_vertices18
7836 (BYTE*)vertices19,
7837 indices19,
7838 attributes19,
7839 num_vertices19,
7840 num_faces19,
7841 options,
7842 declaration_texcoord_ushort2n,
7843 vertex_size_texcoord_short2, /* SHORT2 same size as USHORT2N */
7844 flags19,
7845 &epsilons19,
7846 adjacency19,
7847 (BYTE*)exp_vertices19,
7848 exp_indices19,
7849 exp_face_remap19,
7850 exp_vertex_remap19,
7851 exp_new_num_vertices19
7854 (BYTE*)vertices20,
7855 indices20,
7856 attributes20,
7857 num_vertices20,
7858 num_faces20,
7859 options,
7860 declaration_normal_short4,
7861 vertex_size_normal_short4,
7862 flags20,
7863 &epsilons20,
7864 adjacency20,
7865 (BYTE*)exp_vertices20,
7866 exp_indices20,
7867 exp_face_remap20,
7868 exp_vertex_remap20,
7869 exp_new_num_vertices20
7872 (BYTE*)vertices21,
7873 indices21,
7874 attributes21,
7875 num_vertices21,
7876 num_faces21,
7877 options,
7878 declaration_normal_short4n,
7879 vertex_size_normal_short4, /* SHORT4 same size as SHORT4N */
7880 flags21,
7881 &epsilons21,
7882 adjacency21,
7883 (BYTE*)exp_vertices21,
7884 exp_indices21,
7885 exp_face_remap21,
7886 exp_vertex_remap21,
7887 exp_new_num_vertices21
7890 (BYTE*)vertices22,
7891 indices22,
7892 attributes22,
7893 num_vertices22,
7894 num_faces22,
7895 options,
7896 declaration_normal_ushort4n,
7897 vertex_size_normal_short4, /* SHORT4 same size as USHORT4N */
7898 flags22,
7899 &epsilons22,
7900 adjacency22,
7901 (BYTE*)exp_vertices22,
7902 exp_indices22,
7903 exp_face_remap22,
7904 exp_vertex_remap22,
7905 exp_new_num_vertices22
7908 (BYTE*)vertices23,
7909 indices23,
7910 attributes23,
7911 num_vertices23,
7912 num_faces23,
7913 options,
7914 declaration_texcoord_float16_2,
7915 vertex_size_texcoord_float16_2,
7916 flags23,
7917 &epsilons23,
7918 adjacency23,
7919 (BYTE*)exp_vertices23,
7920 exp_indices23,
7921 exp_face_remap23,
7922 exp_vertex_remap23,
7923 exp_new_num_vertices23
7926 (BYTE*)vertices24,
7927 indices24,
7928 attributes24,
7929 num_vertices24,
7930 num_faces24,
7931 options,
7932 declaration_texcoord_float16_4,
7933 vertex_size_texcoord_float16_4,
7934 flags24,
7935 &epsilons24,
7936 adjacency24,
7937 (BYTE*)exp_vertices24,
7938 exp_indices24,
7939 exp_face_remap24,
7940 exp_vertex_remap24,
7941 exp_new_num_vertices24
7944 (BYTE*)vertices25,
7945 indices25,
7946 attributes25,
7947 num_vertices25,
7948 num_faces25,
7949 options,
7950 declaration_texcoord10,
7951 vertex_size_texcoord,
7952 flags25,
7953 &epsilons25,
7954 adjacency25,
7955 (BYTE*)exp_vertices25,
7956 exp_indices25,
7957 exp_face_remap25,
7958 exp_vertex_remap25,
7959 exp_new_num_vertices25
7962 (BYTE*)vertices26,
7963 indices26,
7964 attributes26,
7965 num_vertices26,
7966 num_faces26,
7967 options,
7968 declaration_color2,
7969 vertex_size_color,
7970 flags26,
7971 &epsilons26,
7972 adjacency26,
7973 (BYTE*)exp_vertices26,
7974 exp_indices26,
7975 exp_face_remap26,
7976 exp_vertex_remap26,
7977 exp_new_num_vertices26
7980 (BYTE*)vertices27,
7981 indices27,
7982 attributes27,
7983 num_vertices27,
7984 num_faces27,
7985 options,
7986 declaration_color2_float4,
7987 vertex_size_color_float4,
7988 flags27,
7989 &epsilons27,
7990 adjacency27,
7991 (BYTE*)exp_vertices27,
7992 exp_indices27,
7993 exp_face_remap27,
7994 exp_vertex_remap27,
7995 exp_new_num_vertices27
7998 (BYTE*)vertices28,
7999 indices28,
8000 attributes28,
8001 num_vertices28,
8002 num_faces28,
8003 options,
8004 declaration_normal_udec3,
8005 vertex_size_normal_udec3,
8006 flags28,
8007 &epsilons28,
8008 adjacency28,
8009 (BYTE*)exp_vertices28,
8010 exp_indices28,
8011 exp_face_remap28,
8012 exp_vertex_remap28,
8013 exp_new_num_vertices28
8016 (BYTE*)vertices29,
8017 indices29,
8018 attributes29,
8019 num_vertices29,
8020 num_faces29,
8021 options,
8022 declaration_normal_dec3n,
8023 vertex_size_normal_dec3n,
8024 flags29,
8025 &epsilons29,
8026 adjacency29,
8027 (BYTE*)exp_vertices29,
8028 exp_indices29,
8029 exp_face_remap29,
8030 exp_vertex_remap29,
8031 exp_new_num_vertices29
8035 test_context = new_test_context();
8036 if (!test_context)
8038 skip("Couldn't create test context\n");
8039 goto cleanup;
8042 for (i = 0; i < ARRAY_SIZE(tc); i++)
8044 DWORD j;
8045 DWORD *vertex_remap_ptr;
8046 DWORD new_num_vertices;
8048 hr = init_test_mesh(tc[i].num_faces, tc[i].num_vertices, tc[i].options,
8049 tc[i].declaration, test_context->device, &mesh,
8050 tc[i].vertices, tc[i].vertex_size,
8051 tc[i].indices, tc[i].attributes);
8052 if (FAILED(hr))
8054 skip("Couldn't initialize test mesh %d.\n", i);
8055 goto cleanup;
8058 /* Allocate out parameters */
8059 adjacency_out = HeapAlloc(GetProcessHeap(), 0, VERTS_PER_FACE * tc[i].num_faces * sizeof(*adjacency_out));
8060 if (!adjacency_out)
8062 skip("Couldn't allocate adjacency_out array.\n");
8063 goto cleanup;
8065 face_remap = HeapAlloc(GetProcessHeap(), 0, tc[i].num_faces * sizeof(*face_remap));
8066 if (!adjacency_out)
8068 skip("Couldn't allocate face_remap array.\n");
8069 goto cleanup;
8072 hr = D3DXWeldVertices(mesh, tc[i].flags, tc[i].epsilons, tc[i].adjacency,
8073 adjacency_out, face_remap, &vertex_remap);
8074 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
8075 /* Check number of vertices*/
8076 new_num_vertices = mesh->lpVtbl->GetNumVertices(mesh);
8077 ok(new_num_vertices == tc[i].exp_new_num_vertices,
8078 "Mesh %d: new_num_vertices == %d, expected %d.\n",
8079 i, new_num_vertices, tc[i].exp_new_num_vertices);
8080 /* Check index buffer */
8081 if (tc[i].options & D3DXMESH_32BIT)
8083 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, (void**)&indices);
8084 if (FAILED(hr))
8086 skip("Couldn't lock index buffer.\n");
8087 goto cleanup;
8089 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
8091 ok(indices[j] == tc[i].exp_indices[j],
8092 "Mesh %d: indices[%d] == %d, expected %d\n",
8093 i, j, indices[j], tc[i].exp_indices[j]);
8096 else
8098 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, (void**)&indices_16bit);
8099 if (FAILED(hr))
8101 skip("Couldn't lock index buffer.\n");
8102 goto cleanup;
8104 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
8106 ok(indices_16bit[j] == tc[i].exp_indices[j],
8107 "Mesh %d: indices_16bit[%d] == %d, expected %d\n",
8108 i, j, indices_16bit[j], tc[i].exp_indices[j]);
8111 mesh->lpVtbl->UnlockIndexBuffer(mesh);
8112 indices = NULL;
8113 indices_16bit = NULL;
8114 /* Check adjacency_out */
8115 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
8117 ok(adjacency_out[j] == tc[i].adjacency[j],
8118 "Mesh %d: adjacency_out[%d] == %d, expected %d\n",
8119 i, j, adjacency_out[j], tc[i].adjacency[j]);
8121 /* Check face_remap */
8122 for (j = 0; j < tc[i].num_faces; j++)
8124 ok(face_remap[j] == tc[i].exp_face_remap[j],
8125 "Mesh %d: face_remap[%d] == %d, expected %d\n",
8126 i, j, face_remap[j], tc[i].exp_face_remap[j]);
8128 /* Check vertex_remap */
8129 vertex_remap_ptr = vertex_remap->lpVtbl->GetBufferPointer(vertex_remap);
8130 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
8132 ok(vertex_remap_ptr[j] == tc[i].exp_vertex_remap[j],
8133 "Mesh %d: vertex_remap_ptr[%d] == %d, expected %d\n",
8134 i, j, vertex_remap_ptr[j], tc[i].exp_vertex_remap[j]);
8136 /* Check vertex buffer */
8137 hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, (void*)&vertices);
8138 if (FAILED(hr))
8140 skip("Couldn't lock vertex buffer.\n");
8141 goto cleanup;
8143 /* Check contents of re-ordered vertex buffer */
8144 for (j = 0; j < tc[i].exp_new_num_vertices; j++)
8146 int index = tc[i].vertex_size*j;
8147 check_vertex_components(__LINE__, i, j, &vertices[index], &tc[i].exp_vertices[index], tc[i].declaration);
8149 mesh->lpVtbl->UnlockVertexBuffer(mesh);
8150 vertices = NULL;
8152 /* Free mesh and output data */
8153 HeapFree(GetProcessHeap(), 0, adjacency_out);
8154 adjacency_out = NULL;
8155 HeapFree(GetProcessHeap(), 0, face_remap);
8156 face_remap = NULL;
8157 vertex_remap->lpVtbl->Release(vertex_remap);
8158 vertex_remap = NULL;
8159 mesh->lpVtbl->Release(mesh);
8160 mesh = NULL;
8163 cleanup:
8164 HeapFree(GetProcessHeap(), 0, adjacency_out);
8165 HeapFree(GetProcessHeap(), 0, face_remap);
8166 if (indices) mesh->lpVtbl->UnlockIndexBuffer(mesh);
8167 if (indices_16bit) mesh->lpVtbl->UnlockIndexBuffer(mesh);
8168 if (mesh) mesh->lpVtbl->Release(mesh);
8169 if (vertex_remap) vertex_remap->lpVtbl->Release(vertex_remap);
8170 if (vertices) mesh->lpVtbl->UnlockVertexBuffer(mesh);
8171 free_test_context(test_context);
8174 static void test_clone_mesh(void)
8176 HRESULT hr;
8177 struct test_context *test_context = NULL;
8178 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
8179 D3DVERTEXELEMENT9 declaration_pn[] =
8181 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8182 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
8183 D3DDECL_END()
8185 D3DVERTEXELEMENT9 declaration_pntc[] =
8187 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8188 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
8189 {0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8190 D3DDECL_END()
8192 D3DVERTEXELEMENT9 declaration_ptcn[] =
8194 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8195 {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8196 {0, 20, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
8197 D3DDECL_END()
8199 D3DVERTEXELEMENT9 declaration_ptc[] =
8201 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8202 {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8203 D3DDECL_END()
8205 D3DVERTEXELEMENT9 declaration_ptc_float16_2[] =
8207 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8208 {0, 12, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8209 D3DDECL_END()
8211 D3DVERTEXELEMENT9 declaration_ptc_float16_4[] =
8213 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8214 {0, 12, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8215 D3DDECL_END()
8217 D3DVERTEXELEMENT9 declaration_ptc_float1[] =
8219 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8220 {0, 12, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8221 D3DDECL_END()
8223 D3DVERTEXELEMENT9 declaration_ptc_float3[] =
8225 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8226 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8227 D3DDECL_END()
8229 D3DVERTEXELEMENT9 declaration_ptc_float4[] =
8231 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8232 {0, 12, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8233 D3DDECL_END()
8235 D3DVERTEXELEMENT9 declaration_ptc_d3dcolor[] =
8237 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8238 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8239 D3DDECL_END()
8241 D3DVERTEXELEMENT9 declaration_ptc_ubyte4[] =
8243 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8244 {0, 12, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8245 D3DDECL_END()
8247 D3DVERTEXELEMENT9 declaration_ptc_ubyte4n[] =
8249 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8250 {0, 12, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8251 D3DDECL_END()
8253 D3DVERTEXELEMENT9 declaration_ptc_short2[] =
8255 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8256 {0, 12, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8257 D3DDECL_END()
8259 D3DVERTEXELEMENT9 declaration_ptc_short4[] =
8261 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8262 {0, 12, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8263 D3DDECL_END()
8265 D3DVERTEXELEMENT9 declaration_ptc_short2n[] =
8267 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8268 {0, 12, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8269 D3DDECL_END()
8271 D3DVERTEXELEMENT9 declaration_ptc_short4n[] =
8273 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8274 {0, 12, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8275 D3DDECL_END()
8277 D3DVERTEXELEMENT9 declaration_ptc_ushort2n[] =
8279 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8280 {0, 12, D3DDECLTYPE_USHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8281 D3DDECL_END()
8283 D3DVERTEXELEMENT9 declaration_ptc_ushort4n[] =
8285 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8286 {0, 12, D3DDECLTYPE_USHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8287 D3DDECL_END()
8289 D3DVERTEXELEMENT9 declaration_ptc_float16_2_partialu[] =
8291 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8292 {0, 12, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_PARTIALU, D3DDECLUSAGE_TEXCOORD, 0},
8293 D3DDECL_END()
8295 D3DVERTEXELEMENT9 declaration_pntc1[] =
8297 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8298 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
8299 {0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
8300 D3DDECL_END()
8302 const unsigned int VERTS_PER_FACE = 3;
8303 BYTE *vertices = NULL;
8304 INT i;
8305 struct vertex_pn
8307 D3DXVECTOR3 position;
8308 D3DXVECTOR3 normal;
8310 struct vertex_pntc
8312 D3DXVECTOR3 position;
8313 D3DXVECTOR3 normal;
8314 D3DXVECTOR2 texcoords;
8316 struct vertex_ptcn
8318 D3DXVECTOR3 position;
8319 D3DXVECTOR2 texcoords;
8320 D3DXVECTOR3 normal;
8322 struct vertex_ptc
8324 D3DXVECTOR3 position;
8325 D3DXVECTOR2 texcoords;
8327 struct vertex_ptc_float16_2
8329 D3DXVECTOR3 position;
8330 WORD texcoords[2]; /* float16_2 */
8332 struct vertex_ptc_float16_4
8334 D3DXVECTOR3 position;
8335 WORD texcoords[4]; /* float16_4 */
8337 struct vertex_ptc_float1
8339 D3DXVECTOR3 position;
8340 FLOAT texcoords;
8342 struct vertex_ptc_float3
8344 D3DXVECTOR3 position;
8345 FLOAT texcoords[3];
8347 struct vertex_ptc_float4
8349 D3DXVECTOR3 position;
8350 FLOAT texcoords[4];
8352 struct vertex_ptc_d3dcolor
8354 D3DXVECTOR3 position;
8355 BYTE texcoords[4];
8357 struct vertex_ptc_ubyte4
8359 D3DXVECTOR3 position;
8360 BYTE texcoords[4];
8362 struct vertex_ptc_ubyte4n
8364 D3DXVECTOR3 position;
8365 BYTE texcoords[4];
8367 struct vertex_ptc_short2
8369 D3DXVECTOR3 position;
8370 SHORT texcoords[2];
8372 struct vertex_ptc_short4
8374 D3DXVECTOR3 position;
8375 SHORT texcoords[4];
8377 struct vertex_ptc_ushort2n
8379 D3DXVECTOR3 position;
8380 USHORT texcoords[2];
8382 struct vertex_ptc_ushort4n
8384 D3DXVECTOR3 position;
8385 USHORT texcoords[4];
8387 struct vertex_ptc_udec3
8389 D3DXVECTOR3 position;
8390 DWORD texcoords;
8392 struct vertex_ptc_dec3n
8394 D3DXVECTOR3 position;
8395 DWORD texcoords;
8397 D3DXVECTOR3 up = {0.0f, 0.0f, 1.0f};
8398 D3DXVECTOR2 zero_vec2 = {0.0f, 0.0f};
8399 /* Test 0. Check that a mesh can be cloned if the new declaration is the
8400 * same as the one used to create the mesh.
8402 * 0--1 3
8403 * | / /|
8404 * |/ / |
8405 * 2 5--4
8407 const struct vertex_pn vertices0[] =
8409 {{ 0.0f, 3.0f, 0.f}, up},
8410 {{ 2.0f, 3.0f, 0.f}, up},
8411 {{ 0.0f, 0.0f, 0.f}, up},
8413 {{ 3.0f, 3.0f, 0.f}, up},
8414 {{ 3.0f, 0.0f, 0.f}, up},
8415 {{ 1.0f, 0.0f, 0.f}, up},
8417 const UINT num_vertices0 = ARRAY_SIZE(vertices0);
8418 const UINT num_faces0 = ARRAY_SIZE(vertices0) / VERTS_PER_FACE;
8419 const UINT vertex_size0 = sizeof(*vertices0);
8420 /* Test 1. Check that 16-bit indices are handled. */
8421 const DWORD options_16bit = D3DXMESH_SYSTEMMEM;
8422 /* Test 2. Check that the size of each vertex is increased and the data
8423 * moved if the new declaration adds an element after the original elements.
8425 const struct vertex_pntc exp_vertices2[] =
8427 {{ 0.0f, 3.0f, 0.f}, up, zero_vec2},
8428 {{ 2.0f, 3.0f, 0.f}, up, zero_vec2},
8429 {{ 0.0f, 0.0f, 0.f}, up, zero_vec2},
8431 {{ 3.0f, 3.0f, 0.f}, up, zero_vec2},
8432 {{ 3.0f, 0.0f, 0.f}, up, zero_vec2},
8433 {{ 1.0f, 0.0f, 0.f}, up, zero_vec2},
8435 const UINT exp_vertex_size2 = sizeof(*exp_vertices2);
8436 /* Test 3. Check that the size of each vertex is increased and the data
8437 * moved if the new declaration adds an element between the original
8438 * elements.
8440 const struct vertex_ptcn exp_vertices3[] =
8442 {{ 0.0f, 3.0f, 0.f}, zero_vec2, up},
8443 {{ 2.0f, 3.0f, 0.f}, zero_vec2, up},
8444 {{ 0.0f, 0.0f, 0.f}, zero_vec2, up},
8446 {{ 3.0f, 3.0f, 0.f}, zero_vec2, up},
8447 {{ 3.0f, 0.0f, 0.f}, zero_vec2, up},
8448 {{ 1.0f, 0.0f, 0.f}, zero_vec2, up},
8450 const UINT exp_vertex_size3 = sizeof(*exp_vertices3);
8451 /* Test 4. Test that data types can be converted, e.g. FLOAT2 to FLOAT16_2. */
8452 const struct vertex_ptc vertices4[] =
8454 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8455 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8456 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
8458 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8459 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
8460 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
8462 const UINT num_vertices4 = ARRAY_SIZE(vertices4);
8463 const UINT num_faces4 = ARRAY_SIZE(vertices4) / VERTS_PER_FACE;
8464 const UINT vertex_size4 = sizeof(*vertices4);
8465 const struct vertex_ptc_float16_2 exp_vertices4[] =
8467 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
8468 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */
8469 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */
8471 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd}}, /* {0.2f, 0.3f} */
8472 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
8473 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */
8475 const UINT exp_vertex_size4 = sizeof(*exp_vertices4);
8476 /* Test 5. Convert FLOAT2 to FLOAT16_4. */
8477 const struct vertex_ptc vertices5[] =
8479 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8480 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8481 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
8483 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8484 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
8485 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
8487 const UINT num_vertices5 = ARRAY_SIZE(vertices5);
8488 const UINT num_faces5 = ARRAY_SIZE(vertices5) / VERTS_PER_FACE;
8489 const UINT vertex_size5 = sizeof(*vertices5);
8490 const struct vertex_ptc_float16_4 exp_vertices5[] =
8492 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00, 0, 0x3c00}}, /* {1.0f, 1.0f, 0.0f, 1.0f} */
8493 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a, 0, 0x3c00}}, /* {0.5f, 0.7f, 0.0f, 1.0f} */
8494 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd, 0, 0x3c00}}, /* {-0.2f, -0.3f, 0.0f, 1.0f} */
8496 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd, 0, 0x3c00}}, /* {0.2f, 0.3f, 0.0f, 1.0f} */
8497 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00, 0, 0x3c00}}, /* {1.0f, 1.0f, 0.0f, 1.0f} */
8498 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266, 0, 0x3c00}}, /* {0.1f, 0.2f, 0.0f, 1.0f} */
8500 const UINT exp_vertex_size5 = sizeof(*exp_vertices5);
8501 /* Test 6. Convert FLOAT2 to FLOAT1. */
8502 const struct vertex_ptc vertices6[] =
8504 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8505 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8506 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
8508 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8509 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
8510 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
8512 const UINT num_vertices6 = ARRAY_SIZE(vertices6);
8513 const UINT num_faces6 = ARRAY_SIZE(vertices6) / VERTS_PER_FACE;
8514 const UINT vertex_size6 = sizeof(*vertices6);
8515 const struct vertex_ptc_float1 exp_vertices6[] =
8517 {{ 0.0f, 3.0f, 0.f}, 1.0f},
8518 {{ 2.0f, 3.0f, 0.f}, 0.5f},
8519 {{ 0.0f, 0.0f, 0.f}, -0.2f},
8521 {{ 3.0f, 3.0f, 0.f}, 0.2f},
8522 {{ 3.0f, 0.0f, 0.f}, 1.0f},
8523 {{ 1.0f, 0.0f, 0.f}, 0.1f},
8525 const UINT exp_vertex_size6 = sizeof(*exp_vertices6);
8526 /* Test 7. Convert FLOAT2 to FLOAT3. */
8527 const struct vertex_ptc vertices7[] =
8529 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8530 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8531 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
8533 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8534 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
8535 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
8537 const UINT num_vertices7 = ARRAY_SIZE(vertices7);
8538 const UINT num_faces7 = ARRAY_SIZE(vertices7) / VERTS_PER_FACE;
8539 const UINT vertex_size7 = sizeof(*vertices7);
8540 const struct vertex_ptc_float3 exp_vertices7[] =
8542 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f, 0.0f}},
8543 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f, 0.0f}},
8544 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f, 0.0f}},
8546 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f, 0.0f}},
8547 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f, 0.0f}},
8548 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f, 0.0f}},
8550 const UINT exp_vertex_size7 = sizeof(*exp_vertices7);
8551 /* Test 8. Convert FLOAT2 to FLOAT4. */
8552 const struct vertex_ptc vertices8[] =
8554 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8555 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8556 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
8558 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8559 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
8560 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
8562 const UINT num_vertices8 = ARRAY_SIZE(vertices8);
8563 const UINT num_faces8 = ARRAY_SIZE(vertices8) / VERTS_PER_FACE;
8564 const UINT vertex_size8 = sizeof(*vertices8);
8565 const struct vertex_ptc_float4 exp_vertices8[] =
8567 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f, 0.0f, 1.0f}},
8568 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f, 0.0f, 1.0f}},
8569 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f, 0.0f, 1.0f}},
8571 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f, 0.0f, 1.0f}},
8572 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f, 0.0f, 1.0f}},
8573 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f, 0.0f, 1.0f}},
8575 const UINT exp_vertex_size8 = sizeof(*exp_vertices8);
8576 /* Test 9. Convert FLOAT2 to D3DCOLOR. */
8577 const struct vertex_ptc vertices9[] =
8579 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8580 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8581 {{ 0.0f, 0.0f, 0.f}, {-0.4f, -0.6f}},
8583 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8584 {{ 3.0f, 0.0f, 0.f}, { 2.0f, 256.0f}},
8585 {{ 1.0f, 0.0f, 0.f}, { 0.11f, 0.2f}},
8587 const UINT num_vertices9 = ARRAY_SIZE(vertices9);
8588 const UINT num_faces9 = ARRAY_SIZE(vertices9) / VERTS_PER_FACE;
8589 const UINT vertex_size9 = sizeof(*vertices9);
8590 const struct vertex_ptc_d3dcolor exp_vertices9[] =
8592 {{ 0.0f, 3.0f, 0.f}, {0, 255, 255, 255}},
8593 {{ 2.0f, 3.0f, 0.f}, {0, 179, 128, 255}},
8594 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 255}},
8596 {{ 3.0f, 3.0f, 0.f}, {0, 77, 51, 255}},
8597 {{ 3.0f, 0.0f, 0.f}, {0, 255, 255, 255}},
8598 {{ 1.0f, 0.0f, 0.f}, {0, 51, 28, 255}},
8600 const UINT exp_vertex_size9 = sizeof(*exp_vertices9);
8601 /* Test 10. Convert FLOAT2 to UBYTE4. */
8602 const struct vertex_ptc vertices10[] =
8604 {{ 0.0f, 3.0f, 0.f}, { 0.0f, 1.0f}},
8605 {{ 2.0f, 3.0f, 0.f}, { 2.0f, 3.0f}},
8606 {{ 0.0f, 0.0f, 0.f}, { 254.0f, 255.0f}},
8608 {{ 3.0f, 3.0f, 0.f}, { 256.0f, 257.0f}},
8609 {{ 3.0f, 0.0f, 0.f}, { 1.4f, 1.5f}},
8610 {{ 1.0f, 0.0f, 0.f}, {-4.0f, -5.0f}},
8612 const UINT num_vertices10 = ARRAY_SIZE(vertices10);
8613 const UINT num_faces10 = ARRAY_SIZE(vertices10) / VERTS_PER_FACE;
8614 const UINT vertex_size10 = sizeof(*vertices10);
8615 const struct vertex_ptc_ubyte4 exp_vertices10[] =
8617 {{ 0.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
8618 {{ 2.0f, 3.0f, 0.f}, {2, 3, 0, 1}},
8619 {{ 0.0f, 0.0f, 0.f}, {254, 255, 0, 1}},
8621 {{ 3.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
8622 {{ 3.0f, 0.0f, 0.f}, {1, 2, 0, 1}},
8623 {{ 1.0f, 0.0f, 0.f}, {0, 0, 0, 1}},
8625 const UINT exp_vertex_size10 = sizeof(*exp_vertices10);
8626 /* Test 11. Convert FLOAT2 to SHORT2. */
8627 const struct vertex_ptc vertices11[] =
8629 {{ 0.0f, 3.0f, 0.f}, { 1.0f, -1.0f}},
8630 {{ 2.0f, 3.0f, 0.f}, { 0.4f, 0.5f}},
8631 {{ 0.0f, 0.0f, 0.f}, {-0.5f, -5.0f}},
8633 {{ 3.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MIN}},
8634 {{ 3.0f, 0.0f, 0.f}, {SHRT_MAX + 1.0f, SHRT_MIN - 1.0f}},
8635 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX + 2.0f, SHRT_MIN - 2.0f}},
8637 {{ 4.0f, 3.0f, 0.f}, {2 * SHRT_MAX, 2 * SHRT_MIN}},
8638 {{ 6.0f, 0.0f, 0.f}, {3 * SHRT_MAX, 3 * SHRT_MIN}},
8639 {{ 4.0f, 0.0f, 0.f}, {4 * SHRT_MAX, 4 * SHRT_MIN}},
8641 const UINT num_vertices11 = ARRAY_SIZE(vertices11);
8642 const UINT num_faces11 = ARRAY_SIZE(vertices11) / VERTS_PER_FACE;
8643 const UINT vertex_size11 = sizeof(*vertices11);
8644 const struct vertex_ptc_short2 exp_vertices11[] =
8646 {{ 0.0f, 3.0f, 0.f}, {1, 0}},
8647 {{ 2.0f, 3.0f, 0.f}, {0, 1}},
8648 {{ 0.0f, 0.0f, 0.f}, {0, -4}},
8650 {{ 3.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MIN + 1}},
8651 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MIN}},
8652 {{ 1.0f, 0.0f, 0.f}, {SHRT_MIN + 1, SHRT_MAX}},
8654 {{ 4.0f, 3.0f, 0.f}, {-2, 1}},
8655 {{ 6.0f, 0.0f, 0.f}, {32765, -32767}},
8656 {{ 4.0f, 0.0f, 0.f}, {-4, 1}},
8658 const UINT exp_vertex_size11 = sizeof(*exp_vertices11);
8659 /* Test 12. Convert FLOAT2 to SHORT4. */
8660 const struct vertex_ptc vertices12[] =
8662 {{ 0.0f, 3.0f, 0.f}, { 1.0f, -1.0f}},
8663 {{ 2.0f, 3.0f, 0.f}, { 0.4f, 0.5f}},
8664 {{ 0.0f, 0.0f, 0.f}, {-0.5f, -5.0f}},
8666 {{ 3.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MIN}},
8667 {{ 3.0f, 0.0f, 0.f}, {SHRT_MAX + 1.0f, SHRT_MIN - 1.0f}},
8668 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX + 2.0f, SHRT_MIN - 2.0f}},
8670 {{ 4.0f, 3.0f, 0.f}, {2 * SHRT_MAX, 2 * SHRT_MIN}},
8671 {{ 6.0f, 0.0f, 0.f}, {3 * SHRT_MAX, 3 * SHRT_MIN}},
8672 {{ 4.0f, 0.0f, 0.f}, {4 * SHRT_MAX, 4 * SHRT_MIN}},
8674 const UINT num_vertices12 = ARRAY_SIZE(vertices12);
8675 const UINT num_faces12 = ARRAY_SIZE(vertices12) / VERTS_PER_FACE;
8676 const UINT vertex_size12 = sizeof(*vertices12);
8677 const struct vertex_ptc_short4 exp_vertices12[] =
8679 {{ 0.0f, 3.0f, 0.f}, {1, 0, 0, 1}},
8680 {{ 2.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
8681 {{ 0.0f, 0.0f, 0.f}, {0, -4, 0, 1}},
8683 {{ 3.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MIN + 1, 0, 1}},
8684 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MIN, 0, 1}},
8685 {{ 1.0f, 0.0f, 0.f}, {SHRT_MIN + 1, SHRT_MAX, 0, 1}},
8687 {{ 4.0f, 3.0f, 0.f}, {-2, 1, 0, 1}},
8688 {{ 6.0f, 0.0f, 0.f}, {32765, -32767, 0, 1}},
8689 {{ 4.0f, 0.0f, 0.f}, {-4, 1, 0, 1}},
8691 const UINT exp_vertex_size12 = sizeof(*exp_vertices12);
8692 /* Test 13. Convert FLOAT2 to UBYTE4N. */
8693 const struct vertex_ptc vertices13[] =
8695 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 2.0f}},
8696 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8697 {{ 0.0f, 0.0f, 0.f}, {-0.4f, -0.5f}},
8699 {{ 3.0f, 3.0f, 0.f}, {-0.6f, -1.0f}},
8700 {{ 3.0f, 0.0f, 0.f}, {UCHAR_MAX, UCHAR_MAX + 1}},
8701 {{ 1.0f, 0.0f, 0.f}, {2 * UCHAR_MAX, -UCHAR_MAX}},
8703 const UINT num_vertices13 = ARRAY_SIZE(vertices13);
8704 const UINT num_faces13 = ARRAY_SIZE(vertices13) / VERTS_PER_FACE;
8705 const UINT vertex_size13 = sizeof(*vertices13);
8706 const struct vertex_ptc_ubyte4n exp_vertices13[] =
8708 {{ 0.0f, 3.0f, 0.f}, {255, 255, 0, 255}},
8709 {{ 2.0f, 3.0f, 0.f}, {128, 179, 0, 255}},
8710 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 255}},
8712 {{ 3.0f, 3.0f, 0.f}, {0, 0, 0, 255}},
8713 {{ 3.0f, 0.0f, 0.f}, {255, 255, 0, 255}},
8714 {{ 1.0f, 0.0f, 0.f}, {255, 0, 0, 255}},
8716 const UINT exp_vertex_size13 = sizeof(*exp_vertices13);
8717 /* Test 14. Convert FLOAT2 to SHORT2N. */
8718 const struct vertex_ptc vertices14[] =
8720 {{ 0.0f, 3.0f, 0.f}, {1.0f, 2.0f}},
8721 {{ 2.0f, 3.0f, 0.f}, {0.4f, 0.5f}},
8722 {{ 0.0f, 0.0f, 0.f}, {0.6f, -1.0f}},
8724 {{ 3.0f, 3.0f, 0.f}, {-0.4f, -0.5f}},
8725 {{ 3.0f, 0.0f, 0.f}, {-0.9f, -0.99997}},
8726 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX, SHRT_MIN}},
8728 const UINT num_vertices14 = ARRAY_SIZE(vertices14);
8729 const UINT num_faces14 = ARRAY_SIZE(vertices14) / VERTS_PER_FACE;
8730 const UINT vertex_size14 = sizeof(*vertices14);
8731 const struct vertex_ptc_short2 exp_vertices14[] =
8733 {{ 0.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MAX}},
8734 {{ 2.0f, 3.0f, 0.f}, {13107, 16384}},
8735 {{ 0.0f, 0.0f, 0.f}, {19660, SHRT_MIN + 2}},
8737 {{ 3.0f, 3.0f, 0.f}, {-13106, -16383}},
8738 {{ 3.0f, 0.0f, 0.f}, {-29489, SHRT_MIN + 3}},
8739 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX, SHRT_MIN + 2}},
8741 const UINT exp_vertex_size14 = sizeof(*exp_vertices14);
8742 /* Test 15. Convert FLOAT2 to SHORT4N. */
8743 const struct vertex_ptc vertices15[] =
8745 {{ 0.0f, 3.0f, 0.f}, {1.0f, 2.0f}},
8746 {{ 2.0f, 3.0f, 0.f}, {0.4f, 0.5f}},
8747 {{ 0.0f, 0.0f, 0.f}, {0.6f, -1.0f}},
8749 {{ 3.0f, 3.0f, 0.f}, {-0.4f, -0.5f}},
8750 {{ 3.0f, 0.0f, 0.f}, {-0.9f, -0.99997}},
8751 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX, SHRT_MIN}},
8753 const UINT num_vertices15 = ARRAY_SIZE(vertices15);
8754 const UINT num_faces15 = ARRAY_SIZE(vertices15) / VERTS_PER_FACE;
8755 const UINT vertex_size15 = sizeof(*vertices15);
8756 const struct vertex_ptc_short4 exp_vertices15[] =
8758 {{ 0.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MAX, 0, SHRT_MAX}},
8759 {{ 2.0f, 3.0f, 0.f}, {13107, 16384, 0, SHRT_MAX}},
8760 {{ 0.0f, 0.0f, 0.f}, {19660, SHRT_MIN + 2, 0, SHRT_MAX}},
8762 {{ 3.0f, 3.0f, 0.f}, {-13106, -16383, 0, SHRT_MAX}},
8763 {{ 3.0f, 0.0f, 0.f}, {-29489, SHRT_MIN + 3, 0, SHRT_MAX}},
8764 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX, SHRT_MIN + 2, 0, SHRT_MAX}},
8766 const UINT exp_vertex_size15 = sizeof(*exp_vertices15);
8767 /* Test 16. Convert FLOAT2 to USHORT2N. */
8768 const struct vertex_ptc vertices16[] =
8770 {{ 0.0f, 3.0f, 0.f}, {1.0f, 2.0f}},
8771 {{ 2.0f, 3.0f, 0.f}, {0.4f, 0.5f}},
8772 {{ 0.0f, 0.0f, 0.f}, {0.6f, -1.0f}},
8774 {{ 3.0f, 3.0f, 0.f}, {-0.4f, -0.5f}},
8775 {{ 3.0f, 0.0f, 0.f}, {-0.9f, 0.99998f}},
8776 {{ 1.0f, 0.0f, 0.f}, {USHRT_MAX, 0.0f}},
8778 const UINT num_vertices16 = ARRAY_SIZE(vertices16);
8779 const UINT num_faces16 = ARRAY_SIZE(vertices16) / VERTS_PER_FACE;
8780 const UINT vertex_size16 = sizeof(*vertices16);
8781 const struct vertex_ptc_ushort2n exp_vertices16[] =
8783 {{ 0.0f, 3.0f, 0.f}, {USHRT_MAX, USHRT_MAX}},
8784 {{ 2.0f, 3.0f, 0.f}, {26214, 32768}},
8785 {{ 0.0f, 0.0f, 0.f}, {39321, 0}},
8787 {{ 3.0f, 3.0f, 0.f}, {0, 0}},
8788 {{ 3.0f, 0.0f, 0.f}, {0, USHRT_MAX - 1}},
8789 {{ 1.0f, 0.0f, 0.f}, {USHRT_MAX, 0}},
8791 const UINT exp_vertex_size16 = sizeof(*exp_vertices16);
8792 /* Test 17. Convert FLOAT2 to USHORT4N. */
8793 const struct vertex_ptc vertices17[] =
8795 {{ 0.0f, 3.0f, 0.f}, {1.0f, 2.0f}},
8796 {{ 2.0f, 3.0f, 0.f}, {0.4f, 0.5f}},
8797 {{ 0.0f, 0.0f, 0.f}, {0.6f, -1.0f}},
8799 {{ 3.0f, 3.0f, 0.f}, {-0.4f, -0.5f}},
8800 {{ 3.0f, 0.0f, 0.f}, {-0.9f, 0.99998f}},
8801 {{ 1.0f, 0.0f, 0.f}, {USHRT_MAX, 0.0f}},
8803 const UINT num_vertices17 = ARRAY_SIZE(vertices17);
8804 const UINT num_faces17 = ARRAY_SIZE(vertices17) / VERTS_PER_FACE;
8805 const UINT vertex_size17 = sizeof(*vertices17);
8806 const struct vertex_ptc_ushort4n exp_vertices17[] =
8808 {{ 0.0f, 3.0f, 0.f}, {USHRT_MAX, USHRT_MAX, 0, USHRT_MAX}},
8809 {{ 2.0f, 3.0f, 0.f}, {26214, 32768, 0, USHRT_MAX}},
8810 {{ 0.0f, 0.0f, 0.f}, {39321, 0, 0, USHRT_MAX}},
8812 {{ 3.0f, 3.0f, 0.f}, {0, 0, 0, USHRT_MAX}},
8813 {{ 3.0f, 0.0f, 0.f}, {0, USHRT_MAX - 1, 0, USHRT_MAX}},
8814 {{ 1.0f, 0.0f, 0.f}, {USHRT_MAX, 0, 0, USHRT_MAX}},
8816 const UINT exp_vertex_size17 = sizeof(*exp_vertices17);
8817 /* Test 18. Test that the method field is compared by converting a FLOAT2 to
8818 * FLOAT16_2. where the method field has been change from
8819 * D3DDECLMETHOD_DEFAULT to D3DDECLMETHOD_PARTIALU. */
8820 const struct vertex_ptc vertices18[] =
8822 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8823 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8824 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
8826 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8827 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
8828 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
8830 const UINT num_vertices18 = ARRAY_SIZE(vertices18);
8831 const UINT num_faces18 = ARRAY_SIZE(vertices18) / VERTS_PER_FACE;
8832 const UINT vertex_size18 = sizeof(*vertices18);
8833 const struct vertex_ptc_float16_2 exp_vertices18[] =
8835 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
8836 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */
8837 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */
8839 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd}}, /* {0.2f, 0.3f} */
8840 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
8841 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */
8843 const UINT exp_vertex_size18 = sizeof(*exp_vertices18);
8844 /* Test 19. Test that data is lost if usage index changes, e.g. TEXCOORD0
8845 * TEXCOORD1. */
8846 const struct vertex_pntc vertices19[] =
8848 {{ 0.0f, 3.0f, 0.f}, up, { 1.0f, 1.0f}},
8849 {{ 2.0f, 3.0f, 0.f}, up, { 0.5f, 0.7f}},
8850 {{ 0.0f, 0.0f, 0.f}, up, {-0.2f, -0.3f}},
8852 {{ 3.0f, 3.0f, 0.f}, up, { 0.2f, 0.3f}},
8853 {{ 3.0f, 0.0f, 0.f}, up, { 1.0f, 1.0f}},
8854 {{ 1.0f, 0.0f, 0.f}, up, { 0.1f, 0.2f}},
8856 const UINT num_vertices19 = ARRAY_SIZE(vertices19);
8857 const UINT num_faces19 = ARRAY_SIZE(vertices19) / VERTS_PER_FACE;
8858 const UINT vertex_size19 = sizeof(*vertices19);
8859 const struct vertex_pntc exp_vertices19[] =
8861 {{ 0.0f, 3.0f, 0.f}, up, zero_vec2},
8862 {{ 2.0f, 3.0f, 0.f}, up, zero_vec2},
8863 {{ 0.0f, 0.0f, 0.f}, up, zero_vec2},
8865 {{ 3.0f, 3.0f, 0.f}, up, zero_vec2},
8866 {{ 3.0f, 0.0f, 0.f}, up, zero_vec2},
8867 {{ 1.0f, 0.0f, 0.f}, up, zero_vec2},
8869 const UINT exp_vertex_size19 = sizeof(*exp_vertices19);
8870 /* Test 20. Another test that data is lost if usage index changes, e.g.
8871 * TEXCOORD1 to TEXCOORD0. */
8872 const struct vertex_pntc vertices20[] =
8874 {{ 0.0f, 3.0f, 0.f}, up, { 1.0f, 1.0f}},
8875 {{ 2.0f, 3.0f, 0.f}, up, { 0.5f, 0.7f}},
8876 {{ 0.0f, 0.0f, 0.f}, up, {-0.2f, -0.3f}},
8878 {{ 3.0f, 3.0f, 0.f}, up, { 0.2f, 0.3f}},
8879 {{ 3.0f, 0.0f, 0.f}, up, { 1.0f, 1.0f}},
8880 {{ 1.0f, 0.0f, 0.f}, up, { 0.1f, 0.2f}},
8882 const UINT num_vertices20 = ARRAY_SIZE(vertices20);
8883 const UINT num_faces20 = ARRAY_SIZE(vertices20) / VERTS_PER_FACE;
8884 const UINT vertex_size20 = sizeof(*vertices20);
8885 const struct vertex_pntc exp_vertices20[] =
8887 {{ 0.0f, 3.0f, 0.f}, up, zero_vec2},
8888 {{ 2.0f, 3.0f, 0.f}, up, zero_vec2},
8889 {{ 0.0f, 0.0f, 0.f}, up, zero_vec2},
8891 {{ 3.0f, 3.0f, 0.f}, up, zero_vec2},
8892 {{ 3.0f, 0.0f, 0.f}, up, zero_vec2},
8893 {{ 1.0f, 0.0f, 0.f}, up, zero_vec2},
8895 const UINT exp_vertex_size20 = sizeof(*exp_vertices20);
8896 /* Test 21. Convert FLOAT1 to FLOAT2. */
8897 const struct vertex_ptc_float1 vertices21[] =
8899 {{ 0.0f, 3.0f, 0.f}, 1.0f},
8900 {{ 2.0f, 3.0f, 0.f}, 0.5f},
8901 {{ 0.0f, 0.0f, 0.f}, -0.2f},
8903 {{ 3.0f, 3.0f, 0.f}, 0.2f},
8904 {{ 3.0f, 0.0f, 0.f}, 1.0f},
8905 {{ 1.0f, 0.0f, 0.f}, 0.1f},
8907 const UINT num_vertices21 = ARRAY_SIZE(vertices21);
8908 const UINT num_faces21 = ARRAY_SIZE(vertices21) / VERTS_PER_FACE;
8909 const UINT vertex_size21 = sizeof(*vertices21);
8910 const struct vertex_ptc exp_vertices21[] =
8912 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 0.0f}},
8913 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.0f}},
8914 {{ 0.0f, 0.0f, 0.f}, {-0.2f, 0.0f}},
8916 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.0f}},
8917 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 0.0f}},
8918 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.0f}},
8920 const UINT exp_vertex_size21 = sizeof(*exp_vertices21);
8921 /* Test 22. Convert FLOAT1 to FLOAT3. */
8922 const struct vertex_ptc_float1 vertices22[] =
8924 {{ 0.0f, 3.0f, 0.f}, 1.0f},
8925 {{ 2.0f, 3.0f, 0.f}, 0.5f},
8926 {{ 0.0f, 0.0f, 0.f}, -0.2f},
8928 {{ 3.0f, 3.0f, 0.f}, 0.2f},
8929 {{ 3.0f, 0.0f, 0.f}, 1.0f},
8930 {{ 1.0f, 0.0f, 0.f}, 0.1f},
8932 const UINT num_vertices22 = ARRAY_SIZE(vertices22);
8933 const UINT num_faces22 = ARRAY_SIZE(vertices22) / VERTS_PER_FACE;
8934 const UINT vertex_size22 = sizeof(*vertices22);
8935 const struct vertex_ptc_float3 exp_vertices22[] =
8937 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 0.0f, 0.0f}},
8938 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.0f, 0.0f}},
8939 {{ 0.0f, 0.0f, 0.f}, {-0.2f, 0.0f, 0.0f}},
8941 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.0f, 0.0f}},
8942 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 0.0f, 0.0f}},
8943 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.0f, 0.0f}},
8945 const UINT exp_vertex_size22 = sizeof(*exp_vertices22);
8946 /* Test 23. Convert FLOAT1 to FLOAT4. */
8947 const struct vertex_ptc_float1 vertices23[] =
8949 {{ 0.0f, 3.0f, 0.f}, 1.0f},
8950 {{ 2.0f, 3.0f, 0.f}, 0.5f},
8951 {{ 0.0f, 0.0f, 0.f}, -0.2f},
8953 {{ 3.0f, 3.0f, 0.f}, 0.2f},
8954 {{ 3.0f, 0.0f, 0.f}, 1.0f},
8955 {{ 1.0f, 0.0f, 0.f}, 0.1f},
8957 const UINT num_vertices23 = ARRAY_SIZE(vertices23);
8958 const UINT num_faces23 = ARRAY_SIZE(vertices23) / VERTS_PER_FACE;
8959 const UINT vertex_size23 = sizeof(*vertices23);
8960 const struct vertex_ptc_float4 exp_vertices23[] =
8962 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 0.0f, 0.0f, 1.0f}},
8963 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.0f, 0.0f, 1.0f}},
8964 {{ 0.0f, 0.0f, 0.f}, {-0.2f, 0.0f, 0.0f, 1.0f}},
8966 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.0f, 0.0f, 1.0f}},
8967 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 0.0f, 0.0f, 1.0f}},
8968 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.0f, 0.0f, 1.0f}},
8970 const UINT exp_vertex_size23 = sizeof(*exp_vertices23);
8971 /* Test 24. Convert FLOAT1 to D3DCOLOR. */
8972 const struct vertex_ptc_float1 vertices24[] =
8974 {{ 0.0f, 3.0f, 0.f}, 1.0f},
8975 {{ 2.0f, 3.0f, 0.f}, 0.5f},
8976 {{ 0.0f, 0.0f, 0.f}, -0.2f},
8978 {{ 3.0f, 3.0f, 0.f}, 0.2f},
8979 {{ 3.0f, 0.0f, 0.f}, 1.0f},
8980 {{ 1.0f, 0.0f, 0.f}, 0.11f},
8982 const UINT num_vertices24 = ARRAY_SIZE(vertices24);
8983 const UINT num_faces24 = ARRAY_SIZE(vertices24) / VERTS_PER_FACE;
8984 const UINT vertex_size24 = sizeof(*vertices24);
8985 const struct vertex_ptc_d3dcolor exp_vertices24[] =
8987 {{ 0.0f, 3.0f, 0.f}, {0, 0, 255, 255}},
8988 {{ 2.0f, 3.0f, 0.f}, {0, 0, 128, 255}},
8989 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 255}},
8991 {{ 3.0f, 3.0f, 0.f}, {0, 0, 51, 255}},
8992 {{ 3.0f, 0.0f, 0.f}, {0, 0, 255, 255}},
8993 {{ 1.0f, 0.0f, 0.f}, {0, 0, 28, 255}},
8995 const UINT exp_vertex_size24 = sizeof(*exp_vertices24);
8996 /* Test 25. Convert FLOAT1 to ubyte4. */
8997 const struct vertex_ptc_float1 vertices25[] =
8999 {{ 0.0f, 3.0f, 0.f}, 0.0f},
9000 {{ 2.0f, 3.0f, 0.f}, 1.4f},
9001 {{ 0.0f, 0.0f, 0.f}, 1.5f},
9003 {{ 3.0f, 3.0f, 0.f}, 255.0f},
9004 {{ 3.0f, 0.0f, 0.f}, 256.0f},
9005 {{ 1.0f, 0.0f, 0.f}, -1.0f},
9007 const UINT num_vertices25 = ARRAY_SIZE(vertices25);
9008 const UINT num_faces25 = ARRAY_SIZE(vertices25) / VERTS_PER_FACE;
9009 const UINT vertex_size25 = sizeof(*vertices25);
9010 const struct vertex_ptc_ubyte4 exp_vertices25[] =
9012 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 1}},
9013 {{ 2.0f, 3.0f, 0.f}, {1, 0, 0, 1}},
9014 {{ 0.0f, 0.0f, 0.f}, {2, 0, 0, 1}},
9016 {{ 3.0f, 3.0f, 0.f}, {255, 0, 0, 1}},
9017 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 1}},
9018 {{ 1.0f, 0.0f, 0.f}, {0, 0, 0, 1}},
9020 const UINT exp_vertex_size25 = sizeof(*exp_vertices25);
9021 /* Test 26. Convert FLOAT4 to D3DCOLOR. */
9022 const struct vertex_ptc_float4 vertices26[] =
9024 {{ 0.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.4f, 0.5f}},
9025 {{ 2.0f, 3.0f, 0.f}, {-0.4f, -0.5f, -1.0f, -2.0f}},
9026 {{ 0.0f, 0.0f, 0.f}, {254.0f, 255.0f, 256.0f, 257.0f}},
9028 {{ 3.0f, 3.0f, 0.f}, {0.1f, 0.2f, 0.3f, 0.4f}},
9029 {{ 3.0f, 0.0f, 0.f}, {0.5f, 0.6f, 0.7f, 0.8f}},
9030 {{ 1.0f, 0.0f, 0.f}, {0.9f, 0.99f, 0.995f, 0.999f}},
9032 const UINT num_vertices26 = ARRAY_SIZE(vertices26);
9033 const UINT num_faces26 = ARRAY_SIZE(vertices26) / VERTS_PER_FACE;
9034 const UINT vertex_size26 = sizeof(*vertices26);
9035 const struct vertex_ptc_d3dcolor exp_vertices26[] =
9037 {{ 0.0f, 3.0f, 0.f}, {102, 255, 0, 128}},
9038 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9039 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
9041 {{ 3.0f, 3.0f, 0.f}, {77, 51, 26, 102}},
9042 {{ 3.0f, 0.0f, 0.f}, {179, 153, 128, 204}},
9043 {{ 1.0f, 0.0f, 0.f}, {254, 252, 230, 255}},
9045 const UINT exp_vertex_size26 = sizeof(*exp_vertices26);
9046 /* Test 27. Convert D3DCOLOR to FLOAT4. */
9047 const struct vertex_ptc_d3dcolor vertices27[] =
9049 {{ 0.0f, 3.0f, 0.f}, {102, 255, 0, 128}},
9050 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9051 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
9053 {{ 3.0f, 3.0f, 0.f}, {77, 51, 26, 102}},
9054 {{ 3.0f, 0.0f, 0.f}, {179, 153, 128, 204}},
9055 {{ 1.0f, 0.0f, 0.f}, {254, 252, 230, 255}},
9057 const UINT num_vertices27 = ARRAY_SIZE(vertices27);
9058 const UINT num_faces27 = ARRAY_SIZE(vertices27) / VERTS_PER_FACE;
9059 const UINT vertex_size27 = sizeof(*vertices27);
9060 const struct vertex_ptc_float4 exp_vertices27[] =
9062 {{ 0.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.4f, 0.501961f}},
9063 {{ 2.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9064 {{ 0.0f, 0.0f, 0.f}, {1.0f, 1.0f, 1.0f, 1.0f}},
9066 {{ 3.0f, 3.0f, 0.f}, {0.101961f, 0.2f, 0.301961f, 0.4f}},
9067 {{ 3.0f, 0.0f, 0.f}, {0.501961f, 0.6f, 0.701961f, 0.8f}},
9068 {{ 1.0f, 0.0f, 0.f}, {0.901961f, 0.988235f, 0.996078f, 1.0f}},
9070 const UINT exp_vertex_size27 = sizeof(*exp_vertices27);
9071 /* Test 28. Convert UBYTE4 to FLOAT4. */
9072 const struct vertex_ptc_ubyte4 vertices28[] =
9074 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9075 {{ 2.0f, 3.0f, 0.f}, {1, 1, 1, 1}},
9076 {{ 0.0f, 0.0f, 0.f}, {1, 0, 1, 0}},
9078 {{ 3.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
9079 {{ 3.0f, 0.0f, 0.f}, {10, 20, 30, 40}},
9080 {{ 1.0f, 0.0f, 0.f}, {50, 60, 127, 255}},
9082 const UINT num_vertices28 = ARRAY_SIZE(vertices28);
9083 const UINT num_faces28 = ARRAY_SIZE(vertices28) / VERTS_PER_FACE;
9084 const UINT vertex_size28 = sizeof(*vertices28);
9085 const struct vertex_ptc_float4 exp_vertices28[] =
9087 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9088 {{ 2.0f, 3.0f, 0.f}, {1.0f, 1.0f, 1.0f, 1.0f}},
9089 {{ 0.0f, 0.0f, 0.f}, {1.0f, 0.0f, 1.0f, 0.0f}},
9091 {{ 3.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.0f, 1.0f}},
9092 {{ 3.0f, 0.0f, 0.f}, {10.0f, 20.0f, 30.0f, 40.0f}},
9093 {{ 1.0f, 0.0f, 0.f}, {50.0f, 60.0f, 127.0f, 255.0f}},
9095 const UINT exp_vertex_size28 = sizeof(*exp_vertices28);
9096 /* Test 29. Convert SHORT2 to FLOAT4. */
9097 const struct vertex_ptc_short2 vertices29[] =
9099 {{ 0.0f, 3.0f, 0.f}, {0, 0}},
9100 {{ 2.0f, 3.0f, 0.f}, {0, 1}},
9101 {{ 0.0f, 0.0f, 0.f}, {1, 0}},
9103 {{ 3.0f, 3.0f, 0.f}, {1, 1}},
9104 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MAX}},
9105 {{ 1.0f, 0.0f, 0.f}, {-42, 42}},
9107 const UINT num_vertices29 = ARRAY_SIZE(vertices29);
9108 const UINT num_faces29 = ARRAY_SIZE(vertices29) / VERTS_PER_FACE;
9109 const UINT vertex_size29 = sizeof(*vertices29);
9110 const struct vertex_ptc_float4 exp_vertices29[] =
9112 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 1.0f}},
9113 {{ 2.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.0f, 1.0f }},
9114 {{ 0.0f, 0.0f, 0.f}, {1.0f, 0.0f, 0.0f, 1.0f}},
9116 {{ 3.0f, 3.0f, 0.f}, {1.0f, 1.0f, 0.0f, 1.0f}},
9117 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MAX, 0.0f, 1.0f}},
9118 {{ 1.0f, 0.0f, 0.f}, {-42.0f, 42.0f, 0.0f, 1.0f}},
9120 const UINT exp_vertex_size29 = sizeof(*exp_vertices29);
9121 /* Test 29. Convert SHORT4 to FLOAT4. */
9122 const struct vertex_ptc_short4 vertices30[] =
9124 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9125 {{ 2.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
9126 {{ 0.0f, 0.0f, 0.f}, {1, 0, 1, 0}},
9128 {{ 3.0f, 3.0f, 0.f}, {1, 1, 1, 1}},
9129 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MAX, 1, 0}},
9130 {{ 1.0f, 0.0f, 0.f}, {-42, 42, SHRT_MAX, SHRT_MIN}},
9132 const UINT num_vertices30 = ARRAY_SIZE(vertices30);
9133 const UINT num_faces30 = ARRAY_SIZE(vertices30) / VERTS_PER_FACE;
9134 const UINT vertex_size30 = sizeof(*vertices30);
9135 const struct vertex_ptc_float4 exp_vertices30[] =
9137 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9138 {{ 2.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.0f, 1.0f }},
9139 {{ 0.0f, 0.0f, 0.f}, {1.0f, 0.0f, 1.0f, 0.0f}},
9141 {{ 3.0f, 3.0f, 0.f}, {1.0f, 1.0f, 1.0f, 1.0f}},
9142 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MAX, 1.0f, 0.0f}},
9143 {{ 1.0f, 0.0f, 0.f}, {-42.0f, 42.0f, SHRT_MAX, SHRT_MIN}},
9145 const UINT exp_vertex_size30 = sizeof(*exp_vertices30);
9146 /* Test 31. Convert UBYTE4N to FLOAT4. */
9147 const struct vertex_ptc_ubyte4n vertices31[] =
9149 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9150 {{ 2.0f, 3.0f, 0.f}, {1, 1, 1, 1}},
9151 {{ 0.0f, 0.0f, 0.f}, {1, 0, 1, 0}},
9153 {{ 3.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
9154 {{ 3.0f, 0.0f, 0.f}, {10, 20, 30, 40}},
9155 {{ 1.0f, 0.0f, 0.f}, {50, 60, 70, UCHAR_MAX}},
9157 const UINT num_vertices31 = ARRAY_SIZE(vertices31);
9158 const UINT num_faces31 = ARRAY_SIZE(vertices31) / VERTS_PER_FACE;
9159 const UINT vertex_size31 = sizeof(*vertices31);
9160 const struct vertex_ptc_float4 exp_vertices31[] =
9162 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9163 {{ 2.0f, 3.0f, 0.f}, {(FLOAT)1/UCHAR_MAX, (FLOAT)1/UCHAR_MAX, (FLOAT)1/UCHAR_MAX, (FLOAT)1/UCHAR_MAX}},
9164 {{ 0.0f, 0.0f, 0.f}, {(FLOAT)1/UCHAR_MAX, 0.0f, (FLOAT)1/UCHAR_MAX, 0.0f}},
9166 {{ 3.0f, 3.0f, 0.f}, {0.0f, (FLOAT)1/UCHAR_MAX, 0.0f, (FLOAT)1/UCHAR_MAX}},
9167 {{ 3.0f, 0.0f, 0.f}, {(FLOAT)10/UCHAR_MAX, (FLOAT)20/UCHAR_MAX, (FLOAT)30/UCHAR_MAX, (FLOAT)40/UCHAR_MAX}},
9168 {{ 1.0f, 0.0f, 0.f}, {(FLOAT)50/UCHAR_MAX, (FLOAT)60/UCHAR_MAX, (FLOAT)70/UCHAR_MAX, 1.0f}},
9170 const UINT exp_vertex_size31 = sizeof(*exp_vertices31);
9171 /* Test 32. Convert SHORT2N to FLOAT4. */
9172 const struct vertex_ptc_short2 vertices32[] =
9174 {{ 0.0f, 3.0f, 0.f}, {0, 0}},
9175 {{ 2.0f, 3.0f, 0.f}, {0, 1}},
9176 {{ 0.0f, 0.0f, 0.f}, {1, 0}},
9178 {{ 3.0f, 3.0f, 0.f}, {1, 1}},
9179 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN + 1, SHRT_MAX}},
9180 {{ 1.0f, 0.0f, 0.f}, {-42, 42}},
9182 const UINT num_vertices32 = ARRAY_SIZE(vertices32);
9183 const UINT num_faces32 = ARRAY_SIZE(vertices32) / VERTS_PER_FACE;
9184 const UINT vertex_size32 = sizeof(*vertices32);
9185 const struct vertex_ptc_float4 exp_vertices32[] =
9187 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 1.0f}},
9188 {{ 2.0f, 3.0f, 0.f}, {0.0f, 1.0f/SHRT_MAX, 0.0f, 1.0f}},
9189 {{ 0.0f, 0.0f, 0.f}, {1.0f/SHRT_MAX, 0.0f, 0.0f, 1.0f}},
9191 {{ 3.0f, 3.0f, 0.f}, {1.0f/SHRT_MAX, 1.0f/SHRT_MAX, 0.0f, 1.0f}},
9192 {{ 3.0f, 0.0f, 0.f}, {-1.0f, 1.0f, 0.0f, 1.0f}},
9193 {{ 1.0f, 0.0f, 0.f}, {-42.0f/SHRT_MAX, 42.0f/SHRT_MAX, 0.0f, 1.0f}},
9195 const UINT exp_vertex_size32 = sizeof(*exp_vertices32);
9196 /* Test 33. Convert SHORT4N to FLOAT4. */
9197 const struct vertex_ptc_short4 vertices33[] =
9199 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9200 {{ 2.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
9201 {{ 0.0f, 0.0f, 0.f}, {1, 0, 1, 0}},
9203 {{ 3.0f, 3.0f, 0.f}, {1, 1, 1, 1}},
9204 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN + 1, SHRT_MAX, SHRT_MIN + 1, SHRT_MAX}},
9205 {{ 1.0f, 0.0f, 0.f}, {-42, 42, 1, 1}},
9207 const UINT num_vertices33 = ARRAY_SIZE(vertices33);
9208 const UINT num_faces33 = ARRAY_SIZE(vertices33) / VERTS_PER_FACE;
9209 const UINT vertex_size33 = sizeof(*vertices33);
9210 const struct vertex_ptc_float4 exp_vertices33[] =
9212 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9213 {{ 2.0f, 3.0f, 0.f}, {0.0f, 1.0f/SHRT_MAX, 0.0f, 1.0f/SHRT_MAX}},
9214 {{ 0.0f, 0.0f, 0.f}, {1.0f/SHRT_MAX, 0.0f, 1.0f/SHRT_MAX, 0.0f}},
9216 {{ 3.0f, 3.0f, 0.f}, {1.0f/SHRT_MAX, 1.0f/SHRT_MAX, 1.0f/SHRT_MAX, 1.0f/SHRT_MAX}},
9217 {{ 3.0f, 0.0f, 0.f}, {-1.0f, 1.0f, -1.0f, 1.0f}},
9218 {{ 1.0f, 0.0f, 0.f}, {-42.0f/SHRT_MAX, 42.0f/SHRT_MAX, 1.0f/SHRT_MAX, 1.0f/SHRT_MAX}},
9220 const UINT exp_vertex_size33 = sizeof(*exp_vertices33);
9221 /* Test 34. Convert FLOAT16_2 to FLOAT4. */
9222 const struct vertex_ptc_float16_2 vertices34[] =
9224 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
9225 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */
9226 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */
9228 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd}}, /* {0.2f, 0.3f} */
9229 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
9230 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */
9232 const UINT num_vertices34 = ARRAY_SIZE(vertices34);
9233 const UINT num_faces34 = ARRAY_SIZE(vertices34) / VERTS_PER_FACE;
9234 const UINT vertex_size34 = sizeof(*vertices34);
9235 const struct vertex_ptc_float4 exp_vertices34[] =
9237 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f, 0.0f, 1.0f}},
9238 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.700195f, 0.0f, 1.0f}},
9239 {{ 0.0f, 0.0f, 0.f}, {-0.199951f, -0.300049f, 0.0f, 1.0f}},
9241 {{ 3.0f, 3.0f, 0.f}, {0.199951f, 0.300049f, 0.0f, 1.0f}},
9242 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f, 0.0f, 1.0f}},
9243 {{ 1.0f, 0.0f, 0.f}, {0.099976f, 0.199951f, 0.0f, 1.0f}},
9245 const UINT exp_vertex_size34 = sizeof(*exp_vertices34);
9246 /* Test 35. Convert FLOAT16_4 to FLOAT4. */
9247 const struct vertex_ptc_float16_4 vertices35[] =
9249 {{ 0.0f, 3.0f, 0.f}, {0x0000, 0x0000, 0x0000, 0x0000}},
9250 {{ 2.0f, 3.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}},
9251 {{ 0.0f, 0.0f, 0.f}, {0x3c00, 0x0000, 0x3c00, 0x0000}},
9253 {{ 3.0f, 3.0f, 0.f}, {0x0000, 0x3c00, 0x0000, 0x3c00}},
9254 {{ 3.0f, 0.0f, 0.f}, {0x3800, 0x399a, 0xb266, 0xb4cd}},
9255 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266, 0x2e66, 0x3266}},
9257 const UINT num_vertices35 = ARRAY_SIZE(vertices35);
9258 const UINT num_faces35 = ARRAY_SIZE(vertices35) / VERTS_PER_FACE;
9259 const UINT vertex_size35 = sizeof(*vertices35);
9260 const struct vertex_ptc_float4 exp_vertices35[] =
9262 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9263 {{ 2.0f, 3.0f, 0.f}, {1.0f, 1.0f, 1.0f, 1.0f}},
9264 {{ 0.0f, 0.0f, 0.f}, {1.0f, 0.0f, 1.0f, 0.0f}},
9266 {{ 3.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.0f, 1.0f}},
9267 {{ 3.0f, 0.0f, 0.f}, {0.5f, 0.700195f, -0.199951f, -0.300049f}},
9268 {{ 1.0f, 0.0f, 0.f}, {0.099976f, 0.199951f, 0.099976f, 0.199951f}},
9270 const UINT exp_vertex_size35 = sizeof(*exp_vertices35);
9271 /* Test 36. Check that vertex buffer sharing is ok. */
9272 const struct vertex_pn vertices36[] =
9274 {{ 0.0f, 3.0f, 0.f}, up},
9275 {{ 2.0f, 3.0f, 0.f}, up},
9276 {{ 0.0f, 0.0f, 0.f}, up},
9278 const UINT num_vertices36 = ARRAY_SIZE(vertices36);
9279 const UINT num_faces36 = ARRAY_SIZE(vertices36) / VERTS_PER_FACE;
9280 const UINT vertex_size36 = sizeof(*vertices36);
9281 const DWORD clone_options36 = options | D3DXMESH_VB_SHARE;
9282 /* Common mesh data */
9283 ID3DXMesh *mesh = NULL;
9284 ID3DXMesh *mesh_clone = NULL;
9285 struct
9287 const BYTE *vertices;
9288 const DWORD *indices;
9289 const DWORD *attributes;
9290 const UINT num_vertices;
9291 const UINT num_faces;
9292 const UINT vertex_size;
9293 const DWORD create_options;
9294 const DWORD clone_options;
9295 D3DVERTEXELEMENT9 *declaration;
9296 D3DVERTEXELEMENT9 *new_declaration;
9297 const BYTE *exp_vertices;
9298 const UINT exp_vertex_size;
9300 tc[] =
9303 (BYTE*)vertices0,
9304 NULL,
9305 NULL,
9306 num_vertices0,
9307 num_faces0,
9308 vertex_size0,
9309 options,
9310 options,
9311 declaration_pn,
9312 declaration_pn,
9313 (BYTE*)vertices0,
9314 vertex_size0
9317 (BYTE*)vertices0,
9318 NULL,
9319 NULL,
9320 num_vertices0,
9321 num_faces0,
9322 vertex_size0,
9323 options_16bit,
9324 options_16bit,
9325 declaration_pn,
9326 declaration_pn,
9327 (BYTE*)vertices0,
9328 vertex_size0
9331 (BYTE*)vertices0,
9332 NULL,
9333 NULL,
9334 num_vertices0,
9335 num_faces0,
9336 vertex_size0,
9337 options,
9338 options,
9339 declaration_pn,
9340 declaration_pntc,
9341 (BYTE*)exp_vertices2,
9342 exp_vertex_size2
9345 (BYTE*)vertices0,
9346 NULL,
9347 NULL,
9348 num_vertices0,
9349 num_faces0,
9350 vertex_size0,
9351 options,
9352 options,
9353 declaration_pn,
9354 declaration_ptcn,
9355 (BYTE*)exp_vertices3,
9356 exp_vertex_size3
9359 (BYTE*)vertices4,
9360 NULL,
9361 NULL,
9362 num_vertices4,
9363 num_faces4,
9364 vertex_size4,
9365 options,
9366 options,
9367 declaration_ptc,
9368 declaration_ptc_float16_2,
9369 (BYTE*)exp_vertices4,
9370 exp_vertex_size4
9373 (BYTE*)vertices5,
9374 NULL,
9375 NULL,
9376 num_vertices5,
9377 num_faces5,
9378 vertex_size5,
9379 options,
9380 options,
9381 declaration_ptc,
9382 declaration_ptc_float16_4,
9383 (BYTE*)exp_vertices5,
9384 exp_vertex_size5
9387 (BYTE*)vertices6,
9388 NULL,
9389 NULL,
9390 num_vertices6,
9391 num_faces6,
9392 vertex_size6,
9393 options,
9394 options,
9395 declaration_ptc,
9396 declaration_ptc_float1,
9397 (BYTE*)exp_vertices6,
9398 exp_vertex_size6
9401 (BYTE*)vertices7,
9402 NULL,
9403 NULL,
9404 num_vertices7,
9405 num_faces7,
9406 vertex_size7,
9407 options,
9408 options,
9409 declaration_ptc,
9410 declaration_ptc_float3,
9411 (BYTE*)exp_vertices7,
9412 exp_vertex_size7
9415 (BYTE*)vertices8,
9416 NULL,
9417 NULL,
9418 num_vertices8,
9419 num_faces8,
9420 vertex_size8,
9421 options,
9422 options,
9423 declaration_ptc,
9424 declaration_ptc_float4,
9425 (BYTE*)exp_vertices8,
9426 exp_vertex_size8
9429 (BYTE*)vertices9,
9430 NULL,
9431 NULL,
9432 num_vertices9,
9433 num_faces9,
9434 vertex_size9,
9435 options,
9436 options,
9437 declaration_ptc,
9438 declaration_ptc_d3dcolor,
9439 (BYTE*)exp_vertices9,
9440 exp_vertex_size9
9443 (BYTE*)vertices10,
9444 NULL,
9445 NULL,
9446 num_vertices10,
9447 num_faces10,
9448 vertex_size10,
9449 options,
9450 options,
9451 declaration_ptc,
9452 declaration_ptc_ubyte4,
9453 (BYTE*)exp_vertices10,
9454 exp_vertex_size10
9457 (BYTE*)vertices11,
9458 NULL,
9459 NULL,
9460 num_vertices11,
9461 num_faces11,
9462 vertex_size11,
9463 options,
9464 options,
9465 declaration_ptc,
9466 declaration_ptc_short2,
9467 (BYTE*)exp_vertices11,
9468 exp_vertex_size11
9471 (BYTE*)vertices12,
9472 NULL,
9473 NULL,
9474 num_vertices12,
9475 num_faces12,
9476 vertex_size12,
9477 options,
9478 options,
9479 declaration_ptc,
9480 declaration_ptc_short4,
9481 (BYTE*)exp_vertices12,
9482 exp_vertex_size12
9485 (BYTE*)vertices13,
9486 NULL,
9487 NULL,
9488 num_vertices13,
9489 num_faces13,
9490 vertex_size13,
9491 options,
9492 options,
9493 declaration_ptc,
9494 declaration_ptc_ubyte4n,
9495 (BYTE*)exp_vertices13,
9496 exp_vertex_size13
9499 (BYTE*)vertices14,
9500 NULL,
9501 NULL,
9502 num_vertices14,
9503 num_faces14,
9504 vertex_size14,
9505 options,
9506 options,
9507 declaration_ptc,
9508 declaration_ptc_short2n,
9509 (BYTE*)exp_vertices14,
9510 exp_vertex_size14
9513 (BYTE*)vertices15,
9514 NULL,
9515 NULL,
9516 num_vertices15,
9517 num_faces15,
9518 vertex_size15,
9519 options,
9520 options,
9521 declaration_ptc,
9522 declaration_ptc_short4n,
9523 (BYTE*)exp_vertices15,
9524 exp_vertex_size15
9527 (BYTE*)vertices16,
9528 NULL,
9529 NULL,
9530 num_vertices16,
9531 num_faces16,
9532 vertex_size16,
9533 options,
9534 options,
9535 declaration_ptc,
9536 declaration_ptc_ushort2n,
9537 (BYTE*)exp_vertices16,
9538 exp_vertex_size16
9541 (BYTE*)vertices17,
9542 NULL,
9543 NULL,
9544 num_vertices17,
9545 num_faces17,
9546 vertex_size17,
9547 options,
9548 options,
9549 declaration_ptc,
9550 declaration_ptc_ushort4n,
9551 (BYTE*)exp_vertices17,
9552 exp_vertex_size17
9555 (BYTE*)vertices18,
9556 NULL,
9557 NULL,
9558 num_vertices18,
9559 num_faces18,
9560 vertex_size18,
9561 options,
9562 options,
9563 declaration_ptc,
9564 declaration_ptc_float16_2_partialu,
9565 (BYTE*)exp_vertices18,
9566 exp_vertex_size18
9569 (BYTE*)vertices19,
9570 NULL,
9571 NULL,
9572 num_vertices19,
9573 num_faces19,
9574 vertex_size19,
9575 options,
9576 options,
9577 declaration_pntc,
9578 declaration_pntc1,
9579 (BYTE*)exp_vertices19,
9580 exp_vertex_size19
9583 (BYTE*)vertices20,
9584 NULL,
9585 NULL,
9586 num_vertices20,
9587 num_faces20,
9588 vertex_size20,
9589 options,
9590 options,
9591 declaration_pntc1,
9592 declaration_pntc,
9593 (BYTE*)exp_vertices20,
9594 exp_vertex_size20
9597 (BYTE*)vertices21,
9598 NULL,
9599 NULL,
9600 num_vertices21,
9601 num_faces21,
9602 vertex_size21,
9603 options,
9604 options,
9605 declaration_ptc_float1,
9606 declaration_ptc,
9607 (BYTE*)exp_vertices21,
9608 exp_vertex_size21
9611 (BYTE*)vertices22,
9612 NULL,
9613 NULL,
9614 num_vertices22,
9615 num_faces22,
9616 vertex_size22,
9617 options,
9618 options,
9619 declaration_ptc_float1,
9620 declaration_ptc_float3,
9621 (BYTE*)exp_vertices22,
9622 exp_vertex_size22
9625 (BYTE*)vertices23,
9626 NULL,
9627 NULL,
9628 num_vertices23,
9629 num_faces23,
9630 vertex_size23,
9631 options,
9632 options,
9633 declaration_ptc_float1,
9634 declaration_ptc_float4,
9635 (BYTE*)exp_vertices23,
9636 exp_vertex_size23
9639 (BYTE*)vertices24,
9640 NULL,
9641 NULL,
9642 num_vertices24,
9643 num_faces24,
9644 vertex_size24,
9645 options,
9646 options,
9647 declaration_ptc_float1,
9648 declaration_ptc_d3dcolor,
9649 (BYTE*)exp_vertices24,
9650 exp_vertex_size24
9653 (BYTE*)vertices25,
9654 NULL,
9655 NULL,
9656 num_vertices25,
9657 num_faces25,
9658 vertex_size25,
9659 options,
9660 options,
9661 declaration_ptc_float1,
9662 declaration_ptc_ubyte4,
9663 (BYTE*)exp_vertices25,
9664 exp_vertex_size25
9667 (BYTE*)vertices26,
9668 NULL,
9669 NULL,
9670 num_vertices26,
9671 num_faces26,
9672 vertex_size26,
9673 options,
9674 options,
9675 declaration_ptc_float4,
9676 declaration_ptc_d3dcolor,
9677 (BYTE*)exp_vertices26,
9678 exp_vertex_size26
9681 (BYTE*)vertices27,
9682 NULL,
9683 NULL,
9684 num_vertices27,
9685 num_faces27,
9686 vertex_size27,
9687 options,
9688 options,
9689 declaration_ptc_d3dcolor,
9690 declaration_ptc_float4,
9691 (BYTE*)exp_vertices27,
9692 exp_vertex_size27
9695 (BYTE*)vertices28,
9696 NULL,
9697 NULL,
9698 num_vertices28,
9699 num_faces28,
9700 vertex_size28,
9701 options,
9702 options,
9703 declaration_ptc_ubyte4,
9704 declaration_ptc_float4,
9705 (BYTE*)exp_vertices28,
9706 exp_vertex_size28
9709 (BYTE*)vertices29,
9710 NULL,
9711 NULL,
9712 num_vertices29,
9713 num_faces29,
9714 vertex_size29,
9715 options,
9716 options,
9717 declaration_ptc_short2,
9718 declaration_ptc_float4,
9719 (BYTE*)exp_vertices29,
9720 exp_vertex_size29
9723 (BYTE*)vertices30,
9724 NULL,
9725 NULL,
9726 num_vertices30,
9727 num_faces30,
9728 vertex_size30,
9729 options,
9730 options,
9731 declaration_ptc_short4,
9732 declaration_ptc_float4,
9733 (BYTE*)exp_vertices30,
9734 exp_vertex_size30
9737 (BYTE*)vertices31,
9738 NULL,
9739 NULL,
9740 num_vertices31,
9741 num_faces31,
9742 vertex_size31,
9743 options,
9744 options,
9745 declaration_ptc_ubyte4n,
9746 declaration_ptc_float4,
9747 (BYTE*)exp_vertices31,
9748 exp_vertex_size31
9751 (BYTE*)vertices32,
9752 NULL,
9753 NULL,
9754 num_vertices32,
9755 num_faces32,
9756 vertex_size32,
9757 options,
9758 options,
9759 declaration_ptc_short2n,
9760 declaration_ptc_float4,
9761 (BYTE*)exp_vertices32,
9762 exp_vertex_size32
9765 (BYTE*)vertices33,
9766 NULL,
9767 NULL,
9768 num_vertices33,
9769 num_faces33,
9770 vertex_size33,
9771 options,
9772 options,
9773 declaration_ptc_short4n,
9774 declaration_ptc_float4,
9775 (BYTE*)exp_vertices33,
9776 exp_vertex_size33
9779 (BYTE*)vertices34,
9780 NULL,
9781 NULL,
9782 num_vertices34,
9783 num_faces34,
9784 vertex_size34,
9785 options,
9786 options,
9787 declaration_ptc_float16_2,
9788 declaration_ptc_float4,
9789 (BYTE*)exp_vertices34,
9790 exp_vertex_size34
9793 (BYTE*)vertices35,
9794 NULL,
9795 NULL,
9796 num_vertices35,
9797 num_faces35,
9798 vertex_size35,
9799 options,
9800 options,
9801 declaration_ptc_float16_4,
9802 declaration_ptc_float4,
9803 (BYTE*)exp_vertices35,
9804 exp_vertex_size35
9807 (BYTE*)vertices36,
9808 NULL,
9809 NULL,
9810 num_vertices36,
9811 num_faces36,
9812 vertex_size36,
9813 options,
9814 clone_options36,
9815 declaration_pn,
9816 declaration_pn,
9817 (BYTE*)vertices36,
9818 vertex_size36
9822 test_context = new_test_context();
9823 if (!test_context)
9825 skip("Couldn't create test context\n");
9826 goto cleanup;
9829 for (i = 0; i < ARRAY_SIZE(tc); i++)
9831 UINT j;
9832 D3DVERTEXELEMENT9 new_declaration[MAX_FVF_DECL_SIZE];
9833 UINT exp_new_decl_length, new_decl_length;
9834 UINT exp_new_decl_size, new_decl_size;
9836 hr = init_test_mesh(tc[i].num_faces, tc[i].num_vertices,
9837 tc[i].create_options,
9838 tc[i].declaration,
9839 test_context->device, &mesh,
9840 tc[i].vertices, tc[i].vertex_size,
9841 tc[i].indices, tc[i].attributes);
9842 if (FAILED(hr))
9844 skip("Couldn't initialize test mesh %d. Got %x expected D3D_OK\n", i, hr);
9845 goto cleanup;
9848 hr = mesh->lpVtbl->CloneMesh(mesh, tc[i].clone_options, tc[i].new_declaration,
9849 test_context->device, &mesh_clone);
9850 ok(hr == D3D_OK, "CloneMesh test case %d failed. Got %x\n, expected D3D_OK\n", i, hr);
9852 hr = mesh_clone->lpVtbl->GetDeclaration(mesh_clone, new_declaration);
9853 ok(hr == D3D_OK, "GetDeclaration test case %d failed. Got %x\n, expected D3D_OK\n", i, hr);
9854 /* Check declaration elements */
9855 for (j = 0; tc[i].new_declaration[j].Stream != 0xFF; j++)
9857 ok(memcmp(&tc[i].new_declaration[j], &new_declaration[j], sizeof(*new_declaration)) == 0,
9858 "Test case %d failed. Declaration element %d did not match.\n", i, j);
9861 /* Check declaration length */
9862 exp_new_decl_length = D3DXGetDeclLength(tc[i].new_declaration);
9863 new_decl_length = D3DXGetDeclLength(new_declaration);
9864 ok(new_decl_length == exp_new_decl_length,
9865 "Test case %d failed. Got new declaration length %d, expected %d\n",
9866 i, new_decl_length, exp_new_decl_length);
9868 /* Check declaration size */
9869 exp_new_decl_size = D3DXGetDeclVertexSize(tc[i].new_declaration, 0);
9870 new_decl_size = D3DXGetDeclVertexSize(new_declaration, 0);
9871 ok(new_decl_size == exp_new_decl_size,
9872 "Test case %d failed. Got new declaration size %d, expected %d\n",
9873 i, new_decl_size, exp_new_decl_size);
9875 /* Check vertex data in cloned mesh */
9876 hr = mesh_clone->lpVtbl->LockVertexBuffer(mesh_clone, 0, (void**)&vertices);
9877 if (FAILED(hr))
9879 skip("Couldn't lock cloned vertex buffer.\n");
9880 goto cleanup;
9882 for (j = 0; j < tc[i].num_vertices; j++)
9884 UINT index = tc[i].exp_vertex_size * j;
9885 check_vertex_components(__LINE__, i, j, &vertices[index], &tc[i].exp_vertices[index], tc[i].new_declaration);
9887 hr = mesh_clone->lpVtbl->UnlockVertexBuffer(mesh_clone);
9888 if (FAILED(hr))
9890 skip("Couldn't unlock vertex buffer.\n");
9891 goto cleanup;
9893 vertices = NULL;
9894 mesh->lpVtbl->Release(mesh);
9895 mesh = NULL;
9896 mesh_clone->lpVtbl->Release(mesh_clone);
9897 mesh_clone = NULL;
9900 /* The following test shows that it is not possible to share a vertex buffer
9901 * with D3DXMESH_VB_SHARE and change the vertex declaration at the same
9902 * time. It reuses the test data from test 2.
9904 hr = init_test_mesh(tc[2].num_faces, tc[2].num_vertices,
9905 tc[2].create_options,
9906 tc[2].declaration,
9907 test_context->device, &mesh,
9908 tc[2].vertices, tc[2].vertex_size,
9909 tc[2].indices, tc[2].attributes);
9910 if (FAILED(hr))
9912 skip("Couldn't initialize test mesh for D3DXMESH_VB_SHARE case."
9913 " Got %x expected D3D_OK\n", hr);
9914 goto cleanup;
9917 hr = mesh->lpVtbl->CloneMesh(mesh, tc[2].create_options | D3DXMESH_VB_SHARE,
9918 tc[2].new_declaration, test_context->device,
9919 &mesh_clone);
9920 ok(hr == D3DERR_INVALIDCALL, "CloneMesh D3DXMESH_VB_SHARE with new"
9921 " declaration. Got %x, expected D3DERR_INVALIDCALL\n",
9922 hr);
9923 mesh->lpVtbl->Release(mesh);
9924 mesh = NULL;
9925 mesh_clone = NULL;
9927 cleanup:
9928 if (vertices) mesh->lpVtbl->UnlockVertexBuffer(mesh);
9929 if (mesh) mesh->lpVtbl->Release(mesh);
9930 if (mesh_clone) mesh_clone->lpVtbl->Release(mesh_clone);
9931 free_test_context(test_context);
9934 static void test_valid_mesh(void)
9936 HRESULT hr;
9937 struct test_context *test_context = NULL;
9938 UINT i;
9939 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
9940 const D3DVERTEXELEMENT9 declaration[] =
9942 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
9943 D3DDECL_END()
9945 const unsigned int VERTS_PER_FACE = 3;
9946 /* mesh0 (one face)
9948 * 0--1
9949 * | /
9950 * |/
9953 const D3DXVECTOR3 vertices0[] =
9955 { 0.0f, 3.0f, 0.f},
9956 { 2.0f, 3.0f, 0.f},
9957 { 0.0f, 0.0f, 0.f},
9959 const DWORD indices0[] = {0, 1, 2};
9960 const unsigned int num_vertices0 = ARRAY_SIZE(vertices0);
9961 const unsigned int num_faces0 = ARRAY_SIZE(indices0) / VERTS_PER_FACE;
9962 const DWORD adjacency0[] = {-1, -1, -1};
9963 const HRESULT exp_hr0 = D3D_OK;
9964 /* mesh1 (Simple bow-tie)
9966 * 0--1 1--3
9967 * | / \ |
9968 * |/ \|
9969 * 2 4
9971 const D3DXVECTOR3 vertices1[] =
9973 { 0.0f, 3.0f, 0.f},
9974 { 2.0f, 3.0f, 0.f},
9975 { 0.0f, 0.0f, 0.f},
9977 { 4.0f, 3.0f, 0.f},
9978 { 4.0f, 0.0f, 0.f},
9980 const DWORD indices1[] = {0, 1, 2, 1, 3, 4};
9981 const unsigned int num_vertices1 = ARRAY_SIZE(vertices1);
9982 const unsigned int num_faces1 = ARRAY_SIZE(indices1) / VERTS_PER_FACE;
9983 const DWORD adjacency1[] = {-1, -1, -1, -1, -1, -1};
9984 const HRESULT exp_hr1 = D3DXERR_INVALIDMESH;
9985 /* Common mesh data */
9986 ID3DXMesh *mesh = NULL;
9987 UINT vertex_size = sizeof(D3DXVECTOR3);
9988 ID3DXBuffer *errors_and_warnings = NULL;
9989 struct
9991 const D3DXVECTOR3 *vertices;
9992 const DWORD *indices;
9993 const UINT num_vertices;
9994 const UINT num_faces;
9995 const DWORD *adjacency;
9996 const HRESULT exp_hr;
9998 tc[] =
10001 vertices0,
10002 indices0,
10003 num_vertices0,
10004 num_faces0,
10005 adjacency0,
10006 exp_hr0,
10009 vertices1,
10010 indices1,
10011 num_vertices1,
10012 num_faces1,
10013 adjacency1,
10014 exp_hr1,
10018 test_context = new_test_context();
10019 if (!test_context)
10021 skip("Couldn't create test context\n");
10022 goto cleanup;
10025 for (i = 0; i < ARRAY_SIZE(tc); i++)
10027 hr = init_test_mesh(tc[i].num_faces, tc[i].num_vertices,
10028 options, declaration,
10029 test_context->device, &mesh,
10030 tc[i].vertices, vertex_size,
10031 tc[i].indices, NULL);
10032 if (FAILED(hr))
10034 skip("Couldn't initialize test mesh %d. Got %x expected D3D_OK\n", i, hr);
10035 goto cleanup;
10038 hr = D3DXValidMesh(mesh, tc[i].adjacency, &errors_and_warnings);
10039 todo_wine ok(hr == tc[i].exp_hr, "D3DXValidMesh test case %d failed. "
10040 "Got %x\n, expected %x\n", i, hr, tc[i].exp_hr);
10042 /* Note errors_and_warnings is deliberately not checked because that
10043 * would require copying wast amounts of the text output. */
10044 if (errors_and_warnings)
10046 ID3DXBuffer_Release(errors_and_warnings);
10047 errors_and_warnings = NULL;
10049 mesh->lpVtbl->Release(mesh);
10050 mesh = NULL;
10053 cleanup:
10054 if (mesh) mesh->lpVtbl->Release(mesh);
10055 free_test_context(test_context);
10058 static void test_optimize_faces(void)
10060 HRESULT hr;
10061 UINT i;
10062 DWORD smallest_face_remap;
10063 /* mesh0
10065 * 0--1
10066 * | /
10067 * |/
10070 const DWORD indices0[] = {0, 1, 2};
10071 const UINT num_faces0 = 1;
10072 const UINT num_vertices0 = 3;
10073 const DWORD exp_face_remap0[] = {0};
10074 /* mesh1
10076 * 0--1 3
10077 * | / /|
10078 * |/ / |
10079 * 2 5--4
10081 const DWORD indices1[] = {0, 1, 2, 3, 4, 5};
10082 const UINT num_faces1 = 2;
10083 const UINT num_vertices1 = 6;
10084 const DWORD exp_face_remap1[] = {1, 0};
10085 /* mesh2
10087 * 0--1
10088 * | /|
10089 * |/ |
10090 * 2--3
10092 const DWORD indices2[] = {0, 1, 2, 1, 3, 2};
10093 const UINT num_faces2 = 2;
10094 const UINT num_vertices2 = 4;
10095 const DWORD exp_face_remap2[] = {1, 0};
10096 /* mesh3
10098 * 0--1
10099 * | /|
10100 * |/ |
10101 * 2--3
10102 * | /|
10103 * |/ |
10104 * 4--5
10106 const DWORD indices3[] = {0, 1, 2, 1, 3, 2, 2, 3, 4, 3, 4, 5};
10107 const UINT num_faces3 = 4;
10108 const UINT num_vertices3 = 6;
10109 const DWORD exp_face_remap3[] = {3, 2, 1, 0};
10110 /* mesh4
10112 * 0--1
10113 * | /|
10114 * |/ |
10115 * 2--3
10116 * | /|
10117 * |/ |
10118 * 4--5
10120 const WORD indices4[] = {0, 1, 2, 1, 3, 2, 2, 3, 4, 3, 4, 5};
10121 const UINT num_faces4 = 4;
10122 const UINT num_vertices4 = 6;
10123 const DWORD exp_face_remap4[] = {3, 2, 1, 0};
10124 /* Test cases are stored in the tc array */
10125 struct
10127 const VOID *indices;
10128 const UINT num_faces;
10129 const UINT num_vertices;
10130 const BOOL indices_are_32bit;
10131 const DWORD *exp_face_remap;
10133 tc[] =
10136 indices0,
10137 num_faces0,
10138 num_vertices0,
10139 TRUE,
10140 exp_face_remap0
10143 indices1,
10144 num_faces1,
10145 num_vertices1,
10146 TRUE,
10147 exp_face_remap1
10150 indices2,
10151 num_faces2,
10152 num_vertices2,
10153 TRUE,
10154 exp_face_remap2
10157 indices3,
10158 num_faces3,
10159 num_vertices3,
10160 TRUE,
10161 exp_face_remap3
10164 indices4,
10165 num_faces4,
10166 num_vertices4,
10167 FALSE,
10168 exp_face_remap4
10172 /* Go through all test cases */
10173 for (i = 0; i < ARRAY_SIZE(tc); i++)
10175 DWORD j;
10176 DWORD *face_remap;
10177 face_remap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
10178 tc[i].num_faces*sizeof(*face_remap));
10180 hr = D3DXOptimizeFaces(tc[i].indices, tc[i].num_faces,
10181 tc[i].num_vertices, tc[i].indices_are_32bit,
10182 face_remap);
10183 ok(hr == D3D_OK, "D3DXOptimizeFaces test case %d failed. "
10184 "Got %x\n, expected D3D_OK\n", i, hr);
10186 /* Compare face remap with expected face remap */
10187 for (j = 0; j < tc[i].num_faces; j++)
10189 ok(tc[i].exp_face_remap[j] == face_remap[j],
10190 "Test case %d: Got face %d at %d, expected %d\n", i,
10191 face_remap[j], j, tc[i].exp_face_remap[j]);
10194 HeapFree(GetProcessHeap(), 0, face_remap);
10197 /* face_remap must not be NULL */
10198 hr = D3DXOptimizeFaces(tc[0].indices, tc[0].num_faces,
10199 tc[0].num_vertices, tc[0].indices_are_32bit,
10200 NULL);
10201 ok(hr == D3DERR_INVALIDCALL, "D3DXOptimizeFaces passed NULL face_remap "
10202 "pointer. Got %x\n, expected D3DERR_INVALIDCALL\n", hr);
10204 /* Number of faces must be smaller than 2^15 */
10205 hr = D3DXOptimizeFaces(tc[0].indices, 2 << 15,
10206 tc[0].num_vertices, FALSE,
10207 &smallest_face_remap);
10208 ok(hr == D3DERR_INVALIDCALL, "D3DXOptimizeFaces should not accept 2^15 "
10209 "faces when using 16-bit indices. Got %x\n, expected D3DERR_INVALIDCALL\n", hr);
10212 START_TEST(mesh)
10214 D3DXBoundProbeTest();
10215 D3DXComputeBoundingBoxTest();
10216 D3DXComputeBoundingSphereTest();
10217 D3DXGetFVFVertexSizeTest();
10218 D3DXIntersectTriTest();
10219 D3DXCreateMeshTest();
10220 D3DXCreateMeshFVFTest();
10221 D3DXLoadMeshTest();
10222 D3DXCreateBoxTest();
10223 D3DXCreateSphereTest();
10224 D3DXCreateCylinderTest();
10225 D3DXCreateTextTest();
10226 test_get_decl_length();
10227 test_get_decl_vertex_size();
10228 test_fvf_decl_conversion();
10229 D3DXGenerateAdjacencyTest();
10230 test_update_semantics();
10231 test_create_skin_info();
10232 test_convert_adjacency_to_point_reps();
10233 test_convert_point_reps_to_adjacency();
10234 test_weld_vertices();
10235 test_clone_mesh();
10236 test_valid_mesh();
10237 test_optimize_faces();