ws2_32: Also check the FQDN when injecting the local IP.
[wine.git] / dlls / d3dx9_36 / tests / mesh.c
blob95dd06e466298520b00254ad2135e759d7dcfffd
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 static BOOL compare_vec4(D3DXVECTOR4 u, D3DXVECTOR4 v)
70 return compare(u.x, v.x) && compare(u.y, v.y) && compare(u.z, v.z) && compare(u.w, v.w);
73 #define check_floats(got, exp, dim) check_floats_(__LINE__, "", got, exp, dim)
74 static void check_floats_(int line, const char *prefix, const float *got, const float *exp, int dim)
76 int i;
77 char exp_buffer[256] = "";
78 char got_buffer[256] = "";
79 char *exp_buffer_ptr = exp_buffer;
80 char *got_buffer_ptr = got_buffer;
81 BOOL equal = TRUE;
83 for (i = 0; i < dim; i++) {
84 if (i) {
85 exp_buffer_ptr += sprintf(exp_buffer_ptr, ", ");
86 got_buffer_ptr += sprintf(got_buffer_ptr, ", ");
88 equal = equal && compare(*exp, *got);
89 exp_buffer_ptr += sprintf(exp_buffer_ptr, "%g", *exp);
90 got_buffer_ptr += sprintf(got_buffer_ptr, "%g", *got);
91 exp++, got++;
93 ok_(__FILE__,line)(equal, "%sExpected (%s), got (%s)", prefix, exp_buffer, got_buffer);
96 struct vertex
98 D3DXVECTOR3 position;
99 D3DXVECTOR3 normal;
102 typedef WORD face[3];
104 static BOOL compare_face(face a, face b)
106 return (a[0]==b[0] && a[1] == b[1] && a[2] == b[2]);
109 struct test_context
111 HWND hwnd;
112 IDirect3D9 *d3d;
113 IDirect3DDevice9 *device;
116 /* Initializes a test context struct. Use it to initialize DirectX.
118 * Returns NULL if an error occurred.
120 static struct test_context *new_test_context(void)
122 HRESULT hr;
123 HWND hwnd = NULL;
124 IDirect3D9 *d3d = NULL;
125 IDirect3DDevice9 *device = NULL;
126 D3DPRESENT_PARAMETERS d3dpp = {0};
127 struct test_context *test_context;
129 if (!(hwnd = CreateWindowA("static", "d3dx9_test", WS_OVERLAPPEDWINDOW, 0, 0,
130 640, 480, NULL, NULL, NULL, NULL)))
132 skip("Couldn't create application window\n");
133 goto error;
136 d3d = Direct3DCreate9(D3D_SDK_VERSION);
137 if (!d3d)
139 skip("Couldn't create IDirect3D9 object\n");
140 goto error;
143 memset(&d3dpp, 0, sizeof(d3dpp));
144 d3dpp.Windowed = TRUE;
145 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
146 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
147 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device);
148 if (FAILED(hr))
150 skip("Couldn't create IDirect3DDevice9 object %#x\n", hr);
151 goto error;
154 test_context = HeapAlloc(GetProcessHeap(), 0, sizeof(*test_context));
155 if (!test_context)
157 skip("Couldn't allocate memory for test_context\n");
158 goto error;
160 test_context->hwnd = hwnd;
161 test_context->d3d = d3d;
162 test_context->device = device;
164 return test_context;
166 error:
167 if (device)
168 IDirect3DDevice9_Release(device);
170 if (d3d)
171 IDirect3D9_Release(d3d);
173 if (hwnd)
174 DestroyWindow(hwnd);
176 return NULL;
179 static void free_test_context(struct test_context *test_context)
181 if (!test_context)
182 return;
184 if (test_context->device)
185 IDirect3DDevice9_Release(test_context->device);
187 if (test_context->d3d)
188 IDirect3D9_Release(test_context->d3d);
190 if (test_context->hwnd)
191 DestroyWindow(test_context->hwnd);
193 HeapFree(GetProcessHeap(), 0, test_context);
196 struct mesh
198 DWORD number_of_vertices;
199 struct vertex *vertices;
201 DWORD number_of_faces;
202 face *faces;
204 DWORD fvf;
205 UINT vertex_size;
208 static void free_mesh(struct mesh *mesh)
210 HeapFree(GetProcessHeap(), 0, mesh->faces);
211 HeapFree(GetProcessHeap(), 0, mesh->vertices);
214 static BOOL new_mesh(struct mesh *mesh, DWORD number_of_vertices, DWORD number_of_faces)
216 mesh->vertices = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, number_of_vertices * sizeof(*mesh->vertices));
217 if (!mesh->vertices)
219 return FALSE;
221 mesh->number_of_vertices = number_of_vertices;
223 mesh->faces = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, number_of_faces * sizeof(*mesh->faces));
224 if (!mesh->faces)
226 HeapFree(GetProcessHeap(), 0, mesh->vertices);
227 return FALSE;
229 mesh->number_of_faces = number_of_faces;
231 return TRUE;
234 static void compare_mesh(const char *name, ID3DXMesh *d3dxmesh, struct mesh *mesh)
236 HRESULT hr;
237 DWORD number_of_vertices, number_of_faces;
238 IDirect3DVertexBuffer9 *vertex_buffer;
239 IDirect3DIndexBuffer9 *index_buffer;
240 D3DVERTEXBUFFER_DESC vertex_buffer_description;
241 D3DINDEXBUFFER_DESC index_buffer_description;
242 struct vertex *vertices;
243 face *faces;
244 int expected, i;
246 number_of_vertices = d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh);
247 ok(number_of_vertices == mesh->number_of_vertices, "Test %s, result %u, expected %d\n",
248 name, number_of_vertices, mesh->number_of_vertices);
250 number_of_faces = d3dxmesh->lpVtbl->GetNumFaces(d3dxmesh);
251 ok(number_of_faces == mesh->number_of_faces, "Test %s, result %u, expected %d\n",
252 name, number_of_faces, mesh->number_of_faces);
254 /* vertex buffer */
255 hr = d3dxmesh->lpVtbl->GetVertexBuffer(d3dxmesh, &vertex_buffer);
256 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
258 if (hr != D3D_OK)
260 skip("Couldn't get vertex buffer\n");
262 else
264 hr = IDirect3DVertexBuffer9_GetDesc(vertex_buffer, &vertex_buffer_description);
265 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
267 if (hr != D3D_OK)
269 skip("Couldn't get vertex buffer description\n");
271 else
273 ok(vertex_buffer_description.Format == D3DFMT_VERTEXDATA, "Test %s, result %x, expected %x (D3DFMT_VERTEXDATA)\n",
274 name, vertex_buffer_description.Format, D3DFMT_VERTEXDATA);
275 ok(vertex_buffer_description.Type == D3DRTYPE_VERTEXBUFFER, "Test %s, result %x, expected %x (D3DRTYPE_VERTEXBUFFER)\n",
276 name, vertex_buffer_description.Type, D3DRTYPE_VERTEXBUFFER);
277 ok(vertex_buffer_description.Usage == 0, "Test %s, result %x, expected %x\n", name, vertex_buffer_description.Usage, 0);
278 ok(vertex_buffer_description.Pool == D3DPOOL_MANAGED, "Test %s, result %x, expected %x (D3DPOOL_MANAGED)\n",
279 name, vertex_buffer_description.Pool, D3DPOOL_MANAGED);
280 ok(vertex_buffer_description.FVF == mesh->fvf, "Test %s, result %x, expected %x\n",
281 name, vertex_buffer_description.FVF, mesh->fvf);
282 if (mesh->fvf == 0)
284 expected = number_of_vertices * mesh->vertex_size;
286 else
288 expected = number_of_vertices * D3DXGetFVFVertexSize(mesh->fvf);
290 ok(vertex_buffer_description.Size == expected, "Test %s, result %x, expected %x\n",
291 name, vertex_buffer_description.Size, expected);
294 /* specify offset and size to avoid potential overruns */
295 hr = IDirect3DVertexBuffer9_Lock(vertex_buffer, 0, number_of_vertices * sizeof(D3DXVECTOR3) * 2,
296 (void **)&vertices, D3DLOCK_DISCARD);
297 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
299 if (hr != D3D_OK)
301 skip("Couldn't lock vertex buffer\n");
303 else
305 for (i = 0; i < number_of_vertices; i++)
307 ok(compare_vec3(vertices[i].position, mesh->vertices[i].position),
308 "Test %s, vertex position %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i,
309 vertices[i].position.x, vertices[i].position.y, vertices[i].position.z,
310 mesh->vertices[i].position.x, mesh->vertices[i].position.y, mesh->vertices[i].position.z);
311 ok(compare_vec3(vertices[i].normal, mesh->vertices[i].normal),
312 "Test %s, vertex normal %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i,
313 vertices[i].normal.x, vertices[i].normal.y, vertices[i].normal.z,
314 mesh->vertices[i].normal.x, mesh->vertices[i].normal.y, mesh->vertices[i].normal.z);
317 IDirect3DVertexBuffer9_Unlock(vertex_buffer);
320 IDirect3DVertexBuffer9_Release(vertex_buffer);
323 /* index buffer */
324 hr = d3dxmesh->lpVtbl->GetIndexBuffer(d3dxmesh, &index_buffer);
325 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
327 if (!index_buffer)
329 skip("Couldn't get index buffer\n");
331 else
333 hr = IDirect3DIndexBuffer9_GetDesc(index_buffer, &index_buffer_description);
334 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
336 if (hr != D3D_OK)
338 skip("Couldn't get index buffer description\n");
340 else
342 ok(index_buffer_description.Format == D3DFMT_INDEX16, "Test %s, result %x, expected %x (D3DFMT_INDEX16)\n",
343 name, index_buffer_description.Format, D3DFMT_INDEX16);
344 ok(index_buffer_description.Type == D3DRTYPE_INDEXBUFFER, "Test %s, result %x, expected %x (D3DRTYPE_INDEXBUFFER)\n",
345 name, index_buffer_description.Type, D3DRTYPE_INDEXBUFFER);
346 ok(index_buffer_description.Usage == 0, "Test %s, result %#x, expected %#x.\n",
347 name, index_buffer_description.Usage, 0);
348 ok(index_buffer_description.Pool == D3DPOOL_MANAGED, "Test %s, result %x, expected %x (D3DPOOL_MANAGED)\n",
349 name, index_buffer_description.Pool, D3DPOOL_MANAGED);
350 expected = number_of_faces * sizeof(WORD) * 3;
351 ok(index_buffer_description.Size == expected, "Test %s, result %x, expected %x\n",
352 name, index_buffer_description.Size, expected);
355 /* specify offset and size to avoid potential overruns */
356 hr = IDirect3DIndexBuffer9_Lock(index_buffer, 0, number_of_faces * sizeof(WORD) * 3,
357 (void **)&faces, D3DLOCK_DISCARD);
358 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
360 if (hr != D3D_OK)
362 skip("Couldn't lock index buffer\n");
364 else
366 for (i = 0; i < number_of_faces; i++)
368 ok(compare_face(faces[i], mesh->faces[i]),
369 "Test %s, face %d, result (%u, %u, %u), expected (%u, %u, %u)\n", name, i,
370 faces[i][0], faces[i][1], faces[i][2],
371 mesh->faces[i][0], mesh->faces[i][1], mesh->faces[i][2]);
374 IDirect3DIndexBuffer9_Unlock(index_buffer);
377 IDirect3DIndexBuffer9_Release(index_buffer);
381 static void D3DXBoundProbeTest(void)
383 BOOL result;
384 D3DXVECTOR3 bottom_point, center, top_point, raydirection, rayposition;
385 FLOAT radius;
387 /*____________Test the Box case___________________________*/
388 bottom_point.x = -3.0f; bottom_point.y = -2.0f; bottom_point.z = -1.0f;
389 top_point.x = 7.0f; top_point.y = 8.0f; top_point.z = 9.0f;
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 == TRUE, "expected TRUE, received FALSE\n");
396 raydirection.x = 4.0f; raydirection.y = 5.0f; raydirection.z = 6.0f;
397 rayposition.x = 5.0f; rayposition.y = 5.0f; rayposition.z = 11.0f;
398 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection);
399 ok(result == FALSE, "expected FALSE, received TRUE\n");
401 rayposition.x = -4.0f; rayposition.y = 1.0f; rayposition.z = -2.0f;
402 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection);
403 ok(result == TRUE, "expected TRUE, received FALSE\n");
405 bottom_point.x = 1.0f; bottom_point.y = 0.0f; bottom_point.z = 0.0f;
406 top_point.x = 1.0f; top_point.y = 0.0f; top_point.z = 0.0f;
407 rayposition.x = 0.0f; rayposition.y = 1.0f; rayposition.z = 0.0f;
408 raydirection.x = 0.0f; raydirection.y = 3.0f; raydirection.z = 0.0f;
409 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection);
410 ok(result == FALSE, "expected FALSE, received TRUE\n");
412 bottom_point.x = 1.0f; bottom_point.y = 2.0f; bottom_point.z = 3.0f;
413 top_point.x = 10.0f; top_point.y = 15.0f; top_point.z = 20.0f;
415 raydirection.x = 7.0f; raydirection.y = 8.0f; raydirection.z = 9.0f;
416 rayposition.x = 3.0f; rayposition.y = 7.0f; rayposition.z = -6.0f;
417 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection);
418 ok(result == TRUE, "expected TRUE, received FALSE\n");
420 bottom_point.x = 0.0f; bottom_point.y = 0.0f; bottom_point.z = 0.0f;
421 top_point.x = 1.0f; top_point.y = 1.0f; top_point.z = 1.0f;
423 raydirection.x = 0.0f; raydirection.y = 1.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 == FALSE, "expected FALSE, received TRUE\n");
428 raydirection.x = 1.0f; raydirection.y = 0.0f; raydirection.z = .0f;
429 rayposition.x = -3.0f; rayposition.y = 0.0f; rayposition.z = 0.0f;
430 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection);
431 ok(result == TRUE, "expected TRUE, received FALSE\n");
433 /*____________Test the Sphere case________________________*/
434 radius = sqrt(77.0f);
435 center.x = 1.0f; center.y = 2.0f; center.z = 3.0f;
436 raydirection.x = 2.0f; raydirection.y = -4.0f; raydirection.z = 2.0f;
438 rayposition.x = 5.0f; rayposition.y = 5.0f; rayposition.z = 9.0f;
439 result = D3DXSphereBoundProbe(&center, radius, &rayposition, &raydirection);
440 ok(result == TRUE, "expected TRUE, received FALSE\n");
442 rayposition.x = 45.0f; rayposition.y = -75.0f; rayposition.z = 49.0f;
443 result = D3DXSphereBoundProbe(&center, radius, &rayposition, &raydirection);
444 ok(result == FALSE, "expected FALSE, received TRUE\n");
446 rayposition.x = 5.0f; rayposition.y = 11.0f; rayposition.z = 9.0f;
447 result = D3DXSphereBoundProbe(&center, radius, &rayposition, &raydirection);
448 ok(result == FALSE, "expected FALSE, received TRUE\n");
451 static void D3DXComputeBoundingBoxTest(void)
453 D3DXVECTOR3 exp_max, exp_min, got_max, got_min, vertex[5];
454 HRESULT hr;
456 vertex[0].x = 1.0f; vertex[0].y = 1.0f; vertex[0].z = 1.0f;
457 vertex[1].x = 1.0f; vertex[1].y = 1.0f; vertex[1].z = 1.0f;
458 vertex[2].x = 1.0f; vertex[2].y = 1.0f; vertex[2].z = 1.0f;
459 vertex[3].x = 1.0f; vertex[3].y = 1.0f; vertex[3].z = 1.0f;
460 vertex[4].x = 9.0f; vertex[4].y = 9.0f; vertex[4].z = 9.0f;
462 exp_min.x = 1.0f; exp_min.y = 1.0f; exp_min.z = 1.0f;
463 exp_max.x = 9.0f; exp_max.y = 9.0f; exp_max.z = 9.0f;
465 hr = D3DXComputeBoundingBox(&vertex[3],2,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_min,&got_max);
467 ok( hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
468 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);
469 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);
471 /*________________________*/
473 vertex[0].x = 2.0f; vertex[0].y = 5.9f; vertex[0].z = -1.2f;
474 vertex[1].x = -1.87f; vertex[1].y = 7.9f; vertex[1].z = 7.4f;
475 vertex[2].x = 7.43f; vertex[2].y = -0.9f; vertex[2].z = 11.9f;
476 vertex[3].x = -6.92f; vertex[3].y = 6.3f; vertex[3].z = -3.8f;
477 vertex[4].x = 11.4f; vertex[4].y = -8.1f; vertex[4].z = 4.5f;
479 exp_min.x = -6.92f; exp_min.y = -8.1f; exp_min.z = -3.80f;
480 exp_max.x = 11.4f; exp_max.y = 7.90f; exp_max.z = 11.9f;
482 hr = D3DXComputeBoundingBox(&vertex[0],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_min,&got_max);
484 ok( hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
485 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);
486 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);
488 /*________________________*/
490 vertex[0].x = 2.0f; vertex[0].y = 5.9f; vertex[0].z = -1.2f;
491 vertex[1].x = -1.87f; vertex[1].y = 7.9f; vertex[1].z = 7.4f;
492 vertex[2].x = 7.43f; vertex[2].y = -0.9f; vertex[2].z = 11.9f;
493 vertex[3].x = -6.92f; vertex[3].y = 6.3f; vertex[3].z = -3.8f;
494 vertex[4].x = 11.4f; vertex[4].y = -8.1f; vertex[4].z = 4.5f;
496 exp_min.x = -6.92f; exp_min.y = -0.9f; exp_min.z = -3.8f;
497 exp_max.x = 7.43f; exp_max.y = 7.90f; exp_max.z = 11.9f;
499 hr = D3DXComputeBoundingBox(&vertex[0],4,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_min,&got_max);
501 ok( hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
502 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);
503 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);
505 /*________________________*/
506 hr = D3DXComputeBoundingBox(NULL,5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_min,&got_max);
507 ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
509 /*________________________*/
510 hr = D3DXComputeBoundingBox(&vertex[3],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),NULL,&got_max);
511 ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
513 /*________________________*/
514 hr = D3DXComputeBoundingBox(&vertex[3],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_min,NULL);
515 ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
518 static void D3DXComputeBoundingSphereTest(void)
520 D3DXVECTOR3 exp_cen, got_cen, vertex[5];
521 FLOAT exp_rad, got_rad;
522 HRESULT hr;
524 vertex[0].x = 1.0f; vertex[0].y = 1.0f; vertex[0].z = 1.0f;
525 vertex[1].x = 1.0f; vertex[1].y = 1.0f; vertex[1].z = 1.0f;
526 vertex[2].x = 1.0f; vertex[2].y = 1.0f; vertex[2].z = 1.0f;
527 vertex[3].x = 1.0f; vertex[3].y = 1.0f; vertex[3].z = 1.0f;
528 vertex[4].x = 9.0f; vertex[4].y = 9.0f; vertex[4].z = 9.0f;
530 exp_rad = 6.928203f;
531 exp_cen.x = 5.0; exp_cen.y = 5.0; exp_cen.z = 5.0;
533 hr = D3DXComputeBoundingSphere(&vertex[3],2,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_cen,&got_rad);
535 ok( hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
536 ok( compare(exp_rad, got_rad), "Expected radius: %f, got radius: %f\n", exp_rad, got_rad);
537 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);
539 /*________________________*/
541 vertex[0].x = 2.0f; vertex[0].y = 5.9f; vertex[0].z = -1.2f;
542 vertex[1].x = -1.87f; vertex[1].y = 7.9f; vertex[1].z = 7.4f;
543 vertex[2].x = 7.43f; vertex[2].y = -0.9f; vertex[2].z = 11.9f;
544 vertex[3].x = -6.92f; vertex[3].y = 6.3f; vertex[3].z = -3.8f;
545 vertex[4].x = 11.4f; vertex[4].y = -8.1f; vertex[4].z = 4.5f;
547 exp_rad = 13.707883f;
548 exp_cen.x = 2.408f; exp_cen.y = 2.22f; exp_cen.z = 3.76f;
550 hr = D3DXComputeBoundingSphere(&vertex[0],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_cen,&got_rad);
552 ok( hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
553 ok( compare(exp_rad, got_rad), "Expected radius: %f, got radius: %f\n", exp_rad, got_rad);
554 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);
556 /*________________________*/
557 hr = D3DXComputeBoundingSphere(NULL,5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_cen,&got_rad);
558 ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
560 /*________________________*/
561 hr = D3DXComputeBoundingSphere(&vertex[3],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),NULL,&got_rad);
562 ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
564 /*________________________*/
565 hr = D3DXComputeBoundingSphere(&vertex[3],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_cen,NULL);
566 ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
569 static void print_elements(const D3DVERTEXELEMENT9 *elements)
571 D3DVERTEXELEMENT9 last = D3DDECL_END();
572 const D3DVERTEXELEMENT9 *ptr = elements;
573 int count = 0;
575 while (memcmp(ptr, &last, sizeof(D3DVERTEXELEMENT9)))
577 trace(
578 "[Element %d] Stream = %d, Offset = %d, Type = %d, Method = %d, Usage = %d, UsageIndex = %d\n",
579 count, ptr->Stream, ptr->Offset, ptr->Type, ptr->Method, ptr->Usage, ptr->UsageIndex);
580 ptr++;
581 count++;
585 static void compare_elements(const D3DVERTEXELEMENT9 *elements, const D3DVERTEXELEMENT9 *expected_elements,
586 unsigned int line, unsigned int test_id)
588 D3DVERTEXELEMENT9 last = D3DDECL_END();
589 unsigned int i;
591 for (i = 0; i < MAX_FVF_DECL_SIZE; i++)
593 int end1 = memcmp(&elements[i], &last, sizeof(last));
594 int end2 = memcmp(&expected_elements[i], &last, sizeof(last));
595 int status;
597 if (!end1 && !end2) break;
599 status = !end1 ^ !end2;
600 ok(!status, "Line %u, test %u: Mismatch in size, test declaration is %s than expected.\n",
601 line, test_id, end1 ? "shorter" : "longer");
602 if (status)
604 print_elements(elements);
605 break;
608 status = memcmp(&elements[i], &expected_elements[i], sizeof(D3DVERTEXELEMENT9));
609 ok(!status, "Line %u, test %u: Mismatch in element %u.\n", line, test_id, i);
610 if (status)
612 print_elements(elements);
613 break;
618 static void test_fvf_to_decl(DWORD test_fvf, const D3DVERTEXELEMENT9 expected_elements[],
619 HRESULT expected_hr, unsigned int line, unsigned int test_id)
621 HRESULT hr;
622 D3DVERTEXELEMENT9 decl[MAX_FVF_DECL_SIZE];
624 hr = D3DXDeclaratorFromFVF(test_fvf, decl);
625 ok(hr == expected_hr,
626 "Line %u, test %u: D3DXDeclaratorFromFVF returned %#x, expected %#x.\n",
627 line, test_id, hr, expected_hr);
628 if (SUCCEEDED(hr)) compare_elements(decl, expected_elements, line, test_id);
631 static void test_decl_to_fvf(const D3DVERTEXELEMENT9 *decl, DWORD expected_fvf,
632 HRESULT expected_hr, unsigned int line, unsigned int test_id)
634 HRESULT hr;
635 DWORD result_fvf = 0xdeadbeef;
637 hr = D3DXFVFFromDeclarator(decl, &result_fvf);
638 ok(hr == expected_hr,
639 "Line %u, test %u: D3DXFVFFromDeclarator returned %#x, expected %#x.\n",
640 line, test_id, hr, expected_hr);
641 if (SUCCEEDED(hr))
643 ok(expected_fvf == result_fvf, "Line %u, test %u: Got FVF %#x, expected %#x.\n",
644 line, test_id, result_fvf, expected_fvf);
648 static void test_fvf_decl_conversion(void)
650 static const struct
652 D3DVERTEXELEMENT9 decl[MAXD3DDECLLENGTH + 1];
653 DWORD fvf;
655 test_data[] =
658 D3DDECL_END(),
659 }, 0},
661 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
662 D3DDECL_END(),
663 }, D3DFVF_XYZ},
665 {0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITIONT, 0},
666 D3DDECL_END(),
667 }, D3DFVF_XYZRHW},
669 {0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITIONT, 0},
670 D3DDECL_END(),
671 }, D3DFVF_XYZRHW},
673 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
674 {0, 12, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
675 D3DDECL_END(),
676 }, D3DFVF_XYZB1},
678 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
679 {0, 12, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
680 D3DDECL_END(),
681 }, D3DFVF_XYZB1 | D3DFVF_LASTBETA_UBYTE4},
683 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
684 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
685 D3DDECL_END(),
686 }, D3DFVF_XYZB1 | D3DFVF_LASTBETA_D3DCOLOR},
688 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
689 {0, 12, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
690 D3DDECL_END(),
691 }, D3DFVF_XYZB2},
693 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
694 {0, 12, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
695 {0, 16, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
696 D3DDECL_END(),
697 }, D3DFVF_XYZB2 | D3DFVF_LASTBETA_UBYTE4},
699 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
700 {0, 12, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
701 {0, 16, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
702 D3DDECL_END(),
703 }, D3DFVF_XYZB2 | D3DFVF_LASTBETA_D3DCOLOR},
705 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
706 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
707 D3DDECL_END(),
708 }, D3DFVF_XYZB3},
710 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
711 {0, 12, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
712 {0, 20, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
713 D3DDECL_END(),
714 }, D3DFVF_XYZB3 | D3DFVF_LASTBETA_UBYTE4},
716 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
717 {0, 12, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
718 {0, 20, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
719 D3DDECL_END(),
720 }, D3DFVF_XYZB3 | D3DFVF_LASTBETA_D3DCOLOR},
722 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
723 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
724 D3DDECL_END(),
725 }, D3DFVF_XYZB4},
727 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
728 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
729 {0, 24, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
730 D3DDECL_END(),
731 }, D3DFVF_XYZB4 | D3DFVF_LASTBETA_UBYTE4},
733 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
734 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
735 {0, 24, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
736 D3DDECL_END(),
737 }, D3DFVF_XYZB4 | D3DFVF_LASTBETA_D3DCOLOR},
739 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
740 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
741 {0, 28, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
742 D3DDECL_END(),
743 }, D3DFVF_XYZB5 | D3DFVF_LASTBETA_UBYTE4},
745 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
746 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
747 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
748 D3DDECL_END(),
749 }, D3DFVF_XYZB5 | D3DFVF_LASTBETA_D3DCOLOR},
751 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
752 D3DDECL_END(),
753 }, D3DFVF_NORMAL},
755 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
756 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
757 D3DDECL_END(),
758 }, D3DFVF_NORMAL | D3DFVF_DIFFUSE},
760 {0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_PSIZE, 0},
761 D3DDECL_END(),
762 }, D3DFVF_PSIZE},
764 {0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
765 D3DDECL_END(),
766 }, D3DFVF_DIFFUSE},
768 {0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1},
769 D3DDECL_END(),
770 }, D3DFVF_SPECULAR},
771 /* Make sure textures of different sizes work. */
773 {0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
774 D3DDECL_END(),
775 }, D3DFVF_TEXCOORDSIZE1(0) | D3DFVF_TEX1},
777 {0, 0, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 0},
778 D3DDECL_END(),
779 }, D3DFVF_TEXCOORDSIZE2(0) | D3DFVF_TEX1},
781 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 0},
782 D3DDECL_END(),
783 }, D3DFVF_TEXCOORDSIZE3(0) | D3DFVF_TEX1},
785 {0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 0},
786 D3DDECL_END(),
787 }, D3DFVF_TEXCOORDSIZE4(0) | D3DFVF_TEX1},
788 /* Make sure the TEXCOORD index works correctly - try several textures. */
790 {0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
791 {0, 4, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 1},
792 {0, 16, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 2},
793 {0, 24, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 3},
794 D3DDECL_END(),
795 }, D3DFVF_TEX4 | D3DFVF_TEXCOORDSIZE1(0) | D3DFVF_TEXCOORDSIZE3(1)
796 | D3DFVF_TEXCOORDSIZE2(2) | D3DFVF_TEXCOORDSIZE4(3)},
797 /* Now try some combination tests. */
799 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
800 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
801 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
802 {0, 32, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1},
803 {0, 36, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 0},
804 {0, 44, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 1},
805 D3DDECL_END(),
806 }, D3DFVF_XYZB4 | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_TEX2
807 | D3DFVF_TEXCOORDSIZE2(0) | D3DFVF_TEXCOORDSIZE3(1)},
809 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
810 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
811 {0, 24, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_PSIZE, 0},
812 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1},
813 {0, 32, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
814 {0, 36, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 1},
815 D3DDECL_END(),
816 }, D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_PSIZE | D3DFVF_SPECULAR | D3DFVF_TEX2
817 | D3DFVF_TEXCOORDSIZE1(0) | D3DFVF_TEXCOORDSIZE4(1)},
819 unsigned int i;
821 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
823 test_decl_to_fvf(test_data[i].decl, test_data[i].fvf, D3D_OK, __LINE__, i);
824 test_fvf_to_decl(test_data[i].fvf, test_data[i].decl, D3D_OK, __LINE__, i);
827 /* Usage indices for position and normal are apparently ignored. */
829 const D3DVERTEXELEMENT9 decl[] =
831 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 1},
832 D3DDECL_END(),
834 test_decl_to_fvf(decl, D3DFVF_XYZ, D3D_OK, __LINE__, 0);
837 const D3DVERTEXELEMENT9 decl[] =
839 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 1},
840 D3DDECL_END(),
842 test_decl_to_fvf(decl, D3DFVF_NORMAL, D3D_OK, __LINE__, 0);
844 /* D3DFVF_LASTBETA_UBYTE4 and D3DFVF_LASTBETA_D3DCOLOR are ignored if
845 * there are no blend matrices. */
847 const D3DVERTEXELEMENT9 decl[] =
849 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
850 D3DDECL_END(),
852 test_fvf_to_decl(D3DFVF_XYZ | D3DFVF_LASTBETA_UBYTE4, decl, D3D_OK, __LINE__, 0);
855 const D3DVERTEXELEMENT9 decl[] =
857 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
858 D3DDECL_END(),
860 test_fvf_to_decl(D3DFVF_XYZ | D3DFVF_LASTBETA_D3DCOLOR, decl, D3D_OK, __LINE__, 0);
862 /* D3DFVF_LASTBETA_UBYTE4 takes precedence over D3DFVF_LASTBETA_D3DCOLOR. */
864 const D3DVERTEXELEMENT9 decl[] =
866 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
867 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
868 {0, 28, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
869 D3DDECL_END(),
871 test_fvf_to_decl(D3DFVF_XYZB5 | D3DFVF_LASTBETA_D3DCOLOR | D3DFVF_LASTBETA_UBYTE4,
872 decl, D3D_OK, __LINE__, 0);
874 /* These are supposed to fail, both ways. */
876 const D3DVERTEXELEMENT9 decl[] =
878 {0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITION, 0},
879 D3DDECL_END(),
881 test_decl_to_fvf(decl, D3DFVF_XYZW, D3DERR_INVALIDCALL, __LINE__, 0);
882 test_fvf_to_decl(D3DFVF_XYZW, decl, D3DERR_INVALIDCALL, __LINE__, 0);
885 const D3DVERTEXELEMENT9 decl[] =
887 {0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITION, 0},
888 {0, 16, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
889 D3DDECL_END(),
891 test_decl_to_fvf(decl, D3DFVF_XYZW | D3DFVF_NORMAL, D3DERR_INVALIDCALL, __LINE__, 0);
892 test_fvf_to_decl(D3DFVF_XYZW | D3DFVF_NORMAL, decl, D3DERR_INVALIDCALL, __LINE__, 0);
895 const D3DVERTEXELEMENT9 decl[] =
897 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
898 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
899 {0, 28, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDINDICES, 0},
900 D3DDECL_END(),
902 test_decl_to_fvf(decl, D3DFVF_XYZB5, D3DERR_INVALIDCALL, __LINE__, 0);
903 test_fvf_to_decl(D3DFVF_XYZB5, decl, D3DERR_INVALIDCALL, __LINE__, 0);
905 /* Test a declaration that can't be converted to an FVF. */
907 const D3DVERTEXELEMENT9 decl[] =
909 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
910 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
911 {0, 24, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_PSIZE, 0},
912 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1},
913 {0, 32, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
914 /* 8 bytes padding */
915 {0, 44, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 1},
916 D3DDECL_END(),
918 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0);
920 /* Elements must be ordered by offset. */
922 const D3DVERTEXELEMENT9 decl[] =
924 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
925 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
926 D3DDECL_END(),
928 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0);
930 /* Basic tests for element order. */
932 const D3DVERTEXELEMENT9 decl[] =
934 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
935 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
936 {0, 16, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
937 D3DDECL_END(),
939 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0);
942 const D3DVERTEXELEMENT9 decl[] =
944 {0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
945 {0, 4, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
946 D3DDECL_END(),
948 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0);
951 const D3DVERTEXELEMENT9 decl[] =
953 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
954 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
955 D3DDECL_END(),
957 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0);
959 /* Textures must be ordered by texcoords. */
961 const D3DVERTEXELEMENT9 decl[] =
963 {0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
964 {0, 4, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 2},
965 {0, 16, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 1},
966 {0, 24, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 3},
967 D3DDECL_END(),
969 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0);
971 /* Duplicate elements are not allowed. */
973 const D3DVERTEXELEMENT9 decl[] =
975 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
976 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
977 {0, 16, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
978 D3DDECL_END(),
980 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0);
982 /* Invalid FVFs cannot be converted to a declarator. */
983 test_fvf_to_decl(0xdeadbeef, NULL, D3DERR_INVALIDCALL, __LINE__, 0);
986 static void D3DXGetFVFVertexSizeTest(void)
988 UINT got;
990 compare_vertex_sizes (D3DFVF_XYZ, 12);
992 compare_vertex_sizes (D3DFVF_XYZB3, 24);
994 compare_vertex_sizes (D3DFVF_XYZB5, 32);
996 compare_vertex_sizes (D3DFVF_XYZ | D3DFVF_NORMAL, 24);
998 compare_vertex_sizes (D3DFVF_XYZ | D3DFVF_DIFFUSE, 16);
1000 compare_vertex_sizes (
1001 D3DFVF_XYZ |
1002 D3DFVF_TEX1 |
1003 D3DFVF_TEXCOORDSIZE1(0), 16);
1004 compare_vertex_sizes (
1005 D3DFVF_XYZ |
1006 D3DFVF_TEX2 |
1007 D3DFVF_TEXCOORDSIZE1(0) |
1008 D3DFVF_TEXCOORDSIZE1(1), 20);
1010 compare_vertex_sizes (
1011 D3DFVF_XYZ |
1012 D3DFVF_TEX1 |
1013 D3DFVF_TEXCOORDSIZE2(0), 20);
1015 compare_vertex_sizes (
1016 D3DFVF_XYZ |
1017 D3DFVF_TEX2 |
1018 D3DFVF_TEXCOORDSIZE2(0) |
1019 D3DFVF_TEXCOORDSIZE2(1), 28);
1021 compare_vertex_sizes (
1022 D3DFVF_XYZ |
1023 D3DFVF_TEX6 |
1024 D3DFVF_TEXCOORDSIZE2(0) |
1025 D3DFVF_TEXCOORDSIZE2(1) |
1026 D3DFVF_TEXCOORDSIZE2(2) |
1027 D3DFVF_TEXCOORDSIZE2(3) |
1028 D3DFVF_TEXCOORDSIZE2(4) |
1029 D3DFVF_TEXCOORDSIZE2(5), 60);
1031 compare_vertex_sizes (
1032 D3DFVF_XYZ |
1033 D3DFVF_TEX8 |
1034 D3DFVF_TEXCOORDSIZE2(0) |
1035 D3DFVF_TEXCOORDSIZE2(1) |
1036 D3DFVF_TEXCOORDSIZE2(2) |
1037 D3DFVF_TEXCOORDSIZE2(3) |
1038 D3DFVF_TEXCOORDSIZE2(4) |
1039 D3DFVF_TEXCOORDSIZE2(5) |
1040 D3DFVF_TEXCOORDSIZE2(6) |
1041 D3DFVF_TEXCOORDSIZE2(7), 76);
1043 compare_vertex_sizes (
1044 D3DFVF_XYZ |
1045 D3DFVF_TEX1 |
1046 D3DFVF_TEXCOORDSIZE3(0), 24);
1048 compare_vertex_sizes (
1049 D3DFVF_XYZ |
1050 D3DFVF_TEX4 |
1051 D3DFVF_TEXCOORDSIZE3(0) |
1052 D3DFVF_TEXCOORDSIZE3(1) |
1053 D3DFVF_TEXCOORDSIZE3(2) |
1054 D3DFVF_TEXCOORDSIZE3(3), 60);
1056 compare_vertex_sizes (
1057 D3DFVF_XYZ |
1058 D3DFVF_TEX1 |
1059 D3DFVF_TEXCOORDSIZE4(0), 28);
1061 compare_vertex_sizes (
1062 D3DFVF_XYZ |
1063 D3DFVF_TEX2 |
1064 D3DFVF_TEXCOORDSIZE4(0) |
1065 D3DFVF_TEXCOORDSIZE4(1), 44);
1067 compare_vertex_sizes (
1068 D3DFVF_XYZ |
1069 D3DFVF_TEX3 |
1070 D3DFVF_TEXCOORDSIZE4(0) |
1071 D3DFVF_TEXCOORDSIZE4(1) |
1072 D3DFVF_TEXCOORDSIZE4(2), 60);
1074 compare_vertex_sizes (
1075 D3DFVF_XYZB5 |
1076 D3DFVF_NORMAL |
1077 D3DFVF_DIFFUSE |
1078 D3DFVF_SPECULAR |
1079 D3DFVF_TEX8 |
1080 D3DFVF_TEXCOORDSIZE4(0) |
1081 D3DFVF_TEXCOORDSIZE4(1) |
1082 D3DFVF_TEXCOORDSIZE4(2) |
1083 D3DFVF_TEXCOORDSIZE4(3) |
1084 D3DFVF_TEXCOORDSIZE4(4) |
1085 D3DFVF_TEXCOORDSIZE4(5) |
1086 D3DFVF_TEXCOORDSIZE4(6) |
1087 D3DFVF_TEXCOORDSIZE4(7), 180);
1090 static void D3DXIntersectTriTest(void)
1092 BOOL exp_res, got_res;
1093 D3DXVECTOR3 position, ray, vertex[3];
1094 FLOAT exp_dist, got_dist, exp_u, got_u, exp_v, got_v;
1096 vertex[0].x = 1.0f; vertex[0].y = 0.0f; vertex[0].z = 0.0f;
1097 vertex[1].x = 2.0f; vertex[1].y = 0.0f; vertex[1].z = 0.0f;
1098 vertex[2].x = 1.0f; vertex[2].y = 1.0f; vertex[2].z = 0.0f;
1100 position.x = -14.5f; position.y = -23.75f; position.z = -32.0f;
1102 ray.x = 2.0f; ray.y = 3.0f; ray.z = 4.0f;
1104 exp_res = TRUE; exp_u = 0.5f; exp_v = 0.25f; exp_dist = 8.0f;
1106 got_res = D3DXIntersectTri(&vertex[0], &vertex[1], &vertex[2], &position, &ray, &got_u, &got_v, &got_dist);
1107 ok(got_res == exp_res, "Expected result %d, got %d.\n", exp_res, got_res);
1108 ok(compare(exp_u, got_u), "Expected u %f, got %f.\n", exp_u, got_u);
1109 ok(compare(exp_v, got_v), "Expected v %f, got %f.\n", exp_v, got_v);
1110 ok(compare(exp_dist, got_dist), "Expected distance %f, got %f.\n", exp_dist, got_dist);
1112 got_res = D3DXIntersectTri(&vertex[0], &vertex[1], &vertex[2], &position, &ray, NULL, NULL, NULL);
1113 ok(got_res == exp_res, "Expected result %d, got %d.\n", exp_res, got_res);
1115 vertex[2].x = 1.0f; vertex[2].y = 0.0f; vertex[2].z = 0.0f;
1116 vertex[1].x = 2.0f; vertex[1].y = 0.0f; vertex[1].z = 0.0f;
1117 vertex[0].x = 1.0f; vertex[0].y = 1.0f; vertex[0].z = 0.0f;
1119 got_u = got_v = got_dist = 0.0f;
1120 got_res = D3DXIntersectTri(&vertex[0], &vertex[1], &vertex[2], &position, &ray, &got_u, &got_v, &got_dist);
1121 ok(got_res == exp_res, "Expected result %d, got %d.\n", exp_res, got_res);
1122 ok(compare(exp_u, got_u), "Expected u %f, got %f.\n", exp_u, got_u);
1123 ok(compare(exp_v, got_v), "Expected v %f, got %f.\n", exp_v, got_v);
1124 ok(compare(exp_dist, got_dist), "Expected distance %f, got %f.\n", exp_dist, got_dist);
1126 vertex[2].x = 1.0f; vertex[2].y = 0.0f; vertex[2].z = 0.0f;
1127 vertex[1].x = 2.0f; vertex[1].y = 0.0f; vertex[1].z = -0.5f;
1128 vertex[0].x = 1.0f; vertex[0].y = 1.0f; vertex[0].z = -1.0f;
1129 exp_u = 0.375f;
1130 exp_v = 0.5625f;
1131 exp_dist = 7.9375f;
1132 got_u = got_v = got_dist = 0.0f;
1133 got_res = D3DXIntersectTri(&vertex[0], &vertex[1], &vertex[2], &position, &ray, &got_u, &got_v, &got_dist);
1134 ok(got_res == exp_res, "Expected result %d, got %d.\n", exp_res, got_res);
1135 ok(compare(exp_u, got_u), "Expected u %f, got %f.\n", exp_u, got_u);
1136 ok(compare(exp_v, got_v), "Expected v %f, got %f.\n", exp_v, got_v);
1137 ok(compare(exp_dist, got_dist), "Expected distance %f, got %f.\n", exp_dist, got_dist);
1140 /*Only positive ray is taken in account*/
1142 vertex[0].x = 1.0f; vertex[0].y = 0.0f; vertex[0].z = 0.0f;
1143 vertex[1].x = 2.0f; vertex[1].y = 0.0f; vertex[1].z = 0.0f;
1144 vertex[2].x = 1.0f; vertex[2].y = 1.0f; vertex[2].z = 0.0f;
1146 position.x = 17.5f; position.y = 24.25f; position.z = 32.0f;
1148 ray.x = 2.0f; ray.y = 3.0f; ray.z = 4.0f;
1150 exp_res = FALSE;
1152 got_res = D3DXIntersectTri(&vertex[0],&vertex[1],&vertex[2],&position,&ray,&got_u,&got_v,&got_dist);
1153 ok( got_res == exp_res, "Expected result = %d, got %d\n",exp_res,got_res);
1155 got_res = D3DXIntersectTri(&vertex[0], &vertex[1], &vertex[2], &position, &ray, NULL, NULL, NULL);
1156 ok(got_res == exp_res, "Expected result = %d, got %d\n", exp_res, got_res);
1158 /*Intersection between ray and triangle in a same plane is considered as empty*/
1160 vertex[0].x = 4.0f; vertex[0].y = 0.0f; vertex[0].z = 0.0f;
1161 vertex[1].x = 6.0f; vertex[1].y = 0.0f; vertex[1].z = 0.0f;
1162 vertex[2].x = 4.0f; vertex[2].y = 2.0f; vertex[2].z = 0.0f;
1164 position.x = 1.0f; position.y = 1.0f; position.z = 0.0f;
1166 ray.x = 1.0f; ray.y = 0.0f; ray.z = 0.0f;
1168 exp_res = FALSE;
1170 got_res = D3DXIntersectTri(&vertex[0],&vertex[1],&vertex[2],&position,&ray,&got_u,&got_v,&got_dist);
1171 ok( got_res == exp_res, "Expected result = %d, got %d\n",exp_res,got_res);
1173 got_res = D3DXIntersectTri(&vertex[0], &vertex[1], &vertex[2], &position, &ray, NULL, NULL, NULL);
1174 ok(got_res == exp_res, "Expected result = %d, got %d\n", exp_res, got_res);
1177 static void D3DXCreateMeshTest(void)
1179 HRESULT hr;
1180 IDirect3DDevice9 *device, *test_device;
1181 ID3DXMesh *d3dxmesh;
1182 int i, size;
1183 D3DVERTEXELEMENT9 test_decl[MAX_FVF_DECL_SIZE];
1184 DWORD options;
1185 struct mesh mesh;
1186 struct test_context *test_context;
1188 static const D3DVERTEXELEMENT9 decl1[3] = {
1189 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1190 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
1191 D3DDECL_END(), };
1193 static const D3DVERTEXELEMENT9 decl2[] = {
1194 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1195 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
1196 {0, 24, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_PSIZE, 0},
1197 {0, 28, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 1},
1198 {0, 32, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
1199 /* 8 bytes padding */
1200 {0, 44, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
1201 D3DDECL_END(),
1204 static const D3DVERTEXELEMENT9 decl3[] = {
1205 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1206 {1, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
1207 D3DDECL_END(),
1210 hr = D3DXCreateMesh(0, 0, 0, NULL, NULL, NULL);
1211 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1213 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl1, NULL, &d3dxmesh);
1214 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1216 test_context = new_test_context();
1217 if (!test_context)
1219 skip("Couldn't create test context\n");
1220 return;
1222 device = test_context->device;
1224 hr = D3DXCreateMesh(0, 3, D3DXMESH_MANAGED, decl1, device, &d3dxmesh);
1225 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1227 hr = D3DXCreateMesh(1, 0, D3DXMESH_MANAGED, decl1, device, &d3dxmesh);
1228 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1230 hr = D3DXCreateMesh(1, 3, 0, decl1, device, &d3dxmesh);
1231 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
1233 if (hr == D3D_OK)
1235 d3dxmesh->lpVtbl->Release(d3dxmesh);
1238 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, 0, device, &d3dxmesh);
1239 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1241 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl1, device, NULL);
1242 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1244 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl1, device, &d3dxmesh);
1245 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
1247 if (hr == D3D_OK)
1249 /* device */
1250 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, NULL);
1251 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1253 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, &test_device);
1254 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
1255 ok(test_device == device, "Got result %p, expected %p\n", test_device, device);
1257 if (hr == D3D_OK)
1259 IDirect3DDevice9_Release(device);
1262 /* declaration */
1263 hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, NULL);
1264 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1266 hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, test_decl);
1267 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
1269 if (hr == D3D_OK)
1271 size = sizeof(decl1) / sizeof(decl1[0]);
1272 for (i = 0; i < size - 1; i++)
1274 ok(test_decl[i].Stream == decl1[i].Stream, "Returned stream %d, expected %d\n", test_decl[i].Stream, decl1[i].Stream);
1275 ok(test_decl[i].Type == decl1[i].Type, "Returned type %d, expected %d\n", test_decl[i].Type, decl1[i].Type);
1276 ok(test_decl[i].Method == decl1[i].Method, "Returned method %d, expected %d\n", test_decl[i].Method, decl1[i].Method);
1277 ok(test_decl[i].Usage == decl1[i].Usage, "Returned usage %d, expected %d\n", test_decl[i].Usage, decl1[i].Usage);
1278 ok(test_decl[i].UsageIndex == decl1[i].UsageIndex, "Returned usage index %d, expected %d\n", test_decl[i].UsageIndex, decl1[i].UsageIndex);
1279 ok(test_decl[i].Offset == decl1[i].Offset, "Returned offset %d, expected %d\n", test_decl[i].Offset, decl1[i].Offset);
1281 ok(decl1[size-1].Stream == 0xFF, "Returned too long vertex declaration\n"); /* end element */
1284 /* options */
1285 options = d3dxmesh->lpVtbl->GetOptions(d3dxmesh);
1286 ok(options == D3DXMESH_MANAGED, "Got result %x, expected %x (D3DXMESH_MANAGED)\n", options, D3DXMESH_MANAGED);
1288 /* rest */
1289 if (!new_mesh(&mesh, 3, 1))
1291 skip("Couldn't create mesh\n");
1293 else
1295 memset(mesh.vertices, 0, mesh.number_of_vertices * sizeof(*mesh.vertices));
1296 memset(mesh.faces, 0, mesh.number_of_faces * sizeof(*mesh.faces));
1297 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
1299 compare_mesh("createmesh1", d3dxmesh, &mesh);
1301 free_mesh(&mesh);
1304 d3dxmesh->lpVtbl->Release(d3dxmesh);
1307 /* Test a declaration that can't be converted to an FVF. */
1308 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl2, device, &d3dxmesh);
1309 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
1311 if (hr == D3D_OK)
1313 /* device */
1314 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, NULL);
1315 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1317 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, &test_device);
1318 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
1319 ok(test_device == device, "Got result %p, expected %p\n", test_device, device);
1321 if (hr == D3D_OK)
1323 IDirect3DDevice9_Release(device);
1326 /* declaration */
1327 hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, test_decl);
1328 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
1330 if (hr == D3D_OK)
1332 size = sizeof(decl2) / sizeof(decl2[0]);
1333 for (i = 0; i < size - 1; i++)
1335 ok(test_decl[i].Stream == decl2[i].Stream, "Returned stream %d, expected %d\n", test_decl[i].Stream, decl2[i].Stream);
1336 ok(test_decl[i].Type == decl2[i].Type, "Returned type %d, expected %d\n", test_decl[i].Type, decl2[i].Type);
1337 ok(test_decl[i].Method == decl2[i].Method, "Returned method %d, expected %d\n", test_decl[i].Method, decl2[i].Method);
1338 ok(test_decl[i].Usage == decl2[i].Usage, "Returned usage %d, expected %d\n", test_decl[i].Usage, decl2[i].Usage);
1339 ok(test_decl[i].UsageIndex == decl2[i].UsageIndex, "Returned usage index %d, expected %d\n", test_decl[i].UsageIndex, decl2[i].UsageIndex);
1340 ok(test_decl[i].Offset == decl2[i].Offset, "Returned offset %d, expected %d\n", test_decl[i].Offset, decl2[i].Offset);
1342 ok(decl2[size-1].Stream == 0xFF, "Returned too long vertex declaration\n"); /* end element */
1345 /* options */
1346 options = d3dxmesh->lpVtbl->GetOptions(d3dxmesh);
1347 ok(options == D3DXMESH_MANAGED, "Got result %x, expected %x (D3DXMESH_MANAGED)\n", options, D3DXMESH_MANAGED);
1349 /* rest */
1350 if (!new_mesh(&mesh, 3, 1))
1352 skip("Couldn't create mesh\n");
1354 else
1356 memset(mesh.vertices, 0, mesh.number_of_vertices * sizeof(*mesh.vertices));
1357 memset(mesh.faces, 0, mesh.number_of_faces * sizeof(*mesh.faces));
1358 mesh.fvf = 0;
1359 mesh.vertex_size = 60;
1361 compare_mesh("createmesh2", d3dxmesh, &mesh);
1363 free_mesh(&mesh);
1366 mesh.vertex_size = d3dxmesh->lpVtbl->GetNumBytesPerVertex(d3dxmesh);
1367 ok(mesh.vertex_size == 60, "Got vertex size %u, expected %u\n", mesh.vertex_size, 60);
1369 d3dxmesh->lpVtbl->Release(d3dxmesh);
1372 /* Test a declaration with multiple streams. */
1373 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl3, device, &d3dxmesh);
1374 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1376 free_test_context(test_context);
1379 static void D3DXCreateMeshFVFTest(void)
1381 HRESULT hr;
1382 IDirect3DDevice9 *device, *test_device;
1383 ID3DXMesh *d3dxmesh;
1384 int i, size;
1385 D3DVERTEXELEMENT9 test_decl[MAX_FVF_DECL_SIZE];
1386 DWORD options;
1387 struct mesh mesh;
1388 struct test_context *test_context;
1390 static const D3DVERTEXELEMENT9 decl[3] = {
1391 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1392 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
1393 D3DDECL_END(), };
1395 hr = D3DXCreateMeshFVF(0, 0, 0, 0, NULL, NULL);
1396 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1398 hr = D3DXCreateMeshFVF(1, 3, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, NULL, &d3dxmesh);
1399 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1401 test_context = new_test_context();
1402 if (!test_context)
1404 skip("Couldn't create test context\n");
1405 return;
1407 device = test_context->device;
1409 hr = D3DXCreateMeshFVF(0, 3, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, device, &d3dxmesh);
1410 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1412 hr = D3DXCreateMeshFVF(1, 0, 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, 3, 0, D3DFVF_XYZ | D3DFVF_NORMAL, device, &d3dxmesh);
1416 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
1418 if (hr == D3D_OK)
1420 d3dxmesh->lpVtbl->Release(d3dxmesh);
1423 hr = D3DXCreateMeshFVF(1, 3, D3DXMESH_MANAGED, 0xdeadbeef, device, &d3dxmesh);
1424 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1426 hr = D3DXCreateMeshFVF(1, 3, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, device, NULL);
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, &d3dxmesh);
1430 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
1432 if (hr == D3D_OK)
1434 /* device */
1435 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, NULL);
1436 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1438 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, &test_device);
1439 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
1440 ok(test_device == device, "Got result %p, expected %p\n", test_device, device);
1442 if (hr == D3D_OK)
1444 IDirect3DDevice9_Release(device);
1447 /* declaration */
1448 hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, NULL);
1449 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1451 hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, test_decl);
1452 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
1454 if (hr == D3D_OK)
1456 size = sizeof(decl) / sizeof(decl[0]);
1457 for (i = 0; i < size - 1; i++)
1459 ok(test_decl[i].Stream == decl[i].Stream, "Returned stream %d, expected %d\n", test_decl[i].Stream, decl[i].Stream);
1460 ok(test_decl[i].Type == decl[i].Type, "Returned type %d, expected %d\n", test_decl[i].Type, decl[i].Type);
1461 ok(test_decl[i].Method == decl[i].Method, "Returned method %d, expected %d\n", test_decl[i].Method, decl[i].Method);
1462 ok(test_decl[i].Usage == decl[i].Usage, "Returned usage %d, expected %d\n", test_decl[i].Usage, decl[i].Usage);
1463 ok(test_decl[i].UsageIndex == decl[i].UsageIndex, "Returned usage index %d, expected %d\n",
1464 test_decl[i].UsageIndex, decl[i].UsageIndex);
1465 ok(test_decl[i].Offset == decl[i].Offset, "Returned offset %d, expected %d\n", test_decl[i].Offset, decl[i].Offset);
1467 ok(decl[size-1].Stream == 0xFF, "Returned too long vertex declaration\n"); /* end element */
1470 /* options */
1471 options = d3dxmesh->lpVtbl->GetOptions(d3dxmesh);
1472 ok(options == D3DXMESH_MANAGED, "Got result %x, expected %x (D3DXMESH_MANAGED)\n", options, D3DXMESH_MANAGED);
1474 /* rest */
1475 if (!new_mesh(&mesh, 3, 1))
1477 skip("Couldn't create mesh\n");
1479 else
1481 memset(mesh.vertices, 0, mesh.number_of_vertices * sizeof(*mesh.vertices));
1482 memset(mesh.faces, 0, mesh.number_of_faces * sizeof(*mesh.faces));
1483 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
1485 compare_mesh("createmeshfvf", d3dxmesh, &mesh);
1487 free_mesh(&mesh);
1490 d3dxmesh->lpVtbl->Release(d3dxmesh);
1493 free_test_context(test_context);
1496 #define check_vertex_buffer(mesh, vertices, num_vertices, fvf) \
1497 check_vertex_buffer_(__LINE__, mesh, vertices, num_vertices, fvf)
1498 static void check_vertex_buffer_(int line, ID3DXMesh *mesh, const void *vertices, DWORD num_vertices, DWORD fvf)
1500 DWORD mesh_num_vertices = mesh->lpVtbl->GetNumVertices(mesh);
1501 DWORD mesh_fvf = mesh->lpVtbl->GetFVF(mesh);
1502 const void *mesh_vertices;
1503 HRESULT hr;
1505 ok_(__FILE__,line)(fvf == mesh_fvf, "expected FVF %x, got %x\n", fvf, mesh_fvf);
1506 ok_(__FILE__,line)(num_vertices == mesh_num_vertices,
1507 "Expected %u vertices, got %u\n", num_vertices, mesh_num_vertices);
1509 hr = mesh->lpVtbl->LockVertexBuffer(mesh, D3DLOCK_READONLY, (void**)&mesh_vertices);
1510 ok_(__FILE__,line)(hr == D3D_OK, "LockVertexBuffer returned %x, expected %x (D3D_OK)\n", hr, D3D_OK);
1511 if (FAILED(hr))
1512 return;
1514 if (mesh_fvf == fvf) {
1515 DWORD vertex_size = D3DXGetFVFVertexSize(fvf), i;
1517 for (i = 0; i < min(num_vertices, mesh_num_vertices); i++)
1519 const FLOAT *exp_float = vertices;
1520 const FLOAT *got_float = mesh_vertices;
1521 DWORD texcount;
1522 DWORD pos_dim = 0;
1523 int j;
1524 BOOL last_beta_dword = FALSE;
1525 char prefix[128];
1527 switch (fvf & D3DFVF_POSITION_MASK) {
1528 case D3DFVF_XYZ: pos_dim = 3; break;
1529 case D3DFVF_XYZRHW: pos_dim = 4; break;
1530 case D3DFVF_XYZB1:
1531 case D3DFVF_XYZB2:
1532 case D3DFVF_XYZB3:
1533 case D3DFVF_XYZB4:
1534 case D3DFVF_XYZB5:
1535 pos_dim = (fvf & D3DFVF_POSITION_MASK) - D3DFVF_XYZB1 + 1;
1536 if (fvf & (D3DFVF_LASTBETA_UBYTE4 | D3DFVF_LASTBETA_D3DCOLOR))
1538 pos_dim--;
1539 last_beta_dword = TRUE;
1541 break;
1542 case D3DFVF_XYZW: pos_dim = 4; break;
1544 sprintf(prefix, "vertex[%u] position, ", i);
1545 check_floats_(line, prefix, got_float, exp_float, pos_dim);
1546 exp_float += pos_dim;
1547 got_float += pos_dim;
1549 if (last_beta_dword) {
1550 ok_(__FILE__,line)(*(DWORD*)exp_float == *(DWORD*)got_float,
1551 "Vertex[%u]: Expected last beta %08x, got %08x\n", i, *(DWORD*)exp_float, *(DWORD*)got_float);
1552 exp_float++;
1553 got_float++;
1556 if (fvf & D3DFVF_NORMAL) {
1557 sprintf(prefix, "vertex[%u] normal, ", i);
1558 check_floats_(line, prefix, got_float, exp_float, 3);
1559 exp_float += 3;
1560 got_float += 3;
1562 if (fvf & D3DFVF_PSIZE) {
1563 ok_(__FILE__,line)(compare(*exp_float, *got_float),
1564 "Vertex[%u]: Expected psize %g, got %g\n", i, *exp_float, *got_float);
1565 exp_float++;
1566 got_float++;
1568 if (fvf & D3DFVF_DIFFUSE) {
1569 ok_(__FILE__,line)(*(DWORD*)exp_float == *(DWORD*)got_float,
1570 "Vertex[%u]: Expected diffuse %08x, got %08x\n", i, *(DWORD*)exp_float, *(DWORD*)got_float);
1571 exp_float++;
1572 got_float++;
1574 if (fvf & D3DFVF_SPECULAR) {
1575 ok_(__FILE__,line)(*(DWORD*)exp_float == *(DWORD*)got_float,
1576 "Vertex[%u]: Expected specular %08x, got %08x\n", i, *(DWORD*)exp_float, *(DWORD*)got_float);
1577 exp_float++;
1578 got_float++;
1581 texcount = (fvf & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
1582 for (j = 0; j < texcount; j++) {
1583 DWORD dim = (((fvf >> (16 + 2 * j)) + 1) & 0x03) + 1;
1584 sprintf(prefix, "vertex[%u] texture, ", i);
1585 check_floats_(line, prefix, got_float, exp_float, dim);
1586 exp_float += dim;
1587 got_float += dim;
1590 vertices = (BYTE*)vertices + vertex_size;
1591 mesh_vertices = (BYTE*)mesh_vertices + vertex_size;
1595 mesh->lpVtbl->UnlockVertexBuffer(mesh);
1598 #define check_index_buffer(mesh, indices, num_indices, index_size) \
1599 check_index_buffer_(__LINE__, mesh, indices, num_indices, index_size)
1600 static void check_index_buffer_(int line, ID3DXMesh *mesh, const void *indices, DWORD num_indices, DWORD index_size)
1602 DWORD mesh_index_size = (mesh->lpVtbl->GetOptions(mesh) & D3DXMESH_32BIT) ? 4 : 2;
1603 DWORD mesh_num_indices = mesh->lpVtbl->GetNumFaces(mesh) * 3;
1604 const void *mesh_indices;
1605 HRESULT hr;
1606 DWORD i;
1608 ok_(__FILE__,line)(index_size == mesh_index_size,
1609 "Expected index size %u, got %u\n", index_size, mesh_index_size);
1610 ok_(__FILE__,line)(num_indices == mesh_num_indices,
1611 "Expected %u indices, got %u\n", num_indices, mesh_num_indices);
1613 hr = mesh->lpVtbl->LockIndexBuffer(mesh, D3DLOCK_READONLY, (void**)&mesh_indices);
1614 ok_(__FILE__,line)(hr == D3D_OK, "LockIndexBuffer returned %x, expected %x (D3D_OK)\n", hr, D3D_OK);
1615 if (FAILED(hr))
1616 return;
1618 if (mesh_index_size == index_size) {
1619 for (i = 0; i < min(num_indices, mesh_num_indices); i++)
1621 if (index_size == 4)
1622 ok_(__FILE__,line)(*(DWORD*)indices == *(DWORD*)mesh_indices,
1623 "Index[%u]: expected %u, got %u\n", i, *(DWORD*)indices, *(DWORD*)mesh_indices);
1624 else
1625 ok_(__FILE__,line)(*(WORD*)indices == *(WORD*)mesh_indices,
1626 "Index[%u]: expected %u, got %u\n", i, *(WORD*)indices, *(WORD*)mesh_indices);
1627 indices = (BYTE*)indices + index_size;
1628 mesh_indices = (BYTE*)mesh_indices + index_size;
1631 mesh->lpVtbl->UnlockIndexBuffer(mesh);
1634 #define check_matrix(got, expected) check_matrix_(__LINE__, got, expected)
1635 static void check_matrix_(int line, const D3DXMATRIX *got, const D3DXMATRIX *expected)
1637 int i, j;
1638 for (i = 0; i < 4; i++) {
1639 for (j = 0; j < 4; j++) {
1640 ok_(__FILE__,line)(compare(U(*expected).m[i][j], U(*got).m[i][j]),
1641 "matrix[%u][%u]: expected %g, got %g\n",
1642 i, j, U(*expected).m[i][j], U(*got).m[i][j]);
1647 static void check_colorvalue_(int line, const char *prefix, const D3DCOLORVALUE got, const D3DCOLORVALUE expected)
1649 ok_(__FILE__,line)(expected.r == got.r && expected.g == got.g && expected.b == got.b && expected.a == got.a,
1650 "%sExpected (%g, %g, %g, %g), got (%g, %g, %g, %g)\n", prefix,
1651 expected.r, expected.g, expected.b, expected.a, got.r, got.g, got.b, got.a);
1654 #define check_materials(got, got_count, expected, expected_count) \
1655 check_materials_(__LINE__, got, got_count, expected, expected_count)
1656 static void check_materials_(int line, const D3DXMATERIAL *got, DWORD got_count, const D3DXMATERIAL *expected, DWORD expected_count)
1658 int i;
1659 ok_(__FILE__,line)(expected_count == got_count, "Expected %u materials, got %u\n", expected_count, got_count);
1660 if (!expected) {
1661 ok_(__FILE__,line)(got == NULL, "Expected NULL material ptr, got %p\n", got);
1662 return;
1664 for (i = 0; i < min(expected_count, got_count); i++)
1666 if (!expected[i].pTextureFilename)
1667 ok_(__FILE__,line)(got[i].pTextureFilename == NULL,
1668 "Expected NULL pTextureFilename, got %p\n", got[i].pTextureFilename);
1669 else
1670 ok_(__FILE__,line)(!strcmp(expected[i].pTextureFilename, got[i].pTextureFilename),
1671 "Expected '%s' for pTextureFilename, got '%s'\n", expected[i].pTextureFilename, got[i].pTextureFilename);
1672 check_colorvalue_(line, "Diffuse: ", got[i].MatD3D.Diffuse, expected[i].MatD3D.Diffuse);
1673 check_colorvalue_(line, "Ambient: ", got[i].MatD3D.Ambient, expected[i].MatD3D.Ambient);
1674 check_colorvalue_(line, "Specular: ", got[i].MatD3D.Specular, expected[i].MatD3D.Specular);
1675 check_colorvalue_(line, "Emissive: ", got[i].MatD3D.Emissive, expected[i].MatD3D.Emissive);
1676 ok_(__FILE__,line)(expected[i].MatD3D.Power == got[i].MatD3D.Power,
1677 "Power: Expected %g, got %g\n", expected[i].MatD3D.Power, got[i].MatD3D.Power);
1681 #define check_generated_adjacency(mesh, got, epsilon) check_generated_adjacency_(__LINE__, mesh, got, epsilon)
1682 static void check_generated_adjacency_(int line, ID3DXMesh *mesh, const DWORD *got, FLOAT epsilon)
1684 DWORD *expected;
1685 DWORD num_faces = mesh->lpVtbl->GetNumFaces(mesh);
1686 HRESULT hr;
1688 expected = HeapAlloc(GetProcessHeap(), 0, num_faces * sizeof(DWORD) * 3);
1689 if (!expected) {
1690 skip_(__FILE__, line)("Out of memory\n");
1691 return;
1693 hr = mesh->lpVtbl->GenerateAdjacency(mesh, epsilon, expected);
1694 ok_(__FILE__, line)(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
1695 if (SUCCEEDED(hr))
1697 int i;
1698 for (i = 0; i < num_faces; i++)
1700 ok_(__FILE__, line)(expected[i * 3] == got[i * 3] &&
1701 expected[i * 3 + 1] == got[i * 3 + 1] &&
1702 expected[i * 3 + 2] == got[i * 3 + 2],
1703 "Face %u adjacencies: Expected (%u, %u, %u), got (%u, %u, %u)\n", i,
1704 expected[i * 3], expected[i * 3 + 1], expected[i * 3 + 2],
1705 got[i * 3], got[i * 3 + 1], got[i * 3 + 2]);
1708 HeapFree(GetProcessHeap(), 0, expected);
1711 #define check_generated_effects(materials, num_materials, effects) \
1712 check_generated_effects_(__LINE__, materials, num_materials, effects)
1713 static void check_generated_effects_(int line, const D3DXMATERIAL *materials, DWORD num_materials, const D3DXEFFECTINSTANCE *effects)
1715 int i;
1716 static const struct {
1717 const char *name;
1718 DWORD name_size;
1719 DWORD num_bytes;
1720 DWORD value_offset;
1721 } params[] = {
1722 #define EFFECT_TABLE_ENTRY(str, field) \
1723 {str, sizeof(str), sizeof(materials->MatD3D.field), offsetof(D3DXMATERIAL, MatD3D.field)}
1724 EFFECT_TABLE_ENTRY("Diffuse", Diffuse),
1725 EFFECT_TABLE_ENTRY("Power", Power),
1726 EFFECT_TABLE_ENTRY("Specular", Specular),
1727 EFFECT_TABLE_ENTRY("Emissive", Emissive),
1728 EFFECT_TABLE_ENTRY("Ambient", Ambient),
1729 #undef EFFECT_TABLE_ENTRY
1732 if (!num_materials) {
1733 ok_(__FILE__, line)(effects == NULL, "Expected NULL effects, got %p\n", effects);
1734 return;
1736 for (i = 0; i < num_materials; i++)
1738 int j;
1739 DWORD expected_num_defaults = ARRAY_SIZE(params) + (materials[i].pTextureFilename ? 1 : 0);
1741 ok_(__FILE__,line)(expected_num_defaults == effects[i].NumDefaults,
1742 "effect[%u] NumDefaults: Expected %u, got %u\n", i,
1743 expected_num_defaults, effects[i].NumDefaults);
1744 for (j = 0; j < min(ARRAY_SIZE(params), effects[i].NumDefaults); j++)
1746 int k;
1747 D3DXEFFECTDEFAULT *got_param = &effects[i].pDefaults[j];
1748 ok_(__FILE__,line)(!strcmp(params[j].name, got_param->pParamName),
1749 "effect[%u].pDefaults[%u].pParamName: Expected '%s', got '%s'\n", i, j,
1750 params[j].name, got_param->pParamName);
1751 ok_(__FILE__,line)(D3DXEDT_FLOATS == got_param->Type,
1752 "effect[%u].pDefaults[%u].Type: Expected %u, got %u\n", i, j,
1753 D3DXEDT_FLOATS, got_param->Type);
1754 ok_(__FILE__,line)(params[j].num_bytes == got_param->NumBytes,
1755 "effect[%u].pDefaults[%u].NumBytes: Expected %u, got %u\n", i, j,
1756 params[j].num_bytes, got_param->NumBytes);
1757 for (k = 0; k < min(params[j].num_bytes, got_param->NumBytes) / 4; k++)
1759 FLOAT expected = ((FLOAT*)((BYTE*)&materials[i] + params[j].value_offset))[k];
1760 FLOAT got = ((FLOAT*)got_param->pValue)[k];
1761 ok_(__FILE__,line)(compare(expected, got),
1762 "effect[%u].pDefaults[%u] float value %u: Expected %g, got %g\n", i, j, k, expected, got);
1765 if (effects[i].NumDefaults > ARRAY_SIZE(params)) {
1766 D3DXEFFECTDEFAULT *got_param = &effects[i].pDefaults[j];
1767 static const char *expected_name = "Texture0@Name";
1769 ok_(__FILE__,line)(!strcmp(expected_name, got_param->pParamName),
1770 "effect[%u].pDefaults[%u].pParamName: Expected '%s', got '%s'\n", i, j,
1771 expected_name, got_param->pParamName);
1772 ok_(__FILE__,line)(D3DXEDT_STRING == got_param->Type,
1773 "effect[%u].pDefaults[%u].Type: Expected %u, got %u\n", i, j,
1774 D3DXEDT_STRING, got_param->Type);
1775 if (materials[i].pTextureFilename) {
1776 ok_(__FILE__,line)(strlen(materials[i].pTextureFilename) + 1 == got_param->NumBytes,
1777 "effect[%u] texture filename length: Expected %u, got %u\n", i,
1778 (DWORD)strlen(materials[i].pTextureFilename) + 1, got_param->NumBytes);
1779 ok_(__FILE__,line)(!strcmp(materials[i].pTextureFilename, got_param->pValue),
1780 "effect[%u] texture filename: Expected '%s', got '%s'\n", i,
1781 materials[i].pTextureFilename, (char*)got_param->pValue);
1787 static char *strdupA(const char *p)
1789 char *ret;
1790 if (!p) return NULL;
1791 ret = HeapAlloc(GetProcessHeap(), 0, strlen(p) + 1);
1792 if (ret) strcpy(ret, p);
1793 return ret;
1796 static HRESULT CALLBACK ID3DXAllocateHierarchyImpl_DestroyFrame(ID3DXAllocateHierarchy *iface, LPD3DXFRAME frame)
1798 TRACECALLBACK("ID3DXAllocateHierarchyImpl_DestroyFrame(%p, %p)\n", iface, frame);
1799 if (frame) {
1800 HeapFree(GetProcessHeap(), 0, frame->Name);
1801 HeapFree(GetProcessHeap(), 0, frame);
1803 return D3D_OK;
1806 static HRESULT CALLBACK ID3DXAllocateHierarchyImpl_CreateFrame(ID3DXAllocateHierarchy *iface,
1807 const char *name, D3DXFRAME **new_frame)
1809 D3DXFRAME *frame;
1811 TRACECALLBACK("ID3DXAllocateHierarchyImpl_CreateFrame(%p, '%s', %p)\n", iface, name, new_frame);
1812 frame = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*frame));
1813 if (!frame)
1814 return E_OUTOFMEMORY;
1815 if (name) {
1816 frame->Name = strdupA(name);
1817 if (!frame->Name) {
1818 HeapFree(GetProcessHeap(), 0, frame);
1819 return E_OUTOFMEMORY;
1822 *new_frame = frame;
1823 return D3D_OK;
1826 static HRESULT destroy_mesh_container(LPD3DXMESHCONTAINER mesh_container)
1828 int i;
1830 if (!mesh_container)
1831 return D3D_OK;
1832 HeapFree(GetProcessHeap(), 0, mesh_container->Name);
1833 if (U(mesh_container->MeshData).pMesh)
1834 IUnknown_Release(U(mesh_container->MeshData).pMesh);
1835 if (mesh_container->pMaterials) {
1836 for (i = 0; i < mesh_container->NumMaterials; i++)
1837 HeapFree(GetProcessHeap(), 0, mesh_container->pMaterials[i].pTextureFilename);
1838 HeapFree(GetProcessHeap(), 0, mesh_container->pMaterials);
1840 if (mesh_container->pEffects) {
1841 for (i = 0; i < mesh_container->NumMaterials; i++) {
1842 HeapFree(GetProcessHeap(), 0, mesh_container->pEffects[i].pEffectFilename);
1843 if (mesh_container->pEffects[i].pDefaults) {
1844 int j;
1845 for (j = 0; j < mesh_container->pEffects[i].NumDefaults; j++) {
1846 HeapFree(GetProcessHeap(), 0, mesh_container->pEffects[i].pDefaults[j].pParamName);
1847 HeapFree(GetProcessHeap(), 0, mesh_container->pEffects[i].pDefaults[j].pValue);
1849 HeapFree(GetProcessHeap(), 0, mesh_container->pEffects[i].pDefaults);
1852 HeapFree(GetProcessHeap(), 0, mesh_container->pEffects);
1854 HeapFree(GetProcessHeap(), 0, mesh_container->pAdjacency);
1855 if (mesh_container->pSkinInfo)
1856 IUnknown_Release(mesh_container->pSkinInfo);
1857 HeapFree(GetProcessHeap(), 0, mesh_container);
1858 return D3D_OK;
1861 static HRESULT CALLBACK ID3DXAllocateHierarchyImpl_DestroyMeshContainer(ID3DXAllocateHierarchy *iface, LPD3DXMESHCONTAINER mesh_container)
1863 TRACECALLBACK("ID3DXAllocateHierarchyImpl_DestroyMeshContainer(%p, %p)\n", iface, mesh_container);
1864 return destroy_mesh_container(mesh_container);
1867 static HRESULT CALLBACK ID3DXAllocateHierarchyImpl_CreateMeshContainer(ID3DXAllocateHierarchy *iface,
1868 const char *name, const D3DXMESHDATA *mesh_data, const D3DXMATERIAL *materials,
1869 const D3DXEFFECTINSTANCE *effects, DWORD num_materials, const DWORD *adjacency,
1870 ID3DXSkinInfo *skin_info, D3DXMESHCONTAINER **new_mesh_container)
1872 LPD3DXMESHCONTAINER mesh_container = NULL;
1873 int i;
1875 TRACECALLBACK("ID3DXAllocateHierarchyImpl_CreateMeshContainer(%p, '%s', %u, %p, %p, %p, %d, %p, %p, %p)\n",
1876 iface, name, mesh_data->Type, U(*mesh_data).pMesh, materials, effects,
1877 num_materials, adjacency, skin_info, *new_mesh_container);
1879 mesh_container = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*mesh_container));
1880 if (!mesh_container)
1881 return E_OUTOFMEMORY;
1883 if (name) {
1884 mesh_container->Name = strdupA(name);
1885 if (!mesh_container->Name)
1886 goto error;
1889 mesh_container->NumMaterials = num_materials;
1890 if (num_materials) {
1891 mesh_container->pMaterials = HeapAlloc(GetProcessHeap(), 0, num_materials * sizeof(*materials));
1892 if (!mesh_container->pMaterials)
1893 goto error;
1895 memcpy(mesh_container->pMaterials, materials, num_materials * sizeof(*materials));
1896 for (i = 0; i < num_materials; i++)
1897 mesh_container->pMaterials[i].pTextureFilename = NULL;
1898 for (i = 0; i < num_materials; i++) {
1899 if (materials[i].pTextureFilename) {
1900 mesh_container->pMaterials[i].pTextureFilename = strdupA(materials[i].pTextureFilename);
1901 if (!mesh_container->pMaterials[i].pTextureFilename)
1902 goto error;
1906 mesh_container->pEffects = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, num_materials * sizeof(*effects));
1907 if (!mesh_container->pEffects)
1908 goto error;
1909 for (i = 0; i < num_materials; i++) {
1910 int j;
1911 const D3DXEFFECTINSTANCE *effect_src = &effects[i];
1912 D3DXEFFECTINSTANCE *effect_dest = &mesh_container->pEffects[i];
1914 if (effect_src->pEffectFilename) {
1915 effect_dest->pEffectFilename = strdupA(effect_src->pEffectFilename);
1916 if (!effect_dest->pEffectFilename)
1917 goto error;
1919 effect_dest->pDefaults = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1920 effect_src->NumDefaults * sizeof(*effect_src->pDefaults));
1921 if (!effect_dest->pDefaults)
1922 goto error;
1923 effect_dest->NumDefaults = effect_src->NumDefaults;
1924 for (j = 0; j < effect_src->NumDefaults; j++) {
1925 const D3DXEFFECTDEFAULT *default_src = &effect_src->pDefaults[j];
1926 D3DXEFFECTDEFAULT *default_dest = &effect_dest->pDefaults[j];
1928 if (default_src->pParamName) {
1929 default_dest->pParamName = strdupA(default_src->pParamName);
1930 if (!default_dest->pParamName)
1931 goto error;
1933 default_dest->NumBytes = default_src->NumBytes;
1934 default_dest->Type = default_src->Type;
1935 default_dest->pValue = HeapAlloc(GetProcessHeap(), 0, default_src->NumBytes);
1936 memcpy(default_dest->pValue, default_src->pValue, default_src->NumBytes);
1941 ok(adjacency != NULL, "Expected non-NULL adjacency, got NULL\n");
1942 if (adjacency) {
1943 if (mesh_data->Type == D3DXMESHTYPE_MESH || mesh_data->Type == D3DXMESHTYPE_PMESH) {
1944 ID3DXBaseMesh *basemesh = (ID3DXBaseMesh*)U(*mesh_data).pMesh;
1945 DWORD num_faces = basemesh->lpVtbl->GetNumFaces(basemesh);
1946 size_t size = num_faces * sizeof(DWORD) * 3;
1947 mesh_container->pAdjacency = HeapAlloc(GetProcessHeap(), 0, size);
1948 if (!mesh_container->pAdjacency)
1949 goto error;
1950 memcpy(mesh_container->pAdjacency, adjacency, size);
1951 } else {
1952 ok(mesh_data->Type == D3DXMESHTYPE_PATCHMESH, "Unknown mesh type %u\n", mesh_data->Type);
1953 if (mesh_data->Type == D3DXMESHTYPE_PATCHMESH)
1954 trace("FIXME: copying adjacency data for patch mesh not implemented\n");
1958 memcpy(&mesh_container->MeshData, mesh_data, sizeof(*mesh_data));
1959 if (U(*mesh_data).pMesh)
1960 IUnknown_AddRef(U(*mesh_data).pMesh);
1961 if (skin_info) {
1962 mesh_container->pSkinInfo = skin_info;
1963 skin_info->lpVtbl->AddRef(skin_info);
1965 *new_mesh_container = mesh_container;
1967 return S_OK;
1968 error:
1969 destroy_mesh_container(mesh_container);
1970 return E_OUTOFMEMORY;
1973 static ID3DXAllocateHierarchyVtbl ID3DXAllocateHierarchyImpl_Vtbl = {
1974 ID3DXAllocateHierarchyImpl_CreateFrame,
1975 ID3DXAllocateHierarchyImpl_CreateMeshContainer,
1976 ID3DXAllocateHierarchyImpl_DestroyFrame,
1977 ID3DXAllocateHierarchyImpl_DestroyMeshContainer,
1979 static ID3DXAllocateHierarchy alloc_hier = { &ID3DXAllocateHierarchyImpl_Vtbl };
1981 #define test_LoadMeshFromX(device, xfile_str, vertex_array, fvf, index_array, materials_array, check_adjacency) \
1982 test_LoadMeshFromX_(__LINE__, device, xfile_str, sizeof(xfile_str) - 1, vertex_array, ARRAY_SIZE(vertex_array), fvf, \
1983 index_array, ARRAY_SIZE(index_array), sizeof(*index_array), materials_array, ARRAY_SIZE(materials_array), \
1984 check_adjacency);
1985 static void test_LoadMeshFromX_(int line, IDirect3DDevice9 *device, const char *xfile_str, size_t xfile_strlen,
1986 const void *vertices, DWORD num_vertices, DWORD fvf, const void *indices, DWORD num_indices, size_t index_size,
1987 const D3DXMATERIAL *expected_materials, DWORD expected_num_materials, BOOL check_adjacency)
1989 HRESULT hr;
1990 ID3DXBuffer *materials = NULL;
1991 ID3DXBuffer *effects = NULL;
1992 ID3DXBuffer *adjacency = NULL;
1993 ID3DXMesh *mesh = NULL;
1994 DWORD num_materials = 0;
1996 /* Adjacency is not checked when the X file contains multiple meshes,
1997 * since calling GenerateAdjacency on the merged mesh is not equivalent
1998 * to calling GenerateAdjacency on the individual meshes and then merging
1999 * the adjacency data. */
2000 hr = D3DXLoadMeshFromXInMemory(xfile_str, xfile_strlen, D3DXMESH_MANAGED, device,
2001 check_adjacency ? &adjacency : NULL, &materials, &effects, &num_materials, &mesh);
2002 ok_(__FILE__,line)(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2003 if (SUCCEEDED(hr)) {
2004 D3DXMATERIAL *materials_ptr = materials ? ID3DXBuffer_GetBufferPointer(materials) : NULL;
2005 D3DXEFFECTINSTANCE *effects_ptr = effects ? ID3DXBuffer_GetBufferPointer(effects) : NULL;
2006 DWORD *adjacency_ptr = check_adjacency ? ID3DXBuffer_GetBufferPointer(adjacency) : NULL;
2008 check_vertex_buffer_(line, mesh, vertices, num_vertices, fvf);
2009 check_index_buffer_(line, mesh, indices, num_indices, index_size);
2010 check_materials_(line, materials_ptr, num_materials, expected_materials, expected_num_materials);
2011 check_generated_effects_(line, materials_ptr, num_materials, effects_ptr);
2012 if (check_adjacency)
2013 check_generated_adjacency_(line, mesh, adjacency_ptr, 0.0f);
2015 if (materials) ID3DXBuffer_Release(materials);
2016 if (effects) ID3DXBuffer_Release(effects);
2017 if (adjacency) ID3DXBuffer_Release(adjacency);
2018 IUnknown_Release(mesh);
2022 static void D3DXLoadMeshTest(void)
2024 static const char empty_xfile[] = "xof 0303txt 0032";
2025 /*________________________*/
2026 static const char simple_xfile[] =
2027 "xof 0303txt 0032"
2028 "Mesh {"
2029 "3;"
2030 "0.0; 0.0; 0.0;,"
2031 "0.0; 1.0; 0.0;,"
2032 "1.0; 1.0; 0.0;;"
2033 "1;"
2034 "3; 0, 1, 2;;"
2035 "}";
2036 static const WORD simple_index_buffer[] = {0, 1, 2};
2037 static const D3DXVECTOR3 simple_vertex_buffer[] = {
2038 {0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {1.0, 1.0, 0.0}
2040 const DWORD simple_fvf = D3DFVF_XYZ;
2041 static const char framed_xfile[] =
2042 "xof 0303txt 0032"
2043 "Frame {"
2044 "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;; }"
2045 "FrameTransformMatrix {" /* translation (0.0, 0.0, 2.0) */
2046 "1.0, 0.0, 0.0, 0.0,"
2047 "0.0, 1.0, 0.0, 0.0,"
2048 "0.0, 0.0, 1.0, 0.0,"
2049 "0.0, 0.0, 2.0, 1.0;;"
2051 "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;; }"
2052 "FrameTransformMatrix {" /* translation (0.0, 0.0, 3.0) */
2053 "1.0, 0.0, 0.0, 0.0,"
2054 "0.0, 1.0, 0.0, 0.0,"
2055 "0.0, 0.0, 1.0, 0.0,"
2056 "0.0, 0.0, 3.0, 1.0;;"
2058 "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;; }"
2059 "}";
2060 static const WORD framed_index_buffer[] = { 0, 1, 2 };
2061 static const D3DXVECTOR3 framed_vertex_buffers[3][3] = {
2062 {{0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {1.0, 1.0, 0.0}},
2063 {{0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {2.0, 1.0, 0.0}},
2064 {{0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {3.0, 1.0, 0.0}},
2066 static const WORD merged_index_buffer[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
2067 /* frame transforms accumulates for D3DXLoadMeshFromX */
2068 static const D3DXVECTOR3 merged_vertex_buffer[] = {
2069 {0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {1.0, 1.0, 0.0},
2070 {0.0, 0.0, 2.0}, {0.0, 1.0, 2.0}, {2.0, 1.0, 2.0},
2071 {0.0, 0.0, 5.0}, {0.0, 1.0, 5.0}, {3.0, 1.0, 5.0},
2073 const DWORD framed_fvf = D3DFVF_XYZ;
2074 /*________________________*/
2075 static const char box_xfile[] =
2076 "xof 0303txt 0032"
2077 "Mesh {"
2078 "8;" /* DWORD nVertices; */
2079 /* array Vector vertices[nVertices]; */
2080 "0.0; 0.0; 0.0;,"
2081 "0.0; 0.0; 1.0;,"
2082 "0.0; 1.0; 0.0;,"
2083 "0.0; 1.0; 1.0;,"
2084 "1.0; 0.0; 0.0;,"
2085 "1.0; 0.0; 1.0;,"
2086 "1.0; 1.0; 0.0;,"
2087 "1.0; 1.0; 1.0;;"
2088 "6;" /* DWORD nFaces; */
2089 /* array MeshFace faces[nFaces]; */
2090 "4; 0, 1, 3, 2;," /* (left side) */
2091 "4; 2, 3, 7, 6;," /* (top side) */
2092 "4; 6, 7, 5, 4;," /* (right side) */
2093 "4; 1, 0, 4, 5;," /* (bottom side) */
2094 "4; 1, 5, 7, 3;," /* (back side) */
2095 "4; 0, 2, 6, 4;;" /* (front side) */
2096 "MeshNormals {"
2097 "6;" /* DWORD nNormals; */
2098 /* array Vector normals[nNormals]; */
2099 "-1.0; 0.0; 0.0;,"
2100 "0.0; 1.0; 0.0;,"
2101 "1.0; 0.0; 0.0;,"
2102 "0.0; -1.0; 0.0;,"
2103 "0.0; 0.0; 1.0;,"
2104 "0.0; 0.0; -1.0;;"
2105 "6;" /* DWORD nFaceNormals; */
2106 /* array MeshFace faceNormals[nFaceNormals]; */
2107 "4; 0, 0, 0, 0;,"
2108 "4; 1, 1, 1, 1;,"
2109 "4; 2, 2, 2, 2;,"
2110 "4; 3, 3, 3, 3;,"
2111 "4; 4, 4, 4, 4;,"
2112 "4; 5, 5, 5, 5;;"
2114 "MeshMaterialList materials {"
2115 "2;" /* DWORD nMaterials; */
2116 "6;" /* DWORD nFaceIndexes; */
2117 /* array DWORD faceIndexes[nFaceIndexes]; */
2118 "0, 0, 0, 1, 1, 1;;"
2119 "Material {"
2120 /* ColorRGBA faceColor; */
2121 "0.0; 0.0; 1.0; 1.0;;"
2122 /* FLOAT power; */
2123 "0.5;"
2124 /* ColorRGB specularColor; */
2125 "1.0; 1.0; 1.0;;"
2126 /* ColorRGB emissiveColor; */
2127 "0.0; 0.0; 0.0;;"
2129 "Material {"
2130 /* ColorRGBA faceColor; */
2131 "1.0; 1.0; 1.0; 1.0;;"
2132 /* FLOAT power; */
2133 "1.0;"
2134 /* ColorRGB specularColor; */
2135 "1.0; 1.0; 1.0;;"
2136 /* ColorRGB emissiveColor; */
2137 "0.0; 0.0; 0.0;;"
2138 "TextureFilename { \"texture.jpg\"; }"
2141 "MeshVertexColors {"
2142 "8;" /* DWORD nVertexColors; */
2143 /* array IndexedColor vertexColors[nVertexColors]; */
2144 "0; 0.0; 0.0; 0.0; 0.0;;"
2145 "1; 0.0; 0.0; 1.0; 0.1;;"
2146 "2; 0.0; 1.0; 0.0; 0.2;;"
2147 "3; 0.0; 1.0; 1.0; 0.3;;"
2148 "4; 1.0; 0.0; 0.0; 0.4;;"
2149 "5; 1.0; 0.0; 1.0; 0.5;;"
2150 "6; 1.0; 1.0; 0.0; 0.6;;"
2151 "7; 1.0; 1.0; 1.0; 0.7;;"
2153 "MeshTextureCoords {"
2154 "8;" /* DWORD nTextureCoords; */
2155 /* array Coords2d textureCoords[nTextureCoords]; */
2156 "0.0; 1.0;,"
2157 "1.0; 1.0;,"
2158 "0.0; 0.0;,"
2159 "1.0; 0.0;,"
2160 "1.0; 1.0;,"
2161 "0.0; 1.0;,"
2162 "1.0; 0.0;,"
2163 "0.0; 0.0;;"
2165 "}";
2166 static const WORD box_index_buffer[] = {
2167 0, 1, 3,
2168 0, 3, 2,
2169 8, 9, 7,
2170 8, 7, 6,
2171 10, 11, 5,
2172 10, 5, 4,
2173 12, 13, 14,
2174 12, 14, 15,
2175 16, 17, 18,
2176 16, 18, 19,
2177 20, 21, 22,
2178 20, 22, 23,
2180 static const struct {
2181 D3DXVECTOR3 position;
2182 D3DXVECTOR3 normal;
2183 D3DCOLOR diffuse;
2184 D3DXVECTOR2 tex_coords;
2185 } box_vertex_buffer[] = {
2186 {{0.0, 0.0, 0.0}, {-1.0, 0.0, 0.0}, 0x00000000, {0.0, 1.0}},
2187 {{0.0, 0.0, 1.0}, {-1.0, 0.0, 0.0}, 0x1a0000ff, {1.0, 1.0}},
2188 {{0.0, 1.0, 0.0}, {-1.0, 0.0, 0.0}, 0x3300ff00, {0.0, 0.0}},
2189 {{0.0, 1.0, 1.0}, {-1.0, 0.0, 0.0}, 0x4d00ffff, {1.0, 0.0}},
2190 {{1.0, 0.0, 0.0}, {1.0, 0.0, 0.0}, 0x66ff0000, {1.0, 1.0}},
2191 {{1.0, 0.0, 1.0}, {1.0, 0.0, 0.0}, 0x80ff00ff, {0.0, 1.0}},
2192 {{1.0, 1.0, 0.0}, {0.0, 1.0, 0.0}, 0x99ffff00, {1.0, 0.0}},
2193 {{1.0, 1.0, 1.0}, {0.0, 1.0, 0.0}, 0xb3ffffff, {0.0, 0.0}},
2194 {{0.0, 1.0, 0.0}, {0.0, 1.0, 0.0}, 0x3300ff00, {0.0, 0.0}},
2195 {{0.0, 1.0, 1.0}, {0.0, 1.0, 0.0}, 0x4d00ffff, {1.0, 0.0}},
2196 {{1.0, 1.0, 0.0}, {1.0, 0.0, 0.0}, 0x99ffff00, {1.0, 0.0}},
2197 {{1.0, 1.0, 1.0}, {1.0, 0.0, 0.0}, 0xb3ffffff, {0.0, 0.0}},
2198 {{0.0, 0.0, 1.0}, {0.0, -1.0, 0.0}, 0x1a0000ff, {1.0, 1.0}},
2199 {{0.0, 0.0, 0.0}, {0.0, -1.0, 0.0}, 0x00000000, {0.0, 1.0}},
2200 {{1.0, 0.0, 0.0}, {0.0, -1.0, 0.0}, 0x66ff0000, {1.0, 1.0}},
2201 {{1.0, 0.0, 1.0}, {0.0, -1.0, 0.0}, 0x80ff00ff, {0.0, 1.0}},
2202 {{0.0, 0.0, 1.0}, {0.0, 0.0, 1.0}, 0x1a0000ff, {1.0, 1.0}},
2203 {{1.0, 0.0, 1.0}, {0.0, 0.0, 1.0}, 0x80ff00ff, {0.0, 1.0}},
2204 {{1.0, 1.0, 1.0}, {0.0, 0.0, 1.0}, 0xb3ffffff, {0.0, 0.0}},
2205 {{0.0, 1.0, 1.0}, {0.0, 0.0, 1.0}, 0x4d00ffff, {1.0, 0.0}},
2206 {{0.0, 0.0, 0.0}, {0.0, 0.0, -1.0}, 0x00000000, {0.0, 1.0}},
2207 {{0.0, 1.0, 0.0}, {0.0, 0.0, -1.0}, 0x3300ff00, {0.0, 0.0}},
2208 {{1.0, 1.0, 0.0}, {0.0, 0.0, -1.0}, 0x99ffff00, {1.0, 0.0}},
2209 {{1.0, 0.0, 0.0}, {0.0, 0.0, -1.0}, 0x66ff0000, {1.0, 1.0}},
2211 static const D3DXMATERIAL box_materials[] = {
2214 {0.0, 0.0, 1.0, 1.0}, /* Diffuse */
2215 {0.0, 0.0, 0.0, 1.0}, /* Ambient */
2216 {1.0, 1.0, 1.0, 1.0}, /* Specular */
2217 {0.0, 0.0, 0.0, 1.0}, /* Emissive */
2218 0.5, /* Power */
2220 NULL, /* pTextureFilename */
2224 {1.0, 1.0, 1.0, 1.0}, /* Diffuse */
2225 {0.0, 0.0, 0.0, 1.0}, /* Ambient */
2226 {1.0, 1.0, 1.0, 1.0}, /* Specular */
2227 {0.0, 0.0, 0.0, 1.0}, /* Emissive */
2228 1.0, /* Power */
2230 (char *)"texture.jpg", /* pTextureFilename */
2233 static const char box_anim_xfile[] =
2234 "xof 0303txt 0032"
2235 "Mesh CubeMesh {"
2236 "8;" /* DWORD nVertices; */
2237 /* array Vector vertices[nVertices]; */
2238 "0.0; 0.0; 0.0;,"
2239 "0.0; 0.0; 1.0;,"
2240 "0.0; 1.0; 0.0;,"
2241 "0.0; 1.0; 1.0;,"
2242 "1.0; 0.0; 0.0;,"
2243 "1.0; 0.0; 1.0;,"
2244 "1.0; 1.0; 0.0;,"
2245 "1.0; 1.0; 1.0;;"
2246 "6;" /* DWORD nFaces; */
2247 /* array MeshFace faces[nFaces]; */
2248 "4; 0, 1, 3, 2;," /* left side */
2249 "4; 2, 3, 7, 6;," /* top side */
2250 "4; 6, 7, 5, 4;," /* right side */
2251 "4; 1, 0, 4, 5;," /* bottom side */
2252 "4; 1, 5, 7, 3;," /* back side */
2253 "4; 0, 2, 6, 4;;" /* front side */
2254 "MeshNormals {"
2255 "6;" /* DWORD nNormals; */
2256 /* array Vector normals[nNormals]; */
2257 "-1.0; 0.0; 0.0;,"
2258 "0.0; 1.0; 0.0;,"
2259 "1.0; 0.0; 0.0;,"
2260 "0.0; -1.0; 0.0;,"
2261 "0.0; 0.0; 1.0;,"
2262 "0.0; 0.0; -1.0;;"
2263 "6;" /* DWORD nFaceNormals; */
2264 /* array MeshFace faceNormals[nFaceNormals]; */
2265 "4; 0, 0, 0, 0;,"
2266 "4; 1, 1, 1, 1;,"
2267 "4; 2, 2, 2, 2;,"
2268 "4; 3, 3, 3, 3;,"
2269 "4; 4, 4, 4, 4;,"
2270 "4; 5, 5, 5, 5;;"
2272 "MeshMaterialList materials {"
2273 "2;" /* DWORD nMaterials; */
2274 "6;" /* DWORD nFaceIndexes; */
2275 /* array DWORD faceIndexes[nFaceIndexes]; */
2276 "0, 0, 0, 1, 1, 1;;"
2277 "Material {"
2278 /* ColorRGBA faceColor; */
2279 "0.0; 0.0; 1.0; 1.0;;"
2280 /* FLOAT power; */
2281 "0.5;"
2282 /* ColorRGB specularColor; */
2283 "1.0; 1.0; 1.0;;"
2284 /* ColorRGB emissiveColor; */
2285 "0.0; 0.0; 0.0;;"
2287 "Material {"
2288 /* ColorRGBA faceColor; */
2289 "1.0; 1.0; 1.0; 1.0;;"
2290 /* FLOAT power; */
2291 "1.0;"
2292 /* ColorRGB specularColor; */
2293 "1.0; 1.0; 1.0;;"
2294 /* ColorRGB emissiveColor; */
2295 "0.0; 0.0; 0.0;;"
2296 "TextureFilename { \"texture.jpg\"; }"
2299 "MeshVertexColors {"
2300 "8;" /* DWORD nVertexColors; */
2301 /* array IndexedColor vertexColors[nVertexColors]; */
2302 "0; 0.0; 0.0; 0.0; 0.0;;"
2303 "1; 0.0; 0.0; 1.0; 0.1;;"
2304 "2; 0.0; 1.0; 0.0; 0.2;;"
2305 "3; 0.0; 1.0; 1.0; 0.3;;"
2306 "4; 1.0; 0.0; 0.0; 0.4;;"
2307 "5; 1.0; 0.0; 1.0; 0.5;;"
2308 "6; 1.0; 1.0; 0.0; 0.6;;"
2309 "7; 1.0; 1.0; 1.0; 0.7;;"
2311 "MeshTextureCoords {"
2312 "8;" /* DWORD nTextureCoords; */
2313 /* array Coords2d textureCoords[nTextureCoords]; */
2314 "0.0; 1.0;,"
2315 "1.0; 1.0;,"
2316 "0.0; 0.0;,"
2317 "1.0; 0.0;,"
2318 "1.0; 1.0;,"
2319 "0.0; 1.0;,"
2320 "1.0; 0.0;,"
2321 "0.0; 0.0;;"
2324 "Frame CubeFrame {"
2325 "FrameTransformMatrix {"
2326 /* Matrix4x4 frameMatrix; */
2327 "1.0, 0.0, 0.0, 0.0,"
2328 "0.0, 1.0, 0.0, 0.0,"
2329 "0.0, 0.0, 1.0, 0.0,"
2330 "0.0, 0.0, 0.0, 1.0;;"
2332 "{CubeMesh}"
2334 "AnimationSet AnimationSet0 {"
2335 "Animation Animation0 {"
2336 "{CubeFrame}"
2337 "AnimationKey {"
2338 "2;" /* DWORD keyType; */
2339 "9;" /* DWORD nKeys; */
2340 /* array TimedFloatKeys keys[nKeys]; */
2341 "10; 3; -100.0, 0.0, 0.0;;,"
2342 "20; 3; -75.0, 0.0, 0.0;;,"
2343 "30; 3; -50.0, 0.0, 0.0;;,"
2344 "40; 3; -25.5, 0.0, 0.0;;,"
2345 "50; 3; 0.0, 0.0, 0.0;;,"
2346 "60; 3; 25.5, 0.0, 0.0;;,"
2347 "70; 3; 50.0, 0.0, 0.0;;,"
2348 "80; 3; 75.5, 0.0, 0.0;;,"
2349 "90; 3; 100.0, 0.0, 0.0;;;"
2352 "}";
2354 const DWORD box_fvf = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_TEX1;
2355 /*________________________*/
2356 static const D3DXMATERIAL default_materials[] = {
2359 {0.5, 0.5, 0.5, 0.0}, /* Diffuse */
2360 {0.0, 0.0, 0.0, 0.0}, /* Ambient */
2361 {0.5, 0.5, 0.5, 0.0}, /* Specular */
2362 {0.0, 0.0, 0.0, 0.0}, /* Emissive */
2363 0.0, /* Power */
2365 NULL, /* pTextureFilename */
2368 HRESULT hr;
2369 IDirect3DDevice9 *device = NULL;
2370 ID3DXMesh *mesh = NULL;
2371 D3DXFRAME *frame_hier = NULL;
2372 D3DXMATRIX transform;
2373 struct test_context *test_context;
2374 ID3DXAnimationController *controller;
2376 if (!(test_context = new_test_context()))
2378 skip("Couldn't create test context\n");
2379 return;
2381 device = test_context->device;
2383 hr = D3DXLoadMeshHierarchyFromXInMemory(NULL, sizeof(simple_xfile) - 1,
2384 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
2385 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2387 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, 0,
2388 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
2389 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2391 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1,
2392 D3DXMESH_MANAGED, NULL, &alloc_hier, NULL, &frame_hier, NULL);
2393 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2395 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1,
2396 D3DXMESH_MANAGED, device, NULL, NULL, &frame_hier, NULL);
2397 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2399 hr = D3DXLoadMeshHierarchyFromXInMemory(empty_xfile, sizeof(empty_xfile) - 1,
2400 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
2401 ok(hr == E_FAIL, "Expected E_FAIL, got %#x\n", hr);
2403 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1,
2404 D3DXMESH_MANAGED, device, &alloc_hier, NULL, NULL, NULL);
2405 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2407 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1,
2408 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
2409 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2410 if (SUCCEEDED(hr)) {
2411 D3DXMESHCONTAINER *container = frame_hier->pMeshContainer;
2413 ok(frame_hier->Name == NULL, "Expected NULL, got '%s'\n", frame_hier->Name);
2414 D3DXMatrixIdentity(&transform);
2415 check_matrix(&frame_hier->TransformationMatrix, &transform);
2417 ok(!strcmp(container->Name, ""), "Expected '', got '%s'\n", container->Name);
2418 ok(container->MeshData.Type == D3DXMESHTYPE_MESH, "Expected %d, got %d\n",
2419 D3DXMESHTYPE_MESH, container->MeshData.Type);
2420 mesh = U(container->MeshData).pMesh;
2421 check_vertex_buffer(mesh, simple_vertex_buffer, ARRAY_SIZE(simple_vertex_buffer), simple_fvf);
2422 check_index_buffer(mesh, simple_index_buffer, ARRAY_SIZE(simple_index_buffer), sizeof(*simple_index_buffer));
2423 check_materials(container->pMaterials, container->NumMaterials, NULL, 0);
2424 check_generated_effects(container->pMaterials, container->NumMaterials, container->pEffects);
2425 check_generated_adjacency(mesh, container->pAdjacency, 0.0f);
2426 hr = D3DXFrameDestroy(frame_hier, &alloc_hier);
2427 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2428 frame_hier = NULL;
2431 controller = (ID3DXAnimationController *)0xdeadbeef;
2432 hr = D3DXLoadMeshHierarchyFromXInMemory(box_anim_xfile, sizeof(box_anim_xfile) - 1,
2433 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, &controller);
2434 todo_wine ok(hr == D3D_OK, "Expected D3D_OK, got %#x.\n", hr);
2435 if (SUCCEEDED(hr))
2437 ok(controller != NULL, "Animation Controller NULL.\n");
2439 hr = D3DXFrameDestroy(frame_hier, &alloc_hier);
2440 ok(hr == D3D_OK, "Expected D3D_OK, got %#x.\n", hr);
2441 if (controller)
2442 controller->lpVtbl->Release(controller);
2444 frame_hier = NULL;
2447 controller = (ID3DXAnimationController *)0xdeadbeef;
2448 hr = D3DXLoadMeshHierarchyFromXInMemory(box_xfile, sizeof(box_xfile) - 1,
2449 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, &controller);
2450 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2451 if (SUCCEEDED(hr))
2453 D3DXMESHCONTAINER *container = frame_hier->pMeshContainer;
2455 ok(!controller, "Animation Controller returned.\n");
2456 ok(frame_hier->Name == NULL, "Expected NULL, got '%s'\n", frame_hier->Name);
2457 D3DXMatrixIdentity(&transform);
2458 check_matrix(&frame_hier->TransformationMatrix, &transform);
2460 ok(!strcmp(container->Name, ""), "Expected '', got '%s'\n", container->Name);
2461 ok(container->MeshData.Type == D3DXMESHTYPE_MESH, "Expected %d, got %d\n",
2462 D3DXMESHTYPE_MESH, container->MeshData.Type);
2463 mesh = U(container->MeshData).pMesh;
2464 check_vertex_buffer(mesh, box_vertex_buffer, ARRAY_SIZE(box_vertex_buffer), box_fvf);
2465 check_index_buffer(mesh, box_index_buffer, ARRAY_SIZE(box_index_buffer), sizeof(*box_index_buffer));
2466 check_materials(container->pMaterials, container->NumMaterials, box_materials, ARRAY_SIZE(box_materials));
2467 check_generated_effects(container->pMaterials, container->NumMaterials, container->pEffects);
2468 check_generated_adjacency(mesh, container->pAdjacency, 0.0f);
2469 hr = D3DXFrameDestroy(frame_hier, &alloc_hier);
2470 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2471 frame_hier = NULL;
2474 hr = D3DXLoadMeshHierarchyFromXInMemory(framed_xfile, sizeof(framed_xfile) - 1,
2475 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
2476 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2477 if (SUCCEEDED(hr)) {
2478 D3DXMESHCONTAINER *container = frame_hier->pMeshContainer;
2479 int i;
2481 ok(!strcmp(frame_hier->Name, ""), "Expected '', got '%s'\n", frame_hier->Name);
2482 /* last frame transform replaces the first */
2483 D3DXMatrixIdentity(&transform);
2484 U(transform).m[3][2] = 3.0;
2485 check_matrix(&frame_hier->TransformationMatrix, &transform);
2487 for (i = 0; i < 3; i++) {
2488 ok(!strcmp(container->Name, ""), "Expected '', got '%s'\n", container->Name);
2489 ok(container->MeshData.Type == D3DXMESHTYPE_MESH, "Expected %d, got %d\n",
2490 D3DXMESHTYPE_MESH, container->MeshData.Type);
2491 mesh = U(container->MeshData).pMesh;
2492 check_vertex_buffer(mesh, framed_vertex_buffers[i], ARRAY_SIZE(framed_vertex_buffers[0]), framed_fvf);
2493 check_index_buffer(mesh, framed_index_buffer, ARRAY_SIZE(framed_index_buffer), sizeof(*framed_index_buffer));
2494 check_materials(container->pMaterials, container->NumMaterials, NULL, 0);
2495 check_generated_effects(container->pMaterials, container->NumMaterials, container->pEffects);
2496 check_generated_adjacency(mesh, container->pAdjacency, 0.0f);
2497 container = container->pNextMeshContainer;
2499 ok(container == NULL, "Expected NULL, got %p\n", container);
2500 hr = D3DXFrameDestroy(frame_hier, &alloc_hier);
2501 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2502 frame_hier = NULL;
2506 hr = D3DXLoadMeshFromXInMemory(NULL, 0, D3DXMESH_MANAGED,
2507 device, NULL, NULL, NULL, NULL, &mesh);
2508 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2510 hr = D3DXLoadMeshFromXInMemory(NULL, sizeof(simple_xfile) - 1, D3DXMESH_MANAGED,
2511 device, NULL, NULL, NULL, NULL, &mesh);
2512 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2514 hr = D3DXLoadMeshFromXInMemory(simple_xfile, 0, D3DXMESH_MANAGED,
2515 device, NULL, NULL, NULL, NULL, &mesh);
2516 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2518 hr = D3DXLoadMeshFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1, D3DXMESH_MANAGED,
2519 device, NULL, NULL, NULL, NULL, NULL);
2520 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2522 hr = D3DXLoadMeshFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1, D3DXMESH_MANAGED,
2523 NULL, NULL, NULL, NULL, NULL, &mesh);
2524 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2526 hr = D3DXLoadMeshFromXInMemory(empty_xfile, sizeof(empty_xfile) - 1, D3DXMESH_MANAGED,
2527 device, NULL, NULL, NULL, NULL, &mesh);
2528 ok(hr == E_FAIL, "Expected E_FAIL, got %#x\n", hr);
2530 hr = D3DXLoadMeshFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1, D3DXMESH_MANAGED,
2531 device, NULL, NULL, NULL, NULL, &mesh);
2532 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2533 if (SUCCEEDED(hr))
2534 IUnknown_Release(mesh);
2536 test_LoadMeshFromX(device, simple_xfile, simple_vertex_buffer, simple_fvf, simple_index_buffer, default_materials, TRUE);
2537 test_LoadMeshFromX(device, box_xfile, box_vertex_buffer, box_fvf, box_index_buffer, box_materials, TRUE);
2538 test_LoadMeshFromX(device, framed_xfile, merged_vertex_buffer, framed_fvf, merged_index_buffer, default_materials, FALSE);
2540 free_test_context(test_context);
2543 static BOOL compute_box(struct mesh *mesh, float width, float height, float depth)
2545 unsigned int i, face;
2546 static const D3DXVECTOR3 unit_box[] =
2548 {-1.0f, -1.0f, -1.0f}, {-1.0f, -1.0f, 1.0f}, {-1.0f, 1.0f, 1.0f}, {-1.0f, 1.0f, -1.0f},
2549 {-1.0f, 1.0f, -1.0f}, {-1.0f, 1.0f, 1.0f}, { 1.0f, 1.0f, 1.0f}, { 1.0f, 1.0f, -1.0f},
2550 { 1.0f, 1.0f, -1.0f}, { 1.0f, 1.0f, 1.0f}, { 1.0f, -1.0f, 1.0f}, { 1.0f, -1.0f, -1.0f},
2551 {-1.0f, -1.0f, 1.0f}, {-1.0f, -1.0f, -1.0f}, { 1.0f, -1.0f, -1.0f}, { 1.0f, -1.0f, 1.0f},
2552 {-1.0f, -1.0f, 1.0f}, { 1.0f, -1.0f, 1.0f}, { 1.0f, 1.0f, 1.0f}, {-1.0f, 1.0f, 1.0f},
2553 {-1.0f, -1.0f, -1.0f}, {-1.0f, 1.0f, -1.0f}, { 1.0f, 1.0f, -1.0f}, { 1.0f, -1.0f, -1.0f}
2555 static const D3DXVECTOR3 normals[] =
2557 {-1.0f, 0.0f, 0.0f}, { 0.0f, 1.0f, 0.0f}, { 1.0f, 0.0f, 0.0f},
2558 { 0.0f, -1.0f, 0.0f}, { 0.0f, 0.0f, 1.0f}, { 0.0f, 0.0f, -1.0f}
2561 if (!new_mesh(mesh, 24, 12))
2563 return FALSE;
2566 width /= 2.0f;
2567 height /= 2.0f;
2568 depth /= 2.0f;
2570 for (i = 0; i < 24; i++)
2572 mesh->vertices[i].position.x = width * unit_box[i].x;
2573 mesh->vertices[i].position.y = height * unit_box[i].y;
2574 mesh->vertices[i].position.z = depth * unit_box[i].z;
2575 mesh->vertices[i].normal.x = normals[i / 4].x;
2576 mesh->vertices[i].normal.y = normals[i / 4].y;
2577 mesh->vertices[i].normal.z = normals[i / 4].z;
2580 face = 0;
2581 for (i = 0; i < 12; i++)
2583 mesh->faces[i][0] = face++;
2584 mesh->faces[i][1] = face++;
2585 mesh->faces[i][2] = (i % 2) ? face - 4 : face;
2588 return TRUE;
2591 static void test_box(IDirect3DDevice9 *device, float width, float height, float depth)
2593 HRESULT hr;
2594 ID3DXMesh *box;
2595 struct mesh mesh;
2596 char name[256];
2598 hr = D3DXCreateBox(device, width, height, depth, &box, NULL);
2599 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
2600 if (hr != D3D_OK)
2602 skip("Couldn't create box\n");
2603 return;
2606 if (!compute_box(&mesh, width, height, depth))
2608 skip("Couldn't create mesh\n");
2609 box->lpVtbl->Release(box);
2610 return;
2613 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
2615 sprintf(name, "box (%g, %g, %g)", width, height, depth);
2616 compare_mesh(name, box, &mesh);
2618 free_mesh(&mesh);
2620 box->lpVtbl->Release(box);
2622 static void D3DXCreateBoxTest(void)
2624 HRESULT hr;
2625 IDirect3DDevice9* device;
2626 ID3DXMesh* box;
2627 ID3DXBuffer* ppBuffer;
2628 DWORD *buffer;
2629 static const DWORD adjacency[36]=
2630 {6, 9, 1, 2, 10, 0,
2631 1, 9, 3, 4, 10, 2,
2632 3, 8, 5, 7, 11, 4,
2633 0, 11, 7, 5, 8, 6,
2634 7, 4, 9, 2, 0, 8,
2635 1, 3, 11, 5, 6, 10};
2636 unsigned int i;
2637 struct test_context *test_context;
2639 if (!(test_context = new_test_context()))
2641 skip("Couldn't create test context\n");
2642 return;
2644 device = test_context->device;
2646 hr = D3DXCreateBox(device,2.0f,20.0f,4.9f,NULL, &ppBuffer);
2647 ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2649 hr = D3DXCreateBox(NULL,22.0f,20.0f,4.9f,&box, &ppBuffer);
2650 ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2652 hr = D3DXCreateBox(device,-2.0f,20.0f,4.9f,&box, &ppBuffer);
2653 ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2655 hr = D3DXCreateBox(device,22.0f,-20.0f,4.9f,&box, &ppBuffer);
2656 ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2658 hr = D3DXCreateBox(device,22.0f,20.0f,-4.9f,&box, &ppBuffer);
2659 ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2661 ppBuffer = NULL;
2662 hr = D3DXCreateBox(device,10.9f,20.0f,4.9f,&box, &ppBuffer);
2663 ok(hr==D3D_OK, "Expected D3D_OK, received %#x\n", hr);
2665 buffer = ID3DXBuffer_GetBufferPointer(ppBuffer);
2666 for(i=0; i<36; i++)
2667 ok(adjacency[i]==buffer[i], "expected adjacency %d: %#x, received %#x\n",i,adjacency[i], buffer[i]);
2669 box->lpVtbl->Release(box);
2670 ID3DXBuffer_Release(ppBuffer);
2672 test_box(device, 10.9f, 20.0f, 4.9f);
2674 free_test_context(test_context);
2677 static BOOL compute_polygon(struct mesh *mesh, float length, unsigned int sides)
2679 unsigned int i;
2680 float scale;
2682 if (!new_mesh(mesh, sides + 1, sides))
2683 return FALSE;
2685 scale = 0.5f * length / sinf(D3DX_PI / sides);
2687 mesh->vertices[0].position.x = 0.0f;
2688 mesh->vertices[0].position.y = 0.0f;
2689 mesh->vertices[0].position.z = 0.0f;
2690 mesh->vertices[0].normal.x = 0.0f;
2691 mesh->vertices[0].normal.y = 0.0f;
2692 mesh->vertices[0].normal.z = 1.0f;
2694 for (i = 0; i < sides; ++i)
2696 mesh->vertices[i + 1].position.x = cosf(2.0f * D3DX_PI * i / sides) * scale;
2697 mesh->vertices[i + 1].position.y = sinf(2.0f * D3DX_PI * i / sides) * scale;
2698 mesh->vertices[i + 1].position.z = 0.0f;
2699 mesh->vertices[i + 1].normal.x = 0.0f;
2700 mesh->vertices[i + 1].normal.y = 0.0f;
2701 mesh->vertices[i + 1].normal.z = 1.0f;
2703 mesh->faces[i][0] = 0;
2704 mesh->faces[i][1] = i + 1;
2705 mesh->faces[i][2] = i + 2;
2708 mesh->faces[sides - 1][2] = 1;
2710 return TRUE;
2713 static void test_polygon(IDirect3DDevice9 *device, float length, unsigned int sides)
2715 HRESULT hr;
2716 ID3DXMesh *polygon;
2717 struct mesh mesh;
2718 char name[64];
2720 hr = D3DXCreatePolygon(device, length, sides, &polygon, NULL);
2721 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
2722 if (hr != D3D_OK)
2724 skip("Couldn't create polygon\n");
2725 return;
2728 if (!compute_polygon(&mesh, length, sides))
2730 skip("Couldn't create mesh\n");
2731 polygon->lpVtbl->Release(polygon);
2732 return;
2735 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
2737 sprintf(name, "polygon (%g, %u)", length, sides);
2738 compare_mesh(name, polygon, &mesh);
2740 free_mesh(&mesh);
2742 polygon->lpVtbl->Release(polygon);
2745 static void D3DXCreatePolygonTest(void)
2747 HRESULT hr;
2748 IDirect3DDevice9 *device;
2749 ID3DXMesh *polygon;
2750 ID3DXBuffer *adjacency;
2751 DWORD (*buffer)[3], buffer_size;
2752 unsigned int i;
2753 struct test_context *test_context;
2755 if (!(test_context = new_test_context()))
2757 skip("Couldn't create test context\n");
2758 return;
2760 device = test_context->device;
2762 hr = D3DXCreatePolygon(device, 2.0f, 11, NULL, &adjacency);
2763 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2765 hr = D3DXCreatePolygon(NULL, 2.0f, 11, &polygon, &adjacency);
2766 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2768 hr = D3DXCreatePolygon(device, -2.0f, 11, &polygon, &adjacency);
2769 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2771 polygon = (void *)0xdeadbeef;
2772 adjacency = (void *)0xdeadbeef;
2773 hr = D3DXCreatePolygon(device, 2.0f, 0, &polygon, &adjacency);
2774 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2775 ok(polygon == (void *)0xdeadbeef, "Polygon was changed to %p\n", polygon);
2776 ok(adjacency == (void *)0xdeadbeef, "Adjacency was changed to %p\n", adjacency);
2778 hr = D3DXCreatePolygon(device, 2.0f, 2, &polygon, &adjacency);
2779 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2781 adjacency = NULL;
2782 hr = D3DXCreatePolygon(device, 3.0f, 11, &polygon, &adjacency);
2783 ok(hr == D3D_OK, "Expected D3D_OK, received %#x\n", hr);
2785 buffer_size = ID3DXBuffer_GetBufferSize(adjacency);
2786 ok(buffer_size == 33 * sizeof(DWORD), "Wrong adjacency buffer size %u\n", buffer_size);
2788 buffer = ID3DXBuffer_GetBufferPointer(adjacency);
2789 for (i = 0; i < 11; ++i)
2791 ok(buffer[i][0] == (i + 10) % 11, "Wrong adjacency[%d][0] = %u\n", i, buffer[i][0]);
2792 ok(buffer[i][1] == ~0U, "Wrong adjacency[%d][1] = %u\n", i, buffer[i][1]);
2793 ok(buffer[i][2] == (i + 1) % 11, "Wrong adjacency[%d][2] = %u\n", i, buffer[i][2]);
2796 polygon->lpVtbl->Release(polygon);
2797 ID3DXBuffer_Release(adjacency);
2799 test_polygon(device, 2.0f, 3);
2800 test_polygon(device, 10.0f, 3);
2801 test_polygon(device, 10.0f, 5);
2802 test_polygon(device, 10.0f, 10);
2803 test_polygon(device, 20.0f, 10);
2805 free_test_context(test_context);
2808 struct sincos_table
2810 float *sin;
2811 float *cos;
2814 static void free_sincos_table(struct sincos_table *sincos_table)
2816 HeapFree(GetProcessHeap(), 0, sincos_table->cos);
2817 HeapFree(GetProcessHeap(), 0, sincos_table->sin);
2820 /* pre compute sine and cosine tables; caller must free */
2821 static BOOL compute_sincos_table(struct sincos_table *sincos_table, float angle_start, float angle_step, int n)
2823 float angle;
2824 int i;
2826 sincos_table->sin = HeapAlloc(GetProcessHeap(), 0, n * sizeof(*sincos_table->sin));
2827 if (!sincos_table->sin)
2829 return FALSE;
2831 sincos_table->cos = HeapAlloc(GetProcessHeap(), 0, n * sizeof(*sincos_table->cos));
2832 if (!sincos_table->cos)
2834 HeapFree(GetProcessHeap(), 0, sincos_table->sin);
2835 return FALSE;
2838 angle = angle_start;
2839 for (i = 0; i < n; i++)
2841 sincos_table->sin[i] = sin(angle);
2842 sincos_table->cos[i] = cos(angle);
2843 angle += angle_step;
2846 return TRUE;
2849 static WORD vertex_index(UINT slices, int slice, int stack)
2851 return stack*slices+slice+1;
2854 /* slices = subdivisions along xy plane, stacks = subdivisions along z axis */
2855 static BOOL compute_sphere(struct mesh *mesh, FLOAT radius, UINT slices, UINT stacks)
2857 float theta_step, theta_start;
2858 struct sincos_table theta;
2859 float phi_step, phi_start;
2860 struct sincos_table phi;
2861 DWORD number_of_vertices, number_of_faces;
2862 DWORD vertex, face;
2863 int slice, stack;
2865 /* theta = angle on xy plane wrt x axis */
2866 theta_step = D3DX_PI / stacks;
2867 theta_start = theta_step;
2869 /* phi = angle on xz plane wrt z axis */
2870 phi_step = -2 * D3DX_PI / slices;
2871 phi_start = D3DX_PI / 2;
2873 if (!compute_sincos_table(&theta, theta_start, theta_step, stacks))
2875 return FALSE;
2877 if (!compute_sincos_table(&phi, phi_start, phi_step, slices))
2879 free_sincos_table(&theta);
2880 return FALSE;
2883 number_of_vertices = 2 + slices * (stacks-1);
2884 number_of_faces = 2 * slices + (stacks - 2) * (2 * slices);
2886 if (!new_mesh(mesh, number_of_vertices, number_of_faces))
2888 free_sincos_table(&phi);
2889 free_sincos_table(&theta);
2890 return FALSE;
2893 vertex = 0;
2894 face = 0;
2896 mesh->vertices[vertex].normal.x = 0.0f;
2897 mesh->vertices[vertex].normal.y = 0.0f;
2898 mesh->vertices[vertex].normal.z = 1.0f;
2899 mesh->vertices[vertex].position.x = 0.0f;
2900 mesh->vertices[vertex].position.y = 0.0f;
2901 mesh->vertices[vertex].position.z = radius;
2902 vertex++;
2904 for (stack = 0; stack < stacks - 1; stack++)
2906 for (slice = 0; slice < slices; slice++)
2908 mesh->vertices[vertex].normal.x = theta.sin[stack] * phi.cos[slice];
2909 mesh->vertices[vertex].normal.y = theta.sin[stack] * phi.sin[slice];
2910 mesh->vertices[vertex].normal.z = theta.cos[stack];
2911 mesh->vertices[vertex].position.x = radius * theta.sin[stack] * phi.cos[slice];
2912 mesh->vertices[vertex].position.y = radius * theta.sin[stack] * phi.sin[slice];
2913 mesh->vertices[vertex].position.z = radius * theta.cos[stack];
2914 vertex++;
2916 if (slice > 0)
2918 if (stack == 0)
2920 /* top stack is triangle fan */
2921 mesh->faces[face][0] = 0;
2922 mesh->faces[face][1] = slice + 1;
2923 mesh->faces[face][2] = slice;
2924 face++;
2926 else
2928 /* stacks in between top and bottom are quad strips */
2929 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
2930 mesh->faces[face][1] = vertex_index(slices, slice, stack-1);
2931 mesh->faces[face][2] = vertex_index(slices, slice-1, stack);
2932 face++;
2934 mesh->faces[face][0] = vertex_index(slices, slice, stack-1);
2935 mesh->faces[face][1] = vertex_index(slices, slice, stack);
2936 mesh->faces[face][2] = vertex_index(slices, slice-1, stack);
2937 face++;
2942 if (stack == 0)
2944 mesh->faces[face][0] = 0;
2945 mesh->faces[face][1] = 1;
2946 mesh->faces[face][2] = slice;
2947 face++;
2949 else
2951 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
2952 mesh->faces[face][1] = vertex_index(slices, 0, stack-1);
2953 mesh->faces[face][2] = vertex_index(slices, slice-1, stack);
2954 face++;
2956 mesh->faces[face][0] = vertex_index(slices, 0, stack-1);
2957 mesh->faces[face][1] = vertex_index(slices, 0, stack);
2958 mesh->faces[face][2] = vertex_index(slices, slice-1, stack);
2959 face++;
2963 mesh->vertices[vertex].position.x = 0.0f;
2964 mesh->vertices[vertex].position.y = 0.0f;
2965 mesh->vertices[vertex].position.z = -radius;
2966 mesh->vertices[vertex].normal.x = 0.0f;
2967 mesh->vertices[vertex].normal.y = 0.0f;
2968 mesh->vertices[vertex].normal.z = -1.0f;
2970 /* bottom stack is triangle fan */
2971 for (slice = 1; slice < slices; slice++)
2973 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
2974 mesh->faces[face][1] = vertex_index(slices, slice, stack-1);
2975 mesh->faces[face][2] = vertex;
2976 face++;
2979 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
2980 mesh->faces[face][1] = vertex_index(slices, 0, stack-1);
2981 mesh->faces[face][2] = vertex;
2983 free_sincos_table(&phi);
2984 free_sincos_table(&theta);
2986 return TRUE;
2989 static void test_sphere(IDirect3DDevice9 *device, FLOAT radius, UINT slices, UINT stacks)
2991 HRESULT hr;
2992 ID3DXMesh *sphere;
2993 struct mesh mesh;
2994 char name[256];
2996 hr = D3DXCreateSphere(device, radius, slices, stacks, &sphere, NULL);
2997 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
2998 if (hr != D3D_OK)
3000 skip("Couldn't create sphere\n");
3001 return;
3004 if (!compute_sphere(&mesh, radius, slices, stacks))
3006 skip("Couldn't create mesh\n");
3007 sphere->lpVtbl->Release(sphere);
3008 return;
3011 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
3013 sprintf(name, "sphere (%g, %u, %u)", radius, slices, stacks);
3014 compare_mesh(name, sphere, &mesh);
3016 free_mesh(&mesh);
3018 sphere->lpVtbl->Release(sphere);
3021 static void D3DXCreateSphereTest(void)
3023 HRESULT hr;
3024 IDirect3DDevice9* device;
3025 ID3DXMesh* sphere = NULL;
3026 struct test_context *test_context;
3028 hr = D3DXCreateSphere(NULL, 0.0f, 0, 0, NULL, NULL);
3029 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3031 hr = D3DXCreateSphere(NULL, 0.1f, 0, 0, NULL, NULL);
3032 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3034 hr = D3DXCreateSphere(NULL, 0.0f, 1, 0, NULL, NULL);
3035 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3037 hr = D3DXCreateSphere(NULL, 0.0f, 0, 1, NULL, NULL);
3038 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3040 if (!(test_context = new_test_context()))
3042 skip("Couldn't create test context\n");
3043 return;
3045 device = test_context->device;
3047 hr = D3DXCreateSphere(device, 1.0f, 1, 1, &sphere, NULL);
3048 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3050 hr = D3DXCreateSphere(device, 1.0f, 2, 1, &sphere, NULL);
3051 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
3053 hr = D3DXCreateSphere(device, 1.0f, 1, 2, &sphere, NULL);
3054 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
3056 hr = D3DXCreateSphere(device, -0.1f, 1, 2, &sphere, NULL);
3057 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
3059 test_sphere(device, 0.0f, 2, 2);
3060 test_sphere(device, 1.0f, 2, 2);
3061 test_sphere(device, 1.0f, 3, 2);
3062 test_sphere(device, 1.0f, 4, 4);
3063 test_sphere(device, 1.0f, 3, 4);
3064 test_sphere(device, 5.0f, 6, 7);
3065 test_sphere(device, 10.0f, 11, 12);
3067 free_test_context(test_context);
3070 static BOOL compute_cylinder(struct mesh *mesh, FLOAT radius1, FLOAT radius2, FLOAT length, UINT slices, UINT stacks)
3072 float theta_step, theta_start;
3073 struct sincos_table theta;
3074 FLOAT delta_radius, radius, radius_step;
3075 FLOAT z, z_step, z_normal;
3076 DWORD number_of_vertices, number_of_faces;
3077 DWORD vertex, face;
3078 int slice, stack;
3080 /* theta = angle on xy plane wrt x axis */
3081 theta_step = -2 * D3DX_PI / slices;
3082 theta_start = D3DX_PI / 2;
3084 if (!compute_sincos_table(&theta, theta_start, theta_step, slices))
3086 return FALSE;
3089 number_of_vertices = 2 + (slices * (3 + stacks));
3090 number_of_faces = 2 * slices + stacks * (2 * slices);
3092 if (!new_mesh(mesh, number_of_vertices, number_of_faces))
3094 free_sincos_table(&theta);
3095 return FALSE;
3098 vertex = 0;
3099 face = 0;
3101 delta_radius = radius1 - radius2;
3102 radius = radius1;
3103 radius_step = delta_radius / stacks;
3105 z = -length / 2;
3106 z_step = length / stacks;
3107 z_normal = delta_radius / length;
3108 if (isnan(z_normal))
3110 z_normal = 0.0f;
3113 mesh->vertices[vertex].normal.x = 0.0f;
3114 mesh->vertices[vertex].normal.y = 0.0f;
3115 mesh->vertices[vertex].normal.z = -1.0f;
3116 mesh->vertices[vertex].position.x = 0.0f;
3117 mesh->vertices[vertex].position.y = 0.0f;
3118 mesh->vertices[vertex++].position.z = z;
3120 for (slice = 0; slice < slices; slice++, vertex++)
3122 mesh->vertices[vertex].normal.x = 0.0f;
3123 mesh->vertices[vertex].normal.y = 0.0f;
3124 mesh->vertices[vertex].normal.z = -1.0f;
3125 mesh->vertices[vertex].position.x = radius * theta.cos[slice];
3126 mesh->vertices[vertex].position.y = radius * theta.sin[slice];
3127 mesh->vertices[vertex].position.z = z;
3129 if (slice > 0)
3131 mesh->faces[face][0] = 0;
3132 mesh->faces[face][1] = slice;
3133 mesh->faces[face++][2] = slice + 1;
3137 mesh->faces[face][0] = 0;
3138 mesh->faces[face][1] = slice;
3139 mesh->faces[face++][2] = 1;
3141 for (stack = 1; stack <= stacks+1; stack++)
3143 for (slice = 0; slice < slices; slice++, vertex++)
3145 mesh->vertices[vertex].normal.x = theta.cos[slice];
3146 mesh->vertices[vertex].normal.y = theta.sin[slice];
3147 mesh->vertices[vertex].normal.z = z_normal;
3148 D3DXVec3Normalize(&mesh->vertices[vertex].normal, &mesh->vertices[vertex].normal);
3149 mesh->vertices[vertex].position.x = radius * theta.cos[slice];
3150 mesh->vertices[vertex].position.y = radius * theta.sin[slice];
3151 mesh->vertices[vertex].position.z = z;
3153 if (stack > 1 && slice > 0)
3155 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
3156 mesh->faces[face][1] = vertex_index(slices, slice-1, stack);
3157 mesh->faces[face++][2] = vertex_index(slices, slice, stack-1);
3159 mesh->faces[face][0] = vertex_index(slices, slice, stack-1);
3160 mesh->faces[face][1] = vertex_index(slices, slice-1, stack);
3161 mesh->faces[face++][2] = vertex_index(slices, slice, stack);
3165 if (stack > 1)
3167 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
3168 mesh->faces[face][1] = vertex_index(slices, slice-1, stack);
3169 mesh->faces[face++][2] = vertex_index(slices, 0, stack-1);
3171 mesh->faces[face][0] = vertex_index(slices, 0, stack-1);
3172 mesh->faces[face][1] = vertex_index(slices, slice-1, stack);
3173 mesh->faces[face++][2] = vertex_index(slices, 0, stack);
3176 if (stack < stacks + 1)
3178 z += z_step;
3179 radius -= radius_step;
3183 for (slice = 0; slice < slices; slice++, vertex++)
3185 mesh->vertices[vertex].normal.x = 0.0f;
3186 mesh->vertices[vertex].normal.y = 0.0f;
3187 mesh->vertices[vertex].normal.z = 1.0f;
3188 mesh->vertices[vertex].position.x = radius * theta.cos[slice];
3189 mesh->vertices[vertex].position.y = radius * theta.sin[slice];
3190 mesh->vertices[vertex].position.z = z;
3192 if (slice > 0)
3194 mesh->faces[face][0] = vertex_index(slices, slice-1, stack);
3195 mesh->faces[face][1] = number_of_vertices - 1;
3196 mesh->faces[face++][2] = vertex_index(slices, slice, stack);
3200 mesh->vertices[vertex].position.x = 0.0f;
3201 mesh->vertices[vertex].position.y = 0.0f;
3202 mesh->vertices[vertex].position.z = z;
3203 mesh->vertices[vertex].normal.x = 0.0f;
3204 mesh->vertices[vertex].normal.y = 0.0f;
3205 mesh->vertices[vertex].normal.z = 1.0f;
3207 mesh->faces[face][0] = vertex_index(slices, slice-1, stack);
3208 mesh->faces[face][1] = number_of_vertices - 1;
3209 mesh->faces[face][2] = vertex_index(slices, 0, stack);
3211 free_sincos_table(&theta);
3213 return TRUE;
3216 static void test_cylinder(IDirect3DDevice9 *device, FLOAT radius1, FLOAT radius2, FLOAT length, UINT slices, UINT stacks)
3218 HRESULT hr;
3219 ID3DXMesh *cylinder;
3220 struct mesh mesh;
3221 char name[256];
3223 hr = D3DXCreateCylinder(device, radius1, radius2, length, slices, stacks, &cylinder, NULL);
3224 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
3225 if (hr != D3D_OK)
3227 skip("Couldn't create cylinder\n");
3228 return;
3231 if (!compute_cylinder(&mesh, radius1, radius2, length, slices, stacks))
3233 skip("Couldn't create mesh\n");
3234 cylinder->lpVtbl->Release(cylinder);
3235 return;
3238 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
3240 sprintf(name, "cylinder (%g, %g, %g, %u, %u)", radius1, radius2, length, slices, stacks);
3241 compare_mesh(name, cylinder, &mesh);
3243 free_mesh(&mesh);
3245 cylinder->lpVtbl->Release(cylinder);
3248 static void D3DXCreateCylinderTest(void)
3250 HRESULT hr;
3251 IDirect3DDevice9* device;
3252 ID3DXMesh* cylinder = NULL;
3253 struct test_context *test_context;
3255 hr = D3DXCreateCylinder(NULL, 0.0f, 0.0f, 0.0f, 0, 0, NULL, NULL);
3256 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3258 hr = D3DXCreateCylinder(NULL, 1.0f, 1.0f, 1.0f, 2, 1, &cylinder, NULL);
3259 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3261 if (!(test_context = new_test_context()))
3263 skip("Couldn't create test context\n");
3264 return;
3266 device = test_context->device;
3268 hr = D3DXCreateCylinder(device, -0.1f, 1.0f, 1.0f, 2, 1, &cylinder, NULL);
3269 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3271 hr = D3DXCreateCylinder(device, 0.0f, 1.0f, 1.0f, 2, 1, &cylinder, NULL);
3272 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n",hr);
3274 if (SUCCEEDED(hr) && cylinder)
3276 cylinder->lpVtbl->Release(cylinder);
3279 hr = D3DXCreateCylinder(device, 1.0f, -0.1f, 1.0f, 2, 1, &cylinder, NULL);
3280 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3282 hr = D3DXCreateCylinder(device, 1.0f, 0.0f, 1.0f, 2, 1, &cylinder, NULL);
3283 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n",hr);
3285 if (SUCCEEDED(hr) && cylinder)
3287 cylinder->lpVtbl->Release(cylinder);
3290 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, -0.1f, 2, 1, &cylinder, NULL);
3291 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3293 /* Test with length == 0.0f succeeds */
3294 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, 0.0f, 2, 1, &cylinder, NULL);
3295 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n",hr);
3297 if (SUCCEEDED(hr) && cylinder)
3299 cylinder->lpVtbl->Release(cylinder);
3302 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, 1.0f, 1, 1, &cylinder, NULL);
3303 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3305 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, 1.0f, 2, 0, &cylinder, NULL);
3306 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3308 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, 1.0f, 2, 1, NULL, NULL);
3309 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3311 test_cylinder(device, 0.0f, 0.0f, 0.0f, 2, 1);
3312 test_cylinder(device, 1.0f, 1.0f, 1.0f, 2, 1);
3313 test_cylinder(device, 1.0f, 1.0f, 2.0f, 3, 4);
3314 test_cylinder(device, 3.0f, 2.0f, 4.0f, 3, 4);
3315 test_cylinder(device, 2.0f, 3.0f, 4.0f, 3, 4);
3316 test_cylinder(device, 3.0f, 4.0f, 5.0f, 11, 20);
3318 free_test_context(test_context);
3321 static BOOL compute_torus(struct mesh *mesh, float innerradius, float outerradius, UINT sides, UINT rings)
3323 float phi, phi_step, sin_phi, cos_phi;
3324 float theta, theta_step, sin_theta, cos_theta;
3325 unsigned int numvert, numfaces, i, j;
3327 numvert = sides * rings;
3328 numfaces = numvert * 2;
3330 if (!new_mesh(mesh, numvert, numfaces))
3331 return FALSE;
3333 phi_step = D3DX_PI / sides * 2.0f;
3334 theta_step = D3DX_PI / rings * -2.0f;
3336 theta = 0.0f;
3338 for (i = 0; i < rings; ++i)
3340 phi = 0.0f;
3342 cos_theta = cosf(theta);
3343 sin_theta = sinf(theta);
3345 for (j = 0; j < sides; ++j)
3347 sin_phi = sinf(phi);
3348 cos_phi = cosf(phi);
3350 mesh->vertices[i * sides + j].position.x = (innerradius * cos_phi + outerradius) * cos_theta;
3351 mesh->vertices[i * sides + j].position.y = (innerradius * cos_phi + outerradius) * sin_theta;
3352 mesh->vertices[i * sides + j].position.z = innerradius * sin_phi;
3353 mesh->vertices[i * sides + j].normal.x = cos_phi * cos_theta;
3354 mesh->vertices[i * sides + j].normal.y = cos_phi * sin_theta;
3355 mesh->vertices[i * sides + j].normal.z = sin_phi;
3357 phi += phi_step;
3360 theta += theta_step;
3363 for (i = 0; i < numfaces - sides * 2; ++i)
3365 mesh->faces[i][0] = i % 2 ? i / 2 + sides : i / 2;
3366 mesh->faces[i][1] = (i / 2 + 1) % sides ? i / 2 + 1 : i / 2 + 1 - sides;
3367 mesh->faces[i][2] = (i + 1) % (sides * 2) ? (i + 1) / 2 + sides : (i + 1) / 2;
3370 for (j = 0; i < numfaces; ++i, ++j)
3372 mesh->faces[i][0] = i % 2 ? j / 2 : i / 2;
3373 mesh->faces[i][1] = (i / 2 + 1) % sides ? i / 2 + 1 : i / 2 + 1 - sides;
3374 mesh->faces[i][2] = i == numfaces - 1 ? 0 : (j + 1) / 2;
3377 return TRUE;
3380 static void test_torus(IDirect3DDevice9 *device, float innerradius, float outerradius, UINT sides, UINT rings)
3382 HRESULT hr;
3383 ID3DXMesh *torus;
3384 struct mesh mesh;
3385 char name[256];
3387 hr = D3DXCreateTorus(device, innerradius, outerradius, sides, rings, &torus, NULL);
3388 ok(hr == D3D_OK, "Got result %#x, expected 0 (D3D_OK)\n", hr);
3389 if (hr != D3D_OK)
3391 skip("Couldn't create torus\n");
3392 return;
3395 if (!compute_torus(&mesh, innerradius, outerradius, sides, rings))
3397 skip("Couldn't create mesh\n");
3398 torus->lpVtbl->Release(torus);
3399 return;
3402 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
3404 sprintf(name, "torus (%g, %g, %u, %u)", innerradius, outerradius, sides, rings);
3405 compare_mesh(name, torus, &mesh);
3407 free_mesh(&mesh);
3409 torus->lpVtbl->Release(torus);
3412 static void D3DXCreateTorusTest(void)
3414 HRESULT hr;
3415 IDirect3DDevice9* device;
3416 ID3DXMesh* torus = NULL;
3417 struct test_context *test_context;
3419 if (!(test_context = new_test_context()))
3421 skip("Couldn't create test context\n");
3422 return;
3424 device = test_context->device;
3426 hr = D3DXCreateTorus(NULL, 0.0f, 0.0f, 3, 3, &torus, NULL);
3427 ok(hr == D3DERR_INVALIDCALL, "Got result %#x, expected %#x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
3429 hr = D3DXCreateTorus(device, -1.0f, 0.0f, 3, 3, &torus, NULL);
3430 ok(hr == D3DERR_INVALIDCALL, "Got result %#x, expected %#x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
3432 hr = D3DXCreateTorus(device, 0.0f, -1.0f, 3, 3, &torus, NULL);
3433 ok(hr == D3DERR_INVALIDCALL, "Got result %#x, expected %#x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
3435 hr = D3DXCreateTorus(device, 0.0f, 0.0f, 2, 3, &torus, NULL);
3436 ok(hr == D3DERR_INVALIDCALL, "Got result %#x, expected %#x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
3438 hr = D3DXCreateTorus(device, 0.0f, 0.0f, 3, 2, &torus, NULL);
3439 ok(hr == D3DERR_INVALIDCALL, "Got result %#x, expected %#x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
3441 hr = D3DXCreateTorus(device, 0.0f, 0.0f, 3, 3, NULL, NULL);
3442 ok(hr == D3DERR_INVALIDCALL, "Got result %#x, expected %#x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
3444 test_torus(device, 0.0f, 0.0f, 3, 3);
3445 test_torus(device, 1.0f, 1.0f, 3, 3);
3446 test_torus(device, 1.0f, 1.0f, 32, 64);
3447 test_torus(device, 0.0f, 1.0f, 5, 5);
3448 test_torus(device, 1.0f, 0.0f, 5, 5);
3449 test_torus(device, 5.0f, 0.2f, 8, 8);
3450 test_torus(device, 0.2f, 1.0f, 60, 3);
3451 test_torus(device, 0.2f, 1.0f, 8, 70);
3453 free_test_context(test_context);
3456 struct dynamic_array
3458 int count, capacity;
3459 void *items;
3462 enum pointtype {
3463 POINTTYPE_CURVE = 0,
3464 POINTTYPE_CORNER,
3465 POINTTYPE_CURVE_START,
3466 POINTTYPE_CURVE_END,
3467 POINTTYPE_CURVE_MIDDLE,
3470 struct point2d
3472 D3DXVECTOR2 pos;
3473 enum pointtype corner;
3476 /* is a dynamic_array */
3477 struct outline
3479 int count, capacity;
3480 struct point2d *items;
3483 /* is a dynamic_array */
3484 struct outline_array
3486 int count, capacity;
3487 struct outline *items;
3490 struct glyphinfo
3492 struct outline_array outlines;
3493 float offset_x;
3496 static BOOL reserve(struct dynamic_array *array, int count, int itemsize)
3498 if (count > array->capacity) {
3499 void *new_buffer;
3500 int new_capacity;
3501 if (array->items && array->capacity) {
3502 new_capacity = max(array->capacity * 2, count);
3503 new_buffer = HeapReAlloc(GetProcessHeap(), 0, array->items, new_capacity * itemsize);
3504 } else {
3505 new_capacity = max(16, count);
3506 new_buffer = HeapAlloc(GetProcessHeap(), 0, new_capacity * itemsize);
3508 if (!new_buffer)
3509 return FALSE;
3510 array->items = new_buffer;
3511 array->capacity = new_capacity;
3513 return TRUE;
3516 static struct point2d *add_point(struct outline *array)
3518 struct point2d *item;
3520 if (!reserve((struct dynamic_array *)array, array->count + 1, sizeof(array->items[0])))
3521 return NULL;
3523 item = &array->items[array->count++];
3524 ZeroMemory(item, sizeof(*item));
3525 return item;
3528 static struct outline *add_outline(struct outline_array *array)
3530 struct outline *item;
3532 if (!reserve((struct dynamic_array *)array, array->count + 1, sizeof(array->items[0])))
3533 return NULL;
3535 item = &array->items[array->count++];
3536 ZeroMemory(item, sizeof(*item));
3537 return item;
3540 static inline D3DXVECTOR2 *convert_fixed_to_float(POINTFX *pt, int count, float emsquare)
3542 D3DXVECTOR2 *ret = (D3DXVECTOR2*)pt;
3543 while (count--) {
3544 D3DXVECTOR2 *pt_flt = (D3DXVECTOR2*)pt;
3545 pt_flt->x = (pt->x.value + pt->x.fract / (float)0x10000) / emsquare;
3546 pt_flt->y = (pt->y.value + pt->y.fract / (float)0x10000) / emsquare;
3547 pt++;
3549 return ret;
3552 static HRESULT add_bezier_points(struct outline *outline, const D3DXVECTOR2 *p1,
3553 const D3DXVECTOR2 *p2, const D3DXVECTOR2 *p3,
3554 float max_deviation)
3556 D3DXVECTOR2 split1 = {0, 0}, split2 = {0, 0}, middle, vec;
3557 float deviation;
3559 D3DXVec2Scale(&split1, D3DXVec2Add(&split1, p1, p2), 0.5f);
3560 D3DXVec2Scale(&split2, D3DXVec2Add(&split2, p2, p3), 0.5f);
3561 D3DXVec2Scale(&middle, D3DXVec2Add(&middle, &split1, &split2), 0.5f);
3563 deviation = D3DXVec2Length(D3DXVec2Subtract(&vec, &middle, p2));
3564 if (deviation < max_deviation) {
3565 struct point2d *pt = add_point(outline);
3566 if (!pt) return E_OUTOFMEMORY;
3567 pt->pos = *p2;
3568 pt->corner = POINTTYPE_CURVE;
3569 /* the end point is omitted because the end line merges into the next segment of
3570 * the split bezier curve, and the end of the split bezier curve is added outside
3571 * this recursive function. */
3572 } else {
3573 HRESULT hr = add_bezier_points(outline, p1, &split1, &middle, max_deviation);
3574 if (hr != S_OK) return hr;
3575 hr = add_bezier_points(outline, &middle, &split2, p3, max_deviation);
3576 if (hr != S_OK) return hr;
3579 return S_OK;
3582 static inline BOOL is_direction_similar(D3DXVECTOR2 *dir1, D3DXVECTOR2 *dir2, float cos_theta)
3584 /* dot product = cos(theta) */
3585 return D3DXVec2Dot(dir1, dir2) > cos_theta;
3588 static inline D3DXVECTOR2 *unit_vec2(D3DXVECTOR2 *dir, const D3DXVECTOR2 *pt1, const D3DXVECTOR2 *pt2)
3590 return D3DXVec2Normalize(D3DXVec2Subtract(dir, pt2, pt1), dir);
3593 static BOOL attempt_line_merge(struct outline *outline,
3594 int pt_index,
3595 const D3DXVECTOR2 *nextpt,
3596 BOOL to_curve)
3598 D3DXVECTOR2 curdir, lastdir;
3599 struct point2d *prevpt, *pt;
3600 BOOL ret = FALSE;
3601 const float cos_half = cos(D3DXToRadian(0.5f));
3603 pt = &outline->items[pt_index];
3604 pt_index = (pt_index - 1 + outline->count) % outline->count;
3605 prevpt = &outline->items[pt_index];
3607 if (to_curve)
3608 pt->corner = pt->corner != POINTTYPE_CORNER ? POINTTYPE_CURVE_MIDDLE : POINTTYPE_CURVE_START;
3610 if (outline->count < 2)
3611 return FALSE;
3613 /* remove last point if the next line continues the last line */
3614 unit_vec2(&lastdir, &prevpt->pos, &pt->pos);
3615 unit_vec2(&curdir, &pt->pos, nextpt);
3616 if (is_direction_similar(&lastdir, &curdir, cos_half))
3618 outline->count--;
3619 if (pt->corner == POINTTYPE_CURVE_END)
3620 prevpt->corner = pt->corner;
3621 if (prevpt->corner == POINTTYPE_CURVE_END && to_curve)
3622 prevpt->corner = POINTTYPE_CURVE_MIDDLE;
3623 pt = prevpt;
3625 ret = TRUE;
3626 if (outline->count < 2)
3627 return ret;
3629 pt_index = (pt_index - 1 + outline->count) % outline->count;
3630 prevpt = &outline->items[pt_index];
3631 unit_vec2(&lastdir, &prevpt->pos, &pt->pos);
3632 unit_vec2(&curdir, &pt->pos, nextpt);
3634 return ret;
3637 static HRESULT create_outline(struct glyphinfo *glyph, void *raw_outline, int datasize,
3638 float max_deviation, float emsquare)
3640 const float cos_45 = cos(D3DXToRadian(45.0f));
3641 const float cos_90 = cos(D3DXToRadian(90.0f));
3642 TTPOLYGONHEADER *header = (TTPOLYGONHEADER *)raw_outline;
3644 while ((char *)header < (char *)raw_outline + datasize)
3646 TTPOLYCURVE *curve = (TTPOLYCURVE *)(header + 1);
3647 struct point2d *lastpt, *pt;
3648 D3DXVECTOR2 lastdir;
3649 D3DXVECTOR2 *pt_flt;
3650 int j;
3651 struct outline *outline = add_outline(&glyph->outlines);
3653 if (!outline)
3654 return E_OUTOFMEMORY;
3656 pt = add_point(outline);
3657 if (!pt)
3658 return E_OUTOFMEMORY;
3659 pt_flt = convert_fixed_to_float(&header->pfxStart, 1, emsquare);
3660 pt->pos = *pt_flt;
3661 pt->corner = POINTTYPE_CORNER;
3663 if (header->dwType != TT_POLYGON_TYPE)
3664 trace("Unknown header type %d\n", header->dwType);
3666 while ((char *)curve < (char *)header + header->cb)
3668 D3DXVECTOR2 bezier_start = outline->items[outline->count - 1].pos;
3669 BOOL to_curve = curve->wType != TT_PRIM_LINE && curve->cpfx > 1;
3671 if (!curve->cpfx) {
3672 curve = (TTPOLYCURVE *)&curve->apfx[curve->cpfx];
3673 continue;
3676 pt_flt = convert_fixed_to_float(curve->apfx, curve->cpfx, emsquare);
3678 attempt_line_merge(outline, outline->count - 1, &pt_flt[0], to_curve);
3680 if (to_curve)
3682 HRESULT hr;
3683 int count = curve->cpfx;
3684 j = 0;
3686 while (count > 2)
3688 D3DXVECTOR2 bezier_end;
3690 D3DXVec2Scale(&bezier_end, D3DXVec2Add(&bezier_end, &pt_flt[j], &pt_flt[j+1]), 0.5f);
3691 hr = add_bezier_points(outline, &bezier_start, &pt_flt[j], &bezier_end, max_deviation);
3692 if (hr != S_OK)
3693 return hr;
3694 bezier_start = bezier_end;
3695 count--;
3696 j++;
3698 hr = add_bezier_points(outline, &bezier_start, &pt_flt[j], &pt_flt[j+1], max_deviation);
3699 if (hr != S_OK)
3700 return hr;
3702 pt = add_point(outline);
3703 if (!pt)
3704 return E_OUTOFMEMORY;
3705 j++;
3706 pt->pos = pt_flt[j];
3707 pt->corner = POINTTYPE_CURVE_END;
3708 } else {
3709 for (j = 0; j < curve->cpfx; j++)
3711 pt = add_point(outline);
3712 if (!pt)
3713 return E_OUTOFMEMORY;
3714 pt->pos = pt_flt[j];
3715 pt->corner = POINTTYPE_CORNER;
3719 curve = (TTPOLYCURVE *)&curve->apfx[curve->cpfx];
3722 /* remove last point if the next line continues the last line */
3723 if (outline->count >= 3) {
3724 BOOL to_curve;
3726 lastpt = &outline->items[outline->count - 1];
3727 pt = &outline->items[0];
3728 if (pt->pos.x == lastpt->pos.x && pt->pos.y == lastpt->pos.y) {
3729 if (lastpt->corner == POINTTYPE_CURVE_END)
3731 if (pt->corner == POINTTYPE_CURVE_START)
3732 pt->corner = POINTTYPE_CURVE_MIDDLE;
3733 else
3734 pt->corner = POINTTYPE_CURVE_END;
3736 outline->count--;
3737 } else {
3738 /* outline closed with a line from end to start point */
3739 attempt_line_merge(outline, outline->count - 1, &pt->pos, FALSE);
3741 lastpt = &outline->items[0];
3742 to_curve = lastpt->corner != POINTTYPE_CORNER && lastpt->corner != POINTTYPE_CURVE_END;
3743 if (lastpt->corner == POINTTYPE_CURVE_START)
3744 lastpt->corner = POINTTYPE_CORNER;
3745 pt = &outline->items[1];
3746 if (attempt_line_merge(outline, 0, &pt->pos, to_curve))
3747 *lastpt = outline->items[outline->count];
3750 lastpt = &outline->items[outline->count - 1];
3751 pt = &outline->items[0];
3752 unit_vec2(&lastdir, &lastpt->pos, &pt->pos);
3753 for (j = 0; j < outline->count; j++)
3755 D3DXVECTOR2 curdir;
3757 lastpt = pt;
3758 pt = &outline->items[(j + 1) % outline->count];
3759 unit_vec2(&curdir, &lastpt->pos, &pt->pos);
3761 switch (lastpt->corner)
3763 case POINTTYPE_CURVE_START:
3764 case POINTTYPE_CURVE_END:
3765 if (!is_direction_similar(&lastdir, &curdir, cos_45))
3766 lastpt->corner = POINTTYPE_CORNER;
3767 break;
3768 case POINTTYPE_CURVE_MIDDLE:
3769 if (!is_direction_similar(&lastdir, &curdir, cos_90))
3770 lastpt->corner = POINTTYPE_CORNER;
3771 else
3772 lastpt->corner = POINTTYPE_CURVE;
3773 break;
3774 default:
3775 break;
3777 lastdir = curdir;
3780 header = (TTPOLYGONHEADER *)((char *)header + header->cb);
3782 return S_OK;
3785 static BOOL compute_text_mesh(struct mesh *mesh, const char *text,
3786 float deviation, float extrusion, float otmEMSquare, const struct glyphinfo *glyphs)
3788 DWORD nb_vertices, nb_faces;
3789 DWORD nb_corners, nb_outline_points;
3790 int textlen = 0;
3791 int i;
3792 struct vertex *vertex_ptr;
3793 face *face_ptr;
3795 textlen = strlen(text);
3797 /* corner points need an extra vertex for the different side faces normals */
3798 nb_corners = 0;
3799 nb_outline_points = 0;
3800 for (i = 0; i < textlen; i++)
3802 int j;
3803 for (j = 0; j < glyphs[i].outlines.count; j++)
3805 int k;
3806 struct outline *outline = &glyphs[i].outlines.items[j];
3807 nb_outline_points += outline->count;
3808 nb_corners++; /* first outline point always repeated as a corner */
3809 for (k = 1; k < outline->count; k++)
3810 if (outline->items[k].corner)
3811 nb_corners++;
3815 nb_vertices = (nb_outline_points + nb_corners) * 2 + textlen;
3816 nb_faces = nb_outline_points * 2;
3818 if (!new_mesh(mesh, nb_vertices, nb_faces))
3819 return FALSE;
3821 /* convert 2D vertices and faces into 3D mesh */
3822 vertex_ptr = mesh->vertices;
3823 face_ptr = mesh->faces;
3824 for (i = 0; i < textlen; i++)
3826 int j;
3828 /* side vertices and faces */
3829 for (j = 0; j < glyphs[i].outlines.count; j++)
3831 struct vertex *outline_vertices = vertex_ptr;
3832 struct outline *outline = &glyphs[i].outlines.items[j];
3833 int k;
3834 struct point2d *prevpt = &outline->items[outline->count - 1];
3835 struct point2d *pt = &outline->items[0];
3837 for (k = 1; k <= outline->count; k++)
3839 struct vertex vtx;
3840 struct point2d *nextpt = &outline->items[k % outline->count];
3841 WORD vtx_idx = vertex_ptr - mesh->vertices;
3842 D3DXVECTOR2 vec;
3844 if (pt->corner == POINTTYPE_CURVE_START)
3845 D3DXVec2Subtract(&vec, &pt->pos, &prevpt->pos);
3846 else if (pt->corner)
3847 D3DXVec2Subtract(&vec, &nextpt->pos, &pt->pos);
3848 else
3849 D3DXVec2Subtract(&vec, &nextpt->pos, &prevpt->pos);
3850 D3DXVec2Normalize(&vec, &vec);
3851 vtx.normal.x = -vec.y;
3852 vtx.normal.y = vec.x;
3853 vtx.normal.z = 0;
3855 vtx.position.x = pt->pos.x + glyphs[i].offset_x;
3856 vtx.position.y = pt->pos.y;
3857 vtx.position.z = 0;
3858 *vertex_ptr++ = vtx;
3860 vtx.position.z = -extrusion;
3861 *vertex_ptr++ = vtx;
3863 vtx.position.x = nextpt->pos.x + glyphs[i].offset_x;
3864 vtx.position.y = nextpt->pos.y;
3865 if (pt->corner && nextpt->corner && nextpt->corner != POINTTYPE_CURVE_END) {
3866 vtx.position.z = -extrusion;
3867 *vertex_ptr++ = vtx;
3868 vtx.position.z = 0;
3869 *vertex_ptr++ = vtx;
3871 (*face_ptr)[0] = vtx_idx;
3872 (*face_ptr)[1] = vtx_idx + 2;
3873 (*face_ptr)[2] = vtx_idx + 1;
3874 face_ptr++;
3876 (*face_ptr)[0] = vtx_idx;
3877 (*face_ptr)[1] = vtx_idx + 3;
3878 (*face_ptr)[2] = vtx_idx + 2;
3879 face_ptr++;
3880 } else {
3881 if (nextpt->corner) {
3882 if (nextpt->corner == POINTTYPE_CURVE_END) {
3883 struct point2d *nextpt2 = &outline->items[(k + 1) % outline->count];
3884 D3DXVec2Subtract(&vec, &nextpt2->pos, &nextpt->pos);
3885 } else {
3886 D3DXVec2Subtract(&vec, &nextpt->pos, &pt->pos);
3888 D3DXVec2Normalize(&vec, &vec);
3889 vtx.normal.x = -vec.y;
3890 vtx.normal.y = vec.x;
3892 vtx.position.z = 0;
3893 *vertex_ptr++ = vtx;
3894 vtx.position.z = -extrusion;
3895 *vertex_ptr++ = vtx;
3898 (*face_ptr)[0] = vtx_idx;
3899 (*face_ptr)[1] = vtx_idx + 3;
3900 (*face_ptr)[2] = vtx_idx + 1;
3901 face_ptr++;
3903 (*face_ptr)[0] = vtx_idx;
3904 (*face_ptr)[1] = vtx_idx + 2;
3905 (*face_ptr)[2] = vtx_idx + 3;
3906 face_ptr++;
3909 prevpt = pt;
3910 pt = nextpt;
3912 if (!pt->corner) {
3913 *vertex_ptr++ = *outline_vertices++;
3914 *vertex_ptr++ = *outline_vertices++;
3918 /* FIXME: compute expected faces */
3919 /* Add placeholder to separate glyph outlines */
3920 vertex_ptr->position.x = 0;
3921 vertex_ptr->position.y = 0;
3922 vertex_ptr->position.z = 0;
3923 vertex_ptr->normal.x = 0;
3924 vertex_ptr->normal.y = 0;
3925 vertex_ptr->normal.z = 1;
3926 vertex_ptr++;
3929 return TRUE;
3932 static void compare_text_outline_mesh(const char *name, ID3DXMesh *d3dxmesh, struct mesh *mesh,
3933 size_t textlen, float extrusion, const struct glyphinfo *glyphs)
3935 HRESULT hr;
3936 DWORD number_of_vertices, number_of_faces;
3937 IDirect3DVertexBuffer9 *vertex_buffer = NULL;
3938 IDirect3DIndexBuffer9 *index_buffer = NULL;
3939 D3DVERTEXBUFFER_DESC vertex_buffer_description;
3940 D3DINDEXBUFFER_DESC index_buffer_description;
3941 struct vertex *vertices = NULL;
3942 face *faces = NULL;
3943 int expected, i;
3944 int vtx_idx1, face_idx1, vtx_idx2, face_idx2;
3946 number_of_vertices = d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh);
3947 number_of_faces = d3dxmesh->lpVtbl->GetNumFaces(d3dxmesh);
3949 /* vertex buffer */
3950 hr = d3dxmesh->lpVtbl->GetVertexBuffer(d3dxmesh, &vertex_buffer);
3951 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
3952 if (hr != D3D_OK)
3954 skip("Couldn't get vertex buffers\n");
3955 goto error;
3958 hr = IDirect3DVertexBuffer9_GetDesc(vertex_buffer, &vertex_buffer_description);
3959 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
3961 if (hr != D3D_OK)
3963 skip("Couldn't get vertex buffer description\n");
3965 else
3967 ok(vertex_buffer_description.Format == D3DFMT_VERTEXDATA, "Test %s, result %x, expected %x (D3DFMT_VERTEXDATA)\n",
3968 name, vertex_buffer_description.Format, D3DFMT_VERTEXDATA);
3969 ok(vertex_buffer_description.Type == D3DRTYPE_VERTEXBUFFER, "Test %s, result %x, expected %x (D3DRTYPE_VERTEXBUFFER)\n",
3970 name, vertex_buffer_description.Type, D3DRTYPE_VERTEXBUFFER);
3971 ok(vertex_buffer_description.Usage == 0, "Test %s, result %x, expected %x\n", name, vertex_buffer_description.Usage, 0);
3972 ok(vertex_buffer_description.Pool == D3DPOOL_MANAGED, "Test %s, result %x, expected %x (D3DPOOL_MANAGED)\n",
3973 name, vertex_buffer_description.Pool, D3DPOOL_MANAGED);
3974 ok(vertex_buffer_description.FVF == mesh->fvf, "Test %s, result %x, expected %x\n",
3975 name, vertex_buffer_description.FVF, mesh->fvf);
3976 if (mesh->fvf == 0)
3978 expected = number_of_vertices * mesh->vertex_size;
3980 else
3982 expected = number_of_vertices * D3DXGetFVFVertexSize(mesh->fvf);
3984 ok(vertex_buffer_description.Size == expected, "Test %s, result %x, expected %x\n",
3985 name, vertex_buffer_description.Size, expected);
3988 hr = d3dxmesh->lpVtbl->GetIndexBuffer(d3dxmesh, &index_buffer);
3989 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
3990 if (hr != D3D_OK)
3992 skip("Couldn't get index buffer\n");
3993 goto error;
3996 hr = IDirect3DIndexBuffer9_GetDesc(index_buffer, &index_buffer_description);
3997 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
3999 if (hr != D3D_OK)
4001 skip("Couldn't get index buffer description\n");
4003 else
4005 ok(index_buffer_description.Format == D3DFMT_INDEX16, "Test %s, result %x, expected %x (D3DFMT_INDEX16)\n",
4006 name, index_buffer_description.Format, D3DFMT_INDEX16);
4007 ok(index_buffer_description.Type == D3DRTYPE_INDEXBUFFER, "Test %s, result %x, expected %x (D3DRTYPE_INDEXBUFFER)\n",
4008 name, index_buffer_description.Type, D3DRTYPE_INDEXBUFFER);
4009 ok(index_buffer_description.Usage == 0, "Test %s, result %#x, expected %#x.\n",
4010 name, index_buffer_description.Usage, 0);
4011 ok(index_buffer_description.Pool == D3DPOOL_MANAGED, "Test %s, result %x, expected %x (D3DPOOL_MANAGED)\n",
4012 name, index_buffer_description.Pool, D3DPOOL_MANAGED);
4013 expected = number_of_faces * sizeof(WORD) * 3;
4014 ok(index_buffer_description.Size == expected, "Test %s, result %x, expected %x\n",
4015 name, index_buffer_description.Size, expected);
4018 /* specify offset and size to avoid potential overruns */
4019 hr = IDirect3DVertexBuffer9_Lock(vertex_buffer, 0, number_of_vertices * sizeof(D3DXVECTOR3) * 2,
4020 (void **)&vertices, D3DLOCK_DISCARD);
4021 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
4022 if (hr != D3D_OK)
4024 skip("Couldn't lock vertex buffer\n");
4025 goto error;
4027 hr = IDirect3DIndexBuffer9_Lock(index_buffer, 0, number_of_faces * sizeof(WORD) * 3,
4028 (void **)&faces, D3DLOCK_DISCARD);
4029 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
4030 if (hr != D3D_OK)
4032 skip("Couldn't lock index buffer\n");
4033 goto error;
4036 face_idx1 = 0;
4037 vtx_idx2 = 0;
4038 face_idx2 = 0;
4039 vtx_idx1 = 0;
4040 for (i = 0; i < textlen; i++)
4042 int nb_outline_vertices1, nb_outline_faces1;
4043 int nb_outline_vertices2, nb_outline_faces2;
4044 int nb_back_vertices, nb_back_faces;
4045 int first_vtx1, first_vtx2;
4046 int first_face1, first_face2;
4047 int j;
4049 first_vtx1 = vtx_idx1;
4050 first_vtx2 = vtx_idx2;
4051 /* Glyphs without outlines do not generate any vertices. */
4052 if (glyphs[i].outlines.count > 0)
4054 for (; vtx_idx1 < number_of_vertices; vtx_idx1++)
4056 if (vertices[vtx_idx1].normal.z != 0)
4057 break;
4060 for (; vtx_idx2 < mesh->number_of_vertices; vtx_idx2++)
4062 if (mesh->vertices[vtx_idx2].normal.z != 0)
4063 break;
4066 nb_outline_vertices1 = vtx_idx1 - first_vtx1;
4067 nb_outline_vertices2 = vtx_idx2 - first_vtx2;
4068 ok(nb_outline_vertices1 == nb_outline_vertices2,
4069 "Test %s, glyph %d, outline vertex count result %d, expected %d\n", name, i,
4070 nb_outline_vertices1, nb_outline_vertices2);
4072 for (j = 0; j < min(nb_outline_vertices1, nb_outline_vertices2); j++)
4074 vtx_idx1 = first_vtx1 + j;
4075 vtx_idx2 = first_vtx2 + j;
4076 ok(compare_vec3(vertices[vtx_idx1].position, mesh->vertices[vtx_idx2].position),
4077 "Test %s, glyph %d, vertex position %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1,
4078 vertices[vtx_idx1].position.x, vertices[vtx_idx1].position.y, vertices[vtx_idx1].position.z,
4079 mesh->vertices[vtx_idx2].position.x, mesh->vertices[vtx_idx2].position.y, mesh->vertices[vtx_idx2].position.z);
4080 ok(compare_vec3(vertices[vtx_idx1].normal, mesh->vertices[first_vtx2 + j].normal),
4081 "Test %s, glyph %d, vertex normal %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1,
4082 vertices[vtx_idx1].normal.x, vertices[vtx_idx1].normal.y, vertices[vtx_idx1].normal.z,
4083 mesh->vertices[vtx_idx2].normal.x, mesh->vertices[vtx_idx2].normal.y, mesh->vertices[vtx_idx2].normal.z);
4085 vtx_idx1 = first_vtx1 + nb_outline_vertices1;
4086 vtx_idx2 = first_vtx2 + nb_outline_vertices2;
4088 first_face1 = face_idx1;
4089 first_face2 = face_idx2;
4090 for (; face_idx1 < number_of_faces; face_idx1++)
4092 if (faces[face_idx1][0] >= vtx_idx1 ||
4093 faces[face_idx1][1] >= vtx_idx1 ||
4094 faces[face_idx1][2] >= vtx_idx1)
4095 break;
4097 for (; face_idx2 < mesh->number_of_faces; face_idx2++)
4099 if (mesh->faces[face_idx2][0] >= vtx_idx2 ||
4100 mesh->faces[face_idx2][1] >= vtx_idx2 ||
4101 mesh->faces[face_idx2][2] >= vtx_idx2)
4102 break;
4104 nb_outline_faces1 = face_idx1 - first_face1;
4105 nb_outline_faces2 = face_idx2 - first_face2;
4106 ok(nb_outline_faces1 == nb_outline_faces2,
4107 "Test %s, glyph %d, outline face count result %d, expected %d\n", name, i,
4108 nb_outline_faces1, nb_outline_faces2);
4110 for (j = 0; j < min(nb_outline_faces1, nb_outline_faces2); j++)
4112 face_idx1 = first_face1 + j;
4113 face_idx2 = first_face2 + j;
4114 ok(faces[face_idx1][0] - first_vtx1 == mesh->faces[face_idx2][0] - first_vtx2 &&
4115 faces[face_idx1][1] - first_vtx1 == mesh->faces[face_idx2][1] - first_vtx2 &&
4116 faces[face_idx1][2] - first_vtx1 == mesh->faces[face_idx2][2] - first_vtx2,
4117 "Test %s, glyph %d, face %d, result (%d, %d, %d), expected (%d, %d, %d)\n", name, i, face_idx1,
4118 faces[face_idx1][0], faces[face_idx1][1], faces[face_idx1][2],
4119 mesh->faces[face_idx2][0] - first_vtx2 + first_vtx1,
4120 mesh->faces[face_idx2][1] - first_vtx2 + first_vtx1,
4121 mesh->faces[face_idx2][2] - first_vtx2 + first_vtx1);
4123 face_idx1 = first_face1 + nb_outline_faces1;
4124 face_idx2 = first_face2 + nb_outline_faces2;
4126 /* partial test on back vertices and faces */
4127 first_vtx1 = vtx_idx1;
4128 for (; vtx_idx1 < number_of_vertices; vtx_idx1++) {
4129 struct vertex vtx;
4131 if (vertices[vtx_idx1].normal.z != 1.0f)
4132 break;
4134 vtx.position.z = 0.0f;
4135 vtx.normal.x = 0.0f;
4136 vtx.normal.y = 0.0f;
4137 vtx.normal.z = 1.0f;
4138 ok(compare(vertices[vtx_idx1].position.z, vtx.position.z),
4139 "Test %s, glyph %d, vertex position.z %d, result %g, expected %g\n", name, i, vtx_idx1,
4140 vertices[vtx_idx1].position.z, vtx.position.z);
4141 ok(compare_vec3(vertices[vtx_idx1].normal, vtx.normal),
4142 "Test %s, glyph %d, vertex normal %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1,
4143 vertices[vtx_idx1].normal.x, vertices[vtx_idx1].normal.y, vertices[vtx_idx1].normal.z,
4144 vtx.normal.x, vtx.normal.y, vtx.normal.z);
4146 nb_back_vertices = vtx_idx1 - first_vtx1;
4147 first_face1 = face_idx1;
4148 for (; face_idx1 < number_of_faces; face_idx1++)
4150 const D3DXVECTOR3 *vtx1, *vtx2, *vtx3;
4151 D3DXVECTOR3 normal;
4152 D3DXVECTOR3 v1 = {0, 0, 0};
4153 D3DXVECTOR3 v2 = {0, 0, 0};
4154 D3DXVECTOR3 forward = {0.0f, 0.0f, 1.0f};
4156 if (faces[face_idx1][0] >= vtx_idx1 ||
4157 faces[face_idx1][1] >= vtx_idx1 ||
4158 faces[face_idx1][2] >= vtx_idx1)
4159 break;
4161 vtx1 = &vertices[faces[face_idx1][0]].position;
4162 vtx2 = &vertices[faces[face_idx1][1]].position;
4163 vtx3 = &vertices[faces[face_idx1][2]].position;
4165 D3DXVec3Subtract(&v1, vtx2, vtx1);
4166 D3DXVec3Subtract(&v2, vtx3, vtx2);
4167 D3DXVec3Cross(&normal, &v1, &v2);
4168 D3DXVec3Normalize(&normal, &normal);
4169 ok(!D3DXVec3Length(&normal) || compare_vec3(normal, forward),
4170 "Test %s, glyph %d, face %d normal, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, face_idx1,
4171 normal.x, normal.y, normal.z, forward.x, forward.y, forward.z);
4173 nb_back_faces = face_idx1 - first_face1;
4175 /* compare front and back faces & vertices */
4176 if (extrusion == 0.0f) {
4177 /* Oddly there are only back faces in this case */
4178 nb_back_vertices /= 2;
4179 nb_back_faces /= 2;
4180 face_idx1 -= nb_back_faces;
4181 vtx_idx1 -= nb_back_vertices;
4183 for (j = 0; j < nb_back_vertices; j++)
4185 struct vertex vtx = vertices[first_vtx1];
4186 vtx.position.z = -extrusion;
4187 vtx.normal.x = 0.0f;
4188 vtx.normal.y = 0.0f;
4189 vtx.normal.z = extrusion == 0.0f ? 1.0f : -1.0f;
4190 ok(compare_vec3(vertices[vtx_idx1].position, vtx.position),
4191 "Test %s, glyph %d, vertex position %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1,
4192 vertices[vtx_idx1].position.x, vertices[vtx_idx1].position.y, vertices[vtx_idx1].position.z,
4193 vtx.position.x, vtx.position.y, vtx.position.z);
4194 ok(compare_vec3(vertices[vtx_idx1].normal, vtx.normal),
4195 "Test %s, glyph %d, vertex normal %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1,
4196 vertices[vtx_idx1].normal.x, vertices[vtx_idx1].normal.y, vertices[vtx_idx1].normal.z,
4197 vtx.normal.x, vtx.normal.y, vtx.normal.z);
4198 vtx_idx1++;
4199 first_vtx1++;
4201 for (j = 0; j < nb_back_faces; j++)
4203 int f1, f2;
4204 if (extrusion == 0.0f) {
4205 f1 = 1;
4206 f2 = 2;
4207 } else {
4208 f1 = 2;
4209 f2 = 1;
4211 ok(faces[face_idx1][0] == faces[first_face1][0] + nb_back_vertices &&
4212 faces[face_idx1][1] == faces[first_face1][f1] + nb_back_vertices &&
4213 faces[face_idx1][2] == faces[first_face1][f2] + nb_back_vertices,
4214 "Test %s, glyph %d, face %d, result (%d, %d, %d), expected (%d, %d, %d)\n", name, i, face_idx1,
4215 faces[face_idx1][0], faces[face_idx1][1], faces[face_idx1][2],
4216 faces[first_face1][0] - nb_back_faces,
4217 faces[first_face1][f1] - nb_back_faces,
4218 faces[first_face1][f2] - nb_back_faces);
4219 first_face1++;
4220 face_idx1++;
4223 /* skip to the outline for the next glyph */
4224 for (; vtx_idx2 < mesh->number_of_vertices; vtx_idx2++) {
4225 if (mesh->vertices[vtx_idx2].normal.z == 0)
4226 break;
4228 for (; face_idx2 < mesh->number_of_faces; face_idx2++)
4230 if (mesh->faces[face_idx2][0] >= vtx_idx2 ||
4231 mesh->faces[face_idx2][1] >= vtx_idx2 ||
4232 mesh->faces[face_idx2][2] >= vtx_idx2) break;
4236 error:
4237 if (vertices) IDirect3DVertexBuffer9_Unlock(vertex_buffer);
4238 if (faces) IDirect3DIndexBuffer9_Unlock(index_buffer);
4239 if (index_buffer) IDirect3DIndexBuffer9_Release(index_buffer);
4240 if (vertex_buffer) IDirect3DVertexBuffer9_Release(vertex_buffer);
4243 static void test_createtext(IDirect3DDevice9 *device, HDC hdc, const char *text, float deviation, float extrusion)
4245 HRESULT hr;
4246 ID3DXMesh *d3dxmesh = NULL;
4247 struct mesh mesh = {0};
4248 char name[256];
4249 OUTLINETEXTMETRICA otm;
4250 GLYPHMETRICS gm;
4251 struct glyphinfo *glyphs = NULL;
4252 GLYPHMETRICSFLOAT *glyphmetrics_float = HeapAlloc(GetProcessHeap(), 0, sizeof(GLYPHMETRICSFLOAT) * strlen(text));
4253 int i;
4254 LOGFONTA lf;
4255 float offset_x;
4256 size_t textlen;
4257 HFONT font = NULL, oldfont = NULL;
4258 char *raw_outline = NULL;
4260 sprintf(name, "text ('%s', %f, %f)", text, deviation, extrusion);
4262 hr = D3DXCreateTextA(device, hdc, text, deviation, extrusion, &d3dxmesh, NULL, glyphmetrics_float);
4263 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
4264 if (hr != D3D_OK)
4266 skip("Couldn't create text with D3DXCreateText\n");
4267 goto error;
4270 /* must select a modified font having lfHeight = otm.otmEMSquare before
4271 * calling GetGlyphOutline to get the expected values */
4272 if (!GetObjectA(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf)
4273 || !GetOutlineTextMetricsA(hdc, sizeof(otm), &otm))
4275 skip("Couldn't get text outline\n");
4276 goto error;
4278 lf.lfHeight = otm.otmEMSquare;
4279 lf.lfWidth = 0;
4280 if (!(font = CreateFontIndirectA(&lf)))
4282 skip("Couldn't create the modified font\n");
4283 goto error;
4286 textlen = strlen(text);
4287 glyphs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, textlen * sizeof(*glyphs));
4288 if (!glyphs)
4289 goto error;
4291 oldfont = SelectObject(hdc, font);
4293 for (i = 0; i < textlen; i++)
4295 const MAT2 identity = {{0, 1}, {0, 0}, {0, 0}, {0, 1}};
4296 GetGlyphOutlineA(hdc, text[i], GGO_NATIVE, &gm, 0, NULL, &identity);
4297 compare_float(glyphmetrics_float[i].gmfBlackBoxX, gm.gmBlackBoxX / (float)otm.otmEMSquare);
4298 compare_float(glyphmetrics_float[i].gmfBlackBoxY, gm.gmBlackBoxY / (float)otm.otmEMSquare);
4299 compare_float(glyphmetrics_float[i].gmfptGlyphOrigin.x, gm.gmptGlyphOrigin.x / (float)otm.otmEMSquare);
4300 compare_float(glyphmetrics_float[i].gmfptGlyphOrigin.y, gm.gmptGlyphOrigin.y / (float)otm.otmEMSquare);
4301 compare_float(glyphmetrics_float[i].gmfCellIncX, gm.gmCellIncX / (float)otm.otmEMSquare);
4302 compare_float(glyphmetrics_float[i].gmfCellIncY, gm.gmCellIncY / (float)otm.otmEMSquare);
4305 if (deviation == 0.0f)
4306 deviation = 1.0f / otm.otmEMSquare;
4308 offset_x = 0.0f;
4309 for (i = 0; i < textlen; i++)
4311 /* get outline points from data returned from GetGlyphOutline */
4312 const MAT2 identity = {{0, 1}, {0, 0}, {0, 0}, {0, 1}};
4313 int datasize;
4315 glyphs[i].offset_x = offset_x;
4317 datasize = GetGlyphOutlineA(hdc, text[i], GGO_NATIVE, &gm, 0, NULL, &identity);
4318 if (datasize < 0)
4320 SelectObject(hdc, oldfont);
4321 goto error;
4323 HeapFree(GetProcessHeap(), 0, raw_outline);
4324 raw_outline = HeapAlloc(GetProcessHeap(), 0, datasize);
4325 if (!raw_outline)
4327 SelectObject(hdc, oldfont);
4328 goto error;
4330 datasize = GetGlyphOutlineA(hdc, text[i], GGO_NATIVE, &gm, datasize, raw_outline, &identity);
4332 create_outline(&glyphs[i], raw_outline, datasize, deviation, otm.otmEMSquare);
4334 offset_x += gm.gmCellIncX / (float)otm.otmEMSquare;
4337 SelectObject(hdc, oldfont);
4339 ZeroMemory(&mesh, sizeof(mesh));
4340 if (!compute_text_mesh(&mesh, text, deviation, extrusion, otm.otmEMSquare, glyphs))
4342 skip("Couldn't create mesh\n");
4343 d3dxmesh->lpVtbl->Release(d3dxmesh);
4344 return;
4346 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
4348 compare_text_outline_mesh(name, d3dxmesh, &mesh, textlen, extrusion, glyphs);
4350 error:
4351 free_mesh(&mesh);
4353 if (d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh);
4354 if (font) DeleteObject(font);
4355 HeapFree(GetProcessHeap(), 0, glyphmetrics_float);
4357 if (glyphs)
4359 for (i = 0; i < textlen; i++)
4361 int j;
4362 for (j = 0; j < glyphs[i].outlines.count; j++)
4363 HeapFree(GetProcessHeap(), 0, glyphs[i].outlines.items[j].items);
4364 HeapFree(GetProcessHeap(), 0, glyphs[i].outlines.items);
4366 HeapFree(GetProcessHeap(), 0, glyphs);
4368 HeapFree(GetProcessHeap(), 0, raw_outline);
4371 static void D3DXCreateTextTest(void)
4373 HRESULT hr;
4374 HDC hdc;
4375 IDirect3DDevice9* device;
4376 ID3DXMesh* d3dxmesh = NULL;
4377 HFONT hFont;
4378 OUTLINETEXTMETRICA otm;
4379 int number_of_vertices;
4380 int number_of_faces;
4381 struct test_context *test_context;
4383 if (!(test_context = new_test_context()))
4385 skip("Couldn't create test context\n");
4386 return;
4388 device = test_context->device;
4390 hdc = CreateCompatibleDC(NULL);
4392 hFont = CreateFontA(12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
4393 CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, "Arial");
4394 SelectObject(hdc, hFont);
4395 GetOutlineTextMetricsA(hdc, sizeof(otm), &otm);
4397 hr = D3DXCreateTextA(device, hdc, "wine", 0.001f, 0.4f, NULL, NULL, NULL);
4398 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4400 /* D3DXCreateTextA page faults from passing NULL text */
4402 hr = D3DXCreateTextW(device, hdc, NULL, 0.001f, 0.4f, &d3dxmesh, NULL, NULL);
4403 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4405 hr = D3DXCreateTextA(device, hdc, "", 0.001f, 0.4f, &d3dxmesh, NULL, NULL);
4406 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4408 hr = D3DXCreateTextA(device, hdc, " ", 0.001f, 0.4f, &d3dxmesh, NULL, NULL);
4409 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4411 hr = D3DXCreateTextA(NULL, hdc, "wine", 0.001f, 0.4f, &d3dxmesh, NULL, NULL);
4412 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4414 hr = D3DXCreateTextA(device, NULL, "wine", 0.001f, 0.4f, &d3dxmesh, NULL, NULL);
4415 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4417 hr = D3DXCreateTextA(device, hdc, "wine", -FLT_MIN, 0.4f, &d3dxmesh, NULL, NULL);
4418 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4420 hr = D3DXCreateTextA(device, hdc, "wine", 0.001f, -FLT_MIN, &d3dxmesh, NULL, NULL);
4421 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4423 /* deviation = 0.0f treated as if deviation = 1.0f / otm.otmEMSquare */
4424 hr = D3DXCreateTextA(device, hdc, "wine", 1.0f / otm.otmEMSquare, 0.4f, &d3dxmesh, NULL, NULL);
4425 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
4426 number_of_vertices = d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh);
4427 number_of_faces = d3dxmesh->lpVtbl->GetNumFaces(d3dxmesh);
4428 d3dxmesh->lpVtbl->Release(d3dxmesh);
4430 hr = D3DXCreateTextA(device, hdc, "wine", 0.0f, 0.4f, &d3dxmesh, NULL, NULL);
4431 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
4432 ok(number_of_vertices == d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh),
4433 "Got %d vertices, expected %d\n",
4434 d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh), number_of_vertices);
4435 ok(number_of_faces == d3dxmesh->lpVtbl->GetNumFaces(d3dxmesh),
4436 "Got %d faces, expected %d\n",
4437 d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh), number_of_faces);
4438 d3dxmesh->lpVtbl->Release(d3dxmesh);
4440 if (0)
4442 /* too much detail requested, so will appear to hang */
4443 trace("Waiting for D3DXCreateText to finish with deviation = FLT_MIN ...\n");
4444 hr = D3DXCreateTextA(device, hdc, "wine", FLT_MIN, 0.4f, &d3dxmesh, NULL, NULL);
4445 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
4446 if (SUCCEEDED(hr) && d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh);
4447 trace("D3DXCreateText finish with deviation = FLT_MIN\n");
4450 hr = D3DXCreateTextA(device, hdc, "wine", 0.001f, 0.4f, &d3dxmesh, NULL, NULL);
4451 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
4452 if (SUCCEEDED(hr) && d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh);
4454 test_createtext(device, hdc, "wine", FLT_MAX, 0.4f);
4455 test_createtext(device, hdc, "wine", 0.001f, FLT_MIN);
4456 test_createtext(device, hdc, "wine", 0.001f, 0.0f);
4457 test_createtext(device, hdc, "wine", 0.001f, FLT_MAX);
4458 test_createtext(device, hdc, "wine", 0.0f, 1.0f);
4459 test_createtext(device, hdc, " wine", 1.0f, 0.0f);
4460 test_createtext(device, hdc, "wine ", 1.0f, 0.0f);
4461 test_createtext(device, hdc, "wi ne", 1.0f, 0.0f);
4463 DeleteDC(hdc);
4464 DeleteObject(hFont);
4466 free_test_context(test_context);
4469 static void test_get_decl_length(void)
4471 static const D3DVERTEXELEMENT9 declaration1[] =
4473 {0, 0, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4474 {1, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4475 {2, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4476 {3, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4477 {4, 0, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4478 {5, 0, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4479 {6, 0, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4480 {7, 0, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4481 {8, 0, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4482 {9, 0, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4483 {10, 0, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4484 {11, 0, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4485 {12, 0, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4486 {13, 0, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4487 {14, 0, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4488 D3DDECL_END(),
4490 static const D3DVERTEXELEMENT9 declaration2[] =
4492 {0, 8, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4493 {1, 8, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4494 {2, 8, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4495 {3, 8, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4496 {4, 8, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4497 {5, 8, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4498 {6, 8, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4499 {7, 8, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4500 {0, 8, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4501 {1, 8, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4502 {2, 8, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4503 {3, 8, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4504 {4, 8, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4505 {5, 8, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4506 {6, 8, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4507 {7, 8, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4508 D3DDECL_END(),
4510 UINT size;
4512 size = D3DXGetDeclLength(declaration1);
4513 ok(size == 15, "Got size %u, expected 15.\n", size);
4515 size = D3DXGetDeclLength(declaration2);
4516 ok(size == 16, "Got size %u, expected 16.\n", size);
4519 static void test_get_decl_vertex_size(void)
4521 static const D3DVERTEXELEMENT9 declaration1[] =
4523 {0, 0, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4524 {1, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4525 {2, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4526 {3, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4527 {4, 0, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4528 {5, 0, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4529 {6, 0, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4530 {7, 0, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4531 {8, 0, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4532 {9, 0, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4533 {10, 0, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4534 {11, 0, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4535 {12, 0, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4536 {13, 0, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4537 {14, 0, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4538 D3DDECL_END(),
4540 static const D3DVERTEXELEMENT9 declaration2[] =
4542 {0, 8, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4543 {1, 8, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4544 {2, 8, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4545 {3, 8, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4546 {4, 8, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4547 {5, 8, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4548 {6, 8, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4549 {7, 8, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4550 {0, 8, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4551 {1, 8, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4552 {2, 8, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4553 {3, 8, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4554 {4, 8, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4555 {5, 8, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4556 {6, 8, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4557 {7, 8, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4558 D3DDECL_END(),
4560 static const UINT sizes1[] =
4562 4, 8, 12, 16,
4563 4, 4, 4, 8,
4564 4, 4, 8, 4,
4565 4, 4, 8, 0,
4567 static const UINT sizes2[] =
4569 12, 16, 20, 24,
4570 12, 12, 16, 16,
4572 unsigned int i;
4573 UINT size;
4575 size = D3DXGetDeclVertexSize(NULL, 0);
4576 ok(size == 0, "Got size %#x, expected 0.\n", size);
4578 for (i = 0; i < 16; ++i)
4580 size = D3DXGetDeclVertexSize(declaration1, i);
4581 ok(size == sizes1[i], "Got size %u for stream %u, expected %u.\n", size, i, sizes1[i]);
4584 for (i = 0; i < 8; ++i)
4586 size = D3DXGetDeclVertexSize(declaration2, i);
4587 ok(size == sizes2[i], "Got size %u for stream %u, expected %u.\n", size, i, sizes2[i]);
4591 static void D3DXGenerateAdjacencyTest(void)
4593 HRESULT hr;
4594 IDirect3DDevice9 *device;
4595 ID3DXMesh *d3dxmesh = NULL;
4596 D3DXVECTOR3 *vertices = NULL;
4597 WORD *indices = NULL;
4598 int i;
4599 struct {
4600 DWORD num_vertices;
4601 D3DXVECTOR3 vertices[6];
4602 DWORD num_faces;
4603 WORD indices[3 * 3];
4604 FLOAT epsilon;
4605 DWORD adjacency[3 * 3];
4606 } test_data[] = {
4607 { /* for epsilon < 0, indices must match for faces to be adjacent */
4608 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}},
4609 2, {0, 1, 2, 0, 2, 3},
4610 -1.0,
4611 {-1, -1, 1, 0, -1, -1},
4614 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}},
4615 2, {0, 1, 2, 3, 4, 5},
4616 -1.0,
4617 {-1, -1, -1, -1, -1, -1},
4619 { /* for epsilon == 0, indices or vertices must match for faces to be adjacent */
4620 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}},
4621 2, {0, 1, 2, 3, 4, 5},
4622 0.0,
4623 {-1, -1, 1, 0, -1, -1},
4625 { /* for epsilon > 0, vertices must be less than (but NOT equal to) epsilon distance away */
4626 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}},
4627 2, {0, 1, 2, 3, 4, 5},
4628 0.25,
4629 {-1, -1, -1, -1, -1, -1},
4631 { /* for epsilon > 0, vertices must be less than (but NOT equal to) epsilon distance away */
4632 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}},
4633 2, {0, 1, 2, 3, 4, 5},
4634 0.250001,
4635 {-1, -1, 1, 0, -1, -1},
4637 { /* length between vertices are compared to epsilon, not the individual dimension deltas */
4638 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}},
4639 2, {0, 1, 2, 3, 4, 5},
4640 0.353, /* < sqrt(0.25*0.25 + 0.25*0.25) */
4641 {-1, -1, -1, -1, -1, -1},
4644 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}},
4645 2, {0, 1, 2, 3, 4, 5},
4646 0.354, /* > sqrt(0.25*0.25 + 0.25*0.25) */
4647 {-1, -1, 1, 0, -1, -1},
4649 { /* adjacent faces must have opposite winding orders at the shared edge */
4650 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}},
4651 2, {0, 1, 2, 0, 3, 2},
4652 0.0,
4653 {-1, -1, -1, -1, -1, -1},
4656 struct test_context *test_context;
4658 if (!(test_context = new_test_context()))
4660 skip("Couldn't create test context\n");
4661 return;
4663 device = test_context->device;
4665 for (i = 0; i < ARRAY_SIZE(test_data); i++)
4667 DWORD adjacency[ARRAY_SIZE(test_data[0].adjacency)];
4668 int j;
4670 if (d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh);
4671 d3dxmesh = NULL;
4673 hr = D3DXCreateMeshFVF(test_data[i].num_faces, test_data[i].num_vertices, 0, D3DFVF_XYZ, device, &d3dxmesh);
4674 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
4676 hr = d3dxmesh->lpVtbl->LockVertexBuffer(d3dxmesh, D3DLOCK_DISCARD, (void**)&vertices);
4677 ok(hr == D3D_OK, "test %d: Got result %x, expected %x (D3D_OK)\n", i, hr, D3D_OK);
4678 if (FAILED(hr)) continue;
4679 CopyMemory(vertices, test_data[i].vertices, test_data[i].num_vertices * sizeof(test_data[0].vertices[0]));
4680 d3dxmesh->lpVtbl->UnlockVertexBuffer(d3dxmesh);
4682 hr = d3dxmesh->lpVtbl->LockIndexBuffer(d3dxmesh, D3DLOCK_DISCARD, (void**)&indices);
4683 ok(hr == D3D_OK, "test %d: Got result %x, expected %x (D3D_OK)\n", i, hr, D3D_OK);
4684 if (FAILED(hr)) continue;
4685 CopyMemory(indices, test_data[i].indices, test_data[i].num_faces * 3 * sizeof(test_data[0].indices[0]));
4686 d3dxmesh->lpVtbl->UnlockIndexBuffer(d3dxmesh);
4688 if (i == 0) {
4689 hr = d3dxmesh->lpVtbl->GenerateAdjacency(d3dxmesh, 0.0f, NULL);
4690 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4693 hr = d3dxmesh->lpVtbl->GenerateAdjacency(d3dxmesh, test_data[i].epsilon, adjacency);
4694 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
4695 if (FAILED(hr)) continue;
4697 for (j = 0; j < test_data[i].num_faces * 3; j++)
4698 ok(adjacency[j] == test_data[i].adjacency[j],
4699 "Test %d adjacency %d: Got result %u, expected %u\n", i, j,
4700 adjacency[j], test_data[i].adjacency[j]);
4702 if (d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh);
4704 free_test_context(test_context);
4707 static void test_update_semantics(void)
4709 HRESULT hr;
4710 struct test_context *test_context = NULL;
4711 ID3DXMesh *mesh = NULL;
4712 D3DVERTEXELEMENT9 declaration0[] =
4714 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4715 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4716 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4717 D3DDECL_END()
4719 D3DVERTEXELEMENT9 declaration_pos_type_color[] =
4721 {0, 0, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4722 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4723 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4724 D3DDECL_END()
4726 D3DVERTEXELEMENT9 declaration_smaller[] =
4728 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4729 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4730 D3DDECL_END()
4732 D3DVERTEXELEMENT9 declaration_larger[] =
4734 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4735 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4736 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4737 {0, 40, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT, 0},
4738 D3DDECL_END()
4740 D3DVERTEXELEMENT9 declaration_multiple_streams[] =
4742 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4743 {1, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT, 0},
4744 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4745 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4747 D3DDECL_END()
4749 D3DVERTEXELEMENT9 declaration_double_usage[] =
4751 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4752 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4753 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4754 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4755 D3DDECL_END()
4757 D3DVERTEXELEMENT9 declaration_undefined_type[] =
4759 {0, 0, D3DDECLTYPE_UNUSED+1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4760 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4761 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4762 D3DDECL_END()
4764 D3DVERTEXELEMENT9 declaration_not_4_byte_aligned_offset[] =
4766 {0, 3, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4767 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4768 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4769 D3DDECL_END()
4771 static const struct
4773 D3DXVECTOR3 position0;
4774 D3DXVECTOR3 position1;
4775 D3DXVECTOR3 normal;
4776 DWORD color;
4778 vertices[] =
4780 { { 0.0f, 1.0f, 0.f}, { 1.0f, 0.0f, 0.f}, {0.0f, 0.0f, 1.0f}, 0xffff0000 },
4781 { { 1.0f, -1.0f, 0.f}, {-1.0f, -1.0f, 0.f}, {0.0f, 0.0f, 1.0f}, 0xff00ff00 },
4782 { {-1.0f, -1.0f, 0.f}, {-1.0f, 1.0f, 0.f}, {0.0f, 0.0f, 1.0f}, 0xff0000ff },
4784 unsigned int faces[] = {0, 1, 2};
4785 unsigned int attributes[] = {0};
4786 unsigned int num_faces = ARRAY_SIZE(faces) / 3;
4787 unsigned int num_vertices = ARRAY_SIZE(vertices);
4788 int offset = sizeof(D3DXVECTOR3);
4789 DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
4790 void *vertex_buffer;
4791 void *index_buffer;
4792 DWORD *attributes_buffer;
4793 D3DVERTEXELEMENT9 declaration[MAX_FVF_DECL_SIZE];
4794 D3DVERTEXELEMENT9 *decl_ptr;
4795 DWORD exp_vertex_size = sizeof(*vertices);
4796 DWORD vertex_size = 0;
4797 int equal;
4798 int i = 0;
4799 int *decl_mem;
4800 int filler_a = 0xaaaaaaaa;
4801 int filler_b = 0xbbbbbbbb;
4803 test_context = new_test_context();
4804 if (!test_context)
4806 skip("Couldn't create a test_context\n");
4807 goto cleanup;
4810 hr = D3DXCreateMesh(num_faces, num_vertices, options, declaration0,
4811 test_context->device, &mesh);
4812 if (FAILED(hr))
4814 skip("Couldn't create test mesh %#x\n", hr);
4815 goto cleanup;
4818 mesh->lpVtbl->LockVertexBuffer(mesh, 0, &vertex_buffer);
4819 memcpy(vertex_buffer, vertices, sizeof(vertices));
4820 mesh->lpVtbl->UnlockVertexBuffer(mesh);
4822 mesh->lpVtbl->LockIndexBuffer(mesh, 0, &index_buffer);
4823 memcpy(index_buffer, faces, sizeof(faces));
4824 mesh->lpVtbl->UnlockIndexBuffer(mesh);
4826 mesh->lpVtbl->LockAttributeBuffer(mesh, 0, &attributes_buffer);
4827 memcpy(attributes_buffer, attributes, sizeof(attributes));
4828 mesh->lpVtbl->UnlockAttributeBuffer(mesh);
4830 /* Get the declaration and try to change it */
4831 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4832 if (FAILED(hr))
4834 skip("Couldn't get vertex declaration %#x\n", hr);
4835 goto cleanup;
4837 equal = memcmp(declaration, declaration0, sizeof(declaration0));
4838 ok(equal == 0, "Vertex declarations were not equal\n");
4840 for (decl_ptr = declaration; decl_ptr->Stream != 0xFF; decl_ptr++)
4842 if (decl_ptr->Usage == D3DDECLUSAGE_POSITION)
4844 /* Use second vertex position instead of first */
4845 decl_ptr->Offset = offset;
4849 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration);
4850 ok(hr == D3D_OK, "Test UpdateSemantics, got %#x expected %#x\n", hr, D3D_OK);
4852 /* Check that declaration was written by getting it again */
4853 memset(declaration, 0, sizeof(declaration));
4854 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4855 if (FAILED(hr))
4857 skip("Couldn't get vertex declaration %#x\n", hr);
4858 goto cleanup;
4861 for (decl_ptr = declaration; decl_ptr->Stream != 0xFF; decl_ptr++)
4863 if (decl_ptr->Usage == D3DDECLUSAGE_POSITION)
4865 ok(decl_ptr->Offset == offset, "Test UpdateSemantics, got offset %d expected %d\n",
4866 decl_ptr->Offset, offset);
4870 /* Check that GetDeclaration only writes up to the D3DDECL_END() marker and
4871 * not the full MAX_FVF_DECL_SIZE elements.
4873 memset(declaration, filler_a, sizeof(declaration));
4874 memcpy(declaration, declaration0, sizeof(declaration0));
4875 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration);
4876 ok(hr == D3D_OK, "Test UpdateSemantics, "
4877 "got %#x expected D3D_OK\n", hr);
4878 memset(declaration, filler_b, sizeof(declaration));
4879 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4880 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4881 decl_mem = (int*)declaration;
4882 for (i = sizeof(declaration0)/sizeof(*decl_mem); i < sizeof(declaration)/sizeof(*decl_mem); i++)
4884 equal = memcmp(&decl_mem[i], &filler_b, sizeof(filler_b));
4885 ok(equal == 0,
4886 "GetDeclaration wrote past the D3DDECL_END() marker. "
4887 "Got %#x, expected %#x\n", decl_mem[i], filler_b);
4888 if (equal != 0) break;
4891 /* UpdateSemantics does not check for overlapping fields */
4892 memset(declaration, 0, sizeof(declaration));
4893 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4894 if (FAILED(hr))
4896 skip("Couldn't get vertex declaration %#x\n", hr);
4897 goto cleanup;
4900 for (decl_ptr = declaration; decl_ptr->Stream != 0xFF; decl_ptr++)
4902 if (decl_ptr->Type == D3DDECLTYPE_FLOAT3)
4904 decl_ptr->Type = D3DDECLTYPE_FLOAT4;
4908 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration);
4909 ok(hr == D3D_OK, "Test UpdateSemantics for overlapping fields, "
4910 "got %#x expected D3D_OK\n", hr);
4912 /* Set the position type to color instead of float3 */
4913 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_pos_type_color);
4914 ok(hr == D3D_OK, "Test UpdateSemantics position type color, "
4915 "got %#x expected D3D_OK\n", hr);
4917 /* The following test cases show that NULL, smaller or larger declarations,
4918 * and declarations with non-zero Stream values are not accepted.
4919 * UpdateSemantics returns D3DERR_INVALIDCALL and the previously set
4920 * declaration will be used by DrawSubset, GetNumBytesPerVertex, and
4921 * GetDeclaration.
4924 /* Null declaration (invalid declaration) */
4925 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4926 hr = mesh->lpVtbl->UpdateSemantics(mesh, NULL);
4927 ok(hr == D3DERR_INVALIDCALL, "Test UpdateSemantics null pointer declaration, "
4928 "got %#x expected D3DERR_INVALIDCALL\n", hr);
4929 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4930 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4931 vertex_size, exp_vertex_size);
4932 memset(declaration, 0, sizeof(declaration));
4933 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4934 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4935 equal = memcmp(declaration, declaration0, sizeof(declaration0));
4936 ok(equal == 0, "Vertex declarations were not equal\n");
4938 /* Smaller vertex declaration (invalid declaration) */
4939 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4940 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_smaller);
4941 ok(hr == D3DERR_INVALIDCALL, "Test UpdateSemantics for smaller vertex declaration, "
4942 "got %#x expected D3DERR_INVALIDCALL\n", hr);
4943 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4944 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4945 vertex_size, exp_vertex_size);
4946 memset(declaration, 0, sizeof(declaration));
4947 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4948 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4949 equal = memcmp(declaration, declaration0, sizeof(declaration0));
4950 ok(equal == 0, "Vertex declarations were not equal\n");
4952 /* Larger vertex declaration (invalid declaration) */
4953 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4954 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_larger);
4955 ok(hr == D3DERR_INVALIDCALL, "Test UpdateSemantics for larger vertex declaration, "
4956 "got %#x expected D3DERR_INVALIDCALL\n", hr);
4957 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4958 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4959 vertex_size, exp_vertex_size);
4960 memset(declaration, 0, sizeof(declaration));
4961 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4962 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4963 equal = memcmp(declaration, declaration0, sizeof(declaration0));
4964 ok(equal == 0, "Vertex declarations were not equal\n");
4966 /* Use multiple streams and keep the same vertex size (invalid declaration) */
4967 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4968 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_multiple_streams);
4969 ok(hr == D3DERR_INVALIDCALL, "Test UpdateSemantics using multiple streams, "
4970 "got %#x expected D3DERR_INVALIDCALL\n", hr);
4971 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4972 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4973 vertex_size, exp_vertex_size);
4974 memset(declaration, 0, sizeof(declaration));
4975 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4976 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4977 equal = memcmp(declaration, declaration0, sizeof(declaration0));
4978 ok(equal == 0, "Vertex declarations were not equal\n");
4980 /* The next following test cases show that some invalid declarations are
4981 * accepted with a D3D_OK. An access violation is thrown on Windows if
4982 * DrawSubset is called. The methods GetNumBytesPerVertex and GetDeclaration
4983 * are not affected, which indicates that the declaration is cached.
4986 /* Double usage (invalid declaration) */
4987 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4988 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_double_usage);
4989 ok(hr == D3D_OK, "Test UpdateSemantics double usage, "
4990 "got %#x expected D3D_OK\n", hr);
4991 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4992 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4993 vertex_size, exp_vertex_size);
4994 memset(declaration, 0, sizeof(declaration));
4995 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4996 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4997 equal = memcmp(declaration, declaration_double_usage, sizeof(declaration_double_usage));
4998 ok(equal == 0, "Vertex declarations were not equal\n");
5000 /* Set the position to an undefined type (invalid declaration) */
5001 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
5002 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_undefined_type);
5003 ok(hr == D3D_OK, "Test UpdateSemantics undefined type, "
5004 "got %#x expected D3D_OK\n", hr);
5005 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
5006 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
5007 vertex_size, exp_vertex_size);
5008 memset(declaration, 0, sizeof(declaration));
5009 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
5010 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
5011 equal = memcmp(declaration, declaration_undefined_type, sizeof(declaration_undefined_type));
5012 ok(equal == 0, "Vertex declarations were not equal\n");
5014 /* Use a not 4 byte aligned offset (invalid declaration) */
5015 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
5016 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_not_4_byte_aligned_offset);
5017 ok(hr == D3D_OK, "Test UpdateSemantics not 4 byte aligned offset, "
5018 "got %#x expected D3D_OK\n", hr);
5019 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
5020 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
5021 vertex_size, exp_vertex_size);
5022 memset(declaration, 0, sizeof(declaration));
5023 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
5024 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
5025 equal = memcmp(declaration, declaration_not_4_byte_aligned_offset,
5026 sizeof(declaration_not_4_byte_aligned_offset));
5027 ok(equal == 0, "Vertex declarations were not equal\n");
5029 cleanup:
5030 if (mesh)
5031 mesh->lpVtbl->Release(mesh);
5033 free_test_context(test_context);
5036 static void test_create_skin_info(void)
5038 HRESULT hr;
5039 ID3DXSkinInfo *skininfo = NULL;
5040 D3DVERTEXELEMENT9 empty_declaration[] = { D3DDECL_END() };
5041 D3DVERTEXELEMENT9 declaration_out[MAX_FVF_DECL_SIZE];
5042 const D3DVERTEXELEMENT9 declaration_with_nonzero_stream[] = {
5043 {1, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
5044 D3DDECL_END()
5047 hr = D3DXCreateSkinInfo(0, empty_declaration, 0, &skininfo);
5048 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5049 if (skininfo) IUnknown_Release(skininfo);
5050 skininfo = NULL;
5052 hr = D3DXCreateSkinInfo(1, NULL, 1, &skininfo);
5053 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5055 hr = D3DXCreateSkinInfo(1, declaration_with_nonzero_stream, 1, &skininfo);
5056 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5058 hr = D3DXCreateSkinInfoFVF(1, 0, 1, &skininfo);
5059 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5060 if (skininfo)
5062 DWORD dword_result;
5063 float flt_result;
5064 const char *string_result;
5065 D3DXMATRIX *transform;
5066 D3DXMATRIX identity_matrix;
5068 /* test initial values */
5069 hr = skininfo->lpVtbl->GetDeclaration(skininfo, declaration_out);
5070 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5071 if (SUCCEEDED(hr))
5072 compare_elements(declaration_out, empty_declaration, __LINE__, 0);
5074 dword_result = skininfo->lpVtbl->GetNumBones(skininfo);
5075 ok(dword_result == 1, "Expected 1, got %u\n", dword_result);
5077 flt_result = skininfo->lpVtbl->GetMinBoneInfluence(skininfo);
5078 ok(flt_result == 0.0f, "Expected 0.0, got %g\n", flt_result);
5080 string_result = skininfo->lpVtbl->GetBoneName(skininfo, 0);
5081 ok(string_result == NULL, "Expected NULL, got %p\n", string_result);
5083 dword_result = skininfo->lpVtbl->GetFVF(skininfo);
5084 ok(dword_result == 0, "Expected 0, got %u\n", dword_result);
5086 dword_result = skininfo->lpVtbl->GetNumBoneInfluences(skininfo, 0);
5087 ok(dword_result == 0, "Expected 0, got %u\n", dword_result);
5089 dword_result = skininfo->lpVtbl->GetNumBoneInfluences(skininfo, 1);
5090 ok(dword_result == 0, "Expected 0, got %u\n", dword_result);
5092 transform = skininfo->lpVtbl->GetBoneOffsetMatrix(skininfo, -1);
5093 ok(transform == NULL, "Expected NULL, got %p\n", transform);
5096 /* test [GS]etBoneOffsetMatrix */
5097 hr = skininfo->lpVtbl->SetBoneOffsetMatrix(skininfo, 1, &identity_matrix);
5098 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5100 hr = skininfo->lpVtbl->SetBoneOffsetMatrix(skininfo, 0, NULL);
5101 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5103 D3DXMatrixIdentity(&identity_matrix);
5104 hr = skininfo->lpVtbl->SetBoneOffsetMatrix(skininfo, 0, &identity_matrix);
5105 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5107 transform = skininfo->lpVtbl->GetBoneOffsetMatrix(skininfo, 0);
5108 check_matrix(transform, &identity_matrix);
5112 /* test [GS]etBoneName */
5113 const char *name_in = "testBoneName";
5114 const char *string_result2;
5116 hr = skininfo->lpVtbl->SetBoneName(skininfo, 1, name_in);
5117 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5119 hr = skininfo->lpVtbl->SetBoneName(skininfo, 0, NULL);
5120 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5122 hr = skininfo->lpVtbl->SetBoneName(skininfo, 0, name_in);
5123 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5125 string_result = skininfo->lpVtbl->GetBoneName(skininfo, 0);
5126 ok(string_result != NULL, "Expected non-NULL string, got %p\n", string_result);
5127 ok(!strcmp(string_result, name_in), "Expected '%s', got '%s'\n", name_in, string_result);
5129 string_result2 = skininfo->lpVtbl->GetBoneName(skininfo, 0);
5130 ok(string_result == string_result2, "Expected %p, got %p\n", string_result, string_result2);
5132 string_result = skininfo->lpVtbl->GetBoneName(skininfo, 1);
5133 ok(string_result == NULL, "Expected NULL, got %p\n", string_result);
5137 /* test [GS]etBoneInfluence */
5138 DWORD vertices[2];
5139 FLOAT weights[2];
5140 int i;
5141 DWORD num_influences;
5142 DWORD exp_vertices[2];
5143 FLOAT exp_weights[2];
5145 /* vertex and weight arrays untouched when num_influences is 0 */
5146 vertices[0] = 0xdeadbeef;
5147 weights[0] = FLT_MAX;
5148 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, vertices, weights);
5149 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5150 ok(vertices[0] == 0xdeadbeef, "expected 0xdeadbeef, got %#x\n", vertices[0]);
5151 ok(weights[0] == FLT_MAX, "expected %g, got %g\n", FLT_MAX, weights[0]);
5153 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 1, vertices, weights);
5154 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5156 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, NULL, NULL);
5157 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5159 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, vertices, NULL);
5160 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5162 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, NULL, weights);
5163 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5166 /* no vertex or weight value checking */
5167 exp_vertices[0] = 0;
5168 exp_vertices[1] = 0x87654321;
5169 exp_weights[0] = 0.5;
5170 exp_weights[1] = NAN;
5171 num_influences = 2;
5173 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 1, num_influences, vertices, weights);
5174 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5176 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, num_influences, NULL, weights);
5177 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5179 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, num_influences, vertices, NULL);
5180 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5182 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, num_influences, NULL, NULL);
5183 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5185 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, num_influences, exp_vertices, exp_weights);
5186 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5188 memset(vertices, 0, sizeof(vertices));
5189 memset(weights, 0, sizeof(weights));
5190 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, vertices, weights);
5191 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5192 for (i = 0; i < num_influences; i++) {
5193 ok(exp_vertices[i] == vertices[i],
5194 "influence[%d]: expected vertex %u, got %u\n", i, exp_vertices[i], vertices[i]);
5195 ok((isnan(exp_weights[i]) && isnan(weights[i])) || exp_weights[i] == weights[i],
5196 "influence[%d]: expected weights %g, got %g\n", i, exp_weights[i], weights[i]);
5199 /* vertices and weights aren't returned after setting num_influences to 0 */
5200 memset(vertices, 0, sizeof(vertices));
5201 memset(weights, 0, sizeof(weights));
5202 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, 0, vertices, weights);
5203 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5205 vertices[0] = 0xdeadbeef;
5206 weights[0] = FLT_MAX;
5207 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, vertices, weights);
5208 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5209 ok(vertices[0] == 0xdeadbeef, "expected vertex 0xdeadbeef, got %u\n", vertices[0]);
5210 ok(weights[0] == FLT_MAX, "expected weight %g, got %g\n", FLT_MAX, weights[0]);
5214 /* test [GS]etFVF and [GS]etDeclaration */
5215 D3DVERTEXELEMENT9 declaration_in[MAX_FVF_DECL_SIZE];
5216 DWORD fvf = D3DFVF_XYZ;
5217 DWORD got_fvf;
5219 hr = skininfo->lpVtbl->SetDeclaration(skininfo, NULL);
5220 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5222 hr = skininfo->lpVtbl->SetDeclaration(skininfo, declaration_with_nonzero_stream);
5223 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5225 hr = skininfo->lpVtbl->SetFVF(skininfo, 0);
5226 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5228 hr = D3DXDeclaratorFromFVF(fvf, declaration_in);
5229 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5230 hr = skininfo->lpVtbl->SetDeclaration(skininfo, declaration_in);
5231 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5232 got_fvf = skininfo->lpVtbl->GetFVF(skininfo);
5233 ok(fvf == got_fvf, "Expected %#x, got %#x\n", fvf, got_fvf);
5234 hr = skininfo->lpVtbl->GetDeclaration(skininfo, declaration_out);
5235 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5236 compare_elements(declaration_out, declaration_in, __LINE__, 0);
5238 hr = skininfo->lpVtbl->SetDeclaration(skininfo, empty_declaration);
5239 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5240 got_fvf = skininfo->lpVtbl->GetFVF(skininfo);
5241 ok(got_fvf == 0, "Expected 0, got %#x\n", got_fvf);
5242 hr = skininfo->lpVtbl->GetDeclaration(skininfo, declaration_out);
5243 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5244 compare_elements(declaration_out, empty_declaration, __LINE__, 0);
5246 hr = skininfo->lpVtbl->SetFVF(skininfo, fvf);
5247 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5248 got_fvf = skininfo->lpVtbl->GetFVF(skininfo);
5249 ok(fvf == got_fvf, "Expected %#x, got %#x\n", fvf, got_fvf);
5250 hr = skininfo->lpVtbl->GetDeclaration(skininfo, declaration_out);
5251 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5252 compare_elements(declaration_out, declaration_in, __LINE__, 0);
5255 if (skininfo) IUnknown_Release(skininfo);
5256 skininfo = NULL;
5258 hr = D3DXCreateSkinInfoFVF(1, D3DFVF_XYZ, 1, NULL);
5259 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5261 hr = D3DXCreateSkinInfo(1, NULL, 1, &skininfo);
5262 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5265 static void test_convert_adjacency_to_point_reps(void)
5267 HRESULT hr;
5268 struct test_context *test_context = NULL;
5269 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
5270 const DWORD options_16bit = D3DXMESH_SYSTEMMEM;
5271 const D3DVERTEXELEMENT9 declaration[] =
5273 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
5274 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
5275 {0, 24, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
5276 D3DDECL_END()
5278 const unsigned int VERTS_PER_FACE = 3;
5279 void *vertex_buffer;
5280 void *index_buffer;
5281 DWORD *attributes_buffer;
5282 int i, j;
5283 enum color { RED = 0xffff0000, GREEN = 0xff00ff00, BLUE = 0xff0000ff};
5284 struct vertex_pnc
5286 D3DXVECTOR3 position;
5287 D3DXVECTOR3 normal;
5288 enum color color; /* In case of manual visual inspection */
5290 D3DXVECTOR3 up = {0.0f, 0.0f, 1.0f};
5291 /* mesh0 (one face)
5293 * 0--1
5294 * | /
5295 * |/
5298 const struct vertex_pnc vertices0[] =
5300 {{ 0.0f, 3.0f, 0.f}, up, RED},
5301 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5302 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5304 const DWORD indices0[] = {0, 1, 2};
5305 const unsigned int num_vertices0 = ARRAY_SIZE(vertices0);
5306 const unsigned int num_faces0 = ARRAY_SIZE(indices0) / VERTS_PER_FACE;
5307 const DWORD adjacency0[] = {-1, -1, -1};
5308 const DWORD exp_point_rep0[] = {0, 1, 2};
5309 /* mesh1 (right)
5311 * 0--1 3
5312 * | / /|
5313 * |/ / |
5314 * 2 5--4
5316 const struct vertex_pnc vertices1[] =
5318 {{ 0.0f, 3.0f, 0.f}, up, RED},
5319 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5320 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5322 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5323 {{ 3.0f, 0.0f, 0.f}, up, RED},
5324 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5326 const DWORD indices1[] = {0, 1, 2, 3, 4, 5};
5327 const unsigned int num_vertices1 = ARRAY_SIZE(vertices1);
5328 const unsigned int num_faces1 = ARRAY_SIZE(indices1) / VERTS_PER_FACE;
5329 const DWORD adjacency1[] = {-1, 1, -1, -1, -1, 0};
5330 const DWORD exp_point_rep1[] = {0, 1, 2, 1, 4, 2};
5331 /* mesh2 (left)
5333 * 3 0--1
5334 * /| | /
5335 * / | |/
5336 * 5--4 2
5338 const struct vertex_pnc vertices2[] =
5340 {{ 0.0f, 3.0f, 0.f}, up, RED},
5341 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5342 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5344 {{-1.0f, 3.0f, 0.f}, up, RED},
5345 {{-1.0f, 0.0f, 0.f}, up, GREEN},
5346 {{-3.0f, 0.0f, 0.f}, up, BLUE},
5348 const DWORD indices2[] = {0, 1, 2, 3, 4, 5};
5349 const unsigned int num_vertices2 = ARRAY_SIZE(vertices2);
5350 const unsigned int num_faces2 = ARRAY_SIZE(indices2) / VERTS_PER_FACE;
5351 const DWORD adjacency2[] = {-1, -1, 1, 0, -1, -1};
5352 const DWORD exp_point_rep2[] = {0, 1, 2, 0, 2, 5};
5353 /* mesh3 (above)
5356 * /|
5357 * / |
5358 * 5--4
5359 * 0--1
5360 * | /
5361 * |/
5364 struct vertex_pnc vertices3[] =
5366 {{ 0.0f, 3.0f, 0.f}, up, RED},
5367 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5368 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5370 {{ 2.0f, 7.0f, 0.f}, up, BLUE},
5371 {{ 2.0f, 4.0f, 0.f}, up, GREEN},
5372 {{ 0.0f, 4.0f, 0.f}, up, RED},
5374 const DWORD indices3[] = {0, 1, 2, 3, 4, 5};
5375 const unsigned int num_vertices3 = ARRAY_SIZE(vertices3);
5376 const unsigned int num_faces3 = ARRAY_SIZE(indices3) / VERTS_PER_FACE;
5377 const DWORD adjacency3[] = {1, -1, -1, -1, 0, -1};
5378 const DWORD exp_point_rep3[] = {0, 1, 2, 3, 1, 0};
5379 /* mesh4 (below, tip against tip)
5381 * 0--1
5382 * | /
5383 * |/
5386 * |\
5387 * | \
5388 * 5--4
5390 struct vertex_pnc vertices4[] =
5392 {{ 0.0f, 3.0f, 0.f}, up, RED},
5393 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5394 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5396 {{ 0.0f, -4.0f, 0.f}, up, BLUE},
5397 {{ 2.0f, -7.0f, 0.f}, up, GREEN},
5398 {{ 0.0f, -7.0f, 0.f}, up, RED},
5400 const DWORD indices4[] = {0, 1, 2, 3, 4, 5};
5401 const unsigned int num_vertices4 = ARRAY_SIZE(vertices4);
5402 const unsigned int num_faces4 = ARRAY_SIZE(indices4) / VERTS_PER_FACE;
5403 const DWORD adjacency4[] = {-1, -1, -1, -1, -1, -1};
5404 const DWORD exp_point_rep4[] = {0, 1, 2, 3, 4, 5};
5405 /* mesh5 (gap in mesh)
5407 * 0 3-----4 15
5408 * / \ \ / / \
5409 * / \ \ / / \
5410 * 2-----1 5 17-----16
5411 * 6-----7 9 12-----13
5412 * \ / / \ \ /
5413 * \ / / \ \ /
5414 * 8 10-----11 14
5417 const struct vertex_pnc vertices5[] =
5419 {{ 0.0f, 1.0f, 0.f}, up, RED},
5420 {{ 1.0f, -1.0f, 0.f}, up, GREEN},
5421 {{-1.0f, -1.0f, 0.f}, up, BLUE},
5423 {{ 0.1f, 1.0f, 0.f}, up, RED},
5424 {{ 2.1f, 1.0f, 0.f}, up, BLUE},
5425 {{ 1.1f, -1.0f, 0.f}, up, GREEN},
5427 {{-1.0f, -1.1f, 0.f}, up, BLUE},
5428 {{ 1.0f, -1.1f, 0.f}, up, GREEN},
5429 {{ 0.0f, -3.1f, 0.f}, up, RED},
5431 {{ 1.1f, -1.1f, 0.f}, up, GREEN},
5432 {{ 2.1f, -3.1f, 0.f}, up, BLUE},
5433 {{ 0.1f, -3.1f, 0.f}, up, RED},
5435 {{ 1.2f, -1.1f, 0.f}, up, GREEN},
5436 {{ 3.2f, -1.1f, 0.f}, up, RED},
5437 {{ 2.2f, -3.1f, 0.f}, up, BLUE},
5439 {{ 2.2f, 1.0f, 0.f}, up, BLUE},
5440 {{ 3.2f, -1.0f, 0.f}, up, RED},
5441 {{ 1.2f, -1.0f, 0.f}, up, GREEN},
5443 const DWORD indices5[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17};
5444 const unsigned int num_vertices5 = ARRAY_SIZE(vertices5);
5445 const unsigned int num_faces5 = ARRAY_SIZE(indices5) / VERTS_PER_FACE;
5446 const DWORD adjacency5[] = {-1, 2, -1, -1, 5, -1, 0, -1, -1, 4, -1, -1, 5, -1, 3, -1, 4, 1};
5447 const DWORD exp_point_rep5[] = {0, 1, 2, 3, 4, 5, 2, 1, 8, 5, 10, 11, 5, 13, 10, 4, 13, 5};
5448 const WORD indices5_16bit[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17};
5449 /* mesh6 (indices re-ordering)
5451 * 0--1 6 3
5452 * | / /| |\
5453 * |/ / | | \
5454 * 2 8--7 5--4
5456 const struct vertex_pnc vertices6[] =
5458 {{ 0.0f, 3.0f, 0.f}, up, RED},
5459 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5460 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5462 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5463 {{ 3.0f, 0.0f, 0.f}, up, RED},
5464 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5466 {{ 4.0f, 3.0f, 0.f}, up, GREEN},
5467 {{ 6.0f, 0.0f, 0.f}, up, BLUE},
5468 {{ 4.0f, 0.0f, 0.f}, up, RED},
5470 const DWORD indices6[] = {0, 1, 2, 6, 7, 8, 3, 4, 5};
5471 const unsigned int num_vertices6 = ARRAY_SIZE(vertices6);
5472 const unsigned int num_faces6 = ARRAY_SIZE(indices6) / VERTS_PER_FACE;
5473 const DWORD adjacency6[] = {-1, 1, -1, 2, -1, 0, -1, -1, 1};
5474 const DWORD exp_point_rep6[] = {0, 1, 2, 1, 4, 5, 1, 5, 2};
5475 /* mesh7 (expands collapsed triangle)
5477 * 0--1 3
5478 * | / /|
5479 * |/ / |
5480 * 2 5--4
5482 const struct vertex_pnc vertices7[] =
5484 {{ 0.0f, 3.0f, 0.f}, up, RED},
5485 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5486 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5488 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5489 {{ 3.0f, 0.0f, 0.f}, up, RED},
5490 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5492 const DWORD indices7[] = {0, 1, 2, 3, 3, 3}; /* Face 1 is collapsed*/
5493 const unsigned int num_vertices7 = ARRAY_SIZE(vertices7);
5494 const unsigned int num_faces7 = ARRAY_SIZE(indices7) / VERTS_PER_FACE;
5495 const DWORD adjacency7[] = {-1, -1, -1, -1, -1, -1};
5496 const DWORD exp_point_rep7[] = {0, 1, 2, 3, 4, 5};
5497 /* mesh8 (indices re-ordering and double replacement)
5499 * 0--1 9 6
5500 * | / /| |\
5501 * |/ / | | \
5502 * 2 11-10 8--7
5503 * 3--4
5504 * | /
5505 * |/
5508 const struct vertex_pnc vertices8[] =
5510 {{ 0.0f, 3.0f, 0.f}, up, RED},
5511 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5512 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5514 {{ 4.0, -4.0, 0.f}, up, RED},
5515 {{ 6.0, -4.0, 0.f}, up, BLUE},
5516 {{ 4.0, -7.0, 0.f}, up, GREEN},
5518 {{ 4.0f, 3.0f, 0.f}, up, GREEN},
5519 {{ 6.0f, 0.0f, 0.f}, up, BLUE},
5520 {{ 4.0f, 0.0f, 0.f}, up, RED},
5522 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5523 {{ 3.0f, 0.0f, 0.f}, up, RED},
5524 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5526 const DWORD indices8[] = {0, 1, 2, 9, 10, 11, 6, 7, 8, 3, 4, 5};
5527 const unsigned int num_vertices8 = ARRAY_SIZE(vertices8);
5528 const unsigned int num_faces8 = ARRAY_SIZE(indices8) / VERTS_PER_FACE;
5529 const DWORD adjacency8[] = {-1, 1, -1, 2, -1, 0, -1, 3, 1, 2, -1, -1};
5530 const DWORD exp_point_rep8[] = {0, 1, 2, 3, 4, 5, 1, 4, 3, 1, 3, 2};
5531 /* mesh9 (right, shared vertices)
5533 * 0--1
5534 * | /|
5535 * |/ |
5536 * 2--3
5538 const struct vertex_pnc vertices9[] =
5540 {{ 0.0f, 3.0f, 0.f}, up, RED},
5541 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5542 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5544 {{ 2.0f, 0.0f, 0.f}, up, RED},
5546 const DWORD indices9[] = {0, 1, 2, 1, 3, 2};
5547 const unsigned int num_vertices9 = ARRAY_SIZE(vertices9);
5548 const unsigned int num_faces9 = ARRAY_SIZE(indices9) / VERTS_PER_FACE;
5549 const DWORD adjacency9[] = {-1, 1, -1, -1, -1, 0};
5550 const DWORD exp_point_rep9[] = {0, 1, 2, 3};
5551 /* All mesh data */
5552 ID3DXMesh *mesh = NULL;
5553 ID3DXMesh *mesh_null_check = NULL;
5554 unsigned int attributes[] = {0};
5555 struct
5557 const struct vertex_pnc *vertices;
5558 const DWORD *indices;
5559 const DWORD num_vertices;
5560 const DWORD num_faces;
5561 const DWORD *adjacency;
5562 const DWORD *exp_point_reps;
5563 const DWORD options;
5565 tc[] =
5568 vertices0,
5569 indices0,
5570 num_vertices0,
5571 num_faces0,
5572 adjacency0,
5573 exp_point_rep0,
5574 options
5577 vertices1,
5578 indices1,
5579 num_vertices1,
5580 num_faces1,
5581 adjacency1,
5582 exp_point_rep1,
5583 options
5586 vertices2,
5587 indices2,
5588 num_vertices2,
5589 num_faces2,
5590 adjacency2,
5591 exp_point_rep2,
5592 options
5595 vertices3,
5596 indices3,
5597 num_vertices3,
5598 num_faces3,
5599 adjacency3,
5600 exp_point_rep3,
5601 options
5604 vertices4,
5605 indices4,
5606 num_vertices4,
5607 num_faces4,
5608 adjacency4,
5609 exp_point_rep4,
5610 options
5613 vertices5,
5614 indices5,
5615 num_vertices5,
5616 num_faces5,
5617 adjacency5,
5618 exp_point_rep5,
5619 options
5622 vertices6,
5623 indices6,
5624 num_vertices6,
5625 num_faces6,
5626 adjacency6,
5627 exp_point_rep6,
5628 options
5631 vertices7,
5632 indices7,
5633 num_vertices7,
5634 num_faces7,
5635 adjacency7,
5636 exp_point_rep7,
5637 options
5640 vertices8,
5641 indices8,
5642 num_vertices8,
5643 num_faces8,
5644 adjacency8,
5645 exp_point_rep8,
5646 options
5649 vertices9,
5650 indices9,
5651 num_vertices9,
5652 num_faces9,
5653 adjacency9,
5654 exp_point_rep9,
5655 options
5658 vertices5,
5659 (DWORD*)indices5_16bit,
5660 num_vertices5,
5661 num_faces5,
5662 adjacency5,
5663 exp_point_rep5,
5664 options_16bit
5667 DWORD *point_reps = NULL;
5669 test_context = new_test_context();
5670 if (!test_context)
5672 skip("Couldn't create test context\n");
5673 goto cleanup;
5676 for (i = 0; i < ARRAY_SIZE(tc); i++)
5678 hr = D3DXCreateMesh(tc[i].num_faces, tc[i].num_vertices, tc[i].options, declaration,
5679 test_context->device, &mesh);
5680 if (FAILED(hr))
5682 skip("Couldn't create mesh %d. Got %x expected D3D_OK\n", i, hr);
5683 goto cleanup;
5686 if (i == 0) /* Save first mesh for later NULL checks */
5687 mesh_null_check = mesh;
5689 point_reps = HeapAlloc(GetProcessHeap(), 0, tc[i].num_vertices * sizeof(*point_reps));
5690 if (!point_reps)
5692 skip("Couldn't allocate point reps array.\n");
5693 goto cleanup;
5696 hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, &vertex_buffer);
5697 if (FAILED(hr))
5699 skip("Couldn't lock vertex buffer.\n");
5700 goto cleanup;
5702 memcpy(vertex_buffer, tc[i].vertices, tc[i].num_vertices * sizeof(*tc[i].vertices));
5703 hr = mesh->lpVtbl->UnlockVertexBuffer(mesh);
5704 if (FAILED(hr))
5706 skip("Couldn't unlock vertex buffer.\n");
5707 goto cleanup;
5710 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, &index_buffer);
5711 if (FAILED(hr))
5713 skip("Couldn't lock index buffer.\n");
5714 goto cleanup;
5716 if (tc[i].options & D3DXMESH_32BIT)
5718 memcpy(index_buffer, tc[i].indices, VERTS_PER_FACE * tc[i].num_faces * sizeof(DWORD));
5720 else
5722 memcpy(index_buffer, tc[i].indices, VERTS_PER_FACE * tc[i].num_faces * sizeof(WORD));
5724 hr = mesh->lpVtbl->UnlockIndexBuffer(mesh);
5725 if (FAILED(hr)) {
5726 skip("Couldn't unlock index buffer.\n");
5727 goto cleanup;
5730 hr = mesh->lpVtbl->LockAttributeBuffer(mesh, 0, &attributes_buffer);
5731 if (FAILED(hr))
5733 skip("Couldn't lock attributes buffer.\n");
5734 goto cleanup;
5736 memcpy(attributes_buffer, attributes, sizeof(attributes));
5737 hr = mesh->lpVtbl->UnlockAttributeBuffer(mesh);
5738 if (FAILED(hr))
5740 skip("Couldn't unlock attributes buffer.\n");
5741 goto cleanup;
5744 /* Convert adjacency to point representation */
5745 for (j = 0; j < tc[i].num_vertices; j++) point_reps[j] = -1;
5746 hr = mesh->lpVtbl->ConvertAdjacencyToPointReps(mesh, tc[i].adjacency, point_reps);
5747 ok(hr == D3D_OK, "ConvertAdjacencyToPointReps failed case %d. "
5748 "Got %x expected D3D_OK\n", i, hr);
5750 /* Check point representation */
5751 for (j = 0; j < tc[i].num_vertices; j++)
5753 ok(point_reps[j] == tc[i].exp_point_reps[j],
5754 "Unexpected point representation at (%d, %d)."
5755 " Got %d expected %d\n",
5756 i, j, point_reps[j], tc[i].exp_point_reps[j]);
5759 HeapFree(GetProcessHeap(), 0, point_reps);
5760 point_reps = NULL;
5762 if (i != 0) /* First mesh will be freed during cleanup */
5763 mesh->lpVtbl->Release(mesh);
5766 /* NULL checks */
5767 hr = mesh_null_check->lpVtbl->ConvertAdjacencyToPointReps(mesh_null_check, tc[0].adjacency, NULL);
5768 ok(hr == D3DERR_INVALIDCALL, "ConvertAdjacencyToPointReps point_reps NULL. "
5769 "Got %x expected D3DERR_INVALIDCALL\n", hr);
5770 hr = mesh_null_check->lpVtbl->ConvertAdjacencyToPointReps(mesh_null_check, NULL, NULL);
5771 ok(hr == D3DERR_INVALIDCALL, "ConvertAdjacencyToPointReps adjacency and point_reps NULL. "
5772 "Got %x expected D3DERR_INVALIDCALL\n", hr);
5774 cleanup:
5775 if (mesh_null_check)
5776 mesh_null_check->lpVtbl->Release(mesh_null_check);
5777 HeapFree(GetProcessHeap(), 0, point_reps);
5778 free_test_context(test_context);
5781 static void test_convert_point_reps_to_adjacency(void)
5783 HRESULT hr;
5784 struct test_context *test_context = NULL;
5785 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
5786 const DWORD options_16bit = D3DXMESH_SYSTEMMEM;
5787 const D3DVERTEXELEMENT9 declaration[] =
5789 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
5790 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
5791 {0, 24, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
5792 D3DDECL_END()
5794 const unsigned int VERTS_PER_FACE = 3;
5795 void *vertex_buffer;
5796 void *index_buffer;
5797 DWORD *attributes_buffer;
5798 int i, j;
5799 enum color { RED = 0xffff0000, GREEN = 0xff00ff00, BLUE = 0xff0000ff};
5800 struct vertex_pnc
5802 D3DXVECTOR3 position;
5803 D3DXVECTOR3 normal;
5804 enum color color; /* In case of manual visual inspection */
5806 D3DXVECTOR3 up = {0.0f, 0.0f, 1.0f};
5807 /* mesh0 (one face)
5809 * 0--1
5810 * | /
5811 * |/
5814 const struct vertex_pnc vertices0[] =
5816 {{ 0.0f, 3.0f, 0.f}, up, RED},
5817 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5818 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5820 const DWORD indices0[] = {0, 1, 2};
5821 const unsigned int num_vertices0 = ARRAY_SIZE(vertices0);
5822 const unsigned int num_faces0 = num_vertices0 / VERTS_PER_FACE;
5823 const DWORD exp_adjacency0[] = {-1, -1, -1};
5824 const DWORD exp_id_adjacency0[] = {-1, -1, -1};
5825 const DWORD point_rep0[] = {0, 1, 2};
5826 /* mesh1 (right)
5828 * 0--1 3
5829 * | / /|
5830 * |/ / |
5831 * 2 5--4
5833 const struct vertex_pnc vertices1[] =
5835 {{ 0.0f, 3.0f, 0.f}, up, RED},
5836 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5837 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5839 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5840 {{ 3.0f, 0.0f, 0.f}, up, RED},
5841 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5843 const DWORD indices1[] = {0, 1, 2, 3, 4, 5};
5844 const unsigned int num_vertices1 = ARRAY_SIZE(vertices1);
5845 const unsigned int num_faces1 = num_vertices1 / VERTS_PER_FACE;
5846 const DWORD exp_adjacency1[] = {-1, 1, -1, -1, -1, 0};
5847 const DWORD exp_id_adjacency1[] = {-1, -1, -1, -1, -1, -1};
5848 const DWORD point_rep1[] = {0, 1, 2, 1, 4, 2};
5849 /* mesh2 (left)
5851 * 3 0--1
5852 * /| | /
5853 * / | |/
5854 * 5--4 2
5856 const struct vertex_pnc vertices2[] =
5858 {{ 0.0f, 3.0f, 0.f}, up, RED},
5859 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5860 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5862 {{-1.0f, 3.0f, 0.f}, up, RED},
5863 {{-1.0f, 0.0f, 0.f}, up, GREEN},
5864 {{-3.0f, 0.0f, 0.f}, up, BLUE},
5866 const DWORD indices2[] = {0, 1, 2, 3, 4, 5};
5867 const unsigned int num_vertices2 = ARRAY_SIZE(vertices2);
5868 const unsigned int num_faces2 = num_vertices2 / VERTS_PER_FACE;
5869 const DWORD exp_adjacency2[] = {-1, -1, 1, 0, -1, -1};
5870 const DWORD exp_id_adjacency2[] = {-1, -1, -1, -1, -1, -1};
5871 const DWORD point_rep2[] = {0, 1, 2, 0, 2, 5};
5872 /* mesh3 (above)
5875 * /|
5876 * / |
5877 * 5--4
5878 * 0--1
5879 * | /
5880 * |/
5883 struct vertex_pnc vertices3[] =
5885 {{ 0.0f, 3.0f, 0.f}, up, RED},
5886 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5887 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5889 {{ 2.0f, 7.0f, 0.f}, up, BLUE},
5890 {{ 2.0f, 4.0f, 0.f}, up, GREEN},
5891 {{ 0.0f, 4.0f, 0.f}, up, RED},
5893 const DWORD indices3[] = {0, 1, 2, 3, 4, 5};
5894 const unsigned int num_vertices3 = ARRAY_SIZE(vertices3);
5895 const unsigned int num_faces3 = num_vertices3 / VERTS_PER_FACE;
5896 const DWORD exp_adjacency3[] = {1, -1, -1, -1, 0, -1};
5897 const DWORD exp_id_adjacency3[] = {-1, -1, -1, -1, -1, -1};
5898 const DWORD point_rep3[] = {0, 1, 2, 3, 1, 0};
5899 /* mesh4 (below, tip against tip)
5901 * 0--1
5902 * | /
5903 * |/
5906 * |\
5907 * | \
5908 * 5--4
5910 struct vertex_pnc vertices4[] =
5912 {{ 0.0f, 3.0f, 0.f}, up, RED},
5913 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5914 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5916 {{ 0.0f, -4.0f, 0.f}, up, BLUE},
5917 {{ 2.0f, -7.0f, 0.f}, up, GREEN},
5918 {{ 0.0f, -7.0f, 0.f}, up, RED},
5920 const DWORD indices4[] = {0, 1, 2, 3, 4, 5};
5921 const unsigned int num_vertices4 = ARRAY_SIZE(vertices4);
5922 const unsigned int num_faces4 = num_vertices4 / VERTS_PER_FACE;
5923 const DWORD exp_adjacency4[] = {-1, -1, -1, -1, -1, -1};
5924 const DWORD exp_id_adjacency4[] = {-1, -1, -1, -1, -1, -1};
5925 const DWORD point_rep4[] = {0, 1, 2, 3, 4, 5};
5926 /* mesh5 (gap in mesh)
5928 * 0 3-----4 15
5929 * / \ \ / / \
5930 * / \ \ / / \
5931 * 2-----1 5 17-----16
5932 * 6-----7 9 12-----13
5933 * \ / / \ \ /
5934 * \ / / \ \ /
5935 * 8 10-----11 14
5938 const struct vertex_pnc vertices5[] =
5940 {{ 0.0f, 1.0f, 0.f}, up, RED},
5941 {{ 1.0f, -1.0f, 0.f}, up, GREEN},
5942 {{-1.0f, -1.0f, 0.f}, up, BLUE},
5944 {{ 0.1f, 1.0f, 0.f}, up, RED},
5945 {{ 2.1f, 1.0f, 0.f}, up, BLUE},
5946 {{ 1.1f, -1.0f, 0.f}, up, GREEN},
5948 {{-1.0f, -1.1f, 0.f}, up, BLUE},
5949 {{ 1.0f, -1.1f, 0.f}, up, GREEN},
5950 {{ 0.0f, -3.1f, 0.f}, up, RED},
5952 {{ 1.1f, -1.1f, 0.f}, up, GREEN},
5953 {{ 2.1f, -3.1f, 0.f}, up, BLUE},
5954 {{ 0.1f, -3.1f, 0.f}, up, RED},
5956 {{ 1.2f, -1.1f, 0.f}, up, GREEN},
5957 {{ 3.2f, -1.1f, 0.f}, up, RED},
5958 {{ 2.2f, -3.1f, 0.f}, up, BLUE},
5960 {{ 2.2f, 1.0f, 0.f}, up, BLUE},
5961 {{ 3.2f, -1.0f, 0.f}, up, RED},
5962 {{ 1.2f, -1.0f, 0.f}, up, GREEN},
5964 const DWORD indices5[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17};
5965 const unsigned int num_vertices5 = ARRAY_SIZE(vertices5);
5966 const unsigned int num_faces5 = num_vertices5 / VERTS_PER_FACE;
5967 const DWORD exp_adjacency5[] = {-1, 2, -1, -1, 5, -1, 0, -1, -1, 4, -1, -1, 5, -1, 3, -1, 4, 1};
5968 const DWORD exp_id_adjacency5[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
5969 const DWORD point_rep5[] = {0, 1, 2, 3, 4, 5, 2, 1, 8, 5, 10, 11, 5, 13, 10, 4, 13, 5};
5970 /* mesh6 (indices re-ordering)
5972 * 0--1 6 3
5973 * | / /| |\
5974 * |/ / | | \
5975 * 2 8--7 5--4
5977 const struct vertex_pnc vertices6[] =
5979 {{ 0.0f, 3.0f, 0.f}, up, RED},
5980 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5981 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5983 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5984 {{ 3.0f, 0.0f, 0.f}, up, RED},
5985 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5987 {{ 4.0f, 3.0f, 0.f}, up, GREEN},
5988 {{ 6.0f, 0.0f, 0.f}, up, BLUE},
5989 {{ 4.0f, 0.0f, 0.f}, up, RED},
5991 const DWORD indices6[] = {0, 1, 2, 6, 7, 8, 3, 4, 5};
5992 const unsigned int num_vertices6 = ARRAY_SIZE(vertices6);
5993 const unsigned int num_faces6 = num_vertices6 / VERTS_PER_FACE;
5994 const DWORD exp_adjacency6[] = {-1, 1, -1, 2, -1, 0, -1, -1, 1};
5995 const DWORD exp_id_adjacency6[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1};
5996 const DWORD point_rep6[] = {0, 1, 2, 1, 4, 5, 1, 5, 2};
5997 /* mesh7 (expands collapsed triangle)
5999 * 0--1 3
6000 * | / /|
6001 * |/ / |
6002 * 2 5--4
6004 const struct vertex_pnc vertices7[] =
6006 {{ 0.0f, 3.0f, 0.f}, up, RED},
6007 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
6008 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
6010 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
6011 {{ 3.0f, 0.0f, 0.f}, up, RED},
6012 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
6014 const DWORD indices7[] = {0, 1, 2, 3, 3, 3}; /* Face 1 is collapsed*/
6015 const unsigned int num_vertices7 = ARRAY_SIZE(vertices7);
6016 const unsigned int num_faces7 = num_vertices7 / VERTS_PER_FACE;
6017 const DWORD exp_adjacency7[] = {-1, -1, -1, -1, -1, -1};
6018 const DWORD exp_id_adjacency7[] = {-1, -1, -1, -1, -1, -1};
6019 const DWORD point_rep7[] = {0, 1, 2, 3, 4, 5};
6020 /* mesh8 (indices re-ordering and double replacement)
6022 * 0--1 9 6
6023 * | / /| |\
6024 * |/ / | | \
6025 * 2 11-10 8--7
6026 * 3--4
6027 * | /
6028 * |/
6031 const struct vertex_pnc vertices8[] =
6033 {{ 0.0f, 3.0f, 0.f}, up, RED},
6034 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
6035 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
6037 {{ 4.0, -4.0, 0.f}, up, RED},
6038 {{ 6.0, -4.0, 0.f}, up, BLUE},
6039 {{ 4.0, -7.0, 0.f}, up, GREEN},
6041 {{ 4.0f, 3.0f, 0.f}, up, GREEN},
6042 {{ 6.0f, 0.0f, 0.f}, up, BLUE},
6043 {{ 4.0f, 0.0f, 0.f}, up, RED},
6045 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
6046 {{ 3.0f, 0.0f, 0.f}, up, RED},
6047 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
6049 const DWORD indices8[] = {0, 1, 2, 9, 10, 11, 6, 7, 8, 3, 4, 5};
6050 const WORD indices8_16bit[] = {0, 1, 2, 9, 10, 11, 6, 7, 8, 3, 4, 5};
6051 const unsigned int num_vertices8 = ARRAY_SIZE(vertices8);
6052 const unsigned int num_faces8 = num_vertices8 / VERTS_PER_FACE;
6053 const DWORD exp_adjacency8[] = {-1, 1, -1, 2, -1, 0, -1, 3, 1, 2, -1, -1};
6054 const DWORD exp_id_adjacency8[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
6055 const DWORD point_rep8[] = {0, 1, 2, 3, 4, 5, 1, 4, 3, 1, 3, 2};
6056 /* mesh9 (right, shared vertices)
6058 * 0--1
6059 * | /|
6060 * |/ |
6061 * 2--3
6063 const struct vertex_pnc vertices9[] =
6065 {{ 0.0f, 3.0f, 0.f}, up, RED},
6066 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
6067 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
6069 {{ 2.0f, 0.0f, 0.f}, up, RED},
6071 const DWORD indices9[] = {0, 1, 2, 1, 3, 2};
6072 const unsigned int num_vertices9 = ARRAY_SIZE(vertices9);
6073 const unsigned int num_faces9 = 2;
6074 const DWORD exp_adjacency9[] = {-1, 1, -1, -1, -1, 0};
6075 const DWORD exp_id_adjacency9[] = {-1, 1, -1, -1, -1, 0};
6076 const DWORD point_rep9[] = {0, 1, 2, 3};
6077 /* All mesh data */
6078 ID3DXMesh *mesh = NULL;
6079 ID3DXMesh *mesh_null_check = NULL;
6080 unsigned int attributes[] = {0};
6081 struct
6083 const struct vertex_pnc *vertices;
6084 const DWORD *indices;
6085 const DWORD num_vertices;
6086 const DWORD num_faces;
6087 const DWORD *point_reps;
6088 const DWORD *exp_adjacency;
6089 const DWORD *exp_id_adjacency;
6090 const DWORD options;
6092 tc[] =
6095 vertices0,
6096 indices0,
6097 num_vertices0,
6098 num_faces0,
6099 point_rep0,
6100 exp_adjacency0,
6101 exp_id_adjacency0,
6102 options
6105 vertices1,
6106 indices1,
6107 num_vertices1,
6108 num_faces1,
6109 point_rep1,
6110 exp_adjacency1,
6111 exp_id_adjacency1,
6112 options
6115 vertices2,
6116 indices2,
6117 num_vertices2,
6118 num_faces2,
6119 point_rep2,
6120 exp_adjacency2,
6121 exp_id_adjacency2,
6122 options
6125 vertices3,
6126 indices3,
6127 num_vertices3,
6128 num_faces3,
6129 point_rep3,
6130 exp_adjacency3,
6131 exp_id_adjacency3,
6132 options
6135 vertices4,
6136 indices4,
6137 num_vertices4,
6138 num_faces4,
6139 point_rep4,
6140 exp_adjacency4,
6141 exp_id_adjacency4,
6142 options
6145 vertices5,
6146 indices5,
6147 num_vertices5,
6148 num_faces5,
6149 point_rep5,
6150 exp_adjacency5,
6151 exp_id_adjacency5,
6152 options
6155 vertices6,
6156 indices6,
6157 num_vertices6,
6158 num_faces6,
6159 point_rep6,
6160 exp_adjacency6,
6161 exp_id_adjacency6,
6162 options
6165 vertices7,
6166 indices7,
6167 num_vertices7,
6168 num_faces7,
6169 point_rep7,
6170 exp_adjacency7,
6171 exp_id_adjacency7,
6172 options
6175 vertices8,
6176 indices8,
6177 num_vertices8,
6178 num_faces8,
6179 point_rep8,
6180 exp_adjacency8,
6181 exp_id_adjacency8,
6182 options
6185 vertices9,
6186 indices9,
6187 num_vertices9,
6188 num_faces9,
6189 point_rep9,
6190 exp_adjacency9,
6191 exp_id_adjacency9,
6192 options
6195 vertices8,
6196 (DWORD*)indices8_16bit,
6197 num_vertices8,
6198 num_faces8,
6199 point_rep8,
6200 exp_adjacency8,
6201 exp_id_adjacency8,
6202 options_16bit
6205 DWORD *adjacency = NULL;
6207 test_context = new_test_context();
6208 if (!test_context)
6210 skip("Couldn't create test context\n");
6211 goto cleanup;
6214 for (i = 0; i < ARRAY_SIZE(tc); i++)
6216 hr = D3DXCreateMesh(tc[i].num_faces, tc[i].num_vertices, tc[i].options,
6217 declaration, test_context->device, &mesh);
6218 if (FAILED(hr))
6220 skip("Couldn't create mesh %d. Got %x expected D3D_OK\n", i, hr);
6221 goto cleanup;
6224 if (i == 0) /* Save first mesh for later NULL checks */
6225 mesh_null_check = mesh;
6227 adjacency = HeapAlloc(GetProcessHeap(), 0, VERTS_PER_FACE * tc[i].num_faces * sizeof(*adjacency));
6228 if (!adjacency)
6230 skip("Couldn't allocate adjacency array.\n");
6231 goto cleanup;
6234 hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, &vertex_buffer);
6235 if (FAILED(hr))
6237 skip("Couldn't lock vertex buffer.\n");
6238 goto cleanup;
6240 memcpy(vertex_buffer, tc[i].vertices, tc[i].num_vertices * sizeof(*tc[i].vertices));
6241 hr = mesh->lpVtbl->UnlockVertexBuffer(mesh);
6242 if (FAILED(hr))
6244 skip("Couldn't unlock vertex buffer.\n");
6245 goto cleanup;
6247 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, &index_buffer);
6248 if (FAILED(hr))
6250 skip("Couldn't lock index buffer.\n");
6251 goto cleanup;
6253 if (tc[i].options & D3DXMESH_32BIT)
6255 memcpy(index_buffer, tc[i].indices, VERTS_PER_FACE * tc[i].num_faces * sizeof(DWORD));
6257 else
6259 memcpy(index_buffer, tc[i].indices, VERTS_PER_FACE * tc[i].num_faces * sizeof(WORD));
6261 hr = mesh->lpVtbl->UnlockIndexBuffer(mesh);
6262 if (FAILED(hr)) {
6263 skip("Couldn't unlock index buffer.\n");
6264 goto cleanup;
6267 hr = mesh->lpVtbl->LockAttributeBuffer(mesh, 0, &attributes_buffer);
6268 if (FAILED(hr))
6270 skip("Couldn't lock attributes buffer.\n");
6271 goto cleanup;
6273 memcpy(attributes_buffer, attributes, sizeof(attributes));
6274 hr = mesh->lpVtbl->UnlockAttributeBuffer(mesh);
6275 if (FAILED(hr))
6277 skip("Couldn't unlock attributes buffer.\n");
6278 goto cleanup;
6281 /* Convert point representation to adjacency*/
6282 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++) adjacency[j] = -2;
6284 hr = mesh->lpVtbl->ConvertPointRepsToAdjacency(mesh, tc[i].point_reps, adjacency);
6285 ok(hr == D3D_OK, "ConvertPointRepsToAdjacency failed case %d. "
6286 "Got %x expected D3D_OK\n", i, hr);
6287 /* Check adjacency */
6288 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
6290 ok(adjacency[j] == tc[i].exp_adjacency[j],
6291 "Unexpected adjacency information at (%d, %d)."
6292 " Got %d expected %d\n",
6293 i, j, adjacency[j], tc[i].exp_adjacency[j]);
6296 /* NULL point representation is considered identity. */
6297 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++) adjacency[j] = -2;
6298 hr = mesh_null_check->lpVtbl->ConvertPointRepsToAdjacency(mesh, NULL, adjacency);
6299 ok(hr == D3D_OK, "ConvertPointRepsToAdjacency NULL point_reps. "
6300 "Got %x expected D3D_OK\n", hr);
6301 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
6303 ok(adjacency[j] == tc[i].exp_id_adjacency[j],
6304 "Unexpected adjacency information (id) at (%d, %d)."
6305 " Got %d expected %d\n",
6306 i, j, adjacency[j], tc[i].exp_id_adjacency[j]);
6309 HeapFree(GetProcessHeap(), 0, adjacency);
6310 adjacency = NULL;
6311 if (i != 0) /* First mesh will be freed during cleanup */
6312 mesh->lpVtbl->Release(mesh);
6315 /* NULL checks */
6316 hr = mesh_null_check->lpVtbl->ConvertPointRepsToAdjacency(mesh_null_check, tc[0].point_reps, NULL);
6317 ok(hr == D3DERR_INVALIDCALL, "ConvertPointRepsToAdjacency NULL adjacency. "
6318 "Got %x expected D3DERR_INVALIDCALL\n", hr);
6319 hr = mesh_null_check->lpVtbl->ConvertPointRepsToAdjacency(mesh_null_check, NULL, NULL);
6320 ok(hr == D3DERR_INVALIDCALL, "ConvertPointRepsToAdjacency NULL point_reps and adjacency. "
6321 "Got %x expected D3DERR_INVALIDCALL\n", hr);
6323 cleanup:
6324 if (mesh_null_check)
6325 mesh_null_check->lpVtbl->Release(mesh_null_check);
6326 HeapFree(GetProcessHeap(), 0, adjacency);
6327 free_test_context(test_context);
6330 static HRESULT init_test_mesh(const DWORD num_faces, const DWORD num_vertices,
6331 const DWORD options,
6332 const D3DVERTEXELEMENT9 *declaration,
6333 IDirect3DDevice9 *device, ID3DXMesh **mesh_ptr,
6334 const void *vertices, const DWORD vertex_size,
6335 const DWORD *indices, const DWORD *attributes)
6337 HRESULT hr;
6338 void *vertex_buffer;
6339 void *index_buffer;
6340 DWORD *attributes_buffer;
6341 ID3DXMesh *mesh = NULL;
6343 hr = D3DXCreateMesh(num_faces, num_vertices, options, declaration, device, mesh_ptr);
6344 if (FAILED(hr))
6346 skip("Couldn't create mesh. Got %x expected D3D_OK\n", hr);
6347 goto cleanup;
6349 mesh = *mesh_ptr;
6351 hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, &vertex_buffer);
6352 if (FAILED(hr))
6354 skip("Couldn't lock vertex buffer.\n");
6355 goto cleanup;
6357 memcpy(vertex_buffer, vertices, num_vertices * vertex_size);
6358 hr = mesh->lpVtbl->UnlockVertexBuffer(mesh);
6359 if (FAILED(hr))
6361 skip("Couldn't unlock vertex buffer.\n");
6362 goto cleanup;
6365 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, &index_buffer);
6366 if (FAILED(hr))
6368 skip("Couldn't lock index buffer.\n");
6369 goto cleanup;
6371 if (options & D3DXMESH_32BIT)
6373 if (indices)
6374 memcpy(index_buffer, indices, 3 * num_faces * sizeof(DWORD));
6375 else
6377 /* Fill index buffer with 0, 1, 2, ...*/
6378 DWORD *indices_32bit = (DWORD*)index_buffer;
6379 UINT i;
6380 for (i = 0; i < 3 * num_faces; i++)
6381 indices_32bit[i] = i;
6384 else
6386 if (indices)
6387 memcpy(index_buffer, indices, 3 * num_faces * sizeof(WORD));
6388 else
6390 /* Fill index buffer with 0, 1, 2, ...*/
6391 WORD *indices_16bit = (WORD*)index_buffer;
6392 UINT i;
6393 for (i = 0; i < 3 * num_faces; i++)
6394 indices_16bit[i] = i;
6397 hr = mesh->lpVtbl->UnlockIndexBuffer(mesh);
6398 if (FAILED(hr)) {
6399 skip("Couldn't unlock index buffer.\n");
6400 goto cleanup;
6403 hr = mesh->lpVtbl->LockAttributeBuffer(mesh, 0, &attributes_buffer);
6404 if (FAILED(hr))
6406 skip("Couldn't lock attributes buffer.\n");
6407 goto cleanup;
6410 if (attributes)
6411 memcpy(attributes_buffer, attributes, num_faces * sizeof(*attributes));
6412 else
6413 memset(attributes_buffer, 0, num_faces * sizeof(*attributes));
6415 hr = mesh->lpVtbl->UnlockAttributeBuffer(mesh);
6416 if (FAILED(hr))
6418 skip("Couldn't unlock attributes buffer.\n");
6419 goto cleanup;
6422 hr = D3D_OK;
6423 cleanup:
6424 return hr;
6427 /* Using structs instead of bit-fields in order to avoid compiler issues. */
6428 struct udec3
6430 UINT x;
6431 UINT y;
6432 UINT z;
6433 UINT w;
6436 struct dec3n
6438 INT x;
6439 INT y;
6440 INT z;
6441 INT w;
6444 static DWORD init_udec3_dword(UINT x, UINT y, UINT z, UINT w)
6446 DWORD d = 0;
6448 d |= x & 0x3ff;
6449 d |= (y << 10) & 0xffc00;
6450 d |= (z << 20) & 0x3ff00000;
6451 d |= (w << 30) & 0xc0000000;
6453 return d;
6456 static DWORD init_dec3n_dword(INT x, INT y, INT z, INT w)
6458 DWORD d = 0;
6460 d |= x & 0x3ff;
6461 d |= (y << 10) & 0xffc00;
6462 d |= (z << 20) & 0x3ff00000;
6463 d |= (w << 30) & 0xc0000000;
6465 return d;
6468 static struct udec3 dword_to_udec3(DWORD d)
6470 struct udec3 v;
6472 v.x = d & 0x3ff;
6473 v.y = (d & 0xffc00) >> 10;
6474 v.z = (d & 0x3ff00000) >> 20;
6475 v.w = (d & 0xc0000000) >> 30;
6477 return v;
6480 static struct dec3n dword_to_dec3n(DWORD d)
6482 struct dec3n v;
6484 v.x = d & 0x3ff;
6485 v.y = (d & 0xffc00) >> 10;
6486 v.z = (d & 0x3ff00000) >> 20;
6487 v.w = (d & 0xc0000000) >> 30;
6489 return v;
6492 static void check_vertex_components(int line, int mesh_number, int vertex_number, BYTE *got_ptr, const BYTE *exp_ptr, D3DVERTEXELEMENT9 *declaration)
6494 const char *usage_strings[] =
6496 "position",
6497 "blend weight",
6498 "blend indices",
6499 "normal",
6500 "point size",
6501 "texture coordinates",
6502 "tangent",
6503 "binormal",
6504 "tessellation factor",
6505 "position transformed",
6506 "color",
6507 "fog",
6508 "depth",
6509 "sample"
6511 D3DVERTEXELEMENT9 *decl_ptr;
6512 const float PRECISION = 1e-5f;
6514 for (decl_ptr = declaration; decl_ptr->Stream != 0xFF; decl_ptr++)
6516 switch (decl_ptr->Type)
6518 case D3DDECLTYPE_FLOAT1:
6520 FLOAT *got = (FLOAT*)(got_ptr + decl_ptr->Offset);
6521 FLOAT *exp = (FLOAT*)(exp_ptr + decl_ptr->Offset);
6522 FLOAT diff = fabsf(*got - *exp);
6523 ok_(__FILE__,line)(diff <= PRECISION, "Mesh %d: Got %f for vertex %d %s, expected %f.\n",
6524 mesh_number, *got, vertex_number, usage_strings[decl_ptr->Usage], *exp);
6525 break;
6527 case D3DDECLTYPE_FLOAT2:
6529 D3DXVECTOR2 *got = (D3DXVECTOR2*)(got_ptr + decl_ptr->Offset);
6530 D3DXVECTOR2 *exp = (D3DXVECTOR2*)(exp_ptr + decl_ptr->Offset);
6531 FLOAT diff = max(fabsf(got->x - exp->x), fabsf(got->y - exp->y));
6532 ok_(__FILE__,line)(diff <= PRECISION, "Mesh %d: Got (%f, %f) for vertex %d %s, expected (%f, %f).\n",
6533 mesh_number, got->x, got->y, vertex_number, usage_strings[decl_ptr->Usage], exp->x, exp->y);
6534 break;
6536 case D3DDECLTYPE_FLOAT3:
6538 D3DXVECTOR3 *got = (D3DXVECTOR3*)(got_ptr + decl_ptr->Offset);
6539 D3DXVECTOR3 *exp = (D3DXVECTOR3*)(exp_ptr + decl_ptr->Offset);
6540 FLOAT diff = max(fabsf(got->x - exp->x), fabsf(got->y - exp->y));
6541 diff = max(diff, fabsf(got->z - exp->z));
6542 ok_(__FILE__,line)(diff <= PRECISION, "Mesh %d: Got (%f, %f, %f) for vertex %d %s, expected (%f, %f, %f).\n",
6543 mesh_number, got->x, got->y, got->z, vertex_number, usage_strings[decl_ptr->Usage], exp->x, exp->y, exp->z);
6544 break;
6546 case D3DDECLTYPE_FLOAT4:
6548 D3DXVECTOR4 *got = (D3DXVECTOR4*)(got_ptr + decl_ptr->Offset);
6549 D3DXVECTOR4 *exp = (D3DXVECTOR4*)(exp_ptr + decl_ptr->Offset);
6550 FLOAT diff = max(fabsf(got->x - exp->x), fabsf(got->y - exp->y));
6551 diff = max(diff, fabsf(got->z - exp->z));
6552 diff = max(diff, fabsf(got->w - exp->w));
6553 ok_(__FILE__,line)(diff <= PRECISION, "Mesh %d: Got (%f, %f, %f, %f) for vertex %d %s, expected (%f, %f, %f, %f).\n",
6554 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);
6555 break;
6557 case D3DDECLTYPE_D3DCOLOR:
6559 BYTE *got = got_ptr + decl_ptr->Offset;
6560 const BYTE *exp = exp_ptr + decl_ptr->Offset;
6561 BOOL same_color = got[0] == exp[0] && got[1] == exp[1]
6562 && got[2] == exp[2] && got[3] == exp[3];
6563 const char *color_types[] = {"diffuse", "specular", "undefined color"};
6564 BYTE usage_index = decl_ptr->UsageIndex;
6565 if (usage_index > 1) usage_index = 2;
6566 ok_(__FILE__,line)(same_color, "Mesh %d: Got (%u, %u, %u, %u) for vertex %d %s, expected (%u, %u, %u, %u).\n",
6567 mesh_number, got[0], got[1], got[2], got[3], vertex_number, color_types[usage_index], exp[0], exp[1], exp[2], exp[3]);
6568 break;
6570 case D3DDECLTYPE_UBYTE4:
6571 case D3DDECLTYPE_UBYTE4N:
6573 BYTE *got = got_ptr + decl_ptr->Offset;
6574 const BYTE *exp = exp_ptr + decl_ptr->Offset;
6575 BOOL same = got[0] == exp[0] && got[1] == exp[1]
6576 && got[2] == exp[2] && got[3] == exp[3];
6577 ok_(__FILE__,line)(same, "Mesh %d: Got (%u, %u, %u, %u) for vertex %d %s, expected (%u, %u, %u, %u).\n",
6578 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]);
6579 break;
6581 case D3DDECLTYPE_SHORT2:
6582 case D3DDECLTYPE_SHORT2N:
6584 SHORT *got = (SHORT*)(got_ptr + decl_ptr->Offset);
6585 SHORT *exp = (SHORT*)(exp_ptr + decl_ptr->Offset);
6586 BOOL same = got[0] == exp[0] && got[1] == exp[1];
6587 ok_(__FILE__,line)(same, "Mesh %d: Got (%hd, %hd) for vertex %d %s, expected (%hd, %hd).\n",
6588 mesh_number, got[0], got[1], vertex_number, usage_strings[decl_ptr->Usage], exp[0], exp[1]);
6589 break;
6591 case D3DDECLTYPE_SHORT4:
6592 case D3DDECLTYPE_SHORT4N:
6594 SHORT *got = (SHORT*)(got_ptr + decl_ptr->Offset);
6595 SHORT *exp = (SHORT*)(exp_ptr + decl_ptr->Offset);
6596 BOOL same = got[0] == exp[0] && got[1] == exp[1]
6597 && got[2] == exp[2] && got[3] == exp[3];
6598 ok_(__FILE__,line)(same, "Mesh %d: Got (%hd, %hd, %hd, %hd) for vertex %d %s, expected (%hd, %hd, %hd, %hd).\n",
6599 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]);
6600 break;
6602 case D3DDECLTYPE_USHORT2N:
6604 USHORT *got = (USHORT*)(got_ptr + decl_ptr->Offset);
6605 USHORT *exp = (USHORT*)(exp_ptr + decl_ptr->Offset);
6606 BOOL same = got[0] == exp[0] && got[1] == exp[1];
6607 ok_(__FILE__,line)(same, "Mesh %d: Got (%hu, %hu) for vertex %d %s, expected (%hu, %hu).\n",
6608 mesh_number, got[0], got[1], vertex_number, usage_strings[decl_ptr->Usage], exp[0], exp[1]);
6609 break;
6611 case D3DDECLTYPE_USHORT4N:
6613 USHORT *got = (USHORT*)(got_ptr + decl_ptr->Offset);
6614 USHORT *exp = (USHORT*)(exp_ptr + decl_ptr->Offset);
6615 BOOL same = got[0] == exp[0] && got[1] == exp[1]
6616 && got[2] == exp[2] && got[3] == exp[3];
6617 ok_(__FILE__,line)(same, "Mesh %d: Got (%hu, %hu, %hu, %hu) for vertex %d %s, expected (%hu, %hu, %hu, %hu).\n",
6618 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]);
6619 break;
6621 case D3DDECLTYPE_UDEC3:
6623 DWORD *got = (DWORD*)(got_ptr + decl_ptr->Offset);
6624 DWORD *exp = (DWORD*)(exp_ptr + decl_ptr->Offset);
6625 BOOL same = memcmp(got, exp, sizeof(*got)) == 0;
6626 struct udec3 got_udec3 = dword_to_udec3(*got);
6627 struct udec3 exp_udec3 = dword_to_udec3(*exp);
6628 ok_(__FILE__,line)(same, "Mesh %d: Got (%u, %u, %u, %u) for vertex %d %s, expected (%u, %u, %u, %u).\n",
6629 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);
6631 break;
6633 case D3DDECLTYPE_DEC3N:
6635 DWORD *got = (DWORD*)(got_ptr + decl_ptr->Offset);
6636 DWORD *exp = (DWORD*)(exp_ptr + decl_ptr->Offset);
6637 BOOL same = memcmp(got, exp, sizeof(*got)) == 0;
6638 struct dec3n got_dec3n = dword_to_dec3n(*got);
6639 struct dec3n exp_dec3n = dword_to_dec3n(*exp);
6640 ok_(__FILE__,line)(same, "Mesh %d: Got (%d, %d, %d, %d) for vertex %d %s, expected (%d, %d, %d, %d).\n",
6641 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);
6642 break;
6644 case D3DDECLTYPE_FLOAT16_2:
6646 WORD *got = (WORD*)(got_ptr + decl_ptr->Offset);
6647 WORD *exp = (WORD*)(exp_ptr + decl_ptr->Offset);
6648 BOOL same = got[0] == exp[0] && got[1] == exp[1];
6649 ok_(__FILE__,line)(same, "Mesh %d: Got (%hx, %hx) for vertex %d %s, expected (%hx, %hx).\n",
6650 mesh_number, got[0], got[1], vertex_number, usage_strings[decl_ptr->Usage], exp[0], exp[1]);
6651 break;
6653 case D3DDECLTYPE_FLOAT16_4:
6655 WORD *got = (WORD*)(got_ptr + decl_ptr->Offset);
6656 WORD *exp = (WORD*)(exp_ptr + decl_ptr->Offset);
6657 BOOL same = got[0] == exp[0] && got[1] == exp[1]
6658 && got[2] == exp[2] && got[3] == exp[3];
6659 ok_(__FILE__,line)(same, "Mesh %d: Got (%hx, %hx, %hx, %hx) for vertex %d %s, expected (%hx, %hx, %hx, %hx).\n",
6660 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]);
6661 break;
6663 default:
6664 break;
6669 static void test_weld_vertices(void)
6671 HRESULT hr;
6672 struct test_context *test_context = NULL;
6673 DWORD i;
6674 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
6675 const DWORD options_16bit = D3DXMESH_SYSTEMMEM;
6676 BYTE *vertices = NULL;
6677 DWORD *indices = NULL;
6678 WORD *indices_16bit = NULL;
6679 const UINT VERTS_PER_FACE = 3;
6680 const D3DXVECTOR3 up = {0.0f, 0.0f, 1.0f};
6681 struct vertex_normal
6683 D3DXVECTOR3 position;
6684 D3DXVECTOR3 normal;
6686 struct vertex_blendweight
6688 D3DXVECTOR3 position;
6689 FLOAT blendweight;
6691 struct vertex_texcoord
6693 D3DXVECTOR3 position;
6694 D3DXVECTOR2 texcoord;
6696 struct vertex_color
6698 D3DXVECTOR3 position;
6699 DWORD color;
6701 struct vertex_color_ubyte4
6703 D3DXVECTOR3 position;
6704 BYTE color[4];
6706 struct vertex_texcoord_short2
6708 D3DXVECTOR3 position;
6709 SHORT texcoord[2];
6711 struct vertex_texcoord_ushort2n
6713 D3DXVECTOR3 position;
6714 USHORT texcoord[2];
6716 struct vertex_normal_short4
6718 D3DXVECTOR3 position;
6719 SHORT normal[4];
6721 struct vertex_texcoord_float16_2
6723 D3DXVECTOR3 position;
6724 WORD texcoord[2];
6726 struct vertex_texcoord_float16_4
6728 D3DXVECTOR3 position;
6729 WORD texcoord[4];
6731 struct vertex_normal_udec3
6733 D3DXVECTOR3 position;
6734 DWORD normal;
6736 struct vertex_normal_dec3n
6738 D3DXVECTOR3 position;
6739 DWORD normal;
6741 UINT vertex_size_normal = sizeof(struct vertex_normal);
6742 UINT vertex_size_blendweight = sizeof(struct vertex_blendweight);
6743 UINT vertex_size_texcoord = sizeof(struct vertex_texcoord);
6744 UINT vertex_size_color = sizeof(struct vertex_color);
6745 UINT vertex_size_color_ubyte4 = sizeof(struct vertex_color_ubyte4);
6746 UINT vertex_size_texcoord_short2 = sizeof(struct vertex_texcoord_short2);
6747 UINT vertex_size_normal_short4 = sizeof(struct vertex_normal_short4);
6748 UINT vertex_size_texcoord_float16_2 = sizeof(struct vertex_texcoord_float16_2);
6749 UINT vertex_size_texcoord_float16_4 = sizeof(struct vertex_texcoord_float16_4);
6750 UINT vertex_size_normal_udec3 = sizeof(struct vertex_normal_udec3);
6751 UINT vertex_size_normal_dec3n = sizeof(struct vertex_normal_dec3n);
6752 D3DVERTEXELEMENT9 declaration_normal[] =
6754 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6755 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6756 D3DDECL_END()
6758 D3DVERTEXELEMENT9 declaration_normal3[] =
6760 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 3},
6761 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6762 D3DDECL_END()
6764 D3DVERTEXELEMENT9 declaration_blendweight[] =
6766 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6767 {0, 12, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BLENDWEIGHT, 0},
6768 D3DDECL_END()
6770 D3DVERTEXELEMENT9 declaration_texcoord[] =
6772 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6773 {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6774 D3DDECL_END()
6776 D3DVERTEXELEMENT9 declaration_color[] =
6778 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6779 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
6780 D3DDECL_END()
6782 D3DVERTEXELEMENT9 declaration_color_ubyte4n[] =
6784 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6785 {0, 12, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
6786 D3DDECL_END()
6788 D3DVERTEXELEMENT9 declaration_color_ubyte4[] =
6790 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6791 {0, 12, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
6792 D3DDECL_END()
6794 D3DVERTEXELEMENT9 declaration_texcoord_short2[] =
6796 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6797 {0, 12, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6798 D3DDECL_END()
6800 D3DVERTEXELEMENT9 declaration_texcoord_short2n[] =
6802 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6803 {0, 12, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6804 D3DDECL_END()
6806 D3DVERTEXELEMENT9 declaration_texcoord_ushort2n[] =
6808 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6809 {0, 12, D3DDECLTYPE_USHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6810 D3DDECL_END()
6812 D3DVERTEXELEMENT9 declaration_normal_short4[] =
6814 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6815 {0, 12, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6816 D3DDECL_END()
6818 D3DVERTEXELEMENT9 declaration_normal_short4n[] =
6820 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6821 {0, 12, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6822 D3DDECL_END()
6824 D3DVERTEXELEMENT9 declaration_normal_ushort4n[] =
6826 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6827 {0, 12, D3DDECLTYPE_USHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6828 D3DDECL_END()
6830 D3DVERTEXELEMENT9 declaration_texcoord10[] =
6832 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6833 {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 10},
6834 D3DDECL_END()
6836 D3DVERTEXELEMENT9 declaration_color2[] =
6838 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6839 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 2},
6840 D3DDECL_END()
6842 D3DVERTEXELEMENT9 declaration_color1[] =
6844 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6845 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 1},
6846 D3DDECL_END()
6848 D3DVERTEXELEMENT9 declaration_texcoord_float16_2[] =
6850 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6851 {0, 12, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6852 D3DDECL_END()
6854 D3DVERTEXELEMENT9 declaration_texcoord_float16_4[] =
6856 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6857 {0, 12, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6858 D3DDECL_END()
6860 D3DVERTEXELEMENT9 declaration_normal_udec3[] =
6862 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6863 {0, 12, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6864 D3DDECL_END()
6866 D3DVERTEXELEMENT9 declaration_normal_dec3n[] =
6868 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6869 {0, 12, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6870 D3DDECL_END()
6872 /* Test 0. One face and no welding.
6874 * 0--1
6875 * | /
6876 * |/
6879 const struct vertex vertices0[] =
6881 {{ 0.0f, 3.0f, 0.f}, up},
6882 {{ 2.0f, 3.0f, 0.f}, up},
6883 {{ 0.0f, 0.0f, 0.f}, up},
6885 const DWORD indices0[] = {0, 1, 2};
6886 const DWORD attributes0[] = {0};
6887 const DWORD exp_indices0[] = {0, 1, 2};
6888 const UINT num_vertices0 = ARRAY_SIZE(vertices0);
6889 const UINT num_faces0 = ARRAY_SIZE(indices0) / VERTS_PER_FACE;
6890 const DWORD flags0 = D3DXWELDEPSILONS_WELDALL;
6891 /* epsilons0 is NULL */
6892 const DWORD adjacency0[] = {-1, -1, -1};
6893 const struct vertex exp_vertices0[] =
6895 {{ 0.0f, 3.0f, 0.f}, up},
6896 {{ 2.0f, 3.0f, 0.f}, up},
6897 {{ 0.0f, 0.0f, 0.f}, up},
6899 const DWORD exp_face_remap0[] = {0};
6900 const DWORD exp_vertex_remap0[] = {0, 1, 2};
6901 const DWORD exp_new_num_vertices0 = ARRAY_SIZE(exp_vertices0);
6902 /* Test 1. Two vertices should be removed without regard to epsilon.
6904 * 0--1 3
6905 * | / /|
6906 * |/ / |
6907 * 2 5--4
6909 const struct vertex_normal vertices1[] =
6911 {{ 0.0f, 3.0f, 0.f}, up},
6912 {{ 2.0f, 3.0f, 0.f}, up},
6913 {{ 0.0f, 0.0f, 0.f}, up},
6915 {{ 3.0f, 3.0f, 0.f}, up},
6916 {{ 3.0f, 0.0f, 0.f}, up},
6917 {{ 1.0f, 0.0f, 0.f}, up},
6919 const DWORD indices1[] = {0, 1, 2, 3, 4, 5};
6920 const DWORD attributes1[] = {0, 0};
6921 const UINT num_vertices1 = ARRAY_SIZE(vertices1);
6922 const UINT num_faces1 = ARRAY_SIZE(indices1) / VERTS_PER_FACE;
6923 const DWORD flags1 = D3DXWELDEPSILONS_WELDALL;
6924 /* epsilons1 is NULL */
6925 const DWORD adjacency1[] = {-1, 1, -1, -1, -1, 0};
6926 const struct vertex_normal exp_vertices1[] =
6928 {{ 0.0f, 3.0f, 0.f}, up},
6929 {{ 2.0f, 3.0f, 0.f}, up},
6930 {{ 0.0f, 0.0f, 0.f}, up},
6932 {{ 3.0f, 0.0f, 0.f}, up}
6934 const DWORD exp_indices1[] = {0, 1, 2, 1, 3, 2};
6935 const DWORD exp_face_remap1[] = {0, 1};
6936 const DWORD exp_vertex_remap1[] = {0, 1, 2, 4, -1, -1};
6937 const DWORD exp_new_num_vertices1 = ARRAY_SIZE(exp_vertices1);
6938 /* Test 2. Two faces. No vertices should be removed because of normal
6939 * epsilon, but the positions should be replaced. */
6940 const struct vertex_normal vertices2[] =
6942 {{ 0.0f, 3.0f, 0.f}, up},
6943 {{ 2.0f, 3.0f, 0.f}, up},
6944 {{ 0.0f, 0.0f, 0.f}, up},
6946 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
6947 {{ 3.0f, 0.0f, 0.f}, up},
6948 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6950 const DWORD indices2[] = {0, 1, 2, 3, 4, 5};
6951 const DWORD attributes2[] = {0, 0};
6952 const UINT num_vertices2 = ARRAY_SIZE(vertices2);
6953 const UINT num_faces2 = ARRAY_SIZE(indices2) / VERTS_PER_FACE;
6954 DWORD flags2 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
6955 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};
6956 const DWORD adjacency2[] = {-1, 1, -1, -1, -1, 0};
6957 const struct vertex_normal exp_vertices2[] =
6959 {{ 0.0f, 3.0f, 0.f}, up},
6960 {{ 2.0f, 3.0f, 0.f}, up},
6961 {{ 0.0f, 0.0f, 0.f}, up},
6963 {{ 2.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
6964 {{ 3.0f, 0.0f, 0.f}, up},
6965 {{ 0.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6967 const DWORD exp_indices2[] = {0, 1, 2, 3, 4, 5};
6968 const DWORD exp_face_remap2[] = {0, 1};
6969 const DWORD exp_vertex_remap2[] = {0, 1, 2, 3, 4, 5};
6970 const DWORD exp_new_num_vertices2 = ARRAY_SIZE(exp_vertices2);
6971 /* Test 3. Two faces. One vertex should be removed because of normal epsilon. */
6972 const struct vertex_normal vertices3[] =
6974 {{ 0.0f, 3.0f, 0.f}, up},
6975 {{ 2.0f, 3.0f, 0.f}, up},
6976 {{ 0.0f, 0.0f, 0.f}, up},
6978 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
6979 {{ 3.0f, 0.0f, 0.f}, up},
6980 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6982 const DWORD indices3[] = {0, 1, 2, 3, 4, 5};
6983 const DWORD attributes3[] = {0, 0};
6984 const UINT num_vertices3 = ARRAY_SIZE(vertices3);
6985 const UINT num_faces3 = ARRAY_SIZE(indices3) / VERTS_PER_FACE;
6986 DWORD flags3 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
6987 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};
6988 const DWORD adjacency3[] = {-1, 1, -1, -1, -1, 0};
6989 const struct vertex_normal exp_vertices3[] =
6991 {{ 0.0f, 3.0f, 0.f}, up},
6992 {{ 2.0f, 3.0f, 0.f}, up},
6993 {{ 0.0f, 0.0f, 0.f}, up},
6995 {{ 3.0f, 0.0f, 0.f}, up},
6996 {{ 0.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6998 const DWORD exp_indices3[] = {0, 1, 2, 1, 3, 4};
6999 const DWORD exp_face_remap3[] = {0, 1};
7000 const DWORD exp_vertex_remap3[] = {0, 1, 2, 4, 5, -1};
7001 const DWORD exp_new_num_vertices3 = ARRAY_SIZE(exp_vertices3);
7002 /* Test 4 Two faces. Two vertices should be removed. */
7003 const struct vertex_normal vertices4[] =
7005 {{ 0.0f, 3.0f, 0.f}, up},
7006 {{ 2.0f, 3.0f, 0.f}, up},
7007 {{ 0.0f, 0.0f, 0.f}, up},
7009 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
7010 {{ 3.0f, 0.0f, 0.f}, up},
7011 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
7013 const DWORD indices4[] = {0, 1, 2, 3, 4, 5};
7014 const DWORD attributes4[] = {0, 0};
7015 const UINT num_vertices4 = ARRAY_SIZE(vertices4);
7016 const UINT num_faces4 = ARRAY_SIZE(indices4) / VERTS_PER_FACE;
7017 DWORD flags4 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7018 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};
7019 const DWORD adjacency4[] = {-1, 1, -1, -1, -1, 0};
7020 const struct vertex_normal exp_vertices4[] =
7022 {{ 0.0f, 3.0f, 0.f}, up},
7023 {{ 2.0f, 3.0f, 0.f}, up},
7024 {{ 0.0f, 0.0f, 0.f}, up},
7026 {{ 3.0f, 0.0f, 0.f}, up},
7028 const DWORD exp_indices4[] = {0, 1, 2, 1, 3, 2};
7029 const DWORD exp_face_remap4[] = {0, 1};
7030 const DWORD exp_vertex_remap4[] = {0, 1, 2, 4, -1, -1};
7031 const DWORD exp_new_num_vertices4 = ARRAY_SIZE(exp_vertices4);
7032 /* Test 5. Odd face ordering.
7034 * 0--1 6 3
7035 * | / /| |\
7036 * |/ / | | \
7037 * 2 8--7 5--4
7039 const struct vertex_normal vertices5[] =
7041 {{ 0.0f, 3.0f, 0.f}, up},
7042 {{ 2.0f, 3.0f, 0.f}, up},
7043 {{ 0.0f, 0.0f, 0.f}, up},
7045 {{ 3.0f, 3.0f, 0.f}, up},
7046 {{ 3.0f, 0.0f, 0.f}, up},
7047 {{ 1.0f, 0.0f, 0.f}, up},
7049 {{ 4.0f, 3.0f, 0.f}, up},
7050 {{ 6.0f, 0.0f, 0.f}, up},
7051 {{ 4.0f, 0.0f, 0.f}, up},
7053 const DWORD indices5[] = {0, 1, 2, 6, 7, 8, 3, 4, 5};
7054 const DWORD exp_indices5[] = {0, 1, 2, 1, 4, 2, 1, 3, 4};
7055 const DWORD attributes5[] = {0, 0, 0};
7056 const UINT num_vertices5 = ARRAY_SIZE(vertices5);
7057 const UINT num_faces5 = ARRAY_SIZE(indices5) / VERTS_PER_FACE;
7058 DWORD flags5 = D3DXWELDEPSILONS_WELDALL;
7059 const DWORD adjacency5[] = {-1, 1, -1, 2, -1, 0, -1, -1, 1};
7060 const struct vertex_normal exp_vertices5[] =
7062 {{ 0.0f, 3.0f, 0.f}, up},
7063 {{ 2.0f, 3.0f, 0.f}, up},
7064 {{ 0.0f, 0.0f, 0.f}, up},
7066 {{ 3.0f, 0.0f, 0.f}, up},
7067 {{ 1.0f, 0.0f, 0.f}, up},
7069 const DWORD exp_face_remap5[] = {0, 1, 2};
7070 const DWORD exp_vertex_remap5[] = {0, 1, 2, 4, 5, -1, -1, -1, -1};
7071 const DWORD exp_new_num_vertices5 = ARRAY_SIZE(exp_vertices5);
7072 /* Test 6. Two faces. Do not remove flag is used, so no vertices should be
7073 * removed. */
7074 const struct vertex_normal vertices6[] =
7076 {{ 0.0f, 3.0f, 0.f}, up},
7077 {{ 2.0f, 3.0f, 0.f}, up},
7078 {{ 0.0f, 0.0f, 0.f}, up},
7080 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
7081 {{ 3.0f, 0.0f, 0.f}, up},
7082 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
7084 const DWORD indices6[] = {0, 1, 2, 3, 4, 5};
7085 const DWORD attributes6[] = {0, 0};
7086 const UINT num_vertices6 = ARRAY_SIZE(vertices6);
7087 const UINT num_faces6 = ARRAY_SIZE(indices6) / VERTS_PER_FACE;
7088 DWORD flags6 = D3DXWELDEPSILONS_WELDPARTIALMATCHES | D3DXWELDEPSILONS_DONOTREMOVEVERTICES;
7089 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};
7090 const DWORD adjacency6[] = {-1, 1, -1, -1, -1, 0};
7091 const struct vertex_normal exp_vertices6[] =
7093 {{ 0.0f, 3.0f, 0.f}, up},
7094 {{ 2.0f, 3.0f, 0.f}, up},
7095 {{ 0.0f, 0.0f, 0.f}, up},
7097 {{ 2.0f, 3.0f, 0.f}, up},
7098 {{ 3.0f, 0.0f, 0.f}, up},
7099 {{ 0.0f, 0.0f, 0.f}, up},
7102 const DWORD exp_indices6[] = {0, 1, 2, 3, 4, 5};
7103 const DWORD exp_face_remap6[] = {0, 1};
7104 const DWORD exp_vertex_remap6[] = {0, 1, 2, 3, 4, 5};
7105 const DWORD exp_new_num_vertices6 = ARRAY_SIZE(exp_vertices6);
7106 /* Test 7. Same as test 6 but with 16 bit indices. */
7107 const WORD indices6_16bit[] = {0, 1, 2, 3, 4, 5};
7108 /* Test 8. No flags. Same result as D3DXWELDEPSILONS_WELDPARTIALMATCHES. */
7109 const struct vertex_normal vertices8[] =
7111 {{ 0.0f, 3.0f, 0.f}, up},
7112 {{ 2.0f, 3.0f, 0.f}, up},
7113 {{ 0.0f, 0.0f, 0.f}, up},
7115 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
7116 {{ 3.0f, 0.0f, 0.f}, up},
7117 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
7119 const DWORD indices8[] = {0, 1, 2, 1, 3, 4};
7120 const DWORD attributes8[] = {0, 0};
7121 const UINT num_vertices8 = ARRAY_SIZE(vertices8);
7122 const UINT num_faces8 = ARRAY_SIZE(indices8) / VERTS_PER_FACE;
7123 DWORD flags8 = 0;
7124 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};
7125 const DWORD adjacency8[] = {-1, 1, -1, -1, -1, 0};
7126 const struct vertex_normal exp_vertices8[] =
7128 {{ 0.0f, 3.0f, 0.f}, up},
7129 {{ 2.0f, 3.0f, 0.f}, up},
7130 {{ 0.0f, 0.0f, 0.f}, up},
7132 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
7133 {{ 3.0f, 0.0f, 0.f}, up},
7135 const DWORD exp_indices8[] = {0, 1, 2, 1, 3, 4};
7136 const DWORD exp_face_remap8[] = {0, 1};
7137 const DWORD exp_vertex_remap8[] = {0, 1, 2, 3, 4, -1};
7138 const DWORD exp_new_num_vertices8 = ARRAY_SIZE(exp_vertices8);
7139 /* Test 9. Vertices are removed even though they belong to separate
7140 * attribute groups if D3DXWELDEPSILONS_DONOTSPLIT is set. */
7141 const struct vertex_normal vertices9[] =
7143 {{ 0.0f, 3.0f, 0.f}, up},
7144 {{ 2.0f, 3.0f, 0.f}, up},
7145 {{ 0.0f, 0.0f, 0.f}, up},
7147 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
7148 {{ 3.0f, 0.0f, 0.f}, up},
7149 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
7151 const DWORD indices9[] = {0, 1, 2, 3, 4, 5};
7152 const DWORD attributes9[] = {0, 1};
7153 const UINT num_vertices9 = ARRAY_SIZE(vertices9);
7154 const UINT num_faces9 = ARRAY_SIZE(indices9) / VERTS_PER_FACE;
7155 DWORD flags9 = D3DXWELDEPSILONS_WELDPARTIALMATCHES | D3DXWELDEPSILONS_DONOTSPLIT;
7156 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};
7157 const DWORD adjacency9[] = {-1, 1, -1, -1, -1, 0};
7158 const struct vertex_normal exp_vertices9[] =
7160 {{ 0.0f, 3.0f, 0.f}, up},
7161 {{ 2.0f, 3.0f, 0.f}, up},
7162 {{ 0.0f, 0.0f, 0.f}, up},
7164 {{ 3.0f, 0.0f, 0.f}, up},
7166 const DWORD exp_indices9[] = {0, 1, 2, 1, 3, 2};
7167 const DWORD exp_face_remap9[] = {0, 1};
7168 const DWORD exp_vertex_remap9[] = {0, 1, 2, 4, -1, -1};
7169 const DWORD exp_new_num_vertices9 = ARRAY_SIZE(exp_vertices9);
7170 /* Test 10. Weld blendweight (FLOAT1). */
7171 const struct vertex_blendweight vertices10[] =
7173 {{ 0.0f, 3.0f, 0.f}, 1.0f},
7174 {{ 2.0f, 3.0f, 0.f}, 1.0f},
7175 {{ 0.0f, 0.0f, 0.f}, 1.0f},
7177 {{ 3.0f, 3.0f, 0.f}, 0.9},
7178 {{ 3.0f, 0.0f, 0.f}, 1.0},
7179 {{ 1.0f, 0.0f, 0.f}, 0.4},
7181 const DWORD indices10[] = {0, 1, 2, 3, 4, 5};
7182 const DWORD attributes10[] = {0, 0};
7183 const UINT num_vertices10 = ARRAY_SIZE(vertices10);
7184 const UINT num_faces10 = ARRAY_SIZE(indices10) / VERTS_PER_FACE;
7185 DWORD flags10 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7186 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};
7187 const DWORD adjacency10[] = {-1, 1, -1, -1, -1, 0};
7188 const struct vertex_blendweight exp_vertices10[] =
7190 {{ 0.0f, 3.0f, 0.f}, 1.0f},
7191 {{ 2.0f, 3.0f, 0.f}, 1.0f},
7192 {{ 0.0f, 0.0f, 0.f}, 1.0f},
7194 {{ 3.0f, 0.0f, 0.f}, 1.0},
7195 {{ 0.0f, 0.0f, 0.f}, 0.4},
7197 const DWORD exp_indices10[] = {0, 1, 2, 1, 3, 4};
7198 const DWORD exp_face_remap10[] = {0, 1};
7199 const DWORD exp_vertex_remap10[] = {0, 1, 2, 4, 5, -1};
7200 const DWORD exp_new_num_vertices10 = ARRAY_SIZE(exp_vertices10);
7201 /* Test 11. Weld texture coordinates. */
7202 const struct vertex_texcoord vertices11[] =
7204 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f}},
7205 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.7f}},
7206 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
7208 {{ 3.0f, 3.0f, 0.f}, {0.2f, 0.3f}},
7209 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f}},
7210 {{ 1.0f, 0.0f, 0.f}, {0.1f, 0.2f}}
7212 const DWORD indices11[] = {0, 1, 2, 3, 4, 5};
7213 const DWORD attributes11[] = {0, 0};
7214 const UINT num_vertices11 = ARRAY_SIZE(vertices11);
7215 const UINT num_faces11 = ARRAY_SIZE(indices11) / VERTS_PER_FACE;
7216 DWORD flags11 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7217 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};
7218 const DWORD adjacency11[] = {-1, 1, -1, -1, -1, 0};
7219 const struct vertex_texcoord exp_vertices11[] =
7221 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f}},
7222 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.7f}},
7223 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
7225 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f}},
7226 {{ 0.0f, 0.0f, 0.f}, {0.1f, 0.2f}},
7228 const DWORD exp_indices11[] = {0, 1, 2, 1, 3, 4};
7229 const DWORD exp_face_remap11[] = {0, 1};
7230 const DWORD exp_vertex_remap11[] = {0, 1, 2, 4, 5, -1};
7231 const DWORD exp_new_num_vertices11 = ARRAY_SIZE(exp_vertices11);
7232 /* Test 12. Weld with color. */
7233 const struct vertex_color vertices12[] =
7235 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7236 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7237 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7239 {{ 3.0f, 3.0f, 0.f}, 0x00000000},
7240 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7241 {{ 1.0f, 0.0f, 0.f}, 0x88888888},
7243 const DWORD indices12[] = {0, 1, 2, 3, 4, 5};
7244 const DWORD attributes12[] = {0, 0};
7245 const UINT num_vertices12 = ARRAY_SIZE(vertices12);
7246 const UINT num_faces12 = ARRAY_SIZE(indices12) / VERTS_PER_FACE;
7247 DWORD flags12 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7248 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};
7249 const DWORD adjacency12[] = {-1, 1, -1, -1, -1, 0};
7250 const struct vertex_color exp_vertices12[] =
7252 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7253 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7254 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7256 {{ 2.0f, 3.0f, 0.f}, 0x00000000},
7257 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7259 const DWORD exp_indices12[] = {0, 1, 2, 3, 4, 2};
7260 const DWORD exp_face_remap12[] = {0, 1};
7261 const DWORD exp_vertex_remap12[] = {0, 1, 2, 3, 4, -1};
7262 const DWORD exp_new_num_vertices12 = ARRAY_SIZE(exp_vertices12);
7263 /* Test 13. Two faces. One vertex should be removed because of normal epsilon.
7264 * This is similar to test 3, but the declaration has been changed to NORMAL3.
7266 const struct vertex_normal vertices13[] =
7268 {{ 0.0f, 3.0f, 0.f}, up},
7269 {{ 2.0f, 3.0f, 0.f}, up},
7270 {{ 0.0f, 0.0f, 0.f}, up},
7272 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
7273 {{ 3.0f, 0.0f, 0.f}, up},
7274 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
7276 const DWORD indices13[] = {0, 1, 2, 3, 4, 5};
7277 const DWORD attributes13[] = {0, 0};
7278 const UINT num_vertices13 = ARRAY_SIZE(vertices3);
7279 const UINT num_faces13 = ARRAY_SIZE(indices3) / VERTS_PER_FACE;
7280 DWORD flags13 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7281 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};
7282 const DWORD adjacency13[] = {-1, 1, -1, -1, -1, 0};
7283 const struct vertex_normal exp_vertices13[] =
7285 {{ 0.0f, 3.0f, 0.f}, up},
7286 {{ 2.0f, 3.0f, 0.f}, up},
7287 {{ 0.0f, 0.0f, 0.f}, up},
7289 {{ 3.0f, 0.0f, 0.f}, up},
7290 {{ 0.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
7292 const DWORD exp_indices13[] = {0, 1, 2, 1, 3, 4};
7293 const DWORD exp_face_remap13[] = {0, 1};
7294 const DWORD exp_vertex_remap13[] = {0, 1, 2, 4, 5, -1};
7295 const DWORD exp_new_num_vertices13 = ARRAY_SIZE(exp_vertices13);
7296 /* Test 14. Another test for welding with color. */
7297 const struct vertex_color vertices14[] =
7299 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7300 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7301 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7303 {{ 3.0f, 3.0f, 0.f}, 0x00000000},
7304 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7305 {{ 1.0f, 0.0f, 0.f}, 0x01010101},
7307 const DWORD indices14[] = {0, 1, 2, 3, 4, 5};
7308 const DWORD attributes14[] = {0, 0};
7309 const UINT num_vertices14 = ARRAY_SIZE(vertices14);
7310 const UINT num_faces14 = ARRAY_SIZE(indices14) / VERTS_PER_FACE;
7311 DWORD flags14 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7312 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};
7313 const DWORD adjacency14[] = {-1, 1, -1, -1, -1, 0};
7314 const struct vertex_color exp_vertices14[] =
7316 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7317 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7318 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7320 {{ 2.0f, 3.0f, 0.f}, 0x00000000},
7321 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7323 const DWORD exp_indices14[] = {0, 1, 2, 3, 4, 2};
7324 const DWORD exp_face_remap14[] = {0, 1};
7325 const DWORD exp_vertex_remap14[] = {0, 1, 2, 3, 4, -1};
7326 const DWORD exp_new_num_vertices14 = ARRAY_SIZE(exp_vertices14);
7327 /* Test 15. Weld with color, but as UBYTE4N instead of D3DCOLOR. It shows
7328 * that UBYTE4N and D3DCOLOR are compared the same way.
7330 const struct vertex_color_ubyte4 vertices15[] =
7332 {{ 0.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7333 {{ 2.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7334 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7336 {{ 3.0f, 3.0f, 0.f}, { 0, 0, 0, 0}},
7337 {{ 3.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7338 {{ 1.0f, 0.0f, 0.f}, { 1, 1, 1, 1}},
7340 const DWORD indices15[] = {0, 1, 2, 3, 4, 5};
7341 const DWORD attributes15[] = {0, 0};
7342 const UINT num_vertices15 = ARRAY_SIZE(vertices15);
7343 const UINT num_faces15 = ARRAY_SIZE(indices15) / VERTS_PER_FACE;
7344 DWORD flags15 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7345 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};
7346 const DWORD adjacency15[] = {-1, 1, -1, -1, -1, 0};
7347 const struct vertex_color_ubyte4 exp_vertices15[] =
7349 {{ 0.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7350 {{ 2.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7351 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7353 {{ 2.0f, 3.0f, 0.f}, { 0, 0, 0, 0}},
7354 {{ 3.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7356 const DWORD exp_indices15[] = {0, 1, 2, 3, 4, 2};
7357 const DWORD exp_face_remap15[] = {0, 1};
7358 const DWORD exp_vertex_remap15[] = {0, 1, 2, 3, 4, -1};
7359 const DWORD exp_new_num_vertices15 = ARRAY_SIZE(exp_vertices15);
7360 /* Test 16. Weld with color, but as UBYTE4 instead of D3DCOLOR. It shows
7361 * that UBYTE4 is not normalized and that epsilon is truncated and compared
7362 * directly to each of the four bytes.
7364 const struct vertex_color_ubyte4 vertices16[] =
7366 {{ 0.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7367 {{ 2.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7368 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7370 {{ 3.0f, 3.0f, 0.f}, { 0, 0, 0, 0}},
7371 {{ 3.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7372 {{ 1.0f, 0.0f, 0.f}, { 1, 1, 1, 1}},
7374 const DWORD indices16[] = {0, 1, 2, 3, 4, 5};
7375 const DWORD attributes16[] = {0, 0};
7376 const UINT num_vertices16 = ARRAY_SIZE(vertices16);
7377 const UINT num_faces16 = ARRAY_SIZE(indices16) / VERTS_PER_FACE;
7378 DWORD flags16 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7379 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};
7380 const DWORD adjacency16[] = {-1, 1, -1, -1, -1, 0};
7381 const struct vertex_color_ubyte4 exp_vertices16[] =
7383 {{ 0.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7384 {{ 2.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7385 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7387 {{ 2.0f, 3.0f, 0.f}, { 0, 0, 0, 0}},
7388 {{ 3.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7390 const DWORD exp_indices16[] = {0, 1, 2, 3, 4, 2};
7391 const DWORD exp_face_remap16[] = {0, 1};
7392 const DWORD exp_vertex_remap16[] = {0, 1, 2, 3, 4, -1};
7393 const DWORD exp_new_num_vertices16 = ARRAY_SIZE(exp_vertices16);
7394 /* Test 17. Weld texture coordinates but as SHORT2 instead of D3DXVECTOR2.*/
7395 const struct vertex_texcoord_short2 vertices17[] =
7397 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7398 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7399 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7401 {{ 3.0f, 3.0f, 0.f}, {32767, 32767}},
7402 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7403 {{ 1.0f, 0.0f, 0.f}, {32766, 32766}},
7405 const DWORD indices17[] = {0, 1, 2, 3, 4, 5};
7406 const DWORD attributes17[] = {0, 0};
7407 const UINT num_vertices17 = ARRAY_SIZE(vertices17);
7408 const UINT num_faces17 = ARRAY_SIZE(indices17) / VERTS_PER_FACE;
7409 DWORD flags17 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7410 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};
7411 const DWORD adjacency17[] = {-1, 1, -1, -1, -1, 0};
7412 const struct vertex_texcoord_short2 exp_vertices17[] =
7414 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7415 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7416 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7418 {{ 2.0f, 3.0f, 0.f}, {32767, 32767}},
7419 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7421 const DWORD exp_indices17[] = {0, 1, 2, 3, 4, 2};
7422 const DWORD exp_face_remap17[] = {0, 1};
7423 const DWORD exp_vertex_remap17[] = {0, 1, 2, 3, 4, -1};
7424 const DWORD exp_new_num_vertices17 = ARRAY_SIZE(exp_vertices17);
7425 /* Test 18. Weld texture coordinates but as SHORT2N instead of D3DXVECTOR2. */
7426 const struct vertex_texcoord_short2 vertices18[] =
7428 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7429 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7430 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7432 {{ 3.0f, 3.0f, 0.f}, {32767, 32767}},
7433 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7434 {{ 1.0f, 0.0f, 0.f}, {32766, 32766}},
7436 const DWORD indices18[] = {0, 1, 2, 3, 4, 5};
7437 const DWORD attributes18[] = {0, 0};
7438 const UINT num_vertices18 = ARRAY_SIZE(vertices18);
7439 const UINT num_faces18 = ARRAY_SIZE(indices18) / VERTS_PER_FACE;
7440 DWORD flags18 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7441 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};
7442 const DWORD adjacency18[] = {-1, 1, -1, -1, -1, 0};
7443 const struct vertex_texcoord_short2 exp_vertices18[] =
7445 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7446 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7447 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7449 {{ 2.0f, 3.0f, 0.f}, {32767, 32767}},
7450 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7452 const DWORD exp_indices18[] = {0, 1, 2, 3, 4, 2};
7453 const DWORD exp_face_remap18[] = {0, 1};
7454 const DWORD exp_vertex_remap18[] = {0, 1, 2, 3, 4, -1};
7455 const DWORD exp_new_num_vertices18 = ARRAY_SIZE(exp_vertices18);
7456 /* Test 19. Weld texture coordinates but as USHORT2N instead of D3DXVECTOR2. */
7457 const struct vertex_texcoord_ushort2n vertices19[] =
7459 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7460 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7461 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7463 {{ 3.0f, 3.0f, 0.f}, {65535, 65535}},
7464 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7465 {{ 1.0f, 0.0f, 0.f}, {65534, 65534}},
7467 const DWORD indices19[] = {0, 1, 2, 3, 4, 5};
7468 const DWORD attributes19[] = {0, 0};
7469 const UINT num_vertices19 = ARRAY_SIZE(vertices19);
7470 const UINT num_faces19 = ARRAY_SIZE(indices19) / VERTS_PER_FACE;
7471 DWORD flags19 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7472 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};
7473 const DWORD adjacency19[] = {-1, 1, -1, -1, -1, 0};
7474 const struct vertex_texcoord_ushort2n exp_vertices19[] =
7476 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7477 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7478 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7480 {{ 2.0f, 3.0f, 0.f}, {65535, 65535}},
7481 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7483 const DWORD exp_indices19[] = {0, 1, 2, 3, 4, 2};
7484 const DWORD exp_face_remap19[] = {0, 1};
7485 const DWORD exp_vertex_remap19[] = {0, 1, 2, 3, 4, -1};
7486 const DWORD exp_new_num_vertices19 = ARRAY_SIZE(exp_vertices19);
7487 /* Test 20. Weld normal as SHORT4 instead of D3DXVECTOR3. */
7488 const struct vertex_normal_short4 vertices20[] =
7490 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7491 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7492 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7494 {{ 3.0f, 3.0f, 0.f}, {32767, 32767, 32767, 32767}},
7495 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7496 {{ 1.0f, 0.0f, 0.f}, {32766, 32766, 32766, 32766}},
7498 const DWORD indices20[] = {0, 1, 2, 3, 4, 5};
7499 const DWORD attributes20[] = {0, 0};
7500 const UINT num_vertices20 = ARRAY_SIZE(vertices20);
7501 const UINT num_faces20 = ARRAY_SIZE(indices20) / VERTS_PER_FACE;
7502 DWORD flags20 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7503 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};
7504 const DWORD adjacency20[] = {-1, 1, -1, -1, -1, 0};
7505 const struct vertex_normal_short4 exp_vertices20[] =
7507 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7508 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7509 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7511 {{ 2.0f, 3.0f, 0.f}, {32767, 32767, 32767, 32767}},
7512 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7514 const DWORD exp_indices20[] = {0, 1, 2, 3, 4, 2};
7515 const DWORD exp_face_remap20[] = {0, 1};
7516 const DWORD exp_vertex_remap20[] = {0, 1, 2, 3, 4, -1};
7517 const DWORD exp_new_num_vertices20 = ARRAY_SIZE(exp_vertices20);
7518 /* Test 21. Weld normal as SHORT4N instead of D3DXVECTOR3. */
7519 const struct vertex_normal_short4 vertices21[] =
7521 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7522 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7523 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7525 {{ 3.0f, 3.0f, 0.f}, {32767, 32767, 32767, 32767}},
7526 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7527 {{ 1.0f, 0.0f, 0.f}, {32766, 32766, 32766, 32766}},
7529 const DWORD indices21[] = {0, 1, 2, 3, 4, 5};
7530 const DWORD attributes21[] = {0, 0};
7531 const UINT num_vertices21 = ARRAY_SIZE(vertices21);
7532 const UINT num_faces21 = ARRAY_SIZE(indices21) / VERTS_PER_FACE;
7533 DWORD flags21 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7534 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};
7535 const DWORD adjacency21[] = {-1, 1, -1, -1, -1, 0};
7536 const struct vertex_normal_short4 exp_vertices21[] =
7538 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7539 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7540 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7542 {{ 2.0f, 3.0f, 0.f}, {32767, 32767, 32767, 32767}},
7543 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7545 const DWORD exp_indices21[] = {0, 1, 2, 3, 4, 2};
7546 const DWORD exp_face_remap21[] = {0, 1};
7547 const DWORD exp_vertex_remap21[] = {0, 1, 2, 3, 4, -1};
7548 const DWORD exp_new_num_vertices21 = ARRAY_SIZE(exp_vertices21);
7549 /* Test 22. Weld normal as USHORT4N instead of D3DXVECTOR3. */
7550 const struct vertex_normal_short4 vertices22[] =
7552 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7553 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7554 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7556 {{ 3.0f, 3.0f, 0.f}, {65535, 65535, 65535, 65535}},
7557 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7558 {{ 1.0f, 0.0f, 0.f}, {65534, 65534, 65534, 65534}},
7560 const DWORD indices22[] = {0, 1, 2, 3, 4, 5};
7561 const DWORD attributes22[] = {0, 0};
7562 const UINT num_vertices22 = ARRAY_SIZE(vertices22);
7563 const UINT num_faces22 = ARRAY_SIZE(indices22) / VERTS_PER_FACE;
7564 DWORD flags22 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7565 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};
7566 const DWORD adjacency22[] = {-1, 1, -1, -1, -1, 0};
7567 const struct vertex_normal_short4 exp_vertices22[] =
7569 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7570 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7571 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7573 {{ 2.0f, 3.0f, 0.f}, {65535, 65535, 65535, 65535}},
7574 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7576 const DWORD exp_indices22[] = {0, 1, 2, 3, 4, 2};
7577 const DWORD exp_face_remap22[] = {0, 1};
7578 const DWORD exp_vertex_remap22[] = {0, 1, 2, 3, 4, -1};
7579 const DWORD exp_new_num_vertices22 = ARRAY_SIZE(exp_vertices22);
7580 /* Test 23. Weld texture coordinates as FLOAT16_2. Similar to test 11, but
7581 * with texture coordinates converted to float16 in hex. */
7582 const struct vertex_texcoord_float16_2 vertices23[] =
7584 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
7585 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */
7586 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */
7588 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd}}, /* {0.2f, 0.3f} */
7589 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
7590 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */
7592 const DWORD indices23[] = {0, 1, 2, 3, 4, 5};
7593 const DWORD attributes23[] = {0, 0};
7594 const UINT num_vertices23 = ARRAY_SIZE(vertices23);
7595 const UINT num_faces23 = ARRAY_SIZE(indices23) / VERTS_PER_FACE;
7596 DWORD flags23 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7597 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};
7598 const DWORD adjacency23[] = {-1, 1, -1, -1, -1, 0};
7599 const struct vertex_texcoord_float16_2 exp_vertices23[] =
7601 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
7602 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */
7603 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */
7605 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
7606 {{ 0.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */
7608 const DWORD exp_indices23[] = {0, 1, 2, 1, 3, 4};
7609 const DWORD exp_face_remap23[] = {0, 1};
7610 const DWORD exp_vertex_remap23[] = {0, 1, 2, 4, 5, -1};
7611 const DWORD exp_new_num_vertices23 = ARRAY_SIZE(exp_vertices23);
7612 /* Test 24. Weld texture coordinates as FLOAT16_4. Similar to test 24. */
7613 const struct vertex_texcoord_float16_4 vertices24[] =
7615 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}},
7616 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a, 0x3800, 0x399a}},
7617 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd, 0xb266, 0xb4cd}},
7619 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd, 0x3266, 0x34cd}},
7620 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}},
7621 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266, 0x2e66, 0x3266}},
7623 const DWORD indices24[] = {0, 1, 2, 3, 4, 5};
7624 const DWORD attributes24[] = {0, 0};
7625 const UINT num_vertices24 = ARRAY_SIZE(vertices24);
7626 const UINT num_faces24 = ARRAY_SIZE(indices24) / VERTS_PER_FACE;
7627 DWORD flags24 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7628 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};
7629 const DWORD adjacency24[] = {-1, 1, -1, -1, -1, 0};
7630 const struct vertex_texcoord_float16_4 exp_vertices24[] =
7632 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}},
7633 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a, 0x3800, 0x399a}},
7634 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd, 0xb266, 0xb4cd}},
7636 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}},
7637 {{ 0.0f, 0.0f, 0.f}, {0x2e66, 0x3266, 0x2e66, 0x3266}},
7639 const DWORD exp_indices24[] = {0, 1, 2, 1, 3, 4};
7640 const DWORD exp_face_remap24[] = {0, 1};
7641 const DWORD exp_vertex_remap24[] = {0, 1, 2, 4, 5, -1};
7642 const DWORD exp_new_num_vertices24 = ARRAY_SIZE(exp_vertices24);
7643 /* Test 25. Weld texture coordinates with usage index 10 (TEXCOORD10). The
7644 * usage index is capped at 7, so the epsilon for TEXCOORD7 is used instead.
7646 const struct vertex_texcoord vertices25[] =
7648 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f}},
7649 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.7f}},
7650 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
7652 {{ 3.0f, 3.0f, 0.f}, {0.2f, 0.3f}},
7653 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f}},
7654 {{ 1.0f, 0.0f, 0.f}, {0.1f, 0.2f}}
7656 const DWORD indices25[] = {0, 1, 2, 3, 4, 5};
7657 const DWORD attributes25[] = {0, 0};
7658 const UINT num_vertices25 = ARRAY_SIZE(vertices25);
7659 const UINT num_faces25 = ARRAY_SIZE(indices25) / VERTS_PER_FACE;
7660 DWORD flags25 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7661 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};
7662 const DWORD adjacency25[] = {-1, 1, -1, -1, -1, 0};
7663 const struct vertex_texcoord exp_vertices25[] =
7665 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f}},
7666 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.7f}},
7667 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
7669 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f}},
7670 {{ 0.0f, 0.0f, 0.f}, {0.1f, 0.2f}},
7672 const DWORD exp_indices25[] = {0, 1, 2, 1, 3, 4};
7673 const DWORD exp_face_remap25[] = {0, 1};
7674 const DWORD exp_vertex_remap25[] = {0, 1, 2, 4, 5, -1};
7675 const DWORD exp_new_num_vertices25 = ARRAY_SIZE(exp_vertices25);
7676 /* Test 26. Weld color with usage index larger than 1. Shows that none of
7677 * the epsilon values are used. */
7678 const struct vertex_color vertices26[] =
7680 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7681 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7682 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7684 {{ 3.0f, 3.0f, 0.f}, 0x00000000},
7685 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7686 {{ 1.0f, 0.0f, 0.f}, 0x01010101},
7688 const DWORD indices26[] = {0, 1, 2, 3, 4, 5};
7689 const DWORD attributes26[] = {0, 0};
7690 const UINT num_vertices26 = ARRAY_SIZE(vertices26);
7691 const UINT num_faces26 = ARRAY_SIZE(indices26) / VERTS_PER_FACE;
7692 DWORD flags26 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7693 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};
7694 const DWORD adjacency26[] = {-1, 1, -1, -1, -1, 0};
7695 const struct vertex_color exp_vertices26[] =
7697 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7698 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7699 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7701 {{ 2.0f, 3.0f, 0.f}, 0x00000000},
7702 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7703 {{ 0.0f, 0.0f, 0.f}, 0x01010101},
7705 const DWORD exp_indices26[] = {0, 1, 2, 3, 4, 5};
7706 const DWORD exp_face_remap26[] = {0, 1};
7707 const DWORD exp_vertex_remap26[] = {0, 1, 2, 3, 4, 5};
7708 const DWORD exp_new_num_vertices26 = ARRAY_SIZE(exp_vertices26);
7709 /* Test 27. Weld color with usage index 1 (specular). */
7710 /* Previously this test used float color values and index > 1 but that case
7711 * appears to be effectively unhandled in native so the test gave
7712 * inconsistent results. */
7713 const struct vertex_color vertices27[] =
7715 {{ 0.0f, 3.0f, 0.0f}, 0x00000000},
7716 {{ 2.0f, 3.0f, 0.0f}, 0x10203040},
7717 {{ 0.0f, 0.0f, 0.0f}, 0x50607080},
7719 {{ 3.0f, 3.0f, 0.0f}, 0x11213141},
7720 {{ 3.0f, 0.0f, 0.0f}, 0xffffffff},
7721 {{ 1.0f, 0.0f, 0.0f}, 0x51617181},
7723 const DWORD indices27[] = {0, 1, 2, 3, 4, 5};
7724 const DWORD attributes27[] = {0, 0};
7725 const UINT num_vertices27 = ARRAY_SIZE(vertices27);
7726 const UINT num_faces27 = ARRAY_SIZE(indices27) / VERTS_PER_FACE;
7727 DWORD flags27 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7728 const D3DXWELDEPSILONS epsilons27 =
7730 1.1f, 0.0f, 0.0f, 0.0f, 2.0f / 255.0f, 0.0f,
7731 {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, 0.0f, 0.0f, 0.0f
7733 const DWORD adjacency27[] = {-1, 1, -1, -1, -1, 0};
7734 const struct vertex_color exp_vertices27[] =
7736 {{ 0.0f, 3.0f, 0.0f}, 0x00000000},
7737 {{ 2.0f, 3.0f, 0.0f}, 0x10203040},
7738 {{ 0.0f, 0.0f, 0.0f}, 0x50607080},
7740 {{ 3.0f, 0.0f, 0.0f}, 0xffffffff},
7742 const DWORD exp_indices27[] = {0, 1, 2, 1, 3, 2};
7743 const DWORD exp_face_remap27[] = {0, 1};
7744 const DWORD exp_vertex_remap27[] = {0, 1, 2, 4, -1, -1};
7745 const DWORD exp_new_num_vertices27 = ARRAY_SIZE(exp_vertices27);
7746 /* Test 28. Weld one normal with UDEC3. */
7747 const DWORD dword_udec3_zero = init_udec3_dword(0, 0, 0, 1);
7748 const DWORD dword_udec3_1023 = init_udec3_dword(1023, 1023, 1023, 1);
7749 const DWORD dword_udec3_1022 = init_udec3_dword(1022, 1022, 1022, 1);
7750 const struct vertex_normal_udec3 vertices28[] =
7752 {{ 0.0f, 3.0f, 0.f}, dword_udec3_zero},
7753 {{ 2.0f, 3.0f, 0.f}, dword_udec3_zero},
7754 {{ 0.0f, 0.0f, 0.f}, dword_udec3_zero},
7756 {{ 3.0f, 3.0f, 0.f}, dword_udec3_1023},
7757 {{ 3.0f, 0.0f, 0.f}, dword_udec3_zero},
7758 {{ 1.0f, 0.0f, 0.f}, dword_udec3_1022},
7760 const DWORD indices28[] = {0, 1, 2, 3, 4, 5};
7761 const DWORD attributes28[] = {0, 0};
7762 const UINT num_vertices28 = ARRAY_SIZE(vertices28);
7763 const UINT num_faces28 = ARRAY_SIZE(indices28) / VERTS_PER_FACE;
7764 DWORD flags28 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7765 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};
7766 const DWORD adjacency28[] = {-1, 1, -1, -1, -1, 0};
7767 const struct vertex_normal_udec3 exp_vertices28[] =
7769 {{ 0.0f, 3.0f, 0.f}, dword_udec3_zero},
7770 {{ 2.0f, 3.0f, 0.f}, dword_udec3_zero},
7771 {{ 0.0f, 0.0f, 0.f}, dword_udec3_zero},
7773 {{ 2.0f, 3.0f, 0.f}, dword_udec3_1023},
7774 {{ 3.0f, 0.0f, 0.f}, dword_udec3_zero},
7776 const DWORD exp_indices28[] = {0, 1, 2, 3, 4, 2};
7777 const DWORD exp_face_remap28[] = {0, 1};
7778 const DWORD exp_vertex_remap28[] = {0, 1, 2, 3, 4, -1};
7779 const DWORD exp_new_num_vertices28 = ARRAY_SIZE(exp_vertices28);
7780 /* Test 29. Weld one normal with DEC3N. */
7781 const DWORD dword_dec3n_zero = init_dec3n_dword(0, 0, 0, 1);
7782 const DWORD dword_dec3n_511 = init_dec3n_dword(511, 511, 511, 1);
7783 const DWORD dword_dec3n_510 = init_dec3n_dword(510, 510, 510, 1);
7784 const struct vertex_normal_dec3n vertices29[] =
7786 {{ 0.0f, 3.0f, 0.f}, dword_dec3n_zero},
7787 {{ 2.0f, 3.0f, 0.f}, dword_dec3n_zero},
7788 {{ 0.0f, 0.0f, 0.f}, dword_dec3n_zero},
7790 {{ 3.0f, 3.0f, 0.f}, dword_dec3n_511},
7791 {{ 3.0f, 0.0f, 0.f}, dword_dec3n_zero},
7792 {{ 1.0f, 0.0f, 0.f}, dword_dec3n_510},
7794 const DWORD indices29[] = {0, 1, 2, 3, 4, 5};
7795 const DWORD attributes29[] = {0, 0};
7796 const UINT num_vertices29 = ARRAY_SIZE(vertices29);
7797 const UINT num_faces29 = ARRAY_SIZE(indices29) / VERTS_PER_FACE;
7798 DWORD flags29 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7799 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};
7800 const DWORD adjacency29[] = {-1, 1, -1, -1, -1, 0};
7801 const struct vertex_normal_dec3n exp_vertices29[] =
7803 {{ 0.0f, 3.0f, 0.f}, dword_dec3n_zero},
7804 {{ 2.0f, 3.0f, 0.f}, dword_dec3n_zero},
7805 {{ 0.0f, 0.0f, 0.f}, dword_dec3n_zero},
7807 {{ 2.0f, 3.0f, 0.f}, dword_dec3n_511},
7808 {{ 3.0f, 0.0f, 0.f}, dword_dec3n_zero},
7810 const DWORD exp_indices29[] = {0, 1, 2, 3, 4, 2};
7811 const DWORD exp_face_remap29[] = {0, 1};
7812 const DWORD exp_vertex_remap29[] = {0, 1, 2, 3, 4, -1};
7813 const DWORD exp_new_num_vertices29 = ARRAY_SIZE(exp_vertices29);
7814 /* All mesh data */
7815 DWORD *adjacency_out = NULL;
7816 DWORD *face_remap = NULL;
7817 ID3DXMesh *mesh = NULL;
7818 ID3DXBuffer *vertex_remap = NULL;
7819 struct
7821 const BYTE *vertices;
7822 const DWORD *indices;
7823 const DWORD *attributes;
7824 const DWORD num_vertices;
7825 const DWORD num_faces;
7826 const DWORD options;
7827 D3DVERTEXELEMENT9 *declaration;
7828 const UINT vertex_size;
7829 const DWORD flags;
7830 const D3DXWELDEPSILONS *epsilons;
7831 const DWORD *adjacency;
7832 const BYTE *exp_vertices;
7833 const DWORD *exp_indices;
7834 const DWORD *exp_face_remap;
7835 const DWORD *exp_vertex_remap;
7836 const DWORD exp_new_num_vertices;
7838 tc[] =
7841 (BYTE*)vertices0,
7842 indices0,
7843 attributes0,
7844 num_vertices0,
7845 num_faces0,
7846 options,
7847 declaration_normal,
7848 vertex_size_normal,
7849 flags0,
7850 NULL,
7851 adjacency0,
7852 (BYTE*)exp_vertices0,
7853 exp_indices0,
7854 exp_face_remap0,
7855 exp_vertex_remap0,
7856 exp_new_num_vertices0
7859 (BYTE*)vertices1,
7860 indices1,
7861 attributes1,
7862 num_vertices1,
7863 num_faces1,
7864 options,
7865 declaration_normal,
7866 vertex_size_normal,
7867 flags1,
7868 NULL,
7869 adjacency1,
7870 (BYTE*)exp_vertices1,
7871 exp_indices1,
7872 exp_face_remap1,
7873 exp_vertex_remap1,
7874 exp_new_num_vertices1
7877 (BYTE*)vertices2,
7878 indices2,
7879 attributes2,
7880 num_vertices2,
7881 num_faces2,
7882 options,
7883 declaration_normal,
7884 vertex_size_normal,
7885 flags2,
7886 &epsilons2,
7887 adjacency2,
7888 (BYTE*)exp_vertices2,
7889 exp_indices2,
7890 exp_face_remap2,
7891 exp_vertex_remap2,
7892 exp_new_num_vertices2
7895 (BYTE*)vertices3,
7896 indices3,
7897 attributes3,
7898 num_vertices3,
7899 num_faces3,
7900 options,
7901 declaration_normal,
7902 vertex_size_normal,
7903 flags3,
7904 &epsilons3,
7905 adjacency3,
7906 (BYTE*)exp_vertices3,
7907 exp_indices3,
7908 exp_face_remap3,
7909 exp_vertex_remap3,
7910 exp_new_num_vertices3
7913 (BYTE*)vertices4,
7914 indices4,
7915 attributes4,
7916 num_vertices4,
7917 num_faces4,
7918 options,
7919 declaration_normal,
7920 vertex_size_normal,
7921 flags4,
7922 &epsilons4,
7923 adjacency4,
7924 (BYTE*)exp_vertices4,
7925 exp_indices4,
7926 exp_face_remap4,
7927 exp_vertex_remap4,
7928 exp_new_num_vertices4
7930 /* Unusual ordering. */
7932 (BYTE*)vertices5,
7933 indices5,
7934 attributes5,
7935 num_vertices5,
7936 num_faces5,
7937 options,
7938 declaration_normal,
7939 vertex_size_normal,
7940 flags5,
7941 NULL,
7942 adjacency5,
7943 (BYTE*)exp_vertices5,
7944 exp_indices5,
7945 exp_face_remap5,
7946 exp_vertex_remap5,
7947 exp_new_num_vertices5
7950 (BYTE*)vertices6,
7951 indices6,
7952 attributes6,
7953 num_vertices6,
7954 num_faces6,
7955 options,
7956 declaration_normal,
7957 vertex_size_normal,
7958 flags6,
7959 &epsilons6,
7960 adjacency6,
7961 (BYTE*)exp_vertices6,
7962 exp_indices6,
7963 exp_face_remap6,
7964 exp_vertex_remap6,
7965 exp_new_num_vertices6
7968 (BYTE*)vertices6,
7969 (DWORD*)indices6_16bit,
7970 attributes6,
7971 num_vertices6,
7972 num_faces6,
7973 options_16bit,
7974 declaration_normal,
7975 vertex_size_normal,
7976 flags6,
7977 &epsilons6,
7978 adjacency6,
7979 (BYTE*)exp_vertices6,
7980 exp_indices6,
7981 exp_face_remap6,
7982 exp_vertex_remap6,
7983 exp_new_num_vertices6
7986 (BYTE*)vertices8,
7987 indices8,
7988 attributes8,
7989 num_vertices8,
7990 num_faces8,
7991 options,
7992 declaration_normal,
7993 vertex_size_normal,
7994 flags8,
7995 &epsilons8,
7996 adjacency8,
7997 (BYTE*)exp_vertices8,
7998 exp_indices8,
7999 exp_face_remap8,
8000 exp_vertex_remap8,
8001 exp_new_num_vertices8
8004 (BYTE*)vertices9,
8005 indices9,
8006 attributes9,
8007 num_vertices9,
8008 num_faces9,
8009 options,
8010 declaration_normal,
8011 vertex_size_normal,
8012 flags9,
8013 &epsilons9,
8014 adjacency9,
8015 (BYTE*)exp_vertices9,
8016 exp_indices9,
8017 exp_face_remap9,
8018 exp_vertex_remap9,
8019 exp_new_num_vertices9
8022 (BYTE*)vertices10,
8023 indices10,
8024 attributes10,
8025 num_vertices10,
8026 num_faces10,
8027 options,
8028 declaration_blendweight,
8029 vertex_size_blendweight,
8030 flags10,
8031 &epsilons10,
8032 adjacency10,
8033 (BYTE*)exp_vertices10,
8034 exp_indices10,
8035 exp_face_remap10,
8036 exp_vertex_remap10,
8037 exp_new_num_vertices10
8040 (BYTE*)vertices11,
8041 indices11,
8042 attributes11,
8043 num_vertices11,
8044 num_faces11,
8045 options,
8046 declaration_texcoord,
8047 vertex_size_texcoord,
8048 flags11,
8049 &epsilons11,
8050 adjacency11,
8051 (BYTE*)exp_vertices11,
8052 exp_indices11,
8053 exp_face_remap11,
8054 exp_vertex_remap11,
8055 exp_new_num_vertices11
8058 (BYTE*)vertices12,
8059 indices12,
8060 attributes12,
8061 num_vertices12,
8062 num_faces12,
8063 options,
8064 declaration_color,
8065 vertex_size_color,
8066 flags12,
8067 &epsilons12,
8068 adjacency12,
8069 (BYTE*)exp_vertices12,
8070 exp_indices12,
8071 exp_face_remap12,
8072 exp_vertex_remap12,
8073 exp_new_num_vertices12
8076 (BYTE*)vertices13,
8077 indices13,
8078 attributes13,
8079 num_vertices13,
8080 num_faces13,
8081 options,
8082 declaration_normal3,
8083 vertex_size_normal,
8084 flags13,
8085 &epsilons13,
8086 adjacency13,
8087 (BYTE*)exp_vertices13,
8088 exp_indices13,
8089 exp_face_remap13,
8090 exp_vertex_remap13,
8091 exp_new_num_vertices13
8094 (BYTE*)vertices14,
8095 indices14,
8096 attributes14,
8097 num_vertices14,
8098 num_faces14,
8099 options,
8100 declaration_color,
8101 vertex_size_color,
8102 flags14,
8103 &epsilons14,
8104 adjacency14,
8105 (BYTE*)exp_vertices14,
8106 exp_indices14,
8107 exp_face_remap14,
8108 exp_vertex_remap14,
8109 exp_new_num_vertices14
8112 (BYTE*)vertices15,
8113 indices15,
8114 attributes15,
8115 num_vertices15,
8116 num_faces15,
8117 options,
8118 declaration_color_ubyte4n,
8119 vertex_size_color_ubyte4, /* UBYTE4 same size as UBYTE4N */
8120 flags15,
8121 &epsilons15,
8122 adjacency15,
8123 (BYTE*)exp_vertices15,
8124 exp_indices15,
8125 exp_face_remap15,
8126 exp_vertex_remap15,
8127 exp_new_num_vertices15
8130 (BYTE*)vertices16,
8131 indices16,
8132 attributes16,
8133 num_vertices16,
8134 num_faces16,
8135 options,
8136 declaration_color_ubyte4,
8137 vertex_size_color_ubyte4,
8138 flags16,
8139 &epsilons16,
8140 adjacency16,
8141 (BYTE*)exp_vertices16,
8142 exp_indices16,
8143 exp_face_remap16,
8144 exp_vertex_remap16,
8145 exp_new_num_vertices16
8148 (BYTE*)vertices17,
8149 indices17,
8150 attributes17,
8151 num_vertices17,
8152 num_faces17,
8153 options,
8154 declaration_texcoord_short2,
8155 vertex_size_texcoord_short2,
8156 flags17,
8157 &epsilons17,
8158 adjacency17,
8159 (BYTE*)exp_vertices17,
8160 exp_indices17,
8161 exp_face_remap17,
8162 exp_vertex_remap17,
8163 exp_new_num_vertices17
8166 (BYTE*)vertices18,
8167 indices18,
8168 attributes18,
8169 num_vertices18,
8170 num_faces18,
8171 options,
8172 declaration_texcoord_short2n,
8173 vertex_size_texcoord_short2, /* SHORT2 same size as SHORT2N */
8174 flags18,
8175 &epsilons18,
8176 adjacency18,
8177 (BYTE*)exp_vertices18,
8178 exp_indices18,
8179 exp_face_remap18,
8180 exp_vertex_remap18,
8181 exp_new_num_vertices18
8184 (BYTE*)vertices19,
8185 indices19,
8186 attributes19,
8187 num_vertices19,
8188 num_faces19,
8189 options,
8190 declaration_texcoord_ushort2n,
8191 vertex_size_texcoord_short2, /* SHORT2 same size as USHORT2N */
8192 flags19,
8193 &epsilons19,
8194 adjacency19,
8195 (BYTE*)exp_vertices19,
8196 exp_indices19,
8197 exp_face_remap19,
8198 exp_vertex_remap19,
8199 exp_new_num_vertices19
8202 (BYTE*)vertices20,
8203 indices20,
8204 attributes20,
8205 num_vertices20,
8206 num_faces20,
8207 options,
8208 declaration_normal_short4,
8209 vertex_size_normal_short4,
8210 flags20,
8211 &epsilons20,
8212 adjacency20,
8213 (BYTE*)exp_vertices20,
8214 exp_indices20,
8215 exp_face_remap20,
8216 exp_vertex_remap20,
8217 exp_new_num_vertices20
8220 (BYTE*)vertices21,
8221 indices21,
8222 attributes21,
8223 num_vertices21,
8224 num_faces21,
8225 options,
8226 declaration_normal_short4n,
8227 vertex_size_normal_short4, /* SHORT4 same size as SHORT4N */
8228 flags21,
8229 &epsilons21,
8230 adjacency21,
8231 (BYTE*)exp_vertices21,
8232 exp_indices21,
8233 exp_face_remap21,
8234 exp_vertex_remap21,
8235 exp_new_num_vertices21
8238 (BYTE*)vertices22,
8239 indices22,
8240 attributes22,
8241 num_vertices22,
8242 num_faces22,
8243 options,
8244 declaration_normal_ushort4n,
8245 vertex_size_normal_short4, /* SHORT4 same size as USHORT4N */
8246 flags22,
8247 &epsilons22,
8248 adjacency22,
8249 (BYTE*)exp_vertices22,
8250 exp_indices22,
8251 exp_face_remap22,
8252 exp_vertex_remap22,
8253 exp_new_num_vertices22
8256 (BYTE*)vertices23,
8257 indices23,
8258 attributes23,
8259 num_vertices23,
8260 num_faces23,
8261 options,
8262 declaration_texcoord_float16_2,
8263 vertex_size_texcoord_float16_2,
8264 flags23,
8265 &epsilons23,
8266 adjacency23,
8267 (BYTE*)exp_vertices23,
8268 exp_indices23,
8269 exp_face_remap23,
8270 exp_vertex_remap23,
8271 exp_new_num_vertices23
8274 (BYTE*)vertices24,
8275 indices24,
8276 attributes24,
8277 num_vertices24,
8278 num_faces24,
8279 options,
8280 declaration_texcoord_float16_4,
8281 vertex_size_texcoord_float16_4,
8282 flags24,
8283 &epsilons24,
8284 adjacency24,
8285 (BYTE*)exp_vertices24,
8286 exp_indices24,
8287 exp_face_remap24,
8288 exp_vertex_remap24,
8289 exp_new_num_vertices24
8292 (BYTE*)vertices25,
8293 indices25,
8294 attributes25,
8295 num_vertices25,
8296 num_faces25,
8297 options,
8298 declaration_texcoord10,
8299 vertex_size_texcoord,
8300 flags25,
8301 &epsilons25,
8302 adjacency25,
8303 (BYTE*)exp_vertices25,
8304 exp_indices25,
8305 exp_face_remap25,
8306 exp_vertex_remap25,
8307 exp_new_num_vertices25
8310 (BYTE*)vertices26,
8311 indices26,
8312 attributes26,
8313 num_vertices26,
8314 num_faces26,
8315 options,
8316 declaration_color2,
8317 vertex_size_color,
8318 flags26,
8319 &epsilons26,
8320 adjacency26,
8321 (BYTE*)exp_vertices26,
8322 exp_indices26,
8323 exp_face_remap26,
8324 exp_vertex_remap26,
8325 exp_new_num_vertices26
8328 (BYTE*)vertices27,
8329 indices27,
8330 attributes27,
8331 num_vertices27,
8332 num_faces27,
8333 options,
8334 declaration_color1,
8335 vertex_size_color,
8336 flags27,
8337 &epsilons27,
8338 adjacency27,
8339 (BYTE*)exp_vertices27,
8340 exp_indices27,
8341 exp_face_remap27,
8342 exp_vertex_remap27,
8343 exp_new_num_vertices27
8346 (BYTE*)vertices28,
8347 indices28,
8348 attributes28,
8349 num_vertices28,
8350 num_faces28,
8351 options,
8352 declaration_normal_udec3,
8353 vertex_size_normal_udec3,
8354 flags28,
8355 &epsilons28,
8356 adjacency28,
8357 (BYTE*)exp_vertices28,
8358 exp_indices28,
8359 exp_face_remap28,
8360 exp_vertex_remap28,
8361 exp_new_num_vertices28
8364 (BYTE*)vertices29,
8365 indices29,
8366 attributes29,
8367 num_vertices29,
8368 num_faces29,
8369 options,
8370 declaration_normal_dec3n,
8371 vertex_size_normal_dec3n,
8372 flags29,
8373 &epsilons29,
8374 adjacency29,
8375 (BYTE*)exp_vertices29,
8376 exp_indices29,
8377 exp_face_remap29,
8378 exp_vertex_remap29,
8379 exp_new_num_vertices29
8383 test_context = new_test_context();
8384 if (!test_context)
8386 skip("Couldn't create test context\n");
8387 goto cleanup;
8390 for (i = 0; i < ARRAY_SIZE(tc); i++)
8392 DWORD j;
8393 DWORD *vertex_remap_ptr;
8394 DWORD new_num_vertices;
8396 hr = init_test_mesh(tc[i].num_faces, tc[i].num_vertices, tc[i].options,
8397 tc[i].declaration, test_context->device, &mesh,
8398 tc[i].vertices, tc[i].vertex_size,
8399 tc[i].indices, tc[i].attributes);
8400 if (FAILED(hr))
8402 skip("Couldn't initialize test mesh %d.\n", i);
8403 goto cleanup;
8406 /* Allocate out parameters */
8407 adjacency_out = HeapAlloc(GetProcessHeap(), 0, VERTS_PER_FACE * tc[i].num_faces * sizeof(*adjacency_out));
8408 if (!adjacency_out)
8410 skip("Couldn't allocate adjacency_out array.\n");
8411 goto cleanup;
8413 face_remap = HeapAlloc(GetProcessHeap(), 0, tc[i].num_faces * sizeof(*face_remap));
8414 if (!face_remap)
8416 skip("Couldn't allocate face_remap array.\n");
8417 goto cleanup;
8420 hr = D3DXWeldVertices(mesh, tc[i].flags, tc[i].epsilons, tc[i].adjacency,
8421 adjacency_out, face_remap, &vertex_remap);
8422 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
8423 /* Check number of vertices*/
8424 new_num_vertices = mesh->lpVtbl->GetNumVertices(mesh);
8425 ok(new_num_vertices == tc[i].exp_new_num_vertices,
8426 "Mesh %d: new_num_vertices == %d, expected %d.\n",
8427 i, new_num_vertices, tc[i].exp_new_num_vertices);
8428 /* Check index buffer */
8429 if (tc[i].options & D3DXMESH_32BIT)
8431 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, (void**)&indices);
8432 if (FAILED(hr))
8434 skip("Couldn't lock index buffer.\n");
8435 goto cleanup;
8437 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
8439 ok(indices[j] == tc[i].exp_indices[j],
8440 "Mesh %d: indices[%d] == %d, expected %d\n",
8441 i, j, indices[j], tc[i].exp_indices[j]);
8444 else
8446 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, (void**)&indices_16bit);
8447 if (FAILED(hr))
8449 skip("Couldn't lock index buffer.\n");
8450 goto cleanup;
8452 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
8454 ok(indices_16bit[j] == tc[i].exp_indices[j],
8455 "Mesh %d: indices_16bit[%d] == %d, expected %d\n",
8456 i, j, indices_16bit[j], tc[i].exp_indices[j]);
8459 mesh->lpVtbl->UnlockIndexBuffer(mesh);
8460 indices = NULL;
8461 indices_16bit = NULL;
8462 /* Check adjacency_out */
8463 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
8465 ok(adjacency_out[j] == tc[i].adjacency[j],
8466 "Mesh %d: adjacency_out[%d] == %d, expected %d\n",
8467 i, j, adjacency_out[j], tc[i].adjacency[j]);
8469 /* Check face_remap */
8470 for (j = 0; j < tc[i].num_faces; j++)
8472 ok(face_remap[j] == tc[i].exp_face_remap[j],
8473 "Mesh %d: face_remap[%d] == %d, expected %d\n",
8474 i, j, face_remap[j], tc[i].exp_face_remap[j]);
8476 /* Check vertex_remap */
8477 vertex_remap_ptr = vertex_remap->lpVtbl->GetBufferPointer(vertex_remap);
8478 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
8480 ok(vertex_remap_ptr[j] == tc[i].exp_vertex_remap[j],
8481 "Mesh %d: vertex_remap_ptr[%d] == %d, expected %d\n",
8482 i, j, vertex_remap_ptr[j], tc[i].exp_vertex_remap[j]);
8484 /* Check vertex buffer */
8485 hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, (void*)&vertices);
8486 if (FAILED(hr))
8488 skip("Couldn't lock vertex buffer.\n");
8489 goto cleanup;
8491 /* Check contents of re-ordered vertex buffer */
8492 for (j = 0; j < tc[i].exp_new_num_vertices; j++)
8494 int index = tc[i].vertex_size*j;
8495 check_vertex_components(__LINE__, i, j, &vertices[index], &tc[i].exp_vertices[index], tc[i].declaration);
8497 mesh->lpVtbl->UnlockVertexBuffer(mesh);
8498 vertices = NULL;
8500 /* Free mesh and output data */
8501 HeapFree(GetProcessHeap(), 0, adjacency_out);
8502 adjacency_out = NULL;
8503 HeapFree(GetProcessHeap(), 0, face_remap);
8504 face_remap = NULL;
8505 vertex_remap->lpVtbl->Release(vertex_remap);
8506 vertex_remap = NULL;
8507 mesh->lpVtbl->Release(mesh);
8508 mesh = NULL;
8511 cleanup:
8512 HeapFree(GetProcessHeap(), 0, adjacency_out);
8513 HeapFree(GetProcessHeap(), 0, face_remap);
8514 if (indices) mesh->lpVtbl->UnlockIndexBuffer(mesh);
8515 if (indices_16bit) mesh->lpVtbl->UnlockIndexBuffer(mesh);
8516 if (mesh) mesh->lpVtbl->Release(mesh);
8517 if (vertex_remap) vertex_remap->lpVtbl->Release(vertex_remap);
8518 if (vertices) mesh->lpVtbl->UnlockVertexBuffer(mesh);
8519 free_test_context(test_context);
8522 static void test_clone_mesh(void)
8524 HRESULT hr;
8525 struct test_context *test_context = NULL;
8526 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
8527 D3DVERTEXELEMENT9 declaration_pn[] =
8529 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8530 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
8531 D3DDECL_END()
8533 D3DVERTEXELEMENT9 declaration_pntc[] =
8535 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8536 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
8537 {0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8538 D3DDECL_END()
8540 D3DVERTEXELEMENT9 declaration_ptcn[] =
8542 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8543 {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8544 {0, 20, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
8545 D3DDECL_END()
8547 D3DVERTEXELEMENT9 declaration_ptc[] =
8549 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8550 {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8551 D3DDECL_END()
8553 D3DVERTEXELEMENT9 declaration_ptc_float16_2[] =
8555 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8556 {0, 12, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8557 D3DDECL_END()
8559 D3DVERTEXELEMENT9 declaration_ptc_float16_4[] =
8561 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8562 {0, 12, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8563 D3DDECL_END()
8565 D3DVERTEXELEMENT9 declaration_ptc_float1[] =
8567 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8568 {0, 12, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8569 D3DDECL_END()
8571 D3DVERTEXELEMENT9 declaration_ptc_float3[] =
8573 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8574 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8575 D3DDECL_END()
8577 D3DVERTEXELEMENT9 declaration_ptc_float4[] =
8579 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8580 {0, 12, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8581 D3DDECL_END()
8583 D3DVERTEXELEMENT9 declaration_ptc_d3dcolor[] =
8585 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8586 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8587 D3DDECL_END()
8589 D3DVERTEXELEMENT9 declaration_ptc_ubyte4[] =
8591 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8592 {0, 12, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8593 D3DDECL_END()
8595 D3DVERTEXELEMENT9 declaration_ptc_ubyte4n[] =
8597 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8598 {0, 12, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8599 D3DDECL_END()
8601 D3DVERTEXELEMENT9 declaration_ptc_short2[] =
8603 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8604 {0, 12, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8605 D3DDECL_END()
8607 D3DVERTEXELEMENT9 declaration_ptc_short4[] =
8609 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8610 {0, 12, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8611 D3DDECL_END()
8613 D3DVERTEXELEMENT9 declaration_ptc_short2n[] =
8615 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8616 {0, 12, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8617 D3DDECL_END()
8619 D3DVERTEXELEMENT9 declaration_ptc_short4n[] =
8621 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8622 {0, 12, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8623 D3DDECL_END()
8625 D3DVERTEXELEMENT9 declaration_ptc_ushort2n[] =
8627 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8628 {0, 12, D3DDECLTYPE_USHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8629 D3DDECL_END()
8631 D3DVERTEXELEMENT9 declaration_ptc_ushort4n[] =
8633 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8634 {0, 12, D3DDECLTYPE_USHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8635 D3DDECL_END()
8637 D3DVERTEXELEMENT9 declaration_ptc_float16_2_partialu[] =
8639 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8640 {0, 12, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_PARTIALU, D3DDECLUSAGE_TEXCOORD, 0},
8641 D3DDECL_END()
8643 D3DVERTEXELEMENT9 declaration_pntc1[] =
8645 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8646 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
8647 {0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
8648 D3DDECL_END()
8650 const unsigned int VERTS_PER_FACE = 3;
8651 BYTE *vertices = NULL;
8652 INT i;
8653 struct vertex_pn
8655 D3DXVECTOR3 position;
8656 D3DXVECTOR3 normal;
8658 struct vertex_pntc
8660 D3DXVECTOR3 position;
8661 D3DXVECTOR3 normal;
8662 D3DXVECTOR2 texcoords;
8664 struct vertex_ptcn
8666 D3DXVECTOR3 position;
8667 D3DXVECTOR2 texcoords;
8668 D3DXVECTOR3 normal;
8670 struct vertex_ptc
8672 D3DXVECTOR3 position;
8673 D3DXVECTOR2 texcoords;
8675 struct vertex_ptc_float16_2
8677 D3DXVECTOR3 position;
8678 WORD texcoords[2]; /* float16_2 */
8680 struct vertex_ptc_float16_4
8682 D3DXVECTOR3 position;
8683 WORD texcoords[4]; /* float16_4 */
8685 struct vertex_ptc_float1
8687 D3DXVECTOR3 position;
8688 FLOAT texcoords;
8690 struct vertex_ptc_float3
8692 D3DXVECTOR3 position;
8693 FLOAT texcoords[3];
8695 struct vertex_ptc_float4
8697 D3DXVECTOR3 position;
8698 FLOAT texcoords[4];
8700 struct vertex_ptc_d3dcolor
8702 D3DXVECTOR3 position;
8703 BYTE texcoords[4];
8705 struct vertex_ptc_ubyte4
8707 D3DXVECTOR3 position;
8708 BYTE texcoords[4];
8710 struct vertex_ptc_ubyte4n
8712 D3DXVECTOR3 position;
8713 BYTE texcoords[4];
8715 struct vertex_ptc_short2
8717 D3DXVECTOR3 position;
8718 SHORT texcoords[2];
8720 struct vertex_ptc_short4
8722 D3DXVECTOR3 position;
8723 SHORT texcoords[4];
8725 struct vertex_ptc_ushort2n
8727 D3DXVECTOR3 position;
8728 USHORT texcoords[2];
8730 struct vertex_ptc_ushort4n
8732 D3DXVECTOR3 position;
8733 USHORT texcoords[4];
8735 struct vertex_ptc_udec3
8737 D3DXVECTOR3 position;
8738 DWORD texcoords;
8740 struct vertex_ptc_dec3n
8742 D3DXVECTOR3 position;
8743 DWORD texcoords;
8745 D3DXVECTOR3 up = {0.0f, 0.0f, 1.0f};
8746 D3DXVECTOR2 zero_vec2 = {0.0f, 0.0f};
8747 /* Test 0. Check that a mesh can be cloned if the new declaration is the
8748 * same as the one used to create the mesh.
8750 * 0--1 3
8751 * | / /|
8752 * |/ / |
8753 * 2 5--4
8755 const struct vertex_pn vertices0[] =
8757 {{ 0.0f, 3.0f, 0.f}, up},
8758 {{ 2.0f, 3.0f, 0.f}, up},
8759 {{ 0.0f, 0.0f, 0.f}, up},
8761 {{ 3.0f, 3.0f, 0.f}, up},
8762 {{ 3.0f, 0.0f, 0.f}, up},
8763 {{ 1.0f, 0.0f, 0.f}, up},
8765 const UINT num_vertices0 = ARRAY_SIZE(vertices0);
8766 const UINT num_faces0 = ARRAY_SIZE(vertices0) / VERTS_PER_FACE;
8767 const UINT vertex_size0 = sizeof(*vertices0);
8768 /* Test 1. Check that 16-bit indices are handled. */
8769 const DWORD options_16bit = D3DXMESH_SYSTEMMEM;
8770 /* Test 2. Check that the size of each vertex is increased and the data
8771 * moved if the new declaration adds an element after the original elements.
8773 const struct vertex_pntc exp_vertices2[] =
8775 {{ 0.0f, 3.0f, 0.f}, up, zero_vec2},
8776 {{ 2.0f, 3.0f, 0.f}, up, zero_vec2},
8777 {{ 0.0f, 0.0f, 0.f}, up, zero_vec2},
8779 {{ 3.0f, 3.0f, 0.f}, up, zero_vec2},
8780 {{ 3.0f, 0.0f, 0.f}, up, zero_vec2},
8781 {{ 1.0f, 0.0f, 0.f}, up, zero_vec2},
8783 const UINT exp_vertex_size2 = sizeof(*exp_vertices2);
8784 /* Test 3. Check that the size of each vertex is increased and the data
8785 * moved if the new declaration adds an element between the original
8786 * elements.
8788 const struct vertex_ptcn exp_vertices3[] =
8790 {{ 0.0f, 3.0f, 0.f}, zero_vec2, up},
8791 {{ 2.0f, 3.0f, 0.f}, zero_vec2, up},
8792 {{ 0.0f, 0.0f, 0.f}, zero_vec2, up},
8794 {{ 3.0f, 3.0f, 0.f}, zero_vec2, up},
8795 {{ 3.0f, 0.0f, 0.f}, zero_vec2, up},
8796 {{ 1.0f, 0.0f, 0.f}, zero_vec2, up},
8798 const UINT exp_vertex_size3 = sizeof(*exp_vertices3);
8799 /* Test 4. Test that data types can be converted, e.g. FLOAT2 to FLOAT16_2. */
8800 const struct vertex_ptc vertices4[] =
8802 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8803 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8804 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
8806 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8807 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
8808 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
8810 const UINT num_vertices4 = ARRAY_SIZE(vertices4);
8811 const UINT num_faces4 = ARRAY_SIZE(vertices4) / VERTS_PER_FACE;
8812 const UINT vertex_size4 = sizeof(*vertices4);
8813 const struct vertex_ptc_float16_2 exp_vertices4[] =
8815 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
8816 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */
8817 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */
8819 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd}}, /* {0.2f, 0.3f} */
8820 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
8821 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */
8823 const UINT exp_vertex_size4 = sizeof(*exp_vertices4);
8824 /* Test 5. Convert FLOAT2 to FLOAT16_4. */
8825 const struct vertex_ptc vertices5[] =
8827 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8828 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8829 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
8831 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8832 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
8833 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
8835 const UINT num_vertices5 = ARRAY_SIZE(vertices5);
8836 const UINT num_faces5 = ARRAY_SIZE(vertices5) / VERTS_PER_FACE;
8837 const UINT vertex_size5 = sizeof(*vertices5);
8838 const struct vertex_ptc_float16_4 exp_vertices5[] =
8840 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00, 0, 0x3c00}}, /* {1.0f, 1.0f, 0.0f, 1.0f} */
8841 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a, 0, 0x3c00}}, /* {0.5f, 0.7f, 0.0f, 1.0f} */
8842 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd, 0, 0x3c00}}, /* {-0.2f, -0.3f, 0.0f, 1.0f} */
8844 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd, 0, 0x3c00}}, /* {0.2f, 0.3f, 0.0f, 1.0f} */
8845 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00, 0, 0x3c00}}, /* {1.0f, 1.0f, 0.0f, 1.0f} */
8846 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266, 0, 0x3c00}}, /* {0.1f, 0.2f, 0.0f, 1.0f} */
8848 const UINT exp_vertex_size5 = sizeof(*exp_vertices5);
8849 /* Test 6. Convert FLOAT2 to FLOAT1. */
8850 const struct vertex_ptc vertices6[] =
8852 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8853 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8854 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
8856 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8857 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
8858 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
8860 const UINT num_vertices6 = ARRAY_SIZE(vertices6);
8861 const UINT num_faces6 = ARRAY_SIZE(vertices6) / VERTS_PER_FACE;
8862 const UINT vertex_size6 = sizeof(*vertices6);
8863 const struct vertex_ptc_float1 exp_vertices6[] =
8865 {{ 0.0f, 3.0f, 0.f}, 1.0f},
8866 {{ 2.0f, 3.0f, 0.f}, 0.5f},
8867 {{ 0.0f, 0.0f, 0.f}, -0.2f},
8869 {{ 3.0f, 3.0f, 0.f}, 0.2f},
8870 {{ 3.0f, 0.0f, 0.f}, 1.0f},
8871 {{ 1.0f, 0.0f, 0.f}, 0.1f},
8873 const UINT exp_vertex_size6 = sizeof(*exp_vertices6);
8874 /* Test 7. Convert FLOAT2 to FLOAT3. */
8875 const struct vertex_ptc vertices7[] =
8877 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8878 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8879 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
8881 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8882 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
8883 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
8885 const UINT num_vertices7 = ARRAY_SIZE(vertices7);
8886 const UINT num_faces7 = ARRAY_SIZE(vertices7) / VERTS_PER_FACE;
8887 const UINT vertex_size7 = sizeof(*vertices7);
8888 const struct vertex_ptc_float3 exp_vertices7[] =
8890 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f, 0.0f}},
8891 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f, 0.0f}},
8892 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f, 0.0f}},
8894 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f, 0.0f}},
8895 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f, 0.0f}},
8896 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f, 0.0f}},
8898 const UINT exp_vertex_size7 = sizeof(*exp_vertices7);
8899 /* Test 8. Convert FLOAT2 to FLOAT4. */
8900 const struct vertex_ptc vertices8[] =
8902 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8903 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8904 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
8906 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8907 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
8908 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
8910 const UINT num_vertices8 = ARRAY_SIZE(vertices8);
8911 const UINT num_faces8 = ARRAY_SIZE(vertices8) / VERTS_PER_FACE;
8912 const UINT vertex_size8 = sizeof(*vertices8);
8913 const struct vertex_ptc_float4 exp_vertices8[] =
8915 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f, 0.0f, 1.0f}},
8916 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f, 0.0f, 1.0f}},
8917 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f, 0.0f, 1.0f}},
8919 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f, 0.0f, 1.0f}},
8920 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f, 0.0f, 1.0f}},
8921 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f, 0.0f, 1.0f}},
8923 const UINT exp_vertex_size8 = sizeof(*exp_vertices8);
8924 /* Test 9. Convert FLOAT2 to D3DCOLOR. */
8925 const struct vertex_ptc vertices9[] =
8927 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8928 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8929 {{ 0.0f, 0.0f, 0.f}, {-0.4f, -0.6f}},
8931 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8932 {{ 3.0f, 0.0f, 0.f}, { 2.0f, 256.0f}},
8933 {{ 1.0f, 0.0f, 0.f}, { 0.11f, 0.2f}},
8935 const UINT num_vertices9 = ARRAY_SIZE(vertices9);
8936 const UINT num_faces9 = ARRAY_SIZE(vertices9) / VERTS_PER_FACE;
8937 const UINT vertex_size9 = sizeof(*vertices9);
8938 const struct vertex_ptc_d3dcolor exp_vertices9[] =
8940 {{ 0.0f, 3.0f, 0.f}, {0, 255, 255, 255}},
8941 {{ 2.0f, 3.0f, 0.f}, {0, 179, 128, 255}},
8942 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 255}},
8944 {{ 3.0f, 3.0f, 0.f}, {0, 77, 51, 255}},
8945 {{ 3.0f, 0.0f, 0.f}, {0, 255, 255, 255}},
8946 {{ 1.0f, 0.0f, 0.f}, {0, 51, 28, 255}},
8948 const UINT exp_vertex_size9 = sizeof(*exp_vertices9);
8949 /* Test 10. Convert FLOAT2 to UBYTE4. */
8950 const struct vertex_ptc vertices10[] =
8952 {{ 0.0f, 3.0f, 0.f}, { 0.0f, 1.0f}},
8953 {{ 2.0f, 3.0f, 0.f}, { 2.0f, 3.0f}},
8954 {{ 0.0f, 0.0f, 0.f}, { 254.0f, 255.0f}},
8956 {{ 3.0f, 3.0f, 0.f}, { 256.0f, 257.0f}},
8957 {{ 3.0f, 0.0f, 0.f}, { 1.4f, 1.5f}},
8958 {{ 1.0f, 0.0f, 0.f}, {-4.0f, -5.0f}},
8960 const UINT num_vertices10 = ARRAY_SIZE(vertices10);
8961 const UINT num_faces10 = ARRAY_SIZE(vertices10) / VERTS_PER_FACE;
8962 const UINT vertex_size10 = sizeof(*vertices10);
8963 const struct vertex_ptc_ubyte4 exp_vertices10[] =
8965 {{ 0.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
8966 {{ 2.0f, 3.0f, 0.f}, {2, 3, 0, 1}},
8967 {{ 0.0f, 0.0f, 0.f}, {254, 255, 0, 1}},
8969 {{ 3.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
8970 {{ 3.0f, 0.0f, 0.f}, {1, 2, 0, 1}},
8971 {{ 1.0f, 0.0f, 0.f}, {0, 0, 0, 1}},
8973 const UINT exp_vertex_size10 = sizeof(*exp_vertices10);
8974 /* Test 11. Convert FLOAT2 to SHORT2. */
8975 const struct vertex_ptc vertices11[] =
8977 {{ 0.0f, 3.0f, 0.f}, { 1.0f, -1.0f}},
8978 {{ 2.0f, 3.0f, 0.f}, { 0.4f, 0.5f}},
8979 {{ 0.0f, 0.0f, 0.f}, {-0.5f, -5.0f}},
8981 {{ 3.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MIN}},
8982 {{ 3.0f, 0.0f, 0.f}, {SHRT_MAX + 1.0f, SHRT_MIN - 1.0f}},
8983 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX + 2.0f, SHRT_MIN - 2.0f}},
8985 {{ 4.0f, 3.0f, 0.f}, {2 * SHRT_MAX, 2 * SHRT_MIN}},
8986 {{ 6.0f, 0.0f, 0.f}, {3 * SHRT_MAX, 3 * SHRT_MIN}},
8987 {{ 4.0f, 0.0f, 0.f}, {4 * SHRT_MAX, 4 * SHRT_MIN}},
8989 const UINT num_vertices11 = ARRAY_SIZE(vertices11);
8990 const UINT num_faces11 = ARRAY_SIZE(vertices11) / VERTS_PER_FACE;
8991 const UINT vertex_size11 = sizeof(*vertices11);
8992 const struct vertex_ptc_short2 exp_vertices11[] =
8994 {{ 0.0f, 3.0f, 0.f}, {1, 0}},
8995 {{ 2.0f, 3.0f, 0.f}, {0, 1}},
8996 {{ 0.0f, 0.0f, 0.f}, {0, -4}},
8998 {{ 3.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MIN + 1}},
8999 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MIN}},
9000 {{ 1.0f, 0.0f, 0.f}, {SHRT_MIN + 1, SHRT_MAX}},
9002 {{ 4.0f, 3.0f, 0.f}, {-2, 1}},
9003 {{ 6.0f, 0.0f, 0.f}, {32765, -32767}},
9004 {{ 4.0f, 0.0f, 0.f}, {-4, 1}},
9006 const UINT exp_vertex_size11 = sizeof(*exp_vertices11);
9007 /* Test 12. Convert FLOAT2 to SHORT4. */
9008 const struct vertex_ptc vertices12[] =
9010 {{ 0.0f, 3.0f, 0.f}, { 1.0f, -1.0f}},
9011 {{ 2.0f, 3.0f, 0.f}, { 0.4f, 0.5f}},
9012 {{ 0.0f, 0.0f, 0.f}, {-0.5f, -5.0f}},
9014 {{ 3.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MIN}},
9015 {{ 3.0f, 0.0f, 0.f}, {SHRT_MAX + 1.0f, SHRT_MIN - 1.0f}},
9016 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX + 2.0f, SHRT_MIN - 2.0f}},
9018 {{ 4.0f, 3.0f, 0.f}, {2 * SHRT_MAX, 2 * SHRT_MIN}},
9019 {{ 6.0f, 0.0f, 0.f}, {3 * SHRT_MAX, 3 * SHRT_MIN}},
9020 {{ 4.0f, 0.0f, 0.f}, {4 * SHRT_MAX, 4 * SHRT_MIN}},
9022 const UINT num_vertices12 = ARRAY_SIZE(vertices12);
9023 const UINT num_faces12 = ARRAY_SIZE(vertices12) / VERTS_PER_FACE;
9024 const UINT vertex_size12 = sizeof(*vertices12);
9025 const struct vertex_ptc_short4 exp_vertices12[] =
9027 {{ 0.0f, 3.0f, 0.f}, {1, 0, 0, 1}},
9028 {{ 2.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
9029 {{ 0.0f, 0.0f, 0.f}, {0, -4, 0, 1}},
9031 {{ 3.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MIN + 1, 0, 1}},
9032 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MIN, 0, 1}},
9033 {{ 1.0f, 0.0f, 0.f}, {SHRT_MIN + 1, SHRT_MAX, 0, 1}},
9035 {{ 4.0f, 3.0f, 0.f}, {-2, 1, 0, 1}},
9036 {{ 6.0f, 0.0f, 0.f}, {32765, -32767, 0, 1}},
9037 {{ 4.0f, 0.0f, 0.f}, {-4, 1, 0, 1}},
9039 const UINT exp_vertex_size12 = sizeof(*exp_vertices12);
9040 /* Test 13. Convert FLOAT2 to UBYTE4N. */
9041 const struct vertex_ptc vertices13[] =
9043 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 2.0f}},
9044 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
9045 {{ 0.0f, 0.0f, 0.f}, {-0.4f, -0.5f}},
9047 {{ 3.0f, 3.0f, 0.f}, {-0.6f, -1.0f}},
9048 {{ 3.0f, 0.0f, 0.f}, {UCHAR_MAX, UCHAR_MAX + 1}},
9049 {{ 1.0f, 0.0f, 0.f}, {2 * UCHAR_MAX, -UCHAR_MAX}},
9051 const UINT num_vertices13 = ARRAY_SIZE(vertices13);
9052 const UINT num_faces13 = ARRAY_SIZE(vertices13) / VERTS_PER_FACE;
9053 const UINT vertex_size13 = sizeof(*vertices13);
9054 const struct vertex_ptc_ubyte4n exp_vertices13[] =
9056 {{ 0.0f, 3.0f, 0.f}, {255, 255, 0, 255}},
9057 {{ 2.0f, 3.0f, 0.f}, {128, 179, 0, 255}},
9058 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 255}},
9060 {{ 3.0f, 3.0f, 0.f}, {0, 0, 0, 255}},
9061 {{ 3.0f, 0.0f, 0.f}, {255, 255, 0, 255}},
9062 {{ 1.0f, 0.0f, 0.f}, {255, 0, 0, 255}},
9064 const UINT exp_vertex_size13 = sizeof(*exp_vertices13);
9065 /* Test 14. Convert FLOAT2 to SHORT2N. */
9066 const struct vertex_ptc vertices14[] =
9068 {{ 0.0f, 3.0f, 0.f}, {1.0f, 2.0f}},
9069 {{ 2.0f, 3.0f, 0.f}, {0.4f, 0.5f}},
9070 {{ 0.0f, 0.0f, 0.f}, {0.6f, -1.0f}},
9072 {{ 3.0f, 3.0f, 0.f}, {-0.4f, -0.5f}},
9073 {{ 3.0f, 0.0f, 0.f}, {-0.9f, -0.99997}},
9074 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX, SHRT_MIN}},
9076 const UINT num_vertices14 = ARRAY_SIZE(vertices14);
9077 const UINT num_faces14 = ARRAY_SIZE(vertices14) / VERTS_PER_FACE;
9078 const UINT vertex_size14 = sizeof(*vertices14);
9079 const struct vertex_ptc_short2 exp_vertices14[] =
9081 {{ 0.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MAX}},
9082 {{ 2.0f, 3.0f, 0.f}, {13107, 16384}},
9083 {{ 0.0f, 0.0f, 0.f}, {19660, SHRT_MIN + 2}},
9085 {{ 3.0f, 3.0f, 0.f}, {-13106, -16383}},
9086 {{ 3.0f, 0.0f, 0.f}, {-29489, SHRT_MIN + 3}},
9087 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX, SHRT_MIN + 2}},
9089 const UINT exp_vertex_size14 = sizeof(*exp_vertices14);
9090 /* Test 15. Convert FLOAT2 to SHORT4N. */
9091 const struct vertex_ptc vertices15[] =
9093 {{ 0.0f, 3.0f, 0.f}, {1.0f, 2.0f}},
9094 {{ 2.0f, 3.0f, 0.f}, {0.4f, 0.5f}},
9095 {{ 0.0f, 0.0f, 0.f}, {0.6f, -1.0f}},
9097 {{ 3.0f, 3.0f, 0.f}, {-0.4f, -0.5f}},
9098 {{ 3.0f, 0.0f, 0.f}, {-0.9f, -0.99997}},
9099 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX, SHRT_MIN}},
9101 const UINT num_vertices15 = ARRAY_SIZE(vertices15);
9102 const UINT num_faces15 = ARRAY_SIZE(vertices15) / VERTS_PER_FACE;
9103 const UINT vertex_size15 = sizeof(*vertices15);
9104 const struct vertex_ptc_short4 exp_vertices15[] =
9106 {{ 0.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MAX, 0, SHRT_MAX}},
9107 {{ 2.0f, 3.0f, 0.f}, {13107, 16384, 0, SHRT_MAX}},
9108 {{ 0.0f, 0.0f, 0.f}, {19660, SHRT_MIN + 2, 0, SHRT_MAX}},
9110 {{ 3.0f, 3.0f, 0.f}, {-13106, -16383, 0, SHRT_MAX}},
9111 {{ 3.0f, 0.0f, 0.f}, {-29489, SHRT_MIN + 3, 0, SHRT_MAX}},
9112 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX, SHRT_MIN + 2, 0, SHRT_MAX}},
9114 const UINT exp_vertex_size15 = sizeof(*exp_vertices15);
9115 /* Test 16. Convert FLOAT2 to USHORT2N. */
9116 const struct vertex_ptc vertices16[] =
9118 {{ 0.0f, 3.0f, 0.f}, {1.0f, 2.0f}},
9119 {{ 2.0f, 3.0f, 0.f}, {0.4f, 0.5f}},
9120 {{ 0.0f, 0.0f, 0.f}, {0.6f, -1.0f}},
9122 {{ 3.0f, 3.0f, 0.f}, {-0.4f, -0.5f}},
9123 {{ 3.0f, 0.0f, 0.f}, {-0.9f, 0.99998f}},
9124 {{ 1.0f, 0.0f, 0.f}, {USHRT_MAX, 0.0f}},
9126 const UINT num_vertices16 = ARRAY_SIZE(vertices16);
9127 const UINT num_faces16 = ARRAY_SIZE(vertices16) / VERTS_PER_FACE;
9128 const UINT vertex_size16 = sizeof(*vertices16);
9129 const struct vertex_ptc_ushort2n exp_vertices16[] =
9131 {{ 0.0f, 3.0f, 0.f}, {USHRT_MAX, USHRT_MAX}},
9132 {{ 2.0f, 3.0f, 0.f}, {26214, 32768}},
9133 {{ 0.0f, 0.0f, 0.f}, {39321, 0}},
9135 {{ 3.0f, 3.0f, 0.f}, {0, 0}},
9136 {{ 3.0f, 0.0f, 0.f}, {0, USHRT_MAX - 1}},
9137 {{ 1.0f, 0.0f, 0.f}, {USHRT_MAX, 0}},
9139 const UINT exp_vertex_size16 = sizeof(*exp_vertices16);
9140 /* Test 17. Convert FLOAT2 to USHORT4N. */
9141 const struct vertex_ptc vertices17[] =
9143 {{ 0.0f, 3.0f, 0.f}, {1.0f, 2.0f}},
9144 {{ 2.0f, 3.0f, 0.f}, {0.4f, 0.5f}},
9145 {{ 0.0f, 0.0f, 0.f}, {0.6f, -1.0f}},
9147 {{ 3.0f, 3.0f, 0.f}, {-0.4f, -0.5f}},
9148 {{ 3.0f, 0.0f, 0.f}, {-0.9f, 0.99998f}},
9149 {{ 1.0f, 0.0f, 0.f}, {USHRT_MAX, 0.0f}},
9151 const UINT num_vertices17 = ARRAY_SIZE(vertices17);
9152 const UINT num_faces17 = ARRAY_SIZE(vertices17) / VERTS_PER_FACE;
9153 const UINT vertex_size17 = sizeof(*vertices17);
9154 const struct vertex_ptc_ushort4n exp_vertices17[] =
9156 {{ 0.0f, 3.0f, 0.f}, {USHRT_MAX, USHRT_MAX, 0, USHRT_MAX}},
9157 {{ 2.0f, 3.0f, 0.f}, {26214, 32768, 0, USHRT_MAX}},
9158 {{ 0.0f, 0.0f, 0.f}, {39321, 0, 0, USHRT_MAX}},
9160 {{ 3.0f, 3.0f, 0.f}, {0, 0, 0, USHRT_MAX}},
9161 {{ 3.0f, 0.0f, 0.f}, {0, USHRT_MAX - 1, 0, USHRT_MAX}},
9162 {{ 1.0f, 0.0f, 0.f}, {USHRT_MAX, 0, 0, USHRT_MAX}},
9164 const UINT exp_vertex_size17 = sizeof(*exp_vertices17);
9165 /* Test 18. Test that the method field is compared by converting a FLOAT2 to
9166 * FLOAT16_2. where the method field has been change from
9167 * D3DDECLMETHOD_DEFAULT to D3DDECLMETHOD_PARTIALU. */
9168 const struct vertex_ptc vertices18[] =
9170 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
9171 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
9172 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
9174 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
9175 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
9176 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
9178 const UINT num_vertices18 = ARRAY_SIZE(vertices18);
9179 const UINT num_faces18 = ARRAY_SIZE(vertices18) / VERTS_PER_FACE;
9180 const UINT vertex_size18 = sizeof(*vertices18);
9181 const struct vertex_ptc_float16_2 exp_vertices18[] =
9183 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
9184 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */
9185 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */
9187 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd}}, /* {0.2f, 0.3f} */
9188 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
9189 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */
9191 const UINT exp_vertex_size18 = sizeof(*exp_vertices18);
9192 /* Test 19. Test that data is lost if usage index changes, e.g. TEXCOORD0
9193 * TEXCOORD1. */
9194 const struct vertex_pntc vertices19[] =
9196 {{ 0.0f, 3.0f, 0.f}, up, { 1.0f, 1.0f}},
9197 {{ 2.0f, 3.0f, 0.f}, up, { 0.5f, 0.7f}},
9198 {{ 0.0f, 0.0f, 0.f}, up, {-0.2f, -0.3f}},
9200 {{ 3.0f, 3.0f, 0.f}, up, { 0.2f, 0.3f}},
9201 {{ 3.0f, 0.0f, 0.f}, up, { 1.0f, 1.0f}},
9202 {{ 1.0f, 0.0f, 0.f}, up, { 0.1f, 0.2f}},
9204 const UINT num_vertices19 = ARRAY_SIZE(vertices19);
9205 const UINT num_faces19 = ARRAY_SIZE(vertices19) / VERTS_PER_FACE;
9206 const UINT vertex_size19 = sizeof(*vertices19);
9207 const struct vertex_pntc exp_vertices19[] =
9209 {{ 0.0f, 3.0f, 0.f}, up, zero_vec2},
9210 {{ 2.0f, 3.0f, 0.f}, up, zero_vec2},
9211 {{ 0.0f, 0.0f, 0.f}, up, zero_vec2},
9213 {{ 3.0f, 3.0f, 0.f}, up, zero_vec2},
9214 {{ 3.0f, 0.0f, 0.f}, up, zero_vec2},
9215 {{ 1.0f, 0.0f, 0.f}, up, zero_vec2},
9217 const UINT exp_vertex_size19 = sizeof(*exp_vertices19);
9218 /* Test 20. Another test that data is lost if usage index changes, e.g.
9219 * TEXCOORD1 to TEXCOORD0. */
9220 const struct vertex_pntc vertices20[] =
9222 {{ 0.0f, 3.0f, 0.f}, up, { 1.0f, 1.0f}},
9223 {{ 2.0f, 3.0f, 0.f}, up, { 0.5f, 0.7f}},
9224 {{ 0.0f, 0.0f, 0.f}, up, {-0.2f, -0.3f}},
9226 {{ 3.0f, 3.0f, 0.f}, up, { 0.2f, 0.3f}},
9227 {{ 3.0f, 0.0f, 0.f}, up, { 1.0f, 1.0f}},
9228 {{ 1.0f, 0.0f, 0.f}, up, { 0.1f, 0.2f}},
9230 const UINT num_vertices20 = ARRAY_SIZE(vertices20);
9231 const UINT num_faces20 = ARRAY_SIZE(vertices20) / VERTS_PER_FACE;
9232 const UINT vertex_size20 = sizeof(*vertices20);
9233 const struct vertex_pntc exp_vertices20[] =
9235 {{ 0.0f, 3.0f, 0.f}, up, zero_vec2},
9236 {{ 2.0f, 3.0f, 0.f}, up, zero_vec2},
9237 {{ 0.0f, 0.0f, 0.f}, up, zero_vec2},
9239 {{ 3.0f, 3.0f, 0.f}, up, zero_vec2},
9240 {{ 3.0f, 0.0f, 0.f}, up, zero_vec2},
9241 {{ 1.0f, 0.0f, 0.f}, up, zero_vec2},
9243 const UINT exp_vertex_size20 = sizeof(*exp_vertices20);
9244 /* Test 21. Convert FLOAT1 to FLOAT2. */
9245 const struct vertex_ptc_float1 vertices21[] =
9247 {{ 0.0f, 3.0f, 0.f}, 1.0f},
9248 {{ 2.0f, 3.0f, 0.f}, 0.5f},
9249 {{ 0.0f, 0.0f, 0.f}, -0.2f},
9251 {{ 3.0f, 3.0f, 0.f}, 0.2f},
9252 {{ 3.0f, 0.0f, 0.f}, 1.0f},
9253 {{ 1.0f, 0.0f, 0.f}, 0.1f},
9255 const UINT num_vertices21 = ARRAY_SIZE(vertices21);
9256 const UINT num_faces21 = ARRAY_SIZE(vertices21) / VERTS_PER_FACE;
9257 const UINT vertex_size21 = sizeof(*vertices21);
9258 const struct vertex_ptc exp_vertices21[] =
9260 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 0.0f}},
9261 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.0f}},
9262 {{ 0.0f, 0.0f, 0.f}, {-0.2f, 0.0f}},
9264 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.0f}},
9265 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 0.0f}},
9266 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.0f}},
9268 const UINT exp_vertex_size21 = sizeof(*exp_vertices21);
9269 /* Test 22. Convert FLOAT1 to FLOAT3. */
9270 const struct vertex_ptc_float1 vertices22[] =
9272 {{ 0.0f, 3.0f, 0.f}, 1.0f},
9273 {{ 2.0f, 3.0f, 0.f}, 0.5f},
9274 {{ 0.0f, 0.0f, 0.f}, -0.2f},
9276 {{ 3.0f, 3.0f, 0.f}, 0.2f},
9277 {{ 3.0f, 0.0f, 0.f}, 1.0f},
9278 {{ 1.0f, 0.0f, 0.f}, 0.1f},
9280 const UINT num_vertices22 = ARRAY_SIZE(vertices22);
9281 const UINT num_faces22 = ARRAY_SIZE(vertices22) / VERTS_PER_FACE;
9282 const UINT vertex_size22 = sizeof(*vertices22);
9283 const struct vertex_ptc_float3 exp_vertices22[] =
9285 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 0.0f, 0.0f}},
9286 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.0f, 0.0f}},
9287 {{ 0.0f, 0.0f, 0.f}, {-0.2f, 0.0f, 0.0f}},
9289 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.0f, 0.0f}},
9290 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 0.0f, 0.0f}},
9291 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.0f, 0.0f}},
9293 const UINT exp_vertex_size22 = sizeof(*exp_vertices22);
9294 /* Test 23. Convert FLOAT1 to FLOAT4. */
9295 const struct vertex_ptc_float1 vertices23[] =
9297 {{ 0.0f, 3.0f, 0.f}, 1.0f},
9298 {{ 2.0f, 3.0f, 0.f}, 0.5f},
9299 {{ 0.0f, 0.0f, 0.f}, -0.2f},
9301 {{ 3.0f, 3.0f, 0.f}, 0.2f},
9302 {{ 3.0f, 0.0f, 0.f}, 1.0f},
9303 {{ 1.0f, 0.0f, 0.f}, 0.1f},
9305 const UINT num_vertices23 = ARRAY_SIZE(vertices23);
9306 const UINT num_faces23 = ARRAY_SIZE(vertices23) / VERTS_PER_FACE;
9307 const UINT vertex_size23 = sizeof(*vertices23);
9308 const struct vertex_ptc_float4 exp_vertices23[] =
9310 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 0.0f, 0.0f, 1.0f}},
9311 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.0f, 0.0f, 1.0f}},
9312 {{ 0.0f, 0.0f, 0.f}, {-0.2f, 0.0f, 0.0f, 1.0f}},
9314 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.0f, 0.0f, 1.0f}},
9315 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 0.0f, 0.0f, 1.0f}},
9316 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.0f, 0.0f, 1.0f}},
9318 const UINT exp_vertex_size23 = sizeof(*exp_vertices23);
9319 /* Test 24. Convert FLOAT1 to D3DCOLOR. */
9320 const struct vertex_ptc_float1 vertices24[] =
9322 {{ 0.0f, 3.0f, 0.f}, 1.0f},
9323 {{ 2.0f, 3.0f, 0.f}, 0.5f},
9324 {{ 0.0f, 0.0f, 0.f}, -0.2f},
9326 {{ 3.0f, 3.0f, 0.f}, 0.2f},
9327 {{ 3.0f, 0.0f, 0.f}, 1.0f},
9328 {{ 1.0f, 0.0f, 0.f}, 0.11f},
9330 const UINT num_vertices24 = ARRAY_SIZE(vertices24);
9331 const UINT num_faces24 = ARRAY_SIZE(vertices24) / VERTS_PER_FACE;
9332 const UINT vertex_size24 = sizeof(*vertices24);
9333 const struct vertex_ptc_d3dcolor exp_vertices24[] =
9335 {{ 0.0f, 3.0f, 0.f}, {0, 0, 255, 255}},
9336 {{ 2.0f, 3.0f, 0.f}, {0, 0, 128, 255}},
9337 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 255}},
9339 {{ 3.0f, 3.0f, 0.f}, {0, 0, 51, 255}},
9340 {{ 3.0f, 0.0f, 0.f}, {0, 0, 255, 255}},
9341 {{ 1.0f, 0.0f, 0.f}, {0, 0, 28, 255}},
9343 const UINT exp_vertex_size24 = sizeof(*exp_vertices24);
9344 /* Test 25. Convert FLOAT1 to ubyte4. */
9345 const struct vertex_ptc_float1 vertices25[] =
9347 {{ 0.0f, 3.0f, 0.f}, 0.0f},
9348 {{ 2.0f, 3.0f, 0.f}, 1.4f},
9349 {{ 0.0f, 0.0f, 0.f}, 1.5f},
9351 {{ 3.0f, 3.0f, 0.f}, 255.0f},
9352 {{ 3.0f, 0.0f, 0.f}, 256.0f},
9353 {{ 1.0f, 0.0f, 0.f}, -1.0f},
9355 const UINT num_vertices25 = ARRAY_SIZE(vertices25);
9356 const UINT num_faces25 = ARRAY_SIZE(vertices25) / VERTS_PER_FACE;
9357 const UINT vertex_size25 = sizeof(*vertices25);
9358 const struct vertex_ptc_ubyte4 exp_vertices25[] =
9360 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 1}},
9361 {{ 2.0f, 3.0f, 0.f}, {1, 0, 0, 1}},
9362 {{ 0.0f, 0.0f, 0.f}, {2, 0, 0, 1}},
9364 {{ 3.0f, 3.0f, 0.f}, {255, 0, 0, 1}},
9365 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 1}},
9366 {{ 1.0f, 0.0f, 0.f}, {0, 0, 0, 1}},
9368 const UINT exp_vertex_size25 = sizeof(*exp_vertices25);
9369 /* Test 26. Convert FLOAT4 to D3DCOLOR. */
9370 const struct vertex_ptc_float4 vertices26[] =
9372 {{ 0.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.4f, 0.5f}},
9373 {{ 2.0f, 3.0f, 0.f}, {-0.4f, -0.5f, -1.0f, -2.0f}},
9374 {{ 0.0f, 0.0f, 0.f}, {254.0f, 255.0f, 256.0f, 257.0f}},
9376 {{ 3.0f, 3.0f, 0.f}, {0.1f, 0.2f, 0.3f, 0.4f}},
9377 {{ 3.0f, 0.0f, 0.f}, {0.5f, 0.6f, 0.7f, 0.8f}},
9378 {{ 1.0f, 0.0f, 0.f}, {0.9f, 0.99f, 0.995f, 0.999f}},
9380 const UINT num_vertices26 = ARRAY_SIZE(vertices26);
9381 const UINT num_faces26 = ARRAY_SIZE(vertices26) / VERTS_PER_FACE;
9382 const UINT vertex_size26 = sizeof(*vertices26);
9383 const struct vertex_ptc_d3dcolor exp_vertices26[] =
9385 {{ 0.0f, 3.0f, 0.f}, {102, 255, 0, 128}},
9386 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9387 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
9389 {{ 3.0f, 3.0f, 0.f}, {77, 51, 26, 102}},
9390 {{ 3.0f, 0.0f, 0.f}, {179, 153, 128, 204}},
9391 {{ 1.0f, 0.0f, 0.f}, {254, 252, 230, 255}},
9393 const UINT exp_vertex_size26 = sizeof(*exp_vertices26);
9394 /* Test 27. Convert D3DCOLOR to FLOAT4. */
9395 const struct vertex_ptc_d3dcolor vertices27[] =
9397 {{ 0.0f, 3.0f, 0.f}, {102, 255, 0, 128}},
9398 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9399 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
9401 {{ 3.0f, 3.0f, 0.f}, {77, 51, 26, 102}},
9402 {{ 3.0f, 0.0f, 0.f}, {179, 153, 128, 204}},
9403 {{ 1.0f, 0.0f, 0.f}, {254, 252, 230, 255}},
9405 const UINT num_vertices27 = ARRAY_SIZE(vertices27);
9406 const UINT num_faces27 = ARRAY_SIZE(vertices27) / VERTS_PER_FACE;
9407 const UINT vertex_size27 = sizeof(*vertices27);
9408 const struct vertex_ptc_float4 exp_vertices27[] =
9410 {{ 0.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.4f, 0.501961f}},
9411 {{ 2.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9412 {{ 0.0f, 0.0f, 0.f}, {1.0f, 1.0f, 1.0f, 1.0f}},
9414 {{ 3.0f, 3.0f, 0.f}, {0.101961f, 0.2f, 0.301961f, 0.4f}},
9415 {{ 3.0f, 0.0f, 0.f}, {0.501961f, 0.6f, 0.701961f, 0.8f}},
9416 {{ 1.0f, 0.0f, 0.f}, {0.901961f, 0.988235f, 0.996078f, 1.0f}},
9418 const UINT exp_vertex_size27 = sizeof(*exp_vertices27);
9419 /* Test 28. Convert UBYTE4 to FLOAT4. */
9420 const struct vertex_ptc_ubyte4 vertices28[] =
9422 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9423 {{ 2.0f, 3.0f, 0.f}, {1, 1, 1, 1}},
9424 {{ 0.0f, 0.0f, 0.f}, {1, 0, 1, 0}},
9426 {{ 3.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
9427 {{ 3.0f, 0.0f, 0.f}, {10, 20, 30, 40}},
9428 {{ 1.0f, 0.0f, 0.f}, {50, 60, 127, 255}},
9430 const UINT num_vertices28 = ARRAY_SIZE(vertices28);
9431 const UINT num_faces28 = ARRAY_SIZE(vertices28) / VERTS_PER_FACE;
9432 const UINT vertex_size28 = sizeof(*vertices28);
9433 const struct vertex_ptc_float4 exp_vertices28[] =
9435 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9436 {{ 2.0f, 3.0f, 0.f}, {1.0f, 1.0f, 1.0f, 1.0f}},
9437 {{ 0.0f, 0.0f, 0.f}, {1.0f, 0.0f, 1.0f, 0.0f}},
9439 {{ 3.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.0f, 1.0f}},
9440 {{ 3.0f, 0.0f, 0.f}, {10.0f, 20.0f, 30.0f, 40.0f}},
9441 {{ 1.0f, 0.0f, 0.f}, {50.0f, 60.0f, 127.0f, 255.0f}},
9443 const UINT exp_vertex_size28 = sizeof(*exp_vertices28);
9444 /* Test 29. Convert SHORT2 to FLOAT4. */
9445 const struct vertex_ptc_short2 vertices29[] =
9447 {{ 0.0f, 3.0f, 0.f}, {0, 0}},
9448 {{ 2.0f, 3.0f, 0.f}, {0, 1}},
9449 {{ 0.0f, 0.0f, 0.f}, {1, 0}},
9451 {{ 3.0f, 3.0f, 0.f}, {1, 1}},
9452 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MAX}},
9453 {{ 1.0f, 0.0f, 0.f}, {-42, 42}},
9455 const UINT num_vertices29 = ARRAY_SIZE(vertices29);
9456 const UINT num_faces29 = ARRAY_SIZE(vertices29) / VERTS_PER_FACE;
9457 const UINT vertex_size29 = sizeof(*vertices29);
9458 const struct vertex_ptc_float4 exp_vertices29[] =
9460 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 1.0f}},
9461 {{ 2.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.0f, 1.0f }},
9462 {{ 0.0f, 0.0f, 0.f}, {1.0f, 0.0f, 0.0f, 1.0f}},
9464 {{ 3.0f, 3.0f, 0.f}, {1.0f, 1.0f, 0.0f, 1.0f}},
9465 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MAX, 0.0f, 1.0f}},
9466 {{ 1.0f, 0.0f, 0.f}, {-42.0f, 42.0f, 0.0f, 1.0f}},
9468 const UINT exp_vertex_size29 = sizeof(*exp_vertices29);
9469 /* Test 29. Convert SHORT4 to FLOAT4. */
9470 const struct vertex_ptc_short4 vertices30[] =
9472 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9473 {{ 2.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
9474 {{ 0.0f, 0.0f, 0.f}, {1, 0, 1, 0}},
9476 {{ 3.0f, 3.0f, 0.f}, {1, 1, 1, 1}},
9477 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MAX, 1, 0}},
9478 {{ 1.0f, 0.0f, 0.f}, {-42, 42, SHRT_MAX, SHRT_MIN}},
9480 const UINT num_vertices30 = ARRAY_SIZE(vertices30);
9481 const UINT num_faces30 = ARRAY_SIZE(vertices30) / VERTS_PER_FACE;
9482 const UINT vertex_size30 = sizeof(*vertices30);
9483 const struct vertex_ptc_float4 exp_vertices30[] =
9485 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9486 {{ 2.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.0f, 1.0f }},
9487 {{ 0.0f, 0.0f, 0.f}, {1.0f, 0.0f, 1.0f, 0.0f}},
9489 {{ 3.0f, 3.0f, 0.f}, {1.0f, 1.0f, 1.0f, 1.0f}},
9490 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MAX, 1.0f, 0.0f}},
9491 {{ 1.0f, 0.0f, 0.f}, {-42.0f, 42.0f, SHRT_MAX, SHRT_MIN}},
9493 const UINT exp_vertex_size30 = sizeof(*exp_vertices30);
9494 /* Test 31. Convert UBYTE4N to FLOAT4. */
9495 const struct vertex_ptc_ubyte4n vertices31[] =
9497 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9498 {{ 2.0f, 3.0f, 0.f}, {1, 1, 1, 1}},
9499 {{ 0.0f, 0.0f, 0.f}, {1, 0, 1, 0}},
9501 {{ 3.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
9502 {{ 3.0f, 0.0f, 0.f}, {10, 20, 30, 40}},
9503 {{ 1.0f, 0.0f, 0.f}, {50, 60, 70, UCHAR_MAX}},
9505 const UINT num_vertices31 = ARRAY_SIZE(vertices31);
9506 const UINT num_faces31 = ARRAY_SIZE(vertices31) / VERTS_PER_FACE;
9507 const UINT vertex_size31 = sizeof(*vertices31);
9508 const struct vertex_ptc_float4 exp_vertices31[] =
9510 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9511 {{ 2.0f, 3.0f, 0.f}, {(FLOAT)1/UCHAR_MAX, (FLOAT)1/UCHAR_MAX, (FLOAT)1/UCHAR_MAX, (FLOAT)1/UCHAR_MAX}},
9512 {{ 0.0f, 0.0f, 0.f}, {(FLOAT)1/UCHAR_MAX, 0.0f, (FLOAT)1/UCHAR_MAX, 0.0f}},
9514 {{ 3.0f, 3.0f, 0.f}, {0.0f, (FLOAT)1/UCHAR_MAX, 0.0f, (FLOAT)1/UCHAR_MAX}},
9515 {{ 3.0f, 0.0f, 0.f}, {(FLOAT)10/UCHAR_MAX, (FLOAT)20/UCHAR_MAX, (FLOAT)30/UCHAR_MAX, (FLOAT)40/UCHAR_MAX}},
9516 {{ 1.0f, 0.0f, 0.f}, {(FLOAT)50/UCHAR_MAX, (FLOAT)60/UCHAR_MAX, (FLOAT)70/UCHAR_MAX, 1.0f}},
9518 const UINT exp_vertex_size31 = sizeof(*exp_vertices31);
9519 /* Test 32. Convert SHORT2N to FLOAT4. */
9520 const struct vertex_ptc_short2 vertices32[] =
9522 {{ 0.0f, 3.0f, 0.f}, {0, 0}},
9523 {{ 2.0f, 3.0f, 0.f}, {0, 1}},
9524 {{ 0.0f, 0.0f, 0.f}, {1, 0}},
9526 {{ 3.0f, 3.0f, 0.f}, {1, 1}},
9527 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN + 1, SHRT_MAX}},
9528 {{ 1.0f, 0.0f, 0.f}, {-42, 42}},
9530 const UINT num_vertices32 = ARRAY_SIZE(vertices32);
9531 const UINT num_faces32 = ARRAY_SIZE(vertices32) / VERTS_PER_FACE;
9532 const UINT vertex_size32 = sizeof(*vertices32);
9533 const struct vertex_ptc_float4 exp_vertices32[] =
9535 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 1.0f}},
9536 {{ 2.0f, 3.0f, 0.f}, {0.0f, 1.0f/SHRT_MAX, 0.0f, 1.0f}},
9537 {{ 0.0f, 0.0f, 0.f}, {1.0f/SHRT_MAX, 0.0f, 0.0f, 1.0f}},
9539 {{ 3.0f, 3.0f, 0.f}, {1.0f/SHRT_MAX, 1.0f/SHRT_MAX, 0.0f, 1.0f}},
9540 {{ 3.0f, 0.0f, 0.f}, {-1.0f, 1.0f, 0.0f, 1.0f}},
9541 {{ 1.0f, 0.0f, 0.f}, {-42.0f/SHRT_MAX, 42.0f/SHRT_MAX, 0.0f, 1.0f}},
9543 const UINT exp_vertex_size32 = sizeof(*exp_vertices32);
9544 /* Test 33. Convert SHORT4N to FLOAT4. */
9545 const struct vertex_ptc_short4 vertices33[] =
9547 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9548 {{ 2.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
9549 {{ 0.0f, 0.0f, 0.f}, {1, 0, 1, 0}},
9551 {{ 3.0f, 3.0f, 0.f}, {1, 1, 1, 1}},
9552 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN + 1, SHRT_MAX, SHRT_MIN + 1, SHRT_MAX}},
9553 {{ 1.0f, 0.0f, 0.f}, {-42, 42, 1, 1}},
9555 const UINT num_vertices33 = ARRAY_SIZE(vertices33);
9556 const UINT num_faces33 = ARRAY_SIZE(vertices33) / VERTS_PER_FACE;
9557 const UINT vertex_size33 = sizeof(*vertices33);
9558 const struct vertex_ptc_float4 exp_vertices33[] =
9560 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9561 {{ 2.0f, 3.0f, 0.f}, {0.0f, 1.0f/SHRT_MAX, 0.0f, 1.0f/SHRT_MAX}},
9562 {{ 0.0f, 0.0f, 0.f}, {1.0f/SHRT_MAX, 0.0f, 1.0f/SHRT_MAX, 0.0f}},
9564 {{ 3.0f, 3.0f, 0.f}, {1.0f/SHRT_MAX, 1.0f/SHRT_MAX, 1.0f/SHRT_MAX, 1.0f/SHRT_MAX}},
9565 {{ 3.0f, 0.0f, 0.f}, {-1.0f, 1.0f, -1.0f, 1.0f}},
9566 {{ 1.0f, 0.0f, 0.f}, {-42.0f/SHRT_MAX, 42.0f/SHRT_MAX, 1.0f/SHRT_MAX, 1.0f/SHRT_MAX}},
9568 const UINT exp_vertex_size33 = sizeof(*exp_vertices33);
9569 /* Test 34. Convert FLOAT16_2 to FLOAT4. */
9570 const struct vertex_ptc_float16_2 vertices34[] =
9572 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
9573 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */
9574 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */
9576 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd}}, /* {0.2f, 0.3f} */
9577 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
9578 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */
9580 const UINT num_vertices34 = ARRAY_SIZE(vertices34);
9581 const UINT num_faces34 = ARRAY_SIZE(vertices34) / VERTS_PER_FACE;
9582 const UINT vertex_size34 = sizeof(*vertices34);
9583 const struct vertex_ptc_float4 exp_vertices34[] =
9585 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f, 0.0f, 1.0f}},
9586 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.700195f, 0.0f, 1.0f}},
9587 {{ 0.0f, 0.0f, 0.f}, {-0.199951f, -0.300049f, 0.0f, 1.0f}},
9589 {{ 3.0f, 3.0f, 0.f}, {0.199951f, 0.300049f, 0.0f, 1.0f}},
9590 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f, 0.0f, 1.0f}},
9591 {{ 1.0f, 0.0f, 0.f}, {0.099976f, 0.199951f, 0.0f, 1.0f}},
9593 const UINT exp_vertex_size34 = sizeof(*exp_vertices34);
9594 /* Test 35. Convert FLOAT16_4 to FLOAT4. */
9595 const struct vertex_ptc_float16_4 vertices35[] =
9597 {{ 0.0f, 3.0f, 0.f}, {0x0000, 0x0000, 0x0000, 0x0000}},
9598 {{ 2.0f, 3.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}},
9599 {{ 0.0f, 0.0f, 0.f}, {0x3c00, 0x0000, 0x3c00, 0x0000}},
9601 {{ 3.0f, 3.0f, 0.f}, {0x0000, 0x3c00, 0x0000, 0x3c00}},
9602 {{ 3.0f, 0.0f, 0.f}, {0x3800, 0x399a, 0xb266, 0xb4cd}},
9603 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266, 0x2e66, 0x3266}},
9605 const UINT num_vertices35 = ARRAY_SIZE(vertices35);
9606 const UINT num_faces35 = ARRAY_SIZE(vertices35) / VERTS_PER_FACE;
9607 const UINT vertex_size35 = sizeof(*vertices35);
9608 const struct vertex_ptc_float4 exp_vertices35[] =
9610 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9611 {{ 2.0f, 3.0f, 0.f}, {1.0f, 1.0f, 1.0f, 1.0f}},
9612 {{ 0.0f, 0.0f, 0.f}, {1.0f, 0.0f, 1.0f, 0.0f}},
9614 {{ 3.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.0f, 1.0f}},
9615 {{ 3.0f, 0.0f, 0.f}, {0.5f, 0.700195f, -0.199951f, -0.300049f}},
9616 {{ 1.0f, 0.0f, 0.f}, {0.099976f, 0.199951f, 0.099976f, 0.199951f}},
9618 const UINT exp_vertex_size35 = sizeof(*exp_vertices35);
9619 /* Test 36. Check that vertex buffer sharing is ok. */
9620 const struct vertex_pn vertices36[] =
9622 {{ 0.0f, 3.0f, 0.f}, up},
9623 {{ 2.0f, 3.0f, 0.f}, up},
9624 {{ 0.0f, 0.0f, 0.f}, up},
9626 const UINT num_vertices36 = ARRAY_SIZE(vertices36);
9627 const UINT num_faces36 = ARRAY_SIZE(vertices36) / VERTS_PER_FACE;
9628 const UINT vertex_size36 = sizeof(*vertices36);
9629 const DWORD clone_options36 = options | D3DXMESH_VB_SHARE;
9630 /* Common mesh data */
9631 ID3DXMesh *mesh = NULL;
9632 ID3DXMesh *mesh_clone = NULL;
9633 struct
9635 const BYTE *vertices;
9636 const DWORD *indices;
9637 const DWORD *attributes;
9638 const UINT num_vertices;
9639 const UINT num_faces;
9640 const UINT vertex_size;
9641 const DWORD create_options;
9642 const DWORD clone_options;
9643 D3DVERTEXELEMENT9 *declaration;
9644 D3DVERTEXELEMENT9 *new_declaration;
9645 const BYTE *exp_vertices;
9646 const UINT exp_vertex_size;
9648 tc[] =
9651 (BYTE*)vertices0,
9652 NULL,
9653 NULL,
9654 num_vertices0,
9655 num_faces0,
9656 vertex_size0,
9657 options,
9658 options,
9659 declaration_pn,
9660 declaration_pn,
9661 (BYTE*)vertices0,
9662 vertex_size0
9665 (BYTE*)vertices0,
9666 NULL,
9667 NULL,
9668 num_vertices0,
9669 num_faces0,
9670 vertex_size0,
9671 options_16bit,
9672 options_16bit,
9673 declaration_pn,
9674 declaration_pn,
9675 (BYTE*)vertices0,
9676 vertex_size0
9679 (BYTE*)vertices0,
9680 NULL,
9681 NULL,
9682 num_vertices0,
9683 num_faces0,
9684 vertex_size0,
9685 options,
9686 options,
9687 declaration_pn,
9688 declaration_pntc,
9689 (BYTE*)exp_vertices2,
9690 exp_vertex_size2
9693 (BYTE*)vertices0,
9694 NULL,
9695 NULL,
9696 num_vertices0,
9697 num_faces0,
9698 vertex_size0,
9699 options,
9700 options,
9701 declaration_pn,
9702 declaration_ptcn,
9703 (BYTE*)exp_vertices3,
9704 exp_vertex_size3
9707 (BYTE*)vertices4,
9708 NULL,
9709 NULL,
9710 num_vertices4,
9711 num_faces4,
9712 vertex_size4,
9713 options,
9714 options,
9715 declaration_ptc,
9716 declaration_ptc_float16_2,
9717 (BYTE*)exp_vertices4,
9718 exp_vertex_size4
9721 (BYTE*)vertices5,
9722 NULL,
9723 NULL,
9724 num_vertices5,
9725 num_faces5,
9726 vertex_size5,
9727 options,
9728 options,
9729 declaration_ptc,
9730 declaration_ptc_float16_4,
9731 (BYTE*)exp_vertices5,
9732 exp_vertex_size5
9735 (BYTE*)vertices6,
9736 NULL,
9737 NULL,
9738 num_vertices6,
9739 num_faces6,
9740 vertex_size6,
9741 options,
9742 options,
9743 declaration_ptc,
9744 declaration_ptc_float1,
9745 (BYTE*)exp_vertices6,
9746 exp_vertex_size6
9749 (BYTE*)vertices7,
9750 NULL,
9751 NULL,
9752 num_vertices7,
9753 num_faces7,
9754 vertex_size7,
9755 options,
9756 options,
9757 declaration_ptc,
9758 declaration_ptc_float3,
9759 (BYTE*)exp_vertices7,
9760 exp_vertex_size7
9763 (BYTE*)vertices8,
9764 NULL,
9765 NULL,
9766 num_vertices8,
9767 num_faces8,
9768 vertex_size8,
9769 options,
9770 options,
9771 declaration_ptc,
9772 declaration_ptc_float4,
9773 (BYTE*)exp_vertices8,
9774 exp_vertex_size8
9777 (BYTE*)vertices9,
9778 NULL,
9779 NULL,
9780 num_vertices9,
9781 num_faces9,
9782 vertex_size9,
9783 options,
9784 options,
9785 declaration_ptc,
9786 declaration_ptc_d3dcolor,
9787 (BYTE*)exp_vertices9,
9788 exp_vertex_size9
9791 (BYTE*)vertices10,
9792 NULL,
9793 NULL,
9794 num_vertices10,
9795 num_faces10,
9796 vertex_size10,
9797 options,
9798 options,
9799 declaration_ptc,
9800 declaration_ptc_ubyte4,
9801 (BYTE*)exp_vertices10,
9802 exp_vertex_size10
9805 (BYTE*)vertices11,
9806 NULL,
9807 NULL,
9808 num_vertices11,
9809 num_faces11,
9810 vertex_size11,
9811 options,
9812 options,
9813 declaration_ptc,
9814 declaration_ptc_short2,
9815 (BYTE*)exp_vertices11,
9816 exp_vertex_size11
9819 (BYTE*)vertices12,
9820 NULL,
9821 NULL,
9822 num_vertices12,
9823 num_faces12,
9824 vertex_size12,
9825 options,
9826 options,
9827 declaration_ptc,
9828 declaration_ptc_short4,
9829 (BYTE*)exp_vertices12,
9830 exp_vertex_size12
9833 (BYTE*)vertices13,
9834 NULL,
9835 NULL,
9836 num_vertices13,
9837 num_faces13,
9838 vertex_size13,
9839 options,
9840 options,
9841 declaration_ptc,
9842 declaration_ptc_ubyte4n,
9843 (BYTE*)exp_vertices13,
9844 exp_vertex_size13
9847 (BYTE*)vertices14,
9848 NULL,
9849 NULL,
9850 num_vertices14,
9851 num_faces14,
9852 vertex_size14,
9853 options,
9854 options,
9855 declaration_ptc,
9856 declaration_ptc_short2n,
9857 (BYTE*)exp_vertices14,
9858 exp_vertex_size14
9861 (BYTE*)vertices15,
9862 NULL,
9863 NULL,
9864 num_vertices15,
9865 num_faces15,
9866 vertex_size15,
9867 options,
9868 options,
9869 declaration_ptc,
9870 declaration_ptc_short4n,
9871 (BYTE*)exp_vertices15,
9872 exp_vertex_size15
9875 (BYTE*)vertices16,
9876 NULL,
9877 NULL,
9878 num_vertices16,
9879 num_faces16,
9880 vertex_size16,
9881 options,
9882 options,
9883 declaration_ptc,
9884 declaration_ptc_ushort2n,
9885 (BYTE*)exp_vertices16,
9886 exp_vertex_size16
9889 (BYTE*)vertices17,
9890 NULL,
9891 NULL,
9892 num_vertices17,
9893 num_faces17,
9894 vertex_size17,
9895 options,
9896 options,
9897 declaration_ptc,
9898 declaration_ptc_ushort4n,
9899 (BYTE*)exp_vertices17,
9900 exp_vertex_size17
9903 (BYTE*)vertices18,
9904 NULL,
9905 NULL,
9906 num_vertices18,
9907 num_faces18,
9908 vertex_size18,
9909 options,
9910 options,
9911 declaration_ptc,
9912 declaration_ptc_float16_2_partialu,
9913 (BYTE*)exp_vertices18,
9914 exp_vertex_size18
9917 (BYTE*)vertices19,
9918 NULL,
9919 NULL,
9920 num_vertices19,
9921 num_faces19,
9922 vertex_size19,
9923 options,
9924 options,
9925 declaration_pntc,
9926 declaration_pntc1,
9927 (BYTE*)exp_vertices19,
9928 exp_vertex_size19
9931 (BYTE*)vertices20,
9932 NULL,
9933 NULL,
9934 num_vertices20,
9935 num_faces20,
9936 vertex_size20,
9937 options,
9938 options,
9939 declaration_pntc1,
9940 declaration_pntc,
9941 (BYTE*)exp_vertices20,
9942 exp_vertex_size20
9945 (BYTE*)vertices21,
9946 NULL,
9947 NULL,
9948 num_vertices21,
9949 num_faces21,
9950 vertex_size21,
9951 options,
9952 options,
9953 declaration_ptc_float1,
9954 declaration_ptc,
9955 (BYTE*)exp_vertices21,
9956 exp_vertex_size21
9959 (BYTE*)vertices22,
9960 NULL,
9961 NULL,
9962 num_vertices22,
9963 num_faces22,
9964 vertex_size22,
9965 options,
9966 options,
9967 declaration_ptc_float1,
9968 declaration_ptc_float3,
9969 (BYTE*)exp_vertices22,
9970 exp_vertex_size22
9973 (BYTE*)vertices23,
9974 NULL,
9975 NULL,
9976 num_vertices23,
9977 num_faces23,
9978 vertex_size23,
9979 options,
9980 options,
9981 declaration_ptc_float1,
9982 declaration_ptc_float4,
9983 (BYTE*)exp_vertices23,
9984 exp_vertex_size23
9987 (BYTE*)vertices24,
9988 NULL,
9989 NULL,
9990 num_vertices24,
9991 num_faces24,
9992 vertex_size24,
9993 options,
9994 options,
9995 declaration_ptc_float1,
9996 declaration_ptc_d3dcolor,
9997 (BYTE*)exp_vertices24,
9998 exp_vertex_size24
10001 (BYTE*)vertices25,
10002 NULL,
10003 NULL,
10004 num_vertices25,
10005 num_faces25,
10006 vertex_size25,
10007 options,
10008 options,
10009 declaration_ptc_float1,
10010 declaration_ptc_ubyte4,
10011 (BYTE*)exp_vertices25,
10012 exp_vertex_size25
10015 (BYTE*)vertices26,
10016 NULL,
10017 NULL,
10018 num_vertices26,
10019 num_faces26,
10020 vertex_size26,
10021 options,
10022 options,
10023 declaration_ptc_float4,
10024 declaration_ptc_d3dcolor,
10025 (BYTE*)exp_vertices26,
10026 exp_vertex_size26
10029 (BYTE*)vertices27,
10030 NULL,
10031 NULL,
10032 num_vertices27,
10033 num_faces27,
10034 vertex_size27,
10035 options,
10036 options,
10037 declaration_ptc_d3dcolor,
10038 declaration_ptc_float4,
10039 (BYTE*)exp_vertices27,
10040 exp_vertex_size27
10043 (BYTE*)vertices28,
10044 NULL,
10045 NULL,
10046 num_vertices28,
10047 num_faces28,
10048 vertex_size28,
10049 options,
10050 options,
10051 declaration_ptc_ubyte4,
10052 declaration_ptc_float4,
10053 (BYTE*)exp_vertices28,
10054 exp_vertex_size28
10057 (BYTE*)vertices29,
10058 NULL,
10059 NULL,
10060 num_vertices29,
10061 num_faces29,
10062 vertex_size29,
10063 options,
10064 options,
10065 declaration_ptc_short2,
10066 declaration_ptc_float4,
10067 (BYTE*)exp_vertices29,
10068 exp_vertex_size29
10071 (BYTE*)vertices30,
10072 NULL,
10073 NULL,
10074 num_vertices30,
10075 num_faces30,
10076 vertex_size30,
10077 options,
10078 options,
10079 declaration_ptc_short4,
10080 declaration_ptc_float4,
10081 (BYTE*)exp_vertices30,
10082 exp_vertex_size30
10085 (BYTE*)vertices31,
10086 NULL,
10087 NULL,
10088 num_vertices31,
10089 num_faces31,
10090 vertex_size31,
10091 options,
10092 options,
10093 declaration_ptc_ubyte4n,
10094 declaration_ptc_float4,
10095 (BYTE*)exp_vertices31,
10096 exp_vertex_size31
10099 (BYTE*)vertices32,
10100 NULL,
10101 NULL,
10102 num_vertices32,
10103 num_faces32,
10104 vertex_size32,
10105 options,
10106 options,
10107 declaration_ptc_short2n,
10108 declaration_ptc_float4,
10109 (BYTE*)exp_vertices32,
10110 exp_vertex_size32
10113 (BYTE*)vertices33,
10114 NULL,
10115 NULL,
10116 num_vertices33,
10117 num_faces33,
10118 vertex_size33,
10119 options,
10120 options,
10121 declaration_ptc_short4n,
10122 declaration_ptc_float4,
10123 (BYTE*)exp_vertices33,
10124 exp_vertex_size33
10127 (BYTE*)vertices34,
10128 NULL,
10129 NULL,
10130 num_vertices34,
10131 num_faces34,
10132 vertex_size34,
10133 options,
10134 options,
10135 declaration_ptc_float16_2,
10136 declaration_ptc_float4,
10137 (BYTE*)exp_vertices34,
10138 exp_vertex_size34
10141 (BYTE*)vertices35,
10142 NULL,
10143 NULL,
10144 num_vertices35,
10145 num_faces35,
10146 vertex_size35,
10147 options,
10148 options,
10149 declaration_ptc_float16_4,
10150 declaration_ptc_float4,
10151 (BYTE*)exp_vertices35,
10152 exp_vertex_size35
10155 (BYTE*)vertices36,
10156 NULL,
10157 NULL,
10158 num_vertices36,
10159 num_faces36,
10160 vertex_size36,
10161 options,
10162 clone_options36,
10163 declaration_pn,
10164 declaration_pn,
10165 (BYTE*)vertices36,
10166 vertex_size36
10170 test_context = new_test_context();
10171 if (!test_context)
10173 skip("Couldn't create test context\n");
10174 goto cleanup;
10177 for (i = 0; i < ARRAY_SIZE(tc); i++)
10179 UINT j;
10180 D3DVERTEXELEMENT9 new_declaration[MAX_FVF_DECL_SIZE];
10181 UINT exp_new_decl_length, new_decl_length;
10182 UINT exp_new_decl_size, new_decl_size;
10184 hr = init_test_mesh(tc[i].num_faces, tc[i].num_vertices,
10185 tc[i].create_options,
10186 tc[i].declaration,
10187 test_context->device, &mesh,
10188 tc[i].vertices, tc[i].vertex_size,
10189 tc[i].indices, tc[i].attributes);
10190 if (FAILED(hr))
10192 skip("Couldn't initialize test mesh %d. Got %x expected D3D_OK\n", i, hr);
10193 goto cleanup;
10196 hr = mesh->lpVtbl->CloneMesh(mesh, tc[i].clone_options, tc[i].new_declaration,
10197 test_context->device, &mesh_clone);
10198 ok(hr == D3D_OK, "CloneMesh test case %d failed. Got %x\n, expected D3D_OK\n", i, hr);
10200 hr = mesh_clone->lpVtbl->GetDeclaration(mesh_clone, new_declaration);
10201 ok(hr == D3D_OK, "GetDeclaration test case %d failed. Got %x\n, expected D3D_OK\n", i, hr);
10202 /* Check declaration elements */
10203 for (j = 0; tc[i].new_declaration[j].Stream != 0xFF; j++)
10205 ok(memcmp(&tc[i].new_declaration[j], &new_declaration[j], sizeof(*new_declaration)) == 0,
10206 "Test case %d failed. Declaration element %d did not match.\n", i, j);
10209 /* Check declaration length */
10210 exp_new_decl_length = D3DXGetDeclLength(tc[i].new_declaration);
10211 new_decl_length = D3DXGetDeclLength(new_declaration);
10212 ok(new_decl_length == exp_new_decl_length,
10213 "Test case %d failed. Got new declaration length %d, expected %d\n",
10214 i, new_decl_length, exp_new_decl_length);
10216 /* Check declaration size */
10217 exp_new_decl_size = D3DXGetDeclVertexSize(tc[i].new_declaration, 0);
10218 new_decl_size = D3DXGetDeclVertexSize(new_declaration, 0);
10219 ok(new_decl_size == exp_new_decl_size,
10220 "Test case %d failed. Got new declaration size %d, expected %d\n",
10221 i, new_decl_size, exp_new_decl_size);
10223 /* Check vertex data in cloned mesh */
10224 hr = mesh_clone->lpVtbl->LockVertexBuffer(mesh_clone, 0, (void**)&vertices);
10225 if (FAILED(hr))
10227 skip("Couldn't lock cloned vertex buffer.\n");
10228 goto cleanup;
10230 for (j = 0; j < tc[i].num_vertices; j++)
10232 UINT index = tc[i].exp_vertex_size * j;
10233 check_vertex_components(__LINE__, i, j, &vertices[index], &tc[i].exp_vertices[index], tc[i].new_declaration);
10235 hr = mesh_clone->lpVtbl->UnlockVertexBuffer(mesh_clone);
10236 if (FAILED(hr))
10238 skip("Couldn't unlock vertex buffer.\n");
10239 goto cleanup;
10241 vertices = NULL;
10242 mesh->lpVtbl->Release(mesh);
10243 mesh = NULL;
10244 mesh_clone->lpVtbl->Release(mesh_clone);
10245 mesh_clone = NULL;
10248 /* The following test shows that it is not possible to share a vertex buffer
10249 * with D3DXMESH_VB_SHARE and change the vertex declaration at the same
10250 * time. It reuses the test data from test 2.
10252 hr = init_test_mesh(tc[2].num_faces, tc[2].num_vertices,
10253 tc[2].create_options,
10254 tc[2].declaration,
10255 test_context->device, &mesh,
10256 tc[2].vertices, tc[2].vertex_size,
10257 tc[2].indices, tc[2].attributes);
10258 if (FAILED(hr))
10260 skip("Couldn't initialize test mesh for D3DXMESH_VB_SHARE case."
10261 " Got %x expected D3D_OK\n", hr);
10262 goto cleanup;
10265 hr = mesh->lpVtbl->CloneMesh(mesh, tc[2].create_options | D3DXMESH_VB_SHARE,
10266 tc[2].new_declaration, test_context->device,
10267 &mesh_clone);
10268 ok(hr == D3DERR_INVALIDCALL, "CloneMesh D3DXMESH_VB_SHARE with new"
10269 " declaration. Got %x, expected D3DERR_INVALIDCALL\n",
10270 hr);
10271 mesh->lpVtbl->Release(mesh);
10272 mesh = NULL;
10273 mesh_clone = NULL;
10275 cleanup:
10276 if (vertices) mesh->lpVtbl->UnlockVertexBuffer(mesh);
10277 if (mesh) mesh->lpVtbl->Release(mesh);
10278 if (mesh_clone) mesh_clone->lpVtbl->Release(mesh_clone);
10279 free_test_context(test_context);
10282 static void test_valid_mesh(void)
10284 HRESULT hr;
10285 struct test_context *test_context = NULL;
10286 UINT i;
10287 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
10288 const D3DVERTEXELEMENT9 declaration[] =
10290 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
10291 D3DDECL_END()
10293 const unsigned int VERTS_PER_FACE = 3;
10294 /* mesh0 (one face)
10296 * 0--1
10297 * | /
10298 * |/
10301 const D3DXVECTOR3 vertices0[] =
10303 { 0.0f, 3.0f, 0.f},
10304 { 2.0f, 3.0f, 0.f},
10305 { 0.0f, 0.0f, 0.f},
10307 const DWORD indices0[] = {0, 1, 2};
10308 const unsigned int num_vertices0 = ARRAY_SIZE(vertices0);
10309 const unsigned int num_faces0 = ARRAY_SIZE(indices0) / VERTS_PER_FACE;
10310 const DWORD adjacency0[] = {-1, -1, -1};
10311 const HRESULT exp_hr0 = D3D_OK;
10312 /* mesh1 (Simple bow-tie)
10314 * 0--1 1--3
10315 * | / \ |
10316 * |/ \|
10317 * 2 4
10319 const D3DXVECTOR3 vertices1[] =
10321 { 0.0f, 3.0f, 0.f},
10322 { 2.0f, 3.0f, 0.f},
10323 { 0.0f, 0.0f, 0.f},
10325 { 4.0f, 3.0f, 0.f},
10326 { 4.0f, 0.0f, 0.f},
10328 const DWORD indices1[] = {0, 1, 2, 1, 3, 4};
10329 const unsigned int num_vertices1 = ARRAY_SIZE(vertices1);
10330 const unsigned int num_faces1 = ARRAY_SIZE(indices1) / VERTS_PER_FACE;
10331 const DWORD adjacency1[] = {-1, -1, -1, -1, -1, -1};
10332 const HRESULT exp_hr1 = D3DXERR_INVALIDMESH;
10333 /* Common mesh data */
10334 ID3DXMesh *mesh = NULL;
10335 UINT vertex_size = sizeof(D3DXVECTOR3);
10336 ID3DXBuffer *errors_and_warnings = NULL;
10337 struct
10339 const D3DXVECTOR3 *vertices;
10340 const DWORD *indices;
10341 const UINT num_vertices;
10342 const UINT num_faces;
10343 const DWORD *adjacency;
10344 const HRESULT exp_hr;
10346 tc[] =
10349 vertices0,
10350 indices0,
10351 num_vertices0,
10352 num_faces0,
10353 adjacency0,
10354 exp_hr0,
10357 vertices1,
10358 indices1,
10359 num_vertices1,
10360 num_faces1,
10361 adjacency1,
10362 exp_hr1,
10366 test_context = new_test_context();
10367 if (!test_context)
10369 skip("Couldn't create test context\n");
10370 goto cleanup;
10373 for (i = 0; i < ARRAY_SIZE(tc); i++)
10375 hr = init_test_mesh(tc[i].num_faces, tc[i].num_vertices,
10376 options, declaration,
10377 test_context->device, &mesh,
10378 tc[i].vertices, vertex_size,
10379 tc[i].indices, NULL);
10380 if (FAILED(hr))
10382 skip("Couldn't initialize test mesh %d. Got %x expected D3D_OK\n", i, hr);
10383 goto cleanup;
10386 hr = D3DXValidMesh(mesh, tc[i].adjacency, &errors_and_warnings);
10387 todo_wine ok(hr == tc[i].exp_hr, "D3DXValidMesh test case %d failed. "
10388 "Got %x\n, expected %x\n", i, hr, tc[i].exp_hr);
10390 /* Note errors_and_warnings is deliberately not checked because that
10391 * would require copying wast amounts of the text output. */
10392 if (errors_and_warnings)
10394 ID3DXBuffer_Release(errors_and_warnings);
10395 errors_and_warnings = NULL;
10397 mesh->lpVtbl->Release(mesh);
10398 mesh = NULL;
10401 cleanup:
10402 if (mesh) mesh->lpVtbl->Release(mesh);
10403 free_test_context(test_context);
10406 static void test_optimize_faces(void)
10408 HRESULT hr;
10409 UINT i;
10410 DWORD smallest_face_remap;
10411 /* mesh0
10413 * 0--1
10414 * | /
10415 * |/
10418 const DWORD indices0[] = {0, 1, 2};
10419 const UINT num_faces0 = 1;
10420 const UINT num_vertices0 = 3;
10421 const DWORD exp_face_remap0[] = {0};
10422 /* mesh1
10424 * 0--1 3
10425 * | / /|
10426 * |/ / |
10427 * 2 5--4
10429 const DWORD indices1[] = {0, 1, 2, 3, 4, 5};
10430 const UINT num_faces1 = 2;
10431 const UINT num_vertices1 = 6;
10432 const DWORD exp_face_remap1[] = {1, 0};
10433 /* mesh2
10435 * 0--1
10436 * | /|
10437 * |/ |
10438 * 2--3
10440 const DWORD indices2[] = {0, 1, 2, 1, 3, 2};
10441 const UINT num_faces2 = 2;
10442 const UINT num_vertices2 = 4;
10443 const DWORD exp_face_remap2[] = {1, 0};
10444 /* mesh3
10446 * 0--1
10447 * | /|
10448 * |/ |
10449 * 2--3
10450 * | /|
10451 * |/ |
10452 * 4--5
10454 const DWORD indices3[] = {0, 1, 2, 1, 3, 2, 2, 3, 4, 3, 4, 5};
10455 const UINT num_faces3 = 4;
10456 const UINT num_vertices3 = 6;
10457 const DWORD exp_face_remap3[] = {3, 2, 1, 0};
10458 /* mesh4
10460 * 0--1
10461 * | /|
10462 * |/ |
10463 * 2--3
10464 * | /|
10465 * |/ |
10466 * 4--5
10468 const WORD indices4[] = {0, 1, 2, 1, 3, 2, 2, 3, 4, 3, 4, 5};
10469 const UINT num_faces4 = 4;
10470 const UINT num_vertices4 = 6;
10471 const DWORD exp_face_remap4[] = {3, 2, 1, 0};
10472 /* Test cases are stored in the tc array */
10473 struct
10475 const VOID *indices;
10476 const UINT num_faces;
10477 const UINT num_vertices;
10478 const BOOL indices_are_32bit;
10479 const DWORD *exp_face_remap;
10481 tc[] =
10484 indices0,
10485 num_faces0,
10486 num_vertices0,
10487 TRUE,
10488 exp_face_remap0
10491 indices1,
10492 num_faces1,
10493 num_vertices1,
10494 TRUE,
10495 exp_face_remap1
10498 indices2,
10499 num_faces2,
10500 num_vertices2,
10501 TRUE,
10502 exp_face_remap2
10505 indices3,
10506 num_faces3,
10507 num_vertices3,
10508 TRUE,
10509 exp_face_remap3
10512 indices4,
10513 num_faces4,
10514 num_vertices4,
10515 FALSE,
10516 exp_face_remap4
10520 /* Go through all test cases */
10521 for (i = 0; i < ARRAY_SIZE(tc); i++)
10523 DWORD j;
10524 DWORD *face_remap;
10525 face_remap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
10526 tc[i].num_faces*sizeof(*face_remap));
10528 hr = D3DXOptimizeFaces(tc[i].indices, tc[i].num_faces,
10529 tc[i].num_vertices, tc[i].indices_are_32bit,
10530 face_remap);
10531 ok(hr == D3D_OK, "D3DXOptimizeFaces test case %d failed. "
10532 "Got %x\n, expected D3D_OK\n", i, hr);
10534 /* Compare face remap with expected face remap */
10535 for (j = 0; j < tc[i].num_faces; j++)
10537 ok(tc[i].exp_face_remap[j] == face_remap[j],
10538 "Test case %d: Got face %d at %d, expected %d\n", i,
10539 face_remap[j], j, tc[i].exp_face_remap[j]);
10542 HeapFree(GetProcessHeap(), 0, face_remap);
10545 /* face_remap must not be NULL */
10546 hr = D3DXOptimizeFaces(tc[0].indices, tc[0].num_faces,
10547 tc[0].num_vertices, tc[0].indices_are_32bit,
10548 NULL);
10549 ok(hr == D3DERR_INVALIDCALL, "D3DXOptimizeFaces passed NULL face_remap "
10550 "pointer. Got %x\n, expected D3DERR_INVALIDCALL\n", hr);
10552 /* Number of faces must be smaller than 2^15 */
10553 hr = D3DXOptimizeFaces(tc[0].indices, 2 << 15,
10554 tc[0].num_vertices, FALSE,
10555 &smallest_face_remap);
10556 ok(hr == D3DERR_INVALIDCALL, "D3DXOptimizeFaces should not accept 2^15 "
10557 "faces when using 16-bit indices. Got %x\n, expected D3DERR_INVALIDCALL\n", hr);
10560 static HRESULT clear_normals(ID3DXMesh *mesh)
10562 HRESULT hr;
10563 BYTE *vertices;
10564 size_t normal_size;
10565 DWORD i, num_vertices, vertex_stride;
10566 const D3DXVECTOR4 normal = {NAN, NAN, NAN, NAN};
10567 D3DVERTEXELEMENT9 *normal_declaration = NULL;
10568 D3DVERTEXELEMENT9 declaration[MAX_FVF_DECL_SIZE] = {D3DDECL_END()};
10570 if (FAILED(hr = mesh->lpVtbl->GetDeclaration(mesh, declaration)))
10571 return hr;
10573 for (i = 0; declaration[i].Stream != 0xff; i++)
10575 if (declaration[i].Usage == D3DDECLUSAGE_NORMAL && !declaration[i].UsageIndex)
10577 normal_declaration = &declaration[i];
10578 break;
10582 if (!normal_declaration)
10583 return D3DERR_INVALIDCALL;
10585 if (normal_declaration->Type == D3DDECLTYPE_FLOAT3)
10587 normal_size = sizeof(D3DXVECTOR3);
10589 else if (normal_declaration->Type == D3DDECLTYPE_FLOAT4)
10591 normal_size = sizeof(D3DXVECTOR4);
10593 else
10595 trace("Cannot clear normals\n");
10596 return E_NOTIMPL;
10599 num_vertices = mesh->lpVtbl->GetNumVertices(mesh);
10600 vertex_stride = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
10602 if (FAILED(hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, (void **)&vertices)))
10603 return hr;
10605 vertices += normal_declaration->Offset;
10607 for (i = 0; i < num_vertices; i++, vertices += vertex_stride)
10608 memcpy(vertices, &normal, normal_size);
10610 return mesh->lpVtbl->UnlockVertexBuffer(mesh);
10613 static void compare_normals(unsigned int line, const char *test_name,
10614 ID3DXMesh *mesh, const D3DXVECTOR3 *normals, unsigned int num_normals)
10616 unsigned int i;
10617 BYTE *vertices;
10618 DWORD num_vertices, vertex_stride;
10619 D3DVERTEXELEMENT9 *normal_declaration = NULL;
10620 D3DVERTEXELEMENT9 declaration[MAX_FVF_DECL_SIZE] = {D3DDECL_END()};
10622 if (FAILED(mesh->lpVtbl->GetDeclaration(mesh, declaration)))
10624 ok_(__FILE__, line)(0, "%s: Failed to get declaration\n", test_name);
10625 return;
10628 for (i = 0; declaration[i].Stream != 0xff; i++)
10630 if (declaration[i].Usage == D3DDECLUSAGE_NORMAL && !declaration[i].UsageIndex)
10632 normal_declaration = &declaration[i];
10633 break;
10637 if (!normal_declaration)
10639 ok_(__FILE__, line)(0, "%s: Mesh has no normals\n", test_name);
10640 return;
10643 if (normal_declaration->Type != D3DDECLTYPE_FLOAT3 && normal_declaration->Type != D3DDECLTYPE_FLOAT4)
10645 ok_(__FILE__, line)(0, "%s: Mesh has invalid normals type\n", test_name);
10646 return;
10649 num_vertices = mesh->lpVtbl->GetNumVertices(mesh);
10650 vertex_stride = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
10652 ok_(__FILE__, line)(num_vertices == num_normals, "%s: Expected %u vertices, got %u\n", test_name,
10653 num_normals, num_vertices);
10655 if (FAILED(mesh->lpVtbl->LockVertexBuffer(mesh, 0, (void **)&vertices)))
10657 ok_(__FILE__, line)(0, "%s: Failed to compare normals\n", test_name);
10658 return;
10661 vertices += normal_declaration->Offset;
10663 for (i = 0; i < min(num_vertices, num_normals); i++, vertices += vertex_stride)
10665 if (normal_declaration->Type == D3DDECLTYPE_FLOAT3)
10667 const D3DXVECTOR3 *n = (D3DXVECTOR3 *)vertices;
10668 ok_(__FILE__, line)(compare_vec3(*n, normals[i]),
10669 "%s: normal %2u, expected (%f, %f, %f), got (%f, %f, %f)\n",
10670 test_name, i, normals[i].x, normals[i].y, normals[i].z, n->x, n->y, n->z);
10672 else
10674 const D3DXVECTOR4 *n = (D3DXVECTOR4 *)vertices;
10675 const D3DXVECTOR4 normal = {normals[i].x, normals[i].y, normals[i].z, 1.0f};
10676 ok_(__FILE__, line)(compare_vec4(*n, normal),
10677 "%s: normal %2u, expected (%f, %f, %f, %f), got (%f, %f, %f, %f)\n",
10678 test_name, i, normals[i].x, normals[i].y, normals[i].z, 1.0f,
10679 n->x, n->y, n->z, n->w);
10683 mesh->lpVtbl->UnlockVertexBuffer(mesh);
10686 static HRESULT compute_normals_D3DXComputeNormals(ID3DXMesh *mesh, const DWORD *adjacency)
10688 return D3DXComputeNormals((ID3DXBaseMesh *)mesh, adjacency);
10691 static HRESULT compute_normals_D3DXComputeTangentFrameEx(ID3DXMesh *mesh, const DWORD *adjacency)
10693 return D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
10694 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS,
10695 adjacency, -1.01f, -0.01f, -1.01f, NULL, NULL);
10698 static void test_compute_normals(void)
10700 HRESULT hr;
10701 ULONG refcount;
10702 ID3DXMesh *mesh, *cloned_mesh;
10703 ID3DXBuffer *adjacency;
10704 IDirect3DDevice9 *device;
10705 struct test_context *test_context;
10706 unsigned int i;
10708 static const struct compute_normals_func
10710 const char *name;
10711 HRESULT (*apply)(ID3DXMesh *mesh, const DWORD *adjacency);
10713 compute_normals_funcs[] =
10715 {"D3DXComputeNormals", compute_normals_D3DXComputeNormals },
10716 {"D3DXComputeTangentFrameEx", compute_normals_D3DXComputeTangentFrameEx}
10719 static const D3DXVECTOR3 box_normals[24] =
10721 {-1.0f, 0.0f, 0.0f}, {-1.0f, 0.0f, 0.0f}, {-1.0f, 0.0f, 0.0f}, {-1.0f, 0.0f, 0.0f},
10722 { 0.0f, 1.0f, 0.0f}, { 0.0f, 1.0f, 0.0f}, { 0.0f, 1.0f, 0.0f}, { 0.0f, 1.0f, 0.0f},
10723 { 1.0f, 0.0f, 0.0f}, { 1.0f, 0.0f, 0.0f}, { 1.0f, 0.0f, 0.0f}, { 1.0f, 0.0f, 0.0f},
10724 { 0.0f,-1.0f, 0.0f}, { 0.0f,-1.0f, 0.0f}, { 0.0f,-1.0f, 0.0f}, { 0.0f,-1.0f, 0.0f},
10725 { 0.0f, 0.0f, 1.0f}, { 0.0f, 0.0f, 1.0f}, { 0.0f, 0.0f, 1.0f}, { 0.0f, 0.0f, 1.0f},
10726 { 0.0f, 0.0f,-1.0f}, { 0.0f, 0.0f,-1.0f}, { 0.0f, 0.0f,-1.0f}, { 0.0f, 0.0f,-1.0f}
10728 const float box_normal_component = 1.0f / sqrtf(3.0f);
10729 const D3DXVECTOR3 box_normals_adjacency[24] =
10731 {-box_normal_component, -box_normal_component, -box_normal_component},
10732 {-box_normal_component, -box_normal_component, box_normal_component},
10733 {-box_normal_component, box_normal_component, box_normal_component},
10734 {-box_normal_component, box_normal_component, -box_normal_component},
10735 {-box_normal_component, box_normal_component, -box_normal_component},
10736 {-box_normal_component, box_normal_component, box_normal_component},
10737 { box_normal_component, box_normal_component, box_normal_component},
10738 { box_normal_component, box_normal_component, -box_normal_component},
10739 { box_normal_component, box_normal_component, -box_normal_component},
10740 { box_normal_component, box_normal_component, box_normal_component},
10741 { box_normal_component, -box_normal_component, box_normal_component},
10742 { box_normal_component, -box_normal_component, -box_normal_component},
10743 {-box_normal_component, -box_normal_component, box_normal_component},
10744 {-box_normal_component, -box_normal_component, -box_normal_component},
10745 { box_normal_component, -box_normal_component, -box_normal_component},
10746 { box_normal_component, -box_normal_component, box_normal_component},
10747 {-box_normal_component, -box_normal_component, box_normal_component},
10748 { box_normal_component, -box_normal_component, box_normal_component},
10749 { box_normal_component, box_normal_component, box_normal_component},
10750 {-box_normal_component, box_normal_component, box_normal_component},
10751 {-box_normal_component, -box_normal_component, -box_normal_component},
10752 {-box_normal_component, box_normal_component, -box_normal_component},
10753 { box_normal_component, box_normal_component, -box_normal_component},
10754 { box_normal_component, -box_normal_component, -box_normal_component}
10756 static const D3DXVECTOR3 box_normals_adjacency_area[24] =
10758 {-0.666667f, -0.333333f, -0.666667f}, {-0.333333f, -0.666667f, 0.666667f},
10759 {-0.816496f, 0.408248f, 0.408248f}, {-0.408248f, 0.816496f, -0.408248f},
10760 {-0.408248f, 0.816496f, -0.408248f}, {-0.816496f, 0.408248f, 0.408248f},
10761 { 0.333333f, 0.666667f, 0.666667f}, { 0.666667f, 0.333333f, -0.666667f},
10762 { 0.666667f, 0.333333f, -0.666667f}, { 0.333333f, 0.666667f, 0.666667f},
10763 { 0.816496f, -0.408248f, 0.408248f}, { 0.408248f, -0.816496f, -0.408248f},
10764 {-0.333333f, -0.666667f, 0.666667f}, {-0.666667f, -0.333333f, -0.666667f},
10765 { 0.408248f, -0.816496f, -0.408248f}, { 0.816496f, -0.408248f, 0.408248f},
10766 {-0.333333f, -0.666667f, 0.666667f}, { 0.816497f, -0.408248f, 0.408248f},
10767 { 0.333333f, 0.666667f, 0.666667f}, {-0.816497f, 0.408248f, 0.408248f},
10768 {-0.666667f, -0.333333f, -0.666667f}, {-0.408248f, 0.816497f, -0.408248f},
10769 { 0.666667f, 0.333333f, -0.666667f}, { 0.408248f, -0.816496f, -0.408248f}
10771 static const D3DXVECTOR3 box_normals_position1f[24] = {{0}};
10772 static const D3DXVECTOR3 box_normals_position2f[24] =
10774 {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f},
10775 {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, 1.0f},
10776 {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, -1.0f},
10777 {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f},
10778 {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, -1.0f},
10779 {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f},
10780 {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f},
10781 {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, -1.0f}
10784 static const D3DXVECTOR3 sphere_normals[22] =
10786 { 0.000000f, -0.000000f, 1.000000f}, { 0.000000f, 0.582244f, 0.813014f},
10787 { 0.582244f, -0.000000f, 0.813014f}, {-0.000000f, -0.582244f, 0.813014f},
10788 {-0.582244f, 0.000000f, 0.813014f}, {-0.000000f, 0.890608f, 0.454772f},
10789 { 0.890608f, 0.000000f, 0.454772f}, { 0.000000f, -0.890608f, 0.454772f},
10790 {-0.890608f, -0.000000f, 0.454772f}, { 0.000000f, 1.000000f, -0.000000f},
10791 { 1.000000f, -0.000000f, -0.000000f}, {-0.000000f, -1.000000f, -0.000000f},
10792 {-1.000000f, 0.000000f, -0.000000f}, { 0.000000f, 0.890608f, -0.454773f},
10793 { 0.890608f, -0.000000f, -0.454772f}, {-0.000000f, -0.890608f, -0.454773f},
10794 {-0.890608f, 0.000000f, -0.454773f}, { 0.000000f, 0.582244f, -0.813015f},
10795 { 0.582244f, -0.000000f, -0.813015f}, { 0.000000f, -0.582244f, -0.813015f},
10796 {-0.582243f, 0.000000f, -0.813015f}, { 0.000000f, 0.000000f, -1.000000f}
10798 static const D3DXVECTOR3 sphere_normals_area[22] =
10800 { 0.000000f, -0.000000f, 1.000000f}, {-0.215311f, 0.554931f, 0.803550f},
10801 { 0.554931f, 0.215311f, 0.803550f}, { 0.215311f, -0.554931f, 0.803550f},
10802 {-0.554931f, -0.215311f, 0.803550f}, {-0.126638f, 0.872121f, 0.472618f},
10803 { 0.872121f, 0.126638f, 0.472618f}, { 0.126638f, -0.872121f, 0.472618f},
10804 {-0.872121f, -0.126637f, 0.472618f}, { 0.000000f, 1.000000f, -0.000000f},
10805 { 1.000000f, -0.000000f, -0.000000f}, {-0.000000f, -1.000000f, -0.000000f},
10806 {-1.000000f, 0.000000f, -0.000000f}, { 0.126638f, 0.872121f, -0.472618f},
10807 { 0.872121f, -0.126638f, -0.472618f}, {-0.126638f, -0.872121f, -0.472618f},
10808 {-0.872121f, 0.126638f, -0.472618f}, { 0.215311f, 0.554931f, -0.803550f},
10809 { 0.554931f, -0.215311f, -0.803550f}, {-0.215311f, -0.554931f, -0.803550f},
10810 {-0.554931f, 0.215311f, -0.803550f}, { 0.000000f, 0.000000f, -1.000000f}
10812 static const D3DXVECTOR3 sphere_normals_equal[22] =
10814 { 0.000000f, -0.000000f, 1.000000f}, {-0.134974f, 0.522078f, 0.842150f},
10815 { 0.522078f, 0.134974f, 0.842150f}, { 0.134974f, -0.522078f, 0.842150f},
10816 {-0.522078f, -0.134974f, 0.842150f}, {-0.026367f, 0.857121f, 0.514440f},
10817 { 0.857121f, 0.026367f, 0.514440f}, { 0.026367f, -0.857121f, 0.514440f},
10818 {-0.857121f, -0.026367f, 0.514440f}, { 0.000000f, 1.000000f, -0.000000f},
10819 { 1.000000f, -0.000000f, -0.000000f}, {-0.000000f, -1.000000f, -0.000000f},
10820 {-1.000000f, 0.000000f, -0.000000f}, { 0.026367f, 0.857121f, -0.514440f},
10821 { 0.857121f, -0.026367f, -0.514440f}, {-0.026367f, -0.857121f, -0.514440f},
10822 {-0.857121f, 0.026367f, -0.514440f}, { 0.134975f, 0.522078f, -0.842150f},
10823 { 0.522078f, -0.134975f, -0.842150f}, {-0.134974f, -0.522078f, -0.842150f},
10824 {-0.522078f, 0.134974f, -0.842150f}, { 0.000000f, 0.000000f, -1.000000f}
10827 static const D3DVERTEXELEMENT9 position3f_normal1f_declaration[] =
10829 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
10830 {0, sizeof(D3DXVECTOR3), D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
10831 D3DDECL_END()
10833 static const D3DVERTEXELEMENT9 position3f_normal2f_declaration[] =
10835 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
10836 {0, sizeof(D3DXVECTOR3), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
10837 D3DDECL_END()
10839 static const D3DVERTEXELEMENT9 normal4f_position3f_declaration[] =
10841 {0, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
10842 {0, sizeof(D3DXVECTOR4), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
10843 D3DDECL_END()
10845 static const D3DVERTEXELEMENT9 position1f_normal3f_declaration[] =
10847 {0, 0, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
10848 {0, sizeof(float), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
10849 D3DDECL_END()
10851 static const D3DVERTEXELEMENT9 position2f_normal3f_declaration[] =
10853 {0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
10854 {0, sizeof(D3DXVECTOR2), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
10855 D3DDECL_END()
10857 static const D3DVERTEXELEMENT9 position4f_normal3f_declaration[] =
10859 {0, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
10860 {0, sizeof(D3DXVECTOR4), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
10861 D3DDECL_END()
10864 for (i = 0; i < ARRAY_SIZE(compute_normals_funcs); i++)
10866 hr = compute_normals_funcs[i].apply(NULL, NULL);
10867 ok(hr == D3DERR_INVALIDCALL, "%s returned %#x, expected D3DERR_INVALIDCALL\n", compute_normals_funcs[i].name, hr);
10870 if (!(test_context = new_test_context()))
10872 skip("Couldn't create test context\n");
10873 return;
10875 device = test_context->device;
10877 hr = D3DXCreateBox(device, 1.0f, 1.0f, 1.0f, &mesh, &adjacency);
10878 ok(SUCCEEDED(hr), "D3DXCreateBox failed %#x\n", hr);
10880 /* Check wrong input */
10881 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
10882 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE, NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
10883 todo_wine ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr);
10885 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DDECLUSAGE_NORMAL, 0,
10886 D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_BY_AREA | D3DXTANGENT_WEIGHT_EQUAL,
10887 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
10888 ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr);
10890 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
10891 D3DDECLUSAGE_NORMAL, 0, 0, NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
10892 todo_wine ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr);
10894 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
10895 D3DDECLUSAGE_NORMAL, 1, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS,
10896 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
10897 ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr);
10899 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
10900 D3DX_DEFAULT, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS,
10901 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
10902 ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr);
10904 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
10905 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_CALCULATE_NORMALS,
10906 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
10907 todo_wine ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr);
10909 for (i = 0; i < ARRAY_SIZE(compute_normals_funcs); i++)
10911 const struct compute_normals_func *func = &compute_normals_funcs[i];
10913 /* Mesh without normals */
10914 hr = mesh->lpVtbl->CloneMeshFVF(mesh, 0, D3DFVF_XYZ, device, &cloned_mesh);
10915 ok(SUCCEEDED(hr), "CloneMeshFVF failed %#x\n", hr);
10917 hr = func->apply(cloned_mesh, NULL);
10918 ok(hr == D3DERR_INVALIDCALL, "%s returned %#x, expected D3DERR_INVALIDCALL\n", func->name, hr);
10920 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh);
10921 ok(!refcount, "Mesh has %u references left\n", refcount);
10923 /* Mesh without positions */
10924 hr = mesh->lpVtbl->CloneMeshFVF(mesh, 0, D3DFVF_NORMAL, device, &cloned_mesh);
10925 ok(SUCCEEDED(hr), "CloneMeshFVF failed %#x\n", hr);
10927 hr = func->apply(cloned_mesh, NULL);
10928 ok(hr == D3DERR_INVALIDCALL, "%s returned %#x, expected D3DERR_INVALIDCALL\n", func->name, hr);
10930 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh);
10931 ok(!refcount, "Mesh has %u references left\n", refcount);
10933 /* Mesh with D3DDECLTYPE_FLOAT1 normals */
10934 hr = mesh->lpVtbl->CloneMesh(mesh, 0, position3f_normal1f_declaration, device, &cloned_mesh);
10935 ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr);
10937 hr = func->apply(cloned_mesh, NULL);
10938 ok(hr == D3DERR_INVALIDCALL, "%s returned %#x, expected D3DERR_INVALIDCALL\n", func->name, hr);
10940 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh);
10941 ok(!refcount, "Mesh has %u references left\n", refcount);
10943 /* Mesh with D3DDECLTYPE_FLOAT2 normals */
10944 hr = mesh->lpVtbl->CloneMesh(mesh, 0, position3f_normal2f_declaration, device, &cloned_mesh);
10945 ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr);
10947 hr = func->apply(cloned_mesh, NULL);
10948 ok(hr == D3DERR_INVALIDCALL, "%s returned %#x, expected D3DERR_INVALIDCALL\n", func->name, hr);
10950 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh);
10951 ok(!refcount, "Mesh has %u references left\n", refcount);
10953 /* Mesh without adjacency data */
10954 hr = clear_normals(mesh);
10955 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr);
10957 hr = func->apply(mesh, NULL);
10958 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr);
10960 compare_normals(__LINE__, func->name, mesh, box_normals, ARRAY_SIZE(box_normals));
10962 /* Mesh with adjacency data */
10963 hr = clear_normals(mesh);
10964 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr);
10966 hr = func->apply(mesh, ID3DXBuffer_GetBufferPointer(adjacency));
10967 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr);
10969 compare_normals(__LINE__, func->name, mesh, box_normals_adjacency, ARRAY_SIZE(box_normals_adjacency));
10971 /* Mesh with custom vertex format, D3DDECLTYPE_FLOAT4 normals and adjacency */
10972 hr = mesh->lpVtbl->CloneMesh(mesh, 0, normal4f_position3f_declaration, device, &cloned_mesh);
10973 ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr);
10975 hr = clear_normals(cloned_mesh);
10976 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr);
10978 hr = func->apply(cloned_mesh, ID3DXBuffer_GetBufferPointer(adjacency));
10979 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr);
10981 compare_normals(__LINE__, func->name, cloned_mesh, box_normals_adjacency, ARRAY_SIZE(box_normals_adjacency));
10983 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh);
10984 ok(!refcount, "Mesh has %u references left\n", refcount);
10986 /* Mesh with D3DDECLTYPE_FLOAT1 positions and D3DDECLTYPE_FLOAT3 normals */
10987 hr = mesh->lpVtbl->CloneMesh(mesh, 0, position1f_normal3f_declaration, device, &cloned_mesh);
10988 ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr);
10990 hr = clear_normals(cloned_mesh);
10991 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr);
10993 hr = func->apply(cloned_mesh, ID3DXBuffer_GetBufferPointer(adjacency));
10994 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr);
10996 compare_normals(__LINE__, func->name, cloned_mesh, box_normals_position1f, ARRAY_SIZE(box_normals_position1f));
10998 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh);
10999 ok(!refcount, "Mesh has %u references left\n", refcount);
11001 /* Mesh with D3DDECLTYPE_FLOAT2 positions and D3DDECLTYPE_FLOAT3 normals */
11002 hr = mesh->lpVtbl->CloneMesh(mesh, 0, position2f_normal3f_declaration, device, &cloned_mesh);
11003 ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr);
11005 hr = clear_normals(cloned_mesh);
11006 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr);
11008 hr = func->apply(cloned_mesh, ID3DXBuffer_GetBufferPointer(adjacency));
11009 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr);
11011 compare_normals(__LINE__, func->name, cloned_mesh, box_normals_position2f, ARRAY_SIZE(box_normals_position2f));
11013 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh);
11014 ok(!refcount, "Mesh has %u references left\n", refcount);
11016 /* Mesh with D3DDECLTYPE_FLOAT4 positions and D3DDECLTYPE_FLOAT3 normals */
11017 hr = mesh->lpVtbl->CloneMesh(mesh, 0, position4f_normal3f_declaration, device, &cloned_mesh);
11018 ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr);
11020 hr = clear_normals(cloned_mesh);
11021 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr);
11023 hr = func->apply(cloned_mesh, ID3DXBuffer_GetBufferPointer(adjacency));
11024 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr);
11026 compare_normals(__LINE__, func->name, cloned_mesh, box_normals_adjacency, ARRAY_SIZE(box_normals_adjacency));
11028 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh);
11029 ok(!refcount, "Mesh has %u references left\n", refcount);
11032 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
11033 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_BY_AREA,
11034 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
11035 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr);
11037 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, box_normals, ARRAY_SIZE(box_normals));
11039 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
11040 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_BY_AREA,
11041 ID3DXBuffer_GetBufferPointer(adjacency), -1.01f, -0.01f, -1.01f, NULL, NULL);
11042 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr);
11044 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, box_normals_adjacency_area, ARRAY_SIZE(box_normals_adjacency_area));
11046 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
11047 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_EQUAL,
11048 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
11049 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr);
11051 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, box_normals, ARRAY_SIZE(box_normals));
11053 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
11054 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_EQUAL,
11055 ID3DXBuffer_GetBufferPointer(adjacency), -1.01f, -0.01f, -1.01f, NULL, NULL);
11056 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr);
11058 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, box_normals_adjacency_area, ARRAY_SIZE(box_normals_adjacency_area));
11060 refcount = mesh->lpVtbl->Release(mesh);
11061 ok(!refcount, "Mesh has %u references left\n", refcount);
11062 refcount = ID3DXBuffer_Release(adjacency);
11063 ok(!refcount, "Buffer has %u references left\n", refcount);
11065 hr = D3DXCreateSphere(device, 1.0f, 4, 6, &mesh, &adjacency);
11066 ok(SUCCEEDED(hr), "D3DXCreateSphere failed %#x\n", hr);
11068 for (i = 0; i < ARRAY_SIZE(compute_normals_funcs); i++)
11070 const struct compute_normals_func *func = &compute_normals_funcs[i];
11072 /* Sphere without adjacency data */
11073 hr = clear_normals(mesh);
11074 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr);
11076 hr = func->apply(mesh, NULL);
11077 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr);
11079 compare_normals(__LINE__, func->name, mesh, sphere_normals, ARRAY_SIZE(sphere_normals));
11081 /* Sphere with adjacency data */
11082 hr = clear_normals(mesh);
11083 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr);
11085 hr = func->apply(mesh, ID3DXBuffer_GetBufferPointer(adjacency));
11086 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr);
11088 compare_normals(__LINE__, func->name, mesh, sphere_normals, ARRAY_SIZE(sphere_normals));
11091 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
11092 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_BY_AREA,
11093 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
11094 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr);
11096 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, sphere_normals_area, ARRAY_SIZE(sphere_normals_area));
11098 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
11099 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_BY_AREA,
11100 ID3DXBuffer_GetBufferPointer(adjacency), -1.01f, -0.01f, -1.01f, NULL, NULL);
11101 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr);
11103 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, sphere_normals_area, ARRAY_SIZE(sphere_normals_area));
11105 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
11106 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_EQUAL,
11107 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
11108 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr);
11110 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, sphere_normals_equal, ARRAY_SIZE(sphere_normals_equal));
11112 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
11113 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_EQUAL,
11114 ID3DXBuffer_GetBufferPointer(adjacency), -1.01f, -0.01f, -1.01f, NULL, NULL);
11115 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr);
11117 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, sphere_normals_equal, ARRAY_SIZE(sphere_normals_equal));
11119 refcount = mesh->lpVtbl->Release(mesh);
11120 ok(!refcount, "Mesh has %u references left\n", refcount);
11121 refcount = ID3DXBuffer_Release(adjacency);
11122 ok(!refcount, "Buffer has %u references left\n", refcount);
11124 free_test_context(test_context);
11127 static void D3DXCreateAnimationControllerTest(void)
11129 HRESULT hr;
11130 ID3DXAnimationController *animation;
11131 UINT value;
11133 hr = D3DXCreateAnimationController(0, 0, 0, 0, NULL);
11134 ok(hr == D3D_OK, "Got unexpected hr returned %#x.\n", hr);
11136 animation = (void*)0xdeadbeef;
11137 hr = D3DXCreateAnimationController(0, 1, 1, 1, &animation);
11138 ok(hr == D3D_OK, "Got unexpected hr returned %#x.\n", hr);
11139 ok(animation == (void*)0xdeadbeef, "Got unexpected animation %p.\n", animation);
11141 animation = (void*)0xdeadbeef;
11142 hr = D3DXCreateAnimationController(1, 0, 1, 1, &animation);
11143 ok(hr == D3D_OK, "Got unexpected hr returned %#x.\n", hr);
11144 ok(animation == (void*)0xdeadbeef, "Got unexpected animation %p.\n", animation);
11146 animation = (void*)0xdeadbeef;
11147 hr = D3DXCreateAnimationController(1, 1, 0, 1, &animation);
11148 ok(hr == D3D_OK, "Got unexpected hr returned %#x.\n", hr);
11149 ok(animation == (void*)0xdeadbeef, "Got unexpected animation %p.\n", animation);
11151 animation = (void*)0xdeadbeef;
11152 hr = D3DXCreateAnimationController(1, 1, 1, 0, &animation);
11153 ok(hr == D3D_OK, "Got unexpected hr returned %#x.\n", hr);
11154 ok(animation == (void*)0xdeadbeef, "Got unexpected animation %p.\n", animation);
11156 hr = D3DXCreateAnimationController(1, 1, 1, 1, &animation);
11157 ok(hr == D3D_OK, "Got unexpected hr returned %#x.\n", hr);
11159 value = animation->lpVtbl->GetMaxNumAnimationOutputs(animation);
11160 ok(value == 1, "Got unexpected value %u.\n", value);
11162 value = animation->lpVtbl->GetMaxNumAnimationSets(animation);
11163 ok(value == 1, "Got unexpected value %u.\n", value);
11165 value = animation->lpVtbl->GetMaxNumTracks(animation);
11166 ok(value == 1, "Got unexpected value %u.\n", value);
11168 value = animation->lpVtbl->GetMaxNumEvents(animation);
11169 ok(value == 1, "Got unexpected value %u.\n", value);
11171 animation->lpVtbl->Release(animation);
11173 hr = D3DXCreateAnimationController(100, 101, 102, 103, &animation);
11174 ok(hr == D3D_OK, "Got unexpected hr returned %#x.\n", hr);
11176 value = animation->lpVtbl->GetMaxNumAnimationOutputs(animation);
11177 ok(value == 100, "Got unexpected value %u.\n", value);
11179 value = animation->lpVtbl->GetMaxNumAnimationSets(animation);
11180 ok(value == 101, "Got unexpected value %u.\n", value);
11182 value = animation->lpVtbl->GetMaxNumTracks(animation);
11183 ok(value == 102, "Got unexpected value %u.\n", value);
11185 value = animation->lpVtbl->GetMaxNumEvents(animation);
11186 ok(value == 103, "Got unexpected value %u.\n", value);
11188 animation->lpVtbl->Release(animation);
11191 START_TEST(mesh)
11193 D3DXBoundProbeTest();
11194 D3DXComputeBoundingBoxTest();
11195 D3DXComputeBoundingSphereTest();
11196 D3DXGetFVFVertexSizeTest();
11197 D3DXIntersectTriTest();
11198 D3DXCreateMeshTest();
11199 D3DXCreateMeshFVFTest();
11200 D3DXLoadMeshTest();
11201 D3DXCreateBoxTest();
11202 D3DXCreatePolygonTest();
11203 D3DXCreateSphereTest();
11204 D3DXCreateCylinderTest();
11205 D3DXCreateTextTest();
11206 D3DXCreateTorusTest();
11207 D3DXCreateAnimationControllerTest();
11208 test_get_decl_length();
11209 test_get_decl_vertex_size();
11210 test_fvf_decl_conversion();
11211 D3DXGenerateAdjacencyTest();
11212 test_update_semantics();
11213 test_create_skin_info();
11214 test_convert_adjacency_to_point_reps();
11215 test_convert_point_reps_to_adjacency();
11216 test_weld_vertices();
11217 test_clone_mesh();
11218 test_valid_mesh();
11219 test_optimize_faces();
11220 test_compute_normals();