d3dx9/tests: Fix HFONT leaks.
[wine/multimedia.git] / dlls / d3dx9_36 / tests / mesh.c
blob4186e19fcb2d3254f785b90ffc374b4026a9bf8a
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 /*Only positive ray is taken in account*/
1117 vertex[0].x = 1.0f; vertex[0].y = 0.0f; vertex[0].z = 0.0f;
1118 vertex[1].x = 2.0f; vertex[1].y = 0.0f; vertex[1].z = 0.0f;
1119 vertex[2].x = 1.0f; vertex[2].y = 1.0f; vertex[2].z = 0.0f;
1121 position.x = 17.5f; position.y = 24.25f; position.z = 32.0f;
1123 ray.x = 2.0f; ray.y = 3.0f; ray.z = 4.0f;
1125 exp_res = FALSE;
1127 got_res = D3DXIntersectTri(&vertex[0],&vertex[1],&vertex[2],&position,&ray,&got_u,&got_v,&got_dist);
1128 ok( got_res == exp_res, "Expected result = %d, got %d\n",exp_res,got_res);
1130 got_res = D3DXIntersectTri(&vertex[0], &vertex[1], &vertex[2], &position, &ray, NULL, NULL, NULL);
1131 ok(got_res == exp_res, "Expected result = %d, got %d\n", exp_res, got_res);
1133 /*Intersection between ray and triangle in a same plane is considered as empty*/
1135 vertex[0].x = 4.0f; vertex[0].y = 0.0f; vertex[0].z = 0.0f;
1136 vertex[1].x = 6.0f; vertex[1].y = 0.0f; vertex[1].z = 0.0f;
1137 vertex[2].x = 4.0f; vertex[2].y = 2.0f; vertex[2].z = 0.0f;
1139 position.x = 1.0f; position.y = 1.0f; position.z = 0.0f;
1141 ray.x = 1.0f; ray.y = 0.0f; ray.z = 0.0f;
1143 exp_res = FALSE;
1145 got_res = D3DXIntersectTri(&vertex[0],&vertex[1],&vertex[2],&position,&ray,&got_u,&got_v,&got_dist);
1146 ok( got_res == exp_res, "Expected result = %d, got %d\n",exp_res,got_res);
1148 got_res = D3DXIntersectTri(&vertex[0], &vertex[1], &vertex[2], &position, &ray, NULL, NULL, NULL);
1149 ok(got_res == exp_res, "Expected result = %d, got %d\n", exp_res, got_res);
1152 static void D3DXCreateMeshTest(void)
1154 HRESULT hr;
1155 IDirect3DDevice9 *device, *test_device;
1156 ID3DXMesh *d3dxmesh;
1157 int i, size;
1158 D3DVERTEXELEMENT9 test_decl[MAX_FVF_DECL_SIZE];
1159 DWORD options;
1160 struct mesh mesh;
1161 struct test_context *test_context;
1163 static const D3DVERTEXELEMENT9 decl1[3] = {
1164 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1165 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
1166 D3DDECL_END(), };
1168 static const D3DVERTEXELEMENT9 decl2[] = {
1169 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1170 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
1171 {0, 24, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_PSIZE, 0},
1172 {0, 28, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 1},
1173 {0, 32, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
1174 /* 8 bytes padding */
1175 {0, 44, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
1176 D3DDECL_END(),
1179 static const D3DVERTEXELEMENT9 decl3[] = {
1180 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1181 {1, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
1182 D3DDECL_END(),
1185 hr = D3DXCreateMesh(0, 0, 0, NULL, NULL, NULL);
1186 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1188 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl1, NULL, &d3dxmesh);
1189 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1191 test_context = new_test_context();
1192 if (!test_context)
1194 skip("Couldn't create test context\n");
1195 return;
1197 device = test_context->device;
1199 hr = D3DXCreateMesh(0, 3, D3DXMESH_MANAGED, decl1, device, &d3dxmesh);
1200 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1202 hr = D3DXCreateMesh(1, 0, D3DXMESH_MANAGED, decl1, device, &d3dxmesh);
1203 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1205 hr = D3DXCreateMesh(1, 3, 0, decl1, device, &d3dxmesh);
1206 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
1208 if (hr == D3D_OK)
1210 d3dxmesh->lpVtbl->Release(d3dxmesh);
1213 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, 0, device, &d3dxmesh);
1214 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1216 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl1, device, NULL);
1217 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1219 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl1, device, &d3dxmesh);
1220 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
1222 if (hr == D3D_OK)
1224 /* device */
1225 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, NULL);
1226 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1228 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, &test_device);
1229 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
1230 ok(test_device == device, "Got result %p, expected %p\n", test_device, device);
1232 if (hr == D3D_OK)
1234 IDirect3DDevice9_Release(device);
1237 /* declaration */
1238 hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, NULL);
1239 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1241 hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, test_decl);
1242 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
1244 if (hr == D3D_OK)
1246 size = sizeof(decl1) / sizeof(decl1[0]);
1247 for (i = 0; i < size - 1; i++)
1249 ok(test_decl[i].Stream == decl1[i].Stream, "Returned stream %d, expected %d\n", test_decl[i].Stream, decl1[i].Stream);
1250 ok(test_decl[i].Type == decl1[i].Type, "Returned type %d, expected %d\n", test_decl[i].Type, decl1[i].Type);
1251 ok(test_decl[i].Method == decl1[i].Method, "Returned method %d, expected %d\n", test_decl[i].Method, decl1[i].Method);
1252 ok(test_decl[i].Usage == decl1[i].Usage, "Returned usage %d, expected %d\n", test_decl[i].Usage, decl1[i].Usage);
1253 ok(test_decl[i].UsageIndex == decl1[i].UsageIndex, "Returned usage index %d, expected %d\n", test_decl[i].UsageIndex, decl1[i].UsageIndex);
1254 ok(test_decl[i].Offset == decl1[i].Offset, "Returned offset %d, expected %d\n", test_decl[i].Offset, decl1[i].Offset);
1256 ok(decl1[size-1].Stream == 0xFF, "Returned too long vertex declaration\n"); /* end element */
1259 /* options */
1260 options = d3dxmesh->lpVtbl->GetOptions(d3dxmesh);
1261 ok(options == D3DXMESH_MANAGED, "Got result %x, expected %x (D3DXMESH_MANAGED)\n", options, D3DXMESH_MANAGED);
1263 /* rest */
1264 if (!new_mesh(&mesh, 3, 1))
1266 skip("Couldn't create mesh\n");
1268 else
1270 memset(mesh.vertices, 0, mesh.number_of_vertices * sizeof(*mesh.vertices));
1271 memset(mesh.faces, 0, mesh.number_of_faces * sizeof(*mesh.faces));
1272 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
1274 compare_mesh("createmesh1", d3dxmesh, &mesh);
1276 free_mesh(&mesh);
1279 d3dxmesh->lpVtbl->Release(d3dxmesh);
1282 /* Test a declaration that can't be converted to an FVF. */
1283 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl2, device, &d3dxmesh);
1284 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
1286 if (hr == D3D_OK)
1288 /* device */
1289 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, NULL);
1290 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1292 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, &test_device);
1293 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
1294 ok(test_device == device, "Got result %p, expected %p\n", test_device, device);
1296 if (hr == D3D_OK)
1298 IDirect3DDevice9_Release(device);
1301 /* declaration */
1302 hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, test_decl);
1303 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
1305 if (hr == D3D_OK)
1307 size = sizeof(decl2) / sizeof(decl2[0]);
1308 for (i = 0; i < size - 1; i++)
1310 ok(test_decl[i].Stream == decl2[i].Stream, "Returned stream %d, expected %d\n", test_decl[i].Stream, decl2[i].Stream);
1311 ok(test_decl[i].Type == decl2[i].Type, "Returned type %d, expected %d\n", test_decl[i].Type, decl2[i].Type);
1312 ok(test_decl[i].Method == decl2[i].Method, "Returned method %d, expected %d\n", test_decl[i].Method, decl2[i].Method);
1313 ok(test_decl[i].Usage == decl2[i].Usage, "Returned usage %d, expected %d\n", test_decl[i].Usage, decl2[i].Usage);
1314 ok(test_decl[i].UsageIndex == decl2[i].UsageIndex, "Returned usage index %d, expected %d\n", test_decl[i].UsageIndex, decl2[i].UsageIndex);
1315 ok(test_decl[i].Offset == decl2[i].Offset, "Returned offset %d, expected %d\n", test_decl[i].Offset, decl2[i].Offset);
1317 ok(decl2[size-1].Stream == 0xFF, "Returned too long vertex declaration\n"); /* end element */
1320 /* options */
1321 options = d3dxmesh->lpVtbl->GetOptions(d3dxmesh);
1322 ok(options == D3DXMESH_MANAGED, "Got result %x, expected %x (D3DXMESH_MANAGED)\n", options, D3DXMESH_MANAGED);
1324 /* rest */
1325 if (!new_mesh(&mesh, 3, 1))
1327 skip("Couldn't create mesh\n");
1329 else
1331 memset(mesh.vertices, 0, mesh.number_of_vertices * sizeof(*mesh.vertices));
1332 memset(mesh.faces, 0, mesh.number_of_faces * sizeof(*mesh.faces));
1333 mesh.fvf = 0;
1334 mesh.vertex_size = 60;
1336 compare_mesh("createmesh2", d3dxmesh, &mesh);
1338 free_mesh(&mesh);
1341 mesh.vertex_size = d3dxmesh->lpVtbl->GetNumBytesPerVertex(d3dxmesh);
1342 ok(mesh.vertex_size == 60, "Got vertex size %u, expected %u\n", mesh.vertex_size, 60);
1344 d3dxmesh->lpVtbl->Release(d3dxmesh);
1347 /* Test a declaration with multiple streams. */
1348 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl3, device, &d3dxmesh);
1349 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1351 free_test_context(test_context);
1354 static void D3DXCreateMeshFVFTest(void)
1356 HRESULT hr;
1357 IDirect3DDevice9 *device, *test_device;
1358 ID3DXMesh *d3dxmesh;
1359 int i, size;
1360 D3DVERTEXELEMENT9 test_decl[MAX_FVF_DECL_SIZE];
1361 DWORD options;
1362 struct mesh mesh;
1363 struct test_context *test_context;
1365 static const D3DVERTEXELEMENT9 decl[3] = {
1366 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1367 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
1368 D3DDECL_END(), };
1370 hr = D3DXCreateMeshFVF(0, 0, 0, 0, NULL, NULL);
1371 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1373 hr = D3DXCreateMeshFVF(1, 3, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, NULL, &d3dxmesh);
1374 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1376 test_context = new_test_context();
1377 if (!test_context)
1379 skip("Couldn't create test context\n");
1380 return;
1382 device = test_context->device;
1384 hr = D3DXCreateMeshFVF(0, 3, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, device, &d3dxmesh);
1385 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1387 hr = D3DXCreateMeshFVF(1, 0, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, device, &d3dxmesh);
1388 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1390 hr = D3DXCreateMeshFVF(1, 3, 0, D3DFVF_XYZ | D3DFVF_NORMAL, device, &d3dxmesh);
1391 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
1393 if (hr == D3D_OK)
1395 d3dxmesh->lpVtbl->Release(d3dxmesh);
1398 hr = D3DXCreateMeshFVF(1, 3, D3DXMESH_MANAGED, 0xdeadbeef, device, &d3dxmesh);
1399 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1401 hr = D3DXCreateMeshFVF(1, 3, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, device, NULL);
1402 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1404 hr = D3DXCreateMeshFVF(1, 3, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, device, &d3dxmesh);
1405 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
1407 if (hr == D3D_OK)
1409 /* device */
1410 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, NULL);
1411 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1413 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, &test_device);
1414 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
1415 ok(test_device == device, "Got result %p, expected %p\n", test_device, device);
1417 if (hr == D3D_OK)
1419 IDirect3DDevice9_Release(device);
1422 /* declaration */
1423 hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, NULL);
1424 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1426 hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, test_decl);
1427 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
1429 if (hr == D3D_OK)
1431 size = sizeof(decl) / sizeof(decl[0]);
1432 for (i = 0; i < size - 1; i++)
1434 ok(test_decl[i].Stream == decl[i].Stream, "Returned stream %d, expected %d\n", test_decl[i].Stream, decl[i].Stream);
1435 ok(test_decl[i].Type == decl[i].Type, "Returned type %d, expected %d\n", test_decl[i].Type, decl[i].Type);
1436 ok(test_decl[i].Method == decl[i].Method, "Returned method %d, expected %d\n", test_decl[i].Method, decl[i].Method);
1437 ok(test_decl[i].Usage == decl[i].Usage, "Returned usage %d, expected %d\n", test_decl[i].Usage, decl[i].Usage);
1438 ok(test_decl[i].UsageIndex == decl[i].UsageIndex, "Returned usage index %d, expected %d\n",
1439 test_decl[i].UsageIndex, decl[i].UsageIndex);
1440 ok(test_decl[i].Offset == decl[i].Offset, "Returned offset %d, expected %d\n", test_decl[i].Offset, decl[i].Offset);
1442 ok(decl[size-1].Stream == 0xFF, "Returned too long vertex declaration\n"); /* end element */
1445 /* options */
1446 options = d3dxmesh->lpVtbl->GetOptions(d3dxmesh);
1447 ok(options == D3DXMESH_MANAGED, "Got result %x, expected %x (D3DXMESH_MANAGED)\n", options, D3DXMESH_MANAGED);
1449 /* rest */
1450 if (!new_mesh(&mesh, 3, 1))
1452 skip("Couldn't create mesh\n");
1454 else
1456 memset(mesh.vertices, 0, mesh.number_of_vertices * sizeof(*mesh.vertices));
1457 memset(mesh.faces, 0, mesh.number_of_faces * sizeof(*mesh.faces));
1458 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
1460 compare_mesh("createmeshfvf", d3dxmesh, &mesh);
1462 free_mesh(&mesh);
1465 d3dxmesh->lpVtbl->Release(d3dxmesh);
1468 free_test_context(test_context);
1471 #define check_vertex_buffer(mesh, vertices, num_vertices, fvf) \
1472 check_vertex_buffer_(__LINE__, mesh, vertices, num_vertices, fvf)
1473 static void check_vertex_buffer_(int line, ID3DXMesh *mesh, const void *vertices, DWORD num_vertices, DWORD fvf)
1475 DWORD mesh_num_vertices = mesh->lpVtbl->GetNumVertices(mesh);
1476 DWORD mesh_fvf = mesh->lpVtbl->GetFVF(mesh);
1477 const void *mesh_vertices;
1478 HRESULT hr;
1480 ok_(__FILE__,line)(fvf == mesh_fvf, "expected FVF %x, got %x\n", fvf, mesh_fvf);
1481 ok_(__FILE__,line)(num_vertices == mesh_num_vertices,
1482 "Expected %u vertices, got %u\n", num_vertices, mesh_num_vertices);
1484 hr = mesh->lpVtbl->LockVertexBuffer(mesh, D3DLOCK_READONLY, (void**)&mesh_vertices);
1485 ok_(__FILE__,line)(hr == D3D_OK, "LockVertexBuffer returned %x, expected %x (D3D_OK)\n", hr, D3D_OK);
1486 if (FAILED(hr))
1487 return;
1489 if (mesh_fvf == fvf) {
1490 DWORD vertex_size = D3DXGetFVFVertexSize(fvf);
1491 int i;
1492 for (i = 0; i < min(num_vertices, mesh_num_vertices); i++)
1494 const FLOAT *exp_float = vertices;
1495 const FLOAT *got_float = mesh_vertices;
1496 DWORD texcount;
1497 DWORD pos_dim = 0;
1498 int j;
1499 BOOL last_beta_dword = FALSE;
1500 char prefix[128];
1502 switch (fvf & D3DFVF_POSITION_MASK) {
1503 case D3DFVF_XYZ: pos_dim = 3; break;
1504 case D3DFVF_XYZRHW: pos_dim = 4; break;
1505 case D3DFVF_XYZB1:
1506 case D3DFVF_XYZB2:
1507 case D3DFVF_XYZB3:
1508 case D3DFVF_XYZB4:
1509 case D3DFVF_XYZB5:
1510 pos_dim = (fvf & D3DFVF_POSITION_MASK) - D3DFVF_XYZB1 + 1;
1511 if (fvf & (D3DFVF_LASTBETA_UBYTE4 | D3DFVF_LASTBETA_D3DCOLOR))
1513 pos_dim--;
1514 last_beta_dword = TRUE;
1516 break;
1517 case D3DFVF_XYZW: pos_dim = 4; break;
1519 sprintf(prefix, "vertex[%u] position, ", i);
1520 check_floats_(line, prefix, got_float, exp_float, pos_dim);
1521 exp_float += pos_dim;
1522 got_float += pos_dim;
1524 if (last_beta_dword) {
1525 ok_(__FILE__,line)(*(DWORD*)exp_float == *(DWORD*)got_float,
1526 "Vertex[%u]: Expected last beta %08x, got %08x\n", i, *(DWORD*)exp_float, *(DWORD*)got_float);
1527 exp_float++;
1528 got_float++;
1531 if (fvf & D3DFVF_NORMAL) {
1532 sprintf(prefix, "vertex[%u] normal, ", i);
1533 check_floats_(line, prefix, got_float, exp_float, 3);
1534 exp_float += 3;
1535 got_float += 3;
1537 if (fvf & D3DFVF_PSIZE) {
1538 ok_(__FILE__,line)(compare(*exp_float, *got_float),
1539 "Vertex[%u]: Expected psize %g, got %g\n", i, *exp_float, *got_float);
1540 exp_float++;
1541 got_float++;
1543 if (fvf & D3DFVF_DIFFUSE) {
1544 ok_(__FILE__,line)(*(DWORD*)exp_float == *(DWORD*)got_float,
1545 "Vertex[%u]: Expected diffuse %08x, got %08x\n", i, *(DWORD*)exp_float, *(DWORD*)got_float);
1546 exp_float++;
1547 got_float++;
1549 if (fvf & D3DFVF_SPECULAR) {
1550 ok_(__FILE__,line)(*(DWORD*)exp_float == *(DWORD*)got_float,
1551 "Vertex[%u]: Expected specular %08x, got %08x\n", i, *(DWORD*)exp_float, *(DWORD*)got_float);
1552 exp_float++;
1553 got_float++;
1556 texcount = (fvf & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
1557 for (j = 0; j < texcount; j++) {
1558 DWORD dim = (((fvf >> (16 + 2 * j)) + 1) & 0x03) + 1;
1559 sprintf(prefix, "vertex[%u] texture, ", i);
1560 check_floats_(line, prefix, got_float, exp_float, dim);
1561 exp_float += dim;
1562 got_float += dim;
1565 vertices = (BYTE*)vertices + vertex_size;
1566 mesh_vertices = (BYTE*)mesh_vertices + vertex_size;
1570 mesh->lpVtbl->UnlockVertexBuffer(mesh);
1573 #define check_index_buffer(mesh, indices, num_indices, index_size) \
1574 check_index_buffer_(__LINE__, mesh, indices, num_indices, index_size)
1575 static void check_index_buffer_(int line, ID3DXMesh *mesh, const void *indices, DWORD num_indices, DWORD index_size)
1577 DWORD mesh_index_size = (mesh->lpVtbl->GetOptions(mesh) & D3DXMESH_32BIT) ? 4 : 2;
1578 DWORD mesh_num_indices = mesh->lpVtbl->GetNumFaces(mesh) * 3;
1579 const void *mesh_indices;
1580 HRESULT hr;
1581 DWORD i;
1583 ok_(__FILE__,line)(index_size == mesh_index_size,
1584 "Expected index size %u, got %u\n", index_size, mesh_index_size);
1585 ok_(__FILE__,line)(num_indices == mesh_num_indices,
1586 "Expected %u indices, got %u\n", num_indices, mesh_num_indices);
1588 hr = mesh->lpVtbl->LockIndexBuffer(mesh, D3DLOCK_READONLY, (void**)&mesh_indices);
1589 ok_(__FILE__,line)(hr == D3D_OK, "LockIndexBuffer returned %x, expected %x (D3D_OK)\n", hr, D3D_OK);
1590 if (FAILED(hr))
1591 return;
1593 if (mesh_index_size == index_size) {
1594 for (i = 0; i < min(num_indices, mesh_num_indices); i++)
1596 if (index_size == 4)
1597 ok_(__FILE__,line)(*(DWORD*)indices == *(DWORD*)mesh_indices,
1598 "Index[%u]: expected %u, got %u\n", i, *(DWORD*)indices, *(DWORD*)mesh_indices);
1599 else
1600 ok_(__FILE__,line)(*(WORD*)indices == *(WORD*)mesh_indices,
1601 "Index[%u]: expected %u, got %u\n", i, *(WORD*)indices, *(WORD*)mesh_indices);
1602 indices = (BYTE*)indices + index_size;
1603 mesh_indices = (BYTE*)mesh_indices + index_size;
1606 mesh->lpVtbl->UnlockIndexBuffer(mesh);
1609 #define check_matrix(got, expected) check_matrix_(__LINE__, got, expected)
1610 static void check_matrix_(int line, const D3DXMATRIX *got, const D3DXMATRIX *expected)
1612 int i, j;
1613 for (i = 0; i < 4; i++) {
1614 for (j = 0; j < 4; j++) {
1615 ok_(__FILE__,line)(compare(U(*expected).m[i][j], U(*got).m[i][j]),
1616 "matrix[%u][%u]: expected %g, got %g\n",
1617 i, j, U(*expected).m[i][j], U(*got).m[i][j]);
1622 static void check_colorvalue_(int line, const char *prefix, const D3DCOLORVALUE got, const D3DCOLORVALUE expected)
1624 ok_(__FILE__,line)(expected.r == got.r && expected.g == got.g && expected.b == got.b && expected.a == got.a,
1625 "%sExpected (%g, %g, %g, %g), got (%g, %g, %g, %g)\n", prefix,
1626 expected.r, expected.g, expected.b, expected.a, got.r, got.g, got.b, got.a);
1629 #define check_materials(got, got_count, expected, expected_count) \
1630 check_materials_(__LINE__, got, got_count, expected, expected_count)
1631 static void check_materials_(int line, const D3DXMATERIAL *got, DWORD got_count, const D3DXMATERIAL *expected, DWORD expected_count)
1633 int i;
1634 ok_(__FILE__,line)(expected_count == got_count, "Expected %u materials, got %u\n", expected_count, got_count);
1635 if (!expected) {
1636 ok_(__FILE__,line)(got == NULL, "Expected NULL material ptr, got %p\n", got);
1637 return;
1639 for (i = 0; i < min(expected_count, got_count); i++)
1641 if (!expected[i].pTextureFilename)
1642 ok_(__FILE__,line)(got[i].pTextureFilename == NULL,
1643 "Expected NULL pTextureFilename, got %p\n", got[i].pTextureFilename);
1644 else
1645 ok_(__FILE__,line)(!strcmp(expected[i].pTextureFilename, got[i].pTextureFilename),
1646 "Expected '%s' for pTextureFilename, got '%s'\n", expected[i].pTextureFilename, got[i].pTextureFilename);
1647 check_colorvalue_(line, "Diffuse: ", got[i].MatD3D.Diffuse, expected[i].MatD3D.Diffuse);
1648 check_colorvalue_(line, "Ambient: ", got[i].MatD3D.Ambient, expected[i].MatD3D.Ambient);
1649 check_colorvalue_(line, "Specular: ", got[i].MatD3D.Specular, expected[i].MatD3D.Specular);
1650 check_colorvalue_(line, "Emissive: ", got[i].MatD3D.Emissive, expected[i].MatD3D.Emissive);
1651 ok_(__FILE__,line)(expected[i].MatD3D.Power == got[i].MatD3D.Power,
1652 "Power: Expected %g, got %g\n", expected[i].MatD3D.Power, got[i].MatD3D.Power);
1656 #define check_generated_adjacency(mesh, got, epsilon) check_generated_adjacency_(__LINE__, mesh, got, epsilon)
1657 static void check_generated_adjacency_(int line, ID3DXMesh *mesh, const DWORD *got, FLOAT epsilon)
1659 DWORD *expected;
1660 DWORD num_faces = mesh->lpVtbl->GetNumFaces(mesh);
1661 HRESULT hr;
1663 expected = HeapAlloc(GetProcessHeap(), 0, num_faces * sizeof(DWORD) * 3);
1664 if (!expected) {
1665 skip_(__FILE__, line)("Out of memory\n");
1666 return;
1668 hr = mesh->lpVtbl->GenerateAdjacency(mesh, epsilon, expected);
1669 ok_(__FILE__, line)(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
1670 if (SUCCEEDED(hr))
1672 int i;
1673 for (i = 0; i < num_faces; i++)
1675 ok_(__FILE__, line)(expected[i * 3] == got[i * 3] &&
1676 expected[i * 3 + 1] == got[i * 3 + 1] &&
1677 expected[i * 3 + 2] == got[i * 3 + 2],
1678 "Face %u adjacencies: Expected (%u, %u, %u), got (%u, %u, %u)\n", i,
1679 expected[i * 3], expected[i * 3 + 1], expected[i * 3 + 2],
1680 got[i * 3], got[i * 3 + 1], got[i * 3 + 2]);
1683 HeapFree(GetProcessHeap(), 0, expected);
1686 #define check_generated_effects(materials, num_materials, effects) \
1687 check_generated_effects_(__LINE__, materials, num_materials, effects)
1688 static void check_generated_effects_(int line, const D3DXMATERIAL *materials, DWORD num_materials, const D3DXEFFECTINSTANCE *effects)
1690 int i;
1691 static const struct {
1692 const char *name;
1693 DWORD name_size;
1694 DWORD num_bytes;
1695 DWORD value_offset;
1696 } params[] = {
1697 #define EFFECT_TABLE_ENTRY(str, field) \
1698 {str, sizeof(str), sizeof(materials->MatD3D.field), offsetof(D3DXMATERIAL, MatD3D.field)}
1699 EFFECT_TABLE_ENTRY("Diffuse", Diffuse),
1700 EFFECT_TABLE_ENTRY("Power", Power),
1701 EFFECT_TABLE_ENTRY("Specular", Specular),
1702 EFFECT_TABLE_ENTRY("Emissive", Emissive),
1703 EFFECT_TABLE_ENTRY("Ambient", Ambient),
1704 #undef EFFECT_TABLE_ENTRY
1707 if (!num_materials) {
1708 ok_(__FILE__, line)(effects == NULL, "Expected NULL effects, got %p\n", effects);
1709 return;
1711 for (i = 0; i < num_materials; i++)
1713 int j;
1714 DWORD expected_num_defaults = ARRAY_SIZE(params) + (materials[i].pTextureFilename ? 1 : 0);
1716 ok_(__FILE__,line)(expected_num_defaults == effects[i].NumDefaults,
1717 "effect[%u] NumDefaults: Expected %u, got %u\n", i,
1718 expected_num_defaults, effects[i].NumDefaults);
1719 for (j = 0; j < min(ARRAY_SIZE(params), effects[i].NumDefaults); j++)
1721 int k;
1722 D3DXEFFECTDEFAULT *got_param = &effects[i].pDefaults[j];
1723 ok_(__FILE__,line)(!strcmp(params[j].name, got_param->pParamName),
1724 "effect[%u].pDefaults[%u].pParamName: Expected '%s', got '%s'\n", i, j,
1725 params[j].name, got_param->pParamName);
1726 ok_(__FILE__,line)(D3DXEDT_FLOATS == got_param->Type,
1727 "effect[%u].pDefaults[%u].Type: Expected %u, got %u\n", i, j,
1728 D3DXEDT_FLOATS, got_param->Type);
1729 ok_(__FILE__,line)(params[j].num_bytes == got_param->NumBytes,
1730 "effect[%u].pDefaults[%u].NumBytes: Expected %u, got %u\n", i, j,
1731 params[j].num_bytes, got_param->NumBytes);
1732 for (k = 0; k < min(params[j].num_bytes, got_param->NumBytes) / 4; k++)
1734 FLOAT expected = ((FLOAT*)((BYTE*)&materials[i] + params[j].value_offset))[k];
1735 FLOAT got = ((FLOAT*)got_param->pValue)[k];
1736 ok_(__FILE__,line)(compare(expected, got),
1737 "effect[%u].pDefaults[%u] float value %u: Expected %g, got %g\n", i, j, k, expected, got);
1740 if (effects[i].NumDefaults > ARRAY_SIZE(params)) {
1741 D3DXEFFECTDEFAULT *got_param = &effects[i].pDefaults[j];
1742 static const char *expected_name = "Texture0@Name";
1744 ok_(__FILE__,line)(!strcmp(expected_name, got_param->pParamName),
1745 "effect[%u].pDefaults[%u].pParamName: Expected '%s', got '%s'\n", i, j,
1746 expected_name, got_param->pParamName);
1747 ok_(__FILE__,line)(D3DXEDT_STRING == got_param->Type,
1748 "effect[%u].pDefaults[%u].Type: Expected %u, got %u\n", i, j,
1749 D3DXEDT_STRING, got_param->Type);
1750 if (materials[i].pTextureFilename) {
1751 ok_(__FILE__,line)(strlen(materials[i].pTextureFilename) + 1 == got_param->NumBytes,
1752 "effect[%u] texture filename length: Expected %u, got %u\n", i,
1753 (DWORD)strlen(materials[i].pTextureFilename) + 1, got_param->NumBytes);
1754 ok_(__FILE__,line)(!strcmp(materials[i].pTextureFilename, got_param->pValue),
1755 "effect[%u] texture filename: Expected '%s', got '%s'\n", i,
1756 materials[i].pTextureFilename, (char*)got_param->pValue);
1762 static char *strdupA(const char *p)
1764 char *ret;
1765 if (!p) return NULL;
1766 ret = HeapAlloc(GetProcessHeap(), 0, strlen(p) + 1);
1767 if (ret) strcpy(ret, p);
1768 return ret;
1771 static HRESULT CALLBACK ID3DXAllocateHierarchyImpl_DestroyFrame(ID3DXAllocateHierarchy *iface, LPD3DXFRAME frame)
1773 TRACECALLBACK("ID3DXAllocateHierarchyImpl_DestroyFrame(%p, %p)\n", iface, frame);
1774 if (frame) {
1775 HeapFree(GetProcessHeap(), 0, frame->Name);
1776 HeapFree(GetProcessHeap(), 0, frame);
1778 return D3D_OK;
1781 static HRESULT CALLBACK ID3DXAllocateHierarchyImpl_CreateFrame(ID3DXAllocateHierarchy *iface,
1782 const char *name, D3DXFRAME **new_frame)
1784 D3DXFRAME *frame;
1786 TRACECALLBACK("ID3DXAllocateHierarchyImpl_CreateFrame(%p, '%s', %p)\n", iface, name, new_frame);
1787 frame = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*frame));
1788 if (!frame)
1789 return E_OUTOFMEMORY;
1790 if (name) {
1791 frame->Name = strdupA(name);
1792 if (!frame->Name) {
1793 HeapFree(GetProcessHeap(), 0, frame);
1794 return E_OUTOFMEMORY;
1797 *new_frame = frame;
1798 return D3D_OK;
1801 static HRESULT destroy_mesh_container(LPD3DXMESHCONTAINER mesh_container)
1803 int i;
1805 if (!mesh_container)
1806 return D3D_OK;
1807 HeapFree(GetProcessHeap(), 0, mesh_container->Name);
1808 if (U(mesh_container->MeshData).pMesh)
1809 IUnknown_Release(U(mesh_container->MeshData).pMesh);
1810 if (mesh_container->pMaterials) {
1811 for (i = 0; i < mesh_container->NumMaterials; i++)
1812 HeapFree(GetProcessHeap(), 0, mesh_container->pMaterials[i].pTextureFilename);
1813 HeapFree(GetProcessHeap(), 0, mesh_container->pMaterials);
1815 if (mesh_container->pEffects) {
1816 for (i = 0; i < mesh_container->NumMaterials; i++) {
1817 HeapFree(GetProcessHeap(), 0, mesh_container->pEffects[i].pEffectFilename);
1818 if (mesh_container->pEffects[i].pDefaults) {
1819 int j;
1820 for (j = 0; j < mesh_container->pEffects[i].NumDefaults; j++) {
1821 HeapFree(GetProcessHeap(), 0, mesh_container->pEffects[i].pDefaults[j].pParamName);
1822 HeapFree(GetProcessHeap(), 0, mesh_container->pEffects[i].pDefaults[j].pValue);
1824 HeapFree(GetProcessHeap(), 0, mesh_container->pEffects[i].pDefaults);
1827 HeapFree(GetProcessHeap(), 0, mesh_container->pEffects);
1829 HeapFree(GetProcessHeap(), 0, mesh_container->pAdjacency);
1830 if (mesh_container->pSkinInfo)
1831 IUnknown_Release(mesh_container->pSkinInfo);
1832 HeapFree(GetProcessHeap(), 0, mesh_container);
1833 return D3D_OK;
1836 static HRESULT CALLBACK ID3DXAllocateHierarchyImpl_DestroyMeshContainer(ID3DXAllocateHierarchy *iface, LPD3DXMESHCONTAINER mesh_container)
1838 TRACECALLBACK("ID3DXAllocateHierarchyImpl_DestroyMeshContainer(%p, %p)\n", iface, mesh_container);
1839 return destroy_mesh_container(mesh_container);
1842 static HRESULT CALLBACK ID3DXAllocateHierarchyImpl_CreateMeshContainer(ID3DXAllocateHierarchy *iface,
1843 const char *name, const D3DXMESHDATA *mesh_data, const D3DXMATERIAL *materials,
1844 const D3DXEFFECTINSTANCE *effects, DWORD num_materials, const DWORD *adjacency,
1845 ID3DXSkinInfo *skin_info, D3DXMESHCONTAINER **new_mesh_container)
1847 LPD3DXMESHCONTAINER mesh_container = NULL;
1848 int i;
1850 TRACECALLBACK("ID3DXAllocateHierarchyImpl_CreateMeshContainer(%p, '%s', %u, %p, %p, %p, %d, %p, %p, %p)\n",
1851 iface, name, mesh_data->Type, U(*mesh_data).pMesh, materials, effects,
1852 num_materials, adjacency, skin_info, *new_mesh_container);
1854 mesh_container = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*mesh_container));
1855 if (!mesh_container)
1856 return E_OUTOFMEMORY;
1858 if (name) {
1859 mesh_container->Name = strdupA(name);
1860 if (!mesh_container->Name)
1861 goto error;
1864 mesh_container->NumMaterials = num_materials;
1865 if (num_materials) {
1866 mesh_container->pMaterials = HeapAlloc(GetProcessHeap(), 0, num_materials * sizeof(*materials));
1867 if (!mesh_container->pMaterials)
1868 goto error;
1870 memcpy(mesh_container->pMaterials, materials, num_materials * sizeof(*materials));
1871 for (i = 0; i < num_materials; i++)
1872 mesh_container->pMaterials[i].pTextureFilename = NULL;
1873 for (i = 0; i < num_materials; i++) {
1874 if (materials[i].pTextureFilename) {
1875 mesh_container->pMaterials[i].pTextureFilename = strdupA(materials[i].pTextureFilename);
1876 if (!mesh_container->pMaterials[i].pTextureFilename)
1877 goto error;
1881 mesh_container->pEffects = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, num_materials * sizeof(*effects));
1882 if (!mesh_container->pEffects)
1883 goto error;
1884 for (i = 0; i < num_materials; i++) {
1885 int j;
1886 const D3DXEFFECTINSTANCE *effect_src = &effects[i];
1887 D3DXEFFECTINSTANCE *effect_dest = &mesh_container->pEffects[i];
1889 if (effect_src->pEffectFilename) {
1890 effect_dest->pEffectFilename = strdupA(effect_src->pEffectFilename);
1891 if (!effect_dest->pEffectFilename)
1892 goto error;
1894 effect_dest->pDefaults = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1895 effect_src->NumDefaults * sizeof(*effect_src->pDefaults));
1896 if (!effect_dest->pDefaults)
1897 goto error;
1898 effect_dest->NumDefaults = effect_src->NumDefaults;
1899 for (j = 0; j < effect_src->NumDefaults; j++) {
1900 const D3DXEFFECTDEFAULT *default_src = &effect_src->pDefaults[j];
1901 D3DXEFFECTDEFAULT *default_dest = &effect_dest->pDefaults[j];
1903 if (default_src->pParamName) {
1904 default_dest->pParamName = strdupA(default_src->pParamName);
1905 if (!default_dest->pParamName)
1906 goto error;
1908 default_dest->NumBytes = default_src->NumBytes;
1909 default_dest->Type = default_src->Type;
1910 default_dest->pValue = HeapAlloc(GetProcessHeap(), 0, default_src->NumBytes);
1911 memcpy(default_dest->pValue, default_src->pValue, default_src->NumBytes);
1916 ok(adjacency != NULL, "Expected non-NULL adjacency, got NULL\n");
1917 if (adjacency) {
1918 if (mesh_data->Type == D3DXMESHTYPE_MESH || mesh_data->Type == D3DXMESHTYPE_PMESH) {
1919 ID3DXBaseMesh *basemesh = (ID3DXBaseMesh*)U(*mesh_data).pMesh;
1920 DWORD num_faces = basemesh->lpVtbl->GetNumFaces(basemesh);
1921 size_t size = num_faces * sizeof(DWORD) * 3;
1922 mesh_container->pAdjacency = HeapAlloc(GetProcessHeap(), 0, size);
1923 if (!mesh_container->pAdjacency)
1924 goto error;
1925 memcpy(mesh_container->pAdjacency, adjacency, size);
1926 } else {
1927 ok(mesh_data->Type == D3DXMESHTYPE_PATCHMESH, "Unknown mesh type %u\n", mesh_data->Type);
1928 if (mesh_data->Type == D3DXMESHTYPE_PATCHMESH)
1929 trace("FIXME: copying adjacency data for patch mesh not implemented\n");
1933 memcpy(&mesh_container->MeshData, mesh_data, sizeof(*mesh_data));
1934 if (U(*mesh_data).pMesh)
1935 IUnknown_AddRef(U(*mesh_data).pMesh);
1936 if (skin_info) {
1937 mesh_container->pSkinInfo = skin_info;
1938 skin_info->lpVtbl->AddRef(skin_info);
1940 *new_mesh_container = mesh_container;
1942 return S_OK;
1943 error:
1944 destroy_mesh_container(mesh_container);
1945 return E_OUTOFMEMORY;
1948 static ID3DXAllocateHierarchyVtbl ID3DXAllocateHierarchyImpl_Vtbl = {
1949 ID3DXAllocateHierarchyImpl_CreateFrame,
1950 ID3DXAllocateHierarchyImpl_CreateMeshContainer,
1951 ID3DXAllocateHierarchyImpl_DestroyFrame,
1952 ID3DXAllocateHierarchyImpl_DestroyMeshContainer,
1954 static ID3DXAllocateHierarchy alloc_hier = { &ID3DXAllocateHierarchyImpl_Vtbl };
1956 #define test_LoadMeshFromX(device, xfile_str, vertex_array, fvf, index_array, materials_array, check_adjacency) \
1957 test_LoadMeshFromX_(__LINE__, device, xfile_str, sizeof(xfile_str) - 1, vertex_array, ARRAY_SIZE(vertex_array), fvf, \
1958 index_array, ARRAY_SIZE(index_array), sizeof(*index_array), materials_array, ARRAY_SIZE(materials_array), \
1959 check_adjacency);
1960 static void test_LoadMeshFromX_(int line, IDirect3DDevice9 *device, const char *xfile_str, size_t xfile_strlen,
1961 const void *vertices, DWORD num_vertices, DWORD fvf, const void *indices, DWORD num_indices, size_t index_size,
1962 const D3DXMATERIAL *expected_materials, DWORD expected_num_materials, BOOL check_adjacency)
1964 HRESULT hr;
1965 ID3DXBuffer *materials = NULL;
1966 ID3DXBuffer *effects = NULL;
1967 ID3DXBuffer *adjacency = NULL;
1968 ID3DXMesh *mesh = NULL;
1969 DWORD num_materials = 0;
1971 /* Adjacency is not checked when the X file contains multiple meshes,
1972 * since calling GenerateAdjacency on the merged mesh is not equivalent
1973 * to calling GenerateAdjacency on the individual meshes and then merging
1974 * the adjacency data. */
1975 hr = D3DXLoadMeshFromXInMemory(xfile_str, xfile_strlen, D3DXMESH_MANAGED, device,
1976 check_adjacency ? &adjacency : NULL, &materials, &effects, &num_materials, &mesh);
1977 ok_(__FILE__,line)(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
1978 if (SUCCEEDED(hr)) {
1979 D3DXMATERIAL *materials_ptr = materials ? ID3DXBuffer_GetBufferPointer(materials) : NULL;
1980 D3DXEFFECTINSTANCE *effects_ptr = effects ? ID3DXBuffer_GetBufferPointer(effects) : NULL;
1981 DWORD *adjacency_ptr = check_adjacency ? ID3DXBuffer_GetBufferPointer(adjacency) : NULL;
1983 check_vertex_buffer_(line, mesh, vertices, num_vertices, fvf);
1984 check_index_buffer_(line, mesh, indices, num_indices, index_size);
1985 check_materials_(line, materials_ptr, num_materials, expected_materials, expected_num_materials);
1986 check_generated_effects_(line, materials_ptr, num_materials, effects_ptr);
1987 if (check_adjacency)
1988 check_generated_adjacency_(line, mesh, adjacency_ptr, 0.0f);
1990 if (materials) ID3DXBuffer_Release(materials);
1991 if (effects) ID3DXBuffer_Release(effects);
1992 if (adjacency) ID3DXBuffer_Release(adjacency);
1993 IUnknown_Release(mesh);
1997 static void D3DXLoadMeshTest(void)
1999 static const char empty_xfile[] = "xof 0303txt 0032";
2000 /*________________________*/
2001 static const char simple_xfile[] =
2002 "xof 0303txt 0032"
2003 "Mesh {"
2004 "3;"
2005 "0.0; 0.0; 0.0;,"
2006 "0.0; 1.0; 0.0;,"
2007 "1.0; 1.0; 0.0;;"
2008 "1;"
2009 "3; 0, 1, 2;;"
2010 "}";
2011 static const WORD simple_index_buffer[] = {0, 1, 2};
2012 static const D3DXVECTOR3 simple_vertex_buffer[] = {
2013 {0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {1.0, 1.0, 0.0}
2015 const DWORD simple_fvf = D3DFVF_XYZ;
2016 static const char framed_xfile[] =
2017 "xof 0303txt 0032"
2018 "Frame {"
2019 "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;; }"
2020 "FrameTransformMatrix {" /* translation (0.0, 0.0, 2.0) */
2021 "1.0, 0.0, 0.0, 0.0,"
2022 "0.0, 1.0, 0.0, 0.0,"
2023 "0.0, 0.0, 1.0, 0.0,"
2024 "0.0, 0.0, 2.0, 1.0;;"
2026 "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;; }"
2027 "FrameTransformMatrix {" /* translation (0.0, 0.0, 3.0) */
2028 "1.0, 0.0, 0.0, 0.0,"
2029 "0.0, 1.0, 0.0, 0.0,"
2030 "0.0, 0.0, 1.0, 0.0,"
2031 "0.0, 0.0, 3.0, 1.0;;"
2033 "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;; }"
2034 "}";
2035 static const WORD framed_index_buffer[] = { 0, 1, 2 };
2036 static const D3DXVECTOR3 framed_vertex_buffers[3][3] = {
2037 {{0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {1.0, 1.0, 0.0}},
2038 {{0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {2.0, 1.0, 0.0}},
2039 {{0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {3.0, 1.0, 0.0}},
2041 static const WORD merged_index_buffer[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
2042 /* frame transforms accumulates for D3DXLoadMeshFromX */
2043 static const D3DXVECTOR3 merged_vertex_buffer[] = {
2044 {0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {1.0, 1.0, 0.0},
2045 {0.0, 0.0, 2.0}, {0.0, 1.0, 2.0}, {2.0, 1.0, 2.0},
2046 {0.0, 0.0, 5.0}, {0.0, 1.0, 5.0}, {3.0, 1.0, 5.0},
2048 const DWORD framed_fvf = D3DFVF_XYZ;
2049 /*________________________*/
2050 static const char box_xfile[] =
2051 "xof 0303txt 0032"
2052 "Mesh {"
2053 "8;" /* DWORD nVertices; */
2054 /* array Vector vertices[nVertices]; */
2055 "0.0; 0.0; 0.0;,"
2056 "0.0; 0.0; 1.0;,"
2057 "0.0; 1.0; 0.0;,"
2058 "0.0; 1.0; 1.0;,"
2059 "1.0; 0.0; 0.0;,"
2060 "1.0; 0.0; 1.0;,"
2061 "1.0; 1.0; 0.0;,"
2062 "1.0; 1.0; 1.0;;"
2063 "6;" /* DWORD nFaces; */
2064 /* array MeshFace faces[nFaces]; */
2065 "4; 0, 1, 3, 2;," /* (left side) */
2066 "4; 2, 3, 7, 6;," /* (top side) */
2067 "4; 6, 7, 5, 4;," /* (right side) */
2068 "4; 1, 0, 4, 5;," /* (bottom side) */
2069 "4; 1, 5, 7, 3;," /* (back side) */
2070 "4; 0, 2, 6, 4;;" /* (front side) */
2071 "MeshNormals {"
2072 "6;" /* DWORD nNormals; */
2073 /* array Vector normals[nNormals]; */
2074 "-1.0; 0.0; 0.0;,"
2075 "0.0; 1.0; 0.0;,"
2076 "1.0; 0.0; 0.0;,"
2077 "0.0; -1.0; 0.0;,"
2078 "0.0; 0.0; 1.0;,"
2079 "0.0; 0.0; -1.0;;"
2080 "6;" /* DWORD nFaceNormals; */
2081 /* array MeshFace faceNormals[nFaceNormals]; */
2082 "4; 0, 0, 0, 0;,"
2083 "4; 1, 1, 1, 1;,"
2084 "4; 2, 2, 2, 2;,"
2085 "4; 3, 3, 3, 3;,"
2086 "4; 4, 4, 4, 4;,"
2087 "4; 5, 5, 5, 5;;"
2089 "MeshMaterialList materials {"
2090 "2;" /* DWORD nMaterials; */
2091 "6;" /* DWORD nFaceIndexes; */
2092 /* array DWORD faceIndexes[nFaceIndexes]; */
2093 "0, 0, 0, 1, 1, 1;;"
2094 "Material {"
2095 /* ColorRGBA faceColor; */
2096 "0.0; 0.0; 1.0; 1.0;;"
2097 /* FLOAT power; */
2098 "0.5;"
2099 /* ColorRGB specularColor; */
2100 "1.0; 1.0; 1.0;;"
2101 /* ColorRGB emissiveColor; */
2102 "0.0; 0.0; 0.0;;"
2104 "Material {"
2105 /* ColorRGBA faceColor; */
2106 "1.0; 1.0; 1.0; 1.0;;"
2107 /* FLOAT power; */
2108 "1.0;"
2109 /* ColorRGB specularColor; */
2110 "1.0; 1.0; 1.0;;"
2111 /* ColorRGB emissiveColor; */
2112 "0.0; 0.0; 0.0;;"
2113 "TextureFilename { \"texture.jpg\"; }"
2116 "MeshVertexColors {"
2117 "8;" /* DWORD nVertexColors; */
2118 /* array IndexedColor vertexColors[nVertexColors]; */
2119 "0; 0.0; 0.0; 0.0; 0.0;;"
2120 "1; 0.0; 0.0; 1.0; 0.1;;"
2121 "2; 0.0; 1.0; 0.0; 0.2;;"
2122 "3; 0.0; 1.0; 1.0; 0.3;;"
2123 "4; 1.0; 0.0; 0.0; 0.4;;"
2124 "5; 1.0; 0.0; 1.0; 0.5;;"
2125 "6; 1.0; 1.0; 0.0; 0.6;;"
2126 "7; 1.0; 1.0; 1.0; 0.7;;"
2128 "MeshTextureCoords {"
2129 "8;" /* DWORD nTextureCoords; */
2130 /* array Coords2d textureCoords[nTextureCoords]; */
2131 "0.0; 1.0;,"
2132 "1.0; 1.0;,"
2133 "0.0; 0.0;,"
2134 "1.0; 0.0;,"
2135 "1.0; 1.0;,"
2136 "0.0; 1.0;,"
2137 "1.0; 0.0;,"
2138 "0.0; 0.0;;"
2140 "}";
2141 static const WORD box_index_buffer[] = {
2142 0, 1, 3,
2143 0, 3, 2,
2144 8, 9, 7,
2145 8, 7, 6,
2146 10, 11, 5,
2147 10, 5, 4,
2148 12, 13, 14,
2149 12, 14, 15,
2150 16, 17, 18,
2151 16, 18, 19,
2152 20, 21, 22,
2153 20, 22, 23,
2155 static const struct {
2156 D3DXVECTOR3 position;
2157 D3DXVECTOR3 normal;
2158 D3DCOLOR diffuse;
2159 D3DXVECTOR2 tex_coords;
2160 } box_vertex_buffer[] = {
2161 {{0.0, 0.0, 0.0}, {-1.0, 0.0, 0.0}, 0x00000000, {0.0, 1.0}},
2162 {{0.0, 0.0, 1.0}, {-1.0, 0.0, 0.0}, 0x1a0000ff, {1.0, 1.0}},
2163 {{0.0, 1.0, 0.0}, {-1.0, 0.0, 0.0}, 0x3300ff00, {0.0, 0.0}},
2164 {{0.0, 1.0, 1.0}, {-1.0, 0.0, 0.0}, 0x4d00ffff, {1.0, 0.0}},
2165 {{1.0, 0.0, 0.0}, {1.0, 0.0, 0.0}, 0x66ff0000, {1.0, 1.0}},
2166 {{1.0, 0.0, 1.0}, {1.0, 0.0, 0.0}, 0x80ff00ff, {0.0, 1.0}},
2167 {{1.0, 1.0, 0.0}, {0.0, 1.0, 0.0}, 0x99ffff00, {1.0, 0.0}},
2168 {{1.0, 1.0, 1.0}, {0.0, 1.0, 0.0}, 0xb3ffffff, {0.0, 0.0}},
2169 {{0.0, 1.0, 0.0}, {0.0, 1.0, 0.0}, 0x3300ff00, {0.0, 0.0}},
2170 {{0.0, 1.0, 1.0}, {0.0, 1.0, 0.0}, 0x4d00ffff, {1.0, 0.0}},
2171 {{1.0, 1.0, 0.0}, {1.0, 0.0, 0.0}, 0x99ffff00, {1.0, 0.0}},
2172 {{1.0, 1.0, 1.0}, {1.0, 0.0, 0.0}, 0xb3ffffff, {0.0, 0.0}},
2173 {{0.0, 0.0, 1.0}, {0.0, -1.0, 0.0}, 0x1a0000ff, {1.0, 1.0}},
2174 {{0.0, 0.0, 0.0}, {0.0, -1.0, 0.0}, 0x00000000, {0.0, 1.0}},
2175 {{1.0, 0.0, 0.0}, {0.0, -1.0, 0.0}, 0x66ff0000, {1.0, 1.0}},
2176 {{1.0, 0.0, 1.0}, {0.0, -1.0, 0.0}, 0x80ff00ff, {0.0, 1.0}},
2177 {{0.0, 0.0, 1.0}, {0.0, 0.0, 1.0}, 0x1a0000ff, {1.0, 1.0}},
2178 {{1.0, 0.0, 1.0}, {0.0, 0.0, 1.0}, 0x80ff00ff, {0.0, 1.0}},
2179 {{1.0, 1.0, 1.0}, {0.0, 0.0, 1.0}, 0xb3ffffff, {0.0, 0.0}},
2180 {{0.0, 1.0, 1.0}, {0.0, 0.0, 1.0}, 0x4d00ffff, {1.0, 0.0}},
2181 {{0.0, 0.0, 0.0}, {0.0, 0.0, -1.0}, 0x00000000, {0.0, 1.0}},
2182 {{0.0, 1.0, 0.0}, {0.0, 0.0, -1.0}, 0x3300ff00, {0.0, 0.0}},
2183 {{1.0, 1.0, 0.0}, {0.0, 0.0, -1.0}, 0x99ffff00, {1.0, 0.0}},
2184 {{1.0, 0.0, 0.0}, {0.0, 0.0, -1.0}, 0x66ff0000, {1.0, 1.0}},
2186 static const D3DXMATERIAL box_materials[] = {
2189 {0.0, 0.0, 1.0, 1.0}, /* Diffuse */
2190 {0.0, 0.0, 0.0, 1.0}, /* Ambient */
2191 {1.0, 1.0, 1.0, 1.0}, /* Specular */
2192 {0.0, 0.0, 0.0, 1.0}, /* Emissive */
2193 0.5, /* Power */
2195 NULL, /* pTextureFilename */
2199 {1.0, 1.0, 1.0, 1.0}, /* Diffuse */
2200 {0.0, 0.0, 0.0, 1.0}, /* Ambient */
2201 {1.0, 1.0, 1.0, 1.0}, /* Specular */
2202 {0.0, 0.0, 0.0, 1.0}, /* Emissive */
2203 1.0, /* Power */
2205 (char *)"texture.jpg", /* pTextureFilename */
2208 const DWORD box_fvf = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_TEX1;
2209 /*________________________*/
2210 static const D3DXMATERIAL default_materials[] = {
2213 {0.5, 0.5, 0.5, 0.0}, /* Diffuse */
2214 {0.0, 0.0, 0.0, 0.0}, /* Ambient */
2215 {0.5, 0.5, 0.5, 0.0}, /* Specular */
2216 {0.0, 0.0, 0.0, 0.0}, /* Emissive */
2217 0.0, /* Power */
2219 NULL, /* pTextureFilename */
2222 HRESULT hr;
2223 IDirect3DDevice9 *device = NULL;
2224 ID3DXMesh *mesh = NULL;
2225 D3DXFRAME *frame_hier = NULL;
2226 D3DXMATRIX transform;
2227 struct test_context *test_context;
2229 if (!(test_context = new_test_context()))
2231 skip("Couldn't create test context\n");
2232 return;
2234 device = test_context->device;
2236 hr = D3DXLoadMeshHierarchyFromXInMemory(NULL, sizeof(simple_xfile) - 1,
2237 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
2238 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2240 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, 0,
2241 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
2242 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2244 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1,
2245 D3DXMESH_MANAGED, NULL, &alloc_hier, NULL, &frame_hier, NULL);
2246 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2248 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1,
2249 D3DXMESH_MANAGED, device, NULL, NULL, &frame_hier, NULL);
2250 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2252 hr = D3DXLoadMeshHierarchyFromXInMemory(empty_xfile, sizeof(empty_xfile) - 1,
2253 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
2254 ok(hr == E_FAIL, "Expected E_FAIL, got %#x\n", hr);
2256 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1,
2257 D3DXMESH_MANAGED, device, &alloc_hier, NULL, NULL, NULL);
2258 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2260 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1,
2261 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
2262 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2263 if (SUCCEEDED(hr)) {
2264 D3DXMESHCONTAINER *container = frame_hier->pMeshContainer;
2266 ok(frame_hier->Name == NULL, "Expected NULL, got '%s'\n", frame_hier->Name);
2267 D3DXMatrixIdentity(&transform);
2268 check_matrix(&frame_hier->TransformationMatrix, &transform);
2270 ok(!strcmp(container->Name, ""), "Expected '', got '%s'\n", container->Name);
2271 ok(container->MeshData.Type == D3DXMESHTYPE_MESH, "Expected %d, got %d\n",
2272 D3DXMESHTYPE_MESH, container->MeshData.Type);
2273 mesh = U(container->MeshData).pMesh;
2274 check_vertex_buffer(mesh, simple_vertex_buffer, ARRAY_SIZE(simple_vertex_buffer), simple_fvf);
2275 check_index_buffer(mesh, simple_index_buffer, ARRAY_SIZE(simple_index_buffer), sizeof(*simple_index_buffer));
2276 check_materials(container->pMaterials, container->NumMaterials, NULL, 0);
2277 check_generated_effects(container->pMaterials, container->NumMaterials, container->pEffects);
2278 check_generated_adjacency(mesh, container->pAdjacency, 0.0f);
2279 hr = D3DXFrameDestroy(frame_hier, &alloc_hier);
2280 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2281 frame_hier = NULL;
2284 hr = D3DXLoadMeshHierarchyFromXInMemory(box_xfile, sizeof(box_xfile) - 1,
2285 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
2286 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2287 if (SUCCEEDED(hr)) {
2288 D3DXMESHCONTAINER *container = frame_hier->pMeshContainer;
2290 ok(frame_hier->Name == NULL, "Expected NULL, got '%s'\n", frame_hier->Name);
2291 D3DXMatrixIdentity(&transform);
2292 check_matrix(&frame_hier->TransformationMatrix, &transform);
2294 ok(!strcmp(container->Name, ""), "Expected '', got '%s'\n", container->Name);
2295 ok(container->MeshData.Type == D3DXMESHTYPE_MESH, "Expected %d, got %d\n",
2296 D3DXMESHTYPE_MESH, container->MeshData.Type);
2297 mesh = U(container->MeshData).pMesh;
2298 check_vertex_buffer(mesh, box_vertex_buffer, ARRAY_SIZE(box_vertex_buffer), box_fvf);
2299 check_index_buffer(mesh, box_index_buffer, ARRAY_SIZE(box_index_buffer), sizeof(*box_index_buffer));
2300 check_materials(container->pMaterials, container->NumMaterials, box_materials, ARRAY_SIZE(box_materials));
2301 check_generated_effects(container->pMaterials, container->NumMaterials, container->pEffects);
2302 check_generated_adjacency(mesh, container->pAdjacency, 0.0f);
2303 hr = D3DXFrameDestroy(frame_hier, &alloc_hier);
2304 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2305 frame_hier = NULL;
2308 hr = D3DXLoadMeshHierarchyFromXInMemory(framed_xfile, sizeof(framed_xfile) - 1,
2309 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
2310 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2311 if (SUCCEEDED(hr)) {
2312 D3DXMESHCONTAINER *container = frame_hier->pMeshContainer;
2313 int i;
2315 ok(!strcmp(frame_hier->Name, ""), "Expected '', got '%s'\n", frame_hier->Name);
2316 /* last frame transform replaces the first */
2317 D3DXMatrixIdentity(&transform);
2318 U(transform).m[3][2] = 3.0;
2319 check_matrix(&frame_hier->TransformationMatrix, &transform);
2321 for (i = 0; i < 3; i++) {
2322 ok(!strcmp(container->Name, ""), "Expected '', got '%s'\n", container->Name);
2323 ok(container->MeshData.Type == D3DXMESHTYPE_MESH, "Expected %d, got %d\n",
2324 D3DXMESHTYPE_MESH, container->MeshData.Type);
2325 mesh = U(container->MeshData).pMesh;
2326 check_vertex_buffer(mesh, framed_vertex_buffers[i], ARRAY_SIZE(framed_vertex_buffers[0]), framed_fvf);
2327 check_index_buffer(mesh, framed_index_buffer, ARRAY_SIZE(framed_index_buffer), sizeof(*framed_index_buffer));
2328 check_materials(container->pMaterials, container->NumMaterials, NULL, 0);
2329 check_generated_effects(container->pMaterials, container->NumMaterials, container->pEffects);
2330 check_generated_adjacency(mesh, container->pAdjacency, 0.0f);
2331 container = container->pNextMeshContainer;
2333 ok(container == NULL, "Expected NULL, got %p\n", container);
2334 hr = D3DXFrameDestroy(frame_hier, &alloc_hier);
2335 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2336 frame_hier = NULL;
2340 hr = D3DXLoadMeshFromXInMemory(NULL, 0, D3DXMESH_MANAGED,
2341 device, NULL, NULL, NULL, NULL, &mesh);
2342 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2344 hr = D3DXLoadMeshFromXInMemory(NULL, sizeof(simple_xfile) - 1, D3DXMESH_MANAGED,
2345 device, NULL, NULL, NULL, NULL, &mesh);
2346 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2348 hr = D3DXLoadMeshFromXInMemory(simple_xfile, 0, D3DXMESH_MANAGED,
2349 device, NULL, NULL, NULL, NULL, &mesh);
2350 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2352 hr = D3DXLoadMeshFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1, D3DXMESH_MANAGED,
2353 device, NULL, NULL, NULL, NULL, NULL);
2354 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2356 hr = D3DXLoadMeshFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1, D3DXMESH_MANAGED,
2357 NULL, NULL, NULL, NULL, NULL, &mesh);
2358 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2360 hr = D3DXLoadMeshFromXInMemory(empty_xfile, sizeof(empty_xfile) - 1, D3DXMESH_MANAGED,
2361 device, NULL, NULL, NULL, NULL, &mesh);
2362 ok(hr == E_FAIL, "Expected E_FAIL, got %#x\n", hr);
2364 hr = D3DXLoadMeshFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1, D3DXMESH_MANAGED,
2365 device, NULL, NULL, NULL, NULL, &mesh);
2366 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2367 if (SUCCEEDED(hr))
2368 IUnknown_Release(mesh);
2370 test_LoadMeshFromX(device, simple_xfile, simple_vertex_buffer, simple_fvf, simple_index_buffer, default_materials, TRUE);
2371 test_LoadMeshFromX(device, box_xfile, box_vertex_buffer, box_fvf, box_index_buffer, box_materials, TRUE);
2372 test_LoadMeshFromX(device, framed_xfile, merged_vertex_buffer, framed_fvf, merged_index_buffer, default_materials, FALSE);
2374 free_test_context(test_context);
2377 static BOOL compute_box(struct mesh *mesh, float width, float height, float depth)
2379 unsigned int i, face;
2380 static const D3DXVECTOR3 unit_box[] =
2382 {-1.0f, -1.0f, -1.0f}, {-1.0f, -1.0f, 1.0f}, {-1.0f, 1.0f, 1.0f}, {-1.0f, 1.0f, -1.0f},
2383 {-1.0f, 1.0f, -1.0f}, {-1.0f, 1.0f, 1.0f}, { 1.0f, 1.0f, 1.0f}, { 1.0f, 1.0f, -1.0f},
2384 { 1.0f, 1.0f, -1.0f}, { 1.0f, 1.0f, 1.0f}, { 1.0f, -1.0f, 1.0f}, { 1.0f, -1.0f, -1.0f},
2385 {-1.0f, -1.0f, 1.0f}, {-1.0f, -1.0f, -1.0f}, { 1.0f, -1.0f, -1.0f}, { 1.0f, -1.0f, 1.0f},
2386 {-1.0f, -1.0f, 1.0f}, { 1.0f, -1.0f, 1.0f}, { 1.0f, 1.0f, 1.0f}, {-1.0f, 1.0f, 1.0f},
2387 {-1.0f, -1.0f, -1.0f}, {-1.0f, 1.0f, -1.0f}, { 1.0f, 1.0f, -1.0f}, { 1.0f, -1.0f, -1.0f}
2389 static const D3DXVECTOR3 normals[] =
2391 {-1.0f, 0.0f, 0.0f}, { 0.0f, 1.0f, 0.0f}, { 1.0f, 0.0f, 0.0f},
2392 { 0.0f, -1.0f, 0.0f}, { 0.0f, 0.0f, 1.0f}, { 0.0f, 0.0f, -1.0f}
2395 if (!new_mesh(mesh, 24, 12))
2397 return FALSE;
2400 width /= 2.0f;
2401 height /= 2.0f;
2402 depth /= 2.0f;
2404 for (i = 0; i < 24; i++)
2406 mesh->vertices[i].position.x = width * unit_box[i].x;
2407 mesh->vertices[i].position.y = height * unit_box[i].y;
2408 mesh->vertices[i].position.z = depth * unit_box[i].z;
2409 mesh->vertices[i].normal.x = normals[i / 4].x;
2410 mesh->vertices[i].normal.y = normals[i / 4].y;
2411 mesh->vertices[i].normal.z = normals[i / 4].z;
2414 face = 0;
2415 for (i = 0; i < 12; i++)
2417 mesh->faces[i][0] = face++;
2418 mesh->faces[i][1] = face++;
2419 mesh->faces[i][2] = (i % 2) ? face - 4 : face;
2422 return TRUE;
2425 static void test_box(IDirect3DDevice9 *device, float width, float height, float depth)
2427 HRESULT hr;
2428 ID3DXMesh *box;
2429 struct mesh mesh;
2430 char name[256];
2432 hr = D3DXCreateBox(device, width, height, depth, &box, NULL);
2433 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
2434 if (hr != D3D_OK)
2436 skip("Couldn't create box\n");
2437 return;
2440 if (!compute_box(&mesh, width, height, depth))
2442 skip("Couldn't create mesh\n");
2443 box->lpVtbl->Release(box);
2444 return;
2447 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
2449 sprintf(name, "box (%g, %g, %g)", width, height, depth);
2450 compare_mesh(name, box, &mesh);
2452 free_mesh(&mesh);
2454 box->lpVtbl->Release(box);
2456 static void D3DXCreateBoxTest(void)
2458 HRESULT hr;
2459 IDirect3DDevice9* device;
2460 ID3DXMesh* box;
2461 ID3DXBuffer* ppBuffer;
2462 DWORD *buffer;
2463 static const DWORD adjacency[36]=
2464 {6, 9, 1, 2, 10, 0,
2465 1, 9, 3, 4, 10, 2,
2466 3, 8, 5, 7, 11, 4,
2467 0, 11, 7, 5, 8, 6,
2468 7, 4, 9, 2, 0, 8,
2469 1, 3, 11, 5, 6, 10};
2470 unsigned int i;
2471 struct test_context *test_context;
2473 if (!(test_context = new_test_context()))
2475 skip("Couldn't create test context\n");
2476 return;
2478 device = test_context->device;
2480 hr = D3DXCreateBox(device,2.0f,20.0f,4.9f,NULL, &ppBuffer);
2481 ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2483 hr = D3DXCreateBox(NULL,22.0f,20.0f,4.9f,&box, &ppBuffer);
2484 ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2486 hr = D3DXCreateBox(device,-2.0f,20.0f,4.9f,&box, &ppBuffer);
2487 ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2489 hr = D3DXCreateBox(device,22.0f,-20.0f,4.9f,&box, &ppBuffer);
2490 ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2492 hr = D3DXCreateBox(device,22.0f,20.0f,-4.9f,&box, &ppBuffer);
2493 ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2495 ppBuffer = NULL;
2496 hr = D3DXCreateBox(device,10.9f,20.0f,4.9f,&box, &ppBuffer);
2497 ok(hr==D3D_OK, "Expected D3D_OK, received %#x\n", hr);
2499 buffer = ID3DXBuffer_GetBufferPointer(ppBuffer);
2500 for(i=0; i<36; i++)
2501 ok(adjacency[i]==buffer[i], "expected adjacency %d: %#x, received %#x\n",i,adjacency[i], buffer[i]);
2503 box->lpVtbl->Release(box);
2504 ID3DXBuffer_Release(ppBuffer);
2506 test_box(device, 10.9f, 20.0f, 4.9f);
2508 free_test_context(test_context);
2511 static BOOL compute_polygon(struct mesh *mesh, float length, unsigned int sides)
2513 unsigned int i;
2514 float scale;
2516 if (!new_mesh(mesh, sides + 1, sides))
2517 return FALSE;
2519 scale = 0.5f * length / sinf(D3DX_PI / sides);
2521 mesh->vertices[0].position.x = 0.0f;
2522 mesh->vertices[0].position.y = 0.0f;
2523 mesh->vertices[0].position.z = 0.0f;
2524 mesh->vertices[0].normal.x = 0.0f;
2525 mesh->vertices[0].normal.y = 0.0f;
2526 mesh->vertices[0].normal.z = 1.0f;
2528 for (i = 0; i < sides; ++i)
2530 mesh->vertices[i + 1].position.x = cosf(2.0f * D3DX_PI * i / sides) * scale;
2531 mesh->vertices[i + 1].position.y = sinf(2.0f * D3DX_PI * i / sides) * scale;
2532 mesh->vertices[i + 1].position.z = 0.0f;
2533 mesh->vertices[i + 1].normal.x = 0.0f;
2534 mesh->vertices[i + 1].normal.y = 0.0f;
2535 mesh->vertices[i + 1].normal.z = 1.0f;
2537 mesh->faces[i][0] = 0;
2538 mesh->faces[i][1] = i + 1;
2539 mesh->faces[i][2] = i + 2;
2542 mesh->faces[sides - 1][2] = 1;
2544 return TRUE;
2547 static void test_polygon(IDirect3DDevice9 *device, float length, unsigned int sides)
2549 HRESULT hr;
2550 ID3DXMesh *polygon;
2551 struct mesh mesh;
2552 char name[64];
2554 hr = D3DXCreatePolygon(device, length, sides, &polygon, NULL);
2555 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
2556 if (hr != D3D_OK)
2558 skip("Couldn't create polygon\n");
2559 return;
2562 if (!compute_polygon(&mesh, length, sides))
2564 skip("Couldn't create mesh\n");
2565 polygon->lpVtbl->Release(polygon);
2566 return;
2569 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
2571 sprintf(name, "polygon (%g, %d)", length, sides);
2572 compare_mesh(name, polygon, &mesh);
2574 free_mesh(&mesh);
2576 polygon->lpVtbl->Release(polygon);
2579 static void D3DXCreatePolygonTest(void)
2581 HRESULT hr;
2582 IDirect3DDevice9 *device;
2583 ID3DXMesh *polygon;
2584 ID3DXBuffer *adjacency;
2585 DWORD (*buffer)[3], buffer_size;
2586 unsigned int i;
2587 struct test_context *test_context;
2589 if (!(test_context = new_test_context()))
2591 skip("Couldn't create test context\n");
2592 return;
2594 device = test_context->device;
2596 hr = D3DXCreatePolygon(device, 2.0f, 11, NULL, &adjacency);
2597 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2599 hr = D3DXCreatePolygon(NULL, 2.0f, 11, &polygon, &adjacency);
2600 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2602 hr = D3DXCreatePolygon(device, -2.0f, 11, &polygon, &adjacency);
2603 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2605 polygon = (void *)0xdeadbeef;
2606 adjacency = (void *)0xdeadbeef;
2607 hr = D3DXCreatePolygon(device, 2.0f, 0, &polygon, &adjacency);
2608 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2609 ok(polygon == (void *)0xdeadbeef, "Polygon was changed to %p\n", polygon);
2610 ok(adjacency == (void *)0xdeadbeef, "Adjacency was changed to %p\n", adjacency);
2612 hr = D3DXCreatePolygon(device, 2.0f, 2, &polygon, &adjacency);
2613 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2615 adjacency = NULL;
2616 hr = D3DXCreatePolygon(device, 3.0f, 11, &polygon, &adjacency);
2617 ok(hr == D3D_OK, "Expected D3D_OK, received %#x\n", hr);
2619 buffer_size = ID3DXBuffer_GetBufferSize(adjacency);
2620 ok(buffer_size == 33 * sizeof(DWORD), "Wrong adjacency buffer size %u\n", buffer_size);
2622 buffer = ID3DXBuffer_GetBufferPointer(adjacency);
2623 for (i = 0; i < 11; ++i)
2625 ok(buffer[i][0] == (i + 10) % 11, "Wrong adjacency[%d][0] = %u\n", i, buffer[i][0]);
2626 ok(buffer[i][1] == ~0U, "Wrong adjacency[%d][1] = %u\n", i, buffer[i][1]);
2627 ok(buffer[i][2] == (i + 1) % 11, "Wrong adjacency[%d][2] = %u\n", i, buffer[i][2]);
2630 polygon->lpVtbl->Release(polygon);
2631 ID3DXBuffer_Release(adjacency);
2633 test_polygon(device, 2.0f, 3);
2634 test_polygon(device, 10.0f, 3);
2635 test_polygon(device, 10.0f, 5);
2636 test_polygon(device, 10.0f, 10);
2637 test_polygon(device, 20.0f, 10);
2639 free_test_context(test_context);
2642 struct sincos_table
2644 float *sin;
2645 float *cos;
2648 static void free_sincos_table(struct sincos_table *sincos_table)
2650 HeapFree(GetProcessHeap(), 0, sincos_table->cos);
2651 HeapFree(GetProcessHeap(), 0, sincos_table->sin);
2654 /* pre compute sine and cosine tables; caller must free */
2655 static BOOL compute_sincos_table(struct sincos_table *sincos_table, float angle_start, float angle_step, int n)
2657 float angle;
2658 int i;
2660 sincos_table->sin = HeapAlloc(GetProcessHeap(), 0, n * sizeof(*sincos_table->sin));
2661 if (!sincos_table->sin)
2663 return FALSE;
2665 sincos_table->cos = HeapAlloc(GetProcessHeap(), 0, n * sizeof(*sincos_table->cos));
2666 if (!sincos_table->cos)
2668 HeapFree(GetProcessHeap(), 0, sincos_table->sin);
2669 return FALSE;
2672 angle = angle_start;
2673 for (i = 0; i < n; i++)
2675 sincos_table->sin[i] = sin(angle);
2676 sincos_table->cos[i] = cos(angle);
2677 angle += angle_step;
2680 return TRUE;
2683 static WORD vertex_index(UINT slices, int slice, int stack)
2685 return stack*slices+slice+1;
2688 /* slices = subdivisions along xy plane, stacks = subdivisions along z axis */
2689 static BOOL compute_sphere(struct mesh *mesh, FLOAT radius, UINT slices, UINT stacks)
2691 float theta_step, theta_start;
2692 struct sincos_table theta;
2693 float phi_step, phi_start;
2694 struct sincos_table phi;
2695 DWORD number_of_vertices, number_of_faces;
2696 DWORD vertex, face;
2697 int slice, stack;
2699 /* theta = angle on xy plane wrt x axis */
2700 theta_step = D3DX_PI / stacks;
2701 theta_start = theta_step;
2703 /* phi = angle on xz plane wrt z axis */
2704 phi_step = -2 * D3DX_PI / slices;
2705 phi_start = D3DX_PI / 2;
2707 if (!compute_sincos_table(&theta, theta_start, theta_step, stacks))
2709 return FALSE;
2711 if (!compute_sincos_table(&phi, phi_start, phi_step, slices))
2713 free_sincos_table(&theta);
2714 return FALSE;
2717 number_of_vertices = 2 + slices * (stacks-1);
2718 number_of_faces = 2 * slices + (stacks - 2) * (2 * slices);
2720 if (!new_mesh(mesh, number_of_vertices, number_of_faces))
2722 free_sincos_table(&phi);
2723 free_sincos_table(&theta);
2724 return FALSE;
2727 vertex = 0;
2728 face = 0;
2730 mesh->vertices[vertex].normal.x = 0.0f;
2731 mesh->vertices[vertex].normal.y = 0.0f;
2732 mesh->vertices[vertex].normal.z = 1.0f;
2733 mesh->vertices[vertex].position.x = 0.0f;
2734 mesh->vertices[vertex].position.y = 0.0f;
2735 mesh->vertices[vertex].position.z = radius;
2736 vertex++;
2738 for (stack = 0; stack < stacks - 1; stack++)
2740 for (slice = 0; slice < slices; slice++)
2742 mesh->vertices[vertex].normal.x = theta.sin[stack] * phi.cos[slice];
2743 mesh->vertices[vertex].normal.y = theta.sin[stack] * phi.sin[slice];
2744 mesh->vertices[vertex].normal.z = theta.cos[stack];
2745 mesh->vertices[vertex].position.x = radius * theta.sin[stack] * phi.cos[slice];
2746 mesh->vertices[vertex].position.y = radius * theta.sin[stack] * phi.sin[slice];
2747 mesh->vertices[vertex].position.z = radius * theta.cos[stack];
2748 vertex++;
2750 if (slice > 0)
2752 if (stack == 0)
2754 /* top stack is triangle fan */
2755 mesh->faces[face][0] = 0;
2756 mesh->faces[face][1] = slice + 1;
2757 mesh->faces[face][2] = slice;
2758 face++;
2760 else
2762 /* stacks in between top and bottom are quad strips */
2763 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
2764 mesh->faces[face][1] = vertex_index(slices, slice, stack-1);
2765 mesh->faces[face][2] = vertex_index(slices, slice-1, stack);
2766 face++;
2768 mesh->faces[face][0] = vertex_index(slices, slice, stack-1);
2769 mesh->faces[face][1] = vertex_index(slices, slice, stack);
2770 mesh->faces[face][2] = vertex_index(slices, slice-1, stack);
2771 face++;
2776 if (stack == 0)
2778 mesh->faces[face][0] = 0;
2779 mesh->faces[face][1] = 1;
2780 mesh->faces[face][2] = slice;
2781 face++;
2783 else
2785 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
2786 mesh->faces[face][1] = vertex_index(slices, 0, stack-1);
2787 mesh->faces[face][2] = vertex_index(slices, slice-1, stack);
2788 face++;
2790 mesh->faces[face][0] = vertex_index(slices, 0, stack-1);
2791 mesh->faces[face][1] = vertex_index(slices, 0, stack);
2792 mesh->faces[face][2] = vertex_index(slices, slice-1, stack);
2793 face++;
2797 mesh->vertices[vertex].position.x = 0.0f;
2798 mesh->vertices[vertex].position.y = 0.0f;
2799 mesh->vertices[vertex].position.z = -radius;
2800 mesh->vertices[vertex].normal.x = 0.0f;
2801 mesh->vertices[vertex].normal.y = 0.0f;
2802 mesh->vertices[vertex].normal.z = -1.0f;
2804 /* bottom stack is triangle fan */
2805 for (slice = 1; slice < slices; slice++)
2807 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
2808 mesh->faces[face][1] = vertex_index(slices, slice, stack-1);
2809 mesh->faces[face][2] = vertex;
2810 face++;
2813 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
2814 mesh->faces[face][1] = vertex_index(slices, 0, stack-1);
2815 mesh->faces[face][2] = vertex;
2817 free_sincos_table(&phi);
2818 free_sincos_table(&theta);
2820 return TRUE;
2823 static void test_sphere(IDirect3DDevice9 *device, FLOAT radius, UINT slices, UINT stacks)
2825 HRESULT hr;
2826 ID3DXMesh *sphere;
2827 struct mesh mesh;
2828 char name[256];
2830 hr = D3DXCreateSphere(device, radius, slices, stacks, &sphere, NULL);
2831 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
2832 if (hr != D3D_OK)
2834 skip("Couldn't create sphere\n");
2835 return;
2838 if (!compute_sphere(&mesh, radius, slices, stacks))
2840 skip("Couldn't create mesh\n");
2841 sphere->lpVtbl->Release(sphere);
2842 return;
2845 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
2847 sprintf(name, "sphere (%g, %u, %u)", radius, slices, stacks);
2848 compare_mesh(name, sphere, &mesh);
2850 free_mesh(&mesh);
2852 sphere->lpVtbl->Release(sphere);
2855 static void D3DXCreateSphereTest(void)
2857 HRESULT hr;
2858 IDirect3DDevice9* device;
2859 ID3DXMesh* sphere = NULL;
2860 struct test_context *test_context;
2862 hr = D3DXCreateSphere(NULL, 0.0f, 0, 0, NULL, NULL);
2863 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
2865 hr = D3DXCreateSphere(NULL, 0.1f, 0, 0, NULL, NULL);
2866 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
2868 hr = D3DXCreateSphere(NULL, 0.0f, 1, 0, NULL, NULL);
2869 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
2871 hr = D3DXCreateSphere(NULL, 0.0f, 0, 1, NULL, NULL);
2872 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
2874 if (!(test_context = new_test_context()))
2876 skip("Couldn't create test context\n");
2877 return;
2879 device = test_context->device;
2881 hr = D3DXCreateSphere(device, 1.0f, 1, 1, &sphere, NULL);
2882 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
2884 hr = D3DXCreateSphere(device, 1.0f, 2, 1, &sphere, NULL);
2885 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
2887 hr = D3DXCreateSphere(device, 1.0f, 1, 2, &sphere, NULL);
2888 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
2890 hr = D3DXCreateSphere(device, -0.1f, 1, 2, &sphere, NULL);
2891 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
2893 test_sphere(device, 0.0f, 2, 2);
2894 test_sphere(device, 1.0f, 2, 2);
2895 test_sphere(device, 1.0f, 3, 2);
2896 test_sphere(device, 1.0f, 4, 4);
2897 test_sphere(device, 1.0f, 3, 4);
2898 test_sphere(device, 5.0f, 6, 7);
2899 test_sphere(device, 10.0f, 11, 12);
2901 free_test_context(test_context);
2904 static BOOL compute_cylinder(struct mesh *mesh, FLOAT radius1, FLOAT radius2, FLOAT length, UINT slices, UINT stacks)
2906 float theta_step, theta_start;
2907 struct sincos_table theta;
2908 FLOAT delta_radius, radius, radius_step;
2909 FLOAT z, z_step, z_normal;
2910 DWORD number_of_vertices, number_of_faces;
2911 DWORD vertex, face;
2912 int slice, stack;
2914 /* theta = angle on xy plane wrt x axis */
2915 theta_step = -2 * D3DX_PI / slices;
2916 theta_start = D3DX_PI / 2;
2918 if (!compute_sincos_table(&theta, theta_start, theta_step, slices))
2920 return FALSE;
2923 number_of_vertices = 2 + (slices * (3 + stacks));
2924 number_of_faces = 2 * slices + stacks * (2 * slices);
2926 if (!new_mesh(mesh, number_of_vertices, number_of_faces))
2928 free_sincos_table(&theta);
2929 return FALSE;
2932 vertex = 0;
2933 face = 0;
2935 delta_radius = radius1 - radius2;
2936 radius = radius1;
2937 radius_step = delta_radius / stacks;
2939 z = -length / 2;
2940 z_step = length / stacks;
2941 z_normal = delta_radius / length;
2942 if (isnan(z_normal))
2944 z_normal = 0.0f;
2947 mesh->vertices[vertex].normal.x = 0.0f;
2948 mesh->vertices[vertex].normal.y = 0.0f;
2949 mesh->vertices[vertex].normal.z = -1.0f;
2950 mesh->vertices[vertex].position.x = 0.0f;
2951 mesh->vertices[vertex].position.y = 0.0f;
2952 mesh->vertices[vertex++].position.z = z;
2954 for (slice = 0; slice < slices; slice++, vertex++)
2956 mesh->vertices[vertex].normal.x = 0.0f;
2957 mesh->vertices[vertex].normal.y = 0.0f;
2958 mesh->vertices[vertex].normal.z = -1.0f;
2959 mesh->vertices[vertex].position.x = radius * theta.cos[slice];
2960 mesh->vertices[vertex].position.y = radius * theta.sin[slice];
2961 mesh->vertices[vertex].position.z = z;
2963 if (slice > 0)
2965 mesh->faces[face][0] = 0;
2966 mesh->faces[face][1] = slice;
2967 mesh->faces[face++][2] = slice + 1;
2971 mesh->faces[face][0] = 0;
2972 mesh->faces[face][1] = slice;
2973 mesh->faces[face++][2] = 1;
2975 for (stack = 1; stack <= stacks+1; stack++)
2977 for (slice = 0; slice < slices; slice++, vertex++)
2979 mesh->vertices[vertex].normal.x = theta.cos[slice];
2980 mesh->vertices[vertex].normal.y = theta.sin[slice];
2981 mesh->vertices[vertex].normal.z = z_normal;
2982 D3DXVec3Normalize(&mesh->vertices[vertex].normal, &mesh->vertices[vertex].normal);
2983 mesh->vertices[vertex].position.x = radius * theta.cos[slice];
2984 mesh->vertices[vertex].position.y = radius * theta.sin[slice];
2985 mesh->vertices[vertex].position.z = z;
2987 if (stack > 1 && slice > 0)
2989 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
2990 mesh->faces[face][1] = vertex_index(slices, slice-1, stack);
2991 mesh->faces[face++][2] = vertex_index(slices, slice, stack-1);
2993 mesh->faces[face][0] = vertex_index(slices, slice, stack-1);
2994 mesh->faces[face][1] = vertex_index(slices, slice-1, stack);
2995 mesh->faces[face++][2] = vertex_index(slices, slice, stack);
2999 if (stack > 1)
3001 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
3002 mesh->faces[face][1] = vertex_index(slices, slice-1, stack);
3003 mesh->faces[face++][2] = vertex_index(slices, 0, stack-1);
3005 mesh->faces[face][0] = vertex_index(slices, 0, stack-1);
3006 mesh->faces[face][1] = vertex_index(slices, slice-1, stack);
3007 mesh->faces[face++][2] = vertex_index(slices, 0, stack);
3010 if (stack < stacks + 1)
3012 z += z_step;
3013 radius -= radius_step;
3017 for (slice = 0; slice < slices; slice++, vertex++)
3019 mesh->vertices[vertex].normal.x = 0.0f;
3020 mesh->vertices[vertex].normal.y = 0.0f;
3021 mesh->vertices[vertex].normal.z = 1.0f;
3022 mesh->vertices[vertex].position.x = radius * theta.cos[slice];
3023 mesh->vertices[vertex].position.y = radius * theta.sin[slice];
3024 mesh->vertices[vertex].position.z = z;
3026 if (slice > 0)
3028 mesh->faces[face][0] = vertex_index(slices, slice-1, stack);
3029 mesh->faces[face][1] = number_of_vertices - 1;
3030 mesh->faces[face++][2] = vertex_index(slices, slice, stack);
3034 mesh->vertices[vertex].position.x = 0.0f;
3035 mesh->vertices[vertex].position.y = 0.0f;
3036 mesh->vertices[vertex].position.z = z;
3037 mesh->vertices[vertex].normal.x = 0.0f;
3038 mesh->vertices[vertex].normal.y = 0.0f;
3039 mesh->vertices[vertex].normal.z = 1.0f;
3041 mesh->faces[face][0] = vertex_index(slices, slice-1, stack);
3042 mesh->faces[face][1] = number_of_vertices - 1;
3043 mesh->faces[face][2] = vertex_index(slices, 0, stack);
3045 free_sincos_table(&theta);
3047 return TRUE;
3050 static void test_cylinder(IDirect3DDevice9 *device, FLOAT radius1, FLOAT radius2, FLOAT length, UINT slices, UINT stacks)
3052 HRESULT hr;
3053 ID3DXMesh *cylinder;
3054 struct mesh mesh;
3055 char name[256];
3057 hr = D3DXCreateCylinder(device, radius1, radius2, length, slices, stacks, &cylinder, NULL);
3058 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
3059 if (hr != D3D_OK)
3061 skip("Couldn't create cylinder\n");
3062 return;
3065 if (!compute_cylinder(&mesh, radius1, radius2, length, slices, stacks))
3067 skip("Couldn't create mesh\n");
3068 cylinder->lpVtbl->Release(cylinder);
3069 return;
3072 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
3074 sprintf(name, "cylinder (%g, %g, %g, %u, %u)", radius1, radius2, length, slices, stacks);
3075 compare_mesh(name, cylinder, &mesh);
3077 free_mesh(&mesh);
3079 cylinder->lpVtbl->Release(cylinder);
3082 static void D3DXCreateCylinderTest(void)
3084 HRESULT hr;
3085 IDirect3DDevice9* device;
3086 ID3DXMesh* cylinder = NULL;
3087 struct test_context *test_context;
3089 hr = D3DXCreateCylinder(NULL, 0.0f, 0.0f, 0.0f, 0, 0, NULL, NULL);
3090 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3092 hr = D3DXCreateCylinder(NULL, 1.0f, 1.0f, 1.0f, 2, 1, &cylinder, NULL);
3093 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3095 if (!(test_context = new_test_context()))
3097 skip("Couldn't create test context\n");
3098 return;
3100 device = test_context->device;
3102 hr = D3DXCreateCylinder(device, -0.1f, 1.0f, 1.0f, 2, 1, &cylinder, NULL);
3103 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3105 hr = D3DXCreateCylinder(device, 0.0f, 1.0f, 1.0f, 2, 1, &cylinder, NULL);
3106 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n",hr);
3108 if (SUCCEEDED(hr) && cylinder)
3110 cylinder->lpVtbl->Release(cylinder);
3113 hr = D3DXCreateCylinder(device, 1.0f, -0.1f, 1.0f, 2, 1, &cylinder, NULL);
3114 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3116 hr = D3DXCreateCylinder(device, 1.0f, 0.0f, 1.0f, 2, 1, &cylinder, NULL);
3117 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n",hr);
3119 if (SUCCEEDED(hr) && cylinder)
3121 cylinder->lpVtbl->Release(cylinder);
3124 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, -0.1f, 2, 1, &cylinder, NULL);
3125 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3127 /* Test with length == 0.0f succeeds */
3128 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, 0.0f, 2, 1, &cylinder, NULL);
3129 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n",hr);
3131 if (SUCCEEDED(hr) && cylinder)
3133 cylinder->lpVtbl->Release(cylinder);
3136 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, 1.0f, 1, 1, &cylinder, NULL);
3137 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3139 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, 1.0f, 2, 0, &cylinder, NULL);
3140 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3142 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, 1.0f, 2, 1, NULL, NULL);
3143 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3145 test_cylinder(device, 0.0f, 0.0f, 0.0f, 2, 1);
3146 test_cylinder(device, 1.0f, 1.0f, 1.0f, 2, 1);
3147 test_cylinder(device, 1.0f, 1.0f, 2.0f, 3, 4);
3148 test_cylinder(device, 3.0f, 2.0f, 4.0f, 3, 4);
3149 test_cylinder(device, 2.0f, 3.0f, 4.0f, 3, 4);
3150 test_cylinder(device, 3.0f, 4.0f, 5.0f, 11, 20);
3152 free_test_context(test_context);
3155 static BOOL compute_torus(struct mesh *mesh, float innerradius, float outerradius, UINT sides, UINT rings)
3157 float phi, phi_step, sin_phi, cos_phi;
3158 float theta, theta_step, sin_theta, cos_theta;
3159 unsigned int numvert, numfaces, i, j;
3161 numvert = sides * rings;
3162 numfaces = numvert * 2;
3164 if (!new_mesh(mesh, numvert, numfaces))
3165 return FALSE;
3167 phi_step = D3DX_PI / sides * 2.0f;
3168 theta_step = D3DX_PI / rings * -2.0f;
3170 theta = 0.0f;
3172 for (i = 0; i < rings; ++i)
3174 phi = 0.0f;
3176 cos_theta = cosf(theta);
3177 sin_theta = sinf(theta);
3179 for (j = 0; j < sides; ++j)
3181 sin_phi = sinf(phi);
3182 cos_phi = cosf(phi);
3184 mesh->vertices[i * sides + j].position.x = (innerradius * cos_phi + outerradius) * cos_theta;
3185 mesh->vertices[i * sides + j].position.y = (innerradius * cos_phi + outerradius) * sin_theta;
3186 mesh->vertices[i * sides + j].position.z = innerradius * sin_phi;
3187 mesh->vertices[i * sides + j].normal.x = cos_phi * cos_theta;
3188 mesh->vertices[i * sides + j].normal.y = cos_phi * sin_theta;
3189 mesh->vertices[i * sides + j].normal.z = sin_phi;
3191 phi += phi_step;
3194 theta += theta_step;
3197 for (i = 0; i < numfaces - sides * 2; ++i)
3199 mesh->faces[i][0] = i % 2 ? i / 2 + sides : i / 2;
3200 mesh->faces[i][1] = (i / 2 + 1) % sides ? i / 2 + 1 : i / 2 + 1 - sides;
3201 mesh->faces[i][2] = (i + 1) % (sides * 2) ? (i + 1) / 2 + sides : (i + 1) / 2;
3204 for (j = 0; i < numfaces; ++i, ++j)
3206 mesh->faces[i][0] = i % 2 ? j / 2 : i / 2;
3207 mesh->faces[i][1] = (i / 2 + 1) % sides ? i / 2 + 1 : i / 2 + 1 - sides;
3208 mesh->faces[i][2] = i == numfaces - 1 ? 0 : (j + 1) / 2;
3211 return TRUE;
3214 static void test_torus(IDirect3DDevice9 *device, float innerradius, float outerradius, UINT sides, UINT rings)
3216 HRESULT hr;
3217 ID3DXMesh *torus;
3218 struct mesh mesh;
3219 char name[256];
3221 hr = D3DXCreateTorus(device, innerradius, outerradius, sides, rings, &torus, NULL);
3222 ok(hr == D3D_OK, "Got result %#x, expected 0 (D3D_OK)\n", hr);
3223 if (hr != D3D_OK)
3225 skip("Couldn't create torus\n");
3226 return;
3229 if (!compute_torus(&mesh, innerradius, outerradius, sides, rings))
3231 skip("Couldn't create mesh\n");
3232 torus->lpVtbl->Release(torus);
3233 return;
3236 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
3238 sprintf(name, "torus (%g, %g, %u, %u)", innerradius, outerradius, sides, rings);
3239 compare_mesh(name, torus, &mesh);
3241 free_mesh(&mesh);
3243 torus->lpVtbl->Release(torus);
3246 static void D3DXCreateTorusTest(void)
3248 HRESULT hr;
3249 IDirect3DDevice9* device;
3250 ID3DXMesh* torus = NULL;
3251 struct test_context *test_context;
3253 if (!(test_context = new_test_context()))
3255 skip("Couldn't create test context\n");
3256 return;
3258 device = test_context->device;
3260 hr = D3DXCreateTorus(NULL, 0.0f, 0.0f, 3, 3, &torus, NULL);
3261 ok(hr == D3DERR_INVALIDCALL, "Got result %#x, expected %#x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
3263 hr = D3DXCreateTorus(device, -1.0f, 0.0f, 3, 3, &torus, NULL);
3264 ok(hr == D3DERR_INVALIDCALL, "Got result %#x, expected %#x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
3266 hr = D3DXCreateTorus(device, 0.0f, -1.0f, 3, 3, &torus, NULL);
3267 ok(hr == D3DERR_INVALIDCALL, "Got result %#x, expected %#x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
3269 hr = D3DXCreateTorus(device, 0.0f, 0.0f, 2, 3, &torus, NULL);
3270 ok(hr == D3DERR_INVALIDCALL, "Got result %#x, expected %#x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
3272 hr = D3DXCreateTorus(device, 0.0f, 0.0f, 3, 2, &torus, NULL);
3273 ok(hr == D3DERR_INVALIDCALL, "Got result %#x, expected %#x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
3275 hr = D3DXCreateTorus(device, 0.0f, 0.0f, 3, 3, NULL, NULL);
3276 ok(hr == D3DERR_INVALIDCALL, "Got result %#x, expected %#x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
3278 test_torus(device, 0.0f, 0.0f, 3, 3);
3279 test_torus(device, 1.0f, 1.0f, 3, 3);
3280 test_torus(device, 1.0f, 1.0f, 32, 64);
3281 test_torus(device, 0.0f, 1.0f, 5, 5);
3282 test_torus(device, 1.0f, 0.0f, 5, 5);
3283 test_torus(device, 5.0f, 0.2f, 8, 8);
3284 test_torus(device, 0.2f, 1.0f, 60, 3);
3285 test_torus(device, 0.2f, 1.0f, 8, 70);
3287 free_test_context(test_context);
3290 struct dynamic_array
3292 int count, capacity;
3293 void *items;
3296 enum pointtype {
3297 POINTTYPE_CURVE = 0,
3298 POINTTYPE_CORNER,
3299 POINTTYPE_CURVE_START,
3300 POINTTYPE_CURVE_END,
3301 POINTTYPE_CURVE_MIDDLE,
3304 struct point2d
3306 D3DXVECTOR2 pos;
3307 enum pointtype corner;
3310 /* is a dynamic_array */
3311 struct outline
3313 int count, capacity;
3314 struct point2d *items;
3317 /* is a dynamic_array */
3318 struct outline_array
3320 int count, capacity;
3321 struct outline *items;
3324 struct glyphinfo
3326 struct outline_array outlines;
3327 float offset_x;
3330 static BOOL reserve(struct dynamic_array *array, int count, int itemsize)
3332 if (count > array->capacity) {
3333 void *new_buffer;
3334 int new_capacity;
3335 if (array->items && array->capacity) {
3336 new_capacity = max(array->capacity * 2, count);
3337 new_buffer = HeapReAlloc(GetProcessHeap(), 0, array->items, new_capacity * itemsize);
3338 } else {
3339 new_capacity = max(16, count);
3340 new_buffer = HeapAlloc(GetProcessHeap(), 0, new_capacity * itemsize);
3342 if (!new_buffer)
3343 return FALSE;
3344 array->items = new_buffer;
3345 array->capacity = new_capacity;
3347 return TRUE;
3350 static struct point2d *add_point(struct outline *array)
3352 struct point2d *item;
3354 if (!reserve((struct dynamic_array *)array, array->count + 1, sizeof(array->items[0])))
3355 return NULL;
3357 item = &array->items[array->count++];
3358 ZeroMemory(item, sizeof(*item));
3359 return item;
3362 static struct outline *add_outline(struct outline_array *array)
3364 struct outline *item;
3366 if (!reserve((struct dynamic_array *)array, array->count + 1, sizeof(array->items[0])))
3367 return NULL;
3369 item = &array->items[array->count++];
3370 ZeroMemory(item, sizeof(*item));
3371 return item;
3374 static inline D3DXVECTOR2 *convert_fixed_to_float(POINTFX *pt, int count, float emsquare)
3376 D3DXVECTOR2 *ret = (D3DXVECTOR2*)pt;
3377 while (count--) {
3378 D3DXVECTOR2 *pt_flt = (D3DXVECTOR2*)pt;
3379 pt_flt->x = (pt->x.value + pt->x.fract / (float)0x10000) / emsquare;
3380 pt_flt->y = (pt->y.value + pt->y.fract / (float)0x10000) / emsquare;
3381 pt++;
3383 return ret;
3386 static HRESULT add_bezier_points(struct outline *outline, const D3DXVECTOR2 *p1,
3387 const D3DXVECTOR2 *p2, const D3DXVECTOR2 *p3,
3388 float max_deviation)
3390 D3DXVECTOR2 split1 = {0, 0}, split2 = {0, 0}, middle, vec;
3391 float deviation;
3393 D3DXVec2Scale(&split1, D3DXVec2Add(&split1, p1, p2), 0.5f);
3394 D3DXVec2Scale(&split2, D3DXVec2Add(&split2, p2, p3), 0.5f);
3395 D3DXVec2Scale(&middle, D3DXVec2Add(&middle, &split1, &split2), 0.5f);
3397 deviation = D3DXVec2Length(D3DXVec2Subtract(&vec, &middle, p2));
3398 if (deviation < max_deviation) {
3399 struct point2d *pt = add_point(outline);
3400 if (!pt) return E_OUTOFMEMORY;
3401 pt->pos = *p2;
3402 pt->corner = POINTTYPE_CURVE;
3403 /* the end point is omitted because the end line merges into the next segment of
3404 * the split bezier curve, and the end of the split bezier curve is added outside
3405 * this recursive function. */
3406 } else {
3407 HRESULT hr = add_bezier_points(outline, p1, &split1, &middle, max_deviation);
3408 if (hr != S_OK) return hr;
3409 hr = add_bezier_points(outline, &middle, &split2, p3, max_deviation);
3410 if (hr != S_OK) return hr;
3413 return S_OK;
3416 static inline BOOL is_direction_similar(D3DXVECTOR2 *dir1, D3DXVECTOR2 *dir2, float cos_theta)
3418 /* dot product = cos(theta) */
3419 return D3DXVec2Dot(dir1, dir2) > cos_theta;
3422 static inline D3DXVECTOR2 *unit_vec2(D3DXVECTOR2 *dir, const D3DXVECTOR2 *pt1, const D3DXVECTOR2 *pt2)
3424 return D3DXVec2Normalize(D3DXVec2Subtract(dir, pt2, pt1), dir);
3427 static BOOL attempt_line_merge(struct outline *outline,
3428 int pt_index,
3429 const D3DXVECTOR2 *nextpt,
3430 BOOL to_curve)
3432 D3DXVECTOR2 curdir, lastdir;
3433 struct point2d *prevpt, *pt;
3434 BOOL ret = FALSE;
3435 const float cos_half = cos(D3DXToRadian(0.5f));
3437 pt = &outline->items[pt_index];
3438 pt_index = (pt_index - 1 + outline->count) % outline->count;
3439 prevpt = &outline->items[pt_index];
3441 if (to_curve)
3442 pt->corner = pt->corner != POINTTYPE_CORNER ? POINTTYPE_CURVE_MIDDLE : POINTTYPE_CURVE_START;
3444 if (outline->count < 2)
3445 return FALSE;
3447 /* remove last point if the next line continues the last line */
3448 unit_vec2(&lastdir, &prevpt->pos, &pt->pos);
3449 unit_vec2(&curdir, &pt->pos, nextpt);
3450 if (is_direction_similar(&lastdir, &curdir, cos_half))
3452 outline->count--;
3453 if (pt->corner == POINTTYPE_CURVE_END)
3454 prevpt->corner = pt->corner;
3455 if (prevpt->corner == POINTTYPE_CURVE_END && to_curve)
3456 prevpt->corner = POINTTYPE_CURVE_MIDDLE;
3457 pt = prevpt;
3459 ret = TRUE;
3460 if (outline->count < 2)
3461 return ret;
3463 pt_index = (pt_index - 1 + outline->count) % outline->count;
3464 prevpt = &outline->items[pt_index];
3465 unit_vec2(&lastdir, &prevpt->pos, &pt->pos);
3466 unit_vec2(&curdir, &pt->pos, nextpt);
3468 return ret;
3471 static HRESULT create_outline(struct glyphinfo *glyph, void *raw_outline, int datasize,
3472 float max_deviation, float emsquare)
3474 const float cos_45 = cos(D3DXToRadian(45.0f));
3475 const float cos_90 = cos(D3DXToRadian(90.0f));
3476 TTPOLYGONHEADER *header = (TTPOLYGONHEADER *)raw_outline;
3478 while ((char *)header < (char *)raw_outline + datasize)
3480 TTPOLYCURVE *curve = (TTPOLYCURVE *)(header + 1);
3481 struct point2d *lastpt, *pt;
3482 D3DXVECTOR2 lastdir;
3483 D3DXVECTOR2 *pt_flt;
3484 int j;
3485 struct outline *outline = add_outline(&glyph->outlines);
3487 if (!outline)
3488 return E_OUTOFMEMORY;
3490 pt = add_point(outline);
3491 if (!pt)
3492 return E_OUTOFMEMORY;
3493 pt_flt = convert_fixed_to_float(&header->pfxStart, 1, emsquare);
3494 pt->pos = *pt_flt;
3495 pt->corner = POINTTYPE_CORNER;
3497 if (header->dwType != TT_POLYGON_TYPE)
3498 trace("Unknown header type %d\n", header->dwType);
3500 while ((char *)curve < (char *)header + header->cb)
3502 D3DXVECTOR2 bezier_start = outline->items[outline->count - 1].pos;
3503 BOOL to_curve = curve->wType != TT_PRIM_LINE && curve->cpfx > 1;
3505 if (!curve->cpfx) {
3506 curve = (TTPOLYCURVE *)&curve->apfx[curve->cpfx];
3507 continue;
3510 pt_flt = convert_fixed_to_float(curve->apfx, curve->cpfx, emsquare);
3512 attempt_line_merge(outline, outline->count - 1, &pt_flt[0], to_curve);
3514 if (to_curve)
3516 HRESULT hr;
3517 int count = curve->cpfx;
3518 j = 0;
3520 while (count > 2)
3522 D3DXVECTOR2 bezier_end;
3524 D3DXVec2Scale(&bezier_end, D3DXVec2Add(&bezier_end, &pt_flt[j], &pt_flt[j+1]), 0.5f);
3525 hr = add_bezier_points(outline, &bezier_start, &pt_flt[j], &bezier_end, max_deviation);
3526 if (hr != S_OK)
3527 return hr;
3528 bezier_start = bezier_end;
3529 count--;
3530 j++;
3532 hr = add_bezier_points(outline, &bezier_start, &pt_flt[j], &pt_flt[j+1], max_deviation);
3533 if (hr != S_OK)
3534 return hr;
3536 pt = add_point(outline);
3537 if (!pt)
3538 return E_OUTOFMEMORY;
3539 j++;
3540 pt->pos = pt_flt[j];
3541 pt->corner = POINTTYPE_CURVE_END;
3542 } else {
3543 for (j = 0; j < curve->cpfx; j++)
3545 pt = add_point(outline);
3546 if (!pt)
3547 return E_OUTOFMEMORY;
3548 pt->pos = pt_flt[j];
3549 pt->corner = POINTTYPE_CORNER;
3553 curve = (TTPOLYCURVE *)&curve->apfx[curve->cpfx];
3556 /* remove last point if the next line continues the last line */
3557 if (outline->count >= 3) {
3558 BOOL to_curve;
3560 lastpt = &outline->items[outline->count - 1];
3561 pt = &outline->items[0];
3562 if (pt->pos.x == lastpt->pos.x && pt->pos.y == lastpt->pos.y) {
3563 if (lastpt->corner == POINTTYPE_CURVE_END)
3565 if (pt->corner == POINTTYPE_CURVE_START)
3566 pt->corner = POINTTYPE_CURVE_MIDDLE;
3567 else
3568 pt->corner = POINTTYPE_CURVE_END;
3570 outline->count--;
3571 lastpt = &outline->items[outline->count - 1];
3572 } else {
3573 /* outline closed with a line from end to start point */
3574 attempt_line_merge(outline, outline->count - 1, &pt->pos, FALSE);
3576 lastpt = &outline->items[0];
3577 to_curve = lastpt->corner != POINTTYPE_CORNER && lastpt->corner != POINTTYPE_CURVE_END;
3578 if (lastpt->corner == POINTTYPE_CURVE_START)
3579 lastpt->corner = POINTTYPE_CORNER;
3580 pt = &outline->items[1];
3581 if (attempt_line_merge(outline, 0, &pt->pos, to_curve))
3582 *lastpt = outline->items[outline->count];
3585 lastpt = &outline->items[outline->count - 1];
3586 pt = &outline->items[0];
3587 unit_vec2(&lastdir, &lastpt->pos, &pt->pos);
3588 for (j = 0; j < outline->count; j++)
3590 D3DXVECTOR2 curdir;
3592 lastpt = pt;
3593 pt = &outline->items[(j + 1) % outline->count];
3594 unit_vec2(&curdir, &lastpt->pos, &pt->pos);
3596 switch (lastpt->corner)
3598 case POINTTYPE_CURVE_START:
3599 case POINTTYPE_CURVE_END:
3600 if (!is_direction_similar(&lastdir, &curdir, cos_45))
3601 lastpt->corner = POINTTYPE_CORNER;
3602 break;
3603 case POINTTYPE_CURVE_MIDDLE:
3604 if (!is_direction_similar(&lastdir, &curdir, cos_90))
3605 lastpt->corner = POINTTYPE_CORNER;
3606 else
3607 lastpt->corner = POINTTYPE_CURVE;
3608 break;
3609 default:
3610 break;
3612 lastdir = curdir;
3615 header = (TTPOLYGONHEADER *)((char *)header + header->cb);
3617 return S_OK;
3620 static BOOL compute_text_mesh(struct mesh *mesh, const char *text,
3621 float deviation, float extrusion, float otmEMSquare, const struct glyphinfo *glyphs)
3623 DWORD nb_vertices, nb_faces;
3624 DWORD nb_corners, nb_outline_points;
3625 int textlen = 0;
3626 int i;
3627 struct vertex *vertex_ptr;
3628 face *face_ptr;
3630 textlen = strlen(text);
3632 /* corner points need an extra vertex for the different side faces normals */
3633 nb_corners = 0;
3634 nb_outline_points = 0;
3635 for (i = 0; i < textlen; i++)
3637 int j;
3638 for (j = 0; j < glyphs[i].outlines.count; j++)
3640 int k;
3641 struct outline *outline = &glyphs[i].outlines.items[j];
3642 nb_outline_points += outline->count;
3643 nb_corners++; /* first outline point always repeated as a corner */
3644 for (k = 1; k < outline->count; k++)
3645 if (outline->items[k].corner)
3646 nb_corners++;
3650 nb_vertices = (nb_outline_points + nb_corners) * 2 + textlen;
3651 nb_faces = nb_outline_points * 2;
3653 if (!new_mesh(mesh, nb_vertices, nb_faces))
3654 return FALSE;
3656 /* convert 2D vertices and faces into 3D mesh */
3657 vertex_ptr = mesh->vertices;
3658 face_ptr = mesh->faces;
3659 for (i = 0; i < textlen; i++)
3661 int j;
3663 /* side vertices and faces */
3664 for (j = 0; j < glyphs[i].outlines.count; j++)
3666 struct vertex *outline_vertices = vertex_ptr;
3667 struct outline *outline = &glyphs[i].outlines.items[j];
3668 int k;
3669 struct point2d *prevpt = &outline->items[outline->count - 1];
3670 struct point2d *pt = &outline->items[0];
3672 for (k = 1; k <= outline->count; k++)
3674 struct vertex vtx;
3675 struct point2d *nextpt = &outline->items[k % outline->count];
3676 WORD vtx_idx = vertex_ptr - mesh->vertices;
3677 D3DXVECTOR2 vec;
3679 if (pt->corner == POINTTYPE_CURVE_START)
3680 D3DXVec2Subtract(&vec, &pt->pos, &prevpt->pos);
3681 else if (pt->corner)
3682 D3DXVec2Subtract(&vec, &nextpt->pos, &pt->pos);
3683 else
3684 D3DXVec2Subtract(&vec, &nextpt->pos, &prevpt->pos);
3685 D3DXVec2Normalize(&vec, &vec);
3686 vtx.normal.x = -vec.y;
3687 vtx.normal.y = vec.x;
3688 vtx.normal.z = 0;
3690 vtx.position.x = pt->pos.x + glyphs[i].offset_x;
3691 vtx.position.y = pt->pos.y;
3692 vtx.position.z = 0;
3693 *vertex_ptr++ = vtx;
3695 vtx.position.z = -extrusion;
3696 *vertex_ptr++ = vtx;
3698 vtx.position.x = nextpt->pos.x + glyphs[i].offset_x;
3699 vtx.position.y = nextpt->pos.y;
3700 if (pt->corner && nextpt->corner && nextpt->corner != POINTTYPE_CURVE_END) {
3701 vtx.position.z = -extrusion;
3702 *vertex_ptr++ = vtx;
3703 vtx.position.z = 0;
3704 *vertex_ptr++ = vtx;
3706 (*face_ptr)[0] = vtx_idx;
3707 (*face_ptr)[1] = vtx_idx + 2;
3708 (*face_ptr)[2] = vtx_idx + 1;
3709 face_ptr++;
3711 (*face_ptr)[0] = vtx_idx;
3712 (*face_ptr)[1] = vtx_idx + 3;
3713 (*face_ptr)[2] = vtx_idx + 2;
3714 face_ptr++;
3715 } else {
3716 if (nextpt->corner) {
3717 if (nextpt->corner == POINTTYPE_CURVE_END) {
3718 struct point2d *nextpt2 = &outline->items[(k + 1) % outline->count];
3719 D3DXVec2Subtract(&vec, &nextpt2->pos, &nextpt->pos);
3720 } else {
3721 D3DXVec2Subtract(&vec, &nextpt->pos, &pt->pos);
3723 D3DXVec2Normalize(&vec, &vec);
3724 vtx.normal.x = -vec.y;
3725 vtx.normal.y = vec.x;
3727 vtx.position.z = 0;
3728 *vertex_ptr++ = vtx;
3729 vtx.position.z = -extrusion;
3730 *vertex_ptr++ = vtx;
3733 (*face_ptr)[0] = vtx_idx;
3734 (*face_ptr)[1] = vtx_idx + 3;
3735 (*face_ptr)[2] = vtx_idx + 1;
3736 face_ptr++;
3738 (*face_ptr)[0] = vtx_idx;
3739 (*face_ptr)[1] = vtx_idx + 2;
3740 (*face_ptr)[2] = vtx_idx + 3;
3741 face_ptr++;
3744 prevpt = pt;
3745 pt = nextpt;
3747 if (!pt->corner) {
3748 *vertex_ptr++ = *outline_vertices++;
3749 *vertex_ptr++ = *outline_vertices++;
3753 /* FIXME: compute expected faces */
3754 /* Add placeholder to separate glyph outlines */
3755 vertex_ptr->position.x = 0;
3756 vertex_ptr->position.y = 0;
3757 vertex_ptr->position.z = 0;
3758 vertex_ptr->normal.x = 0;
3759 vertex_ptr->normal.y = 0;
3760 vertex_ptr->normal.z = 1;
3761 vertex_ptr++;
3764 return TRUE;
3767 static void compare_text_outline_mesh(const char *name, ID3DXMesh *d3dxmesh, struct mesh *mesh,
3768 size_t textlen, float extrusion, const struct glyphinfo *glyphs)
3770 HRESULT hr;
3771 DWORD number_of_vertices, number_of_faces;
3772 IDirect3DVertexBuffer9 *vertex_buffer = NULL;
3773 IDirect3DIndexBuffer9 *index_buffer = NULL;
3774 D3DVERTEXBUFFER_DESC vertex_buffer_description;
3775 D3DINDEXBUFFER_DESC index_buffer_description;
3776 struct vertex *vertices = NULL;
3777 face *faces = NULL;
3778 int expected, i;
3779 int vtx_idx1, face_idx1, vtx_idx2, face_idx2;
3781 number_of_vertices = d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh);
3782 number_of_faces = d3dxmesh->lpVtbl->GetNumFaces(d3dxmesh);
3784 /* vertex buffer */
3785 hr = d3dxmesh->lpVtbl->GetVertexBuffer(d3dxmesh, &vertex_buffer);
3786 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
3787 if (hr != D3D_OK)
3789 skip("Couldn't get vertex buffers\n");
3790 goto error;
3793 hr = IDirect3DVertexBuffer9_GetDesc(vertex_buffer, &vertex_buffer_description);
3794 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
3796 if (hr != D3D_OK)
3798 skip("Couldn't get vertex buffer description\n");
3800 else
3802 ok(vertex_buffer_description.Format == D3DFMT_VERTEXDATA, "Test %s, result %x, expected %x (D3DFMT_VERTEXDATA)\n",
3803 name, vertex_buffer_description.Format, D3DFMT_VERTEXDATA);
3804 ok(vertex_buffer_description.Type == D3DRTYPE_VERTEXBUFFER, "Test %s, result %x, expected %x (D3DRTYPE_VERTEXBUFFER)\n",
3805 name, vertex_buffer_description.Type, D3DRTYPE_VERTEXBUFFER);
3806 ok(vertex_buffer_description.Usage == 0, "Test %s, result %x, expected %x\n", name, vertex_buffer_description.Usage, 0);
3807 ok(vertex_buffer_description.Pool == D3DPOOL_MANAGED, "Test %s, result %x, expected %x (D3DPOOL_MANAGED)\n",
3808 name, vertex_buffer_description.Pool, D3DPOOL_MANAGED);
3809 ok(vertex_buffer_description.FVF == mesh->fvf, "Test %s, result %x, expected %x\n",
3810 name, vertex_buffer_description.FVF, mesh->fvf);
3811 if (mesh->fvf == 0)
3813 expected = number_of_vertices * mesh->vertex_size;
3815 else
3817 expected = number_of_vertices * D3DXGetFVFVertexSize(mesh->fvf);
3819 ok(vertex_buffer_description.Size == expected, "Test %s, result %x, expected %x\n",
3820 name, vertex_buffer_description.Size, expected);
3823 hr = d3dxmesh->lpVtbl->GetIndexBuffer(d3dxmesh, &index_buffer);
3824 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
3825 if (hr != D3D_OK)
3827 skip("Couldn't get index buffer\n");
3828 goto error;
3831 hr = IDirect3DIndexBuffer9_GetDesc(index_buffer, &index_buffer_description);
3832 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
3834 if (hr != D3D_OK)
3836 skip("Couldn't get index buffer description\n");
3838 else
3840 ok(index_buffer_description.Format == D3DFMT_INDEX16, "Test %s, result %x, expected %x (D3DFMT_INDEX16)\n",
3841 name, index_buffer_description.Format, D3DFMT_INDEX16);
3842 ok(index_buffer_description.Type == D3DRTYPE_INDEXBUFFER, "Test %s, result %x, expected %x (D3DRTYPE_INDEXBUFFER)\n",
3843 name, index_buffer_description.Type, D3DRTYPE_INDEXBUFFER);
3844 ok(index_buffer_description.Usage == 0, "Test %s, result %#x, expected %#x.\n",
3845 name, index_buffer_description.Usage, 0);
3846 ok(index_buffer_description.Pool == D3DPOOL_MANAGED, "Test %s, result %x, expected %x (D3DPOOL_MANAGED)\n",
3847 name, index_buffer_description.Pool, D3DPOOL_MANAGED);
3848 expected = number_of_faces * sizeof(WORD) * 3;
3849 ok(index_buffer_description.Size == expected, "Test %s, result %x, expected %x\n",
3850 name, index_buffer_description.Size, expected);
3853 /* specify offset and size to avoid potential overruns */
3854 hr = IDirect3DVertexBuffer9_Lock(vertex_buffer, 0, number_of_vertices * sizeof(D3DXVECTOR3) * 2,
3855 (void **)&vertices, D3DLOCK_DISCARD);
3856 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
3857 if (hr != D3D_OK)
3859 skip("Couldn't lock vertex buffer\n");
3860 goto error;
3862 hr = IDirect3DIndexBuffer9_Lock(index_buffer, 0, number_of_faces * sizeof(WORD) * 3,
3863 (void **)&faces, D3DLOCK_DISCARD);
3864 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
3865 if (hr != D3D_OK)
3867 skip("Couldn't lock index buffer\n");
3868 goto error;
3871 face_idx1 = 0;
3872 vtx_idx2 = 0;
3873 face_idx2 = 0;
3874 vtx_idx1 = 0;
3875 for (i = 0; i < textlen; i++)
3877 int nb_outline_vertices1, nb_outline_faces1;
3878 int nb_outline_vertices2, nb_outline_faces2;
3879 int nb_back_vertices, nb_back_faces;
3880 int first_vtx1, first_vtx2;
3881 int first_face1, first_face2;
3882 int j;
3884 first_vtx1 = vtx_idx1;
3885 first_vtx2 = vtx_idx2;
3886 /* Glyphs without outlines do not generate any vertices. */
3887 if (glyphs[i].outlines.count > 0)
3889 for (; vtx_idx1 < number_of_vertices; vtx_idx1++)
3891 if (vertices[vtx_idx1].normal.z != 0)
3892 break;
3895 for (; vtx_idx2 < mesh->number_of_vertices; vtx_idx2++)
3897 if (mesh->vertices[vtx_idx2].normal.z != 0)
3898 break;
3901 nb_outline_vertices1 = vtx_idx1 - first_vtx1;
3902 nb_outline_vertices2 = vtx_idx2 - first_vtx2;
3903 ok(nb_outline_vertices1 == nb_outline_vertices2,
3904 "Test %s, glyph %d, outline vertex count result %d, expected %d\n", name, i,
3905 nb_outline_vertices1, nb_outline_vertices2);
3907 for (j = 0; j < min(nb_outline_vertices1, nb_outline_vertices2); j++)
3909 vtx_idx1 = first_vtx1 + j;
3910 vtx_idx2 = first_vtx2 + j;
3911 ok(compare_vec3(vertices[vtx_idx1].position, mesh->vertices[vtx_idx2].position),
3912 "Test %s, glyph %d, vertex position %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1,
3913 vertices[vtx_idx1].position.x, vertices[vtx_idx1].position.y, vertices[vtx_idx1].position.z,
3914 mesh->vertices[vtx_idx2].position.x, mesh->vertices[vtx_idx2].position.y, mesh->vertices[vtx_idx2].position.z);
3915 ok(compare_vec3(vertices[vtx_idx1].normal, mesh->vertices[first_vtx2 + j].normal),
3916 "Test %s, glyph %d, vertex normal %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1,
3917 vertices[vtx_idx1].normal.x, vertices[vtx_idx1].normal.y, vertices[vtx_idx1].normal.z,
3918 mesh->vertices[vtx_idx2].normal.x, mesh->vertices[vtx_idx2].normal.y, mesh->vertices[vtx_idx2].normal.z);
3920 vtx_idx1 = first_vtx1 + nb_outline_vertices1;
3921 vtx_idx2 = first_vtx2 + nb_outline_vertices2;
3923 first_face1 = face_idx1;
3924 first_face2 = face_idx2;
3925 for (; face_idx1 < number_of_faces; face_idx1++)
3927 if (faces[face_idx1][0] >= vtx_idx1 ||
3928 faces[face_idx1][1] >= vtx_idx1 ||
3929 faces[face_idx1][2] >= vtx_idx1)
3930 break;
3932 for (; face_idx2 < mesh->number_of_faces; face_idx2++)
3934 if (mesh->faces[face_idx2][0] >= vtx_idx2 ||
3935 mesh->faces[face_idx2][1] >= vtx_idx2 ||
3936 mesh->faces[face_idx2][2] >= vtx_idx2)
3937 break;
3939 nb_outline_faces1 = face_idx1 - first_face1;
3940 nb_outline_faces2 = face_idx2 - first_face2;
3941 ok(nb_outline_faces1 == nb_outline_faces2,
3942 "Test %s, glyph %d, outline face count result %d, expected %d\n", name, i,
3943 nb_outline_faces1, nb_outline_faces2);
3945 for (j = 0; j < min(nb_outline_faces1, nb_outline_faces2); j++)
3947 face_idx1 = first_face1 + j;
3948 face_idx2 = first_face2 + j;
3949 ok(faces[face_idx1][0] - first_vtx1 == mesh->faces[face_idx2][0] - first_vtx2 &&
3950 faces[face_idx1][1] - first_vtx1 == mesh->faces[face_idx2][1] - first_vtx2 &&
3951 faces[face_idx1][2] - first_vtx1 == mesh->faces[face_idx2][2] - first_vtx2,
3952 "Test %s, glyph %d, face %d, result (%d, %d, %d), expected (%d, %d, %d)\n", name, i, face_idx1,
3953 faces[face_idx1][0], faces[face_idx1][1], faces[face_idx1][2],
3954 mesh->faces[face_idx2][0] - first_vtx2 + first_vtx1,
3955 mesh->faces[face_idx2][1] - first_vtx2 + first_vtx1,
3956 mesh->faces[face_idx2][2] - first_vtx2 + first_vtx1);
3958 face_idx1 = first_face1 + nb_outline_faces1;
3959 face_idx2 = first_face2 + nb_outline_faces2;
3961 /* partial test on back vertices and faces */
3962 first_vtx1 = vtx_idx1;
3963 for (; vtx_idx1 < number_of_vertices; vtx_idx1++) {
3964 struct vertex vtx;
3966 if (vertices[vtx_idx1].normal.z != 1.0f)
3967 break;
3969 vtx.position.z = 0.0f;
3970 vtx.normal.x = 0.0f;
3971 vtx.normal.y = 0.0f;
3972 vtx.normal.z = 1.0f;
3973 ok(compare(vertices[vtx_idx1].position.z, vtx.position.z),
3974 "Test %s, glyph %d, vertex position.z %d, result %g, expected %g\n", name, i, vtx_idx1,
3975 vertices[vtx_idx1].position.z, vtx.position.z);
3976 ok(compare_vec3(vertices[vtx_idx1].normal, vtx.normal),
3977 "Test %s, glyph %d, vertex normal %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1,
3978 vertices[vtx_idx1].normal.x, vertices[vtx_idx1].normal.y, vertices[vtx_idx1].normal.z,
3979 vtx.normal.x, vtx.normal.y, vtx.normal.z);
3981 nb_back_vertices = vtx_idx1 - first_vtx1;
3982 first_face1 = face_idx1;
3983 for (; face_idx1 < number_of_faces; face_idx1++)
3985 const D3DXVECTOR3 *vtx1, *vtx2, *vtx3;
3986 D3DXVECTOR3 normal;
3987 D3DXVECTOR3 v1 = {0, 0, 0};
3988 D3DXVECTOR3 v2 = {0, 0, 0};
3989 D3DXVECTOR3 forward = {0.0f, 0.0f, 1.0f};
3991 if (faces[face_idx1][0] >= vtx_idx1 ||
3992 faces[face_idx1][1] >= vtx_idx1 ||
3993 faces[face_idx1][2] >= vtx_idx1)
3994 break;
3996 vtx1 = &vertices[faces[face_idx1][0]].position;
3997 vtx2 = &vertices[faces[face_idx1][1]].position;
3998 vtx3 = &vertices[faces[face_idx1][2]].position;
4000 D3DXVec3Subtract(&v1, vtx2, vtx1);
4001 D3DXVec3Subtract(&v2, vtx3, vtx2);
4002 D3DXVec3Cross(&normal, &v1, &v2);
4003 D3DXVec3Normalize(&normal, &normal);
4004 ok(!D3DXVec3Length(&normal) || compare_vec3(normal, forward),
4005 "Test %s, glyph %d, face %d normal, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, face_idx1,
4006 normal.x, normal.y, normal.z, forward.x, forward.y, forward.z);
4008 nb_back_faces = face_idx1 - first_face1;
4010 /* compare front and back faces & vertices */
4011 if (extrusion == 0.0f) {
4012 /* Oddly there are only back faces in this case */
4013 nb_back_vertices /= 2;
4014 nb_back_faces /= 2;
4015 face_idx1 -= nb_back_faces;
4016 vtx_idx1 -= nb_back_vertices;
4018 for (j = 0; j < nb_back_vertices; j++)
4020 struct vertex vtx = vertices[first_vtx1];
4021 vtx.position.z = -extrusion;
4022 vtx.normal.x = 0.0f;
4023 vtx.normal.y = 0.0f;
4024 vtx.normal.z = extrusion == 0.0f ? 1.0f : -1.0f;
4025 ok(compare_vec3(vertices[vtx_idx1].position, vtx.position),
4026 "Test %s, glyph %d, vertex position %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1,
4027 vertices[vtx_idx1].position.x, vertices[vtx_idx1].position.y, vertices[vtx_idx1].position.z,
4028 vtx.position.x, vtx.position.y, vtx.position.z);
4029 ok(compare_vec3(vertices[vtx_idx1].normal, vtx.normal),
4030 "Test %s, glyph %d, vertex normal %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1,
4031 vertices[vtx_idx1].normal.x, vertices[vtx_idx1].normal.y, vertices[vtx_idx1].normal.z,
4032 vtx.normal.x, vtx.normal.y, vtx.normal.z);
4033 vtx_idx1++;
4034 first_vtx1++;
4036 for (j = 0; j < nb_back_faces; j++)
4038 int f1, f2;
4039 if (extrusion == 0.0f) {
4040 f1 = 1;
4041 f2 = 2;
4042 } else {
4043 f1 = 2;
4044 f2 = 1;
4046 ok(faces[face_idx1][0] == faces[first_face1][0] + nb_back_vertices &&
4047 faces[face_idx1][1] == faces[first_face1][f1] + nb_back_vertices &&
4048 faces[face_idx1][2] == faces[first_face1][f2] + nb_back_vertices,
4049 "Test %s, glyph %d, face %d, result (%d, %d, %d), expected (%d, %d, %d)\n", name, i, face_idx1,
4050 faces[face_idx1][0], faces[face_idx1][1], faces[face_idx1][2],
4051 faces[first_face1][0] - nb_back_faces,
4052 faces[first_face1][f1] - nb_back_faces,
4053 faces[first_face1][f2] - nb_back_faces);
4054 first_face1++;
4055 face_idx1++;
4058 /* skip to the outline for the next glyph */
4059 for (; vtx_idx2 < mesh->number_of_vertices; vtx_idx2++) {
4060 if (mesh->vertices[vtx_idx2].normal.z == 0)
4061 break;
4063 for (; face_idx2 < mesh->number_of_faces; face_idx2++)
4065 if (mesh->faces[face_idx2][0] >= vtx_idx2 ||
4066 mesh->faces[face_idx2][1] >= vtx_idx2 ||
4067 mesh->faces[face_idx2][2] >= vtx_idx2) break;
4071 error:
4072 if (vertices) IDirect3DVertexBuffer9_Unlock(vertex_buffer);
4073 if (faces) IDirect3DIndexBuffer9_Unlock(index_buffer);
4074 if (index_buffer) IDirect3DIndexBuffer9_Release(index_buffer);
4075 if (vertex_buffer) IDirect3DVertexBuffer9_Release(vertex_buffer);
4078 static void test_createtext(IDirect3DDevice9 *device, HDC hdc, const char *text, float deviation, float extrusion)
4080 HRESULT hr;
4081 ID3DXMesh *d3dxmesh = NULL;
4082 struct mesh mesh = {0};
4083 char name[256];
4084 OUTLINETEXTMETRICA otm;
4085 GLYPHMETRICS gm;
4086 struct glyphinfo *glyphs = NULL;
4087 GLYPHMETRICSFLOAT *glyphmetrics_float = HeapAlloc(GetProcessHeap(), 0, sizeof(GLYPHMETRICSFLOAT) * strlen(text));
4088 int i;
4089 LOGFONTA lf;
4090 float offset_x;
4091 size_t textlen;
4092 HFONT font = NULL, oldfont = NULL;
4093 char *raw_outline = NULL;
4095 sprintf(name, "text ('%s', %f, %f)", text, deviation, extrusion);
4097 hr = D3DXCreateTextA(device, hdc, text, deviation, extrusion, &d3dxmesh, NULL, glyphmetrics_float);
4098 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
4099 if (hr != D3D_OK)
4101 skip("Couldn't create text with D3DXCreateText\n");
4102 goto error;
4105 /* must select a modified font having lfHeight = otm.otmEMSquare before
4106 * calling GetGlyphOutline to get the expected values */
4107 if (!GetObjectA(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf)
4108 || !GetOutlineTextMetricsA(hdc, sizeof(otm), &otm))
4110 skip("Couldn't get text outline\n");
4111 goto error;
4113 lf.lfHeight = otm.otmEMSquare;
4114 lf.lfWidth = 0;
4115 if (!(font = CreateFontIndirectA(&lf)))
4117 skip("Couldn't create the modified font\n");
4118 goto error;
4121 textlen = strlen(text);
4122 glyphs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, textlen * sizeof(*glyphs));
4123 if (!glyphs)
4124 goto error;
4126 oldfont = SelectObject(hdc, font);
4128 for (i = 0; i < textlen; i++)
4130 const MAT2 identity = {{0, 1}, {0, 0}, {0, 0}, {0, 1}};
4131 GetGlyphOutlineA(hdc, text[i], GGO_NATIVE, &gm, 0, NULL, &identity);
4132 compare_float(glyphmetrics_float[i].gmfBlackBoxX, gm.gmBlackBoxX / (float)otm.otmEMSquare);
4133 compare_float(glyphmetrics_float[i].gmfBlackBoxY, gm.gmBlackBoxY / (float)otm.otmEMSquare);
4134 compare_float(glyphmetrics_float[i].gmfptGlyphOrigin.x, gm.gmptGlyphOrigin.x / (float)otm.otmEMSquare);
4135 compare_float(glyphmetrics_float[i].gmfptGlyphOrigin.y, gm.gmptGlyphOrigin.y / (float)otm.otmEMSquare);
4136 compare_float(glyphmetrics_float[i].gmfCellIncX, gm.gmCellIncX / (float)otm.otmEMSquare);
4137 compare_float(glyphmetrics_float[i].gmfCellIncY, gm.gmCellIncY / (float)otm.otmEMSquare);
4140 if (deviation == 0.0f)
4141 deviation = 1.0f / otm.otmEMSquare;
4143 offset_x = 0.0f;
4144 for (i = 0; i < textlen; i++)
4146 /* get outline points from data returned from GetGlyphOutline */
4147 const MAT2 identity = {{0, 1}, {0, 0}, {0, 0}, {0, 1}};
4148 int datasize;
4150 glyphs[i].offset_x = offset_x;
4152 datasize = GetGlyphOutlineA(hdc, text[i], GGO_NATIVE, &gm, 0, NULL, &identity);
4153 if (datasize < 0)
4155 SelectObject(hdc, oldfont);
4156 goto error;
4158 HeapFree(GetProcessHeap(), 0, raw_outline);
4159 raw_outline = HeapAlloc(GetProcessHeap(), 0, datasize);
4160 if (!raw_outline)
4162 SelectObject(hdc, oldfont);
4163 goto error;
4165 datasize = GetGlyphOutlineA(hdc, text[i], GGO_NATIVE, &gm, datasize, raw_outline, &identity);
4167 create_outline(&glyphs[i], raw_outline, datasize, deviation, otm.otmEMSquare);
4169 offset_x += gm.gmCellIncX / (float)otm.otmEMSquare;
4172 SelectObject(hdc, oldfont);
4174 ZeroMemory(&mesh, sizeof(mesh));
4175 if (!compute_text_mesh(&mesh, text, deviation, extrusion, otm.otmEMSquare, glyphs))
4177 skip("Couldn't create mesh\n");
4178 d3dxmesh->lpVtbl->Release(d3dxmesh);
4179 return;
4181 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
4183 compare_text_outline_mesh(name, d3dxmesh, &mesh, textlen, extrusion, glyphs);
4185 error:
4186 free_mesh(&mesh);
4188 if (d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh);
4189 if (font) DeleteObject(font);
4190 HeapFree(GetProcessHeap(), 0, glyphmetrics_float);
4192 if (glyphs)
4194 for (i = 0; i < textlen; i++)
4196 int j;
4197 for (j = 0; j < glyphs[i].outlines.count; j++)
4198 HeapFree(GetProcessHeap(), 0, glyphs[i].outlines.items[j].items);
4199 HeapFree(GetProcessHeap(), 0, glyphs[i].outlines.items);
4201 HeapFree(GetProcessHeap(), 0, glyphs);
4203 HeapFree(GetProcessHeap(), 0, raw_outline);
4206 static void D3DXCreateTextTest(void)
4208 HRESULT hr;
4209 HDC hdc;
4210 IDirect3DDevice9* device;
4211 ID3DXMesh* d3dxmesh = NULL;
4212 HFONT hFont;
4213 OUTLINETEXTMETRICA otm;
4214 int number_of_vertices;
4215 int number_of_faces;
4216 struct test_context *test_context;
4218 if (!(test_context = new_test_context()))
4220 skip("Couldn't create test context\n");
4221 return;
4223 device = test_context->device;
4225 hdc = CreateCompatibleDC(NULL);
4227 hFont = CreateFontA(12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
4228 CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, "Arial");
4229 SelectObject(hdc, hFont);
4230 GetOutlineTextMetricsA(hdc, sizeof(otm), &otm);
4232 hr = D3DXCreateTextA(device, hdc, "wine", 0.001f, 0.4f, NULL, NULL, NULL);
4233 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4235 /* D3DXCreateTextA page faults from passing NULL text */
4237 hr = D3DXCreateTextW(device, hdc, NULL, 0.001f, 0.4f, &d3dxmesh, NULL, NULL);
4238 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4240 hr = D3DXCreateTextA(device, hdc, "", 0.001f, 0.4f, &d3dxmesh, NULL, NULL);
4241 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4243 hr = D3DXCreateTextA(device, hdc, " ", 0.001f, 0.4f, &d3dxmesh, NULL, NULL);
4244 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4246 hr = D3DXCreateTextA(NULL, hdc, "wine", 0.001f, 0.4f, &d3dxmesh, NULL, NULL);
4247 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4249 hr = D3DXCreateTextA(device, NULL, "wine", 0.001f, 0.4f, &d3dxmesh, NULL, NULL);
4250 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4252 hr = D3DXCreateTextA(device, hdc, "wine", -FLT_MIN, 0.4f, &d3dxmesh, NULL, NULL);
4253 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4255 hr = D3DXCreateTextA(device, hdc, "wine", 0.001f, -FLT_MIN, &d3dxmesh, NULL, NULL);
4256 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4258 /* deviation = 0.0f treated as if deviation = 1.0f / otm.otmEMSquare */
4259 hr = D3DXCreateTextA(device, hdc, "wine", 1.0f / otm.otmEMSquare, 0.4f, &d3dxmesh, NULL, NULL);
4260 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
4261 number_of_vertices = d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh);
4262 number_of_faces = d3dxmesh->lpVtbl->GetNumFaces(d3dxmesh);
4263 if (SUCCEEDED(hr) && d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh);
4265 hr = D3DXCreateTextA(device, hdc, "wine", 0.0f, 0.4f, &d3dxmesh, NULL, NULL);
4266 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
4267 ok(number_of_vertices == d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh),
4268 "Got %d vertices, expected %d\n",
4269 d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh), number_of_vertices);
4270 ok(number_of_faces == d3dxmesh->lpVtbl->GetNumFaces(d3dxmesh),
4271 "Got %d faces, expected %d\n",
4272 d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh), number_of_faces);
4273 if (SUCCEEDED(hr) && d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh);
4275 if (0)
4277 /* too much detail requested, so will appear to hang */
4278 trace("Waiting for D3DXCreateText to finish with deviation = FLT_MIN ...\n");
4279 hr = D3DXCreateTextA(device, hdc, "wine", FLT_MIN, 0.4f, &d3dxmesh, NULL, NULL);
4280 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
4281 if (SUCCEEDED(hr) && d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh);
4282 trace("D3DXCreateText finish with deviation = FLT_MIN\n");
4285 hr = D3DXCreateTextA(device, hdc, "wine", 0.001f, 0.4f, &d3dxmesh, NULL, NULL);
4286 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
4287 if (SUCCEEDED(hr) && d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh);
4289 test_createtext(device, hdc, "wine", FLT_MAX, 0.4f);
4290 test_createtext(device, hdc, "wine", 0.001f, FLT_MIN);
4291 test_createtext(device, hdc, "wine", 0.001f, 0.0f);
4292 test_createtext(device, hdc, "wine", 0.001f, FLT_MAX);
4293 test_createtext(device, hdc, "wine", 0.0f, 1.0f);
4294 test_createtext(device, hdc, " wine", 1.0f, 0.0f);
4295 test_createtext(device, hdc, "wine ", 1.0f, 0.0f);
4296 test_createtext(device, hdc, "wi ne", 1.0f, 0.0f);
4298 DeleteDC(hdc);
4299 DeleteObject(hFont);
4301 free_test_context(test_context);
4304 static void test_get_decl_length(void)
4306 static const D3DVERTEXELEMENT9 declaration1[] =
4308 {0, 0, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4309 {1, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4310 {2, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4311 {3, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4312 {4, 0, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4313 {5, 0, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4314 {6, 0, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4315 {7, 0, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4316 {8, 0, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4317 {9, 0, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4318 {10, 0, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4319 {11, 0, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4320 {12, 0, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4321 {13, 0, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4322 {14, 0, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4323 D3DDECL_END(),
4325 static const D3DVERTEXELEMENT9 declaration2[] =
4327 {0, 8, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4328 {1, 8, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4329 {2, 8, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4330 {3, 8, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4331 {4, 8, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4332 {5, 8, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4333 {6, 8, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4334 {7, 8, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4335 {0, 8, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4336 {1, 8, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4337 {2, 8, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4338 {3, 8, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4339 {4, 8, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4340 {5, 8, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4341 {6, 8, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4342 {7, 8, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4343 D3DDECL_END(),
4345 UINT size;
4347 size = D3DXGetDeclLength(declaration1);
4348 ok(size == 15, "Got size %u, expected 15.\n", size);
4350 size = D3DXGetDeclLength(declaration2);
4351 ok(size == 16, "Got size %u, expected 16.\n", size);
4354 static void test_get_decl_vertex_size(void)
4356 static const D3DVERTEXELEMENT9 declaration1[] =
4358 {0, 0, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4359 {1, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4360 {2, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4361 {3, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4362 {4, 0, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4363 {5, 0, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4364 {6, 0, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4365 {7, 0, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4366 {8, 0, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4367 {9, 0, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4368 {10, 0, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4369 {11, 0, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4370 {12, 0, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4371 {13, 0, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4372 {14, 0, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4373 D3DDECL_END(),
4375 static const D3DVERTEXELEMENT9 declaration2[] =
4377 {0, 8, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4378 {1, 8, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4379 {2, 8, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4380 {3, 8, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4381 {4, 8, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4382 {5, 8, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4383 {6, 8, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4384 {7, 8, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4385 {0, 8, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4386 {1, 8, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4387 {2, 8, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4388 {3, 8, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4389 {4, 8, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4390 {5, 8, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4391 {6, 8, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4392 {7, 8, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4393 D3DDECL_END(),
4395 static const UINT sizes1[] =
4397 4, 8, 12, 16,
4398 4, 4, 4, 8,
4399 4, 4, 8, 4,
4400 4, 4, 8, 0,
4402 static const UINT sizes2[] =
4404 12, 16, 20, 24,
4405 12, 12, 16, 16,
4407 unsigned int i;
4408 UINT size;
4410 size = D3DXGetDeclVertexSize(NULL, 0);
4411 ok(size == 0, "Got size %#x, expected 0.\n", size);
4413 for (i = 0; i < 16; ++i)
4415 size = D3DXGetDeclVertexSize(declaration1, i);
4416 ok(size == sizes1[i], "Got size %u for stream %u, expected %u.\n", size, i, sizes1[i]);
4419 for (i = 0; i < 8; ++i)
4421 size = D3DXGetDeclVertexSize(declaration2, i);
4422 ok(size == sizes2[i], "Got size %u for stream %u, expected %u.\n", size, i, sizes2[i]);
4426 static void D3DXGenerateAdjacencyTest(void)
4428 HRESULT hr;
4429 IDirect3DDevice9 *device;
4430 ID3DXMesh *d3dxmesh = NULL;
4431 D3DXVECTOR3 *vertices = NULL;
4432 WORD *indices = NULL;
4433 int i;
4434 struct {
4435 DWORD num_vertices;
4436 D3DXVECTOR3 vertices[6];
4437 DWORD num_faces;
4438 WORD indices[3 * 3];
4439 FLOAT epsilon;
4440 DWORD adjacency[3 * 3];
4441 } test_data[] = {
4442 { /* for epsilon < 0, indices must match for faces to be adjacent */
4443 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}},
4444 2, {0, 1, 2, 0, 2, 3},
4445 -1.0,
4446 {-1, -1, 1, 0, -1, -1},
4449 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}},
4450 2, {0, 1, 2, 3, 4, 5},
4451 -1.0,
4452 {-1, -1, -1, -1, -1, -1},
4454 { /* for epsilon == 0, indices or vertices must match for faces to be adjacent */
4455 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}},
4456 2, {0, 1, 2, 3, 4, 5},
4457 0.0,
4458 {-1, -1, 1, 0, -1, -1},
4460 { /* for epsilon > 0, vertices must be less than (but NOT equal to) epsilon distance away */
4461 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}},
4462 2, {0, 1, 2, 3, 4, 5},
4463 0.25,
4464 {-1, -1, -1, -1, -1, -1},
4466 { /* for epsilon > 0, vertices must be less than (but NOT equal to) epsilon distance away */
4467 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}},
4468 2, {0, 1, 2, 3, 4, 5},
4469 0.250001,
4470 {-1, -1, 1, 0, -1, -1},
4472 { /* length between vertices are compared to epsilon, not the individual dimension deltas */
4473 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}},
4474 2, {0, 1, 2, 3, 4, 5},
4475 0.353, /* < sqrt(0.25*0.25 + 0.25*0.25) */
4476 {-1, -1, -1, -1, -1, -1},
4479 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}},
4480 2, {0, 1, 2, 3, 4, 5},
4481 0.354, /* > sqrt(0.25*0.25 + 0.25*0.25) */
4482 {-1, -1, 1, 0, -1, -1},
4484 { /* adjacent faces must have opposite winding orders at the shared edge */
4485 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}},
4486 2, {0, 1, 2, 0, 3, 2},
4487 0.0,
4488 {-1, -1, -1, -1, -1, -1},
4491 struct test_context *test_context;
4493 if (!(test_context = new_test_context()))
4495 skip("Couldn't create test context\n");
4496 return;
4498 device = test_context->device;
4500 for (i = 0; i < ARRAY_SIZE(test_data); i++)
4502 DWORD adjacency[ARRAY_SIZE(test_data[0].adjacency)];
4503 int j;
4505 if (d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh);
4506 d3dxmesh = NULL;
4508 hr = D3DXCreateMeshFVF(test_data[i].num_faces, test_data[i].num_vertices, 0, D3DFVF_XYZ, device, &d3dxmesh);
4509 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
4511 hr = d3dxmesh->lpVtbl->LockVertexBuffer(d3dxmesh, D3DLOCK_DISCARD, (void**)&vertices);
4512 ok(hr == D3D_OK, "test %d: Got result %x, expected %x (D3D_OK)\n", i, hr, D3D_OK);
4513 if (FAILED(hr)) continue;
4514 CopyMemory(vertices, test_data[i].vertices, test_data[i].num_vertices * sizeof(test_data[0].vertices[0]));
4515 d3dxmesh->lpVtbl->UnlockVertexBuffer(d3dxmesh);
4517 hr = d3dxmesh->lpVtbl->LockIndexBuffer(d3dxmesh, D3DLOCK_DISCARD, (void**)&indices);
4518 ok(hr == D3D_OK, "test %d: Got result %x, expected %x (D3D_OK)\n", i, hr, D3D_OK);
4519 if (FAILED(hr)) continue;
4520 CopyMemory(indices, test_data[i].indices, test_data[i].num_faces * 3 * sizeof(test_data[0].indices[0]));
4521 d3dxmesh->lpVtbl->UnlockIndexBuffer(d3dxmesh);
4523 if (i == 0) {
4524 hr = d3dxmesh->lpVtbl->GenerateAdjacency(d3dxmesh, 0.0f, NULL);
4525 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4528 hr = d3dxmesh->lpVtbl->GenerateAdjacency(d3dxmesh, test_data[i].epsilon, adjacency);
4529 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
4530 if (FAILED(hr)) continue;
4532 for (j = 0; j < test_data[i].num_faces * 3; j++)
4533 ok(adjacency[j] == test_data[i].adjacency[j],
4534 "Test %d adjacency %d: Got result %u, expected %u\n", i, j,
4535 adjacency[j], test_data[i].adjacency[j]);
4537 if (d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh);
4539 free_test_context(test_context);
4542 static void test_update_semantics(void)
4544 HRESULT hr;
4545 struct test_context *test_context = NULL;
4546 ID3DXMesh *mesh = NULL;
4547 D3DVERTEXELEMENT9 declaration0[] =
4549 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4550 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4551 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4552 D3DDECL_END()
4554 D3DVERTEXELEMENT9 declaration_pos_type_color[] =
4556 {0, 0, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4557 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4558 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4559 D3DDECL_END()
4561 D3DVERTEXELEMENT9 declaration_smaller[] =
4563 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4564 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4565 D3DDECL_END()
4567 D3DVERTEXELEMENT9 declaration_larger[] =
4569 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4570 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4571 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4572 {0, 40, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT, 0},
4573 D3DDECL_END()
4575 D3DVERTEXELEMENT9 declaration_multiple_streams[] =
4577 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4578 {1, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT, 0},
4579 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4580 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4582 D3DDECL_END()
4584 D3DVERTEXELEMENT9 declaration_double_usage[] =
4586 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4587 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4588 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4589 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4590 D3DDECL_END()
4592 D3DVERTEXELEMENT9 declaration_undefined_type[] =
4594 {0, 0, D3DDECLTYPE_UNUSED+1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4595 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4596 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4597 D3DDECL_END()
4599 D3DVERTEXELEMENT9 declaration_not_4_byte_aligned_offset[] =
4601 {0, 3, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4602 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4603 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4604 D3DDECL_END()
4606 static const struct
4608 D3DXVECTOR3 position0;
4609 D3DXVECTOR3 position1;
4610 D3DXVECTOR3 normal;
4611 DWORD color;
4613 vertices[] =
4615 { { 0.0f, 1.0f, 0.f}, { 1.0f, 0.0f, 0.f}, {0.0f, 0.0f, 1.0f}, 0xffff0000 },
4616 { { 1.0f, -1.0f, 0.f}, {-1.0f, -1.0f, 0.f}, {0.0f, 0.0f, 1.0f}, 0xff00ff00 },
4617 { {-1.0f, -1.0f, 0.f}, {-1.0f, 1.0f, 0.f}, {0.0f, 0.0f, 1.0f}, 0xff0000ff },
4619 unsigned int faces[] = {0, 1, 2};
4620 unsigned int attributes[] = {0};
4621 unsigned int num_faces = ARRAY_SIZE(faces) / 3;
4622 unsigned int num_vertices = ARRAY_SIZE(vertices);
4623 int offset = sizeof(D3DXVECTOR3);
4624 DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
4625 void *vertex_buffer;
4626 void *index_buffer;
4627 DWORD *attributes_buffer;
4628 D3DVERTEXELEMENT9 declaration[MAX_FVF_DECL_SIZE];
4629 D3DVERTEXELEMENT9 *decl_ptr;
4630 DWORD exp_vertex_size = sizeof(*vertices);
4631 DWORD vertex_size = 0;
4632 int equal;
4633 int i = 0;
4634 int *decl_mem;
4635 int filler_a = 0xaaaaaaaa;
4636 int filler_b = 0xbbbbbbbb;
4638 test_context = new_test_context();
4639 if (!test_context)
4641 skip("Couldn't create a test_context\n");
4642 goto cleanup;
4645 hr = D3DXCreateMesh(num_faces, num_vertices, options, declaration0,
4646 test_context->device, &mesh);
4647 if (FAILED(hr))
4649 skip("Couldn't create test mesh %#x\n", hr);
4650 goto cleanup;
4653 mesh->lpVtbl->LockVertexBuffer(mesh, 0, &vertex_buffer);
4654 memcpy(vertex_buffer, vertices, sizeof(vertices));
4655 mesh->lpVtbl->UnlockVertexBuffer(mesh);
4657 mesh->lpVtbl->LockIndexBuffer(mesh, 0, &index_buffer);
4658 memcpy(index_buffer, faces, sizeof(faces));
4659 mesh->lpVtbl->UnlockIndexBuffer(mesh);
4661 mesh->lpVtbl->LockAttributeBuffer(mesh, 0, &attributes_buffer);
4662 memcpy(attributes_buffer, attributes, sizeof(attributes));
4663 mesh->lpVtbl->UnlockAttributeBuffer(mesh);
4665 /* Get the declaration and try to change it */
4666 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4667 if (FAILED(hr))
4669 skip("Couldn't get vertex declaration %#x\n", hr);
4670 goto cleanup;
4672 equal = memcmp(declaration, declaration0, sizeof(declaration0));
4673 ok(equal == 0, "Vertex declarations were not equal\n");
4675 for (decl_ptr = declaration; decl_ptr->Stream != 0xFF; decl_ptr++)
4677 if (decl_ptr->Usage == D3DDECLUSAGE_POSITION)
4679 /* Use second vertex position instead of first */
4680 decl_ptr->Offset = offset;
4684 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration);
4685 ok(hr == D3D_OK, "Test UpdateSematics, got %#x expected %#x\n", hr, D3D_OK);
4687 /* Check that declaration was written by getting it again */
4688 memset(declaration, 0, sizeof(declaration));
4689 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4690 if (FAILED(hr))
4692 skip("Couldn't get vertex declaration %#x\n", hr);
4693 goto cleanup;
4696 for (decl_ptr = declaration; decl_ptr->Stream != 0xFF; decl_ptr++)
4698 if (decl_ptr->Usage == D3DDECLUSAGE_POSITION)
4700 ok(decl_ptr->Offset == offset, "Test UpdateSematics, got offset %d expected %d\n",
4701 decl_ptr->Offset, offset);
4705 /* Check that GetDeclaration only writes up to the D3DDECL_END() marker and
4706 * not the full MAX_FVF_DECL_SIZE elements.
4708 memset(declaration, filler_a, sizeof(declaration));
4709 memcpy(declaration, declaration0, sizeof(declaration0));
4710 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration);
4711 ok(hr == D3D_OK, "Test UpdateSematics, "
4712 "got %#x expected D3D_OK\n", hr);
4713 memset(declaration, filler_b, sizeof(declaration));
4714 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4715 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4716 decl_mem = (int*)declaration;
4717 for (i = sizeof(declaration0)/sizeof(*decl_mem); i < sizeof(declaration)/sizeof(*decl_mem); i++)
4719 equal = memcmp(&decl_mem[i], &filler_b, sizeof(filler_b));
4720 ok(equal == 0,
4721 "GetDeclaration wrote past the D3DDECL_END() marker. "
4722 "Got %#x, expected %#x\n", decl_mem[i], filler_b);
4723 if (equal != 0) break;
4726 /* UpdateSemantics does not check for overlapping fields */
4727 memset(declaration, 0, sizeof(declaration));
4728 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4729 if (FAILED(hr))
4731 skip("Couldn't get vertex declaration %#x\n", hr);
4732 goto cleanup;
4735 for (decl_ptr = declaration; decl_ptr->Stream != 0xFF; decl_ptr++)
4737 if (decl_ptr->Type == D3DDECLTYPE_FLOAT3)
4739 decl_ptr->Type = D3DDECLTYPE_FLOAT4;
4743 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration);
4744 ok(hr == D3D_OK, "Test UpdateSematics for overlapping fields, "
4745 "got %#x expected D3D_OK\n", hr);
4747 /* Set the position type to color instead of float3 */
4748 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_pos_type_color);
4749 ok(hr == D3D_OK, "Test UpdateSematics position type color, "
4750 "got %#x expected D3D_OK\n", hr);
4752 /* The following test cases show that NULL, smaller or larger declarations,
4753 * and declarations with non-zero Stream values are not accepted.
4754 * UpdateSemantics returns D3DERR_INVALIDCALL and the previously set
4755 * declaration will be used by DrawSubset, GetNumBytesPerVertex, and
4756 * GetDeclaration.
4759 /* Null declaration (invalid declaration) */
4760 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4761 hr = mesh->lpVtbl->UpdateSemantics(mesh, NULL);
4762 ok(hr == D3DERR_INVALIDCALL, "Test UpdateSematics null pointer declaration, "
4763 "got %#x expected D3DERR_INVALIDCALL\n", hr);
4764 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4765 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4766 vertex_size, exp_vertex_size);
4767 memset(declaration, 0, sizeof(declaration));
4768 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4769 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4770 equal = memcmp(declaration, declaration0, sizeof(declaration0));
4771 ok(equal == 0, "Vertex declarations were not equal\n");
4773 /* Smaller vertex declaration (invalid declaration) */
4774 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4775 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_smaller);
4776 ok(hr == D3DERR_INVALIDCALL, "Test UpdateSematics for smaller vertex declaration, "
4777 "got %#x expected D3DERR_INVALIDCALL\n", hr);
4778 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4779 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4780 vertex_size, exp_vertex_size);
4781 memset(declaration, 0, sizeof(declaration));
4782 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4783 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4784 equal = memcmp(declaration, declaration0, sizeof(declaration0));
4785 ok(equal == 0, "Vertex declarations were not equal\n");
4787 /* Larger vertex declaration (invalid declaration) */
4788 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4789 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_larger);
4790 ok(hr == D3DERR_INVALIDCALL, "Test UpdateSematics for larger vertex declaration, "
4791 "got %#x expected D3DERR_INVALIDCALL\n", hr);
4792 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4793 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4794 vertex_size, exp_vertex_size);
4795 memset(declaration, 0, sizeof(declaration));
4796 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4797 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4798 equal = memcmp(declaration, declaration0, sizeof(declaration0));
4799 ok(equal == 0, "Vertex declarations were not equal\n");
4801 /* Use multiple streams and keep the same vertex size (invalid declaration) */
4802 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4803 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_multiple_streams);
4804 ok(hr == D3DERR_INVALIDCALL, "Test UpdateSematics using multiple streams, "
4805 "got %#x expected D3DERR_INVALIDCALL\n", hr);
4806 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4807 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4808 vertex_size, exp_vertex_size);
4809 memset(declaration, 0, sizeof(declaration));
4810 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4811 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4812 equal = memcmp(declaration, declaration0, sizeof(declaration0));
4813 ok(equal == 0, "Vertex declarations were not equal\n");
4815 /* The next following test cases show that some invalid declarations are
4816 * accepted with a D3D_OK. An access violation is thrown on Windows if
4817 * DrawSubset is called. The methods GetNumBytesPerVertex and GetDeclaration
4818 * are not affected, which indicates that the declaration is cached.
4821 /* Double usage (invalid declaration) */
4822 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4823 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_double_usage);
4824 ok(hr == D3D_OK, "Test UpdateSematics double usage, "
4825 "got %#x expected D3D_OK\n", hr);
4826 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4827 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4828 vertex_size, exp_vertex_size);
4829 memset(declaration, 0, sizeof(declaration));
4830 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4831 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4832 equal = memcmp(declaration, declaration_double_usage, sizeof(declaration_double_usage));
4833 ok(equal == 0, "Vertex declarations were not equal\n");
4835 /* Set the position to an undefined type (invalid declaration) */
4836 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4837 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_undefined_type);
4838 ok(hr == D3D_OK, "Test UpdateSematics undefined type, "
4839 "got %#x expected D3D_OK\n", hr);
4840 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4841 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4842 vertex_size, exp_vertex_size);
4843 memset(declaration, 0, sizeof(declaration));
4844 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4845 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4846 equal = memcmp(declaration, declaration_undefined_type, sizeof(declaration_undefined_type));
4847 ok(equal == 0, "Vertex declarations were not equal\n");
4849 /* Use a not 4 byte aligned offset (invalid declaration) */
4850 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4851 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_not_4_byte_aligned_offset);
4852 ok(hr == D3D_OK, "Test UpdateSematics not 4 byte aligned offset, "
4853 "got %#x expected D3D_OK\n", hr);
4854 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4855 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4856 vertex_size, exp_vertex_size);
4857 memset(declaration, 0, sizeof(declaration));
4858 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4859 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4860 equal = memcmp(declaration, declaration_not_4_byte_aligned_offset,
4861 sizeof(declaration_not_4_byte_aligned_offset));
4862 ok(equal == 0, "Vertex declarations were not equal\n");
4864 cleanup:
4865 if (mesh)
4866 mesh->lpVtbl->Release(mesh);
4868 free_test_context(test_context);
4871 static void test_create_skin_info(void)
4873 HRESULT hr;
4874 ID3DXSkinInfo *skininfo = NULL;
4875 D3DVERTEXELEMENT9 empty_declaration[] = { D3DDECL_END() };
4876 D3DVERTEXELEMENT9 declaration_out[MAX_FVF_DECL_SIZE];
4877 const D3DVERTEXELEMENT9 declaration_with_nonzero_stream[] = {
4878 {1, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
4879 D3DDECL_END()
4882 hr = D3DXCreateSkinInfo(0, empty_declaration, 0, &skininfo);
4883 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4884 if (skininfo) IUnknown_Release(skininfo);
4885 skininfo = NULL;
4887 hr = D3DXCreateSkinInfo(1, NULL, 1, &skininfo);
4888 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4890 hr = D3DXCreateSkinInfo(1, declaration_with_nonzero_stream, 1, &skininfo);
4891 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4893 hr = D3DXCreateSkinInfoFVF(1, 0, 1, &skininfo);
4894 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4895 if (skininfo)
4897 DWORD dword_result;
4898 float flt_result;
4899 const char *string_result;
4900 D3DXMATRIX *transform;
4901 D3DXMATRIX identity_matrix;
4903 /* test initial values */
4904 hr = skininfo->lpVtbl->GetDeclaration(skininfo, declaration_out);
4905 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4906 if (SUCCEEDED(hr))
4907 compare_elements(declaration_out, empty_declaration, __LINE__, 0);
4909 dword_result = skininfo->lpVtbl->GetNumBones(skininfo);
4910 ok(dword_result == 1, "Expected 1, got %u\n", dword_result);
4912 flt_result = skininfo->lpVtbl->GetMinBoneInfluence(skininfo);
4913 ok(flt_result == 0.0f, "Expected 0.0, got %g\n", flt_result);
4915 string_result = skininfo->lpVtbl->GetBoneName(skininfo, 0);
4916 ok(string_result == NULL, "Expected NULL, got %p\n", string_result);
4918 dword_result = skininfo->lpVtbl->GetFVF(skininfo);
4919 ok(dword_result == 0, "Expected 0, got %u\n", dword_result);
4921 dword_result = skininfo->lpVtbl->GetNumBoneInfluences(skininfo, 0);
4922 ok(dword_result == 0, "Expected 0, got %u\n", dword_result);
4924 dword_result = skininfo->lpVtbl->GetNumBoneInfluences(skininfo, 1);
4925 ok(dword_result == 0, "Expected 0, got %u\n", dword_result);
4927 transform = skininfo->lpVtbl->GetBoneOffsetMatrix(skininfo, -1);
4928 ok(transform == NULL, "Expected NULL, got %p\n", transform);
4931 /* test [GS]etBoneOffsetMatrix */
4932 hr = skininfo->lpVtbl->SetBoneOffsetMatrix(skininfo, 1, &identity_matrix);
4933 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4935 hr = skininfo->lpVtbl->SetBoneOffsetMatrix(skininfo, 0, NULL);
4936 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4938 D3DXMatrixIdentity(&identity_matrix);
4939 hr = skininfo->lpVtbl->SetBoneOffsetMatrix(skininfo, 0, &identity_matrix);
4940 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4942 transform = skininfo->lpVtbl->GetBoneOffsetMatrix(skininfo, 0);
4943 check_matrix(transform, &identity_matrix);
4947 /* test [GS]etBoneName */
4948 const char *name_in = "testBoneName";
4949 const char *string_result2;
4951 hr = skininfo->lpVtbl->SetBoneName(skininfo, 1, name_in);
4952 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4954 hr = skininfo->lpVtbl->SetBoneName(skininfo, 0, NULL);
4955 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4957 hr = skininfo->lpVtbl->SetBoneName(skininfo, 0, name_in);
4958 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4960 string_result = skininfo->lpVtbl->GetBoneName(skininfo, 0);
4961 ok(string_result != NULL, "Expected non-NULL string, got %p\n", string_result);
4962 ok(!strcmp(string_result, name_in), "Expected '%s', got '%s'\n", name_in, string_result);
4964 string_result2 = skininfo->lpVtbl->GetBoneName(skininfo, 0);
4965 ok(string_result == string_result2, "Expected %p, got %p\n", string_result, string_result2);
4967 string_result = skininfo->lpVtbl->GetBoneName(skininfo, 1);
4968 ok(string_result == NULL, "Expected NULL, got %p\n", string_result);
4972 /* test [GS]etBoneInfluence */
4973 DWORD vertices[2];
4974 FLOAT weights[2];
4975 int i;
4976 DWORD num_influences;
4977 DWORD exp_vertices[2];
4978 FLOAT exp_weights[2];
4980 /* vertex and weight arrays untouched when num_influences is 0 */
4981 vertices[0] = 0xdeadbeef;
4982 weights[0] = FLT_MAX;
4983 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, vertices, weights);
4984 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4985 ok(vertices[0] == 0xdeadbeef, "expected 0xdeadbeef, got %#x\n", vertices[0]);
4986 ok(weights[0] == FLT_MAX, "expected %g, got %g\n", FLT_MAX, weights[0]);
4988 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 1, vertices, weights);
4989 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4991 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, NULL, NULL);
4992 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4994 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, vertices, NULL);
4995 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4997 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, NULL, weights);
4998 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5001 /* no vertex or weight value checking */
5002 exp_vertices[0] = 0;
5003 exp_vertices[1] = 0x87654321;
5004 exp_weights[0] = 0.5;
5005 exp_weights[1] = NAN;
5006 num_influences = 2;
5008 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 1, num_influences, vertices, weights);
5009 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5011 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, num_influences, NULL, weights);
5012 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5014 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, num_influences, vertices, NULL);
5015 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5017 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, num_influences, NULL, NULL);
5018 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5020 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, num_influences, exp_vertices, exp_weights);
5021 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5023 memset(vertices, 0, sizeof(vertices));
5024 memset(weights, 0, sizeof(weights));
5025 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, vertices, weights);
5026 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5027 for (i = 0; i < num_influences; i++) {
5028 ok(exp_vertices[i] == vertices[i],
5029 "influence[%d]: expected vertex %u, got %u\n", i, exp_vertices[i], vertices[i]);
5030 ok((isnan(exp_weights[i]) && isnan(weights[i])) || exp_weights[i] == weights[i],
5031 "influence[%d]: expected weights %g, got %g\n", i, exp_weights[i], weights[i]);
5034 /* vertices and weights aren't returned after setting num_influences to 0 */
5035 memset(vertices, 0, sizeof(vertices));
5036 memset(weights, 0, sizeof(weights));
5037 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, 0, vertices, weights);
5038 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5040 vertices[0] = 0xdeadbeef;
5041 weights[0] = FLT_MAX;
5042 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, vertices, weights);
5043 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5044 ok(vertices[0] == 0xdeadbeef, "expected vertex 0xdeadbeef, got %u\n", vertices[0]);
5045 ok(weights[0] == FLT_MAX, "expected weight %g, got %g\n", FLT_MAX, weights[0]);
5049 /* test [GS]etFVF and [GS]etDeclaration */
5050 D3DVERTEXELEMENT9 declaration_in[MAX_FVF_DECL_SIZE];
5051 DWORD fvf = D3DFVF_XYZ;
5052 DWORD got_fvf;
5054 hr = skininfo->lpVtbl->SetDeclaration(skininfo, NULL);
5055 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5057 hr = skininfo->lpVtbl->SetDeclaration(skininfo, declaration_with_nonzero_stream);
5058 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5060 hr = skininfo->lpVtbl->SetFVF(skininfo, 0);
5061 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5063 hr = D3DXDeclaratorFromFVF(fvf, declaration_in);
5064 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5065 hr = skininfo->lpVtbl->SetDeclaration(skininfo, declaration_in);
5066 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5067 got_fvf = skininfo->lpVtbl->GetFVF(skininfo);
5068 ok(fvf == got_fvf, "Expected %#x, got %#x\n", fvf, got_fvf);
5069 hr = skininfo->lpVtbl->GetDeclaration(skininfo, declaration_out);
5070 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5071 compare_elements(declaration_out, declaration_in, __LINE__, 0);
5073 hr = skininfo->lpVtbl->SetDeclaration(skininfo, empty_declaration);
5074 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5075 got_fvf = skininfo->lpVtbl->GetFVF(skininfo);
5076 ok(got_fvf == 0, "Expected 0, got %#x\n", got_fvf);
5077 hr = skininfo->lpVtbl->GetDeclaration(skininfo, declaration_out);
5078 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5079 compare_elements(declaration_out, empty_declaration, __LINE__, 0);
5081 hr = skininfo->lpVtbl->SetFVF(skininfo, fvf);
5082 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5083 got_fvf = skininfo->lpVtbl->GetFVF(skininfo);
5084 ok(fvf == got_fvf, "Expected %#x, got %#x\n", fvf, got_fvf);
5085 hr = skininfo->lpVtbl->GetDeclaration(skininfo, declaration_out);
5086 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5087 compare_elements(declaration_out, declaration_in, __LINE__, 0);
5090 if (skininfo) IUnknown_Release(skininfo);
5091 skininfo = NULL;
5093 hr = D3DXCreateSkinInfoFVF(1, D3DFVF_XYZ, 1, NULL);
5094 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5096 hr = D3DXCreateSkinInfo(1, NULL, 1, &skininfo);
5097 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5100 static void test_convert_adjacency_to_point_reps(void)
5102 HRESULT hr;
5103 struct test_context *test_context = NULL;
5104 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
5105 const DWORD options_16bit = D3DXMESH_SYSTEMMEM;
5106 const D3DVERTEXELEMENT9 declaration[] =
5108 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
5109 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
5110 {0, 24, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
5111 D3DDECL_END()
5113 const unsigned int VERTS_PER_FACE = 3;
5114 void *vertex_buffer;
5115 void *index_buffer;
5116 DWORD *attributes_buffer;
5117 int i, j;
5118 enum color { RED = 0xffff0000, GREEN = 0xff00ff00, BLUE = 0xff0000ff};
5119 struct vertex_pnc
5121 D3DXVECTOR3 position;
5122 D3DXVECTOR3 normal;
5123 enum color color; /* In case of manual visual inspection */
5125 D3DXVECTOR3 up = {0.0f, 0.0f, 1.0f};
5126 /* mesh0 (one face)
5128 * 0--1
5129 * | /
5130 * |/
5133 const struct vertex_pnc vertices0[] =
5135 {{ 0.0f, 3.0f, 0.f}, up, RED},
5136 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5137 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5139 const DWORD indices0[] = {0, 1, 2};
5140 const unsigned int num_vertices0 = ARRAY_SIZE(vertices0);
5141 const unsigned int num_faces0 = ARRAY_SIZE(indices0) / VERTS_PER_FACE;
5142 const DWORD adjacency0[] = {-1, -1, -1};
5143 const DWORD exp_point_rep0[] = {0, 1, 2};
5144 /* mesh1 (right)
5146 * 0--1 3
5147 * | / /|
5148 * |/ / |
5149 * 2 5--4
5151 const struct vertex_pnc vertices1[] =
5153 {{ 0.0f, 3.0f, 0.f}, up, RED},
5154 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5155 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5157 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5158 {{ 3.0f, 0.0f, 0.f}, up, RED},
5159 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5161 const DWORD indices1[] = {0, 1, 2, 3, 4, 5};
5162 const unsigned int num_vertices1 = ARRAY_SIZE(vertices1);
5163 const unsigned int num_faces1 = ARRAY_SIZE(indices1) / VERTS_PER_FACE;
5164 const DWORD adjacency1[] = {-1, 1, -1, -1, -1, 0};
5165 const DWORD exp_point_rep1[] = {0, 1, 2, 1, 4, 2};
5166 /* mesh2 (left)
5168 * 3 0--1
5169 * /| | /
5170 * / | |/
5171 * 5--4 2
5173 const struct vertex_pnc vertices2[] =
5175 {{ 0.0f, 3.0f, 0.f}, up, RED},
5176 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5177 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5179 {{-1.0f, 3.0f, 0.f}, up, RED},
5180 {{-1.0f, 0.0f, 0.f}, up, GREEN},
5181 {{-3.0f, 0.0f, 0.f}, up, BLUE},
5183 const DWORD indices2[] = {0, 1, 2, 3, 4, 5};
5184 const unsigned int num_vertices2 = ARRAY_SIZE(vertices2);
5185 const unsigned int num_faces2 = ARRAY_SIZE(indices2) / VERTS_PER_FACE;
5186 const DWORD adjacency2[] = {-1, -1, 1, 0, -1, -1};
5187 const DWORD exp_point_rep2[] = {0, 1, 2, 0, 2, 5};
5188 /* mesh3 (above)
5191 * /|
5192 * / |
5193 * 5--4
5194 * 0--1
5195 * | /
5196 * |/
5199 struct vertex_pnc vertices3[] =
5201 {{ 0.0f, 3.0f, 0.f}, up, RED},
5202 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5203 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5205 {{ 2.0f, 7.0f, 0.f}, up, BLUE},
5206 {{ 2.0f, 4.0f, 0.f}, up, GREEN},
5207 {{ 0.0f, 4.0f, 0.f}, up, RED},
5209 const DWORD indices3[] = {0, 1, 2, 3, 4, 5};
5210 const unsigned int num_vertices3 = ARRAY_SIZE(vertices3);
5211 const unsigned int num_faces3 = ARRAY_SIZE(indices3) / VERTS_PER_FACE;
5212 const DWORD adjacency3[] = {1, -1, -1, -1, 0, -1};
5213 const DWORD exp_point_rep3[] = {0, 1, 2, 3, 1, 0};
5214 /* mesh4 (below, tip against tip)
5216 * 0--1
5217 * | /
5218 * |/
5221 * |\
5222 * | \
5223 * 5--4
5225 struct vertex_pnc vertices4[] =
5227 {{ 0.0f, 3.0f, 0.f}, up, RED},
5228 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5229 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5231 {{ 0.0f, -4.0f, 0.f}, up, BLUE},
5232 {{ 2.0f, -7.0f, 0.f}, up, GREEN},
5233 {{ 0.0f, -7.0f, 0.f}, up, RED},
5235 const DWORD indices4[] = {0, 1, 2, 3, 4, 5};
5236 const unsigned int num_vertices4 = ARRAY_SIZE(vertices4);
5237 const unsigned int num_faces4 = ARRAY_SIZE(indices4) / VERTS_PER_FACE;
5238 const DWORD adjacency4[] = {-1, -1, -1, -1, -1, -1};
5239 const DWORD exp_point_rep4[] = {0, 1, 2, 3, 4, 5};
5240 /* mesh5 (gap in mesh)
5242 * 0 3-----4 15
5243 * / \ \ / / \
5244 * / \ \ / / \
5245 * 2-----1 5 17-----16
5246 * 6-----7 9 12-----13
5247 * \ / / \ \ /
5248 * \ / / \ \ /
5249 * 8 10-----11 14
5252 const struct vertex_pnc vertices5[] =
5254 {{ 0.0f, 1.0f, 0.f}, up, RED},
5255 {{ 1.0f, -1.0f, 0.f}, up, GREEN},
5256 {{-1.0f, -1.0f, 0.f}, up, BLUE},
5258 {{ 0.1f, 1.0f, 0.f}, up, RED},
5259 {{ 2.1f, 1.0f, 0.f}, up, BLUE},
5260 {{ 1.1f, -1.0f, 0.f}, up, GREEN},
5262 {{-1.0f, -1.1f, 0.f}, up, BLUE},
5263 {{ 1.0f, -1.1f, 0.f}, up, GREEN},
5264 {{ 0.0f, -3.1f, 0.f}, up, RED},
5266 {{ 1.1f, -1.1f, 0.f}, up, GREEN},
5267 {{ 2.1f, -3.1f, 0.f}, up, BLUE},
5268 {{ 0.1f, -3.1f, 0.f}, up, RED},
5270 {{ 1.2f, -1.1f, 0.f}, up, GREEN},
5271 {{ 3.2f, -1.1f, 0.f}, up, RED},
5272 {{ 2.2f, -3.1f, 0.f}, up, BLUE},
5274 {{ 2.2f, 1.0f, 0.f}, up, BLUE},
5275 {{ 3.2f, -1.0f, 0.f}, up, RED},
5276 {{ 1.2f, -1.0f, 0.f}, up, GREEN},
5278 const DWORD indices5[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17};
5279 const unsigned int num_vertices5 = ARRAY_SIZE(vertices5);
5280 const unsigned int num_faces5 = ARRAY_SIZE(indices5) / VERTS_PER_FACE;
5281 const DWORD adjacency5[] = {-1, 2, -1, -1, 5, -1, 0, -1, -1, 4, -1, -1, 5, -1, 3, -1, 4, 1};
5282 const DWORD exp_point_rep5[] = {0, 1, 2, 3, 4, 5, 2, 1, 8, 5, 10, 11, 5, 13, 10, 4, 13, 5};
5283 const WORD indices5_16bit[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17};
5284 /* mesh6 (indices re-ordering)
5286 * 0--1 6 3
5287 * | / /| |\
5288 * |/ / | | \
5289 * 2 8--7 5--4
5291 const struct vertex_pnc vertices6[] =
5293 {{ 0.0f, 3.0f, 0.f}, up, RED},
5294 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5295 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5297 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5298 {{ 3.0f, 0.0f, 0.f}, up, RED},
5299 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5301 {{ 4.0f, 3.0f, 0.f}, up, GREEN},
5302 {{ 6.0f, 0.0f, 0.f}, up, BLUE},
5303 {{ 4.0f, 0.0f, 0.f}, up, RED},
5305 const DWORD indices6[] = {0, 1, 2, 6, 7, 8, 3, 4, 5};
5306 const unsigned int num_vertices6 = ARRAY_SIZE(vertices6);
5307 const unsigned int num_faces6 = ARRAY_SIZE(indices6) / VERTS_PER_FACE;
5308 const DWORD adjacency6[] = {-1, 1, -1, 2, -1, 0, -1, -1, 1};
5309 const DWORD exp_point_rep6[] = {0, 1, 2, 1, 4, 5, 1, 5, 2};
5310 /* mesh7 (expands collapsed triangle)
5312 * 0--1 3
5313 * | / /|
5314 * |/ / |
5315 * 2 5--4
5317 const struct vertex_pnc vertices7[] =
5319 {{ 0.0f, 3.0f, 0.f}, up, RED},
5320 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5321 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5323 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5324 {{ 3.0f, 0.0f, 0.f}, up, RED},
5325 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5327 const DWORD indices7[] = {0, 1, 2, 3, 3, 3}; /* Face 1 is collapsed*/
5328 const unsigned int num_vertices7 = ARRAY_SIZE(vertices7);
5329 const unsigned int num_faces7 = ARRAY_SIZE(indices7) / VERTS_PER_FACE;
5330 const DWORD adjacency7[] = {-1, -1, -1, -1, -1, -1};
5331 const DWORD exp_point_rep7[] = {0, 1, 2, 3, 4, 5};
5332 /* mesh8 (indices re-ordering and double replacement)
5334 * 0--1 9 6
5335 * | / /| |\
5336 * |/ / | | \
5337 * 2 11-10 8--7
5338 * 3--4
5339 * | /
5340 * |/
5343 const struct vertex_pnc vertices8[] =
5345 {{ 0.0f, 3.0f, 0.f}, up, RED},
5346 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5347 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5349 {{ 4.0, -4.0, 0.f}, up, RED},
5350 {{ 6.0, -4.0, 0.f}, up, BLUE},
5351 {{ 4.0, -7.0, 0.f}, up, GREEN},
5353 {{ 4.0f, 3.0f, 0.f}, up, GREEN},
5354 {{ 6.0f, 0.0f, 0.f}, up, BLUE},
5355 {{ 4.0f, 0.0f, 0.f}, up, RED},
5357 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5358 {{ 3.0f, 0.0f, 0.f}, up, RED},
5359 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5361 const DWORD indices8[] = {0, 1, 2, 9, 10, 11, 6, 7, 8, 3, 4, 5};
5362 const unsigned int num_vertices8 = ARRAY_SIZE(vertices8);
5363 const unsigned int num_faces8 = ARRAY_SIZE(indices8) / VERTS_PER_FACE;
5364 const DWORD adjacency8[] = {-1, 1, -1, 2, -1, 0, -1, 3, 1, 2, -1, -1};
5365 const DWORD exp_point_rep8[] = {0, 1, 2, 3, 4, 5, 1, 4, 3, 1, 3, 2};
5366 /* mesh9 (right, shared vertices)
5368 * 0--1
5369 * | /|
5370 * |/ |
5371 * 2--3
5373 const struct vertex_pnc vertices9[] =
5375 {{ 0.0f, 3.0f, 0.f}, up, RED},
5376 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5377 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5379 {{ 2.0f, 0.0f, 0.f}, up, RED},
5381 const DWORD indices9[] = {0, 1, 2, 1, 3, 2};
5382 const unsigned int num_vertices9 = ARRAY_SIZE(vertices9);
5383 const unsigned int num_faces9 = ARRAY_SIZE(indices9) / VERTS_PER_FACE;
5384 const DWORD adjacency9[] = {-1, 1, -1, -1, -1, 0};
5385 const DWORD exp_point_rep9[] = {0, 1, 2, 3};
5386 /* All mesh data */
5387 ID3DXMesh *mesh = NULL;
5388 ID3DXMesh *mesh_null_check = NULL;
5389 unsigned int attributes[] = {0};
5390 struct
5392 const struct vertex_pnc *vertices;
5393 const DWORD *indices;
5394 const DWORD num_vertices;
5395 const DWORD num_faces;
5396 const DWORD *adjacency;
5397 const DWORD *exp_point_reps;
5398 const DWORD options;
5400 tc[] =
5403 vertices0,
5404 indices0,
5405 num_vertices0,
5406 num_faces0,
5407 adjacency0,
5408 exp_point_rep0,
5409 options
5412 vertices1,
5413 indices1,
5414 num_vertices1,
5415 num_faces1,
5416 adjacency1,
5417 exp_point_rep1,
5418 options
5421 vertices2,
5422 indices2,
5423 num_vertices2,
5424 num_faces2,
5425 adjacency2,
5426 exp_point_rep2,
5427 options
5430 vertices3,
5431 indices3,
5432 num_vertices3,
5433 num_faces3,
5434 adjacency3,
5435 exp_point_rep3,
5436 options
5439 vertices4,
5440 indices4,
5441 num_vertices4,
5442 num_faces4,
5443 adjacency4,
5444 exp_point_rep4,
5445 options
5448 vertices5,
5449 indices5,
5450 num_vertices5,
5451 num_faces5,
5452 adjacency5,
5453 exp_point_rep5,
5454 options
5457 vertices6,
5458 indices6,
5459 num_vertices6,
5460 num_faces6,
5461 adjacency6,
5462 exp_point_rep6,
5463 options
5466 vertices7,
5467 indices7,
5468 num_vertices7,
5469 num_faces7,
5470 adjacency7,
5471 exp_point_rep7,
5472 options
5475 vertices8,
5476 indices8,
5477 num_vertices8,
5478 num_faces8,
5479 adjacency8,
5480 exp_point_rep8,
5481 options
5484 vertices9,
5485 indices9,
5486 num_vertices9,
5487 num_faces9,
5488 adjacency9,
5489 exp_point_rep9,
5490 options
5493 vertices5,
5494 (DWORD*)indices5_16bit,
5495 num_vertices5,
5496 num_faces5,
5497 adjacency5,
5498 exp_point_rep5,
5499 options_16bit
5502 DWORD *point_reps = NULL;
5504 test_context = new_test_context();
5505 if (!test_context)
5507 skip("Couldn't create test context\n");
5508 goto cleanup;
5511 for (i = 0; i < ARRAY_SIZE(tc); i++)
5513 hr = D3DXCreateMesh(tc[i].num_faces, tc[i].num_vertices, tc[i].options, declaration,
5514 test_context->device, &mesh);
5515 if (FAILED(hr))
5517 skip("Couldn't create mesh %d. Got %x expected D3D_OK\n", i, hr);
5518 goto cleanup;
5521 if (i == 0) /* Save first mesh for later NULL checks */
5522 mesh_null_check = mesh;
5524 point_reps = HeapAlloc(GetProcessHeap(), 0, tc[i].num_vertices * sizeof(*point_reps));
5525 if (!point_reps)
5527 skip("Couldn't allocate point reps array.\n");
5528 goto cleanup;
5531 hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, &vertex_buffer);
5532 if (FAILED(hr))
5534 skip("Couldn't lock vertex buffer.\n");
5535 goto cleanup;
5537 memcpy(vertex_buffer, tc[i].vertices, tc[i].num_vertices * sizeof(*tc[i].vertices));
5538 hr = mesh->lpVtbl->UnlockVertexBuffer(mesh);
5539 if (FAILED(hr))
5541 skip("Couldn't unlock vertex buffer.\n");
5542 goto cleanup;
5545 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, &index_buffer);
5546 if (FAILED(hr))
5548 skip("Couldn't lock index buffer.\n");
5549 goto cleanup;
5551 if (tc[i].options & D3DXMESH_32BIT)
5553 memcpy(index_buffer, tc[i].indices, VERTS_PER_FACE * tc[i].num_faces * sizeof(DWORD));
5555 else
5557 memcpy(index_buffer, tc[i].indices, VERTS_PER_FACE * tc[i].num_faces * sizeof(WORD));
5559 hr = mesh->lpVtbl->UnlockIndexBuffer(mesh);
5560 if (FAILED(hr)) {
5561 skip("Couldn't unlock index buffer.\n");
5562 goto cleanup;
5565 hr = mesh->lpVtbl->LockAttributeBuffer(mesh, 0, &attributes_buffer);
5566 if (FAILED(hr))
5568 skip("Couldn't lock attributes buffer.\n");
5569 goto cleanup;
5571 memcpy(attributes_buffer, attributes, sizeof(attributes));
5572 hr = mesh->lpVtbl->UnlockAttributeBuffer(mesh);
5573 if (FAILED(hr))
5575 skip("Couldn't unlock attributes buffer.\n");
5576 goto cleanup;
5579 /* Convert adjacency to point representation */
5580 for (j = 0; j < tc[i].num_vertices; j++) point_reps[j] = -1;
5581 hr = mesh->lpVtbl->ConvertAdjacencyToPointReps(mesh, tc[i].adjacency, point_reps);
5582 ok(hr == D3D_OK, "ConvertAdjacencyToPointReps failed case %d. "
5583 "Got %x expected D3D_OK\n", i, hr);
5585 /* Check point representation */
5586 for (j = 0; j < tc[i].num_vertices; j++)
5588 ok(point_reps[j] == tc[i].exp_point_reps[j],
5589 "Unexpected point representation at (%d, %d)."
5590 " Got %d expected %d\n",
5591 i, j, point_reps[j], tc[i].exp_point_reps[j]);
5594 HeapFree(GetProcessHeap(), 0, point_reps);
5595 point_reps = NULL;
5597 if (i != 0) /* First mesh will be freed during cleanup */
5598 mesh->lpVtbl->Release(mesh);
5601 /* NULL checks */
5602 hr = mesh_null_check->lpVtbl->ConvertAdjacencyToPointReps(mesh_null_check, tc[0].adjacency, NULL);
5603 ok(hr == D3DERR_INVALIDCALL, "ConvertAdjacencyToPointReps point_reps NULL. "
5604 "Got %x expected D3DERR_INVALIDCALL\n", hr);
5605 hr = mesh_null_check->lpVtbl->ConvertAdjacencyToPointReps(mesh_null_check, NULL, NULL);
5606 ok(hr == D3DERR_INVALIDCALL, "ConvertAdjacencyToPointReps adjacency and point_reps NULL. "
5607 "Got %x expected D3DERR_INVALIDCALL\n", hr);
5609 cleanup:
5610 if (mesh_null_check)
5611 mesh_null_check->lpVtbl->Release(mesh_null_check);
5612 HeapFree(GetProcessHeap(), 0, point_reps);
5613 free_test_context(test_context);
5616 static void test_convert_point_reps_to_adjacency(void)
5618 HRESULT hr;
5619 struct test_context *test_context = NULL;
5620 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
5621 const DWORD options_16bit = D3DXMESH_SYSTEMMEM;
5622 const D3DVERTEXELEMENT9 declaration[] =
5624 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
5625 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
5626 {0, 24, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
5627 D3DDECL_END()
5629 const unsigned int VERTS_PER_FACE = 3;
5630 void *vertex_buffer;
5631 void *index_buffer;
5632 DWORD *attributes_buffer;
5633 int i, j;
5634 enum color { RED = 0xffff0000, GREEN = 0xff00ff00, BLUE = 0xff0000ff};
5635 struct vertex_pnc
5637 D3DXVECTOR3 position;
5638 D3DXVECTOR3 normal;
5639 enum color color; /* In case of manual visual inspection */
5641 D3DXVECTOR3 up = {0.0f, 0.0f, 1.0f};
5642 /* mesh0 (one face)
5644 * 0--1
5645 * | /
5646 * |/
5649 const struct vertex_pnc vertices0[] =
5651 {{ 0.0f, 3.0f, 0.f}, up, RED},
5652 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5653 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5655 const DWORD indices0[] = {0, 1, 2};
5656 const unsigned int num_vertices0 = ARRAY_SIZE(vertices0);
5657 const unsigned int num_faces0 = num_vertices0 / VERTS_PER_FACE;
5658 const DWORD exp_adjacency0[] = {-1, -1, -1};
5659 const DWORD exp_id_adjacency0[] = {-1, -1, -1};
5660 const DWORD point_rep0[] = {0, 1, 2};
5661 /* mesh1 (right)
5663 * 0--1 3
5664 * | / /|
5665 * |/ / |
5666 * 2 5--4
5668 const struct vertex_pnc vertices1[] =
5670 {{ 0.0f, 3.0f, 0.f}, up, RED},
5671 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5672 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5674 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5675 {{ 3.0f, 0.0f, 0.f}, up, RED},
5676 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5678 const DWORD indices1[] = {0, 1, 2, 3, 4, 5};
5679 const unsigned int num_vertices1 = ARRAY_SIZE(vertices1);
5680 const unsigned int num_faces1 = num_vertices1 / VERTS_PER_FACE;
5681 const DWORD exp_adjacency1[] = {-1, 1, -1, -1, -1, 0};
5682 const DWORD exp_id_adjacency1[] = {-1, -1, -1, -1, -1, -1};
5683 const DWORD point_rep1[] = {0, 1, 2, 1, 4, 2};
5684 /* mesh2 (left)
5686 * 3 0--1
5687 * /| | /
5688 * / | |/
5689 * 5--4 2
5691 const struct vertex_pnc vertices2[] =
5693 {{ 0.0f, 3.0f, 0.f}, up, RED},
5694 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5695 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5697 {{-1.0f, 3.0f, 0.f}, up, RED},
5698 {{-1.0f, 0.0f, 0.f}, up, GREEN},
5699 {{-3.0f, 0.0f, 0.f}, up, BLUE},
5701 const DWORD indices2[] = {0, 1, 2, 3, 4, 5};
5702 const unsigned int num_vertices2 = ARRAY_SIZE(vertices2);
5703 const unsigned int num_faces2 = num_vertices2 / VERTS_PER_FACE;
5704 const DWORD exp_adjacency2[] = {-1, -1, 1, 0, -1, -1};
5705 const DWORD exp_id_adjacency2[] = {-1, -1, -1, -1, -1, -1};
5706 const DWORD point_rep2[] = {0, 1, 2, 0, 2, 5};
5707 /* mesh3 (above)
5710 * /|
5711 * / |
5712 * 5--4
5713 * 0--1
5714 * | /
5715 * |/
5718 struct vertex_pnc vertices3[] =
5720 {{ 0.0f, 3.0f, 0.f}, up, RED},
5721 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5722 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5724 {{ 2.0f, 7.0f, 0.f}, up, BLUE},
5725 {{ 2.0f, 4.0f, 0.f}, up, GREEN},
5726 {{ 0.0f, 4.0f, 0.f}, up, RED},
5728 const DWORD indices3[] = {0, 1, 2, 3, 4, 5};
5729 const unsigned int num_vertices3 = ARRAY_SIZE(vertices3);
5730 const unsigned int num_faces3 = num_vertices3 / VERTS_PER_FACE;
5731 const DWORD exp_adjacency3[] = {1, -1, -1, -1, 0, -1};
5732 const DWORD exp_id_adjacency3[] = {-1, -1, -1, -1, -1, -1};
5733 const DWORD point_rep3[] = {0, 1, 2, 3, 1, 0};
5734 /* mesh4 (below, tip against tip)
5736 * 0--1
5737 * | /
5738 * |/
5741 * |\
5742 * | \
5743 * 5--4
5745 struct vertex_pnc vertices4[] =
5747 {{ 0.0f, 3.0f, 0.f}, up, RED},
5748 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5749 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5751 {{ 0.0f, -4.0f, 0.f}, up, BLUE},
5752 {{ 2.0f, -7.0f, 0.f}, up, GREEN},
5753 {{ 0.0f, -7.0f, 0.f}, up, RED},
5755 const DWORD indices4[] = {0, 1, 2, 3, 4, 5};
5756 const unsigned int num_vertices4 = ARRAY_SIZE(vertices4);
5757 const unsigned int num_faces4 = num_vertices4 / VERTS_PER_FACE;
5758 const DWORD exp_adjacency4[] = {-1, -1, -1, -1, -1, -1};
5759 const DWORD exp_id_adjacency4[] = {-1, -1, -1, -1, -1, -1};
5760 const DWORD point_rep4[] = {0, 1, 2, 3, 4, 5};
5761 /* mesh5 (gap in mesh)
5763 * 0 3-----4 15
5764 * / \ \ / / \
5765 * / \ \ / / \
5766 * 2-----1 5 17-----16
5767 * 6-----7 9 12-----13
5768 * \ / / \ \ /
5769 * \ / / \ \ /
5770 * 8 10-----11 14
5773 const struct vertex_pnc vertices5[] =
5775 {{ 0.0f, 1.0f, 0.f}, up, RED},
5776 {{ 1.0f, -1.0f, 0.f}, up, GREEN},
5777 {{-1.0f, -1.0f, 0.f}, up, BLUE},
5779 {{ 0.1f, 1.0f, 0.f}, up, RED},
5780 {{ 2.1f, 1.0f, 0.f}, up, BLUE},
5781 {{ 1.1f, -1.0f, 0.f}, up, GREEN},
5783 {{-1.0f, -1.1f, 0.f}, up, BLUE},
5784 {{ 1.0f, -1.1f, 0.f}, up, GREEN},
5785 {{ 0.0f, -3.1f, 0.f}, up, RED},
5787 {{ 1.1f, -1.1f, 0.f}, up, GREEN},
5788 {{ 2.1f, -3.1f, 0.f}, up, BLUE},
5789 {{ 0.1f, -3.1f, 0.f}, up, RED},
5791 {{ 1.2f, -1.1f, 0.f}, up, GREEN},
5792 {{ 3.2f, -1.1f, 0.f}, up, RED},
5793 {{ 2.2f, -3.1f, 0.f}, up, BLUE},
5795 {{ 2.2f, 1.0f, 0.f}, up, BLUE},
5796 {{ 3.2f, -1.0f, 0.f}, up, RED},
5797 {{ 1.2f, -1.0f, 0.f}, up, GREEN},
5799 const DWORD indices5[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17};
5800 const unsigned int num_vertices5 = ARRAY_SIZE(vertices5);
5801 const unsigned int num_faces5 = num_vertices5 / VERTS_PER_FACE;
5802 const DWORD exp_adjacency5[] = {-1, 2, -1, -1, 5, -1, 0, -1, -1, 4, -1, -1, 5, -1, 3, -1, 4, 1};
5803 const DWORD exp_id_adjacency5[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
5804 const DWORD point_rep5[] = {0, 1, 2, 3, 4, 5, 2, 1, 8, 5, 10, 11, 5, 13, 10, 4, 13, 5};
5805 /* mesh6 (indices re-ordering)
5807 * 0--1 6 3
5808 * | / /| |\
5809 * |/ / | | \
5810 * 2 8--7 5--4
5812 const struct vertex_pnc vertices6[] =
5814 {{ 0.0f, 3.0f, 0.f}, up, RED},
5815 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5816 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5818 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5819 {{ 3.0f, 0.0f, 0.f}, up, RED},
5820 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5822 {{ 4.0f, 3.0f, 0.f}, up, GREEN},
5823 {{ 6.0f, 0.0f, 0.f}, up, BLUE},
5824 {{ 4.0f, 0.0f, 0.f}, up, RED},
5826 const DWORD indices6[] = {0, 1, 2, 6, 7, 8, 3, 4, 5};
5827 const unsigned int num_vertices6 = ARRAY_SIZE(vertices6);
5828 const unsigned int num_faces6 = num_vertices6 / VERTS_PER_FACE;
5829 const DWORD exp_adjacency6[] = {-1, 1, -1, 2, -1, 0, -1, -1, 1};
5830 const DWORD exp_id_adjacency6[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1};
5831 const DWORD point_rep6[] = {0, 1, 2, 1, 4, 5, 1, 5, 2};
5832 /* mesh7 (expands collapsed triangle)
5834 * 0--1 3
5835 * | / /|
5836 * |/ / |
5837 * 2 5--4
5839 const struct vertex_pnc vertices7[] =
5841 {{ 0.0f, 3.0f, 0.f}, up, RED},
5842 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5843 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5845 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5846 {{ 3.0f, 0.0f, 0.f}, up, RED},
5847 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5849 const DWORD indices7[] = {0, 1, 2, 3, 3, 3}; /* Face 1 is collapsed*/
5850 const unsigned int num_vertices7 = ARRAY_SIZE(vertices7);
5851 const unsigned int num_faces7 = num_vertices7 / VERTS_PER_FACE;
5852 const DWORD exp_adjacency7[] = {-1, -1, -1, -1, -1, -1};
5853 const DWORD exp_id_adjacency7[] = {-1, -1, -1, -1, -1, -1};
5854 const DWORD point_rep7[] = {0, 1, 2, 3, 4, 5};
5855 /* mesh8 (indices re-ordering and double replacement)
5857 * 0--1 9 6
5858 * | / /| |\
5859 * |/ / | | \
5860 * 2 11-10 8--7
5861 * 3--4
5862 * | /
5863 * |/
5866 const struct vertex_pnc vertices8[] =
5868 {{ 0.0f, 3.0f, 0.f}, up, RED},
5869 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5870 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5872 {{ 4.0, -4.0, 0.f}, up, RED},
5873 {{ 6.0, -4.0, 0.f}, up, BLUE},
5874 {{ 4.0, -7.0, 0.f}, up, GREEN},
5876 {{ 4.0f, 3.0f, 0.f}, up, GREEN},
5877 {{ 6.0f, 0.0f, 0.f}, up, BLUE},
5878 {{ 4.0f, 0.0f, 0.f}, up, RED},
5880 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5881 {{ 3.0f, 0.0f, 0.f}, up, RED},
5882 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5884 const DWORD indices8[] = {0, 1, 2, 9, 10, 11, 6, 7, 8, 3, 4, 5};
5885 const WORD indices8_16bit[] = {0, 1, 2, 9, 10, 11, 6, 7, 8, 3, 4, 5};
5886 const unsigned int num_vertices8 = ARRAY_SIZE(vertices8);
5887 const unsigned int num_faces8 = num_vertices8 / VERTS_PER_FACE;
5888 const DWORD exp_adjacency8[] = {-1, 1, -1, 2, -1, 0, -1, 3, 1, 2, -1, -1};
5889 const DWORD exp_id_adjacency8[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
5890 const DWORD point_rep8[] = {0, 1, 2, 3, 4, 5, 1, 4, 3, 1, 3, 2};
5891 /* mesh9 (right, shared vertices)
5893 * 0--1
5894 * | /|
5895 * |/ |
5896 * 2--3
5898 const struct vertex_pnc vertices9[] =
5900 {{ 0.0f, 3.0f, 0.f}, up, RED},
5901 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5902 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5904 {{ 2.0f, 0.0f, 0.f}, up, RED},
5906 const DWORD indices9[] = {0, 1, 2, 1, 3, 2};
5907 const unsigned int num_vertices9 = ARRAY_SIZE(vertices9);
5908 const unsigned int num_faces9 = 2;
5909 const DWORD exp_adjacency9[] = {-1, 1, -1, -1, -1, 0};
5910 const DWORD exp_id_adjacency9[] = {-1, 1, -1, -1, -1, 0};
5911 const DWORD point_rep9[] = {0, 1, 2, 3};
5912 /* All mesh data */
5913 ID3DXMesh *mesh = NULL;
5914 ID3DXMesh *mesh_null_check = NULL;
5915 unsigned int attributes[] = {0};
5916 struct
5918 const struct vertex_pnc *vertices;
5919 const DWORD *indices;
5920 const DWORD num_vertices;
5921 const DWORD num_faces;
5922 const DWORD *point_reps;
5923 const DWORD *exp_adjacency;
5924 const DWORD *exp_id_adjacency;
5925 const DWORD options;
5927 tc[] =
5930 vertices0,
5931 indices0,
5932 num_vertices0,
5933 num_faces0,
5934 point_rep0,
5935 exp_adjacency0,
5936 exp_id_adjacency0,
5937 options
5940 vertices1,
5941 indices1,
5942 num_vertices1,
5943 num_faces1,
5944 point_rep1,
5945 exp_adjacency1,
5946 exp_id_adjacency1,
5947 options
5950 vertices2,
5951 indices2,
5952 num_vertices2,
5953 num_faces2,
5954 point_rep2,
5955 exp_adjacency2,
5956 exp_id_adjacency2,
5957 options
5960 vertices3,
5961 indices3,
5962 num_vertices3,
5963 num_faces3,
5964 point_rep3,
5965 exp_adjacency3,
5966 exp_id_adjacency3,
5967 options
5970 vertices4,
5971 indices4,
5972 num_vertices4,
5973 num_faces4,
5974 point_rep4,
5975 exp_adjacency4,
5976 exp_id_adjacency4,
5977 options
5980 vertices5,
5981 indices5,
5982 num_vertices5,
5983 num_faces5,
5984 point_rep5,
5985 exp_adjacency5,
5986 exp_id_adjacency5,
5987 options
5990 vertices6,
5991 indices6,
5992 num_vertices6,
5993 num_faces6,
5994 point_rep6,
5995 exp_adjacency6,
5996 exp_id_adjacency6,
5997 options
6000 vertices7,
6001 indices7,
6002 num_vertices7,
6003 num_faces7,
6004 point_rep7,
6005 exp_adjacency7,
6006 exp_id_adjacency7,
6007 options
6010 vertices8,
6011 indices8,
6012 num_vertices8,
6013 num_faces8,
6014 point_rep8,
6015 exp_adjacency8,
6016 exp_id_adjacency8,
6017 options
6020 vertices9,
6021 indices9,
6022 num_vertices9,
6023 num_faces9,
6024 point_rep9,
6025 exp_adjacency9,
6026 exp_id_adjacency9,
6027 options
6030 vertices8,
6031 (DWORD*)indices8_16bit,
6032 num_vertices8,
6033 num_faces8,
6034 point_rep8,
6035 exp_adjacency8,
6036 exp_id_adjacency8,
6037 options_16bit
6040 DWORD *adjacency = NULL;
6042 test_context = new_test_context();
6043 if (!test_context)
6045 skip("Couldn't create test context\n");
6046 goto cleanup;
6049 for (i = 0; i < ARRAY_SIZE(tc); i++)
6051 hr = D3DXCreateMesh(tc[i].num_faces, tc[i].num_vertices, tc[i].options,
6052 declaration, test_context->device, &mesh);
6053 if (FAILED(hr))
6055 skip("Couldn't create mesh %d. Got %x expected D3D_OK\n", i, hr);
6056 goto cleanup;
6059 if (i == 0) /* Save first mesh for later NULL checks */
6060 mesh_null_check = mesh;
6062 adjacency = HeapAlloc(GetProcessHeap(), 0, VERTS_PER_FACE * tc[i].num_faces * sizeof(*adjacency));
6063 if (!adjacency)
6065 skip("Couldn't allocate adjacency array.\n");
6066 goto cleanup;
6069 hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, &vertex_buffer);
6070 if (FAILED(hr))
6072 skip("Couldn't lock vertex buffer.\n");
6073 goto cleanup;
6075 memcpy(vertex_buffer, tc[i].vertices, tc[i].num_vertices * sizeof(*tc[i].vertices));
6076 hr = mesh->lpVtbl->UnlockVertexBuffer(mesh);
6077 if (FAILED(hr))
6079 skip("Couldn't unlock vertex buffer.\n");
6080 goto cleanup;
6082 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, &index_buffer);
6083 if (FAILED(hr))
6085 skip("Couldn't lock index buffer.\n");
6086 goto cleanup;
6088 if (tc[i].options & D3DXMESH_32BIT)
6090 memcpy(index_buffer, tc[i].indices, VERTS_PER_FACE * tc[i].num_faces * sizeof(DWORD));
6092 else
6094 memcpy(index_buffer, tc[i].indices, VERTS_PER_FACE * tc[i].num_faces * sizeof(WORD));
6096 hr = mesh->lpVtbl->UnlockIndexBuffer(mesh);
6097 if (FAILED(hr)) {
6098 skip("Couldn't unlock index buffer.\n");
6099 goto cleanup;
6102 hr = mesh->lpVtbl->LockAttributeBuffer(mesh, 0, &attributes_buffer);
6103 if (FAILED(hr))
6105 skip("Couldn't lock attributes buffer.\n");
6106 goto cleanup;
6108 memcpy(attributes_buffer, attributes, sizeof(attributes));
6109 hr = mesh->lpVtbl->UnlockAttributeBuffer(mesh);
6110 if (FAILED(hr))
6112 skip("Couldn't unlock attributes buffer.\n");
6113 goto cleanup;
6116 /* Convert point representation to adjacency*/
6117 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++) adjacency[j] = -2;
6119 hr = mesh->lpVtbl->ConvertPointRepsToAdjacency(mesh, tc[i].point_reps, adjacency);
6120 ok(hr == D3D_OK, "ConvertPointRepsToAdjacency failed case %d. "
6121 "Got %x expected D3D_OK\n", i, hr);
6122 /* Check adjacency */
6123 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
6125 ok(adjacency[j] == tc[i].exp_adjacency[j],
6126 "Unexpected adjacency information at (%d, %d)."
6127 " Got %d expected %d\n",
6128 i, j, adjacency[j], tc[i].exp_adjacency[j]);
6131 /* NULL point representation is considered identity. */
6132 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++) adjacency[j] = -2;
6133 hr = mesh_null_check->lpVtbl->ConvertPointRepsToAdjacency(mesh, NULL, adjacency);
6134 ok(hr == D3D_OK, "ConvertPointRepsToAdjacency NULL point_reps. "
6135 "Got %x expected D3D_OK\n", hr);
6136 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
6138 ok(adjacency[j] == tc[i].exp_id_adjacency[j],
6139 "Unexpected adjacency information (id) at (%d, %d)."
6140 " Got %d expected %d\n",
6141 i, j, adjacency[j], tc[i].exp_id_adjacency[j]);
6144 HeapFree(GetProcessHeap(), 0, adjacency);
6145 adjacency = NULL;
6146 if (i != 0) /* First mesh will be freed during cleanup */
6147 mesh->lpVtbl->Release(mesh);
6150 /* NULL checks */
6151 hr = mesh_null_check->lpVtbl->ConvertPointRepsToAdjacency(mesh_null_check, tc[0].point_reps, NULL);
6152 ok(hr == D3DERR_INVALIDCALL, "ConvertPointRepsToAdjacency NULL adjacency. "
6153 "Got %x expected D3DERR_INVALIDCALL\n", hr);
6154 hr = mesh_null_check->lpVtbl->ConvertPointRepsToAdjacency(mesh_null_check, NULL, NULL);
6155 ok(hr == D3DERR_INVALIDCALL, "ConvertPointRepsToAdjacency NULL point_reps and adjacency. "
6156 "Got %x expected D3DERR_INVALIDCALL\n", hr);
6158 cleanup:
6159 if (mesh_null_check)
6160 mesh_null_check->lpVtbl->Release(mesh_null_check);
6161 HeapFree(GetProcessHeap(), 0, adjacency);
6162 free_test_context(test_context);
6165 static HRESULT init_test_mesh(const DWORD num_faces, const DWORD num_vertices,
6166 const DWORD options,
6167 const D3DVERTEXELEMENT9 *declaration,
6168 IDirect3DDevice9 *device, ID3DXMesh **mesh_ptr,
6169 const void *vertices, const DWORD vertex_size,
6170 const DWORD *indices, const DWORD *attributes)
6172 HRESULT hr;
6173 void *vertex_buffer;
6174 void *index_buffer;
6175 DWORD *attributes_buffer;
6176 ID3DXMesh *mesh = NULL;
6178 hr = D3DXCreateMesh(num_faces, num_vertices, options, declaration, device, mesh_ptr);
6179 if (FAILED(hr))
6181 skip("Couldn't create mesh. Got %x expected D3D_OK\n", hr);
6182 goto cleanup;
6184 mesh = *mesh_ptr;
6186 hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, &vertex_buffer);
6187 if (FAILED(hr))
6189 skip("Couldn't lock vertex buffer.\n");
6190 goto cleanup;
6192 memcpy(vertex_buffer, vertices, num_vertices * vertex_size);
6193 hr = mesh->lpVtbl->UnlockVertexBuffer(mesh);
6194 if (FAILED(hr))
6196 skip("Couldn't unlock vertex buffer.\n");
6197 goto cleanup;
6200 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, &index_buffer);
6201 if (FAILED(hr))
6203 skip("Couldn't lock index buffer.\n");
6204 goto cleanup;
6206 if (options & D3DXMESH_32BIT)
6208 if (indices)
6209 memcpy(index_buffer, indices, 3 * num_faces * sizeof(DWORD));
6210 else
6212 /* Fill index buffer with 0, 1, 2, ...*/
6213 DWORD *indices_32bit = (DWORD*)index_buffer;
6214 UINT i;
6215 for (i = 0; i < 3 * num_faces; i++)
6216 indices_32bit[i] = i;
6219 else
6221 if (indices)
6222 memcpy(index_buffer, indices, 3 * num_faces * sizeof(WORD));
6223 else
6225 /* Fill index buffer with 0, 1, 2, ...*/
6226 WORD *indices_16bit = (WORD*)index_buffer;
6227 UINT i;
6228 for (i = 0; i < 3 * num_faces; i++)
6229 indices_16bit[i] = i;
6232 hr = mesh->lpVtbl->UnlockIndexBuffer(mesh);
6233 if (FAILED(hr)) {
6234 skip("Couldn't unlock index buffer.\n");
6235 goto cleanup;
6238 hr = mesh->lpVtbl->LockAttributeBuffer(mesh, 0, &attributes_buffer);
6239 if (FAILED(hr))
6241 skip("Couldn't lock attributes buffer.\n");
6242 goto cleanup;
6245 if (attributes)
6246 memcpy(attributes_buffer, attributes, num_faces * sizeof(*attributes));
6247 else
6248 memset(attributes_buffer, 0, num_faces * sizeof(*attributes));
6250 hr = mesh->lpVtbl->UnlockAttributeBuffer(mesh);
6251 if (FAILED(hr))
6253 skip("Couldn't unlock attributes buffer.\n");
6254 goto cleanup;
6257 hr = D3D_OK;
6258 cleanup:
6259 return hr;
6262 /* Using structs instead of bit-fields in order to avoid compiler issues. */
6263 struct udec3
6265 UINT x;
6266 UINT y;
6267 UINT z;
6268 UINT w;
6271 struct dec3n
6273 INT x;
6274 INT y;
6275 INT z;
6276 INT w;
6279 static DWORD init_udec3_dword(UINT x, UINT y, UINT z, UINT w)
6281 DWORD d = 0;
6283 d |= x & 0x3ff;
6284 d |= (y << 10) & 0xffc00;
6285 d |= (z << 20) & 0x3ff00000;
6286 d |= (w << 30) & 0xc0000000;
6288 return d;
6291 static DWORD init_dec3n_dword(INT x, INT y, INT z, INT w)
6293 DWORD d = 0;
6295 d |= x & 0x3ff;
6296 d |= (y << 10) & 0xffc00;
6297 d |= (z << 20) & 0x3ff00000;
6298 d |= (w << 30) & 0xc0000000;
6300 return d;
6303 static struct udec3 dword_to_udec3(DWORD d)
6305 struct udec3 v;
6307 v.x = d & 0x3ff;
6308 v.y = (d & 0xffc00) >> 10;
6309 v.z = (d & 0x3ff00000) >> 20;
6310 v.w = (d & 0xc0000000) >> 30;
6312 return v;
6315 static struct dec3n dword_to_dec3n(DWORD d)
6317 struct dec3n v;
6319 v.x = d & 0x3ff;
6320 v.y = (d & 0xffc00) >> 10;
6321 v.z = (d & 0x3ff00000) >> 20;
6322 v.w = (d & 0xc0000000) >> 30;
6324 return v;
6327 static void check_vertex_components(int line, int mesh_number, int vertex_number, BYTE *got_ptr, const BYTE *exp_ptr, D3DVERTEXELEMENT9 *declaration)
6329 const char *usage_strings[] =
6331 "position",
6332 "blend weight",
6333 "blend indices",
6334 "normal",
6335 "point size",
6336 "texture coordinates",
6337 "tangent",
6338 "binormal",
6339 "tessellation factor",
6340 "position transformed",
6341 "color",
6342 "fog",
6343 "depth",
6344 "sample"
6346 D3DVERTEXELEMENT9 *decl_ptr;
6347 const float PRECISION = 1e-5f;
6349 for (decl_ptr = declaration; decl_ptr->Stream != 0xFF; decl_ptr++)
6351 switch (decl_ptr->Type)
6353 case D3DDECLTYPE_FLOAT1:
6355 FLOAT *got = (FLOAT*)(got_ptr + decl_ptr->Offset);
6356 FLOAT *exp = (FLOAT*)(exp_ptr + decl_ptr->Offset);
6357 FLOAT diff = fabsf(*got - *exp);
6358 ok_(__FILE__,line)(diff <= PRECISION, "Mesh %d: Got %f for vertex %d %s, expected %f.\n",
6359 mesh_number, *got, vertex_number, usage_strings[decl_ptr->Usage], *exp);
6360 break;
6362 case D3DDECLTYPE_FLOAT2:
6364 D3DXVECTOR2 *got = (D3DXVECTOR2*)(got_ptr + decl_ptr->Offset);
6365 D3DXVECTOR2 *exp = (D3DXVECTOR2*)(exp_ptr + decl_ptr->Offset);
6366 FLOAT diff = max(fabsf(got->x - exp->x), fabsf(got->y - exp->y));
6367 ok_(__FILE__,line)(diff <= PRECISION, "Mesh %d: Got (%f, %f) for vertex %d %s, expected (%f, %f).\n",
6368 mesh_number, got->x, got->y, vertex_number, usage_strings[decl_ptr->Usage], exp->x, exp->y);
6369 break;
6371 case D3DDECLTYPE_FLOAT3:
6373 D3DXVECTOR3 *got = (D3DXVECTOR3*)(got_ptr + decl_ptr->Offset);
6374 D3DXVECTOR3 *exp = (D3DXVECTOR3*)(exp_ptr + decl_ptr->Offset);
6375 FLOAT diff = max(fabsf(got->x - exp->x), fabsf(got->y - exp->y));
6376 diff = max(diff, fabsf(got->z - exp->z));
6377 ok_(__FILE__,line)(diff <= PRECISION, "Mesh %d: Got (%f, %f, %f) for vertex %d %s, expected (%f, %f, %f).\n",
6378 mesh_number, got->x, got->y, got->z, vertex_number, usage_strings[decl_ptr->Usage], exp->x, exp->y, exp->z);
6379 break;
6381 case D3DDECLTYPE_FLOAT4:
6383 D3DXVECTOR4 *got = (D3DXVECTOR4*)(got_ptr + decl_ptr->Offset);
6384 D3DXVECTOR4 *exp = (D3DXVECTOR4*)(exp_ptr + decl_ptr->Offset);
6385 FLOAT diff = max(fabsf(got->x - exp->x), fabsf(got->y - exp->y));
6386 diff = max(diff, fabsf(got->z - exp->z));
6387 diff = max(diff, fabsf(got->w - exp->w));
6388 ok_(__FILE__,line)(diff <= PRECISION, "Mesh %d: Got (%f, %f, %f, %f) for vertex %d %s, expected (%f, %f, %f, %f).\n",
6389 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);
6390 break;
6392 case D3DDECLTYPE_D3DCOLOR:
6394 BYTE *got = got_ptr + decl_ptr->Offset;
6395 const BYTE *exp = exp_ptr + decl_ptr->Offset;
6396 BOOL same_color = got[0] == exp[0] && got[1] == exp[1]
6397 && got[2] == exp[2] && got[3] == exp[3];
6398 const char *color_types[] = {"diffuse", "specular", "undefined color"};
6399 BYTE usage_index = decl_ptr->UsageIndex;
6400 if (usage_index > 1) usage_index = 2;
6401 ok_(__FILE__,line)(same_color, "Mesh %d: Got (%u, %u, %u, %u) for vertex %d %s, expected (%u, %u, %u, %u).\n",
6402 mesh_number, got[0], got[1], got[2], got[3], vertex_number, color_types[usage_index], exp[0], exp[1], exp[2], exp[3]);
6403 break;
6405 case D3DDECLTYPE_UBYTE4:
6406 case D3DDECLTYPE_UBYTE4N:
6408 BYTE *got = got_ptr + decl_ptr->Offset;
6409 const BYTE *exp = exp_ptr + decl_ptr->Offset;
6410 BOOL same = got[0] == exp[0] && got[1] == exp[1]
6411 && got[2] == exp[2] && got[3] == exp[3];
6412 ok_(__FILE__,line)(same, "Mesh %d: Got (%u, %u, %u, %u) for vertex %d %s, expected (%u, %u, %u, %u).\n",
6413 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]);
6414 break;
6416 case D3DDECLTYPE_SHORT2:
6417 case D3DDECLTYPE_SHORT2N:
6419 SHORT *got = (SHORT*)(got_ptr + decl_ptr->Offset);
6420 SHORT *exp = (SHORT*)(exp_ptr + decl_ptr->Offset);
6421 BOOL same = got[0] == exp[0] && got[1] == exp[1];
6422 ok_(__FILE__,line)(same, "Mesh %d: Got (%hd, %hd) for vertex %d %s, expected (%hd, %hd).\n",
6423 mesh_number, got[0], got[1], vertex_number, usage_strings[decl_ptr->Usage], exp[0], exp[1]);
6424 break;
6426 case D3DDECLTYPE_SHORT4:
6427 case D3DDECLTYPE_SHORT4N:
6429 SHORT *got = (SHORT*)(got_ptr + decl_ptr->Offset);
6430 SHORT *exp = (SHORT*)(exp_ptr + decl_ptr->Offset);
6431 BOOL same = got[0] == exp[0] && got[1] == exp[1]
6432 && got[2] == exp[2] && got[3] == exp[3];
6433 ok_(__FILE__,line)(same, "Mesh %d: Got (%hd, %hd, %hd, %hd) for vertex %d %s, expected (%hd, %hd, %hd, %hd).\n",
6434 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]);
6435 break;
6437 case D3DDECLTYPE_USHORT2N:
6439 USHORT *got = (USHORT*)(got_ptr + decl_ptr->Offset);
6440 USHORT *exp = (USHORT*)(exp_ptr + decl_ptr->Offset);
6441 BOOL same = got[0] == exp[0] && got[1] == exp[1];
6442 ok_(__FILE__,line)(same, "Mesh %d: Got (%hu, %hu) for vertex %d %s, expected (%hu, %hu).\n",
6443 mesh_number, got[0], got[1], vertex_number, usage_strings[decl_ptr->Usage], exp[0], exp[1]);
6444 break;
6446 case D3DDECLTYPE_USHORT4N:
6448 USHORT *got = (USHORT*)(got_ptr + decl_ptr->Offset);
6449 USHORT *exp = (USHORT*)(exp_ptr + decl_ptr->Offset);
6450 BOOL same = got[0] == exp[0] && got[1] == exp[1]
6451 && got[2] == exp[2] && got[3] == exp[3];
6452 ok_(__FILE__,line)(same, "Mesh %d: Got (%hu, %hu, %hu, %hu) for vertex %d %s, expected (%hu, %hu, %hu, %hu).\n",
6453 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]);
6454 break;
6456 case D3DDECLTYPE_UDEC3:
6458 DWORD *got = (DWORD*)(got_ptr + decl_ptr->Offset);
6459 DWORD *exp = (DWORD*)(exp_ptr + decl_ptr->Offset);
6460 BOOL same = memcmp(got, exp, sizeof(*got)) == 0;
6461 struct udec3 got_udec3 = dword_to_udec3(*got);
6462 struct udec3 exp_udec3 = dword_to_udec3(*exp);
6463 ok_(__FILE__,line)(same, "Mesh %d: Got (%u, %u, %u, %u) for vertex %d %s, expected (%u, %u, %u, %u).\n",
6464 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);
6466 break;
6468 case D3DDECLTYPE_DEC3N:
6470 DWORD *got = (DWORD*)(got_ptr + decl_ptr->Offset);
6471 DWORD *exp = (DWORD*)(exp_ptr + decl_ptr->Offset);
6472 BOOL same = memcmp(got, exp, sizeof(*got)) == 0;
6473 struct dec3n got_dec3n = dword_to_dec3n(*got);
6474 struct dec3n exp_dec3n = dword_to_dec3n(*exp);
6475 ok_(__FILE__,line)(same, "Mesh %d: Got (%d, %d, %d, %d) for vertex %d %s, expected (%d, %d, %d, %d).\n",
6476 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);
6477 break;
6479 case D3DDECLTYPE_FLOAT16_2:
6481 WORD *got = (WORD*)(got_ptr + decl_ptr->Offset);
6482 WORD *exp = (WORD*)(exp_ptr + decl_ptr->Offset);
6483 BOOL same = got[0] == exp[0] && got[1] == exp[1];
6484 ok_(__FILE__,line)(same, "Mesh %d: Got (%hx, %hx) for vertex %d %s, expected (%hx, %hx).\n",
6485 mesh_number, got[0], got[1], vertex_number, usage_strings[decl_ptr->Usage], exp[0], exp[1]);
6486 break;
6488 case D3DDECLTYPE_FLOAT16_4:
6490 WORD *got = (WORD*)(got_ptr + decl_ptr->Offset);
6491 WORD *exp = (WORD*)(exp_ptr + decl_ptr->Offset);
6492 BOOL same = got[0] == exp[0] && got[1] == exp[1]
6493 && got[2] == exp[2] && got[3] == exp[3];
6494 ok_(__FILE__,line)(same, "Mesh %d: Got (%hx, %hx, %hx, %hx) for vertex %d %s, expected (%hx, %hx, %hx, %hx).\n",
6495 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]);
6496 break;
6498 default:
6499 break;
6504 static void test_weld_vertices(void)
6506 HRESULT hr;
6507 struct test_context *test_context = NULL;
6508 DWORD i;
6509 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
6510 const DWORD options_16bit = D3DXMESH_SYSTEMMEM;
6511 BYTE *vertices = NULL;
6512 DWORD *indices = NULL;
6513 WORD *indices_16bit = NULL;
6514 const UINT VERTS_PER_FACE = 3;
6515 const D3DXVECTOR3 up = {0.0f, 0.0f, 1.0f};
6516 struct vertex_normal
6518 D3DXVECTOR3 position;
6519 D3DXVECTOR3 normal;
6521 struct vertex_blendweight
6523 D3DXVECTOR3 position;
6524 FLOAT blendweight;
6526 struct vertex_texcoord
6528 D3DXVECTOR3 position;
6529 D3DXVECTOR2 texcoord;
6531 struct vertex_color
6533 D3DXVECTOR3 position;
6534 DWORD color;
6536 struct vertex_color_ubyte4
6538 D3DXVECTOR3 position;
6539 BYTE color[4];
6541 struct vertex_texcoord_short2
6543 D3DXVECTOR3 position;
6544 SHORT texcoord[2];
6546 struct vertex_texcoord_ushort2n
6548 D3DXVECTOR3 position;
6549 USHORT texcoord[2];
6551 struct vertex_normal_short4
6553 D3DXVECTOR3 position;
6554 SHORT normal[4];
6556 struct vertex_texcoord_float16_2
6558 D3DXVECTOR3 position;
6559 WORD texcoord[2];
6561 struct vertex_texcoord_float16_4
6563 D3DXVECTOR3 position;
6564 WORD texcoord[4];
6566 struct vertex_normal_udec3
6568 D3DXVECTOR3 position;
6569 DWORD normal;
6571 struct vertex_normal_dec3n
6573 D3DXVECTOR3 position;
6574 DWORD normal;
6576 UINT vertex_size_normal = sizeof(struct vertex_normal);
6577 UINT vertex_size_blendweight = sizeof(struct vertex_blendweight);
6578 UINT vertex_size_texcoord = sizeof(struct vertex_texcoord);
6579 UINT vertex_size_color = sizeof(struct vertex_color);
6580 UINT vertex_size_color_ubyte4 = sizeof(struct vertex_color_ubyte4);
6581 UINT vertex_size_texcoord_short2 = sizeof(struct vertex_texcoord_short2);
6582 UINT vertex_size_normal_short4 = sizeof(struct vertex_normal_short4);
6583 UINT vertex_size_texcoord_float16_2 = sizeof(struct vertex_texcoord_float16_2);
6584 UINT vertex_size_texcoord_float16_4 = sizeof(struct vertex_texcoord_float16_4);
6585 UINT vertex_size_normal_udec3 = sizeof(struct vertex_normal_udec3);
6586 UINT vertex_size_normal_dec3n = sizeof(struct vertex_normal_dec3n);
6587 D3DVERTEXELEMENT9 declaration_normal[] =
6589 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6590 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6591 D3DDECL_END()
6593 D3DVERTEXELEMENT9 declaration_normal3[] =
6595 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 3},
6596 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6597 D3DDECL_END()
6599 D3DVERTEXELEMENT9 declaration_blendweight[] =
6601 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6602 {0, 12, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BLENDWEIGHT, 0},
6603 D3DDECL_END()
6605 D3DVERTEXELEMENT9 declaration_texcoord[] =
6607 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6608 {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6609 D3DDECL_END()
6611 D3DVERTEXELEMENT9 declaration_color[] =
6613 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6614 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
6615 D3DDECL_END()
6617 D3DVERTEXELEMENT9 declaration_color_ubyte4n[] =
6619 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6620 {0, 12, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
6621 D3DDECL_END()
6623 D3DVERTEXELEMENT9 declaration_color_ubyte4[] =
6625 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6626 {0, 12, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
6627 D3DDECL_END()
6629 D3DVERTEXELEMENT9 declaration_texcoord_short2[] =
6631 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6632 {0, 12, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6633 D3DDECL_END()
6635 D3DVERTEXELEMENT9 declaration_texcoord_short2n[] =
6637 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6638 {0, 12, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6639 D3DDECL_END()
6641 D3DVERTEXELEMENT9 declaration_texcoord_ushort2n[] =
6643 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6644 {0, 12, D3DDECLTYPE_USHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6645 D3DDECL_END()
6647 D3DVERTEXELEMENT9 declaration_normal_short4[] =
6649 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6650 {0, 12, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6651 D3DDECL_END()
6653 D3DVERTEXELEMENT9 declaration_normal_short4n[] =
6655 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6656 {0, 12, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6657 D3DDECL_END()
6659 D3DVERTEXELEMENT9 declaration_normal_ushort4n[] =
6661 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6662 {0, 12, D3DDECLTYPE_USHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6663 D3DDECL_END()
6665 D3DVERTEXELEMENT9 declaration_texcoord10[] =
6667 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6668 {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 10},
6669 D3DDECL_END()
6671 D3DVERTEXELEMENT9 declaration_color2[] =
6673 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6674 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 2},
6675 D3DDECL_END()
6677 D3DVERTEXELEMENT9 declaration_color1[] =
6679 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6680 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 1},
6681 D3DDECL_END()
6683 D3DVERTEXELEMENT9 declaration_texcoord_float16_2[] =
6685 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6686 {0, 12, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6687 D3DDECL_END()
6689 D3DVERTEXELEMENT9 declaration_texcoord_float16_4[] =
6691 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6692 {0, 12, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6693 D3DDECL_END()
6695 D3DVERTEXELEMENT9 declaration_normal_udec3[] =
6697 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6698 {0, 12, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6699 D3DDECL_END()
6701 D3DVERTEXELEMENT9 declaration_normal_dec3n[] =
6703 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6704 {0, 12, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6705 D3DDECL_END()
6707 /* Test 0. One face and no welding.
6709 * 0--1
6710 * | /
6711 * |/
6714 const struct vertex vertices0[] =
6716 {{ 0.0f, 3.0f, 0.f}, up},
6717 {{ 2.0f, 3.0f, 0.f}, up},
6718 {{ 0.0f, 0.0f, 0.f}, up},
6720 const DWORD indices0[] = {0, 1, 2};
6721 const DWORD attributes0[] = {0};
6722 const DWORD exp_indices0[] = {0, 1, 2};
6723 const UINT num_vertices0 = ARRAY_SIZE(vertices0);
6724 const UINT num_faces0 = ARRAY_SIZE(indices0) / VERTS_PER_FACE;
6725 const DWORD flags0 = D3DXWELDEPSILONS_WELDALL;
6726 /* epsilons0 is NULL */
6727 const DWORD adjacency0[] = {-1, -1, -1};
6728 const struct vertex exp_vertices0[] =
6730 {{ 0.0f, 3.0f, 0.f}, up},
6731 {{ 2.0f, 3.0f, 0.f}, up},
6732 {{ 0.0f, 0.0f, 0.f}, up},
6734 const DWORD exp_face_remap0[] = {0};
6735 const DWORD exp_vertex_remap0[] = {0, 1, 2};
6736 const DWORD exp_new_num_vertices0 = ARRAY_SIZE(exp_vertices0);
6737 /* Test 1. Two vertices should be removed without regard to epsilon.
6739 * 0--1 3
6740 * | / /|
6741 * |/ / |
6742 * 2 5--4
6744 const struct vertex_normal vertices1[] =
6746 {{ 0.0f, 3.0f, 0.f}, up},
6747 {{ 2.0f, 3.0f, 0.f}, up},
6748 {{ 0.0f, 0.0f, 0.f}, up},
6750 {{ 3.0f, 3.0f, 0.f}, up},
6751 {{ 3.0f, 0.0f, 0.f}, up},
6752 {{ 1.0f, 0.0f, 0.f}, up},
6754 const DWORD indices1[] = {0, 1, 2, 3, 4, 5};
6755 const DWORD attributes1[] = {0, 0};
6756 const UINT num_vertices1 = ARRAY_SIZE(vertices1);
6757 const UINT num_faces1 = ARRAY_SIZE(indices1) / VERTS_PER_FACE;
6758 const DWORD flags1 = D3DXWELDEPSILONS_WELDALL;
6759 /* epsilons1 is NULL */
6760 const DWORD adjacency1[] = {-1, 1, -1, -1, -1, 0};
6761 const struct vertex_normal exp_vertices1[] =
6763 {{ 0.0f, 3.0f, 0.f}, up},
6764 {{ 2.0f, 3.0f, 0.f}, up},
6765 {{ 0.0f, 0.0f, 0.f}, up},
6767 {{ 3.0f, 0.0f, 0.f}, up}
6769 const DWORD exp_indices1[] = {0, 1, 2, 1, 3, 2};
6770 const DWORD exp_face_remap1[] = {0, 1};
6771 const DWORD exp_vertex_remap1[] = {0, 1, 2, 4, -1, -1};
6772 const DWORD exp_new_num_vertices1 = ARRAY_SIZE(exp_vertices1);
6773 /* Test 2. Two faces. No vertices should be removed because of normal
6774 * epsilon, but the positions should be replaced. */
6775 const struct vertex_normal vertices2[] =
6777 {{ 0.0f, 3.0f, 0.f}, up},
6778 {{ 2.0f, 3.0f, 0.f}, up},
6779 {{ 0.0f, 0.0f, 0.f}, up},
6781 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
6782 {{ 3.0f, 0.0f, 0.f}, up},
6783 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6785 const DWORD indices2[] = {0, 1, 2, 3, 4, 5};
6786 const DWORD attributes2[] = {0, 0};
6787 const UINT num_vertices2 = ARRAY_SIZE(vertices2);
6788 const UINT num_faces2 = ARRAY_SIZE(indices2) / VERTS_PER_FACE;
6789 DWORD flags2 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
6790 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};
6791 const DWORD adjacency2[] = {-1, 1, -1, -1, -1, 0};
6792 const struct vertex_normal exp_vertices2[] =
6794 {{ 0.0f, 3.0f, 0.f}, up},
6795 {{ 2.0f, 3.0f, 0.f}, up},
6796 {{ 0.0f, 0.0f, 0.f}, up},
6798 {{ 2.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
6799 {{ 3.0f, 0.0f, 0.f}, up},
6800 {{ 0.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6802 const DWORD exp_indices2[] = {0, 1, 2, 3, 4, 5};
6803 const DWORD exp_face_remap2[] = {0, 1};
6804 const DWORD exp_vertex_remap2[] = {0, 1, 2, 3, 4, 5};
6805 const DWORD exp_new_num_vertices2 = ARRAY_SIZE(exp_vertices2);
6806 /* Test 3. Two faces. One vertex should be removed because of normal epsilon. */
6807 const struct vertex_normal vertices3[] =
6809 {{ 0.0f, 3.0f, 0.f}, up},
6810 {{ 2.0f, 3.0f, 0.f}, up},
6811 {{ 0.0f, 0.0f, 0.f}, up},
6813 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
6814 {{ 3.0f, 0.0f, 0.f}, up},
6815 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6817 const DWORD indices3[] = {0, 1, 2, 3, 4, 5};
6818 const DWORD attributes3[] = {0, 0};
6819 const UINT num_vertices3 = ARRAY_SIZE(vertices3);
6820 const UINT num_faces3 = ARRAY_SIZE(indices3) / VERTS_PER_FACE;
6821 DWORD flags3 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
6822 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};
6823 const DWORD adjacency3[] = {-1, 1, -1, -1, -1, 0};
6824 const struct vertex_normal exp_vertices3[] =
6826 {{ 0.0f, 3.0f, 0.f}, up},
6827 {{ 2.0f, 3.0f, 0.f}, up},
6828 {{ 0.0f, 0.0f, 0.f}, up},
6830 {{ 3.0f, 0.0f, 0.f}, up},
6831 {{ 0.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6833 const DWORD exp_indices3[] = {0, 1, 2, 1, 3, 4};
6834 const DWORD exp_face_remap3[] = {0, 1};
6835 const DWORD exp_vertex_remap3[] = {0, 1, 2, 4, 5, -1};
6836 const DWORD exp_new_num_vertices3 = ARRAY_SIZE(exp_vertices3);
6837 /* Test 4 Two faces. Two vertices should be removed. */
6838 const struct vertex_normal vertices4[] =
6840 {{ 0.0f, 3.0f, 0.f}, up},
6841 {{ 2.0f, 3.0f, 0.f}, up},
6842 {{ 0.0f, 0.0f, 0.f}, up},
6844 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
6845 {{ 3.0f, 0.0f, 0.f}, up},
6846 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6848 const DWORD indices4[] = {0, 1, 2, 3, 4, 5};
6849 const DWORD attributes4[] = {0, 0};
6850 const UINT num_vertices4 = ARRAY_SIZE(vertices4);
6851 const UINT num_faces4 = ARRAY_SIZE(indices4) / VERTS_PER_FACE;
6852 DWORD flags4 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
6853 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};
6854 const DWORD adjacency4[] = {-1, 1, -1, -1, -1, 0};
6855 const struct vertex_normal exp_vertices4[] =
6857 {{ 0.0f, 3.0f, 0.f}, up},
6858 {{ 2.0f, 3.0f, 0.f}, up},
6859 {{ 0.0f, 0.0f, 0.f}, up},
6861 {{ 3.0f, 0.0f, 0.f}, up},
6863 const DWORD exp_indices4[] = {0, 1, 2, 1, 3, 2};
6864 const DWORD exp_face_remap4[] = {0, 1};
6865 const DWORD exp_vertex_remap4[] = {0, 1, 2, 4, -1, -1};
6866 const DWORD exp_new_num_vertices4 = ARRAY_SIZE(exp_vertices4);
6867 /* Test 5. Odd face ordering.
6869 * 0--1 6 3
6870 * | / /| |\
6871 * |/ / | | \
6872 * 2 8--7 5--4
6874 const struct vertex_normal vertices5[] =
6876 {{ 0.0f, 3.0f, 0.f}, up},
6877 {{ 2.0f, 3.0f, 0.f}, up},
6878 {{ 0.0f, 0.0f, 0.f}, up},
6880 {{ 3.0f, 3.0f, 0.f}, up},
6881 {{ 3.0f, 0.0f, 0.f}, up},
6882 {{ 1.0f, 0.0f, 0.f}, up},
6884 {{ 4.0f, 3.0f, 0.f}, up},
6885 {{ 6.0f, 0.0f, 0.f}, up},
6886 {{ 4.0f, 0.0f, 0.f}, up},
6888 const DWORD indices5[] = {0, 1, 2, 6, 7, 8, 3, 4, 5};
6889 const DWORD exp_indices5[] = {0, 1, 2, 1, 4, 2, 1, 3, 4};
6890 const DWORD attributes5[] = {0, 0, 0};
6891 const UINT num_vertices5 = ARRAY_SIZE(vertices5);
6892 const UINT num_faces5 = ARRAY_SIZE(indices5) / VERTS_PER_FACE;
6893 DWORD flags5 = D3DXWELDEPSILONS_WELDALL;
6894 const DWORD adjacency5[] = {-1, 1, -1, 2, -1, 0, -1, -1, 1};
6895 const struct vertex_normal exp_vertices5[] =
6897 {{ 0.0f, 3.0f, 0.f}, up},
6898 {{ 2.0f, 3.0f, 0.f}, up},
6899 {{ 0.0f, 0.0f, 0.f}, up},
6901 {{ 3.0f, 0.0f, 0.f}, up},
6902 {{ 1.0f, 0.0f, 0.f}, up},
6904 const DWORD exp_face_remap5[] = {0, 1, 2};
6905 const DWORD exp_vertex_remap5[] = {0, 1, 2, 4, 5, -1, -1, -1, -1};
6906 const DWORD exp_new_num_vertices5 = ARRAY_SIZE(exp_vertices5);
6907 /* Test 6. Two faces. Do not remove flag is used, so no vertices should be
6908 * removed. */
6909 const struct vertex_normal vertices6[] =
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}, {0.0f, 0.5f, 0.5f}},
6916 {{ 3.0f, 0.0f, 0.f}, up},
6917 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6919 const DWORD indices6[] = {0, 1, 2, 3, 4, 5};
6920 const DWORD attributes6[] = {0, 0};
6921 const UINT num_vertices6 = ARRAY_SIZE(vertices6);
6922 const UINT num_faces6 = ARRAY_SIZE(indices6) / VERTS_PER_FACE;
6923 DWORD flags6 = D3DXWELDEPSILONS_WELDPARTIALMATCHES | D3DXWELDEPSILONS_DONOTREMOVEVERTICES;
6924 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};
6925 const DWORD adjacency6[] = {-1, 1, -1, -1, -1, 0};
6926 const struct vertex_normal exp_vertices6[] =
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 {{ 2.0f, 3.0f, 0.f}, up},
6933 {{ 3.0f, 0.0f, 0.f}, up},
6934 {{ 0.0f, 0.0f, 0.f}, up},
6937 const DWORD exp_indices6[] = {0, 1, 2, 3, 4, 5};
6938 const DWORD exp_face_remap6[] = {0, 1};
6939 const DWORD exp_vertex_remap6[] = {0, 1, 2, 3, 4, 5};
6940 const DWORD exp_new_num_vertices6 = ARRAY_SIZE(exp_vertices6);
6941 /* Test 7. Same as test 6 but with 16 bit indices. */
6942 const WORD indices6_16bit[] = {0, 1, 2, 3, 4, 5};
6943 /* Test 8. No flags. Same result as D3DXWELDEPSILONS_WELDPARTIALMATCHES. */
6944 const struct vertex_normal vertices8[] =
6946 {{ 0.0f, 3.0f, 0.f}, up},
6947 {{ 2.0f, 3.0f, 0.f}, up},
6948 {{ 0.0f, 0.0f, 0.f}, up},
6950 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
6951 {{ 3.0f, 0.0f, 0.f}, up},
6952 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6954 const DWORD indices8[] = {0, 1, 2, 1, 3, 4};
6955 const DWORD attributes8[] = {0, 0};
6956 const UINT num_vertices8 = ARRAY_SIZE(vertices8);
6957 const UINT num_faces8 = ARRAY_SIZE(indices8) / VERTS_PER_FACE;
6958 DWORD flags8 = 0;
6959 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};
6960 const DWORD adjacency8[] = {-1, 1, -1, -1, -1, 0};
6961 const struct vertex_normal exp_vertices8[] =
6963 {{ 0.0f, 3.0f, 0.f}, up},
6964 {{ 2.0f, 3.0f, 0.f}, up},
6965 {{ 0.0f, 0.0f, 0.f}, up},
6967 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
6968 {{ 3.0f, 0.0f, 0.f}, up},
6970 const DWORD exp_indices8[] = {0, 1, 2, 1, 3, 4};
6971 const DWORD exp_face_remap8[] = {0, 1};
6972 const DWORD exp_vertex_remap8[] = {0, 1, 2, 3, 4, -1};
6973 const DWORD exp_new_num_vertices8 = ARRAY_SIZE(exp_vertices8);
6974 /* Test 9. Vertices are removed even though they belong to separate
6975 * attribute groups if D3DXWELDEPSILONS_DONOTSPLIT is set. */
6976 const struct vertex_normal vertices9[] =
6978 {{ 0.0f, 3.0f, 0.f}, up},
6979 {{ 2.0f, 3.0f, 0.f}, up},
6980 {{ 0.0f, 0.0f, 0.f}, up},
6982 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
6983 {{ 3.0f, 0.0f, 0.f}, up},
6984 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6986 const DWORD indices9[] = {0, 1, 2, 3, 4, 5};
6987 const DWORD attributes9[] = {0, 1};
6988 const UINT num_vertices9 = ARRAY_SIZE(vertices9);
6989 const UINT num_faces9 = ARRAY_SIZE(indices9) / VERTS_PER_FACE;
6990 DWORD flags9 = D3DXWELDEPSILONS_WELDPARTIALMATCHES | D3DXWELDEPSILONS_DONOTSPLIT;
6991 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};
6992 const DWORD adjacency9[] = {-1, 1, -1, -1, -1, 0};
6993 const struct vertex_normal exp_vertices9[] =
6995 {{ 0.0f, 3.0f, 0.f}, up},
6996 {{ 2.0f, 3.0f, 0.f}, up},
6997 {{ 0.0f, 0.0f, 0.f}, up},
6999 {{ 3.0f, 0.0f, 0.f}, up},
7001 const DWORD exp_indices9[] = {0, 1, 2, 1, 3, 2};
7002 const DWORD exp_face_remap9[] = {0, 1};
7003 const DWORD exp_vertex_remap9[] = {0, 1, 2, 4, -1, -1};
7004 const DWORD exp_new_num_vertices9 = ARRAY_SIZE(exp_vertices9);
7005 /* Test 10. Weld blendweight (FLOAT1). */
7006 const struct vertex_blendweight vertices10[] =
7008 {{ 0.0f, 3.0f, 0.f}, 1.0f},
7009 {{ 2.0f, 3.0f, 0.f}, 1.0f},
7010 {{ 0.0f, 0.0f, 0.f}, 1.0f},
7012 {{ 3.0f, 3.0f, 0.f}, 0.9},
7013 {{ 3.0f, 0.0f, 0.f}, 1.0},
7014 {{ 1.0f, 0.0f, 0.f}, 0.4},
7016 const DWORD indices10[] = {0, 1, 2, 3, 4, 5};
7017 const DWORD attributes10[] = {0, 0};
7018 const UINT num_vertices10 = ARRAY_SIZE(vertices10);
7019 const UINT num_faces10 = ARRAY_SIZE(indices10) / VERTS_PER_FACE;
7020 DWORD flags10 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7021 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};
7022 const DWORD adjacency10[] = {-1, 1, -1, -1, -1, 0};
7023 const struct vertex_blendweight exp_vertices10[] =
7025 {{ 0.0f, 3.0f, 0.f}, 1.0f},
7026 {{ 2.0f, 3.0f, 0.f}, 1.0f},
7027 {{ 0.0f, 0.0f, 0.f}, 1.0f},
7029 {{ 3.0f, 0.0f, 0.f}, 1.0},
7030 {{ 0.0f, 0.0f, 0.f}, 0.4},
7032 const DWORD exp_indices10[] = {0, 1, 2, 1, 3, 4};
7033 const DWORD exp_face_remap10[] = {0, 1};
7034 const DWORD exp_vertex_remap10[] = {0, 1, 2, 4, 5, -1};
7035 const DWORD exp_new_num_vertices10 = ARRAY_SIZE(exp_vertices10);
7036 /* Test 11. Weld texture coordinates. */
7037 const struct vertex_texcoord vertices11[] =
7039 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f}},
7040 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.7f}},
7041 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
7043 {{ 3.0f, 3.0f, 0.f}, {0.2f, 0.3f}},
7044 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f}},
7045 {{ 1.0f, 0.0f, 0.f}, {0.1f, 0.2f}}
7047 const DWORD indices11[] = {0, 1, 2, 3, 4, 5};
7048 const DWORD attributes11[] = {0, 0};
7049 const UINT num_vertices11 = ARRAY_SIZE(vertices11);
7050 const UINT num_faces11 = ARRAY_SIZE(indices11) / VERTS_PER_FACE;
7051 DWORD flags11 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7052 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};
7053 const DWORD adjacency11[] = {-1, 1, -1, -1, -1, 0};
7054 const struct vertex_texcoord exp_vertices11[] =
7056 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f}},
7057 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.7f}},
7058 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
7060 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f}},
7061 {{ 0.0f, 0.0f, 0.f}, {0.1f, 0.2f}},
7063 const DWORD exp_indices11[] = {0, 1, 2, 1, 3, 4};
7064 const DWORD exp_face_remap11[] = {0, 1};
7065 const DWORD exp_vertex_remap11[] = {0, 1, 2, 4, 5, -1};
7066 const DWORD exp_new_num_vertices11 = ARRAY_SIZE(exp_vertices11);
7067 /* Test 12. Weld with color. */
7068 const struct vertex_color vertices12[] =
7070 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7071 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7072 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7074 {{ 3.0f, 3.0f, 0.f}, 0x00000000},
7075 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7076 {{ 1.0f, 0.0f, 0.f}, 0x88888888},
7078 const DWORD indices12[] = {0, 1, 2, 3, 4, 5};
7079 const DWORD attributes12[] = {0, 0};
7080 const UINT num_vertices12 = ARRAY_SIZE(vertices12);
7081 const UINT num_faces12 = ARRAY_SIZE(indices12) / VERTS_PER_FACE;
7082 DWORD flags12 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7083 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};
7084 const DWORD adjacency12[] = {-1, 1, -1, -1, -1, 0};
7085 const struct vertex_color exp_vertices12[] =
7087 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7088 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7089 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7091 {{ 2.0f, 3.0f, 0.f}, 0x00000000},
7092 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7094 const DWORD exp_indices12[] = {0, 1, 2, 3, 4, 2};
7095 const DWORD exp_face_remap12[] = {0, 1};
7096 const DWORD exp_vertex_remap12[] = {0, 1, 2, 3, 4, -1};
7097 const DWORD exp_new_num_vertices12 = ARRAY_SIZE(exp_vertices12);
7098 /* Test 13. Two faces. One vertex should be removed because of normal epsilon.
7099 * This is similar to test 3, but the declaration has been changed to NORMAL3.
7101 const struct vertex_normal vertices13[] =
7103 {{ 0.0f, 3.0f, 0.f}, up},
7104 {{ 2.0f, 3.0f, 0.f}, up},
7105 {{ 0.0f, 0.0f, 0.f}, up},
7107 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
7108 {{ 3.0f, 0.0f, 0.f}, up},
7109 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
7111 const DWORD indices13[] = {0, 1, 2, 3, 4, 5};
7112 const DWORD attributes13[] = {0, 0};
7113 const UINT num_vertices13 = ARRAY_SIZE(vertices3);
7114 const UINT num_faces13 = ARRAY_SIZE(indices3) / VERTS_PER_FACE;
7115 DWORD flags13 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7116 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};
7117 const DWORD adjacency13[] = {-1, 1, -1, -1, -1, 0};
7118 const struct vertex_normal exp_vertices13[] =
7120 {{ 0.0f, 3.0f, 0.f}, up},
7121 {{ 2.0f, 3.0f, 0.f}, up},
7122 {{ 0.0f, 0.0f, 0.f}, up},
7124 {{ 3.0f, 0.0f, 0.f}, up},
7125 {{ 0.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
7127 const DWORD exp_indices13[] = {0, 1, 2, 1, 3, 4};
7128 const DWORD exp_face_remap13[] = {0, 1};
7129 const DWORD exp_vertex_remap13[] = {0, 1, 2, 4, 5, -1};
7130 const DWORD exp_new_num_vertices13 = ARRAY_SIZE(exp_vertices13);
7131 /* Test 14. Another test for welding with color. */
7132 const struct vertex_color vertices14[] =
7134 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7135 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7136 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7138 {{ 3.0f, 3.0f, 0.f}, 0x00000000},
7139 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7140 {{ 1.0f, 0.0f, 0.f}, 0x01010101},
7142 const DWORD indices14[] = {0, 1, 2, 3, 4, 5};
7143 const DWORD attributes14[] = {0, 0};
7144 const UINT num_vertices14 = ARRAY_SIZE(vertices14);
7145 const UINT num_faces14 = ARRAY_SIZE(indices14) / VERTS_PER_FACE;
7146 DWORD flags14 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7147 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};
7148 const DWORD adjacency14[] = {-1, 1, -1, -1, -1, 0};
7149 const struct vertex_color exp_vertices14[] =
7151 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7152 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7153 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7155 {{ 2.0f, 3.0f, 0.f}, 0x00000000},
7156 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7158 const DWORD exp_indices14[] = {0, 1, 2, 3, 4, 2};
7159 const DWORD exp_face_remap14[] = {0, 1};
7160 const DWORD exp_vertex_remap14[] = {0, 1, 2, 3, 4, -1};
7161 const DWORD exp_new_num_vertices14 = ARRAY_SIZE(exp_vertices14);
7162 /* Test 15. Weld with color, but as UBYTE4N instead of D3DCOLOR. It shows
7163 * that UBYTE4N and D3DCOLOR are compared the same way.
7165 const struct vertex_color_ubyte4 vertices15[] =
7167 {{ 0.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7168 {{ 2.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7169 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7171 {{ 3.0f, 3.0f, 0.f}, { 0, 0, 0, 0}},
7172 {{ 3.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7173 {{ 1.0f, 0.0f, 0.f}, { 1, 1, 1, 1}},
7175 const DWORD indices15[] = {0, 1, 2, 3, 4, 5};
7176 const DWORD attributes15[] = {0, 0};
7177 const UINT num_vertices15 = ARRAY_SIZE(vertices15);
7178 const UINT num_faces15 = ARRAY_SIZE(indices15) / VERTS_PER_FACE;
7179 DWORD flags15 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7180 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};
7181 const DWORD adjacency15[] = {-1, 1, -1, -1, -1, 0};
7182 const struct vertex_color_ubyte4 exp_vertices15[] =
7184 {{ 0.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7185 {{ 2.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7186 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7188 {{ 2.0f, 3.0f, 0.f}, { 0, 0, 0, 0}},
7189 {{ 3.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7191 const DWORD exp_indices15[] = {0, 1, 2, 3, 4, 2};
7192 const DWORD exp_face_remap15[] = {0, 1};
7193 const DWORD exp_vertex_remap15[] = {0, 1, 2, 3, 4, -1};
7194 const DWORD exp_new_num_vertices15 = ARRAY_SIZE(exp_vertices15);
7195 /* Test 16. Weld with color, but as UBYTE4 instead of D3DCOLOR. It shows
7196 * that UBYTE4 is not normalized and that epsilon is truncated and compared
7197 * directly to each of the four bytes.
7199 const struct vertex_color_ubyte4 vertices16[] =
7201 {{ 0.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7202 {{ 2.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7203 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7205 {{ 3.0f, 3.0f, 0.f}, { 0, 0, 0, 0}},
7206 {{ 3.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7207 {{ 1.0f, 0.0f, 0.f}, { 1, 1, 1, 1}},
7209 const DWORD indices16[] = {0, 1, 2, 3, 4, 5};
7210 const DWORD attributes16[] = {0, 0};
7211 const UINT num_vertices16 = ARRAY_SIZE(vertices16);
7212 const UINT num_faces16 = ARRAY_SIZE(indices16) / VERTS_PER_FACE;
7213 DWORD flags16 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7214 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};
7215 const DWORD adjacency16[] = {-1, 1, -1, -1, -1, 0};
7216 const struct vertex_color_ubyte4 exp_vertices16[] =
7218 {{ 0.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7219 {{ 2.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7220 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7222 {{ 2.0f, 3.0f, 0.f}, { 0, 0, 0, 0}},
7223 {{ 3.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7225 const DWORD exp_indices16[] = {0, 1, 2, 3, 4, 2};
7226 const DWORD exp_face_remap16[] = {0, 1};
7227 const DWORD exp_vertex_remap16[] = {0, 1, 2, 3, 4, -1};
7228 const DWORD exp_new_num_vertices16 = ARRAY_SIZE(exp_vertices16);
7229 /* Test 17. Weld texture coordinates but as SHORT2 instead of D3DXVECTOR2.*/
7230 const struct vertex_texcoord_short2 vertices17[] =
7232 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7233 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7234 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7236 {{ 3.0f, 3.0f, 0.f}, {32767, 32767}},
7237 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7238 {{ 1.0f, 0.0f, 0.f}, {32766, 32766}},
7240 const DWORD indices17[] = {0, 1, 2, 3, 4, 5};
7241 const DWORD attributes17[] = {0, 0};
7242 const UINT num_vertices17 = ARRAY_SIZE(vertices17);
7243 const UINT num_faces17 = ARRAY_SIZE(indices17) / VERTS_PER_FACE;
7244 DWORD flags17 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7245 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};
7246 const DWORD adjacency17[] = {-1, 1, -1, -1, -1, 0};
7247 const struct vertex_texcoord_short2 exp_vertices17[] =
7249 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7250 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7251 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7253 {{ 2.0f, 3.0f, 0.f}, {32767, 32767}},
7254 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7256 const DWORD exp_indices17[] = {0, 1, 2, 3, 4, 2};
7257 const DWORD exp_face_remap17[] = {0, 1};
7258 const DWORD exp_vertex_remap17[] = {0, 1, 2, 3, 4, -1};
7259 const DWORD exp_new_num_vertices17 = ARRAY_SIZE(exp_vertices17);
7260 /* Test 18. Weld texture coordinates but as SHORT2N instead of D3DXVECTOR2. */
7261 const struct vertex_texcoord_short2 vertices18[] =
7263 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7264 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7265 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7267 {{ 3.0f, 3.0f, 0.f}, {32767, 32767}},
7268 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7269 {{ 1.0f, 0.0f, 0.f}, {32766, 32766}},
7271 const DWORD indices18[] = {0, 1, 2, 3, 4, 5};
7272 const DWORD attributes18[] = {0, 0};
7273 const UINT num_vertices18 = ARRAY_SIZE(vertices18);
7274 const UINT num_faces18 = ARRAY_SIZE(indices18) / VERTS_PER_FACE;
7275 DWORD flags18 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7276 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};
7277 const DWORD adjacency18[] = {-1, 1, -1, -1, -1, 0};
7278 const struct vertex_texcoord_short2 exp_vertices18[] =
7280 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7281 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7282 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7284 {{ 2.0f, 3.0f, 0.f}, {32767, 32767}},
7285 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7287 const DWORD exp_indices18[] = {0, 1, 2, 3, 4, 2};
7288 const DWORD exp_face_remap18[] = {0, 1};
7289 const DWORD exp_vertex_remap18[] = {0, 1, 2, 3, 4, -1};
7290 const DWORD exp_new_num_vertices18 = ARRAY_SIZE(exp_vertices18);
7291 /* Test 19. Weld texture coordinates but as USHORT2N instead of D3DXVECTOR2. */
7292 const struct vertex_texcoord_ushort2n vertices19[] =
7294 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7295 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7296 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7298 {{ 3.0f, 3.0f, 0.f}, {65535, 65535}},
7299 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7300 {{ 1.0f, 0.0f, 0.f}, {65534, 65534}},
7302 const DWORD indices19[] = {0, 1, 2, 3, 4, 5};
7303 const DWORD attributes19[] = {0, 0};
7304 const UINT num_vertices19 = ARRAY_SIZE(vertices19);
7305 const UINT num_faces19 = ARRAY_SIZE(indices19) / VERTS_PER_FACE;
7306 DWORD flags19 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7307 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};
7308 const DWORD adjacency19[] = {-1, 1, -1, -1, -1, 0};
7309 const struct vertex_texcoord_ushort2n exp_vertices19[] =
7311 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7312 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7313 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7315 {{ 2.0f, 3.0f, 0.f}, {65535, 65535}},
7316 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7318 const DWORD exp_indices19[] = {0, 1, 2, 3, 4, 2};
7319 const DWORD exp_face_remap19[] = {0, 1};
7320 const DWORD exp_vertex_remap19[] = {0, 1, 2, 3, 4, -1};
7321 const DWORD exp_new_num_vertices19 = ARRAY_SIZE(exp_vertices19);
7322 /* Test 20. Weld normal as SHORT4 instead of D3DXVECTOR3. */
7323 const struct vertex_normal_short4 vertices20[] =
7325 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7326 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7327 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7329 {{ 3.0f, 3.0f, 0.f}, {32767, 32767, 32767, 32767}},
7330 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7331 {{ 1.0f, 0.0f, 0.f}, {32766, 32766, 32766, 32766}},
7333 const DWORD indices20[] = {0, 1, 2, 3, 4, 5};
7334 const DWORD attributes20[] = {0, 0};
7335 const UINT num_vertices20 = ARRAY_SIZE(vertices20);
7336 const UINT num_faces20 = ARRAY_SIZE(indices20) / VERTS_PER_FACE;
7337 DWORD flags20 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7338 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};
7339 const DWORD adjacency20[] = {-1, 1, -1, -1, -1, 0};
7340 const struct vertex_normal_short4 exp_vertices20[] =
7342 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7343 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7344 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7346 {{ 2.0f, 3.0f, 0.f}, {32767, 32767, 32767, 32767}},
7347 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7349 const DWORD exp_indices20[] = {0, 1, 2, 3, 4, 2};
7350 const DWORD exp_face_remap20[] = {0, 1};
7351 const DWORD exp_vertex_remap20[] = {0, 1, 2, 3, 4, -1};
7352 const DWORD exp_new_num_vertices20 = ARRAY_SIZE(exp_vertices20);
7353 /* Test 21. Weld normal as SHORT4N instead of D3DXVECTOR3. */
7354 const struct vertex_normal_short4 vertices21[] =
7356 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7357 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7358 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7360 {{ 3.0f, 3.0f, 0.f}, {32767, 32767, 32767, 32767}},
7361 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7362 {{ 1.0f, 0.0f, 0.f}, {32766, 32766, 32766, 32766}},
7364 const DWORD indices21[] = {0, 1, 2, 3, 4, 5};
7365 const DWORD attributes21[] = {0, 0};
7366 const UINT num_vertices21 = ARRAY_SIZE(vertices21);
7367 const UINT num_faces21 = ARRAY_SIZE(indices21) / VERTS_PER_FACE;
7368 DWORD flags21 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7369 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};
7370 const DWORD adjacency21[] = {-1, 1, -1, -1, -1, 0};
7371 const struct vertex_normal_short4 exp_vertices21[] =
7373 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7374 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7375 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7377 {{ 2.0f, 3.0f, 0.f}, {32767, 32767, 32767, 32767}},
7378 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7380 const DWORD exp_indices21[] = {0, 1, 2, 3, 4, 2};
7381 const DWORD exp_face_remap21[] = {0, 1};
7382 const DWORD exp_vertex_remap21[] = {0, 1, 2, 3, 4, -1};
7383 const DWORD exp_new_num_vertices21 = ARRAY_SIZE(exp_vertices21);
7384 /* Test 22. Weld normal as USHORT4N instead of D3DXVECTOR3. */
7385 const struct vertex_normal_short4 vertices22[] =
7387 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7388 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7389 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7391 {{ 3.0f, 3.0f, 0.f}, {65535, 65535, 65535, 65535}},
7392 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7393 {{ 1.0f, 0.0f, 0.f}, {65534, 65534, 65534, 65534}},
7395 const DWORD indices22[] = {0, 1, 2, 3, 4, 5};
7396 const DWORD attributes22[] = {0, 0};
7397 const UINT num_vertices22 = ARRAY_SIZE(vertices22);
7398 const UINT num_faces22 = ARRAY_SIZE(indices22) / VERTS_PER_FACE;
7399 DWORD flags22 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7400 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};
7401 const DWORD adjacency22[] = {-1, 1, -1, -1, -1, 0};
7402 const struct vertex_normal_short4 exp_vertices22[] =
7404 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7405 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7406 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7408 {{ 2.0f, 3.0f, 0.f}, {65535, 65535, 65535, 65535}},
7409 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7411 const DWORD exp_indices22[] = {0, 1, 2, 3, 4, 2};
7412 const DWORD exp_face_remap22[] = {0, 1};
7413 const DWORD exp_vertex_remap22[] = {0, 1, 2, 3, 4, -1};
7414 const DWORD exp_new_num_vertices22 = ARRAY_SIZE(exp_vertices22);
7415 /* Test 23. Weld texture coordinates as FLOAT16_2. Similar to test 11, but
7416 * with texture coordinates converted to float16 in hex. */
7417 const struct vertex_texcoord_float16_2 vertices23[] =
7419 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
7420 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */
7421 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */
7423 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd}}, /* {0.2f, 0.3f} */
7424 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
7425 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */
7427 const DWORD indices23[] = {0, 1, 2, 3, 4, 5};
7428 const DWORD attributes23[] = {0, 0};
7429 const UINT num_vertices23 = ARRAY_SIZE(vertices23);
7430 const UINT num_faces23 = ARRAY_SIZE(indices23) / VERTS_PER_FACE;
7431 DWORD flags23 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7432 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};
7433 const DWORD adjacency23[] = {-1, 1, -1, -1, -1, 0};
7434 const struct vertex_texcoord_float16_2 exp_vertices23[] =
7436 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
7437 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */
7438 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */
7440 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
7441 {{ 0.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */
7443 const DWORD exp_indices23[] = {0, 1, 2, 1, 3, 4};
7444 const DWORD exp_face_remap23[] = {0, 1};
7445 const DWORD exp_vertex_remap23[] = {0, 1, 2, 4, 5, -1};
7446 const DWORD exp_new_num_vertices23 = ARRAY_SIZE(exp_vertices23);
7447 /* Test 24. Weld texture coordinates as FLOAT16_4. Similar to test 24. */
7448 const struct vertex_texcoord_float16_4 vertices24[] =
7450 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}},
7451 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a, 0x3800, 0x399a}},
7452 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd, 0xb266, 0xb4cd}},
7454 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd, 0x3266, 0x34cd}},
7455 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}},
7456 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266, 0x2e66, 0x3266}},
7458 const DWORD indices24[] = {0, 1, 2, 3, 4, 5};
7459 const DWORD attributes24[] = {0, 0};
7460 const UINT num_vertices24 = ARRAY_SIZE(vertices24);
7461 const UINT num_faces24 = ARRAY_SIZE(indices24) / VERTS_PER_FACE;
7462 DWORD flags24 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7463 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};
7464 const DWORD adjacency24[] = {-1, 1, -1, -1, -1, 0};
7465 const struct vertex_texcoord_float16_4 exp_vertices24[] =
7467 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}},
7468 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a, 0x3800, 0x399a}},
7469 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd, 0xb266, 0xb4cd}},
7471 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}},
7472 {{ 0.0f, 0.0f, 0.f}, {0x2e66, 0x3266, 0x2e66, 0x3266}},
7474 const DWORD exp_indices24[] = {0, 1, 2, 1, 3, 4};
7475 const DWORD exp_face_remap24[] = {0, 1};
7476 const DWORD exp_vertex_remap24[] = {0, 1, 2, 4, 5, -1};
7477 const DWORD exp_new_num_vertices24 = ARRAY_SIZE(exp_vertices24);
7478 /* Test 25. Weld texture coordinates with usage index 10 (TEXCOORD10). The
7479 * usage index is capped at 7, so the epsilon for TEXCOORD7 is used instead.
7481 const struct vertex_texcoord vertices25[] =
7483 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f}},
7484 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.7f}},
7485 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
7487 {{ 3.0f, 3.0f, 0.f}, {0.2f, 0.3f}},
7488 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f}},
7489 {{ 1.0f, 0.0f, 0.f}, {0.1f, 0.2f}}
7491 const DWORD indices25[] = {0, 1, 2, 3, 4, 5};
7492 const DWORD attributes25[] = {0, 0};
7493 const UINT num_vertices25 = ARRAY_SIZE(vertices25);
7494 const UINT num_faces25 = ARRAY_SIZE(indices25) / VERTS_PER_FACE;
7495 DWORD flags25 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7496 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};
7497 const DWORD adjacency25[] = {-1, 1, -1, -1, -1, 0};
7498 const struct vertex_texcoord exp_vertices25[] =
7500 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f}},
7501 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.7f}},
7502 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
7504 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f}},
7505 {{ 0.0f, 0.0f, 0.f}, {0.1f, 0.2f}},
7507 const DWORD exp_indices25[] = {0, 1, 2, 1, 3, 4};
7508 const DWORD exp_face_remap25[] = {0, 1};
7509 const DWORD exp_vertex_remap25[] = {0, 1, 2, 4, 5, -1};
7510 const DWORD exp_new_num_vertices25 = ARRAY_SIZE(exp_vertices25);
7511 /* Test 26. Weld color with usage index larger than 1. Shows that none of
7512 * the epsilon values are used. */
7513 const struct vertex_color vertices26[] =
7515 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7516 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7517 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7519 {{ 3.0f, 3.0f, 0.f}, 0x00000000},
7520 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7521 {{ 1.0f, 0.0f, 0.f}, 0x01010101},
7523 const DWORD indices26[] = {0, 1, 2, 3, 4, 5};
7524 const DWORD attributes26[] = {0, 0};
7525 const UINT num_vertices26 = ARRAY_SIZE(vertices26);
7526 const UINT num_faces26 = ARRAY_SIZE(indices26) / VERTS_PER_FACE;
7527 DWORD flags26 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7528 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};
7529 const DWORD adjacency26[] = {-1, 1, -1, -1, -1, 0};
7530 const struct vertex_color exp_vertices26[] =
7532 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7533 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7534 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7536 {{ 2.0f, 3.0f, 0.f}, 0x00000000},
7537 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7538 {{ 0.0f, 0.0f, 0.f}, 0x01010101},
7540 const DWORD exp_indices26[] = {0, 1, 2, 3, 4, 5};
7541 const DWORD exp_face_remap26[] = {0, 1};
7542 const DWORD exp_vertex_remap26[] = {0, 1, 2, 3, 4, 5};
7543 const DWORD exp_new_num_vertices26 = ARRAY_SIZE(exp_vertices26);
7544 /* Test 27. Weld color with usage index 1 (specular). */
7545 /* Previously this test used float color values and index > 1 but that case
7546 * appears to be effectively unhandled in native so the test gave
7547 * inconsistent results. */
7548 const struct vertex_color vertices27[] =
7550 {{ 0.0f, 3.0f, 0.0f}, 0x00000000},
7551 {{ 2.0f, 3.0f, 0.0f}, 0x10203040},
7552 {{ 0.0f, 0.0f, 0.0f}, 0x50607080},
7554 {{ 3.0f, 3.0f, 0.0f}, 0x11213141},
7555 {{ 3.0f, 0.0f, 0.0f}, 0xffffffff},
7556 {{ 1.0f, 0.0f, 0.0f}, 0x51617181},
7558 const DWORD indices27[] = {0, 1, 2, 3, 4, 5};
7559 const DWORD attributes27[] = {0, 0};
7560 const UINT num_vertices27 = ARRAY_SIZE(vertices27);
7561 const UINT num_faces27 = ARRAY_SIZE(indices27) / VERTS_PER_FACE;
7562 DWORD flags27 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7563 const D3DXWELDEPSILONS epsilons27 =
7565 1.1f, 0.0f, 0.0f, 0.0f, 2.0f / 255.0f, 0.0f,
7566 {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, 0.0f, 0.0f, 0.0f
7568 const DWORD adjacency27[] = {-1, 1, -1, -1, -1, 0};
7569 const struct vertex_color exp_vertices27[] =
7571 {{ 0.0f, 3.0f, 0.0f}, 0x00000000},
7572 {{ 2.0f, 3.0f, 0.0f}, 0x10203040},
7573 {{ 0.0f, 0.0f, 0.0f}, 0x50607080},
7575 {{ 3.0f, 0.0f, 0.0f}, 0xffffffff},
7577 const DWORD exp_indices27[] = {0, 1, 2, 1, 3, 2};
7578 const DWORD exp_face_remap27[] = {0, 1};
7579 const DWORD exp_vertex_remap27[] = {0, 1, 2, 4, -1, -1};
7580 const DWORD exp_new_num_vertices27 = ARRAY_SIZE(exp_vertices27);
7581 /* Test 28. Weld one normal with UDEC3. */
7582 const DWORD dword_udec3_zero = init_udec3_dword(0, 0, 0, 1);
7583 const DWORD dword_udec3_1023 = init_udec3_dword(1023, 1023, 1023, 1);
7584 const DWORD dword_udec3_1022 = init_udec3_dword(1022, 1022, 1022, 1);
7585 const struct vertex_normal_udec3 vertices28[] =
7587 {{ 0.0f, 3.0f, 0.f}, dword_udec3_zero},
7588 {{ 2.0f, 3.0f, 0.f}, dword_udec3_zero},
7589 {{ 0.0f, 0.0f, 0.f}, dword_udec3_zero},
7591 {{ 3.0f, 3.0f, 0.f}, dword_udec3_1023},
7592 {{ 3.0f, 0.0f, 0.f}, dword_udec3_zero},
7593 {{ 1.0f, 0.0f, 0.f}, dword_udec3_1022},
7595 const DWORD indices28[] = {0, 1, 2, 3, 4, 5};
7596 const DWORD attributes28[] = {0, 0};
7597 const UINT num_vertices28 = ARRAY_SIZE(vertices28);
7598 const UINT num_faces28 = ARRAY_SIZE(indices28) / VERTS_PER_FACE;
7599 DWORD flags28 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7600 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};
7601 const DWORD adjacency28[] = {-1, 1, -1, -1, -1, 0};
7602 const struct vertex_normal_udec3 exp_vertices28[] =
7604 {{ 0.0f, 3.0f, 0.f}, dword_udec3_zero},
7605 {{ 2.0f, 3.0f, 0.f}, dword_udec3_zero},
7606 {{ 0.0f, 0.0f, 0.f}, dword_udec3_zero},
7608 {{ 2.0f, 3.0f, 0.f}, dword_udec3_1023},
7609 {{ 3.0f, 0.0f, 0.f}, dword_udec3_zero},
7611 const DWORD exp_indices28[] = {0, 1, 2, 3, 4, 2};
7612 const DWORD exp_face_remap28[] = {0, 1};
7613 const DWORD exp_vertex_remap28[] = {0, 1, 2, 3, 4, -1};
7614 const DWORD exp_new_num_vertices28 = ARRAY_SIZE(exp_vertices28);
7615 /* Test 29. Weld one normal with DEC3N. */
7616 const DWORD dword_dec3n_zero = init_dec3n_dword(0, 0, 0, 1);
7617 const DWORD dword_dec3n_511 = init_dec3n_dword(511, 511, 511, 1);
7618 const DWORD dword_dec3n_510 = init_dec3n_dword(510, 510, 510, 1);
7619 const struct vertex_normal_dec3n vertices29[] =
7621 {{ 0.0f, 3.0f, 0.f}, dword_dec3n_zero},
7622 {{ 2.0f, 3.0f, 0.f}, dword_dec3n_zero},
7623 {{ 0.0f, 0.0f, 0.f}, dword_dec3n_zero},
7625 {{ 3.0f, 3.0f, 0.f}, dword_dec3n_511},
7626 {{ 3.0f, 0.0f, 0.f}, dword_dec3n_zero},
7627 {{ 1.0f, 0.0f, 0.f}, dword_dec3n_510},
7629 const DWORD indices29[] = {0, 1, 2, 3, 4, 5};
7630 const DWORD attributes29[] = {0, 0};
7631 const UINT num_vertices29 = ARRAY_SIZE(vertices29);
7632 const UINT num_faces29 = ARRAY_SIZE(indices29) / VERTS_PER_FACE;
7633 DWORD flags29 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7634 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};
7635 const DWORD adjacency29[] = {-1, 1, -1, -1, -1, 0};
7636 const struct vertex_normal_dec3n exp_vertices29[] =
7638 {{ 0.0f, 3.0f, 0.f}, dword_dec3n_zero},
7639 {{ 2.0f, 3.0f, 0.f}, dword_dec3n_zero},
7640 {{ 0.0f, 0.0f, 0.f}, dword_dec3n_zero},
7642 {{ 2.0f, 3.0f, 0.f}, dword_dec3n_511},
7643 {{ 3.0f, 0.0f, 0.f}, dword_dec3n_zero},
7645 const DWORD exp_indices29[] = {0, 1, 2, 3, 4, 2};
7646 const DWORD exp_face_remap29[] = {0, 1};
7647 const DWORD exp_vertex_remap29[] = {0, 1, 2, 3, 4, -1};
7648 const DWORD exp_new_num_vertices29 = ARRAY_SIZE(exp_vertices29);
7649 /* All mesh data */
7650 DWORD *adjacency_out = NULL;
7651 DWORD *face_remap = NULL;
7652 ID3DXMesh *mesh = NULL;
7653 ID3DXBuffer *vertex_remap = NULL;
7654 struct
7656 const BYTE *vertices;
7657 const DWORD *indices;
7658 const DWORD *attributes;
7659 const DWORD num_vertices;
7660 const DWORD num_faces;
7661 const DWORD options;
7662 D3DVERTEXELEMENT9 *declaration;
7663 const UINT vertex_size;
7664 const DWORD flags;
7665 const D3DXWELDEPSILONS *epsilons;
7666 const DWORD *adjacency;
7667 const BYTE *exp_vertices;
7668 const DWORD *exp_indices;
7669 const DWORD *exp_face_remap;
7670 const DWORD *exp_vertex_remap;
7671 const DWORD exp_new_num_vertices;
7673 tc[] =
7676 (BYTE*)vertices0,
7677 indices0,
7678 attributes0,
7679 num_vertices0,
7680 num_faces0,
7681 options,
7682 declaration_normal,
7683 vertex_size_normal,
7684 flags0,
7685 NULL,
7686 adjacency0,
7687 (BYTE*)exp_vertices0,
7688 exp_indices0,
7689 exp_face_remap0,
7690 exp_vertex_remap0,
7691 exp_new_num_vertices0
7694 (BYTE*)vertices1,
7695 indices1,
7696 attributes1,
7697 num_vertices1,
7698 num_faces1,
7699 options,
7700 declaration_normal,
7701 vertex_size_normal,
7702 flags1,
7703 NULL,
7704 adjacency1,
7705 (BYTE*)exp_vertices1,
7706 exp_indices1,
7707 exp_face_remap1,
7708 exp_vertex_remap1,
7709 exp_new_num_vertices1
7712 (BYTE*)vertices2,
7713 indices2,
7714 attributes2,
7715 num_vertices2,
7716 num_faces2,
7717 options,
7718 declaration_normal,
7719 vertex_size_normal,
7720 flags2,
7721 &epsilons2,
7722 adjacency2,
7723 (BYTE*)exp_vertices2,
7724 exp_indices2,
7725 exp_face_remap2,
7726 exp_vertex_remap2,
7727 exp_new_num_vertices2
7730 (BYTE*)vertices3,
7731 indices3,
7732 attributes3,
7733 num_vertices3,
7734 num_faces3,
7735 options,
7736 declaration_normal,
7737 vertex_size_normal,
7738 flags3,
7739 &epsilons3,
7740 adjacency3,
7741 (BYTE*)exp_vertices3,
7742 exp_indices3,
7743 exp_face_remap3,
7744 exp_vertex_remap3,
7745 exp_new_num_vertices3
7748 (BYTE*)vertices4,
7749 indices4,
7750 attributes4,
7751 num_vertices4,
7752 num_faces4,
7753 options,
7754 declaration_normal,
7755 vertex_size_normal,
7756 flags4,
7757 &epsilons4,
7758 adjacency4,
7759 (BYTE*)exp_vertices4,
7760 exp_indices4,
7761 exp_face_remap4,
7762 exp_vertex_remap4,
7763 exp_new_num_vertices4
7765 /* Unusual ordering. */
7767 (BYTE*)vertices5,
7768 indices5,
7769 attributes5,
7770 num_vertices5,
7771 num_faces5,
7772 options,
7773 declaration_normal,
7774 vertex_size_normal,
7775 flags5,
7776 NULL,
7777 adjacency5,
7778 (BYTE*)exp_vertices5,
7779 exp_indices5,
7780 exp_face_remap5,
7781 exp_vertex_remap5,
7782 exp_new_num_vertices5
7785 (BYTE*)vertices6,
7786 indices6,
7787 attributes6,
7788 num_vertices6,
7789 num_faces6,
7790 options,
7791 declaration_normal,
7792 vertex_size_normal,
7793 flags6,
7794 &epsilons6,
7795 adjacency6,
7796 (BYTE*)exp_vertices6,
7797 exp_indices6,
7798 exp_face_remap6,
7799 exp_vertex_remap6,
7800 exp_new_num_vertices6
7803 (BYTE*)vertices6,
7804 (DWORD*)indices6_16bit,
7805 attributes6,
7806 num_vertices6,
7807 num_faces6,
7808 options_16bit,
7809 declaration_normal,
7810 vertex_size_normal,
7811 flags6,
7812 &epsilons6,
7813 adjacency6,
7814 (BYTE*)exp_vertices6,
7815 exp_indices6,
7816 exp_face_remap6,
7817 exp_vertex_remap6,
7818 exp_new_num_vertices6
7821 (BYTE*)vertices8,
7822 indices8,
7823 attributes8,
7824 num_vertices8,
7825 num_faces8,
7826 options,
7827 declaration_normal,
7828 vertex_size_normal,
7829 flags8,
7830 &epsilons8,
7831 adjacency8,
7832 (BYTE*)exp_vertices8,
7833 exp_indices8,
7834 exp_face_remap8,
7835 exp_vertex_remap8,
7836 exp_new_num_vertices8
7839 (BYTE*)vertices9,
7840 indices9,
7841 attributes9,
7842 num_vertices9,
7843 num_faces9,
7844 options,
7845 declaration_normal,
7846 vertex_size_normal,
7847 flags9,
7848 &epsilons9,
7849 adjacency9,
7850 (BYTE*)exp_vertices9,
7851 exp_indices9,
7852 exp_face_remap9,
7853 exp_vertex_remap9,
7854 exp_new_num_vertices9
7857 (BYTE*)vertices10,
7858 indices10,
7859 attributes10,
7860 num_vertices10,
7861 num_faces10,
7862 options,
7863 declaration_blendweight,
7864 vertex_size_blendweight,
7865 flags10,
7866 &epsilons10,
7867 adjacency10,
7868 (BYTE*)exp_vertices10,
7869 exp_indices10,
7870 exp_face_remap10,
7871 exp_vertex_remap10,
7872 exp_new_num_vertices10
7875 (BYTE*)vertices11,
7876 indices11,
7877 attributes11,
7878 num_vertices11,
7879 num_faces11,
7880 options,
7881 declaration_texcoord,
7882 vertex_size_texcoord,
7883 flags11,
7884 &epsilons11,
7885 adjacency11,
7886 (BYTE*)exp_vertices11,
7887 exp_indices11,
7888 exp_face_remap11,
7889 exp_vertex_remap11,
7890 exp_new_num_vertices11
7893 (BYTE*)vertices12,
7894 indices12,
7895 attributes12,
7896 num_vertices12,
7897 num_faces12,
7898 options,
7899 declaration_color,
7900 vertex_size_color,
7901 flags12,
7902 &epsilons12,
7903 adjacency12,
7904 (BYTE*)exp_vertices12,
7905 exp_indices12,
7906 exp_face_remap12,
7907 exp_vertex_remap12,
7908 exp_new_num_vertices12
7911 (BYTE*)vertices13,
7912 indices13,
7913 attributes13,
7914 num_vertices13,
7915 num_faces13,
7916 options,
7917 declaration_normal3,
7918 vertex_size_normal,
7919 flags13,
7920 &epsilons13,
7921 adjacency13,
7922 (BYTE*)exp_vertices13,
7923 exp_indices13,
7924 exp_face_remap13,
7925 exp_vertex_remap13,
7926 exp_new_num_vertices13
7929 (BYTE*)vertices14,
7930 indices14,
7931 attributes14,
7932 num_vertices14,
7933 num_faces14,
7934 options,
7935 declaration_color,
7936 vertex_size_color,
7937 flags14,
7938 &epsilons14,
7939 adjacency14,
7940 (BYTE*)exp_vertices14,
7941 exp_indices14,
7942 exp_face_remap14,
7943 exp_vertex_remap14,
7944 exp_new_num_vertices14
7947 (BYTE*)vertices15,
7948 indices15,
7949 attributes15,
7950 num_vertices15,
7951 num_faces15,
7952 options,
7953 declaration_color_ubyte4n,
7954 vertex_size_color_ubyte4, /* UBYTE4 same size as UBYTE4N */
7955 flags15,
7956 &epsilons15,
7957 adjacency15,
7958 (BYTE*)exp_vertices15,
7959 exp_indices15,
7960 exp_face_remap15,
7961 exp_vertex_remap15,
7962 exp_new_num_vertices15
7965 (BYTE*)vertices16,
7966 indices16,
7967 attributes16,
7968 num_vertices16,
7969 num_faces16,
7970 options,
7971 declaration_color_ubyte4,
7972 vertex_size_color_ubyte4,
7973 flags16,
7974 &epsilons16,
7975 adjacency16,
7976 (BYTE*)exp_vertices16,
7977 exp_indices16,
7978 exp_face_remap16,
7979 exp_vertex_remap16,
7980 exp_new_num_vertices16
7983 (BYTE*)vertices17,
7984 indices17,
7985 attributes17,
7986 num_vertices17,
7987 num_faces17,
7988 options,
7989 declaration_texcoord_short2,
7990 vertex_size_texcoord_short2,
7991 flags17,
7992 &epsilons17,
7993 adjacency17,
7994 (BYTE*)exp_vertices17,
7995 exp_indices17,
7996 exp_face_remap17,
7997 exp_vertex_remap17,
7998 exp_new_num_vertices17
8001 (BYTE*)vertices18,
8002 indices18,
8003 attributes18,
8004 num_vertices18,
8005 num_faces18,
8006 options,
8007 declaration_texcoord_short2n,
8008 vertex_size_texcoord_short2, /* SHORT2 same size as SHORT2N */
8009 flags18,
8010 &epsilons18,
8011 adjacency18,
8012 (BYTE*)exp_vertices18,
8013 exp_indices18,
8014 exp_face_remap18,
8015 exp_vertex_remap18,
8016 exp_new_num_vertices18
8019 (BYTE*)vertices19,
8020 indices19,
8021 attributes19,
8022 num_vertices19,
8023 num_faces19,
8024 options,
8025 declaration_texcoord_ushort2n,
8026 vertex_size_texcoord_short2, /* SHORT2 same size as USHORT2N */
8027 flags19,
8028 &epsilons19,
8029 adjacency19,
8030 (BYTE*)exp_vertices19,
8031 exp_indices19,
8032 exp_face_remap19,
8033 exp_vertex_remap19,
8034 exp_new_num_vertices19
8037 (BYTE*)vertices20,
8038 indices20,
8039 attributes20,
8040 num_vertices20,
8041 num_faces20,
8042 options,
8043 declaration_normal_short4,
8044 vertex_size_normal_short4,
8045 flags20,
8046 &epsilons20,
8047 adjacency20,
8048 (BYTE*)exp_vertices20,
8049 exp_indices20,
8050 exp_face_remap20,
8051 exp_vertex_remap20,
8052 exp_new_num_vertices20
8055 (BYTE*)vertices21,
8056 indices21,
8057 attributes21,
8058 num_vertices21,
8059 num_faces21,
8060 options,
8061 declaration_normal_short4n,
8062 vertex_size_normal_short4, /* SHORT4 same size as SHORT4N */
8063 flags21,
8064 &epsilons21,
8065 adjacency21,
8066 (BYTE*)exp_vertices21,
8067 exp_indices21,
8068 exp_face_remap21,
8069 exp_vertex_remap21,
8070 exp_new_num_vertices21
8073 (BYTE*)vertices22,
8074 indices22,
8075 attributes22,
8076 num_vertices22,
8077 num_faces22,
8078 options,
8079 declaration_normal_ushort4n,
8080 vertex_size_normal_short4, /* SHORT4 same size as USHORT4N */
8081 flags22,
8082 &epsilons22,
8083 adjacency22,
8084 (BYTE*)exp_vertices22,
8085 exp_indices22,
8086 exp_face_remap22,
8087 exp_vertex_remap22,
8088 exp_new_num_vertices22
8091 (BYTE*)vertices23,
8092 indices23,
8093 attributes23,
8094 num_vertices23,
8095 num_faces23,
8096 options,
8097 declaration_texcoord_float16_2,
8098 vertex_size_texcoord_float16_2,
8099 flags23,
8100 &epsilons23,
8101 adjacency23,
8102 (BYTE*)exp_vertices23,
8103 exp_indices23,
8104 exp_face_remap23,
8105 exp_vertex_remap23,
8106 exp_new_num_vertices23
8109 (BYTE*)vertices24,
8110 indices24,
8111 attributes24,
8112 num_vertices24,
8113 num_faces24,
8114 options,
8115 declaration_texcoord_float16_4,
8116 vertex_size_texcoord_float16_4,
8117 flags24,
8118 &epsilons24,
8119 adjacency24,
8120 (BYTE*)exp_vertices24,
8121 exp_indices24,
8122 exp_face_remap24,
8123 exp_vertex_remap24,
8124 exp_new_num_vertices24
8127 (BYTE*)vertices25,
8128 indices25,
8129 attributes25,
8130 num_vertices25,
8131 num_faces25,
8132 options,
8133 declaration_texcoord10,
8134 vertex_size_texcoord,
8135 flags25,
8136 &epsilons25,
8137 adjacency25,
8138 (BYTE*)exp_vertices25,
8139 exp_indices25,
8140 exp_face_remap25,
8141 exp_vertex_remap25,
8142 exp_new_num_vertices25
8145 (BYTE*)vertices26,
8146 indices26,
8147 attributes26,
8148 num_vertices26,
8149 num_faces26,
8150 options,
8151 declaration_color2,
8152 vertex_size_color,
8153 flags26,
8154 &epsilons26,
8155 adjacency26,
8156 (BYTE*)exp_vertices26,
8157 exp_indices26,
8158 exp_face_remap26,
8159 exp_vertex_remap26,
8160 exp_new_num_vertices26
8163 (BYTE*)vertices27,
8164 indices27,
8165 attributes27,
8166 num_vertices27,
8167 num_faces27,
8168 options,
8169 declaration_color1,
8170 vertex_size_color,
8171 flags27,
8172 &epsilons27,
8173 adjacency27,
8174 (BYTE*)exp_vertices27,
8175 exp_indices27,
8176 exp_face_remap27,
8177 exp_vertex_remap27,
8178 exp_new_num_vertices27
8181 (BYTE*)vertices28,
8182 indices28,
8183 attributes28,
8184 num_vertices28,
8185 num_faces28,
8186 options,
8187 declaration_normal_udec3,
8188 vertex_size_normal_udec3,
8189 flags28,
8190 &epsilons28,
8191 adjacency28,
8192 (BYTE*)exp_vertices28,
8193 exp_indices28,
8194 exp_face_remap28,
8195 exp_vertex_remap28,
8196 exp_new_num_vertices28
8199 (BYTE*)vertices29,
8200 indices29,
8201 attributes29,
8202 num_vertices29,
8203 num_faces29,
8204 options,
8205 declaration_normal_dec3n,
8206 vertex_size_normal_dec3n,
8207 flags29,
8208 &epsilons29,
8209 adjacency29,
8210 (BYTE*)exp_vertices29,
8211 exp_indices29,
8212 exp_face_remap29,
8213 exp_vertex_remap29,
8214 exp_new_num_vertices29
8218 test_context = new_test_context();
8219 if (!test_context)
8221 skip("Couldn't create test context\n");
8222 goto cleanup;
8225 for (i = 0; i < ARRAY_SIZE(tc); i++)
8227 DWORD j;
8228 DWORD *vertex_remap_ptr;
8229 DWORD new_num_vertices;
8231 hr = init_test_mesh(tc[i].num_faces, tc[i].num_vertices, tc[i].options,
8232 tc[i].declaration, test_context->device, &mesh,
8233 tc[i].vertices, tc[i].vertex_size,
8234 tc[i].indices, tc[i].attributes);
8235 if (FAILED(hr))
8237 skip("Couldn't initialize test mesh %d.\n", i);
8238 goto cleanup;
8241 /* Allocate out parameters */
8242 adjacency_out = HeapAlloc(GetProcessHeap(), 0, VERTS_PER_FACE * tc[i].num_faces * sizeof(*adjacency_out));
8243 if (!adjacency_out)
8245 skip("Couldn't allocate adjacency_out array.\n");
8246 goto cleanup;
8248 face_remap = HeapAlloc(GetProcessHeap(), 0, tc[i].num_faces * sizeof(*face_remap));
8249 if (!face_remap)
8251 skip("Couldn't allocate face_remap array.\n");
8252 goto cleanup;
8255 hr = D3DXWeldVertices(mesh, tc[i].flags, tc[i].epsilons, tc[i].adjacency,
8256 adjacency_out, face_remap, &vertex_remap);
8257 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
8258 /* Check number of vertices*/
8259 new_num_vertices = mesh->lpVtbl->GetNumVertices(mesh);
8260 ok(new_num_vertices == tc[i].exp_new_num_vertices,
8261 "Mesh %d: new_num_vertices == %d, expected %d.\n",
8262 i, new_num_vertices, tc[i].exp_new_num_vertices);
8263 /* Check index buffer */
8264 if (tc[i].options & D3DXMESH_32BIT)
8266 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, (void**)&indices);
8267 if (FAILED(hr))
8269 skip("Couldn't lock index buffer.\n");
8270 goto cleanup;
8272 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
8274 ok(indices[j] == tc[i].exp_indices[j],
8275 "Mesh %d: indices[%d] == %d, expected %d\n",
8276 i, j, indices[j], tc[i].exp_indices[j]);
8279 else
8281 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, (void**)&indices_16bit);
8282 if (FAILED(hr))
8284 skip("Couldn't lock index buffer.\n");
8285 goto cleanup;
8287 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
8289 ok(indices_16bit[j] == tc[i].exp_indices[j],
8290 "Mesh %d: indices_16bit[%d] == %d, expected %d\n",
8291 i, j, indices_16bit[j], tc[i].exp_indices[j]);
8294 mesh->lpVtbl->UnlockIndexBuffer(mesh);
8295 indices = NULL;
8296 indices_16bit = NULL;
8297 /* Check adjacency_out */
8298 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
8300 ok(adjacency_out[j] == tc[i].adjacency[j],
8301 "Mesh %d: adjacency_out[%d] == %d, expected %d\n",
8302 i, j, adjacency_out[j], tc[i].adjacency[j]);
8304 /* Check face_remap */
8305 for (j = 0; j < tc[i].num_faces; j++)
8307 ok(face_remap[j] == tc[i].exp_face_remap[j],
8308 "Mesh %d: face_remap[%d] == %d, expected %d\n",
8309 i, j, face_remap[j], tc[i].exp_face_remap[j]);
8311 /* Check vertex_remap */
8312 vertex_remap_ptr = vertex_remap->lpVtbl->GetBufferPointer(vertex_remap);
8313 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
8315 ok(vertex_remap_ptr[j] == tc[i].exp_vertex_remap[j],
8316 "Mesh %d: vertex_remap_ptr[%d] == %d, expected %d\n",
8317 i, j, vertex_remap_ptr[j], tc[i].exp_vertex_remap[j]);
8319 /* Check vertex buffer */
8320 hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, (void*)&vertices);
8321 if (FAILED(hr))
8323 skip("Couldn't lock vertex buffer.\n");
8324 goto cleanup;
8326 /* Check contents of re-ordered vertex buffer */
8327 for (j = 0; j < tc[i].exp_new_num_vertices; j++)
8329 int index = tc[i].vertex_size*j;
8330 check_vertex_components(__LINE__, i, j, &vertices[index], &tc[i].exp_vertices[index], tc[i].declaration);
8332 mesh->lpVtbl->UnlockVertexBuffer(mesh);
8333 vertices = NULL;
8335 /* Free mesh and output data */
8336 HeapFree(GetProcessHeap(), 0, adjacency_out);
8337 adjacency_out = NULL;
8338 HeapFree(GetProcessHeap(), 0, face_remap);
8339 face_remap = NULL;
8340 vertex_remap->lpVtbl->Release(vertex_remap);
8341 vertex_remap = NULL;
8342 mesh->lpVtbl->Release(mesh);
8343 mesh = NULL;
8346 cleanup:
8347 HeapFree(GetProcessHeap(), 0, adjacency_out);
8348 HeapFree(GetProcessHeap(), 0, face_remap);
8349 if (indices) mesh->lpVtbl->UnlockIndexBuffer(mesh);
8350 if (indices_16bit) mesh->lpVtbl->UnlockIndexBuffer(mesh);
8351 if (mesh) mesh->lpVtbl->Release(mesh);
8352 if (vertex_remap) vertex_remap->lpVtbl->Release(vertex_remap);
8353 if (vertices) mesh->lpVtbl->UnlockVertexBuffer(mesh);
8354 free_test_context(test_context);
8357 static void test_clone_mesh(void)
8359 HRESULT hr;
8360 struct test_context *test_context = NULL;
8361 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
8362 D3DVERTEXELEMENT9 declaration_pn[] =
8364 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8365 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
8366 D3DDECL_END()
8368 D3DVERTEXELEMENT9 declaration_pntc[] =
8370 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8371 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
8372 {0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8373 D3DDECL_END()
8375 D3DVERTEXELEMENT9 declaration_ptcn[] =
8377 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8378 {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8379 {0, 20, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
8380 D3DDECL_END()
8382 D3DVERTEXELEMENT9 declaration_ptc[] =
8384 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8385 {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8386 D3DDECL_END()
8388 D3DVERTEXELEMENT9 declaration_ptc_float16_2[] =
8390 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8391 {0, 12, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8392 D3DDECL_END()
8394 D3DVERTEXELEMENT9 declaration_ptc_float16_4[] =
8396 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8397 {0, 12, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8398 D3DDECL_END()
8400 D3DVERTEXELEMENT9 declaration_ptc_float1[] =
8402 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8403 {0, 12, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8404 D3DDECL_END()
8406 D3DVERTEXELEMENT9 declaration_ptc_float3[] =
8408 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8409 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8410 D3DDECL_END()
8412 D3DVERTEXELEMENT9 declaration_ptc_float4[] =
8414 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8415 {0, 12, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8416 D3DDECL_END()
8418 D3DVERTEXELEMENT9 declaration_ptc_d3dcolor[] =
8420 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8421 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8422 D3DDECL_END()
8424 D3DVERTEXELEMENT9 declaration_ptc_ubyte4[] =
8426 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8427 {0, 12, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8428 D3DDECL_END()
8430 D3DVERTEXELEMENT9 declaration_ptc_ubyte4n[] =
8432 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8433 {0, 12, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8434 D3DDECL_END()
8436 D3DVERTEXELEMENT9 declaration_ptc_short2[] =
8438 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8439 {0, 12, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8440 D3DDECL_END()
8442 D3DVERTEXELEMENT9 declaration_ptc_short4[] =
8444 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8445 {0, 12, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8446 D3DDECL_END()
8448 D3DVERTEXELEMENT9 declaration_ptc_short2n[] =
8450 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8451 {0, 12, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8452 D3DDECL_END()
8454 D3DVERTEXELEMENT9 declaration_ptc_short4n[] =
8456 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8457 {0, 12, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8458 D3DDECL_END()
8460 D3DVERTEXELEMENT9 declaration_ptc_ushort2n[] =
8462 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8463 {0, 12, D3DDECLTYPE_USHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8464 D3DDECL_END()
8466 D3DVERTEXELEMENT9 declaration_ptc_ushort4n[] =
8468 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8469 {0, 12, D3DDECLTYPE_USHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8470 D3DDECL_END()
8472 D3DVERTEXELEMENT9 declaration_ptc_float16_2_partialu[] =
8474 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8475 {0, 12, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_PARTIALU, D3DDECLUSAGE_TEXCOORD, 0},
8476 D3DDECL_END()
8478 D3DVERTEXELEMENT9 declaration_pntc1[] =
8480 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8481 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
8482 {0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
8483 D3DDECL_END()
8485 const unsigned int VERTS_PER_FACE = 3;
8486 BYTE *vertices = NULL;
8487 INT i;
8488 struct vertex_pn
8490 D3DXVECTOR3 position;
8491 D3DXVECTOR3 normal;
8493 struct vertex_pntc
8495 D3DXVECTOR3 position;
8496 D3DXVECTOR3 normal;
8497 D3DXVECTOR2 texcoords;
8499 struct vertex_ptcn
8501 D3DXVECTOR3 position;
8502 D3DXVECTOR2 texcoords;
8503 D3DXVECTOR3 normal;
8505 struct vertex_ptc
8507 D3DXVECTOR3 position;
8508 D3DXVECTOR2 texcoords;
8510 struct vertex_ptc_float16_2
8512 D3DXVECTOR3 position;
8513 WORD texcoords[2]; /* float16_2 */
8515 struct vertex_ptc_float16_4
8517 D3DXVECTOR3 position;
8518 WORD texcoords[4]; /* float16_4 */
8520 struct vertex_ptc_float1
8522 D3DXVECTOR3 position;
8523 FLOAT texcoords;
8525 struct vertex_ptc_float3
8527 D3DXVECTOR3 position;
8528 FLOAT texcoords[3];
8530 struct vertex_ptc_float4
8532 D3DXVECTOR3 position;
8533 FLOAT texcoords[4];
8535 struct vertex_ptc_d3dcolor
8537 D3DXVECTOR3 position;
8538 BYTE texcoords[4];
8540 struct vertex_ptc_ubyte4
8542 D3DXVECTOR3 position;
8543 BYTE texcoords[4];
8545 struct vertex_ptc_ubyte4n
8547 D3DXVECTOR3 position;
8548 BYTE texcoords[4];
8550 struct vertex_ptc_short2
8552 D3DXVECTOR3 position;
8553 SHORT texcoords[2];
8555 struct vertex_ptc_short4
8557 D3DXVECTOR3 position;
8558 SHORT texcoords[4];
8560 struct vertex_ptc_ushort2n
8562 D3DXVECTOR3 position;
8563 USHORT texcoords[2];
8565 struct vertex_ptc_ushort4n
8567 D3DXVECTOR3 position;
8568 USHORT texcoords[4];
8570 struct vertex_ptc_udec3
8572 D3DXVECTOR3 position;
8573 DWORD texcoords;
8575 struct vertex_ptc_dec3n
8577 D3DXVECTOR3 position;
8578 DWORD texcoords;
8580 D3DXVECTOR3 up = {0.0f, 0.0f, 1.0f};
8581 D3DXVECTOR2 zero_vec2 = {0.0f, 0.0f};
8582 /* Test 0. Check that a mesh can be cloned if the new declaration is the
8583 * same as the one used to create the mesh.
8585 * 0--1 3
8586 * | / /|
8587 * |/ / |
8588 * 2 5--4
8590 const struct vertex_pn vertices0[] =
8592 {{ 0.0f, 3.0f, 0.f}, up},
8593 {{ 2.0f, 3.0f, 0.f}, up},
8594 {{ 0.0f, 0.0f, 0.f}, up},
8596 {{ 3.0f, 3.0f, 0.f}, up},
8597 {{ 3.0f, 0.0f, 0.f}, up},
8598 {{ 1.0f, 0.0f, 0.f}, up},
8600 const UINT num_vertices0 = ARRAY_SIZE(vertices0);
8601 const UINT num_faces0 = ARRAY_SIZE(vertices0) / VERTS_PER_FACE;
8602 const UINT vertex_size0 = sizeof(*vertices0);
8603 /* Test 1. Check that 16-bit indices are handled. */
8604 const DWORD options_16bit = D3DXMESH_SYSTEMMEM;
8605 /* Test 2. Check that the size of each vertex is increased and the data
8606 * moved if the new declaration adds an element after the original elements.
8608 const struct vertex_pntc exp_vertices2[] =
8610 {{ 0.0f, 3.0f, 0.f}, up, zero_vec2},
8611 {{ 2.0f, 3.0f, 0.f}, up, zero_vec2},
8612 {{ 0.0f, 0.0f, 0.f}, up, zero_vec2},
8614 {{ 3.0f, 3.0f, 0.f}, up, zero_vec2},
8615 {{ 3.0f, 0.0f, 0.f}, up, zero_vec2},
8616 {{ 1.0f, 0.0f, 0.f}, up, zero_vec2},
8618 const UINT exp_vertex_size2 = sizeof(*exp_vertices2);
8619 /* Test 3. Check that the size of each vertex is increased and the data
8620 * moved if the new declaration adds an element between the original
8621 * elements.
8623 const struct vertex_ptcn exp_vertices3[] =
8625 {{ 0.0f, 3.0f, 0.f}, zero_vec2, up},
8626 {{ 2.0f, 3.0f, 0.f}, zero_vec2, up},
8627 {{ 0.0f, 0.0f, 0.f}, zero_vec2, up},
8629 {{ 3.0f, 3.0f, 0.f}, zero_vec2, up},
8630 {{ 3.0f, 0.0f, 0.f}, zero_vec2, up},
8631 {{ 1.0f, 0.0f, 0.f}, zero_vec2, up},
8633 const UINT exp_vertex_size3 = sizeof(*exp_vertices3);
8634 /* Test 4. Test that data types can be converted, e.g. FLOAT2 to FLOAT16_2. */
8635 const struct vertex_ptc vertices4[] =
8637 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8638 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8639 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
8641 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8642 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
8643 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
8645 const UINT num_vertices4 = ARRAY_SIZE(vertices4);
8646 const UINT num_faces4 = ARRAY_SIZE(vertices4) / VERTS_PER_FACE;
8647 const UINT vertex_size4 = sizeof(*vertices4);
8648 const struct vertex_ptc_float16_2 exp_vertices4[] =
8650 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
8651 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */
8652 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */
8654 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd}}, /* {0.2f, 0.3f} */
8655 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
8656 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */
8658 const UINT exp_vertex_size4 = sizeof(*exp_vertices4);
8659 /* Test 5. Convert FLOAT2 to FLOAT16_4. */
8660 const struct vertex_ptc vertices5[] =
8662 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8663 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8664 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
8666 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8667 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
8668 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
8670 const UINT num_vertices5 = ARRAY_SIZE(vertices5);
8671 const UINT num_faces5 = ARRAY_SIZE(vertices5) / VERTS_PER_FACE;
8672 const UINT vertex_size5 = sizeof(*vertices5);
8673 const struct vertex_ptc_float16_4 exp_vertices5[] =
8675 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00, 0, 0x3c00}}, /* {1.0f, 1.0f, 0.0f, 1.0f} */
8676 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a, 0, 0x3c00}}, /* {0.5f, 0.7f, 0.0f, 1.0f} */
8677 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd, 0, 0x3c00}}, /* {-0.2f, -0.3f, 0.0f, 1.0f} */
8679 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd, 0, 0x3c00}}, /* {0.2f, 0.3f, 0.0f, 1.0f} */
8680 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00, 0, 0x3c00}}, /* {1.0f, 1.0f, 0.0f, 1.0f} */
8681 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266, 0, 0x3c00}}, /* {0.1f, 0.2f, 0.0f, 1.0f} */
8683 const UINT exp_vertex_size5 = sizeof(*exp_vertices5);
8684 /* Test 6. Convert FLOAT2 to FLOAT1. */
8685 const struct vertex_ptc vertices6[] =
8687 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8688 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8689 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
8691 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8692 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
8693 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
8695 const UINT num_vertices6 = ARRAY_SIZE(vertices6);
8696 const UINT num_faces6 = ARRAY_SIZE(vertices6) / VERTS_PER_FACE;
8697 const UINT vertex_size6 = sizeof(*vertices6);
8698 const struct vertex_ptc_float1 exp_vertices6[] =
8700 {{ 0.0f, 3.0f, 0.f}, 1.0f},
8701 {{ 2.0f, 3.0f, 0.f}, 0.5f},
8702 {{ 0.0f, 0.0f, 0.f}, -0.2f},
8704 {{ 3.0f, 3.0f, 0.f}, 0.2f},
8705 {{ 3.0f, 0.0f, 0.f}, 1.0f},
8706 {{ 1.0f, 0.0f, 0.f}, 0.1f},
8708 const UINT exp_vertex_size6 = sizeof(*exp_vertices6);
8709 /* Test 7. Convert FLOAT2 to FLOAT3. */
8710 const struct vertex_ptc vertices7[] =
8712 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8713 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8714 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
8716 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8717 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
8718 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
8720 const UINT num_vertices7 = ARRAY_SIZE(vertices7);
8721 const UINT num_faces7 = ARRAY_SIZE(vertices7) / VERTS_PER_FACE;
8722 const UINT vertex_size7 = sizeof(*vertices7);
8723 const struct vertex_ptc_float3 exp_vertices7[] =
8725 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f, 0.0f}},
8726 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f, 0.0f}},
8727 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f, 0.0f}},
8729 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f, 0.0f}},
8730 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f, 0.0f}},
8731 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f, 0.0f}},
8733 const UINT exp_vertex_size7 = sizeof(*exp_vertices7);
8734 /* Test 8. Convert FLOAT2 to FLOAT4. */
8735 const struct vertex_ptc vertices8[] =
8737 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8738 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8739 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
8741 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8742 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
8743 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
8745 const UINT num_vertices8 = ARRAY_SIZE(vertices8);
8746 const UINT num_faces8 = ARRAY_SIZE(vertices8) / VERTS_PER_FACE;
8747 const UINT vertex_size8 = sizeof(*vertices8);
8748 const struct vertex_ptc_float4 exp_vertices8[] =
8750 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f, 0.0f, 1.0f}},
8751 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f, 0.0f, 1.0f}},
8752 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f, 0.0f, 1.0f}},
8754 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f, 0.0f, 1.0f}},
8755 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f, 0.0f, 1.0f}},
8756 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f, 0.0f, 1.0f}},
8758 const UINT exp_vertex_size8 = sizeof(*exp_vertices8);
8759 /* Test 9. Convert FLOAT2 to D3DCOLOR. */
8760 const struct vertex_ptc vertices9[] =
8762 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8763 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8764 {{ 0.0f, 0.0f, 0.f}, {-0.4f, -0.6f}},
8766 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8767 {{ 3.0f, 0.0f, 0.f}, { 2.0f, 256.0f}},
8768 {{ 1.0f, 0.0f, 0.f}, { 0.11f, 0.2f}},
8770 const UINT num_vertices9 = ARRAY_SIZE(vertices9);
8771 const UINT num_faces9 = ARRAY_SIZE(vertices9) / VERTS_PER_FACE;
8772 const UINT vertex_size9 = sizeof(*vertices9);
8773 const struct vertex_ptc_d3dcolor exp_vertices9[] =
8775 {{ 0.0f, 3.0f, 0.f}, {0, 255, 255, 255}},
8776 {{ 2.0f, 3.0f, 0.f}, {0, 179, 128, 255}},
8777 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 255}},
8779 {{ 3.0f, 3.0f, 0.f}, {0, 77, 51, 255}},
8780 {{ 3.0f, 0.0f, 0.f}, {0, 255, 255, 255}},
8781 {{ 1.0f, 0.0f, 0.f}, {0, 51, 28, 255}},
8783 const UINT exp_vertex_size9 = sizeof(*exp_vertices9);
8784 /* Test 10. Convert FLOAT2 to UBYTE4. */
8785 const struct vertex_ptc vertices10[] =
8787 {{ 0.0f, 3.0f, 0.f}, { 0.0f, 1.0f}},
8788 {{ 2.0f, 3.0f, 0.f}, { 2.0f, 3.0f}},
8789 {{ 0.0f, 0.0f, 0.f}, { 254.0f, 255.0f}},
8791 {{ 3.0f, 3.0f, 0.f}, { 256.0f, 257.0f}},
8792 {{ 3.0f, 0.0f, 0.f}, { 1.4f, 1.5f}},
8793 {{ 1.0f, 0.0f, 0.f}, {-4.0f, -5.0f}},
8795 const UINT num_vertices10 = ARRAY_SIZE(vertices10);
8796 const UINT num_faces10 = ARRAY_SIZE(vertices10) / VERTS_PER_FACE;
8797 const UINT vertex_size10 = sizeof(*vertices10);
8798 const struct vertex_ptc_ubyte4 exp_vertices10[] =
8800 {{ 0.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
8801 {{ 2.0f, 3.0f, 0.f}, {2, 3, 0, 1}},
8802 {{ 0.0f, 0.0f, 0.f}, {254, 255, 0, 1}},
8804 {{ 3.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
8805 {{ 3.0f, 0.0f, 0.f}, {1, 2, 0, 1}},
8806 {{ 1.0f, 0.0f, 0.f}, {0, 0, 0, 1}},
8808 const UINT exp_vertex_size10 = sizeof(*exp_vertices10);
8809 /* Test 11. Convert FLOAT2 to SHORT2. */
8810 const struct vertex_ptc vertices11[] =
8812 {{ 0.0f, 3.0f, 0.f}, { 1.0f, -1.0f}},
8813 {{ 2.0f, 3.0f, 0.f}, { 0.4f, 0.5f}},
8814 {{ 0.0f, 0.0f, 0.f}, {-0.5f, -5.0f}},
8816 {{ 3.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MIN}},
8817 {{ 3.0f, 0.0f, 0.f}, {SHRT_MAX + 1.0f, SHRT_MIN - 1.0f}},
8818 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX + 2.0f, SHRT_MIN - 2.0f}},
8820 {{ 4.0f, 3.0f, 0.f}, {2 * SHRT_MAX, 2 * SHRT_MIN}},
8821 {{ 6.0f, 0.0f, 0.f}, {3 * SHRT_MAX, 3 * SHRT_MIN}},
8822 {{ 4.0f, 0.0f, 0.f}, {4 * SHRT_MAX, 4 * SHRT_MIN}},
8824 const UINT num_vertices11 = ARRAY_SIZE(vertices11);
8825 const UINT num_faces11 = ARRAY_SIZE(vertices11) / VERTS_PER_FACE;
8826 const UINT vertex_size11 = sizeof(*vertices11);
8827 const struct vertex_ptc_short2 exp_vertices11[] =
8829 {{ 0.0f, 3.0f, 0.f}, {1, 0}},
8830 {{ 2.0f, 3.0f, 0.f}, {0, 1}},
8831 {{ 0.0f, 0.0f, 0.f}, {0, -4}},
8833 {{ 3.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MIN + 1}},
8834 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MIN}},
8835 {{ 1.0f, 0.0f, 0.f}, {SHRT_MIN + 1, SHRT_MAX}},
8837 {{ 4.0f, 3.0f, 0.f}, {-2, 1}},
8838 {{ 6.0f, 0.0f, 0.f}, {32765, -32767}},
8839 {{ 4.0f, 0.0f, 0.f}, {-4, 1}},
8841 const UINT exp_vertex_size11 = sizeof(*exp_vertices11);
8842 /* Test 12. Convert FLOAT2 to SHORT4. */
8843 const struct vertex_ptc vertices12[] =
8845 {{ 0.0f, 3.0f, 0.f}, { 1.0f, -1.0f}},
8846 {{ 2.0f, 3.0f, 0.f}, { 0.4f, 0.5f}},
8847 {{ 0.0f, 0.0f, 0.f}, {-0.5f, -5.0f}},
8849 {{ 3.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MIN}},
8850 {{ 3.0f, 0.0f, 0.f}, {SHRT_MAX + 1.0f, SHRT_MIN - 1.0f}},
8851 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX + 2.0f, SHRT_MIN - 2.0f}},
8853 {{ 4.0f, 3.0f, 0.f}, {2 * SHRT_MAX, 2 * SHRT_MIN}},
8854 {{ 6.0f, 0.0f, 0.f}, {3 * SHRT_MAX, 3 * SHRT_MIN}},
8855 {{ 4.0f, 0.0f, 0.f}, {4 * SHRT_MAX, 4 * SHRT_MIN}},
8857 const UINT num_vertices12 = ARRAY_SIZE(vertices12);
8858 const UINT num_faces12 = ARRAY_SIZE(vertices12) / VERTS_PER_FACE;
8859 const UINT vertex_size12 = sizeof(*vertices12);
8860 const struct vertex_ptc_short4 exp_vertices12[] =
8862 {{ 0.0f, 3.0f, 0.f}, {1, 0, 0, 1}},
8863 {{ 2.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
8864 {{ 0.0f, 0.0f, 0.f}, {0, -4, 0, 1}},
8866 {{ 3.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MIN + 1, 0, 1}},
8867 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MIN, 0, 1}},
8868 {{ 1.0f, 0.0f, 0.f}, {SHRT_MIN + 1, SHRT_MAX, 0, 1}},
8870 {{ 4.0f, 3.0f, 0.f}, {-2, 1, 0, 1}},
8871 {{ 6.0f, 0.0f, 0.f}, {32765, -32767, 0, 1}},
8872 {{ 4.0f, 0.0f, 0.f}, {-4, 1, 0, 1}},
8874 const UINT exp_vertex_size12 = sizeof(*exp_vertices12);
8875 /* Test 13. Convert FLOAT2 to UBYTE4N. */
8876 const struct vertex_ptc vertices13[] =
8878 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 2.0f}},
8879 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8880 {{ 0.0f, 0.0f, 0.f}, {-0.4f, -0.5f}},
8882 {{ 3.0f, 3.0f, 0.f}, {-0.6f, -1.0f}},
8883 {{ 3.0f, 0.0f, 0.f}, {UCHAR_MAX, UCHAR_MAX + 1}},
8884 {{ 1.0f, 0.0f, 0.f}, {2 * UCHAR_MAX, -UCHAR_MAX}},
8886 const UINT num_vertices13 = ARRAY_SIZE(vertices13);
8887 const UINT num_faces13 = ARRAY_SIZE(vertices13) / VERTS_PER_FACE;
8888 const UINT vertex_size13 = sizeof(*vertices13);
8889 const struct vertex_ptc_ubyte4n exp_vertices13[] =
8891 {{ 0.0f, 3.0f, 0.f}, {255, 255, 0, 255}},
8892 {{ 2.0f, 3.0f, 0.f}, {128, 179, 0, 255}},
8893 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 255}},
8895 {{ 3.0f, 3.0f, 0.f}, {0, 0, 0, 255}},
8896 {{ 3.0f, 0.0f, 0.f}, {255, 255, 0, 255}},
8897 {{ 1.0f, 0.0f, 0.f}, {255, 0, 0, 255}},
8899 const UINT exp_vertex_size13 = sizeof(*exp_vertices13);
8900 /* Test 14. Convert FLOAT2 to SHORT2N. */
8901 const struct vertex_ptc vertices14[] =
8903 {{ 0.0f, 3.0f, 0.f}, {1.0f, 2.0f}},
8904 {{ 2.0f, 3.0f, 0.f}, {0.4f, 0.5f}},
8905 {{ 0.0f, 0.0f, 0.f}, {0.6f, -1.0f}},
8907 {{ 3.0f, 3.0f, 0.f}, {-0.4f, -0.5f}},
8908 {{ 3.0f, 0.0f, 0.f}, {-0.9f, -0.99997}},
8909 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX, SHRT_MIN}},
8911 const UINT num_vertices14 = ARRAY_SIZE(vertices14);
8912 const UINT num_faces14 = ARRAY_SIZE(vertices14) / VERTS_PER_FACE;
8913 const UINT vertex_size14 = sizeof(*vertices14);
8914 const struct vertex_ptc_short2 exp_vertices14[] =
8916 {{ 0.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MAX}},
8917 {{ 2.0f, 3.0f, 0.f}, {13107, 16384}},
8918 {{ 0.0f, 0.0f, 0.f}, {19660, SHRT_MIN + 2}},
8920 {{ 3.0f, 3.0f, 0.f}, {-13106, -16383}},
8921 {{ 3.0f, 0.0f, 0.f}, {-29489, SHRT_MIN + 3}},
8922 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX, SHRT_MIN + 2}},
8924 const UINT exp_vertex_size14 = sizeof(*exp_vertices14);
8925 /* Test 15. Convert FLOAT2 to SHORT4N. */
8926 const struct vertex_ptc vertices15[] =
8928 {{ 0.0f, 3.0f, 0.f}, {1.0f, 2.0f}},
8929 {{ 2.0f, 3.0f, 0.f}, {0.4f, 0.5f}},
8930 {{ 0.0f, 0.0f, 0.f}, {0.6f, -1.0f}},
8932 {{ 3.0f, 3.0f, 0.f}, {-0.4f, -0.5f}},
8933 {{ 3.0f, 0.0f, 0.f}, {-0.9f, -0.99997}},
8934 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX, SHRT_MIN}},
8936 const UINT num_vertices15 = ARRAY_SIZE(vertices15);
8937 const UINT num_faces15 = ARRAY_SIZE(vertices15) / VERTS_PER_FACE;
8938 const UINT vertex_size15 = sizeof(*vertices15);
8939 const struct vertex_ptc_short4 exp_vertices15[] =
8941 {{ 0.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MAX, 0, SHRT_MAX}},
8942 {{ 2.0f, 3.0f, 0.f}, {13107, 16384, 0, SHRT_MAX}},
8943 {{ 0.0f, 0.0f, 0.f}, {19660, SHRT_MIN + 2, 0, SHRT_MAX}},
8945 {{ 3.0f, 3.0f, 0.f}, {-13106, -16383, 0, SHRT_MAX}},
8946 {{ 3.0f, 0.0f, 0.f}, {-29489, SHRT_MIN + 3, 0, SHRT_MAX}},
8947 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX, SHRT_MIN + 2, 0, SHRT_MAX}},
8949 const UINT exp_vertex_size15 = sizeof(*exp_vertices15);
8950 /* Test 16. Convert FLOAT2 to USHORT2N. */
8951 const struct vertex_ptc vertices16[] =
8953 {{ 0.0f, 3.0f, 0.f}, {1.0f, 2.0f}},
8954 {{ 2.0f, 3.0f, 0.f}, {0.4f, 0.5f}},
8955 {{ 0.0f, 0.0f, 0.f}, {0.6f, -1.0f}},
8957 {{ 3.0f, 3.0f, 0.f}, {-0.4f, -0.5f}},
8958 {{ 3.0f, 0.0f, 0.f}, {-0.9f, 0.99998f}},
8959 {{ 1.0f, 0.0f, 0.f}, {USHRT_MAX, 0.0f}},
8961 const UINT num_vertices16 = ARRAY_SIZE(vertices16);
8962 const UINT num_faces16 = ARRAY_SIZE(vertices16) / VERTS_PER_FACE;
8963 const UINT vertex_size16 = sizeof(*vertices16);
8964 const struct vertex_ptc_ushort2n exp_vertices16[] =
8966 {{ 0.0f, 3.0f, 0.f}, {USHRT_MAX, USHRT_MAX}},
8967 {{ 2.0f, 3.0f, 0.f}, {26214, 32768}},
8968 {{ 0.0f, 0.0f, 0.f}, {39321, 0}},
8970 {{ 3.0f, 3.0f, 0.f}, {0, 0}},
8971 {{ 3.0f, 0.0f, 0.f}, {0, USHRT_MAX - 1}},
8972 {{ 1.0f, 0.0f, 0.f}, {USHRT_MAX, 0}},
8974 const UINT exp_vertex_size16 = sizeof(*exp_vertices16);
8975 /* Test 17. Convert FLOAT2 to USHORT4N. */
8976 const struct vertex_ptc vertices17[] =
8978 {{ 0.0f, 3.0f, 0.f}, {1.0f, 2.0f}},
8979 {{ 2.0f, 3.0f, 0.f}, {0.4f, 0.5f}},
8980 {{ 0.0f, 0.0f, 0.f}, {0.6f, -1.0f}},
8982 {{ 3.0f, 3.0f, 0.f}, {-0.4f, -0.5f}},
8983 {{ 3.0f, 0.0f, 0.f}, {-0.9f, 0.99998f}},
8984 {{ 1.0f, 0.0f, 0.f}, {USHRT_MAX, 0.0f}},
8986 const UINT num_vertices17 = ARRAY_SIZE(vertices17);
8987 const UINT num_faces17 = ARRAY_SIZE(vertices17) / VERTS_PER_FACE;
8988 const UINT vertex_size17 = sizeof(*vertices17);
8989 const struct vertex_ptc_ushort4n exp_vertices17[] =
8991 {{ 0.0f, 3.0f, 0.f}, {USHRT_MAX, USHRT_MAX, 0, USHRT_MAX}},
8992 {{ 2.0f, 3.0f, 0.f}, {26214, 32768, 0, USHRT_MAX}},
8993 {{ 0.0f, 0.0f, 0.f}, {39321, 0, 0, USHRT_MAX}},
8995 {{ 3.0f, 3.0f, 0.f}, {0, 0, 0, USHRT_MAX}},
8996 {{ 3.0f, 0.0f, 0.f}, {0, USHRT_MAX - 1, 0, USHRT_MAX}},
8997 {{ 1.0f, 0.0f, 0.f}, {USHRT_MAX, 0, 0, USHRT_MAX}},
8999 const UINT exp_vertex_size17 = sizeof(*exp_vertices17);
9000 /* Test 18. Test that the method field is compared by converting a FLOAT2 to
9001 * FLOAT16_2. where the method field has been change from
9002 * D3DDECLMETHOD_DEFAULT to D3DDECLMETHOD_PARTIALU. */
9003 const struct vertex_ptc vertices18[] =
9005 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
9006 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
9007 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
9009 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
9010 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
9011 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
9013 const UINT num_vertices18 = ARRAY_SIZE(vertices18);
9014 const UINT num_faces18 = ARRAY_SIZE(vertices18) / VERTS_PER_FACE;
9015 const UINT vertex_size18 = sizeof(*vertices18);
9016 const struct vertex_ptc_float16_2 exp_vertices18[] =
9018 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
9019 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */
9020 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */
9022 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd}}, /* {0.2f, 0.3f} */
9023 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
9024 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */
9026 const UINT exp_vertex_size18 = sizeof(*exp_vertices18);
9027 /* Test 19. Test that data is lost if usage index changes, e.g. TEXCOORD0
9028 * TEXCOORD1. */
9029 const struct vertex_pntc vertices19[] =
9031 {{ 0.0f, 3.0f, 0.f}, up, { 1.0f, 1.0f}},
9032 {{ 2.0f, 3.0f, 0.f}, up, { 0.5f, 0.7f}},
9033 {{ 0.0f, 0.0f, 0.f}, up, {-0.2f, -0.3f}},
9035 {{ 3.0f, 3.0f, 0.f}, up, { 0.2f, 0.3f}},
9036 {{ 3.0f, 0.0f, 0.f}, up, { 1.0f, 1.0f}},
9037 {{ 1.0f, 0.0f, 0.f}, up, { 0.1f, 0.2f}},
9039 const UINT num_vertices19 = ARRAY_SIZE(vertices19);
9040 const UINT num_faces19 = ARRAY_SIZE(vertices19) / VERTS_PER_FACE;
9041 const UINT vertex_size19 = sizeof(*vertices19);
9042 const struct vertex_pntc exp_vertices19[] =
9044 {{ 0.0f, 3.0f, 0.f}, up, zero_vec2},
9045 {{ 2.0f, 3.0f, 0.f}, up, zero_vec2},
9046 {{ 0.0f, 0.0f, 0.f}, up, zero_vec2},
9048 {{ 3.0f, 3.0f, 0.f}, up, zero_vec2},
9049 {{ 3.0f, 0.0f, 0.f}, up, zero_vec2},
9050 {{ 1.0f, 0.0f, 0.f}, up, zero_vec2},
9052 const UINT exp_vertex_size19 = sizeof(*exp_vertices19);
9053 /* Test 20. Another test that data is lost if usage index changes, e.g.
9054 * TEXCOORD1 to TEXCOORD0. */
9055 const struct vertex_pntc vertices20[] =
9057 {{ 0.0f, 3.0f, 0.f}, up, { 1.0f, 1.0f}},
9058 {{ 2.0f, 3.0f, 0.f}, up, { 0.5f, 0.7f}},
9059 {{ 0.0f, 0.0f, 0.f}, up, {-0.2f, -0.3f}},
9061 {{ 3.0f, 3.0f, 0.f}, up, { 0.2f, 0.3f}},
9062 {{ 3.0f, 0.0f, 0.f}, up, { 1.0f, 1.0f}},
9063 {{ 1.0f, 0.0f, 0.f}, up, { 0.1f, 0.2f}},
9065 const UINT num_vertices20 = ARRAY_SIZE(vertices20);
9066 const UINT num_faces20 = ARRAY_SIZE(vertices20) / VERTS_PER_FACE;
9067 const UINT vertex_size20 = sizeof(*vertices20);
9068 const struct vertex_pntc exp_vertices20[] =
9070 {{ 0.0f, 3.0f, 0.f}, up, zero_vec2},
9071 {{ 2.0f, 3.0f, 0.f}, up, zero_vec2},
9072 {{ 0.0f, 0.0f, 0.f}, up, zero_vec2},
9074 {{ 3.0f, 3.0f, 0.f}, up, zero_vec2},
9075 {{ 3.0f, 0.0f, 0.f}, up, zero_vec2},
9076 {{ 1.0f, 0.0f, 0.f}, up, zero_vec2},
9078 const UINT exp_vertex_size20 = sizeof(*exp_vertices20);
9079 /* Test 21. Convert FLOAT1 to FLOAT2. */
9080 const struct vertex_ptc_float1 vertices21[] =
9082 {{ 0.0f, 3.0f, 0.f}, 1.0f},
9083 {{ 2.0f, 3.0f, 0.f}, 0.5f},
9084 {{ 0.0f, 0.0f, 0.f}, -0.2f},
9086 {{ 3.0f, 3.0f, 0.f}, 0.2f},
9087 {{ 3.0f, 0.0f, 0.f}, 1.0f},
9088 {{ 1.0f, 0.0f, 0.f}, 0.1f},
9090 const UINT num_vertices21 = ARRAY_SIZE(vertices21);
9091 const UINT num_faces21 = ARRAY_SIZE(vertices21) / VERTS_PER_FACE;
9092 const UINT vertex_size21 = sizeof(*vertices21);
9093 const struct vertex_ptc exp_vertices21[] =
9095 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 0.0f}},
9096 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.0f}},
9097 {{ 0.0f, 0.0f, 0.f}, {-0.2f, 0.0f}},
9099 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.0f}},
9100 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 0.0f}},
9101 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.0f}},
9103 const UINT exp_vertex_size21 = sizeof(*exp_vertices21);
9104 /* Test 22. Convert FLOAT1 to FLOAT3. */
9105 const struct vertex_ptc_float1 vertices22[] =
9107 {{ 0.0f, 3.0f, 0.f}, 1.0f},
9108 {{ 2.0f, 3.0f, 0.f}, 0.5f},
9109 {{ 0.0f, 0.0f, 0.f}, -0.2f},
9111 {{ 3.0f, 3.0f, 0.f}, 0.2f},
9112 {{ 3.0f, 0.0f, 0.f}, 1.0f},
9113 {{ 1.0f, 0.0f, 0.f}, 0.1f},
9115 const UINT num_vertices22 = ARRAY_SIZE(vertices22);
9116 const UINT num_faces22 = ARRAY_SIZE(vertices22) / VERTS_PER_FACE;
9117 const UINT vertex_size22 = sizeof(*vertices22);
9118 const struct vertex_ptc_float3 exp_vertices22[] =
9120 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 0.0f, 0.0f}},
9121 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.0f, 0.0f}},
9122 {{ 0.0f, 0.0f, 0.f}, {-0.2f, 0.0f, 0.0f}},
9124 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.0f, 0.0f}},
9125 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 0.0f, 0.0f}},
9126 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.0f, 0.0f}},
9128 const UINT exp_vertex_size22 = sizeof(*exp_vertices22);
9129 /* Test 23. Convert FLOAT1 to FLOAT4. */
9130 const struct vertex_ptc_float1 vertices23[] =
9132 {{ 0.0f, 3.0f, 0.f}, 1.0f},
9133 {{ 2.0f, 3.0f, 0.f}, 0.5f},
9134 {{ 0.0f, 0.0f, 0.f}, -0.2f},
9136 {{ 3.0f, 3.0f, 0.f}, 0.2f},
9137 {{ 3.0f, 0.0f, 0.f}, 1.0f},
9138 {{ 1.0f, 0.0f, 0.f}, 0.1f},
9140 const UINT num_vertices23 = ARRAY_SIZE(vertices23);
9141 const UINT num_faces23 = ARRAY_SIZE(vertices23) / VERTS_PER_FACE;
9142 const UINT vertex_size23 = sizeof(*vertices23);
9143 const struct vertex_ptc_float4 exp_vertices23[] =
9145 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 0.0f, 0.0f, 1.0f}},
9146 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.0f, 0.0f, 1.0f}},
9147 {{ 0.0f, 0.0f, 0.f}, {-0.2f, 0.0f, 0.0f, 1.0f}},
9149 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.0f, 0.0f, 1.0f}},
9150 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 0.0f, 0.0f, 1.0f}},
9151 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.0f, 0.0f, 1.0f}},
9153 const UINT exp_vertex_size23 = sizeof(*exp_vertices23);
9154 /* Test 24. Convert FLOAT1 to D3DCOLOR. */
9155 const struct vertex_ptc_float1 vertices24[] =
9157 {{ 0.0f, 3.0f, 0.f}, 1.0f},
9158 {{ 2.0f, 3.0f, 0.f}, 0.5f},
9159 {{ 0.0f, 0.0f, 0.f}, -0.2f},
9161 {{ 3.0f, 3.0f, 0.f}, 0.2f},
9162 {{ 3.0f, 0.0f, 0.f}, 1.0f},
9163 {{ 1.0f, 0.0f, 0.f}, 0.11f},
9165 const UINT num_vertices24 = ARRAY_SIZE(vertices24);
9166 const UINT num_faces24 = ARRAY_SIZE(vertices24) / VERTS_PER_FACE;
9167 const UINT vertex_size24 = sizeof(*vertices24);
9168 const struct vertex_ptc_d3dcolor exp_vertices24[] =
9170 {{ 0.0f, 3.0f, 0.f}, {0, 0, 255, 255}},
9171 {{ 2.0f, 3.0f, 0.f}, {0, 0, 128, 255}},
9172 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 255}},
9174 {{ 3.0f, 3.0f, 0.f}, {0, 0, 51, 255}},
9175 {{ 3.0f, 0.0f, 0.f}, {0, 0, 255, 255}},
9176 {{ 1.0f, 0.0f, 0.f}, {0, 0, 28, 255}},
9178 const UINT exp_vertex_size24 = sizeof(*exp_vertices24);
9179 /* Test 25. Convert FLOAT1 to ubyte4. */
9180 const struct vertex_ptc_float1 vertices25[] =
9182 {{ 0.0f, 3.0f, 0.f}, 0.0f},
9183 {{ 2.0f, 3.0f, 0.f}, 1.4f},
9184 {{ 0.0f, 0.0f, 0.f}, 1.5f},
9186 {{ 3.0f, 3.0f, 0.f}, 255.0f},
9187 {{ 3.0f, 0.0f, 0.f}, 256.0f},
9188 {{ 1.0f, 0.0f, 0.f}, -1.0f},
9190 const UINT num_vertices25 = ARRAY_SIZE(vertices25);
9191 const UINT num_faces25 = ARRAY_SIZE(vertices25) / VERTS_PER_FACE;
9192 const UINT vertex_size25 = sizeof(*vertices25);
9193 const struct vertex_ptc_ubyte4 exp_vertices25[] =
9195 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 1}},
9196 {{ 2.0f, 3.0f, 0.f}, {1, 0, 0, 1}},
9197 {{ 0.0f, 0.0f, 0.f}, {2, 0, 0, 1}},
9199 {{ 3.0f, 3.0f, 0.f}, {255, 0, 0, 1}},
9200 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 1}},
9201 {{ 1.0f, 0.0f, 0.f}, {0, 0, 0, 1}},
9203 const UINT exp_vertex_size25 = sizeof(*exp_vertices25);
9204 /* Test 26. Convert FLOAT4 to D3DCOLOR. */
9205 const struct vertex_ptc_float4 vertices26[] =
9207 {{ 0.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.4f, 0.5f}},
9208 {{ 2.0f, 3.0f, 0.f}, {-0.4f, -0.5f, -1.0f, -2.0f}},
9209 {{ 0.0f, 0.0f, 0.f}, {254.0f, 255.0f, 256.0f, 257.0f}},
9211 {{ 3.0f, 3.0f, 0.f}, {0.1f, 0.2f, 0.3f, 0.4f}},
9212 {{ 3.0f, 0.0f, 0.f}, {0.5f, 0.6f, 0.7f, 0.8f}},
9213 {{ 1.0f, 0.0f, 0.f}, {0.9f, 0.99f, 0.995f, 0.999f}},
9215 const UINT num_vertices26 = ARRAY_SIZE(vertices26);
9216 const UINT num_faces26 = ARRAY_SIZE(vertices26) / VERTS_PER_FACE;
9217 const UINT vertex_size26 = sizeof(*vertices26);
9218 const struct vertex_ptc_d3dcolor exp_vertices26[] =
9220 {{ 0.0f, 3.0f, 0.f}, {102, 255, 0, 128}},
9221 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9222 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
9224 {{ 3.0f, 3.0f, 0.f}, {77, 51, 26, 102}},
9225 {{ 3.0f, 0.0f, 0.f}, {179, 153, 128, 204}},
9226 {{ 1.0f, 0.0f, 0.f}, {254, 252, 230, 255}},
9228 const UINT exp_vertex_size26 = sizeof(*exp_vertices26);
9229 /* Test 27. Convert D3DCOLOR to FLOAT4. */
9230 const struct vertex_ptc_d3dcolor vertices27[] =
9232 {{ 0.0f, 3.0f, 0.f}, {102, 255, 0, 128}},
9233 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9234 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
9236 {{ 3.0f, 3.0f, 0.f}, {77, 51, 26, 102}},
9237 {{ 3.0f, 0.0f, 0.f}, {179, 153, 128, 204}},
9238 {{ 1.0f, 0.0f, 0.f}, {254, 252, 230, 255}},
9240 const UINT num_vertices27 = ARRAY_SIZE(vertices27);
9241 const UINT num_faces27 = ARRAY_SIZE(vertices27) / VERTS_PER_FACE;
9242 const UINT vertex_size27 = sizeof(*vertices27);
9243 const struct vertex_ptc_float4 exp_vertices27[] =
9245 {{ 0.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.4f, 0.501961f}},
9246 {{ 2.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9247 {{ 0.0f, 0.0f, 0.f}, {1.0f, 1.0f, 1.0f, 1.0f}},
9249 {{ 3.0f, 3.0f, 0.f}, {0.101961f, 0.2f, 0.301961f, 0.4f}},
9250 {{ 3.0f, 0.0f, 0.f}, {0.501961f, 0.6f, 0.701961f, 0.8f}},
9251 {{ 1.0f, 0.0f, 0.f}, {0.901961f, 0.988235f, 0.996078f, 1.0f}},
9253 const UINT exp_vertex_size27 = sizeof(*exp_vertices27);
9254 /* Test 28. Convert UBYTE4 to FLOAT4. */
9255 const struct vertex_ptc_ubyte4 vertices28[] =
9257 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9258 {{ 2.0f, 3.0f, 0.f}, {1, 1, 1, 1}},
9259 {{ 0.0f, 0.0f, 0.f}, {1, 0, 1, 0}},
9261 {{ 3.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
9262 {{ 3.0f, 0.0f, 0.f}, {10, 20, 30, 40}},
9263 {{ 1.0f, 0.0f, 0.f}, {50, 60, 127, 255}},
9265 const UINT num_vertices28 = ARRAY_SIZE(vertices28);
9266 const UINT num_faces28 = ARRAY_SIZE(vertices28) / VERTS_PER_FACE;
9267 const UINT vertex_size28 = sizeof(*vertices28);
9268 const struct vertex_ptc_float4 exp_vertices28[] =
9270 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9271 {{ 2.0f, 3.0f, 0.f}, {1.0f, 1.0f, 1.0f, 1.0f}},
9272 {{ 0.0f, 0.0f, 0.f}, {1.0f, 0.0f, 1.0f, 0.0f}},
9274 {{ 3.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.0f, 1.0f}},
9275 {{ 3.0f, 0.0f, 0.f}, {10.0f, 20.0f, 30.0f, 40.0f}},
9276 {{ 1.0f, 0.0f, 0.f}, {50.0f, 60.0f, 127.0f, 255.0f}},
9278 const UINT exp_vertex_size28 = sizeof(*exp_vertices28);
9279 /* Test 29. Convert SHORT2 to FLOAT4. */
9280 const struct vertex_ptc_short2 vertices29[] =
9282 {{ 0.0f, 3.0f, 0.f}, {0, 0}},
9283 {{ 2.0f, 3.0f, 0.f}, {0, 1}},
9284 {{ 0.0f, 0.0f, 0.f}, {1, 0}},
9286 {{ 3.0f, 3.0f, 0.f}, {1, 1}},
9287 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MAX}},
9288 {{ 1.0f, 0.0f, 0.f}, {-42, 42}},
9290 const UINT num_vertices29 = ARRAY_SIZE(vertices29);
9291 const UINT num_faces29 = ARRAY_SIZE(vertices29) / VERTS_PER_FACE;
9292 const UINT vertex_size29 = sizeof(*vertices29);
9293 const struct vertex_ptc_float4 exp_vertices29[] =
9295 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 1.0f}},
9296 {{ 2.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.0f, 1.0f }},
9297 {{ 0.0f, 0.0f, 0.f}, {1.0f, 0.0f, 0.0f, 1.0f}},
9299 {{ 3.0f, 3.0f, 0.f}, {1.0f, 1.0f, 0.0f, 1.0f}},
9300 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MAX, 0.0f, 1.0f}},
9301 {{ 1.0f, 0.0f, 0.f}, {-42.0f, 42.0f, 0.0f, 1.0f}},
9303 const UINT exp_vertex_size29 = sizeof(*exp_vertices29);
9304 /* Test 29. Convert SHORT4 to FLOAT4. */
9305 const struct vertex_ptc_short4 vertices30[] =
9307 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9308 {{ 2.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
9309 {{ 0.0f, 0.0f, 0.f}, {1, 0, 1, 0}},
9311 {{ 3.0f, 3.0f, 0.f}, {1, 1, 1, 1}},
9312 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MAX, 1, 0}},
9313 {{ 1.0f, 0.0f, 0.f}, {-42, 42, SHRT_MAX, SHRT_MIN}},
9315 const UINT num_vertices30 = ARRAY_SIZE(vertices30);
9316 const UINT num_faces30 = ARRAY_SIZE(vertices30) / VERTS_PER_FACE;
9317 const UINT vertex_size30 = sizeof(*vertices30);
9318 const struct vertex_ptc_float4 exp_vertices30[] =
9320 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9321 {{ 2.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.0f, 1.0f }},
9322 {{ 0.0f, 0.0f, 0.f}, {1.0f, 0.0f, 1.0f, 0.0f}},
9324 {{ 3.0f, 3.0f, 0.f}, {1.0f, 1.0f, 1.0f, 1.0f}},
9325 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MAX, 1.0f, 0.0f}},
9326 {{ 1.0f, 0.0f, 0.f}, {-42.0f, 42.0f, SHRT_MAX, SHRT_MIN}},
9328 const UINT exp_vertex_size30 = sizeof(*exp_vertices30);
9329 /* Test 31. Convert UBYTE4N to FLOAT4. */
9330 const struct vertex_ptc_ubyte4n vertices31[] =
9332 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9333 {{ 2.0f, 3.0f, 0.f}, {1, 1, 1, 1}},
9334 {{ 0.0f, 0.0f, 0.f}, {1, 0, 1, 0}},
9336 {{ 3.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
9337 {{ 3.0f, 0.0f, 0.f}, {10, 20, 30, 40}},
9338 {{ 1.0f, 0.0f, 0.f}, {50, 60, 70, UCHAR_MAX}},
9340 const UINT num_vertices31 = ARRAY_SIZE(vertices31);
9341 const UINT num_faces31 = ARRAY_SIZE(vertices31) / VERTS_PER_FACE;
9342 const UINT vertex_size31 = sizeof(*vertices31);
9343 const struct vertex_ptc_float4 exp_vertices31[] =
9345 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9346 {{ 2.0f, 3.0f, 0.f}, {(FLOAT)1/UCHAR_MAX, (FLOAT)1/UCHAR_MAX, (FLOAT)1/UCHAR_MAX, (FLOAT)1/UCHAR_MAX}},
9347 {{ 0.0f, 0.0f, 0.f}, {(FLOAT)1/UCHAR_MAX, 0.0f, (FLOAT)1/UCHAR_MAX, 0.0f}},
9349 {{ 3.0f, 3.0f, 0.f}, {0.0f, (FLOAT)1/UCHAR_MAX, 0.0f, (FLOAT)1/UCHAR_MAX}},
9350 {{ 3.0f, 0.0f, 0.f}, {(FLOAT)10/UCHAR_MAX, (FLOAT)20/UCHAR_MAX, (FLOAT)30/UCHAR_MAX, (FLOAT)40/UCHAR_MAX}},
9351 {{ 1.0f, 0.0f, 0.f}, {(FLOAT)50/UCHAR_MAX, (FLOAT)60/UCHAR_MAX, (FLOAT)70/UCHAR_MAX, 1.0f}},
9353 const UINT exp_vertex_size31 = sizeof(*exp_vertices31);
9354 /* Test 32. Convert SHORT2N to FLOAT4. */
9355 const struct vertex_ptc_short2 vertices32[] =
9357 {{ 0.0f, 3.0f, 0.f}, {0, 0}},
9358 {{ 2.0f, 3.0f, 0.f}, {0, 1}},
9359 {{ 0.0f, 0.0f, 0.f}, {1, 0}},
9361 {{ 3.0f, 3.0f, 0.f}, {1, 1}},
9362 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN + 1, SHRT_MAX}},
9363 {{ 1.0f, 0.0f, 0.f}, {-42, 42}},
9365 const UINT num_vertices32 = ARRAY_SIZE(vertices32);
9366 const UINT num_faces32 = ARRAY_SIZE(vertices32) / VERTS_PER_FACE;
9367 const UINT vertex_size32 = sizeof(*vertices32);
9368 const struct vertex_ptc_float4 exp_vertices32[] =
9370 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 1.0f}},
9371 {{ 2.0f, 3.0f, 0.f}, {0.0f, 1.0f/SHRT_MAX, 0.0f, 1.0f}},
9372 {{ 0.0f, 0.0f, 0.f}, {1.0f/SHRT_MAX, 0.0f, 0.0f, 1.0f}},
9374 {{ 3.0f, 3.0f, 0.f}, {1.0f/SHRT_MAX, 1.0f/SHRT_MAX, 0.0f, 1.0f}},
9375 {{ 3.0f, 0.0f, 0.f}, {-1.0f, 1.0f, 0.0f, 1.0f}},
9376 {{ 1.0f, 0.0f, 0.f}, {-42.0f/SHRT_MAX, 42.0f/SHRT_MAX, 0.0f, 1.0f}},
9378 const UINT exp_vertex_size32 = sizeof(*exp_vertices32);
9379 /* Test 33. Convert SHORT4N to FLOAT4. */
9380 const struct vertex_ptc_short4 vertices33[] =
9382 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9383 {{ 2.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
9384 {{ 0.0f, 0.0f, 0.f}, {1, 0, 1, 0}},
9386 {{ 3.0f, 3.0f, 0.f}, {1, 1, 1, 1}},
9387 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN + 1, SHRT_MAX, SHRT_MIN + 1, SHRT_MAX}},
9388 {{ 1.0f, 0.0f, 0.f}, {-42, 42, 1, 1}},
9390 const UINT num_vertices33 = ARRAY_SIZE(vertices33);
9391 const UINT num_faces33 = ARRAY_SIZE(vertices33) / VERTS_PER_FACE;
9392 const UINT vertex_size33 = sizeof(*vertices33);
9393 const struct vertex_ptc_float4 exp_vertices33[] =
9395 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9396 {{ 2.0f, 3.0f, 0.f}, {0.0f, 1.0f/SHRT_MAX, 0.0f, 1.0f/SHRT_MAX}},
9397 {{ 0.0f, 0.0f, 0.f}, {1.0f/SHRT_MAX, 0.0f, 1.0f/SHRT_MAX, 0.0f}},
9399 {{ 3.0f, 3.0f, 0.f}, {1.0f/SHRT_MAX, 1.0f/SHRT_MAX, 1.0f/SHRT_MAX, 1.0f/SHRT_MAX}},
9400 {{ 3.0f, 0.0f, 0.f}, {-1.0f, 1.0f, -1.0f, 1.0f}},
9401 {{ 1.0f, 0.0f, 0.f}, {-42.0f/SHRT_MAX, 42.0f/SHRT_MAX, 1.0f/SHRT_MAX, 1.0f/SHRT_MAX}},
9403 const UINT exp_vertex_size33 = sizeof(*exp_vertices33);
9404 /* Test 34. Convert FLOAT16_2 to FLOAT4. */
9405 const struct vertex_ptc_float16_2 vertices34[] =
9407 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
9408 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */
9409 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */
9411 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd}}, /* {0.2f, 0.3f} */
9412 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
9413 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */
9415 const UINT num_vertices34 = ARRAY_SIZE(vertices34);
9416 const UINT num_faces34 = ARRAY_SIZE(vertices34) / VERTS_PER_FACE;
9417 const UINT vertex_size34 = sizeof(*vertices34);
9418 const struct vertex_ptc_float4 exp_vertices34[] =
9420 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f, 0.0f, 1.0f}},
9421 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.700195f, 0.0f, 1.0f}},
9422 {{ 0.0f, 0.0f, 0.f}, {-0.199951f, -0.300049f, 0.0f, 1.0f}},
9424 {{ 3.0f, 3.0f, 0.f}, {0.199951f, 0.300049f, 0.0f, 1.0f}},
9425 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f, 0.0f, 1.0f}},
9426 {{ 1.0f, 0.0f, 0.f}, {0.099976f, 0.199951f, 0.0f, 1.0f}},
9428 const UINT exp_vertex_size34 = sizeof(*exp_vertices34);
9429 /* Test 35. Convert FLOAT16_4 to FLOAT4. */
9430 const struct vertex_ptc_float16_4 vertices35[] =
9432 {{ 0.0f, 3.0f, 0.f}, {0x0000, 0x0000, 0x0000, 0x0000}},
9433 {{ 2.0f, 3.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}},
9434 {{ 0.0f, 0.0f, 0.f}, {0x3c00, 0x0000, 0x3c00, 0x0000}},
9436 {{ 3.0f, 3.0f, 0.f}, {0x0000, 0x3c00, 0x0000, 0x3c00}},
9437 {{ 3.0f, 0.0f, 0.f}, {0x3800, 0x399a, 0xb266, 0xb4cd}},
9438 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266, 0x2e66, 0x3266}},
9440 const UINT num_vertices35 = ARRAY_SIZE(vertices35);
9441 const UINT num_faces35 = ARRAY_SIZE(vertices35) / VERTS_PER_FACE;
9442 const UINT vertex_size35 = sizeof(*vertices35);
9443 const struct vertex_ptc_float4 exp_vertices35[] =
9445 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9446 {{ 2.0f, 3.0f, 0.f}, {1.0f, 1.0f, 1.0f, 1.0f}},
9447 {{ 0.0f, 0.0f, 0.f}, {1.0f, 0.0f, 1.0f, 0.0f}},
9449 {{ 3.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.0f, 1.0f}},
9450 {{ 3.0f, 0.0f, 0.f}, {0.5f, 0.700195f, -0.199951f, -0.300049f}},
9451 {{ 1.0f, 0.0f, 0.f}, {0.099976f, 0.199951f, 0.099976f, 0.199951f}},
9453 const UINT exp_vertex_size35 = sizeof(*exp_vertices35);
9454 /* Test 36. Check that vertex buffer sharing is ok. */
9455 const struct vertex_pn vertices36[] =
9457 {{ 0.0f, 3.0f, 0.f}, up},
9458 {{ 2.0f, 3.0f, 0.f}, up},
9459 {{ 0.0f, 0.0f, 0.f}, up},
9461 const UINT num_vertices36 = ARRAY_SIZE(vertices36);
9462 const UINT num_faces36 = ARRAY_SIZE(vertices36) / VERTS_PER_FACE;
9463 const UINT vertex_size36 = sizeof(*vertices36);
9464 const DWORD clone_options36 = options | D3DXMESH_VB_SHARE;
9465 /* Common mesh data */
9466 ID3DXMesh *mesh = NULL;
9467 ID3DXMesh *mesh_clone = NULL;
9468 struct
9470 const BYTE *vertices;
9471 const DWORD *indices;
9472 const DWORD *attributes;
9473 const UINT num_vertices;
9474 const UINT num_faces;
9475 const UINT vertex_size;
9476 const DWORD create_options;
9477 const DWORD clone_options;
9478 D3DVERTEXELEMENT9 *declaration;
9479 D3DVERTEXELEMENT9 *new_declaration;
9480 const BYTE *exp_vertices;
9481 const UINT exp_vertex_size;
9483 tc[] =
9486 (BYTE*)vertices0,
9487 NULL,
9488 NULL,
9489 num_vertices0,
9490 num_faces0,
9491 vertex_size0,
9492 options,
9493 options,
9494 declaration_pn,
9495 declaration_pn,
9496 (BYTE*)vertices0,
9497 vertex_size0
9500 (BYTE*)vertices0,
9501 NULL,
9502 NULL,
9503 num_vertices0,
9504 num_faces0,
9505 vertex_size0,
9506 options_16bit,
9507 options_16bit,
9508 declaration_pn,
9509 declaration_pn,
9510 (BYTE*)vertices0,
9511 vertex_size0
9514 (BYTE*)vertices0,
9515 NULL,
9516 NULL,
9517 num_vertices0,
9518 num_faces0,
9519 vertex_size0,
9520 options,
9521 options,
9522 declaration_pn,
9523 declaration_pntc,
9524 (BYTE*)exp_vertices2,
9525 exp_vertex_size2
9528 (BYTE*)vertices0,
9529 NULL,
9530 NULL,
9531 num_vertices0,
9532 num_faces0,
9533 vertex_size0,
9534 options,
9535 options,
9536 declaration_pn,
9537 declaration_ptcn,
9538 (BYTE*)exp_vertices3,
9539 exp_vertex_size3
9542 (BYTE*)vertices4,
9543 NULL,
9544 NULL,
9545 num_vertices4,
9546 num_faces4,
9547 vertex_size4,
9548 options,
9549 options,
9550 declaration_ptc,
9551 declaration_ptc_float16_2,
9552 (BYTE*)exp_vertices4,
9553 exp_vertex_size4
9556 (BYTE*)vertices5,
9557 NULL,
9558 NULL,
9559 num_vertices5,
9560 num_faces5,
9561 vertex_size5,
9562 options,
9563 options,
9564 declaration_ptc,
9565 declaration_ptc_float16_4,
9566 (BYTE*)exp_vertices5,
9567 exp_vertex_size5
9570 (BYTE*)vertices6,
9571 NULL,
9572 NULL,
9573 num_vertices6,
9574 num_faces6,
9575 vertex_size6,
9576 options,
9577 options,
9578 declaration_ptc,
9579 declaration_ptc_float1,
9580 (BYTE*)exp_vertices6,
9581 exp_vertex_size6
9584 (BYTE*)vertices7,
9585 NULL,
9586 NULL,
9587 num_vertices7,
9588 num_faces7,
9589 vertex_size7,
9590 options,
9591 options,
9592 declaration_ptc,
9593 declaration_ptc_float3,
9594 (BYTE*)exp_vertices7,
9595 exp_vertex_size7
9598 (BYTE*)vertices8,
9599 NULL,
9600 NULL,
9601 num_vertices8,
9602 num_faces8,
9603 vertex_size8,
9604 options,
9605 options,
9606 declaration_ptc,
9607 declaration_ptc_float4,
9608 (BYTE*)exp_vertices8,
9609 exp_vertex_size8
9612 (BYTE*)vertices9,
9613 NULL,
9614 NULL,
9615 num_vertices9,
9616 num_faces9,
9617 vertex_size9,
9618 options,
9619 options,
9620 declaration_ptc,
9621 declaration_ptc_d3dcolor,
9622 (BYTE*)exp_vertices9,
9623 exp_vertex_size9
9626 (BYTE*)vertices10,
9627 NULL,
9628 NULL,
9629 num_vertices10,
9630 num_faces10,
9631 vertex_size10,
9632 options,
9633 options,
9634 declaration_ptc,
9635 declaration_ptc_ubyte4,
9636 (BYTE*)exp_vertices10,
9637 exp_vertex_size10
9640 (BYTE*)vertices11,
9641 NULL,
9642 NULL,
9643 num_vertices11,
9644 num_faces11,
9645 vertex_size11,
9646 options,
9647 options,
9648 declaration_ptc,
9649 declaration_ptc_short2,
9650 (BYTE*)exp_vertices11,
9651 exp_vertex_size11
9654 (BYTE*)vertices12,
9655 NULL,
9656 NULL,
9657 num_vertices12,
9658 num_faces12,
9659 vertex_size12,
9660 options,
9661 options,
9662 declaration_ptc,
9663 declaration_ptc_short4,
9664 (BYTE*)exp_vertices12,
9665 exp_vertex_size12
9668 (BYTE*)vertices13,
9669 NULL,
9670 NULL,
9671 num_vertices13,
9672 num_faces13,
9673 vertex_size13,
9674 options,
9675 options,
9676 declaration_ptc,
9677 declaration_ptc_ubyte4n,
9678 (BYTE*)exp_vertices13,
9679 exp_vertex_size13
9682 (BYTE*)vertices14,
9683 NULL,
9684 NULL,
9685 num_vertices14,
9686 num_faces14,
9687 vertex_size14,
9688 options,
9689 options,
9690 declaration_ptc,
9691 declaration_ptc_short2n,
9692 (BYTE*)exp_vertices14,
9693 exp_vertex_size14
9696 (BYTE*)vertices15,
9697 NULL,
9698 NULL,
9699 num_vertices15,
9700 num_faces15,
9701 vertex_size15,
9702 options,
9703 options,
9704 declaration_ptc,
9705 declaration_ptc_short4n,
9706 (BYTE*)exp_vertices15,
9707 exp_vertex_size15
9710 (BYTE*)vertices16,
9711 NULL,
9712 NULL,
9713 num_vertices16,
9714 num_faces16,
9715 vertex_size16,
9716 options,
9717 options,
9718 declaration_ptc,
9719 declaration_ptc_ushort2n,
9720 (BYTE*)exp_vertices16,
9721 exp_vertex_size16
9724 (BYTE*)vertices17,
9725 NULL,
9726 NULL,
9727 num_vertices17,
9728 num_faces17,
9729 vertex_size17,
9730 options,
9731 options,
9732 declaration_ptc,
9733 declaration_ptc_ushort4n,
9734 (BYTE*)exp_vertices17,
9735 exp_vertex_size17
9738 (BYTE*)vertices18,
9739 NULL,
9740 NULL,
9741 num_vertices18,
9742 num_faces18,
9743 vertex_size18,
9744 options,
9745 options,
9746 declaration_ptc,
9747 declaration_ptc_float16_2_partialu,
9748 (BYTE*)exp_vertices18,
9749 exp_vertex_size18
9752 (BYTE*)vertices19,
9753 NULL,
9754 NULL,
9755 num_vertices19,
9756 num_faces19,
9757 vertex_size19,
9758 options,
9759 options,
9760 declaration_pntc,
9761 declaration_pntc1,
9762 (BYTE*)exp_vertices19,
9763 exp_vertex_size19
9766 (BYTE*)vertices20,
9767 NULL,
9768 NULL,
9769 num_vertices20,
9770 num_faces20,
9771 vertex_size20,
9772 options,
9773 options,
9774 declaration_pntc1,
9775 declaration_pntc,
9776 (BYTE*)exp_vertices20,
9777 exp_vertex_size20
9780 (BYTE*)vertices21,
9781 NULL,
9782 NULL,
9783 num_vertices21,
9784 num_faces21,
9785 vertex_size21,
9786 options,
9787 options,
9788 declaration_ptc_float1,
9789 declaration_ptc,
9790 (BYTE*)exp_vertices21,
9791 exp_vertex_size21
9794 (BYTE*)vertices22,
9795 NULL,
9796 NULL,
9797 num_vertices22,
9798 num_faces22,
9799 vertex_size22,
9800 options,
9801 options,
9802 declaration_ptc_float1,
9803 declaration_ptc_float3,
9804 (BYTE*)exp_vertices22,
9805 exp_vertex_size22
9808 (BYTE*)vertices23,
9809 NULL,
9810 NULL,
9811 num_vertices23,
9812 num_faces23,
9813 vertex_size23,
9814 options,
9815 options,
9816 declaration_ptc_float1,
9817 declaration_ptc_float4,
9818 (BYTE*)exp_vertices23,
9819 exp_vertex_size23
9822 (BYTE*)vertices24,
9823 NULL,
9824 NULL,
9825 num_vertices24,
9826 num_faces24,
9827 vertex_size24,
9828 options,
9829 options,
9830 declaration_ptc_float1,
9831 declaration_ptc_d3dcolor,
9832 (BYTE*)exp_vertices24,
9833 exp_vertex_size24
9836 (BYTE*)vertices25,
9837 NULL,
9838 NULL,
9839 num_vertices25,
9840 num_faces25,
9841 vertex_size25,
9842 options,
9843 options,
9844 declaration_ptc_float1,
9845 declaration_ptc_ubyte4,
9846 (BYTE*)exp_vertices25,
9847 exp_vertex_size25
9850 (BYTE*)vertices26,
9851 NULL,
9852 NULL,
9853 num_vertices26,
9854 num_faces26,
9855 vertex_size26,
9856 options,
9857 options,
9858 declaration_ptc_float4,
9859 declaration_ptc_d3dcolor,
9860 (BYTE*)exp_vertices26,
9861 exp_vertex_size26
9864 (BYTE*)vertices27,
9865 NULL,
9866 NULL,
9867 num_vertices27,
9868 num_faces27,
9869 vertex_size27,
9870 options,
9871 options,
9872 declaration_ptc_d3dcolor,
9873 declaration_ptc_float4,
9874 (BYTE*)exp_vertices27,
9875 exp_vertex_size27
9878 (BYTE*)vertices28,
9879 NULL,
9880 NULL,
9881 num_vertices28,
9882 num_faces28,
9883 vertex_size28,
9884 options,
9885 options,
9886 declaration_ptc_ubyte4,
9887 declaration_ptc_float4,
9888 (BYTE*)exp_vertices28,
9889 exp_vertex_size28
9892 (BYTE*)vertices29,
9893 NULL,
9894 NULL,
9895 num_vertices29,
9896 num_faces29,
9897 vertex_size29,
9898 options,
9899 options,
9900 declaration_ptc_short2,
9901 declaration_ptc_float4,
9902 (BYTE*)exp_vertices29,
9903 exp_vertex_size29
9906 (BYTE*)vertices30,
9907 NULL,
9908 NULL,
9909 num_vertices30,
9910 num_faces30,
9911 vertex_size30,
9912 options,
9913 options,
9914 declaration_ptc_short4,
9915 declaration_ptc_float4,
9916 (BYTE*)exp_vertices30,
9917 exp_vertex_size30
9920 (BYTE*)vertices31,
9921 NULL,
9922 NULL,
9923 num_vertices31,
9924 num_faces31,
9925 vertex_size31,
9926 options,
9927 options,
9928 declaration_ptc_ubyte4n,
9929 declaration_ptc_float4,
9930 (BYTE*)exp_vertices31,
9931 exp_vertex_size31
9934 (BYTE*)vertices32,
9935 NULL,
9936 NULL,
9937 num_vertices32,
9938 num_faces32,
9939 vertex_size32,
9940 options,
9941 options,
9942 declaration_ptc_short2n,
9943 declaration_ptc_float4,
9944 (BYTE*)exp_vertices32,
9945 exp_vertex_size32
9948 (BYTE*)vertices33,
9949 NULL,
9950 NULL,
9951 num_vertices33,
9952 num_faces33,
9953 vertex_size33,
9954 options,
9955 options,
9956 declaration_ptc_short4n,
9957 declaration_ptc_float4,
9958 (BYTE*)exp_vertices33,
9959 exp_vertex_size33
9962 (BYTE*)vertices34,
9963 NULL,
9964 NULL,
9965 num_vertices34,
9966 num_faces34,
9967 vertex_size34,
9968 options,
9969 options,
9970 declaration_ptc_float16_2,
9971 declaration_ptc_float4,
9972 (BYTE*)exp_vertices34,
9973 exp_vertex_size34
9976 (BYTE*)vertices35,
9977 NULL,
9978 NULL,
9979 num_vertices35,
9980 num_faces35,
9981 vertex_size35,
9982 options,
9983 options,
9984 declaration_ptc_float16_4,
9985 declaration_ptc_float4,
9986 (BYTE*)exp_vertices35,
9987 exp_vertex_size35
9990 (BYTE*)vertices36,
9991 NULL,
9992 NULL,
9993 num_vertices36,
9994 num_faces36,
9995 vertex_size36,
9996 options,
9997 clone_options36,
9998 declaration_pn,
9999 declaration_pn,
10000 (BYTE*)vertices36,
10001 vertex_size36
10005 test_context = new_test_context();
10006 if (!test_context)
10008 skip("Couldn't create test context\n");
10009 goto cleanup;
10012 for (i = 0; i < ARRAY_SIZE(tc); i++)
10014 UINT j;
10015 D3DVERTEXELEMENT9 new_declaration[MAX_FVF_DECL_SIZE];
10016 UINT exp_new_decl_length, new_decl_length;
10017 UINT exp_new_decl_size, new_decl_size;
10019 hr = init_test_mesh(tc[i].num_faces, tc[i].num_vertices,
10020 tc[i].create_options,
10021 tc[i].declaration,
10022 test_context->device, &mesh,
10023 tc[i].vertices, tc[i].vertex_size,
10024 tc[i].indices, tc[i].attributes);
10025 if (FAILED(hr))
10027 skip("Couldn't initialize test mesh %d. Got %x expected D3D_OK\n", i, hr);
10028 goto cleanup;
10031 hr = mesh->lpVtbl->CloneMesh(mesh, tc[i].clone_options, tc[i].new_declaration,
10032 test_context->device, &mesh_clone);
10033 ok(hr == D3D_OK, "CloneMesh test case %d failed. Got %x\n, expected D3D_OK\n", i, hr);
10035 hr = mesh_clone->lpVtbl->GetDeclaration(mesh_clone, new_declaration);
10036 ok(hr == D3D_OK, "GetDeclaration test case %d failed. Got %x\n, expected D3D_OK\n", i, hr);
10037 /* Check declaration elements */
10038 for (j = 0; tc[i].new_declaration[j].Stream != 0xFF; j++)
10040 ok(memcmp(&tc[i].new_declaration[j], &new_declaration[j], sizeof(*new_declaration)) == 0,
10041 "Test case %d failed. Declaration element %d did not match.\n", i, j);
10044 /* Check declaration length */
10045 exp_new_decl_length = D3DXGetDeclLength(tc[i].new_declaration);
10046 new_decl_length = D3DXGetDeclLength(new_declaration);
10047 ok(new_decl_length == exp_new_decl_length,
10048 "Test case %d failed. Got new declaration length %d, expected %d\n",
10049 i, new_decl_length, exp_new_decl_length);
10051 /* Check declaration size */
10052 exp_new_decl_size = D3DXGetDeclVertexSize(tc[i].new_declaration, 0);
10053 new_decl_size = D3DXGetDeclVertexSize(new_declaration, 0);
10054 ok(new_decl_size == exp_new_decl_size,
10055 "Test case %d failed. Got new declaration size %d, expected %d\n",
10056 i, new_decl_size, exp_new_decl_size);
10058 /* Check vertex data in cloned mesh */
10059 hr = mesh_clone->lpVtbl->LockVertexBuffer(mesh_clone, 0, (void**)&vertices);
10060 if (FAILED(hr))
10062 skip("Couldn't lock cloned vertex buffer.\n");
10063 goto cleanup;
10065 for (j = 0; j < tc[i].num_vertices; j++)
10067 UINT index = tc[i].exp_vertex_size * j;
10068 check_vertex_components(__LINE__, i, j, &vertices[index], &tc[i].exp_vertices[index], tc[i].new_declaration);
10070 hr = mesh_clone->lpVtbl->UnlockVertexBuffer(mesh_clone);
10071 if (FAILED(hr))
10073 skip("Couldn't unlock vertex buffer.\n");
10074 goto cleanup;
10076 vertices = NULL;
10077 mesh->lpVtbl->Release(mesh);
10078 mesh = NULL;
10079 mesh_clone->lpVtbl->Release(mesh_clone);
10080 mesh_clone = NULL;
10083 /* The following test shows that it is not possible to share a vertex buffer
10084 * with D3DXMESH_VB_SHARE and change the vertex declaration at the same
10085 * time. It reuses the test data from test 2.
10087 hr = init_test_mesh(tc[2].num_faces, tc[2].num_vertices,
10088 tc[2].create_options,
10089 tc[2].declaration,
10090 test_context->device, &mesh,
10091 tc[2].vertices, tc[2].vertex_size,
10092 tc[2].indices, tc[2].attributes);
10093 if (FAILED(hr))
10095 skip("Couldn't initialize test mesh for D3DXMESH_VB_SHARE case."
10096 " Got %x expected D3D_OK\n", hr);
10097 goto cleanup;
10100 hr = mesh->lpVtbl->CloneMesh(mesh, tc[2].create_options | D3DXMESH_VB_SHARE,
10101 tc[2].new_declaration, test_context->device,
10102 &mesh_clone);
10103 ok(hr == D3DERR_INVALIDCALL, "CloneMesh D3DXMESH_VB_SHARE with new"
10104 " declaration. Got %x, expected D3DERR_INVALIDCALL\n",
10105 hr);
10106 mesh->lpVtbl->Release(mesh);
10107 mesh = NULL;
10108 mesh_clone = NULL;
10110 cleanup:
10111 if (vertices) mesh->lpVtbl->UnlockVertexBuffer(mesh);
10112 if (mesh) mesh->lpVtbl->Release(mesh);
10113 if (mesh_clone) mesh_clone->lpVtbl->Release(mesh_clone);
10114 free_test_context(test_context);
10117 static void test_valid_mesh(void)
10119 HRESULT hr;
10120 struct test_context *test_context = NULL;
10121 UINT i;
10122 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
10123 const D3DVERTEXELEMENT9 declaration[] =
10125 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
10126 D3DDECL_END()
10128 const unsigned int VERTS_PER_FACE = 3;
10129 /* mesh0 (one face)
10131 * 0--1
10132 * | /
10133 * |/
10136 const D3DXVECTOR3 vertices0[] =
10138 { 0.0f, 3.0f, 0.f},
10139 { 2.0f, 3.0f, 0.f},
10140 { 0.0f, 0.0f, 0.f},
10142 const DWORD indices0[] = {0, 1, 2};
10143 const unsigned int num_vertices0 = ARRAY_SIZE(vertices0);
10144 const unsigned int num_faces0 = ARRAY_SIZE(indices0) / VERTS_PER_FACE;
10145 const DWORD adjacency0[] = {-1, -1, -1};
10146 const HRESULT exp_hr0 = D3D_OK;
10147 /* mesh1 (Simple bow-tie)
10149 * 0--1 1--3
10150 * | / \ |
10151 * |/ \|
10152 * 2 4
10154 const D3DXVECTOR3 vertices1[] =
10156 { 0.0f, 3.0f, 0.f},
10157 { 2.0f, 3.0f, 0.f},
10158 { 0.0f, 0.0f, 0.f},
10160 { 4.0f, 3.0f, 0.f},
10161 { 4.0f, 0.0f, 0.f},
10163 const DWORD indices1[] = {0, 1, 2, 1, 3, 4};
10164 const unsigned int num_vertices1 = ARRAY_SIZE(vertices1);
10165 const unsigned int num_faces1 = ARRAY_SIZE(indices1) / VERTS_PER_FACE;
10166 const DWORD adjacency1[] = {-1, -1, -1, -1, -1, -1};
10167 const HRESULT exp_hr1 = D3DXERR_INVALIDMESH;
10168 /* Common mesh data */
10169 ID3DXMesh *mesh = NULL;
10170 UINT vertex_size = sizeof(D3DXVECTOR3);
10171 ID3DXBuffer *errors_and_warnings = NULL;
10172 struct
10174 const D3DXVECTOR3 *vertices;
10175 const DWORD *indices;
10176 const UINT num_vertices;
10177 const UINT num_faces;
10178 const DWORD *adjacency;
10179 const HRESULT exp_hr;
10181 tc[] =
10184 vertices0,
10185 indices0,
10186 num_vertices0,
10187 num_faces0,
10188 adjacency0,
10189 exp_hr0,
10192 vertices1,
10193 indices1,
10194 num_vertices1,
10195 num_faces1,
10196 adjacency1,
10197 exp_hr1,
10201 test_context = new_test_context();
10202 if (!test_context)
10204 skip("Couldn't create test context\n");
10205 goto cleanup;
10208 for (i = 0; i < ARRAY_SIZE(tc); i++)
10210 hr = init_test_mesh(tc[i].num_faces, tc[i].num_vertices,
10211 options, declaration,
10212 test_context->device, &mesh,
10213 tc[i].vertices, vertex_size,
10214 tc[i].indices, NULL);
10215 if (FAILED(hr))
10217 skip("Couldn't initialize test mesh %d. Got %x expected D3D_OK\n", i, hr);
10218 goto cleanup;
10221 hr = D3DXValidMesh(mesh, tc[i].adjacency, &errors_and_warnings);
10222 todo_wine ok(hr == tc[i].exp_hr, "D3DXValidMesh test case %d failed. "
10223 "Got %x\n, expected %x\n", i, hr, tc[i].exp_hr);
10225 /* Note errors_and_warnings is deliberately not checked because that
10226 * would require copying wast amounts of the text output. */
10227 if (errors_and_warnings)
10229 ID3DXBuffer_Release(errors_and_warnings);
10230 errors_and_warnings = NULL;
10232 mesh->lpVtbl->Release(mesh);
10233 mesh = NULL;
10236 cleanup:
10237 if (mesh) mesh->lpVtbl->Release(mesh);
10238 free_test_context(test_context);
10241 static void test_optimize_faces(void)
10243 HRESULT hr;
10244 UINT i;
10245 DWORD smallest_face_remap;
10246 /* mesh0
10248 * 0--1
10249 * | /
10250 * |/
10253 const DWORD indices0[] = {0, 1, 2};
10254 const UINT num_faces0 = 1;
10255 const UINT num_vertices0 = 3;
10256 const DWORD exp_face_remap0[] = {0};
10257 /* mesh1
10259 * 0--1 3
10260 * | / /|
10261 * |/ / |
10262 * 2 5--4
10264 const DWORD indices1[] = {0, 1, 2, 3, 4, 5};
10265 const UINT num_faces1 = 2;
10266 const UINT num_vertices1 = 6;
10267 const DWORD exp_face_remap1[] = {1, 0};
10268 /* mesh2
10270 * 0--1
10271 * | /|
10272 * |/ |
10273 * 2--3
10275 const DWORD indices2[] = {0, 1, 2, 1, 3, 2};
10276 const UINT num_faces2 = 2;
10277 const UINT num_vertices2 = 4;
10278 const DWORD exp_face_remap2[] = {1, 0};
10279 /* mesh3
10281 * 0--1
10282 * | /|
10283 * |/ |
10284 * 2--3
10285 * | /|
10286 * |/ |
10287 * 4--5
10289 const DWORD indices3[] = {0, 1, 2, 1, 3, 2, 2, 3, 4, 3, 4, 5};
10290 const UINT num_faces3 = 4;
10291 const UINT num_vertices3 = 6;
10292 const DWORD exp_face_remap3[] = {3, 2, 1, 0};
10293 /* mesh4
10295 * 0--1
10296 * | /|
10297 * |/ |
10298 * 2--3
10299 * | /|
10300 * |/ |
10301 * 4--5
10303 const WORD indices4[] = {0, 1, 2, 1, 3, 2, 2, 3, 4, 3, 4, 5};
10304 const UINT num_faces4 = 4;
10305 const UINT num_vertices4 = 6;
10306 const DWORD exp_face_remap4[] = {3, 2, 1, 0};
10307 /* Test cases are stored in the tc array */
10308 struct
10310 const VOID *indices;
10311 const UINT num_faces;
10312 const UINT num_vertices;
10313 const BOOL indices_are_32bit;
10314 const DWORD *exp_face_remap;
10316 tc[] =
10319 indices0,
10320 num_faces0,
10321 num_vertices0,
10322 TRUE,
10323 exp_face_remap0
10326 indices1,
10327 num_faces1,
10328 num_vertices1,
10329 TRUE,
10330 exp_face_remap1
10333 indices2,
10334 num_faces2,
10335 num_vertices2,
10336 TRUE,
10337 exp_face_remap2
10340 indices3,
10341 num_faces3,
10342 num_vertices3,
10343 TRUE,
10344 exp_face_remap3
10347 indices4,
10348 num_faces4,
10349 num_vertices4,
10350 FALSE,
10351 exp_face_remap4
10355 /* Go through all test cases */
10356 for (i = 0; i < ARRAY_SIZE(tc); i++)
10358 DWORD j;
10359 DWORD *face_remap;
10360 face_remap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
10361 tc[i].num_faces*sizeof(*face_remap));
10363 hr = D3DXOptimizeFaces(tc[i].indices, tc[i].num_faces,
10364 tc[i].num_vertices, tc[i].indices_are_32bit,
10365 face_remap);
10366 ok(hr == D3D_OK, "D3DXOptimizeFaces test case %d failed. "
10367 "Got %x\n, expected D3D_OK\n", i, hr);
10369 /* Compare face remap with expected face remap */
10370 for (j = 0; j < tc[i].num_faces; j++)
10372 ok(tc[i].exp_face_remap[j] == face_remap[j],
10373 "Test case %d: Got face %d at %d, expected %d\n", i,
10374 face_remap[j], j, tc[i].exp_face_remap[j]);
10377 HeapFree(GetProcessHeap(), 0, face_remap);
10380 /* face_remap must not be NULL */
10381 hr = D3DXOptimizeFaces(tc[0].indices, tc[0].num_faces,
10382 tc[0].num_vertices, tc[0].indices_are_32bit,
10383 NULL);
10384 ok(hr == D3DERR_INVALIDCALL, "D3DXOptimizeFaces passed NULL face_remap "
10385 "pointer. Got %x\n, expected D3DERR_INVALIDCALL\n", hr);
10387 /* Number of faces must be smaller than 2^15 */
10388 hr = D3DXOptimizeFaces(tc[0].indices, 2 << 15,
10389 tc[0].num_vertices, FALSE,
10390 &smallest_face_remap);
10391 ok(hr == D3DERR_INVALIDCALL, "D3DXOptimizeFaces should not accept 2^15 "
10392 "faces when using 16-bit indices. Got %x\n, expected D3DERR_INVALIDCALL\n", hr);
10395 static HRESULT clear_normals(ID3DXMesh *mesh)
10397 HRESULT hr;
10398 BYTE *vertices;
10399 size_t normal_size;
10400 DWORD i, num_vertices, vertex_stride;
10401 const D3DXVECTOR4 normal = {NAN, NAN, NAN, NAN};
10402 D3DVERTEXELEMENT9 *normal_declaration = NULL;
10403 D3DVERTEXELEMENT9 declaration[MAX_FVF_DECL_SIZE] = {D3DDECL_END()};
10405 if (FAILED(hr = mesh->lpVtbl->GetDeclaration(mesh, declaration)))
10406 return hr;
10408 for (i = 0; declaration[i].Stream != 0xff; i++)
10410 if (declaration[i].Usage == D3DDECLUSAGE_NORMAL && !declaration[i].UsageIndex)
10412 normal_declaration = &declaration[i];
10413 break;
10417 if (!normal_declaration)
10418 return D3DERR_INVALIDCALL;
10420 if (normal_declaration->Type == D3DDECLTYPE_FLOAT3)
10422 normal_size = sizeof(D3DXVECTOR3);
10424 else if (normal_declaration->Type == D3DDECLTYPE_FLOAT4)
10426 normal_size = sizeof(D3DXVECTOR4);
10428 else
10430 trace("Cannot clear normals\n");
10431 return E_NOTIMPL;
10434 num_vertices = mesh->lpVtbl->GetNumVertices(mesh);
10435 vertex_stride = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
10437 if (FAILED(hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, (void **)&vertices)))
10438 return hr;
10440 vertices += normal_declaration->Offset;
10442 for (i = 0; i < num_vertices; i++, vertices += vertex_stride)
10443 memcpy(vertices, &normal, normal_size);
10445 return mesh->lpVtbl->UnlockVertexBuffer(mesh);
10448 static void compare_normals(unsigned int line, const char *test_name,
10449 ID3DXMesh *mesh, const D3DXVECTOR3 *normals, unsigned int num_normals)
10451 unsigned int i;
10452 BYTE *vertices;
10453 DWORD num_vertices, vertex_stride;
10454 D3DVERTEXELEMENT9 *normal_declaration = NULL;
10455 D3DVERTEXELEMENT9 declaration[MAX_FVF_DECL_SIZE] = {D3DDECL_END()};
10457 if (FAILED(mesh->lpVtbl->GetDeclaration(mesh, declaration)))
10459 ok_(__FILE__, line)(0, "%s: Failed to get declaration\n", test_name);
10460 return;
10463 for (i = 0; declaration[i].Stream != 0xff; i++)
10465 if (declaration[i].Usage == D3DDECLUSAGE_NORMAL && !declaration[i].UsageIndex)
10467 normal_declaration = &declaration[i];
10468 break;
10472 if (!normal_declaration)
10474 ok_(__FILE__, line)(0, "%s: Mesh has no normals\n", test_name);
10475 return;
10478 if (normal_declaration->Type != D3DDECLTYPE_FLOAT3 && normal_declaration->Type != D3DDECLTYPE_FLOAT4)
10480 ok_(__FILE__, line)(0, "%s: Mesh has invalid normals type\n", test_name);
10481 return;
10484 num_vertices = mesh->lpVtbl->GetNumVertices(mesh);
10485 vertex_stride = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
10487 ok_(__FILE__, line)(num_vertices == num_normals, "%s: Expected %u vertices, got %u\n", test_name,
10488 num_normals, num_vertices);
10490 if (FAILED(mesh->lpVtbl->LockVertexBuffer(mesh, 0, (void **)&vertices)))
10492 ok_(__FILE__, line)(0, "%s: Failed to compare normals\n", test_name);
10493 return;
10496 vertices += normal_declaration->Offset;
10498 for (i = 0; i < min(num_vertices, num_normals); i++, vertices += vertex_stride)
10500 if (normal_declaration->Type == D3DDECLTYPE_FLOAT3)
10502 const D3DXVECTOR3 *n = (D3DXVECTOR3 *)vertices;
10503 ok_(__FILE__, line)(compare_vec3(*n, normals[i]),
10504 "%s: normal %2u, expected (%f, %f, %f), got (%f, %f, %f)\n",
10505 test_name, i, normals[i].x, normals[i].y, normals[i].z, n->x, n->y, n->z);
10507 else
10509 const D3DXVECTOR4 *n = (D3DXVECTOR4 *)vertices;
10510 const D3DXVECTOR4 normal = {normals[i].x, normals[i].y, normals[i].z, 1.0f};
10511 ok_(__FILE__, line)(compare_vec4(*n, normal),
10512 "%s: normal %2u, expected (%f, %f, %f, %f), got (%f, %f, %f, %f)\n",
10513 test_name, i, normals[i].x, normals[i].y, normals[i].z, 1.0f,
10514 n->x, n->y, n->z, n->w);
10518 mesh->lpVtbl->UnlockVertexBuffer(mesh);
10521 static HRESULT compute_normals_D3DXComputeNormals(ID3DXMesh *mesh, const DWORD *adjacency)
10523 return D3DXComputeNormals((ID3DXBaseMesh *)mesh, adjacency);
10526 static HRESULT compute_normals_D3DXComputeTangentFrameEx(ID3DXMesh *mesh, const DWORD *adjacency)
10528 return D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
10529 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS,
10530 adjacency, -1.01f, -0.01f, -1.01f, NULL, NULL);
10533 static void test_compute_normals(void)
10535 HRESULT hr;
10536 ULONG refcount;
10537 ID3DXMesh *mesh, *cloned_mesh;
10538 ID3DXBuffer *adjacency;
10539 IDirect3DDevice9 *device;
10540 struct test_context *test_context;
10541 unsigned int i;
10543 static const struct compute_normals_func
10545 const char *name;
10546 HRESULT (*apply)(ID3DXMesh *mesh, const DWORD *adjacency);
10548 compute_normals_funcs[] =
10550 {"D3DXComputeNormals", compute_normals_D3DXComputeNormals },
10551 {"D3DXComputeTangentFrameEx", compute_normals_D3DXComputeTangentFrameEx}
10554 static const D3DXVECTOR3 box_normals[24] =
10556 {-1.0f, 0.0f, 0.0f}, {-1.0f, 0.0f, 0.0f}, {-1.0f, 0.0f, 0.0f}, {-1.0f, 0.0f, 0.0f},
10557 { 0.0f, 1.0f, 0.0f}, { 0.0f, 1.0f, 0.0f}, { 0.0f, 1.0f, 0.0f}, { 0.0f, 1.0f, 0.0f},
10558 { 1.0f, 0.0f, 0.0f}, { 1.0f, 0.0f, 0.0f}, { 1.0f, 0.0f, 0.0f}, { 1.0f, 0.0f, 0.0f},
10559 { 0.0f,-1.0f, 0.0f}, { 0.0f,-1.0f, 0.0f}, { 0.0f,-1.0f, 0.0f}, { 0.0f,-1.0f, 0.0f},
10560 { 0.0f, 0.0f, 1.0f}, { 0.0f, 0.0f, 1.0f}, { 0.0f, 0.0f, 1.0f}, { 0.0f, 0.0f, 1.0f},
10561 { 0.0f, 0.0f,-1.0f}, { 0.0f, 0.0f,-1.0f}, { 0.0f, 0.0f,-1.0f}, { 0.0f, 0.0f,-1.0f}
10563 const float box_normal_component = 1.0f / sqrtf(3.0f);
10564 const D3DXVECTOR3 box_normals_adjacency[24] =
10566 {-box_normal_component, -box_normal_component, -box_normal_component},
10567 {-box_normal_component, -box_normal_component, box_normal_component},
10568 {-box_normal_component, box_normal_component, box_normal_component},
10569 {-box_normal_component, box_normal_component, -box_normal_component},
10570 {-box_normal_component, box_normal_component, -box_normal_component},
10571 {-box_normal_component, box_normal_component, box_normal_component},
10572 { box_normal_component, box_normal_component, box_normal_component},
10573 { box_normal_component, box_normal_component, -box_normal_component},
10574 { box_normal_component, box_normal_component, -box_normal_component},
10575 { box_normal_component, box_normal_component, box_normal_component},
10576 { box_normal_component, -box_normal_component, box_normal_component},
10577 { box_normal_component, -box_normal_component, -box_normal_component},
10578 {-box_normal_component, -box_normal_component, box_normal_component},
10579 {-box_normal_component, -box_normal_component, -box_normal_component},
10580 { box_normal_component, -box_normal_component, -box_normal_component},
10581 { box_normal_component, -box_normal_component, box_normal_component},
10582 {-box_normal_component, -box_normal_component, box_normal_component},
10583 { box_normal_component, -box_normal_component, box_normal_component},
10584 { box_normal_component, box_normal_component, box_normal_component},
10585 {-box_normal_component, box_normal_component, box_normal_component},
10586 {-box_normal_component, -box_normal_component, -box_normal_component},
10587 {-box_normal_component, box_normal_component, -box_normal_component},
10588 { box_normal_component, box_normal_component, -box_normal_component},
10589 { box_normal_component, -box_normal_component, -box_normal_component}
10591 static const D3DXVECTOR3 box_normals_adjacency_area[24] =
10593 {-0.666667f, -0.333333f, -0.666667f}, {-0.333333f, -0.666667f, 0.666667f},
10594 {-0.816496f, 0.408248f, 0.408248f}, {-0.408248f, 0.816496f, -0.408248f},
10595 {-0.408248f, 0.816496f, -0.408248f}, {-0.816496f, 0.408248f, 0.408248f},
10596 { 0.333333f, 0.666667f, 0.666667f}, { 0.666667f, 0.333333f, -0.666667f},
10597 { 0.666667f, 0.333333f, -0.666667f}, { 0.333333f, 0.666667f, 0.666667f},
10598 { 0.816496f, -0.408248f, 0.408248f}, { 0.408248f, -0.816496f, -0.408248f},
10599 {-0.333333f, -0.666667f, 0.666667f}, {-0.666667f, -0.333333f, -0.666667f},
10600 { 0.408248f, -0.816496f, -0.408248f}, { 0.816496f, -0.408248f, 0.408248f},
10601 {-0.333333f, -0.666667f, 0.666667f}, { 0.816497f, -0.408248f, 0.408248f},
10602 { 0.333333f, 0.666667f, 0.666667f}, {-0.816497f, 0.408248f, 0.408248f},
10603 {-0.666667f, -0.333333f, -0.666667f}, {-0.408248f, 0.816497f, -0.408248f},
10604 { 0.666667f, 0.333333f, -0.666667f}, { 0.408248f, -0.816496f, -0.408248f}
10606 static const D3DXVECTOR3 box_normals_position1f[24] = {{0}};
10607 static const D3DXVECTOR3 box_normals_position2f[24] =
10609 {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f},
10610 {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, 1.0f},
10611 {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, -1.0f},
10612 {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f},
10613 {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, -1.0f},
10614 {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f},
10615 {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f},
10616 {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, -1.0f}
10619 static const D3DXVECTOR3 sphere_normals[22] =
10621 { 0.000000f, -0.000000f, 1.000000f}, { 0.000000f, 0.582244f, 0.813014f},
10622 { 0.582244f, -0.000000f, 0.813014f}, {-0.000000f, -0.582244f, 0.813014f},
10623 {-0.582244f, 0.000000f, 0.813014f}, {-0.000000f, 0.890608f, 0.454772f},
10624 { 0.890608f, 0.000000f, 0.454772f}, { 0.000000f, -0.890608f, 0.454772f},
10625 {-0.890608f, -0.000000f, 0.454772f}, { 0.000000f, 1.000000f, -0.000000f},
10626 { 1.000000f, -0.000000f, -0.000000f}, {-0.000000f, -1.000000f, -0.000000f},
10627 {-1.000000f, 0.000000f, -0.000000f}, { 0.000000f, 0.890608f, -0.454773f},
10628 { 0.890608f, -0.000000f, -0.454772f}, {-0.000000f, -0.890608f, -0.454773f},
10629 {-0.890608f, 0.000000f, -0.454773f}, { 0.000000f, 0.582244f, -0.813015f},
10630 { 0.582244f, -0.000000f, -0.813015f}, { 0.000000f, -0.582244f, -0.813015f},
10631 {-0.582243f, 0.000000f, -0.813015f}, { 0.000000f, 0.000000f, -1.000000f}
10633 static const D3DXVECTOR3 sphere_normals_area[22] =
10635 { 0.000000f, -0.000000f, 1.000000f}, {-0.215311f, 0.554931f, 0.803550f},
10636 { 0.554931f, 0.215311f, 0.803550f}, { 0.215311f, -0.554931f, 0.803550f},
10637 {-0.554931f, -0.215311f, 0.803550f}, {-0.126638f, 0.872121f, 0.472618f},
10638 { 0.872121f, 0.126638f, 0.472618f}, { 0.126638f, -0.872121f, 0.472618f},
10639 {-0.872121f, -0.126637f, 0.472618f}, { 0.000000f, 1.000000f, -0.000000f},
10640 { 1.000000f, -0.000000f, -0.000000f}, {-0.000000f, -1.000000f, -0.000000f},
10641 {-1.000000f, 0.000000f, -0.000000f}, { 0.126638f, 0.872121f, -0.472618f},
10642 { 0.872121f, -0.126638f, -0.472618f}, {-0.126638f, -0.872121f, -0.472618f},
10643 {-0.872121f, 0.126638f, -0.472618f}, { 0.215311f, 0.554931f, -0.803550f},
10644 { 0.554931f, -0.215311f, -0.803550f}, {-0.215311f, -0.554931f, -0.803550f},
10645 {-0.554931f, 0.215311f, -0.803550f}, { 0.000000f, 0.000000f, -1.000000f}
10647 static const D3DXVECTOR3 sphere_normals_equal[22] =
10649 { 0.000000f, -0.000000f, 1.000000f}, {-0.134974f, 0.522078f, 0.842150f},
10650 { 0.522078f, 0.134974f, 0.842150f}, { 0.134974f, -0.522078f, 0.842150f},
10651 {-0.522078f, -0.134974f, 0.842150f}, {-0.026367f, 0.857121f, 0.514440f},
10652 { 0.857121f, 0.026367f, 0.514440f}, { 0.026367f, -0.857121f, 0.514440f},
10653 {-0.857121f, -0.026367f, 0.514440f}, { 0.000000f, 1.000000f, -0.000000f},
10654 { 1.000000f, -0.000000f, -0.000000f}, {-0.000000f, -1.000000f, -0.000000f},
10655 {-1.000000f, 0.000000f, -0.000000f}, { 0.026367f, 0.857121f, -0.514440f},
10656 { 0.857121f, -0.026367f, -0.514440f}, {-0.026367f, -0.857121f, -0.514440f},
10657 {-0.857121f, 0.026367f, -0.514440f}, { 0.134975f, 0.522078f, -0.842150f},
10658 { 0.522078f, -0.134975f, -0.842150f}, {-0.134974f, -0.522078f, -0.842150f},
10659 {-0.522078f, 0.134974f, -0.842150f}, { 0.000000f, 0.000000f, -1.000000f}
10662 static const D3DVERTEXELEMENT9 position3f_normal1f_declaration[] =
10664 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
10665 {0, sizeof(D3DXVECTOR3), D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
10666 D3DDECL_END()
10668 static const D3DVERTEXELEMENT9 position3f_normal2f_declaration[] =
10670 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
10671 {0, sizeof(D3DXVECTOR3), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
10672 D3DDECL_END()
10674 static const D3DVERTEXELEMENT9 normal4f_position3f_declaration[] =
10676 {0, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
10677 {0, sizeof(D3DXVECTOR4), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
10678 D3DDECL_END()
10680 static const D3DVERTEXELEMENT9 position1f_normal3f_declaration[] =
10682 {0, 0, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
10683 {0, sizeof(float), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
10684 D3DDECL_END()
10686 static const D3DVERTEXELEMENT9 position2f_normal3f_declaration[] =
10688 {0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
10689 {0, sizeof(D3DXVECTOR2), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
10690 D3DDECL_END()
10692 static const D3DVERTEXELEMENT9 position4f_normal3f_declaration[] =
10694 {0, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
10695 {0, sizeof(D3DXVECTOR4), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
10696 D3DDECL_END()
10699 for (i = 0; i < ARRAY_SIZE(compute_normals_funcs); i++)
10701 hr = compute_normals_funcs[i].apply(NULL, NULL);
10702 ok(hr == D3DERR_INVALIDCALL, "%s returned %#x, expected D3DERR_INVALIDCALL\n", compute_normals_funcs[i].name, hr);
10705 if (!(test_context = new_test_context()))
10707 skip("Couldn't create test context\n");
10708 return;
10710 device = test_context->device;
10712 hr = D3DXCreateBox(device, 1.0f, 1.0f, 1.0f, &mesh, &adjacency);
10713 ok(SUCCEEDED(hr), "D3DXCreateBox failed %#x\n", hr);
10715 /* Check wrong input */
10716 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
10717 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE, NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
10718 todo_wine ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr);
10720 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DDECLUSAGE_NORMAL, 0,
10721 D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_BY_AREA | D3DXTANGENT_WEIGHT_EQUAL,
10722 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
10723 ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr);
10725 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
10726 D3DDECLUSAGE_NORMAL, 0, 0, NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
10727 todo_wine ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr);
10729 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
10730 D3DDECLUSAGE_NORMAL, 1, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS,
10731 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
10732 ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr);
10734 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
10735 D3DX_DEFAULT, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS,
10736 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
10737 ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr);
10739 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
10740 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_CALCULATE_NORMALS,
10741 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
10742 todo_wine ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr);
10744 for (i = 0; i < ARRAY_SIZE(compute_normals_funcs); i++)
10746 const struct compute_normals_func *func = &compute_normals_funcs[i];
10748 /* Mesh without normals */
10749 hr = mesh->lpVtbl->CloneMeshFVF(mesh, 0, D3DFVF_XYZ, device, &cloned_mesh);
10750 ok(SUCCEEDED(hr), "CloneMeshFVF failed %#x\n", hr);
10752 hr = func->apply(cloned_mesh, NULL);
10753 ok(hr == D3DERR_INVALIDCALL, "%s returned %#x, expected D3DERR_INVALIDCALL\n", func->name, hr);
10755 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh);
10756 ok(!refcount, "Mesh has %u references left\n", refcount);
10758 /* Mesh without positions */
10759 hr = mesh->lpVtbl->CloneMeshFVF(mesh, 0, D3DFVF_NORMAL, device, &cloned_mesh);
10760 ok(SUCCEEDED(hr), "CloneMeshFVF failed %#x\n", hr);
10762 hr = func->apply(cloned_mesh, NULL);
10763 ok(hr == D3DERR_INVALIDCALL, "%s returned %#x, expected D3DERR_INVALIDCALL\n", func->name, hr);
10765 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh);
10766 ok(!refcount, "Mesh has %u references left\n", refcount);
10768 /* Mesh with D3DDECLTYPE_FLOAT1 normals */
10769 hr = mesh->lpVtbl->CloneMesh(mesh, 0, position3f_normal1f_declaration, device, &cloned_mesh);
10770 ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr);
10772 hr = func->apply(cloned_mesh, NULL);
10773 ok(hr == D3DERR_INVALIDCALL, "%s returned %#x, expected D3DERR_INVALIDCALL\n", func->name, hr);
10775 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh);
10776 ok(!refcount, "Mesh has %u references left\n", refcount);
10778 /* Mesh with D3DDECLTYPE_FLOAT2 normals */
10779 hr = mesh->lpVtbl->CloneMesh(mesh, 0, position3f_normal2f_declaration, device, &cloned_mesh);
10780 ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr);
10782 hr = func->apply(cloned_mesh, NULL);
10783 ok(hr == D3DERR_INVALIDCALL, "%s returned %#x, expected D3DERR_INVALIDCALL\n", func->name, hr);
10785 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh);
10786 ok(!refcount, "Mesh has %u references left\n", refcount);
10788 /* Mesh without adjacency data */
10789 hr = clear_normals(mesh);
10790 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr);
10792 hr = func->apply(mesh, NULL);
10793 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr);
10795 compare_normals(__LINE__, func->name, mesh, box_normals, ARRAY_SIZE(box_normals));
10797 /* Mesh with adjacency data */
10798 hr = clear_normals(mesh);
10799 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr);
10801 hr = func->apply(mesh, ID3DXBuffer_GetBufferPointer(adjacency));
10802 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr);
10804 compare_normals(__LINE__, func->name, mesh, box_normals_adjacency, ARRAY_SIZE(box_normals_adjacency));
10806 /* Mesh with custom vertex format, D3DDECLTYPE_FLOAT4 normals and adjacency */
10807 hr = mesh->lpVtbl->CloneMesh(mesh, 0, normal4f_position3f_declaration, device, &cloned_mesh);
10808 ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr);
10810 hr = clear_normals(cloned_mesh);
10811 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr);
10813 hr = func->apply(cloned_mesh, ID3DXBuffer_GetBufferPointer(adjacency));
10814 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr);
10816 compare_normals(__LINE__, func->name, cloned_mesh, box_normals_adjacency, ARRAY_SIZE(box_normals_adjacency));
10818 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh);
10819 ok(!refcount, "Mesh has %u references left\n", refcount);
10821 /* Mesh with D3DDECLTYPE_FLOAT1 positions and D3DDECLTYPE_FLOAT3 normals */
10822 hr = mesh->lpVtbl->CloneMesh(mesh, 0, position1f_normal3f_declaration, device, &cloned_mesh);
10823 ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr);
10825 hr = clear_normals(cloned_mesh);
10826 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr);
10828 hr = func->apply(cloned_mesh, ID3DXBuffer_GetBufferPointer(adjacency));
10829 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr);
10831 compare_normals(__LINE__, func->name, cloned_mesh, box_normals_position1f, ARRAY_SIZE(box_normals_position1f));
10833 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh);
10834 ok(!refcount, "Mesh has %u references left\n", refcount);
10836 /* Mesh with D3DDECLTYPE_FLOAT2 positions and D3DDECLTYPE_FLOAT3 normals */
10837 hr = mesh->lpVtbl->CloneMesh(mesh, 0, position2f_normal3f_declaration, device, &cloned_mesh);
10838 ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr);
10840 hr = clear_normals(cloned_mesh);
10841 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr);
10843 hr = func->apply(cloned_mesh, ID3DXBuffer_GetBufferPointer(adjacency));
10844 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr);
10846 compare_normals(__LINE__, func->name, cloned_mesh, box_normals_position2f, ARRAY_SIZE(box_normals_position2f));
10848 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh);
10849 ok(!refcount, "Mesh has %u references left\n", refcount);
10851 /* Mesh with D3DDECLTYPE_FLOAT4 positions and D3DDECLTYPE_FLOAT3 normals */
10852 hr = mesh->lpVtbl->CloneMesh(mesh, 0, position4f_normal3f_declaration, device, &cloned_mesh);
10853 ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr);
10855 hr = clear_normals(cloned_mesh);
10856 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr);
10858 hr = func->apply(cloned_mesh, ID3DXBuffer_GetBufferPointer(adjacency));
10859 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr);
10861 compare_normals(__LINE__, func->name, cloned_mesh, box_normals_adjacency, ARRAY_SIZE(box_normals_adjacency));
10863 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh);
10864 ok(!refcount, "Mesh has %u references left\n", refcount);
10867 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
10868 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_BY_AREA,
10869 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
10870 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr);
10872 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, box_normals, ARRAY_SIZE(box_normals));
10874 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
10875 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_BY_AREA,
10876 ID3DXBuffer_GetBufferPointer(adjacency), -1.01f, -0.01f, -1.01f, NULL, NULL);
10877 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr);
10879 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, box_normals_adjacency_area, ARRAY_SIZE(box_normals_adjacency_area));
10881 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
10882 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_EQUAL,
10883 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
10884 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr);
10886 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, box_normals, ARRAY_SIZE(box_normals));
10888 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
10889 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_EQUAL,
10890 ID3DXBuffer_GetBufferPointer(adjacency), -1.01f, -0.01f, -1.01f, NULL, NULL);
10891 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr);
10893 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, box_normals_adjacency_area, ARRAY_SIZE(box_normals_adjacency_area));
10895 refcount = mesh->lpVtbl->Release(mesh);
10896 ok(!refcount, "Mesh has %u references left\n", refcount);
10897 refcount = ID3DXBuffer_Release(adjacency);
10898 ok(!refcount, "Buffer has %u references left\n", refcount);
10900 hr = D3DXCreateSphere(device, 1.0f, 4, 6, &mesh, &adjacency);
10901 ok(SUCCEEDED(hr), "D3DXCreateSphere failed %#x\n", hr);
10903 for (i = 0; i < ARRAY_SIZE(compute_normals_funcs); i++)
10905 const struct compute_normals_func *func = &compute_normals_funcs[i];
10907 /* Sphere without adjacency data */
10908 hr = clear_normals(mesh);
10909 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr);
10911 hr = func->apply(mesh, NULL);
10912 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr);
10914 compare_normals(__LINE__, func->name, mesh, sphere_normals, ARRAY_SIZE(sphere_normals));
10916 /* Sphere with adjacency data */
10917 hr = clear_normals(mesh);
10918 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr);
10920 hr = func->apply(mesh, ID3DXBuffer_GetBufferPointer(adjacency));
10921 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr);
10923 compare_normals(__LINE__, func->name, mesh, sphere_normals, ARRAY_SIZE(sphere_normals));
10926 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
10927 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_BY_AREA,
10928 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
10929 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr);
10931 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, sphere_normals_area, ARRAY_SIZE(sphere_normals_area));
10933 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
10934 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_BY_AREA,
10935 ID3DXBuffer_GetBufferPointer(adjacency), -1.01f, -0.01f, -1.01f, NULL, NULL);
10936 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr);
10938 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, sphere_normals_area, ARRAY_SIZE(sphere_normals_area));
10940 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
10941 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_EQUAL,
10942 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
10943 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr);
10945 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, sphere_normals_equal, ARRAY_SIZE(sphere_normals_equal));
10947 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
10948 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_EQUAL,
10949 ID3DXBuffer_GetBufferPointer(adjacency), -1.01f, -0.01f, -1.01f, NULL, NULL);
10950 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr);
10952 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, sphere_normals_equal, ARRAY_SIZE(sphere_normals_equal));
10954 refcount = mesh->lpVtbl->Release(mesh);
10955 ok(!refcount, "Mesh has %u references left\n", refcount);
10956 refcount = ID3DXBuffer_Release(adjacency);
10957 ok(!refcount, "Buffer has %u references left\n", refcount);
10959 free_test_context(test_context);
10962 START_TEST(mesh)
10964 D3DXBoundProbeTest();
10965 D3DXComputeBoundingBoxTest();
10966 D3DXComputeBoundingSphereTest();
10967 D3DXGetFVFVertexSizeTest();
10968 D3DXIntersectTriTest();
10969 D3DXCreateMeshTest();
10970 D3DXCreateMeshFVFTest();
10971 D3DXLoadMeshTest();
10972 D3DXCreateBoxTest();
10973 D3DXCreatePolygonTest();
10974 D3DXCreateSphereTest();
10975 D3DXCreateCylinderTest();
10976 D3DXCreateTextTest();
10977 D3DXCreateTorusTest();
10978 test_get_decl_length();
10979 test_get_decl_vertex_size();
10980 test_fvf_decl_conversion();
10981 D3DXGenerateAdjacencyTest();
10982 test_update_semantics();
10983 test_create_skin_info();
10984 test_convert_adjacency_to_point_reps();
10985 test_convert_point_reps_to_adjacency();
10986 test_weld_vertices();
10987 test_clone_mesh();
10988 test_valid_mesh();
10989 test_optimize_faces();
10990 test_compute_normals();