d3dx9: Don't always fail if an ID3DXAnimationController pointer is passed to D3DXLoad...
[wine/multimedia.git] / dlls / d3dx9_36 / tests / mesh.c
blob588654ddfe0b8c556e8b298ff845b0ced59e15ea
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), 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 static const char box_anim_xfile[] =
2209 "xof 0303txt 0032"
2210 "Mesh CubeMesh {"
2211 "8;" /* DWORD nVertices; */
2212 /* array Vector vertices[nVertices]; */
2213 "0.0; 0.0; 0.0;,"
2214 "0.0; 0.0; 1.0;,"
2215 "0.0; 1.0; 0.0;,"
2216 "0.0; 1.0; 1.0;,"
2217 "1.0; 0.0; 0.0;,"
2218 "1.0; 0.0; 1.0;,"
2219 "1.0; 1.0; 0.0;,"
2220 "1.0; 1.0; 1.0;;"
2221 "6;" /* DWORD nFaces; */
2222 /* array MeshFace faces[nFaces]; */
2223 "4; 0, 1, 3, 2;," /* left side */
2224 "4; 2, 3, 7, 6;," /* top side */
2225 "4; 6, 7, 5, 4;," /* right side */
2226 "4; 1, 0, 4, 5;," /* bottom side */
2227 "4; 1, 5, 7, 3;," /* back side */
2228 "4; 0, 2, 6, 4;;" /* front side */
2229 "MeshNormals {"
2230 "6;" /* DWORD nNormals; */
2231 /* array Vector normals[nNormals]; */
2232 "-1.0; 0.0; 0.0;,"
2233 "0.0; 1.0; 0.0;,"
2234 "1.0; 0.0; 0.0;,"
2235 "0.0; -1.0; 0.0;,"
2236 "0.0; 0.0; 1.0;,"
2237 "0.0; 0.0; -1.0;;"
2238 "6;" /* DWORD nFaceNormals; */
2239 /* array MeshFace faceNormals[nFaceNormals]; */
2240 "4; 0, 0, 0, 0;,"
2241 "4; 1, 1, 1, 1;,"
2242 "4; 2, 2, 2, 2;,"
2243 "4; 3, 3, 3, 3;,"
2244 "4; 4, 4, 4, 4;,"
2245 "4; 5, 5, 5, 5;;"
2247 "MeshMaterialList materials {"
2248 "2;" /* DWORD nMaterials; */
2249 "6;" /* DWORD nFaceIndexes; */
2250 /* array DWORD faceIndexes[nFaceIndexes]; */
2251 "0, 0, 0, 1, 1, 1;;"
2252 "Material {"
2253 /* ColorRGBA faceColor; */
2254 "0.0; 0.0; 1.0; 1.0;;"
2255 /* FLOAT power; */
2256 "0.5;"
2257 /* ColorRGB specularColor; */
2258 "1.0; 1.0; 1.0;;"
2259 /* ColorRGB emissiveColor; */
2260 "0.0; 0.0; 0.0;;"
2262 "Material {"
2263 /* ColorRGBA faceColor; */
2264 "1.0; 1.0; 1.0; 1.0;;"
2265 /* FLOAT power; */
2266 "1.0;"
2267 /* ColorRGB specularColor; */
2268 "1.0; 1.0; 1.0;;"
2269 /* ColorRGB emissiveColor; */
2270 "0.0; 0.0; 0.0;;"
2271 "TextureFilename { \"texture.jpg\"; }"
2274 "MeshVertexColors {"
2275 "8;" /* DWORD nVertexColors; */
2276 /* array IndexedColor vertexColors[nVertexColors]; */
2277 "0; 0.0; 0.0; 0.0; 0.0;;"
2278 "1; 0.0; 0.0; 1.0; 0.1;;"
2279 "2; 0.0; 1.0; 0.0; 0.2;;"
2280 "3; 0.0; 1.0; 1.0; 0.3;;"
2281 "4; 1.0; 0.0; 0.0; 0.4;;"
2282 "5; 1.0; 0.0; 1.0; 0.5;;"
2283 "6; 1.0; 1.0; 0.0; 0.6;;"
2284 "7; 1.0; 1.0; 1.0; 0.7;;"
2286 "MeshTextureCoords {"
2287 "8;" /* DWORD nTextureCoords; */
2288 /* array Coords2d textureCoords[nTextureCoords]; */
2289 "0.0; 1.0;,"
2290 "1.0; 1.0;,"
2291 "0.0; 0.0;,"
2292 "1.0; 0.0;,"
2293 "1.0; 1.0;,"
2294 "0.0; 1.0;,"
2295 "1.0; 0.0;,"
2296 "0.0; 0.0;;"
2299 "Frame CubeFrame {"
2300 "FrameTransformMatrix {"
2301 /* Matrix4x4 frameMatrix; */
2302 "1.0, 0.0, 0.0, 0.0,"
2303 "0.0, 1.0, 0.0, 0.0,"
2304 "0.0, 0.0, 1.0, 0.0,"
2305 "0.0, 0.0, 0.0, 1.0;;"
2307 "{CubeMesh}"
2309 "AnimationSet AnimationSet0 {"
2310 "Animation Animation0 {"
2311 "{CubeFrame}"
2312 "AnimationKey {"
2313 "2;" /* DWORD keyType; */
2314 "9;" /* DWORD nKeys; */
2315 /* array TimedFloatKeys keys[nKeys]; */
2316 "10; 3; -100.0, 0.0, 0.0;;,"
2317 "20; 3; -75.0, 0.0, 0.0;;,"
2318 "30; 3; -50.0, 0.0, 0.0;;,"
2319 "40; 3; -25.5, 0.0, 0.0;;,"
2320 "50; 3; 0.0, 0.0, 0.0;;,"
2321 "60; 3; 25.5, 0.0, 0.0;;,"
2322 "70; 3; 50.0, 0.0, 0.0;;,"
2323 "80; 3; 75.5, 0.0, 0.0;;,"
2324 "90; 3; 100.0, 0.0, 0.0;;;"
2327 "}";
2329 const DWORD box_fvf = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_TEX1;
2330 /*________________________*/
2331 static const D3DXMATERIAL default_materials[] = {
2334 {0.5, 0.5, 0.5, 0.0}, /* Diffuse */
2335 {0.0, 0.0, 0.0, 0.0}, /* Ambient */
2336 {0.5, 0.5, 0.5, 0.0}, /* Specular */
2337 {0.0, 0.0, 0.0, 0.0}, /* Emissive */
2338 0.0, /* Power */
2340 NULL, /* pTextureFilename */
2343 HRESULT hr;
2344 IDirect3DDevice9 *device = NULL;
2345 ID3DXMesh *mesh = NULL;
2346 D3DXFRAME *frame_hier = NULL;
2347 D3DXMATRIX transform;
2348 struct test_context *test_context;
2349 ID3DXAnimationController *controller;
2351 if (!(test_context = new_test_context()))
2353 skip("Couldn't create test context\n");
2354 return;
2356 device = test_context->device;
2358 hr = D3DXLoadMeshHierarchyFromXInMemory(NULL, sizeof(simple_xfile) - 1,
2359 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
2360 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2362 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, 0,
2363 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
2364 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2366 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1,
2367 D3DXMESH_MANAGED, NULL, &alloc_hier, NULL, &frame_hier, NULL);
2368 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2370 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1,
2371 D3DXMESH_MANAGED, device, NULL, NULL, &frame_hier, NULL);
2372 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2374 hr = D3DXLoadMeshHierarchyFromXInMemory(empty_xfile, sizeof(empty_xfile) - 1,
2375 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
2376 ok(hr == E_FAIL, "Expected E_FAIL, got %#x\n", hr);
2378 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1,
2379 D3DXMESH_MANAGED, device, &alloc_hier, NULL, NULL, NULL);
2380 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2382 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1,
2383 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
2384 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2385 if (SUCCEEDED(hr)) {
2386 D3DXMESHCONTAINER *container = frame_hier->pMeshContainer;
2388 ok(frame_hier->Name == NULL, "Expected NULL, got '%s'\n", frame_hier->Name);
2389 D3DXMatrixIdentity(&transform);
2390 check_matrix(&frame_hier->TransformationMatrix, &transform);
2392 ok(!strcmp(container->Name, ""), "Expected '', got '%s'\n", container->Name);
2393 ok(container->MeshData.Type == D3DXMESHTYPE_MESH, "Expected %d, got %d\n",
2394 D3DXMESHTYPE_MESH, container->MeshData.Type);
2395 mesh = U(container->MeshData).pMesh;
2396 check_vertex_buffer(mesh, simple_vertex_buffer, ARRAY_SIZE(simple_vertex_buffer), simple_fvf);
2397 check_index_buffer(mesh, simple_index_buffer, ARRAY_SIZE(simple_index_buffer), sizeof(*simple_index_buffer));
2398 check_materials(container->pMaterials, container->NumMaterials, NULL, 0);
2399 check_generated_effects(container->pMaterials, container->NumMaterials, container->pEffects);
2400 check_generated_adjacency(mesh, container->pAdjacency, 0.0f);
2401 hr = D3DXFrameDestroy(frame_hier, &alloc_hier);
2402 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2403 frame_hier = NULL;
2406 controller = (ID3DXAnimationController *)0xdeadbeef;
2407 hr = D3DXLoadMeshHierarchyFromXInMemory(box_anim_xfile, sizeof(box_anim_xfile) - 1,
2408 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, &controller);
2409 todo_wine ok(hr == D3D_OK, "Expected D3D_OK, got %#x.\n", hr);
2410 if (SUCCEEDED(hr))
2412 ok(controller != NULL, "Animation Controller NULL.\n");
2414 hr = D3DXFrameDestroy(frame_hier, &alloc_hier);
2415 ok(hr == D3D_OK, "Expected D3D_OK, got %#x.\n", hr);
2416 if (controller)
2417 controller->lpVtbl->Release(controller);
2419 frame_hier = NULL;
2422 controller = (ID3DXAnimationController *)0xdeadbeef;
2423 hr = D3DXLoadMeshHierarchyFromXInMemory(box_xfile, sizeof(box_xfile) - 1,
2424 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, &controller);
2425 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2426 if (SUCCEEDED(hr))
2428 D3DXMESHCONTAINER *container = frame_hier->pMeshContainer;
2430 ok(!controller, "Animation Controller returned.\n");
2431 ok(frame_hier->Name == NULL, "Expected NULL, got '%s'\n", frame_hier->Name);
2432 D3DXMatrixIdentity(&transform);
2433 check_matrix(&frame_hier->TransformationMatrix, &transform);
2435 ok(!strcmp(container->Name, ""), "Expected '', got '%s'\n", container->Name);
2436 ok(container->MeshData.Type == D3DXMESHTYPE_MESH, "Expected %d, got %d\n",
2437 D3DXMESHTYPE_MESH, container->MeshData.Type);
2438 mesh = U(container->MeshData).pMesh;
2439 check_vertex_buffer(mesh, box_vertex_buffer, ARRAY_SIZE(box_vertex_buffer), box_fvf);
2440 check_index_buffer(mesh, box_index_buffer, ARRAY_SIZE(box_index_buffer), sizeof(*box_index_buffer));
2441 check_materials(container->pMaterials, container->NumMaterials, box_materials, ARRAY_SIZE(box_materials));
2442 check_generated_effects(container->pMaterials, container->NumMaterials, container->pEffects);
2443 check_generated_adjacency(mesh, container->pAdjacency, 0.0f);
2444 hr = D3DXFrameDestroy(frame_hier, &alloc_hier);
2445 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2446 frame_hier = NULL;
2449 hr = D3DXLoadMeshHierarchyFromXInMemory(framed_xfile, sizeof(framed_xfile) - 1,
2450 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
2451 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2452 if (SUCCEEDED(hr)) {
2453 D3DXMESHCONTAINER *container = frame_hier->pMeshContainer;
2454 int i;
2456 ok(!strcmp(frame_hier->Name, ""), "Expected '', got '%s'\n", frame_hier->Name);
2457 /* last frame transform replaces the first */
2458 D3DXMatrixIdentity(&transform);
2459 U(transform).m[3][2] = 3.0;
2460 check_matrix(&frame_hier->TransformationMatrix, &transform);
2462 for (i = 0; i < 3; i++) {
2463 ok(!strcmp(container->Name, ""), "Expected '', got '%s'\n", container->Name);
2464 ok(container->MeshData.Type == D3DXMESHTYPE_MESH, "Expected %d, got %d\n",
2465 D3DXMESHTYPE_MESH, container->MeshData.Type);
2466 mesh = U(container->MeshData).pMesh;
2467 check_vertex_buffer(mesh, framed_vertex_buffers[i], ARRAY_SIZE(framed_vertex_buffers[0]), framed_fvf);
2468 check_index_buffer(mesh, framed_index_buffer, ARRAY_SIZE(framed_index_buffer), sizeof(*framed_index_buffer));
2469 check_materials(container->pMaterials, container->NumMaterials, NULL, 0);
2470 check_generated_effects(container->pMaterials, container->NumMaterials, container->pEffects);
2471 check_generated_adjacency(mesh, container->pAdjacency, 0.0f);
2472 container = container->pNextMeshContainer;
2474 ok(container == NULL, "Expected NULL, got %p\n", container);
2475 hr = D3DXFrameDestroy(frame_hier, &alloc_hier);
2476 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2477 frame_hier = NULL;
2481 hr = D3DXLoadMeshFromXInMemory(NULL, 0, D3DXMESH_MANAGED,
2482 device, NULL, NULL, NULL, NULL, &mesh);
2483 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2485 hr = D3DXLoadMeshFromXInMemory(NULL, sizeof(simple_xfile) - 1, D3DXMESH_MANAGED,
2486 device, NULL, NULL, NULL, NULL, &mesh);
2487 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2489 hr = D3DXLoadMeshFromXInMemory(simple_xfile, 0, D3DXMESH_MANAGED,
2490 device, NULL, NULL, NULL, NULL, &mesh);
2491 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2493 hr = D3DXLoadMeshFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1, D3DXMESH_MANAGED,
2494 device, NULL, NULL, NULL, NULL, NULL);
2495 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2497 hr = D3DXLoadMeshFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1, D3DXMESH_MANAGED,
2498 NULL, NULL, NULL, NULL, NULL, &mesh);
2499 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2501 hr = D3DXLoadMeshFromXInMemory(empty_xfile, sizeof(empty_xfile) - 1, D3DXMESH_MANAGED,
2502 device, NULL, NULL, NULL, NULL, &mesh);
2503 ok(hr == E_FAIL, "Expected E_FAIL, got %#x\n", hr);
2505 hr = D3DXLoadMeshFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1, D3DXMESH_MANAGED,
2506 device, NULL, NULL, NULL, NULL, &mesh);
2507 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2508 if (SUCCEEDED(hr))
2509 IUnknown_Release(mesh);
2511 test_LoadMeshFromX(device, simple_xfile, simple_vertex_buffer, simple_fvf, simple_index_buffer, default_materials, TRUE);
2512 test_LoadMeshFromX(device, box_xfile, box_vertex_buffer, box_fvf, box_index_buffer, box_materials, TRUE);
2513 test_LoadMeshFromX(device, framed_xfile, merged_vertex_buffer, framed_fvf, merged_index_buffer, default_materials, FALSE);
2515 free_test_context(test_context);
2518 static BOOL compute_box(struct mesh *mesh, float width, float height, float depth)
2520 unsigned int i, face;
2521 static const D3DXVECTOR3 unit_box[] =
2523 {-1.0f, -1.0f, -1.0f}, {-1.0f, -1.0f, 1.0f}, {-1.0f, 1.0f, 1.0f}, {-1.0f, 1.0f, -1.0f},
2524 {-1.0f, 1.0f, -1.0f}, {-1.0f, 1.0f, 1.0f}, { 1.0f, 1.0f, 1.0f}, { 1.0f, 1.0f, -1.0f},
2525 { 1.0f, 1.0f, -1.0f}, { 1.0f, 1.0f, 1.0f}, { 1.0f, -1.0f, 1.0f}, { 1.0f, -1.0f, -1.0f},
2526 {-1.0f, -1.0f, 1.0f}, {-1.0f, -1.0f, -1.0f}, { 1.0f, -1.0f, -1.0f}, { 1.0f, -1.0f, 1.0f},
2527 {-1.0f, -1.0f, 1.0f}, { 1.0f, -1.0f, 1.0f}, { 1.0f, 1.0f, 1.0f}, {-1.0f, 1.0f, 1.0f},
2528 {-1.0f, -1.0f, -1.0f}, {-1.0f, 1.0f, -1.0f}, { 1.0f, 1.0f, -1.0f}, { 1.0f, -1.0f, -1.0f}
2530 static const D3DXVECTOR3 normals[] =
2532 {-1.0f, 0.0f, 0.0f}, { 0.0f, 1.0f, 0.0f}, { 1.0f, 0.0f, 0.0f},
2533 { 0.0f, -1.0f, 0.0f}, { 0.0f, 0.0f, 1.0f}, { 0.0f, 0.0f, -1.0f}
2536 if (!new_mesh(mesh, 24, 12))
2538 return FALSE;
2541 width /= 2.0f;
2542 height /= 2.0f;
2543 depth /= 2.0f;
2545 for (i = 0; i < 24; i++)
2547 mesh->vertices[i].position.x = width * unit_box[i].x;
2548 mesh->vertices[i].position.y = height * unit_box[i].y;
2549 mesh->vertices[i].position.z = depth * unit_box[i].z;
2550 mesh->vertices[i].normal.x = normals[i / 4].x;
2551 mesh->vertices[i].normal.y = normals[i / 4].y;
2552 mesh->vertices[i].normal.z = normals[i / 4].z;
2555 face = 0;
2556 for (i = 0; i < 12; i++)
2558 mesh->faces[i][0] = face++;
2559 mesh->faces[i][1] = face++;
2560 mesh->faces[i][2] = (i % 2) ? face - 4 : face;
2563 return TRUE;
2566 static void test_box(IDirect3DDevice9 *device, float width, float height, float depth)
2568 HRESULT hr;
2569 ID3DXMesh *box;
2570 struct mesh mesh;
2571 char name[256];
2573 hr = D3DXCreateBox(device, width, height, depth, &box, NULL);
2574 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
2575 if (hr != D3D_OK)
2577 skip("Couldn't create box\n");
2578 return;
2581 if (!compute_box(&mesh, width, height, depth))
2583 skip("Couldn't create mesh\n");
2584 box->lpVtbl->Release(box);
2585 return;
2588 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
2590 sprintf(name, "box (%g, %g, %g)", width, height, depth);
2591 compare_mesh(name, box, &mesh);
2593 free_mesh(&mesh);
2595 box->lpVtbl->Release(box);
2597 static void D3DXCreateBoxTest(void)
2599 HRESULT hr;
2600 IDirect3DDevice9* device;
2601 ID3DXMesh* box;
2602 ID3DXBuffer* ppBuffer;
2603 DWORD *buffer;
2604 static const DWORD adjacency[36]=
2605 {6, 9, 1, 2, 10, 0,
2606 1, 9, 3, 4, 10, 2,
2607 3, 8, 5, 7, 11, 4,
2608 0, 11, 7, 5, 8, 6,
2609 7, 4, 9, 2, 0, 8,
2610 1, 3, 11, 5, 6, 10};
2611 unsigned int i;
2612 struct test_context *test_context;
2614 if (!(test_context = new_test_context()))
2616 skip("Couldn't create test context\n");
2617 return;
2619 device = test_context->device;
2621 hr = D3DXCreateBox(device,2.0f,20.0f,4.9f,NULL, &ppBuffer);
2622 ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2624 hr = D3DXCreateBox(NULL,22.0f,20.0f,4.9f,&box, &ppBuffer);
2625 ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2627 hr = D3DXCreateBox(device,-2.0f,20.0f,4.9f,&box, &ppBuffer);
2628 ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2630 hr = D3DXCreateBox(device,22.0f,-20.0f,4.9f,&box, &ppBuffer);
2631 ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2633 hr = D3DXCreateBox(device,22.0f,20.0f,-4.9f,&box, &ppBuffer);
2634 ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2636 ppBuffer = NULL;
2637 hr = D3DXCreateBox(device,10.9f,20.0f,4.9f,&box, &ppBuffer);
2638 ok(hr==D3D_OK, "Expected D3D_OK, received %#x\n", hr);
2640 buffer = ID3DXBuffer_GetBufferPointer(ppBuffer);
2641 for(i=0; i<36; i++)
2642 ok(adjacency[i]==buffer[i], "expected adjacency %d: %#x, received %#x\n",i,adjacency[i], buffer[i]);
2644 box->lpVtbl->Release(box);
2645 ID3DXBuffer_Release(ppBuffer);
2647 test_box(device, 10.9f, 20.0f, 4.9f);
2649 free_test_context(test_context);
2652 static BOOL compute_polygon(struct mesh *mesh, float length, unsigned int sides)
2654 unsigned int i;
2655 float scale;
2657 if (!new_mesh(mesh, sides + 1, sides))
2658 return FALSE;
2660 scale = 0.5f * length / sinf(D3DX_PI / sides);
2662 mesh->vertices[0].position.x = 0.0f;
2663 mesh->vertices[0].position.y = 0.0f;
2664 mesh->vertices[0].position.z = 0.0f;
2665 mesh->vertices[0].normal.x = 0.0f;
2666 mesh->vertices[0].normal.y = 0.0f;
2667 mesh->vertices[0].normal.z = 1.0f;
2669 for (i = 0; i < sides; ++i)
2671 mesh->vertices[i + 1].position.x = cosf(2.0f * D3DX_PI * i / sides) * scale;
2672 mesh->vertices[i + 1].position.y = sinf(2.0f * D3DX_PI * i / sides) * scale;
2673 mesh->vertices[i + 1].position.z = 0.0f;
2674 mesh->vertices[i + 1].normal.x = 0.0f;
2675 mesh->vertices[i + 1].normal.y = 0.0f;
2676 mesh->vertices[i + 1].normal.z = 1.0f;
2678 mesh->faces[i][0] = 0;
2679 mesh->faces[i][1] = i + 1;
2680 mesh->faces[i][2] = i + 2;
2683 mesh->faces[sides - 1][2] = 1;
2685 return TRUE;
2688 static void test_polygon(IDirect3DDevice9 *device, float length, unsigned int sides)
2690 HRESULT hr;
2691 ID3DXMesh *polygon;
2692 struct mesh mesh;
2693 char name[64];
2695 hr = D3DXCreatePolygon(device, length, sides, &polygon, NULL);
2696 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
2697 if (hr != D3D_OK)
2699 skip("Couldn't create polygon\n");
2700 return;
2703 if (!compute_polygon(&mesh, length, sides))
2705 skip("Couldn't create mesh\n");
2706 polygon->lpVtbl->Release(polygon);
2707 return;
2710 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
2712 sprintf(name, "polygon (%g, %u)", length, sides);
2713 compare_mesh(name, polygon, &mesh);
2715 free_mesh(&mesh);
2717 polygon->lpVtbl->Release(polygon);
2720 static void D3DXCreatePolygonTest(void)
2722 HRESULT hr;
2723 IDirect3DDevice9 *device;
2724 ID3DXMesh *polygon;
2725 ID3DXBuffer *adjacency;
2726 DWORD (*buffer)[3], buffer_size;
2727 unsigned int i;
2728 struct test_context *test_context;
2730 if (!(test_context = new_test_context()))
2732 skip("Couldn't create test context\n");
2733 return;
2735 device = test_context->device;
2737 hr = D3DXCreatePolygon(device, 2.0f, 11, NULL, &adjacency);
2738 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2740 hr = D3DXCreatePolygon(NULL, 2.0f, 11, &polygon, &adjacency);
2741 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2743 hr = D3DXCreatePolygon(device, -2.0f, 11, &polygon, &adjacency);
2744 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2746 polygon = (void *)0xdeadbeef;
2747 adjacency = (void *)0xdeadbeef;
2748 hr = D3DXCreatePolygon(device, 2.0f, 0, &polygon, &adjacency);
2749 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2750 ok(polygon == (void *)0xdeadbeef, "Polygon was changed to %p\n", polygon);
2751 ok(adjacency == (void *)0xdeadbeef, "Adjacency was changed to %p\n", adjacency);
2753 hr = D3DXCreatePolygon(device, 2.0f, 2, &polygon, &adjacency);
2754 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2756 adjacency = NULL;
2757 hr = D3DXCreatePolygon(device, 3.0f, 11, &polygon, &adjacency);
2758 ok(hr == D3D_OK, "Expected D3D_OK, received %#x\n", hr);
2760 buffer_size = ID3DXBuffer_GetBufferSize(adjacency);
2761 ok(buffer_size == 33 * sizeof(DWORD), "Wrong adjacency buffer size %u\n", buffer_size);
2763 buffer = ID3DXBuffer_GetBufferPointer(adjacency);
2764 for (i = 0; i < 11; ++i)
2766 ok(buffer[i][0] == (i + 10) % 11, "Wrong adjacency[%d][0] = %u\n", i, buffer[i][0]);
2767 ok(buffer[i][1] == ~0U, "Wrong adjacency[%d][1] = %u\n", i, buffer[i][1]);
2768 ok(buffer[i][2] == (i + 1) % 11, "Wrong adjacency[%d][2] = %u\n", i, buffer[i][2]);
2771 polygon->lpVtbl->Release(polygon);
2772 ID3DXBuffer_Release(adjacency);
2774 test_polygon(device, 2.0f, 3);
2775 test_polygon(device, 10.0f, 3);
2776 test_polygon(device, 10.0f, 5);
2777 test_polygon(device, 10.0f, 10);
2778 test_polygon(device, 20.0f, 10);
2780 free_test_context(test_context);
2783 struct sincos_table
2785 float *sin;
2786 float *cos;
2789 static void free_sincos_table(struct sincos_table *sincos_table)
2791 HeapFree(GetProcessHeap(), 0, sincos_table->cos);
2792 HeapFree(GetProcessHeap(), 0, sincos_table->sin);
2795 /* pre compute sine and cosine tables; caller must free */
2796 static BOOL compute_sincos_table(struct sincos_table *sincos_table, float angle_start, float angle_step, int n)
2798 float angle;
2799 int i;
2801 sincos_table->sin = HeapAlloc(GetProcessHeap(), 0, n * sizeof(*sincos_table->sin));
2802 if (!sincos_table->sin)
2804 return FALSE;
2806 sincos_table->cos = HeapAlloc(GetProcessHeap(), 0, n * sizeof(*sincos_table->cos));
2807 if (!sincos_table->cos)
2809 HeapFree(GetProcessHeap(), 0, sincos_table->sin);
2810 return FALSE;
2813 angle = angle_start;
2814 for (i = 0; i < n; i++)
2816 sincos_table->sin[i] = sin(angle);
2817 sincos_table->cos[i] = cos(angle);
2818 angle += angle_step;
2821 return TRUE;
2824 static WORD vertex_index(UINT slices, int slice, int stack)
2826 return stack*slices+slice+1;
2829 /* slices = subdivisions along xy plane, stacks = subdivisions along z axis */
2830 static BOOL compute_sphere(struct mesh *mesh, FLOAT radius, UINT slices, UINT stacks)
2832 float theta_step, theta_start;
2833 struct sincos_table theta;
2834 float phi_step, phi_start;
2835 struct sincos_table phi;
2836 DWORD number_of_vertices, number_of_faces;
2837 DWORD vertex, face;
2838 int slice, stack;
2840 /* theta = angle on xy plane wrt x axis */
2841 theta_step = D3DX_PI / stacks;
2842 theta_start = theta_step;
2844 /* phi = angle on xz plane wrt z axis */
2845 phi_step = -2 * D3DX_PI / slices;
2846 phi_start = D3DX_PI / 2;
2848 if (!compute_sincos_table(&theta, theta_start, theta_step, stacks))
2850 return FALSE;
2852 if (!compute_sincos_table(&phi, phi_start, phi_step, slices))
2854 free_sincos_table(&theta);
2855 return FALSE;
2858 number_of_vertices = 2 + slices * (stacks-1);
2859 number_of_faces = 2 * slices + (stacks - 2) * (2 * slices);
2861 if (!new_mesh(mesh, number_of_vertices, number_of_faces))
2863 free_sincos_table(&phi);
2864 free_sincos_table(&theta);
2865 return FALSE;
2868 vertex = 0;
2869 face = 0;
2871 mesh->vertices[vertex].normal.x = 0.0f;
2872 mesh->vertices[vertex].normal.y = 0.0f;
2873 mesh->vertices[vertex].normal.z = 1.0f;
2874 mesh->vertices[vertex].position.x = 0.0f;
2875 mesh->vertices[vertex].position.y = 0.0f;
2876 mesh->vertices[vertex].position.z = radius;
2877 vertex++;
2879 for (stack = 0; stack < stacks - 1; stack++)
2881 for (slice = 0; slice < slices; slice++)
2883 mesh->vertices[vertex].normal.x = theta.sin[stack] * phi.cos[slice];
2884 mesh->vertices[vertex].normal.y = theta.sin[stack] * phi.sin[slice];
2885 mesh->vertices[vertex].normal.z = theta.cos[stack];
2886 mesh->vertices[vertex].position.x = radius * theta.sin[stack] * phi.cos[slice];
2887 mesh->vertices[vertex].position.y = radius * theta.sin[stack] * phi.sin[slice];
2888 mesh->vertices[vertex].position.z = radius * theta.cos[stack];
2889 vertex++;
2891 if (slice > 0)
2893 if (stack == 0)
2895 /* top stack is triangle fan */
2896 mesh->faces[face][0] = 0;
2897 mesh->faces[face][1] = slice + 1;
2898 mesh->faces[face][2] = slice;
2899 face++;
2901 else
2903 /* stacks in between top and bottom are quad strips */
2904 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
2905 mesh->faces[face][1] = vertex_index(slices, slice, stack-1);
2906 mesh->faces[face][2] = vertex_index(slices, slice-1, stack);
2907 face++;
2909 mesh->faces[face][0] = vertex_index(slices, slice, stack-1);
2910 mesh->faces[face][1] = vertex_index(slices, slice, stack);
2911 mesh->faces[face][2] = vertex_index(slices, slice-1, stack);
2912 face++;
2917 if (stack == 0)
2919 mesh->faces[face][0] = 0;
2920 mesh->faces[face][1] = 1;
2921 mesh->faces[face][2] = slice;
2922 face++;
2924 else
2926 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
2927 mesh->faces[face][1] = vertex_index(slices, 0, stack-1);
2928 mesh->faces[face][2] = vertex_index(slices, slice-1, stack);
2929 face++;
2931 mesh->faces[face][0] = vertex_index(slices, 0, stack-1);
2932 mesh->faces[face][1] = vertex_index(slices, 0, stack);
2933 mesh->faces[face][2] = vertex_index(slices, slice-1, stack);
2934 face++;
2938 mesh->vertices[vertex].position.x = 0.0f;
2939 mesh->vertices[vertex].position.y = 0.0f;
2940 mesh->vertices[vertex].position.z = -radius;
2941 mesh->vertices[vertex].normal.x = 0.0f;
2942 mesh->vertices[vertex].normal.y = 0.0f;
2943 mesh->vertices[vertex].normal.z = -1.0f;
2945 /* bottom stack is triangle fan */
2946 for (slice = 1; slice < slices; slice++)
2948 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
2949 mesh->faces[face][1] = vertex_index(slices, slice, stack-1);
2950 mesh->faces[face][2] = vertex;
2951 face++;
2954 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
2955 mesh->faces[face][1] = vertex_index(slices, 0, stack-1);
2956 mesh->faces[face][2] = vertex;
2958 free_sincos_table(&phi);
2959 free_sincos_table(&theta);
2961 return TRUE;
2964 static void test_sphere(IDirect3DDevice9 *device, FLOAT radius, UINT slices, UINT stacks)
2966 HRESULT hr;
2967 ID3DXMesh *sphere;
2968 struct mesh mesh;
2969 char name[256];
2971 hr = D3DXCreateSphere(device, radius, slices, stacks, &sphere, NULL);
2972 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
2973 if (hr != D3D_OK)
2975 skip("Couldn't create sphere\n");
2976 return;
2979 if (!compute_sphere(&mesh, radius, slices, stacks))
2981 skip("Couldn't create mesh\n");
2982 sphere->lpVtbl->Release(sphere);
2983 return;
2986 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
2988 sprintf(name, "sphere (%g, %u, %u)", radius, slices, stacks);
2989 compare_mesh(name, sphere, &mesh);
2991 free_mesh(&mesh);
2993 sphere->lpVtbl->Release(sphere);
2996 static void D3DXCreateSphereTest(void)
2998 HRESULT hr;
2999 IDirect3DDevice9* device;
3000 ID3DXMesh* sphere = NULL;
3001 struct test_context *test_context;
3003 hr = D3DXCreateSphere(NULL, 0.0f, 0, 0, NULL, NULL);
3004 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3006 hr = D3DXCreateSphere(NULL, 0.1f, 0, 0, NULL, NULL);
3007 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3009 hr = D3DXCreateSphere(NULL, 0.0f, 1, 0, NULL, NULL);
3010 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3012 hr = D3DXCreateSphere(NULL, 0.0f, 0, 1, NULL, NULL);
3013 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3015 if (!(test_context = new_test_context()))
3017 skip("Couldn't create test context\n");
3018 return;
3020 device = test_context->device;
3022 hr = D3DXCreateSphere(device, 1.0f, 1, 1, &sphere, NULL);
3023 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3025 hr = D3DXCreateSphere(device, 1.0f, 2, 1, &sphere, NULL);
3026 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
3028 hr = D3DXCreateSphere(device, 1.0f, 1, 2, &sphere, NULL);
3029 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
3031 hr = D3DXCreateSphere(device, -0.1f, 1, 2, &sphere, NULL);
3032 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
3034 test_sphere(device, 0.0f, 2, 2);
3035 test_sphere(device, 1.0f, 2, 2);
3036 test_sphere(device, 1.0f, 3, 2);
3037 test_sphere(device, 1.0f, 4, 4);
3038 test_sphere(device, 1.0f, 3, 4);
3039 test_sphere(device, 5.0f, 6, 7);
3040 test_sphere(device, 10.0f, 11, 12);
3042 free_test_context(test_context);
3045 static BOOL compute_cylinder(struct mesh *mesh, FLOAT radius1, FLOAT radius2, FLOAT length, UINT slices, UINT stacks)
3047 float theta_step, theta_start;
3048 struct sincos_table theta;
3049 FLOAT delta_radius, radius, radius_step;
3050 FLOAT z, z_step, z_normal;
3051 DWORD number_of_vertices, number_of_faces;
3052 DWORD vertex, face;
3053 int slice, stack;
3055 /* theta = angle on xy plane wrt x axis */
3056 theta_step = -2 * D3DX_PI / slices;
3057 theta_start = D3DX_PI / 2;
3059 if (!compute_sincos_table(&theta, theta_start, theta_step, slices))
3061 return FALSE;
3064 number_of_vertices = 2 + (slices * (3 + stacks));
3065 number_of_faces = 2 * slices + stacks * (2 * slices);
3067 if (!new_mesh(mesh, number_of_vertices, number_of_faces))
3069 free_sincos_table(&theta);
3070 return FALSE;
3073 vertex = 0;
3074 face = 0;
3076 delta_radius = radius1 - radius2;
3077 radius = radius1;
3078 radius_step = delta_radius / stacks;
3080 z = -length / 2;
3081 z_step = length / stacks;
3082 z_normal = delta_radius / length;
3083 if (isnan(z_normal))
3085 z_normal = 0.0f;
3088 mesh->vertices[vertex].normal.x = 0.0f;
3089 mesh->vertices[vertex].normal.y = 0.0f;
3090 mesh->vertices[vertex].normal.z = -1.0f;
3091 mesh->vertices[vertex].position.x = 0.0f;
3092 mesh->vertices[vertex].position.y = 0.0f;
3093 mesh->vertices[vertex++].position.z = z;
3095 for (slice = 0; slice < slices; slice++, vertex++)
3097 mesh->vertices[vertex].normal.x = 0.0f;
3098 mesh->vertices[vertex].normal.y = 0.0f;
3099 mesh->vertices[vertex].normal.z = -1.0f;
3100 mesh->vertices[vertex].position.x = radius * theta.cos[slice];
3101 mesh->vertices[vertex].position.y = radius * theta.sin[slice];
3102 mesh->vertices[vertex].position.z = z;
3104 if (slice > 0)
3106 mesh->faces[face][0] = 0;
3107 mesh->faces[face][1] = slice;
3108 mesh->faces[face++][2] = slice + 1;
3112 mesh->faces[face][0] = 0;
3113 mesh->faces[face][1] = slice;
3114 mesh->faces[face++][2] = 1;
3116 for (stack = 1; stack <= stacks+1; stack++)
3118 for (slice = 0; slice < slices; slice++, vertex++)
3120 mesh->vertices[vertex].normal.x = theta.cos[slice];
3121 mesh->vertices[vertex].normal.y = theta.sin[slice];
3122 mesh->vertices[vertex].normal.z = z_normal;
3123 D3DXVec3Normalize(&mesh->vertices[vertex].normal, &mesh->vertices[vertex].normal);
3124 mesh->vertices[vertex].position.x = radius * theta.cos[slice];
3125 mesh->vertices[vertex].position.y = radius * theta.sin[slice];
3126 mesh->vertices[vertex].position.z = z;
3128 if (stack > 1 && slice > 0)
3130 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
3131 mesh->faces[face][1] = vertex_index(slices, slice-1, stack);
3132 mesh->faces[face++][2] = vertex_index(slices, slice, stack-1);
3134 mesh->faces[face][0] = vertex_index(slices, slice, stack-1);
3135 mesh->faces[face][1] = vertex_index(slices, slice-1, stack);
3136 mesh->faces[face++][2] = vertex_index(slices, slice, stack);
3140 if (stack > 1)
3142 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
3143 mesh->faces[face][1] = vertex_index(slices, slice-1, stack);
3144 mesh->faces[face++][2] = vertex_index(slices, 0, stack-1);
3146 mesh->faces[face][0] = vertex_index(slices, 0, stack-1);
3147 mesh->faces[face][1] = vertex_index(slices, slice-1, stack);
3148 mesh->faces[face++][2] = vertex_index(slices, 0, stack);
3151 if (stack < stacks + 1)
3153 z += z_step;
3154 radius -= radius_step;
3158 for (slice = 0; slice < slices; slice++, vertex++)
3160 mesh->vertices[vertex].normal.x = 0.0f;
3161 mesh->vertices[vertex].normal.y = 0.0f;
3162 mesh->vertices[vertex].normal.z = 1.0f;
3163 mesh->vertices[vertex].position.x = radius * theta.cos[slice];
3164 mesh->vertices[vertex].position.y = radius * theta.sin[slice];
3165 mesh->vertices[vertex].position.z = z;
3167 if (slice > 0)
3169 mesh->faces[face][0] = vertex_index(slices, slice-1, stack);
3170 mesh->faces[face][1] = number_of_vertices - 1;
3171 mesh->faces[face++][2] = vertex_index(slices, slice, stack);
3175 mesh->vertices[vertex].position.x = 0.0f;
3176 mesh->vertices[vertex].position.y = 0.0f;
3177 mesh->vertices[vertex].position.z = z;
3178 mesh->vertices[vertex].normal.x = 0.0f;
3179 mesh->vertices[vertex].normal.y = 0.0f;
3180 mesh->vertices[vertex].normal.z = 1.0f;
3182 mesh->faces[face][0] = vertex_index(slices, slice-1, stack);
3183 mesh->faces[face][1] = number_of_vertices - 1;
3184 mesh->faces[face][2] = vertex_index(slices, 0, stack);
3186 free_sincos_table(&theta);
3188 return TRUE;
3191 static void test_cylinder(IDirect3DDevice9 *device, FLOAT radius1, FLOAT radius2, FLOAT length, UINT slices, UINT stacks)
3193 HRESULT hr;
3194 ID3DXMesh *cylinder;
3195 struct mesh mesh;
3196 char name[256];
3198 hr = D3DXCreateCylinder(device, radius1, radius2, length, slices, stacks, &cylinder, NULL);
3199 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
3200 if (hr != D3D_OK)
3202 skip("Couldn't create cylinder\n");
3203 return;
3206 if (!compute_cylinder(&mesh, radius1, radius2, length, slices, stacks))
3208 skip("Couldn't create mesh\n");
3209 cylinder->lpVtbl->Release(cylinder);
3210 return;
3213 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
3215 sprintf(name, "cylinder (%g, %g, %g, %u, %u)", radius1, radius2, length, slices, stacks);
3216 compare_mesh(name, cylinder, &mesh);
3218 free_mesh(&mesh);
3220 cylinder->lpVtbl->Release(cylinder);
3223 static void D3DXCreateCylinderTest(void)
3225 HRESULT hr;
3226 IDirect3DDevice9* device;
3227 ID3DXMesh* cylinder = NULL;
3228 struct test_context *test_context;
3230 hr = D3DXCreateCylinder(NULL, 0.0f, 0.0f, 0.0f, 0, 0, NULL, NULL);
3231 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3233 hr = D3DXCreateCylinder(NULL, 1.0f, 1.0f, 1.0f, 2, 1, &cylinder, NULL);
3234 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3236 if (!(test_context = new_test_context()))
3238 skip("Couldn't create test context\n");
3239 return;
3241 device = test_context->device;
3243 hr = D3DXCreateCylinder(device, -0.1f, 1.0f, 1.0f, 2, 1, &cylinder, NULL);
3244 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3246 hr = D3DXCreateCylinder(device, 0.0f, 1.0f, 1.0f, 2, 1, &cylinder, NULL);
3247 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n",hr);
3249 if (SUCCEEDED(hr) && cylinder)
3251 cylinder->lpVtbl->Release(cylinder);
3254 hr = D3DXCreateCylinder(device, 1.0f, -0.1f, 1.0f, 2, 1, &cylinder, NULL);
3255 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3257 hr = D3DXCreateCylinder(device, 1.0f, 0.0f, 1.0f, 2, 1, &cylinder, NULL);
3258 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n",hr);
3260 if (SUCCEEDED(hr) && cylinder)
3262 cylinder->lpVtbl->Release(cylinder);
3265 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, -0.1f, 2, 1, &cylinder, NULL);
3266 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3268 /* Test with length == 0.0f succeeds */
3269 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, 0.0f, 2, 1, &cylinder, NULL);
3270 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n",hr);
3272 if (SUCCEEDED(hr) && cylinder)
3274 cylinder->lpVtbl->Release(cylinder);
3277 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, 1.0f, 1, 1, &cylinder, NULL);
3278 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3280 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, 1.0f, 2, 0, &cylinder, NULL);
3281 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3283 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, 1.0f, 2, 1, NULL, NULL);
3284 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3286 test_cylinder(device, 0.0f, 0.0f, 0.0f, 2, 1);
3287 test_cylinder(device, 1.0f, 1.0f, 1.0f, 2, 1);
3288 test_cylinder(device, 1.0f, 1.0f, 2.0f, 3, 4);
3289 test_cylinder(device, 3.0f, 2.0f, 4.0f, 3, 4);
3290 test_cylinder(device, 2.0f, 3.0f, 4.0f, 3, 4);
3291 test_cylinder(device, 3.0f, 4.0f, 5.0f, 11, 20);
3293 free_test_context(test_context);
3296 static BOOL compute_torus(struct mesh *mesh, float innerradius, float outerradius, UINT sides, UINT rings)
3298 float phi, phi_step, sin_phi, cos_phi;
3299 float theta, theta_step, sin_theta, cos_theta;
3300 unsigned int numvert, numfaces, i, j;
3302 numvert = sides * rings;
3303 numfaces = numvert * 2;
3305 if (!new_mesh(mesh, numvert, numfaces))
3306 return FALSE;
3308 phi_step = D3DX_PI / sides * 2.0f;
3309 theta_step = D3DX_PI / rings * -2.0f;
3311 theta = 0.0f;
3313 for (i = 0; i < rings; ++i)
3315 phi = 0.0f;
3317 cos_theta = cosf(theta);
3318 sin_theta = sinf(theta);
3320 for (j = 0; j < sides; ++j)
3322 sin_phi = sinf(phi);
3323 cos_phi = cosf(phi);
3325 mesh->vertices[i * sides + j].position.x = (innerradius * cos_phi + outerradius) * cos_theta;
3326 mesh->vertices[i * sides + j].position.y = (innerradius * cos_phi + outerradius) * sin_theta;
3327 mesh->vertices[i * sides + j].position.z = innerradius * sin_phi;
3328 mesh->vertices[i * sides + j].normal.x = cos_phi * cos_theta;
3329 mesh->vertices[i * sides + j].normal.y = cos_phi * sin_theta;
3330 mesh->vertices[i * sides + j].normal.z = sin_phi;
3332 phi += phi_step;
3335 theta += theta_step;
3338 for (i = 0; i < numfaces - sides * 2; ++i)
3340 mesh->faces[i][0] = i % 2 ? i / 2 + sides : i / 2;
3341 mesh->faces[i][1] = (i / 2 + 1) % sides ? i / 2 + 1 : i / 2 + 1 - sides;
3342 mesh->faces[i][2] = (i + 1) % (sides * 2) ? (i + 1) / 2 + sides : (i + 1) / 2;
3345 for (j = 0; i < numfaces; ++i, ++j)
3347 mesh->faces[i][0] = i % 2 ? j / 2 : i / 2;
3348 mesh->faces[i][1] = (i / 2 + 1) % sides ? i / 2 + 1 : i / 2 + 1 - sides;
3349 mesh->faces[i][2] = i == numfaces - 1 ? 0 : (j + 1) / 2;
3352 return TRUE;
3355 static void test_torus(IDirect3DDevice9 *device, float innerradius, float outerradius, UINT sides, UINT rings)
3357 HRESULT hr;
3358 ID3DXMesh *torus;
3359 struct mesh mesh;
3360 char name[256];
3362 hr = D3DXCreateTorus(device, innerradius, outerradius, sides, rings, &torus, NULL);
3363 ok(hr == D3D_OK, "Got result %#x, expected 0 (D3D_OK)\n", hr);
3364 if (hr != D3D_OK)
3366 skip("Couldn't create torus\n");
3367 return;
3370 if (!compute_torus(&mesh, innerradius, outerradius, sides, rings))
3372 skip("Couldn't create mesh\n");
3373 torus->lpVtbl->Release(torus);
3374 return;
3377 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
3379 sprintf(name, "torus (%g, %g, %u, %u)", innerradius, outerradius, sides, rings);
3380 compare_mesh(name, torus, &mesh);
3382 free_mesh(&mesh);
3384 torus->lpVtbl->Release(torus);
3387 static void D3DXCreateTorusTest(void)
3389 HRESULT hr;
3390 IDirect3DDevice9* device;
3391 ID3DXMesh* torus = NULL;
3392 struct test_context *test_context;
3394 if (!(test_context = new_test_context()))
3396 skip("Couldn't create test context\n");
3397 return;
3399 device = test_context->device;
3401 hr = D3DXCreateTorus(NULL, 0.0f, 0.0f, 3, 3, &torus, NULL);
3402 ok(hr == D3DERR_INVALIDCALL, "Got result %#x, expected %#x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
3404 hr = D3DXCreateTorus(device, -1.0f, 0.0f, 3, 3, &torus, NULL);
3405 ok(hr == D3DERR_INVALIDCALL, "Got result %#x, expected %#x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
3407 hr = D3DXCreateTorus(device, 0.0f, -1.0f, 3, 3, &torus, NULL);
3408 ok(hr == D3DERR_INVALIDCALL, "Got result %#x, expected %#x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
3410 hr = D3DXCreateTorus(device, 0.0f, 0.0f, 2, 3, &torus, NULL);
3411 ok(hr == D3DERR_INVALIDCALL, "Got result %#x, expected %#x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
3413 hr = D3DXCreateTorus(device, 0.0f, 0.0f, 3, 2, &torus, NULL);
3414 ok(hr == D3DERR_INVALIDCALL, "Got result %#x, expected %#x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
3416 hr = D3DXCreateTorus(device, 0.0f, 0.0f, 3, 3, NULL, NULL);
3417 ok(hr == D3DERR_INVALIDCALL, "Got result %#x, expected %#x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
3419 test_torus(device, 0.0f, 0.0f, 3, 3);
3420 test_torus(device, 1.0f, 1.0f, 3, 3);
3421 test_torus(device, 1.0f, 1.0f, 32, 64);
3422 test_torus(device, 0.0f, 1.0f, 5, 5);
3423 test_torus(device, 1.0f, 0.0f, 5, 5);
3424 test_torus(device, 5.0f, 0.2f, 8, 8);
3425 test_torus(device, 0.2f, 1.0f, 60, 3);
3426 test_torus(device, 0.2f, 1.0f, 8, 70);
3428 free_test_context(test_context);
3431 struct dynamic_array
3433 int count, capacity;
3434 void *items;
3437 enum pointtype {
3438 POINTTYPE_CURVE = 0,
3439 POINTTYPE_CORNER,
3440 POINTTYPE_CURVE_START,
3441 POINTTYPE_CURVE_END,
3442 POINTTYPE_CURVE_MIDDLE,
3445 struct point2d
3447 D3DXVECTOR2 pos;
3448 enum pointtype corner;
3451 /* is a dynamic_array */
3452 struct outline
3454 int count, capacity;
3455 struct point2d *items;
3458 /* is a dynamic_array */
3459 struct outline_array
3461 int count, capacity;
3462 struct outline *items;
3465 struct glyphinfo
3467 struct outline_array outlines;
3468 float offset_x;
3471 static BOOL reserve(struct dynamic_array *array, int count, int itemsize)
3473 if (count > array->capacity) {
3474 void *new_buffer;
3475 int new_capacity;
3476 if (array->items && array->capacity) {
3477 new_capacity = max(array->capacity * 2, count);
3478 new_buffer = HeapReAlloc(GetProcessHeap(), 0, array->items, new_capacity * itemsize);
3479 } else {
3480 new_capacity = max(16, count);
3481 new_buffer = HeapAlloc(GetProcessHeap(), 0, new_capacity * itemsize);
3483 if (!new_buffer)
3484 return FALSE;
3485 array->items = new_buffer;
3486 array->capacity = new_capacity;
3488 return TRUE;
3491 static struct point2d *add_point(struct outline *array)
3493 struct point2d *item;
3495 if (!reserve((struct dynamic_array *)array, array->count + 1, sizeof(array->items[0])))
3496 return NULL;
3498 item = &array->items[array->count++];
3499 ZeroMemory(item, sizeof(*item));
3500 return item;
3503 static struct outline *add_outline(struct outline_array *array)
3505 struct outline *item;
3507 if (!reserve((struct dynamic_array *)array, array->count + 1, sizeof(array->items[0])))
3508 return NULL;
3510 item = &array->items[array->count++];
3511 ZeroMemory(item, sizeof(*item));
3512 return item;
3515 static inline D3DXVECTOR2 *convert_fixed_to_float(POINTFX *pt, int count, float emsquare)
3517 D3DXVECTOR2 *ret = (D3DXVECTOR2*)pt;
3518 while (count--) {
3519 D3DXVECTOR2 *pt_flt = (D3DXVECTOR2*)pt;
3520 pt_flt->x = (pt->x.value + pt->x.fract / (float)0x10000) / emsquare;
3521 pt_flt->y = (pt->y.value + pt->y.fract / (float)0x10000) / emsquare;
3522 pt++;
3524 return ret;
3527 static HRESULT add_bezier_points(struct outline *outline, const D3DXVECTOR2 *p1,
3528 const D3DXVECTOR2 *p2, const D3DXVECTOR2 *p3,
3529 float max_deviation)
3531 D3DXVECTOR2 split1 = {0, 0}, split2 = {0, 0}, middle, vec;
3532 float deviation;
3534 D3DXVec2Scale(&split1, D3DXVec2Add(&split1, p1, p2), 0.5f);
3535 D3DXVec2Scale(&split2, D3DXVec2Add(&split2, p2, p3), 0.5f);
3536 D3DXVec2Scale(&middle, D3DXVec2Add(&middle, &split1, &split2), 0.5f);
3538 deviation = D3DXVec2Length(D3DXVec2Subtract(&vec, &middle, p2));
3539 if (deviation < max_deviation) {
3540 struct point2d *pt = add_point(outline);
3541 if (!pt) return E_OUTOFMEMORY;
3542 pt->pos = *p2;
3543 pt->corner = POINTTYPE_CURVE;
3544 /* the end point is omitted because the end line merges into the next segment of
3545 * the split bezier curve, and the end of the split bezier curve is added outside
3546 * this recursive function. */
3547 } else {
3548 HRESULT hr = add_bezier_points(outline, p1, &split1, &middle, max_deviation);
3549 if (hr != S_OK) return hr;
3550 hr = add_bezier_points(outline, &middle, &split2, p3, max_deviation);
3551 if (hr != S_OK) return hr;
3554 return S_OK;
3557 static inline BOOL is_direction_similar(D3DXVECTOR2 *dir1, D3DXVECTOR2 *dir2, float cos_theta)
3559 /* dot product = cos(theta) */
3560 return D3DXVec2Dot(dir1, dir2) > cos_theta;
3563 static inline D3DXVECTOR2 *unit_vec2(D3DXVECTOR2 *dir, const D3DXVECTOR2 *pt1, const D3DXVECTOR2 *pt2)
3565 return D3DXVec2Normalize(D3DXVec2Subtract(dir, pt2, pt1), dir);
3568 static BOOL attempt_line_merge(struct outline *outline,
3569 int pt_index,
3570 const D3DXVECTOR2 *nextpt,
3571 BOOL to_curve)
3573 D3DXVECTOR2 curdir, lastdir;
3574 struct point2d *prevpt, *pt;
3575 BOOL ret = FALSE;
3576 const float cos_half = cos(D3DXToRadian(0.5f));
3578 pt = &outline->items[pt_index];
3579 pt_index = (pt_index - 1 + outline->count) % outline->count;
3580 prevpt = &outline->items[pt_index];
3582 if (to_curve)
3583 pt->corner = pt->corner != POINTTYPE_CORNER ? POINTTYPE_CURVE_MIDDLE : POINTTYPE_CURVE_START;
3585 if (outline->count < 2)
3586 return FALSE;
3588 /* remove last point if the next line continues the last line */
3589 unit_vec2(&lastdir, &prevpt->pos, &pt->pos);
3590 unit_vec2(&curdir, &pt->pos, nextpt);
3591 if (is_direction_similar(&lastdir, &curdir, cos_half))
3593 outline->count--;
3594 if (pt->corner == POINTTYPE_CURVE_END)
3595 prevpt->corner = pt->corner;
3596 if (prevpt->corner == POINTTYPE_CURVE_END && to_curve)
3597 prevpt->corner = POINTTYPE_CURVE_MIDDLE;
3598 pt = prevpt;
3600 ret = TRUE;
3601 if (outline->count < 2)
3602 return ret;
3604 pt_index = (pt_index - 1 + outline->count) % outline->count;
3605 prevpt = &outline->items[pt_index];
3606 unit_vec2(&lastdir, &prevpt->pos, &pt->pos);
3607 unit_vec2(&curdir, &pt->pos, nextpt);
3609 return ret;
3612 static HRESULT create_outline(struct glyphinfo *glyph, void *raw_outline, int datasize,
3613 float max_deviation, float emsquare)
3615 const float cos_45 = cos(D3DXToRadian(45.0f));
3616 const float cos_90 = cos(D3DXToRadian(90.0f));
3617 TTPOLYGONHEADER *header = (TTPOLYGONHEADER *)raw_outline;
3619 while ((char *)header < (char *)raw_outline + datasize)
3621 TTPOLYCURVE *curve = (TTPOLYCURVE *)(header + 1);
3622 struct point2d *lastpt, *pt;
3623 D3DXVECTOR2 lastdir;
3624 D3DXVECTOR2 *pt_flt;
3625 int j;
3626 struct outline *outline = add_outline(&glyph->outlines);
3628 if (!outline)
3629 return E_OUTOFMEMORY;
3631 pt = add_point(outline);
3632 if (!pt)
3633 return E_OUTOFMEMORY;
3634 pt_flt = convert_fixed_to_float(&header->pfxStart, 1, emsquare);
3635 pt->pos = *pt_flt;
3636 pt->corner = POINTTYPE_CORNER;
3638 if (header->dwType != TT_POLYGON_TYPE)
3639 trace("Unknown header type %d\n", header->dwType);
3641 while ((char *)curve < (char *)header + header->cb)
3643 D3DXVECTOR2 bezier_start = outline->items[outline->count - 1].pos;
3644 BOOL to_curve = curve->wType != TT_PRIM_LINE && curve->cpfx > 1;
3646 if (!curve->cpfx) {
3647 curve = (TTPOLYCURVE *)&curve->apfx[curve->cpfx];
3648 continue;
3651 pt_flt = convert_fixed_to_float(curve->apfx, curve->cpfx, emsquare);
3653 attempt_line_merge(outline, outline->count - 1, &pt_flt[0], to_curve);
3655 if (to_curve)
3657 HRESULT hr;
3658 int count = curve->cpfx;
3659 j = 0;
3661 while (count > 2)
3663 D3DXVECTOR2 bezier_end;
3665 D3DXVec2Scale(&bezier_end, D3DXVec2Add(&bezier_end, &pt_flt[j], &pt_flt[j+1]), 0.5f);
3666 hr = add_bezier_points(outline, &bezier_start, &pt_flt[j], &bezier_end, max_deviation);
3667 if (hr != S_OK)
3668 return hr;
3669 bezier_start = bezier_end;
3670 count--;
3671 j++;
3673 hr = add_bezier_points(outline, &bezier_start, &pt_flt[j], &pt_flt[j+1], max_deviation);
3674 if (hr != S_OK)
3675 return hr;
3677 pt = add_point(outline);
3678 if (!pt)
3679 return E_OUTOFMEMORY;
3680 j++;
3681 pt->pos = pt_flt[j];
3682 pt->corner = POINTTYPE_CURVE_END;
3683 } else {
3684 for (j = 0; j < curve->cpfx; j++)
3686 pt = add_point(outline);
3687 if (!pt)
3688 return E_OUTOFMEMORY;
3689 pt->pos = pt_flt[j];
3690 pt->corner = POINTTYPE_CORNER;
3694 curve = (TTPOLYCURVE *)&curve->apfx[curve->cpfx];
3697 /* remove last point if the next line continues the last line */
3698 if (outline->count >= 3) {
3699 BOOL to_curve;
3701 lastpt = &outline->items[outline->count - 1];
3702 pt = &outline->items[0];
3703 if (pt->pos.x == lastpt->pos.x && pt->pos.y == lastpt->pos.y) {
3704 if (lastpt->corner == POINTTYPE_CURVE_END)
3706 if (pt->corner == POINTTYPE_CURVE_START)
3707 pt->corner = POINTTYPE_CURVE_MIDDLE;
3708 else
3709 pt->corner = POINTTYPE_CURVE_END;
3711 outline->count--;
3712 lastpt = &outline->items[outline->count - 1];
3713 } else {
3714 /* outline closed with a line from end to start point */
3715 attempt_line_merge(outline, outline->count - 1, &pt->pos, FALSE);
3717 lastpt = &outline->items[0];
3718 to_curve = lastpt->corner != POINTTYPE_CORNER && lastpt->corner != POINTTYPE_CURVE_END;
3719 if (lastpt->corner == POINTTYPE_CURVE_START)
3720 lastpt->corner = POINTTYPE_CORNER;
3721 pt = &outline->items[1];
3722 if (attempt_line_merge(outline, 0, &pt->pos, to_curve))
3723 *lastpt = outline->items[outline->count];
3726 lastpt = &outline->items[outline->count - 1];
3727 pt = &outline->items[0];
3728 unit_vec2(&lastdir, &lastpt->pos, &pt->pos);
3729 for (j = 0; j < outline->count; j++)
3731 D3DXVECTOR2 curdir;
3733 lastpt = pt;
3734 pt = &outline->items[(j + 1) % outline->count];
3735 unit_vec2(&curdir, &lastpt->pos, &pt->pos);
3737 switch (lastpt->corner)
3739 case POINTTYPE_CURVE_START:
3740 case POINTTYPE_CURVE_END:
3741 if (!is_direction_similar(&lastdir, &curdir, cos_45))
3742 lastpt->corner = POINTTYPE_CORNER;
3743 break;
3744 case POINTTYPE_CURVE_MIDDLE:
3745 if (!is_direction_similar(&lastdir, &curdir, cos_90))
3746 lastpt->corner = POINTTYPE_CORNER;
3747 else
3748 lastpt->corner = POINTTYPE_CURVE;
3749 break;
3750 default:
3751 break;
3753 lastdir = curdir;
3756 header = (TTPOLYGONHEADER *)((char *)header + header->cb);
3758 return S_OK;
3761 static BOOL compute_text_mesh(struct mesh *mesh, const char *text,
3762 float deviation, float extrusion, float otmEMSquare, const struct glyphinfo *glyphs)
3764 DWORD nb_vertices, nb_faces;
3765 DWORD nb_corners, nb_outline_points;
3766 int textlen = 0;
3767 int i;
3768 struct vertex *vertex_ptr;
3769 face *face_ptr;
3771 textlen = strlen(text);
3773 /* corner points need an extra vertex for the different side faces normals */
3774 nb_corners = 0;
3775 nb_outline_points = 0;
3776 for (i = 0; i < textlen; i++)
3778 int j;
3779 for (j = 0; j < glyphs[i].outlines.count; j++)
3781 int k;
3782 struct outline *outline = &glyphs[i].outlines.items[j];
3783 nb_outline_points += outline->count;
3784 nb_corners++; /* first outline point always repeated as a corner */
3785 for (k = 1; k < outline->count; k++)
3786 if (outline->items[k].corner)
3787 nb_corners++;
3791 nb_vertices = (nb_outline_points + nb_corners) * 2 + textlen;
3792 nb_faces = nb_outline_points * 2;
3794 if (!new_mesh(mesh, nb_vertices, nb_faces))
3795 return FALSE;
3797 /* convert 2D vertices and faces into 3D mesh */
3798 vertex_ptr = mesh->vertices;
3799 face_ptr = mesh->faces;
3800 for (i = 0; i < textlen; i++)
3802 int j;
3804 /* side vertices and faces */
3805 for (j = 0; j < glyphs[i].outlines.count; j++)
3807 struct vertex *outline_vertices = vertex_ptr;
3808 struct outline *outline = &glyphs[i].outlines.items[j];
3809 int k;
3810 struct point2d *prevpt = &outline->items[outline->count - 1];
3811 struct point2d *pt = &outline->items[0];
3813 for (k = 1; k <= outline->count; k++)
3815 struct vertex vtx;
3816 struct point2d *nextpt = &outline->items[k % outline->count];
3817 WORD vtx_idx = vertex_ptr - mesh->vertices;
3818 D3DXVECTOR2 vec;
3820 if (pt->corner == POINTTYPE_CURVE_START)
3821 D3DXVec2Subtract(&vec, &pt->pos, &prevpt->pos);
3822 else if (pt->corner)
3823 D3DXVec2Subtract(&vec, &nextpt->pos, &pt->pos);
3824 else
3825 D3DXVec2Subtract(&vec, &nextpt->pos, &prevpt->pos);
3826 D3DXVec2Normalize(&vec, &vec);
3827 vtx.normal.x = -vec.y;
3828 vtx.normal.y = vec.x;
3829 vtx.normal.z = 0;
3831 vtx.position.x = pt->pos.x + glyphs[i].offset_x;
3832 vtx.position.y = pt->pos.y;
3833 vtx.position.z = 0;
3834 *vertex_ptr++ = vtx;
3836 vtx.position.z = -extrusion;
3837 *vertex_ptr++ = vtx;
3839 vtx.position.x = nextpt->pos.x + glyphs[i].offset_x;
3840 vtx.position.y = nextpt->pos.y;
3841 if (pt->corner && nextpt->corner && nextpt->corner != POINTTYPE_CURVE_END) {
3842 vtx.position.z = -extrusion;
3843 *vertex_ptr++ = vtx;
3844 vtx.position.z = 0;
3845 *vertex_ptr++ = vtx;
3847 (*face_ptr)[0] = vtx_idx;
3848 (*face_ptr)[1] = vtx_idx + 2;
3849 (*face_ptr)[2] = vtx_idx + 1;
3850 face_ptr++;
3852 (*face_ptr)[0] = vtx_idx;
3853 (*face_ptr)[1] = vtx_idx + 3;
3854 (*face_ptr)[2] = vtx_idx + 2;
3855 face_ptr++;
3856 } else {
3857 if (nextpt->corner) {
3858 if (nextpt->corner == POINTTYPE_CURVE_END) {
3859 struct point2d *nextpt2 = &outline->items[(k + 1) % outline->count];
3860 D3DXVec2Subtract(&vec, &nextpt2->pos, &nextpt->pos);
3861 } else {
3862 D3DXVec2Subtract(&vec, &nextpt->pos, &pt->pos);
3864 D3DXVec2Normalize(&vec, &vec);
3865 vtx.normal.x = -vec.y;
3866 vtx.normal.y = vec.x;
3868 vtx.position.z = 0;
3869 *vertex_ptr++ = vtx;
3870 vtx.position.z = -extrusion;
3871 *vertex_ptr++ = vtx;
3874 (*face_ptr)[0] = vtx_idx;
3875 (*face_ptr)[1] = vtx_idx + 3;
3876 (*face_ptr)[2] = vtx_idx + 1;
3877 face_ptr++;
3879 (*face_ptr)[0] = vtx_idx;
3880 (*face_ptr)[1] = vtx_idx + 2;
3881 (*face_ptr)[2] = vtx_idx + 3;
3882 face_ptr++;
3885 prevpt = pt;
3886 pt = nextpt;
3888 if (!pt->corner) {
3889 *vertex_ptr++ = *outline_vertices++;
3890 *vertex_ptr++ = *outline_vertices++;
3894 /* FIXME: compute expected faces */
3895 /* Add placeholder to separate glyph outlines */
3896 vertex_ptr->position.x = 0;
3897 vertex_ptr->position.y = 0;
3898 vertex_ptr->position.z = 0;
3899 vertex_ptr->normal.x = 0;
3900 vertex_ptr->normal.y = 0;
3901 vertex_ptr->normal.z = 1;
3902 vertex_ptr++;
3905 return TRUE;
3908 static void compare_text_outline_mesh(const char *name, ID3DXMesh *d3dxmesh, struct mesh *mesh,
3909 size_t textlen, float extrusion, const struct glyphinfo *glyphs)
3911 HRESULT hr;
3912 DWORD number_of_vertices, number_of_faces;
3913 IDirect3DVertexBuffer9 *vertex_buffer = NULL;
3914 IDirect3DIndexBuffer9 *index_buffer = NULL;
3915 D3DVERTEXBUFFER_DESC vertex_buffer_description;
3916 D3DINDEXBUFFER_DESC index_buffer_description;
3917 struct vertex *vertices = NULL;
3918 face *faces = NULL;
3919 int expected, i;
3920 int vtx_idx1, face_idx1, vtx_idx2, face_idx2;
3922 number_of_vertices = d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh);
3923 number_of_faces = d3dxmesh->lpVtbl->GetNumFaces(d3dxmesh);
3925 /* vertex buffer */
3926 hr = d3dxmesh->lpVtbl->GetVertexBuffer(d3dxmesh, &vertex_buffer);
3927 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
3928 if (hr != D3D_OK)
3930 skip("Couldn't get vertex buffers\n");
3931 goto error;
3934 hr = IDirect3DVertexBuffer9_GetDesc(vertex_buffer, &vertex_buffer_description);
3935 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
3937 if (hr != D3D_OK)
3939 skip("Couldn't get vertex buffer description\n");
3941 else
3943 ok(vertex_buffer_description.Format == D3DFMT_VERTEXDATA, "Test %s, result %x, expected %x (D3DFMT_VERTEXDATA)\n",
3944 name, vertex_buffer_description.Format, D3DFMT_VERTEXDATA);
3945 ok(vertex_buffer_description.Type == D3DRTYPE_VERTEXBUFFER, "Test %s, result %x, expected %x (D3DRTYPE_VERTEXBUFFER)\n",
3946 name, vertex_buffer_description.Type, D3DRTYPE_VERTEXBUFFER);
3947 ok(vertex_buffer_description.Usage == 0, "Test %s, result %x, expected %x\n", name, vertex_buffer_description.Usage, 0);
3948 ok(vertex_buffer_description.Pool == D3DPOOL_MANAGED, "Test %s, result %x, expected %x (D3DPOOL_MANAGED)\n",
3949 name, vertex_buffer_description.Pool, D3DPOOL_MANAGED);
3950 ok(vertex_buffer_description.FVF == mesh->fvf, "Test %s, result %x, expected %x\n",
3951 name, vertex_buffer_description.FVF, mesh->fvf);
3952 if (mesh->fvf == 0)
3954 expected = number_of_vertices * mesh->vertex_size;
3956 else
3958 expected = number_of_vertices * D3DXGetFVFVertexSize(mesh->fvf);
3960 ok(vertex_buffer_description.Size == expected, "Test %s, result %x, expected %x\n",
3961 name, vertex_buffer_description.Size, expected);
3964 hr = d3dxmesh->lpVtbl->GetIndexBuffer(d3dxmesh, &index_buffer);
3965 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
3966 if (hr != D3D_OK)
3968 skip("Couldn't get index buffer\n");
3969 goto error;
3972 hr = IDirect3DIndexBuffer9_GetDesc(index_buffer, &index_buffer_description);
3973 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
3975 if (hr != D3D_OK)
3977 skip("Couldn't get index buffer description\n");
3979 else
3981 ok(index_buffer_description.Format == D3DFMT_INDEX16, "Test %s, result %x, expected %x (D3DFMT_INDEX16)\n",
3982 name, index_buffer_description.Format, D3DFMT_INDEX16);
3983 ok(index_buffer_description.Type == D3DRTYPE_INDEXBUFFER, "Test %s, result %x, expected %x (D3DRTYPE_INDEXBUFFER)\n",
3984 name, index_buffer_description.Type, D3DRTYPE_INDEXBUFFER);
3985 ok(index_buffer_description.Usage == 0, "Test %s, result %#x, expected %#x.\n",
3986 name, index_buffer_description.Usage, 0);
3987 ok(index_buffer_description.Pool == D3DPOOL_MANAGED, "Test %s, result %x, expected %x (D3DPOOL_MANAGED)\n",
3988 name, index_buffer_description.Pool, D3DPOOL_MANAGED);
3989 expected = number_of_faces * sizeof(WORD) * 3;
3990 ok(index_buffer_description.Size == expected, "Test %s, result %x, expected %x\n",
3991 name, index_buffer_description.Size, expected);
3994 /* specify offset and size to avoid potential overruns */
3995 hr = IDirect3DVertexBuffer9_Lock(vertex_buffer, 0, number_of_vertices * sizeof(D3DXVECTOR3) * 2,
3996 (void **)&vertices, D3DLOCK_DISCARD);
3997 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
3998 if (hr != D3D_OK)
4000 skip("Couldn't lock vertex buffer\n");
4001 goto error;
4003 hr = IDirect3DIndexBuffer9_Lock(index_buffer, 0, number_of_faces * sizeof(WORD) * 3,
4004 (void **)&faces, D3DLOCK_DISCARD);
4005 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
4006 if (hr != D3D_OK)
4008 skip("Couldn't lock index buffer\n");
4009 goto error;
4012 face_idx1 = 0;
4013 vtx_idx2 = 0;
4014 face_idx2 = 0;
4015 vtx_idx1 = 0;
4016 for (i = 0; i < textlen; i++)
4018 int nb_outline_vertices1, nb_outline_faces1;
4019 int nb_outline_vertices2, nb_outline_faces2;
4020 int nb_back_vertices, nb_back_faces;
4021 int first_vtx1, first_vtx2;
4022 int first_face1, first_face2;
4023 int j;
4025 first_vtx1 = vtx_idx1;
4026 first_vtx2 = vtx_idx2;
4027 /* Glyphs without outlines do not generate any vertices. */
4028 if (glyphs[i].outlines.count > 0)
4030 for (; vtx_idx1 < number_of_vertices; vtx_idx1++)
4032 if (vertices[vtx_idx1].normal.z != 0)
4033 break;
4036 for (; vtx_idx2 < mesh->number_of_vertices; vtx_idx2++)
4038 if (mesh->vertices[vtx_idx2].normal.z != 0)
4039 break;
4042 nb_outline_vertices1 = vtx_idx1 - first_vtx1;
4043 nb_outline_vertices2 = vtx_idx2 - first_vtx2;
4044 ok(nb_outline_vertices1 == nb_outline_vertices2,
4045 "Test %s, glyph %d, outline vertex count result %d, expected %d\n", name, i,
4046 nb_outline_vertices1, nb_outline_vertices2);
4048 for (j = 0; j < min(nb_outline_vertices1, nb_outline_vertices2); j++)
4050 vtx_idx1 = first_vtx1 + j;
4051 vtx_idx2 = first_vtx2 + j;
4052 ok(compare_vec3(vertices[vtx_idx1].position, mesh->vertices[vtx_idx2].position),
4053 "Test %s, glyph %d, vertex position %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1,
4054 vertices[vtx_idx1].position.x, vertices[vtx_idx1].position.y, vertices[vtx_idx1].position.z,
4055 mesh->vertices[vtx_idx2].position.x, mesh->vertices[vtx_idx2].position.y, mesh->vertices[vtx_idx2].position.z);
4056 ok(compare_vec3(vertices[vtx_idx1].normal, mesh->vertices[first_vtx2 + j].normal),
4057 "Test %s, glyph %d, vertex normal %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1,
4058 vertices[vtx_idx1].normal.x, vertices[vtx_idx1].normal.y, vertices[vtx_idx1].normal.z,
4059 mesh->vertices[vtx_idx2].normal.x, mesh->vertices[vtx_idx2].normal.y, mesh->vertices[vtx_idx2].normal.z);
4061 vtx_idx1 = first_vtx1 + nb_outline_vertices1;
4062 vtx_idx2 = first_vtx2 + nb_outline_vertices2;
4064 first_face1 = face_idx1;
4065 first_face2 = face_idx2;
4066 for (; face_idx1 < number_of_faces; face_idx1++)
4068 if (faces[face_idx1][0] >= vtx_idx1 ||
4069 faces[face_idx1][1] >= vtx_idx1 ||
4070 faces[face_idx1][2] >= vtx_idx1)
4071 break;
4073 for (; face_idx2 < mesh->number_of_faces; face_idx2++)
4075 if (mesh->faces[face_idx2][0] >= vtx_idx2 ||
4076 mesh->faces[face_idx2][1] >= vtx_idx2 ||
4077 mesh->faces[face_idx2][2] >= vtx_idx2)
4078 break;
4080 nb_outline_faces1 = face_idx1 - first_face1;
4081 nb_outline_faces2 = face_idx2 - first_face2;
4082 ok(nb_outline_faces1 == nb_outline_faces2,
4083 "Test %s, glyph %d, outline face count result %d, expected %d\n", name, i,
4084 nb_outline_faces1, nb_outline_faces2);
4086 for (j = 0; j < min(nb_outline_faces1, nb_outline_faces2); j++)
4088 face_idx1 = first_face1 + j;
4089 face_idx2 = first_face2 + j;
4090 ok(faces[face_idx1][0] - first_vtx1 == mesh->faces[face_idx2][0] - first_vtx2 &&
4091 faces[face_idx1][1] - first_vtx1 == mesh->faces[face_idx2][1] - first_vtx2 &&
4092 faces[face_idx1][2] - first_vtx1 == mesh->faces[face_idx2][2] - first_vtx2,
4093 "Test %s, glyph %d, face %d, result (%d, %d, %d), expected (%d, %d, %d)\n", name, i, face_idx1,
4094 faces[face_idx1][0], faces[face_idx1][1], faces[face_idx1][2],
4095 mesh->faces[face_idx2][0] - first_vtx2 + first_vtx1,
4096 mesh->faces[face_idx2][1] - first_vtx2 + first_vtx1,
4097 mesh->faces[face_idx2][2] - first_vtx2 + first_vtx1);
4099 face_idx1 = first_face1 + nb_outline_faces1;
4100 face_idx2 = first_face2 + nb_outline_faces2;
4102 /* partial test on back vertices and faces */
4103 first_vtx1 = vtx_idx1;
4104 for (; vtx_idx1 < number_of_vertices; vtx_idx1++) {
4105 struct vertex vtx;
4107 if (vertices[vtx_idx1].normal.z != 1.0f)
4108 break;
4110 vtx.position.z = 0.0f;
4111 vtx.normal.x = 0.0f;
4112 vtx.normal.y = 0.0f;
4113 vtx.normal.z = 1.0f;
4114 ok(compare(vertices[vtx_idx1].position.z, vtx.position.z),
4115 "Test %s, glyph %d, vertex position.z %d, result %g, expected %g\n", name, i, vtx_idx1,
4116 vertices[vtx_idx1].position.z, vtx.position.z);
4117 ok(compare_vec3(vertices[vtx_idx1].normal, vtx.normal),
4118 "Test %s, glyph %d, vertex normal %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1,
4119 vertices[vtx_idx1].normal.x, vertices[vtx_idx1].normal.y, vertices[vtx_idx1].normal.z,
4120 vtx.normal.x, vtx.normal.y, vtx.normal.z);
4122 nb_back_vertices = vtx_idx1 - first_vtx1;
4123 first_face1 = face_idx1;
4124 for (; face_idx1 < number_of_faces; face_idx1++)
4126 const D3DXVECTOR3 *vtx1, *vtx2, *vtx3;
4127 D3DXVECTOR3 normal;
4128 D3DXVECTOR3 v1 = {0, 0, 0};
4129 D3DXVECTOR3 v2 = {0, 0, 0};
4130 D3DXVECTOR3 forward = {0.0f, 0.0f, 1.0f};
4132 if (faces[face_idx1][0] >= vtx_idx1 ||
4133 faces[face_idx1][1] >= vtx_idx1 ||
4134 faces[face_idx1][2] >= vtx_idx1)
4135 break;
4137 vtx1 = &vertices[faces[face_idx1][0]].position;
4138 vtx2 = &vertices[faces[face_idx1][1]].position;
4139 vtx3 = &vertices[faces[face_idx1][2]].position;
4141 D3DXVec3Subtract(&v1, vtx2, vtx1);
4142 D3DXVec3Subtract(&v2, vtx3, vtx2);
4143 D3DXVec3Cross(&normal, &v1, &v2);
4144 D3DXVec3Normalize(&normal, &normal);
4145 ok(!D3DXVec3Length(&normal) || compare_vec3(normal, forward),
4146 "Test %s, glyph %d, face %d normal, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, face_idx1,
4147 normal.x, normal.y, normal.z, forward.x, forward.y, forward.z);
4149 nb_back_faces = face_idx1 - first_face1;
4151 /* compare front and back faces & vertices */
4152 if (extrusion == 0.0f) {
4153 /* Oddly there are only back faces in this case */
4154 nb_back_vertices /= 2;
4155 nb_back_faces /= 2;
4156 face_idx1 -= nb_back_faces;
4157 vtx_idx1 -= nb_back_vertices;
4159 for (j = 0; j < nb_back_vertices; j++)
4161 struct vertex vtx = vertices[first_vtx1];
4162 vtx.position.z = -extrusion;
4163 vtx.normal.x = 0.0f;
4164 vtx.normal.y = 0.0f;
4165 vtx.normal.z = extrusion == 0.0f ? 1.0f : -1.0f;
4166 ok(compare_vec3(vertices[vtx_idx1].position, vtx.position),
4167 "Test %s, glyph %d, vertex position %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1,
4168 vertices[vtx_idx1].position.x, vertices[vtx_idx1].position.y, vertices[vtx_idx1].position.z,
4169 vtx.position.x, vtx.position.y, vtx.position.z);
4170 ok(compare_vec3(vertices[vtx_idx1].normal, vtx.normal),
4171 "Test %s, glyph %d, vertex normal %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1,
4172 vertices[vtx_idx1].normal.x, vertices[vtx_idx1].normal.y, vertices[vtx_idx1].normal.z,
4173 vtx.normal.x, vtx.normal.y, vtx.normal.z);
4174 vtx_idx1++;
4175 first_vtx1++;
4177 for (j = 0; j < nb_back_faces; j++)
4179 int f1, f2;
4180 if (extrusion == 0.0f) {
4181 f1 = 1;
4182 f2 = 2;
4183 } else {
4184 f1 = 2;
4185 f2 = 1;
4187 ok(faces[face_idx1][0] == faces[first_face1][0] + nb_back_vertices &&
4188 faces[face_idx1][1] == faces[first_face1][f1] + nb_back_vertices &&
4189 faces[face_idx1][2] == faces[first_face1][f2] + nb_back_vertices,
4190 "Test %s, glyph %d, face %d, result (%d, %d, %d), expected (%d, %d, %d)\n", name, i, face_idx1,
4191 faces[face_idx1][0], faces[face_idx1][1], faces[face_idx1][2],
4192 faces[first_face1][0] - nb_back_faces,
4193 faces[first_face1][f1] - nb_back_faces,
4194 faces[first_face1][f2] - nb_back_faces);
4195 first_face1++;
4196 face_idx1++;
4199 /* skip to the outline for the next glyph */
4200 for (; vtx_idx2 < mesh->number_of_vertices; vtx_idx2++) {
4201 if (mesh->vertices[vtx_idx2].normal.z == 0)
4202 break;
4204 for (; face_idx2 < mesh->number_of_faces; face_idx2++)
4206 if (mesh->faces[face_idx2][0] >= vtx_idx2 ||
4207 mesh->faces[face_idx2][1] >= vtx_idx2 ||
4208 mesh->faces[face_idx2][2] >= vtx_idx2) break;
4212 error:
4213 if (vertices) IDirect3DVertexBuffer9_Unlock(vertex_buffer);
4214 if (faces) IDirect3DIndexBuffer9_Unlock(index_buffer);
4215 if (index_buffer) IDirect3DIndexBuffer9_Release(index_buffer);
4216 if (vertex_buffer) IDirect3DVertexBuffer9_Release(vertex_buffer);
4219 static void test_createtext(IDirect3DDevice9 *device, HDC hdc, const char *text, float deviation, float extrusion)
4221 HRESULT hr;
4222 ID3DXMesh *d3dxmesh = NULL;
4223 struct mesh mesh = {0};
4224 char name[256];
4225 OUTLINETEXTMETRICA otm;
4226 GLYPHMETRICS gm;
4227 struct glyphinfo *glyphs = NULL;
4228 GLYPHMETRICSFLOAT *glyphmetrics_float = HeapAlloc(GetProcessHeap(), 0, sizeof(GLYPHMETRICSFLOAT) * strlen(text));
4229 int i;
4230 LOGFONTA lf;
4231 float offset_x;
4232 size_t textlen;
4233 HFONT font = NULL, oldfont = NULL;
4234 char *raw_outline = NULL;
4236 sprintf(name, "text ('%s', %f, %f)", text, deviation, extrusion);
4238 hr = D3DXCreateTextA(device, hdc, text, deviation, extrusion, &d3dxmesh, NULL, glyphmetrics_float);
4239 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
4240 if (hr != D3D_OK)
4242 skip("Couldn't create text with D3DXCreateText\n");
4243 goto error;
4246 /* must select a modified font having lfHeight = otm.otmEMSquare before
4247 * calling GetGlyphOutline to get the expected values */
4248 if (!GetObjectA(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf)
4249 || !GetOutlineTextMetricsA(hdc, sizeof(otm), &otm))
4251 skip("Couldn't get text outline\n");
4252 goto error;
4254 lf.lfHeight = otm.otmEMSquare;
4255 lf.lfWidth = 0;
4256 if (!(font = CreateFontIndirectA(&lf)))
4258 skip("Couldn't create the modified font\n");
4259 goto error;
4262 textlen = strlen(text);
4263 glyphs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, textlen * sizeof(*glyphs));
4264 if (!glyphs)
4265 goto error;
4267 oldfont = SelectObject(hdc, font);
4269 for (i = 0; i < textlen; i++)
4271 const MAT2 identity = {{0, 1}, {0, 0}, {0, 0}, {0, 1}};
4272 GetGlyphOutlineA(hdc, text[i], GGO_NATIVE, &gm, 0, NULL, &identity);
4273 compare_float(glyphmetrics_float[i].gmfBlackBoxX, gm.gmBlackBoxX / (float)otm.otmEMSquare);
4274 compare_float(glyphmetrics_float[i].gmfBlackBoxY, gm.gmBlackBoxY / (float)otm.otmEMSquare);
4275 compare_float(glyphmetrics_float[i].gmfptGlyphOrigin.x, gm.gmptGlyphOrigin.x / (float)otm.otmEMSquare);
4276 compare_float(glyphmetrics_float[i].gmfptGlyphOrigin.y, gm.gmptGlyphOrigin.y / (float)otm.otmEMSquare);
4277 compare_float(glyphmetrics_float[i].gmfCellIncX, gm.gmCellIncX / (float)otm.otmEMSquare);
4278 compare_float(glyphmetrics_float[i].gmfCellIncY, gm.gmCellIncY / (float)otm.otmEMSquare);
4281 if (deviation == 0.0f)
4282 deviation = 1.0f / otm.otmEMSquare;
4284 offset_x = 0.0f;
4285 for (i = 0; i < textlen; i++)
4287 /* get outline points from data returned from GetGlyphOutline */
4288 const MAT2 identity = {{0, 1}, {0, 0}, {0, 0}, {0, 1}};
4289 int datasize;
4291 glyphs[i].offset_x = offset_x;
4293 datasize = GetGlyphOutlineA(hdc, text[i], GGO_NATIVE, &gm, 0, NULL, &identity);
4294 if (datasize < 0)
4296 SelectObject(hdc, oldfont);
4297 goto error;
4299 HeapFree(GetProcessHeap(), 0, raw_outline);
4300 raw_outline = HeapAlloc(GetProcessHeap(), 0, datasize);
4301 if (!raw_outline)
4303 SelectObject(hdc, oldfont);
4304 goto error;
4306 datasize = GetGlyphOutlineA(hdc, text[i], GGO_NATIVE, &gm, datasize, raw_outline, &identity);
4308 create_outline(&glyphs[i], raw_outline, datasize, deviation, otm.otmEMSquare);
4310 offset_x += gm.gmCellIncX / (float)otm.otmEMSquare;
4313 SelectObject(hdc, oldfont);
4315 ZeroMemory(&mesh, sizeof(mesh));
4316 if (!compute_text_mesh(&mesh, text, deviation, extrusion, otm.otmEMSquare, glyphs))
4318 skip("Couldn't create mesh\n");
4319 d3dxmesh->lpVtbl->Release(d3dxmesh);
4320 return;
4322 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
4324 compare_text_outline_mesh(name, d3dxmesh, &mesh, textlen, extrusion, glyphs);
4326 error:
4327 free_mesh(&mesh);
4329 if (d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh);
4330 if (font) DeleteObject(font);
4331 HeapFree(GetProcessHeap(), 0, glyphmetrics_float);
4333 if (glyphs)
4335 for (i = 0; i < textlen; i++)
4337 int j;
4338 for (j = 0; j < glyphs[i].outlines.count; j++)
4339 HeapFree(GetProcessHeap(), 0, glyphs[i].outlines.items[j].items);
4340 HeapFree(GetProcessHeap(), 0, glyphs[i].outlines.items);
4342 HeapFree(GetProcessHeap(), 0, glyphs);
4344 HeapFree(GetProcessHeap(), 0, raw_outline);
4347 static void D3DXCreateTextTest(void)
4349 HRESULT hr;
4350 HDC hdc;
4351 IDirect3DDevice9* device;
4352 ID3DXMesh* d3dxmesh = NULL;
4353 HFONT hFont;
4354 OUTLINETEXTMETRICA otm;
4355 int number_of_vertices;
4356 int number_of_faces;
4357 struct test_context *test_context;
4359 if (!(test_context = new_test_context()))
4361 skip("Couldn't create test context\n");
4362 return;
4364 device = test_context->device;
4366 hdc = CreateCompatibleDC(NULL);
4368 hFont = CreateFontA(12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
4369 CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, "Arial");
4370 SelectObject(hdc, hFont);
4371 GetOutlineTextMetricsA(hdc, sizeof(otm), &otm);
4373 hr = D3DXCreateTextA(device, hdc, "wine", 0.001f, 0.4f, NULL, NULL, NULL);
4374 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4376 /* D3DXCreateTextA page faults from passing NULL text */
4378 hr = D3DXCreateTextW(device, hdc, NULL, 0.001f, 0.4f, &d3dxmesh, NULL, NULL);
4379 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4381 hr = D3DXCreateTextA(device, hdc, "", 0.001f, 0.4f, &d3dxmesh, NULL, NULL);
4382 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4384 hr = D3DXCreateTextA(device, hdc, " ", 0.001f, 0.4f, &d3dxmesh, NULL, NULL);
4385 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4387 hr = D3DXCreateTextA(NULL, hdc, "wine", 0.001f, 0.4f, &d3dxmesh, NULL, NULL);
4388 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4390 hr = D3DXCreateTextA(device, NULL, "wine", 0.001f, 0.4f, &d3dxmesh, NULL, NULL);
4391 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4393 hr = D3DXCreateTextA(device, hdc, "wine", -FLT_MIN, 0.4f, &d3dxmesh, NULL, NULL);
4394 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4396 hr = D3DXCreateTextA(device, hdc, "wine", 0.001f, -FLT_MIN, &d3dxmesh, NULL, NULL);
4397 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4399 /* deviation = 0.0f treated as if deviation = 1.0f / otm.otmEMSquare */
4400 hr = D3DXCreateTextA(device, hdc, "wine", 1.0f / otm.otmEMSquare, 0.4f, &d3dxmesh, NULL, NULL);
4401 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
4402 number_of_vertices = d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh);
4403 number_of_faces = d3dxmesh->lpVtbl->GetNumFaces(d3dxmesh);
4404 if (SUCCEEDED(hr) && d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh);
4406 hr = D3DXCreateTextA(device, hdc, "wine", 0.0f, 0.4f, &d3dxmesh, NULL, NULL);
4407 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
4408 ok(number_of_vertices == d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh),
4409 "Got %d vertices, expected %d\n",
4410 d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh), number_of_vertices);
4411 ok(number_of_faces == d3dxmesh->lpVtbl->GetNumFaces(d3dxmesh),
4412 "Got %d faces, expected %d\n",
4413 d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh), number_of_faces);
4414 if (SUCCEEDED(hr) && d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh);
4416 if (0)
4418 /* too much detail requested, so will appear to hang */
4419 trace("Waiting for D3DXCreateText to finish with deviation = FLT_MIN ...\n");
4420 hr = D3DXCreateTextA(device, hdc, "wine", FLT_MIN, 0.4f, &d3dxmesh, NULL, NULL);
4421 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
4422 if (SUCCEEDED(hr) && d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh);
4423 trace("D3DXCreateText finish with deviation = FLT_MIN\n");
4426 hr = D3DXCreateTextA(device, hdc, "wine", 0.001f, 0.4f, &d3dxmesh, NULL, NULL);
4427 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
4428 if (SUCCEEDED(hr) && d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh);
4430 test_createtext(device, hdc, "wine", FLT_MAX, 0.4f);
4431 test_createtext(device, hdc, "wine", 0.001f, FLT_MIN);
4432 test_createtext(device, hdc, "wine", 0.001f, 0.0f);
4433 test_createtext(device, hdc, "wine", 0.001f, FLT_MAX);
4434 test_createtext(device, hdc, "wine", 0.0f, 1.0f);
4435 test_createtext(device, hdc, " wine", 1.0f, 0.0f);
4436 test_createtext(device, hdc, "wine ", 1.0f, 0.0f);
4437 test_createtext(device, hdc, "wi ne", 1.0f, 0.0f);
4439 DeleteDC(hdc);
4440 DeleteObject(hFont);
4442 free_test_context(test_context);
4445 static void test_get_decl_length(void)
4447 static const D3DVERTEXELEMENT9 declaration1[] =
4449 {0, 0, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4450 {1, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4451 {2, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4452 {3, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4453 {4, 0, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4454 {5, 0, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4455 {6, 0, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4456 {7, 0, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4457 {8, 0, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4458 {9, 0, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4459 {10, 0, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4460 {11, 0, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4461 {12, 0, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4462 {13, 0, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4463 {14, 0, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4464 D3DDECL_END(),
4466 static const D3DVERTEXELEMENT9 declaration2[] =
4468 {0, 8, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4469 {1, 8, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4470 {2, 8, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4471 {3, 8, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4472 {4, 8, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4473 {5, 8, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4474 {6, 8, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4475 {7, 8, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4476 {0, 8, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4477 {1, 8, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4478 {2, 8, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4479 {3, 8, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4480 {4, 8, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4481 {5, 8, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4482 {6, 8, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4483 {7, 8, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4484 D3DDECL_END(),
4486 UINT size;
4488 size = D3DXGetDeclLength(declaration1);
4489 ok(size == 15, "Got size %u, expected 15.\n", size);
4491 size = D3DXGetDeclLength(declaration2);
4492 ok(size == 16, "Got size %u, expected 16.\n", size);
4495 static void test_get_decl_vertex_size(void)
4497 static const D3DVERTEXELEMENT9 declaration1[] =
4499 {0, 0, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4500 {1, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4501 {2, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4502 {3, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4503 {4, 0, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4504 {5, 0, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4505 {6, 0, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4506 {7, 0, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4507 {8, 0, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4508 {9, 0, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4509 {10, 0, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4510 {11, 0, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4511 {12, 0, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4512 {13, 0, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4513 {14, 0, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4514 D3DDECL_END(),
4516 static const D3DVERTEXELEMENT9 declaration2[] =
4518 {0, 8, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4519 {1, 8, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4520 {2, 8, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4521 {3, 8, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4522 {4, 8, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4523 {5, 8, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4524 {6, 8, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4525 {7, 8, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4526 {0, 8, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4527 {1, 8, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4528 {2, 8, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4529 {3, 8, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4530 {4, 8, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4531 {5, 8, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4532 {6, 8, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4533 {7, 8, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4534 D3DDECL_END(),
4536 static const UINT sizes1[] =
4538 4, 8, 12, 16,
4539 4, 4, 4, 8,
4540 4, 4, 8, 4,
4541 4, 4, 8, 0,
4543 static const UINT sizes2[] =
4545 12, 16, 20, 24,
4546 12, 12, 16, 16,
4548 unsigned int i;
4549 UINT size;
4551 size = D3DXGetDeclVertexSize(NULL, 0);
4552 ok(size == 0, "Got size %#x, expected 0.\n", size);
4554 for (i = 0; i < 16; ++i)
4556 size = D3DXGetDeclVertexSize(declaration1, i);
4557 ok(size == sizes1[i], "Got size %u for stream %u, expected %u.\n", size, i, sizes1[i]);
4560 for (i = 0; i < 8; ++i)
4562 size = D3DXGetDeclVertexSize(declaration2, i);
4563 ok(size == sizes2[i], "Got size %u for stream %u, expected %u.\n", size, i, sizes2[i]);
4567 static void D3DXGenerateAdjacencyTest(void)
4569 HRESULT hr;
4570 IDirect3DDevice9 *device;
4571 ID3DXMesh *d3dxmesh = NULL;
4572 D3DXVECTOR3 *vertices = NULL;
4573 WORD *indices = NULL;
4574 int i;
4575 struct {
4576 DWORD num_vertices;
4577 D3DXVECTOR3 vertices[6];
4578 DWORD num_faces;
4579 WORD indices[3 * 3];
4580 FLOAT epsilon;
4581 DWORD adjacency[3 * 3];
4582 } test_data[] = {
4583 { /* for epsilon < 0, indices must match for faces to be adjacent */
4584 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}},
4585 2, {0, 1, 2, 0, 2, 3},
4586 -1.0,
4587 {-1, -1, 1, 0, -1, -1},
4590 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}},
4591 2, {0, 1, 2, 3, 4, 5},
4592 -1.0,
4593 {-1, -1, -1, -1, -1, -1},
4595 { /* for epsilon == 0, indices or vertices must match for faces to be adjacent */
4596 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}},
4597 2, {0, 1, 2, 3, 4, 5},
4598 0.0,
4599 {-1, -1, 1, 0, -1, -1},
4601 { /* for epsilon > 0, vertices must be less than (but NOT equal to) epsilon distance away */
4602 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}},
4603 2, {0, 1, 2, 3, 4, 5},
4604 0.25,
4605 {-1, -1, -1, -1, -1, -1},
4607 { /* for epsilon > 0, vertices must be less than (but NOT equal to) epsilon distance away */
4608 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}},
4609 2, {0, 1, 2, 3, 4, 5},
4610 0.250001,
4611 {-1, -1, 1, 0, -1, -1},
4613 { /* length between vertices are compared to epsilon, not the individual dimension deltas */
4614 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}},
4615 2, {0, 1, 2, 3, 4, 5},
4616 0.353, /* < sqrt(0.25*0.25 + 0.25*0.25) */
4617 {-1, -1, -1, -1, -1, -1},
4620 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}},
4621 2, {0, 1, 2, 3, 4, 5},
4622 0.354, /* > sqrt(0.25*0.25 + 0.25*0.25) */
4623 {-1, -1, 1, 0, -1, -1},
4625 { /* adjacent faces must have opposite winding orders at the shared edge */
4626 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}},
4627 2, {0, 1, 2, 0, 3, 2},
4628 0.0,
4629 {-1, -1, -1, -1, -1, -1},
4632 struct test_context *test_context;
4634 if (!(test_context = new_test_context()))
4636 skip("Couldn't create test context\n");
4637 return;
4639 device = test_context->device;
4641 for (i = 0; i < ARRAY_SIZE(test_data); i++)
4643 DWORD adjacency[ARRAY_SIZE(test_data[0].adjacency)];
4644 int j;
4646 if (d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh);
4647 d3dxmesh = NULL;
4649 hr = D3DXCreateMeshFVF(test_data[i].num_faces, test_data[i].num_vertices, 0, D3DFVF_XYZ, device, &d3dxmesh);
4650 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
4652 hr = d3dxmesh->lpVtbl->LockVertexBuffer(d3dxmesh, D3DLOCK_DISCARD, (void**)&vertices);
4653 ok(hr == D3D_OK, "test %d: Got result %x, expected %x (D3D_OK)\n", i, hr, D3D_OK);
4654 if (FAILED(hr)) continue;
4655 CopyMemory(vertices, test_data[i].vertices, test_data[i].num_vertices * sizeof(test_data[0].vertices[0]));
4656 d3dxmesh->lpVtbl->UnlockVertexBuffer(d3dxmesh);
4658 hr = d3dxmesh->lpVtbl->LockIndexBuffer(d3dxmesh, D3DLOCK_DISCARD, (void**)&indices);
4659 ok(hr == D3D_OK, "test %d: Got result %x, expected %x (D3D_OK)\n", i, hr, D3D_OK);
4660 if (FAILED(hr)) continue;
4661 CopyMemory(indices, test_data[i].indices, test_data[i].num_faces * 3 * sizeof(test_data[0].indices[0]));
4662 d3dxmesh->lpVtbl->UnlockIndexBuffer(d3dxmesh);
4664 if (i == 0) {
4665 hr = d3dxmesh->lpVtbl->GenerateAdjacency(d3dxmesh, 0.0f, NULL);
4666 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4669 hr = d3dxmesh->lpVtbl->GenerateAdjacency(d3dxmesh, test_data[i].epsilon, adjacency);
4670 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
4671 if (FAILED(hr)) continue;
4673 for (j = 0; j < test_data[i].num_faces * 3; j++)
4674 ok(adjacency[j] == test_data[i].adjacency[j],
4675 "Test %d adjacency %d: Got result %u, expected %u\n", i, j,
4676 adjacency[j], test_data[i].adjacency[j]);
4678 if (d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh);
4680 free_test_context(test_context);
4683 static void test_update_semantics(void)
4685 HRESULT hr;
4686 struct test_context *test_context = NULL;
4687 ID3DXMesh *mesh = NULL;
4688 D3DVERTEXELEMENT9 declaration0[] =
4690 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4691 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4692 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4693 D3DDECL_END()
4695 D3DVERTEXELEMENT9 declaration_pos_type_color[] =
4697 {0, 0, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4698 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4699 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4700 D3DDECL_END()
4702 D3DVERTEXELEMENT9 declaration_smaller[] =
4704 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4705 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4706 D3DDECL_END()
4708 D3DVERTEXELEMENT9 declaration_larger[] =
4710 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4711 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4712 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4713 {0, 40, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT, 0},
4714 D3DDECL_END()
4716 D3DVERTEXELEMENT9 declaration_multiple_streams[] =
4718 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4719 {1, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT, 0},
4720 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4721 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4723 D3DDECL_END()
4725 D3DVERTEXELEMENT9 declaration_double_usage[] =
4727 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4728 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4729 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4730 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4731 D3DDECL_END()
4733 D3DVERTEXELEMENT9 declaration_undefined_type[] =
4735 {0, 0, D3DDECLTYPE_UNUSED+1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4736 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4737 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4738 D3DDECL_END()
4740 D3DVERTEXELEMENT9 declaration_not_4_byte_aligned_offset[] =
4742 {0, 3, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4743 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4744 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4745 D3DDECL_END()
4747 static const struct
4749 D3DXVECTOR3 position0;
4750 D3DXVECTOR3 position1;
4751 D3DXVECTOR3 normal;
4752 DWORD color;
4754 vertices[] =
4756 { { 0.0f, 1.0f, 0.f}, { 1.0f, 0.0f, 0.f}, {0.0f, 0.0f, 1.0f}, 0xffff0000 },
4757 { { 1.0f, -1.0f, 0.f}, {-1.0f, -1.0f, 0.f}, {0.0f, 0.0f, 1.0f}, 0xff00ff00 },
4758 { {-1.0f, -1.0f, 0.f}, {-1.0f, 1.0f, 0.f}, {0.0f, 0.0f, 1.0f}, 0xff0000ff },
4760 unsigned int faces[] = {0, 1, 2};
4761 unsigned int attributes[] = {0};
4762 unsigned int num_faces = ARRAY_SIZE(faces) / 3;
4763 unsigned int num_vertices = ARRAY_SIZE(vertices);
4764 int offset = sizeof(D3DXVECTOR3);
4765 DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
4766 void *vertex_buffer;
4767 void *index_buffer;
4768 DWORD *attributes_buffer;
4769 D3DVERTEXELEMENT9 declaration[MAX_FVF_DECL_SIZE];
4770 D3DVERTEXELEMENT9 *decl_ptr;
4771 DWORD exp_vertex_size = sizeof(*vertices);
4772 DWORD vertex_size = 0;
4773 int equal;
4774 int i = 0;
4775 int *decl_mem;
4776 int filler_a = 0xaaaaaaaa;
4777 int filler_b = 0xbbbbbbbb;
4779 test_context = new_test_context();
4780 if (!test_context)
4782 skip("Couldn't create a test_context\n");
4783 goto cleanup;
4786 hr = D3DXCreateMesh(num_faces, num_vertices, options, declaration0,
4787 test_context->device, &mesh);
4788 if (FAILED(hr))
4790 skip("Couldn't create test mesh %#x\n", hr);
4791 goto cleanup;
4794 mesh->lpVtbl->LockVertexBuffer(mesh, 0, &vertex_buffer);
4795 memcpy(vertex_buffer, vertices, sizeof(vertices));
4796 mesh->lpVtbl->UnlockVertexBuffer(mesh);
4798 mesh->lpVtbl->LockIndexBuffer(mesh, 0, &index_buffer);
4799 memcpy(index_buffer, faces, sizeof(faces));
4800 mesh->lpVtbl->UnlockIndexBuffer(mesh);
4802 mesh->lpVtbl->LockAttributeBuffer(mesh, 0, &attributes_buffer);
4803 memcpy(attributes_buffer, attributes, sizeof(attributes));
4804 mesh->lpVtbl->UnlockAttributeBuffer(mesh);
4806 /* Get the declaration and try to change it */
4807 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4808 if (FAILED(hr))
4810 skip("Couldn't get vertex declaration %#x\n", hr);
4811 goto cleanup;
4813 equal = memcmp(declaration, declaration0, sizeof(declaration0));
4814 ok(equal == 0, "Vertex declarations were not equal\n");
4816 for (decl_ptr = declaration; decl_ptr->Stream != 0xFF; decl_ptr++)
4818 if (decl_ptr->Usage == D3DDECLUSAGE_POSITION)
4820 /* Use second vertex position instead of first */
4821 decl_ptr->Offset = offset;
4825 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration);
4826 ok(hr == D3D_OK, "Test UpdateSematics, got %#x expected %#x\n", hr, D3D_OK);
4828 /* Check that declaration was written by getting it again */
4829 memset(declaration, 0, sizeof(declaration));
4830 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4831 if (FAILED(hr))
4833 skip("Couldn't get vertex declaration %#x\n", hr);
4834 goto cleanup;
4837 for (decl_ptr = declaration; decl_ptr->Stream != 0xFF; decl_ptr++)
4839 if (decl_ptr->Usage == D3DDECLUSAGE_POSITION)
4841 ok(decl_ptr->Offset == offset, "Test UpdateSematics, got offset %d expected %d\n",
4842 decl_ptr->Offset, offset);
4846 /* Check that GetDeclaration only writes up to the D3DDECL_END() marker and
4847 * not the full MAX_FVF_DECL_SIZE elements.
4849 memset(declaration, filler_a, sizeof(declaration));
4850 memcpy(declaration, declaration0, sizeof(declaration0));
4851 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration);
4852 ok(hr == D3D_OK, "Test UpdateSematics, "
4853 "got %#x expected D3D_OK\n", hr);
4854 memset(declaration, filler_b, sizeof(declaration));
4855 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4856 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4857 decl_mem = (int*)declaration;
4858 for (i = sizeof(declaration0)/sizeof(*decl_mem); i < sizeof(declaration)/sizeof(*decl_mem); i++)
4860 equal = memcmp(&decl_mem[i], &filler_b, sizeof(filler_b));
4861 ok(equal == 0,
4862 "GetDeclaration wrote past the D3DDECL_END() marker. "
4863 "Got %#x, expected %#x\n", decl_mem[i], filler_b);
4864 if (equal != 0) break;
4867 /* UpdateSemantics does not check for overlapping fields */
4868 memset(declaration, 0, sizeof(declaration));
4869 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4870 if (FAILED(hr))
4872 skip("Couldn't get vertex declaration %#x\n", hr);
4873 goto cleanup;
4876 for (decl_ptr = declaration; decl_ptr->Stream != 0xFF; decl_ptr++)
4878 if (decl_ptr->Type == D3DDECLTYPE_FLOAT3)
4880 decl_ptr->Type = D3DDECLTYPE_FLOAT4;
4884 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration);
4885 ok(hr == D3D_OK, "Test UpdateSematics for overlapping fields, "
4886 "got %#x expected D3D_OK\n", hr);
4888 /* Set the position type to color instead of float3 */
4889 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_pos_type_color);
4890 ok(hr == D3D_OK, "Test UpdateSematics position type color, "
4891 "got %#x expected D3D_OK\n", hr);
4893 /* The following test cases show that NULL, smaller or larger declarations,
4894 * and declarations with non-zero Stream values are not accepted.
4895 * UpdateSemantics returns D3DERR_INVALIDCALL and the previously set
4896 * declaration will be used by DrawSubset, GetNumBytesPerVertex, and
4897 * GetDeclaration.
4900 /* Null declaration (invalid declaration) */
4901 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4902 hr = mesh->lpVtbl->UpdateSemantics(mesh, NULL);
4903 ok(hr == D3DERR_INVALIDCALL, "Test UpdateSematics null pointer declaration, "
4904 "got %#x expected D3DERR_INVALIDCALL\n", hr);
4905 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4906 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4907 vertex_size, exp_vertex_size);
4908 memset(declaration, 0, sizeof(declaration));
4909 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4910 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4911 equal = memcmp(declaration, declaration0, sizeof(declaration0));
4912 ok(equal == 0, "Vertex declarations were not equal\n");
4914 /* Smaller vertex declaration (invalid declaration) */
4915 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4916 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_smaller);
4917 ok(hr == D3DERR_INVALIDCALL, "Test UpdateSematics for smaller vertex declaration, "
4918 "got %#x expected D3DERR_INVALIDCALL\n", hr);
4919 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4920 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4921 vertex_size, exp_vertex_size);
4922 memset(declaration, 0, sizeof(declaration));
4923 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4924 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4925 equal = memcmp(declaration, declaration0, sizeof(declaration0));
4926 ok(equal == 0, "Vertex declarations were not equal\n");
4928 /* Larger vertex declaration (invalid declaration) */
4929 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4930 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_larger);
4931 ok(hr == D3DERR_INVALIDCALL, "Test UpdateSematics for larger vertex declaration, "
4932 "got %#x expected D3DERR_INVALIDCALL\n", hr);
4933 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4934 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4935 vertex_size, exp_vertex_size);
4936 memset(declaration, 0, sizeof(declaration));
4937 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4938 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4939 equal = memcmp(declaration, declaration0, sizeof(declaration0));
4940 ok(equal == 0, "Vertex declarations were not equal\n");
4942 /* Use multiple streams and keep the same vertex size (invalid declaration) */
4943 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4944 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_multiple_streams);
4945 ok(hr == D3DERR_INVALIDCALL, "Test UpdateSematics using multiple streams, "
4946 "got %#x expected D3DERR_INVALIDCALL\n", hr);
4947 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4948 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4949 vertex_size, exp_vertex_size);
4950 memset(declaration, 0, sizeof(declaration));
4951 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4952 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4953 equal = memcmp(declaration, declaration0, sizeof(declaration0));
4954 ok(equal == 0, "Vertex declarations were not equal\n");
4956 /* The next following test cases show that some invalid declarations are
4957 * accepted with a D3D_OK. An access violation is thrown on Windows if
4958 * DrawSubset is called. The methods GetNumBytesPerVertex and GetDeclaration
4959 * are not affected, which indicates that the declaration is cached.
4962 /* Double usage (invalid declaration) */
4963 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4964 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_double_usage);
4965 ok(hr == D3D_OK, "Test UpdateSematics double usage, "
4966 "got %#x expected D3D_OK\n", hr);
4967 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4968 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4969 vertex_size, exp_vertex_size);
4970 memset(declaration, 0, sizeof(declaration));
4971 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4972 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4973 equal = memcmp(declaration, declaration_double_usage, sizeof(declaration_double_usage));
4974 ok(equal == 0, "Vertex declarations were not equal\n");
4976 /* Set the position to an undefined type (invalid declaration) */
4977 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4978 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_undefined_type);
4979 ok(hr == D3D_OK, "Test UpdateSematics undefined type, "
4980 "got %#x expected D3D_OK\n", hr);
4981 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4982 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4983 vertex_size, exp_vertex_size);
4984 memset(declaration, 0, sizeof(declaration));
4985 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4986 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4987 equal = memcmp(declaration, declaration_undefined_type, sizeof(declaration_undefined_type));
4988 ok(equal == 0, "Vertex declarations were not equal\n");
4990 /* Use a not 4 byte aligned offset (invalid declaration) */
4991 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4992 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_not_4_byte_aligned_offset);
4993 ok(hr == D3D_OK, "Test UpdateSematics not 4 byte aligned offset, "
4994 "got %#x expected D3D_OK\n", hr);
4995 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4996 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4997 vertex_size, exp_vertex_size);
4998 memset(declaration, 0, sizeof(declaration));
4999 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
5000 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
5001 equal = memcmp(declaration, declaration_not_4_byte_aligned_offset,
5002 sizeof(declaration_not_4_byte_aligned_offset));
5003 ok(equal == 0, "Vertex declarations were not equal\n");
5005 cleanup:
5006 if (mesh)
5007 mesh->lpVtbl->Release(mesh);
5009 free_test_context(test_context);
5012 static void test_create_skin_info(void)
5014 HRESULT hr;
5015 ID3DXSkinInfo *skininfo = NULL;
5016 D3DVERTEXELEMENT9 empty_declaration[] = { D3DDECL_END() };
5017 D3DVERTEXELEMENT9 declaration_out[MAX_FVF_DECL_SIZE];
5018 const D3DVERTEXELEMENT9 declaration_with_nonzero_stream[] = {
5019 {1, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
5020 D3DDECL_END()
5023 hr = D3DXCreateSkinInfo(0, empty_declaration, 0, &skininfo);
5024 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5025 if (skininfo) IUnknown_Release(skininfo);
5026 skininfo = NULL;
5028 hr = D3DXCreateSkinInfo(1, NULL, 1, &skininfo);
5029 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5031 hr = D3DXCreateSkinInfo(1, declaration_with_nonzero_stream, 1, &skininfo);
5032 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5034 hr = D3DXCreateSkinInfoFVF(1, 0, 1, &skininfo);
5035 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5036 if (skininfo)
5038 DWORD dword_result;
5039 float flt_result;
5040 const char *string_result;
5041 D3DXMATRIX *transform;
5042 D3DXMATRIX identity_matrix;
5044 /* test initial values */
5045 hr = skininfo->lpVtbl->GetDeclaration(skininfo, declaration_out);
5046 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5047 if (SUCCEEDED(hr))
5048 compare_elements(declaration_out, empty_declaration, __LINE__, 0);
5050 dword_result = skininfo->lpVtbl->GetNumBones(skininfo);
5051 ok(dword_result == 1, "Expected 1, got %u\n", dword_result);
5053 flt_result = skininfo->lpVtbl->GetMinBoneInfluence(skininfo);
5054 ok(flt_result == 0.0f, "Expected 0.0, got %g\n", flt_result);
5056 string_result = skininfo->lpVtbl->GetBoneName(skininfo, 0);
5057 ok(string_result == NULL, "Expected NULL, got %p\n", string_result);
5059 dword_result = skininfo->lpVtbl->GetFVF(skininfo);
5060 ok(dword_result == 0, "Expected 0, got %u\n", dword_result);
5062 dword_result = skininfo->lpVtbl->GetNumBoneInfluences(skininfo, 0);
5063 ok(dword_result == 0, "Expected 0, got %u\n", dword_result);
5065 dword_result = skininfo->lpVtbl->GetNumBoneInfluences(skininfo, 1);
5066 ok(dword_result == 0, "Expected 0, got %u\n", dword_result);
5068 transform = skininfo->lpVtbl->GetBoneOffsetMatrix(skininfo, -1);
5069 ok(transform == NULL, "Expected NULL, got %p\n", transform);
5072 /* test [GS]etBoneOffsetMatrix */
5073 hr = skininfo->lpVtbl->SetBoneOffsetMatrix(skininfo, 1, &identity_matrix);
5074 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5076 hr = skininfo->lpVtbl->SetBoneOffsetMatrix(skininfo, 0, NULL);
5077 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5079 D3DXMatrixIdentity(&identity_matrix);
5080 hr = skininfo->lpVtbl->SetBoneOffsetMatrix(skininfo, 0, &identity_matrix);
5081 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5083 transform = skininfo->lpVtbl->GetBoneOffsetMatrix(skininfo, 0);
5084 check_matrix(transform, &identity_matrix);
5088 /* test [GS]etBoneName */
5089 const char *name_in = "testBoneName";
5090 const char *string_result2;
5092 hr = skininfo->lpVtbl->SetBoneName(skininfo, 1, name_in);
5093 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5095 hr = skininfo->lpVtbl->SetBoneName(skininfo, 0, NULL);
5096 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5098 hr = skininfo->lpVtbl->SetBoneName(skininfo, 0, name_in);
5099 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5101 string_result = skininfo->lpVtbl->GetBoneName(skininfo, 0);
5102 ok(string_result != NULL, "Expected non-NULL string, got %p\n", string_result);
5103 ok(!strcmp(string_result, name_in), "Expected '%s', got '%s'\n", name_in, string_result);
5105 string_result2 = skininfo->lpVtbl->GetBoneName(skininfo, 0);
5106 ok(string_result == string_result2, "Expected %p, got %p\n", string_result, string_result2);
5108 string_result = skininfo->lpVtbl->GetBoneName(skininfo, 1);
5109 ok(string_result == NULL, "Expected NULL, got %p\n", string_result);
5113 /* test [GS]etBoneInfluence */
5114 DWORD vertices[2];
5115 FLOAT weights[2];
5116 int i;
5117 DWORD num_influences;
5118 DWORD exp_vertices[2];
5119 FLOAT exp_weights[2];
5121 /* vertex and weight arrays untouched when num_influences is 0 */
5122 vertices[0] = 0xdeadbeef;
5123 weights[0] = FLT_MAX;
5124 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, vertices, weights);
5125 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5126 ok(vertices[0] == 0xdeadbeef, "expected 0xdeadbeef, got %#x\n", vertices[0]);
5127 ok(weights[0] == FLT_MAX, "expected %g, got %g\n", FLT_MAX, weights[0]);
5129 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 1, vertices, weights);
5130 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5132 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, NULL, NULL);
5133 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5135 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, vertices, NULL);
5136 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5138 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, NULL, weights);
5139 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5142 /* no vertex or weight value checking */
5143 exp_vertices[0] = 0;
5144 exp_vertices[1] = 0x87654321;
5145 exp_weights[0] = 0.5;
5146 exp_weights[1] = NAN;
5147 num_influences = 2;
5149 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 1, num_influences, vertices, weights);
5150 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5152 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, num_influences, NULL, weights);
5153 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5155 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, num_influences, vertices, NULL);
5156 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5158 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, num_influences, NULL, NULL);
5159 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5161 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, num_influences, exp_vertices, exp_weights);
5162 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5164 memset(vertices, 0, sizeof(vertices));
5165 memset(weights, 0, sizeof(weights));
5166 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, vertices, weights);
5167 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5168 for (i = 0; i < num_influences; i++) {
5169 ok(exp_vertices[i] == vertices[i],
5170 "influence[%d]: expected vertex %u, got %u\n", i, exp_vertices[i], vertices[i]);
5171 ok((isnan(exp_weights[i]) && isnan(weights[i])) || exp_weights[i] == weights[i],
5172 "influence[%d]: expected weights %g, got %g\n", i, exp_weights[i], weights[i]);
5175 /* vertices and weights aren't returned after setting num_influences to 0 */
5176 memset(vertices, 0, sizeof(vertices));
5177 memset(weights, 0, sizeof(weights));
5178 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, 0, vertices, weights);
5179 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5181 vertices[0] = 0xdeadbeef;
5182 weights[0] = FLT_MAX;
5183 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, vertices, weights);
5184 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5185 ok(vertices[0] == 0xdeadbeef, "expected vertex 0xdeadbeef, got %u\n", vertices[0]);
5186 ok(weights[0] == FLT_MAX, "expected weight %g, got %g\n", FLT_MAX, weights[0]);
5190 /* test [GS]etFVF and [GS]etDeclaration */
5191 D3DVERTEXELEMENT9 declaration_in[MAX_FVF_DECL_SIZE];
5192 DWORD fvf = D3DFVF_XYZ;
5193 DWORD got_fvf;
5195 hr = skininfo->lpVtbl->SetDeclaration(skininfo, NULL);
5196 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5198 hr = skininfo->lpVtbl->SetDeclaration(skininfo, declaration_with_nonzero_stream);
5199 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5201 hr = skininfo->lpVtbl->SetFVF(skininfo, 0);
5202 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5204 hr = D3DXDeclaratorFromFVF(fvf, declaration_in);
5205 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5206 hr = skininfo->lpVtbl->SetDeclaration(skininfo, declaration_in);
5207 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5208 got_fvf = skininfo->lpVtbl->GetFVF(skininfo);
5209 ok(fvf == got_fvf, "Expected %#x, got %#x\n", fvf, got_fvf);
5210 hr = skininfo->lpVtbl->GetDeclaration(skininfo, declaration_out);
5211 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5212 compare_elements(declaration_out, declaration_in, __LINE__, 0);
5214 hr = skininfo->lpVtbl->SetDeclaration(skininfo, empty_declaration);
5215 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5216 got_fvf = skininfo->lpVtbl->GetFVF(skininfo);
5217 ok(got_fvf == 0, "Expected 0, got %#x\n", got_fvf);
5218 hr = skininfo->lpVtbl->GetDeclaration(skininfo, declaration_out);
5219 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5220 compare_elements(declaration_out, empty_declaration, __LINE__, 0);
5222 hr = skininfo->lpVtbl->SetFVF(skininfo, fvf);
5223 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5224 got_fvf = skininfo->lpVtbl->GetFVF(skininfo);
5225 ok(fvf == got_fvf, "Expected %#x, got %#x\n", fvf, got_fvf);
5226 hr = skininfo->lpVtbl->GetDeclaration(skininfo, declaration_out);
5227 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5228 compare_elements(declaration_out, declaration_in, __LINE__, 0);
5231 if (skininfo) IUnknown_Release(skininfo);
5232 skininfo = NULL;
5234 hr = D3DXCreateSkinInfoFVF(1, D3DFVF_XYZ, 1, NULL);
5235 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5237 hr = D3DXCreateSkinInfo(1, NULL, 1, &skininfo);
5238 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5241 static void test_convert_adjacency_to_point_reps(void)
5243 HRESULT hr;
5244 struct test_context *test_context = NULL;
5245 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
5246 const DWORD options_16bit = D3DXMESH_SYSTEMMEM;
5247 const D3DVERTEXELEMENT9 declaration[] =
5249 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
5250 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
5251 {0, 24, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
5252 D3DDECL_END()
5254 const unsigned int VERTS_PER_FACE = 3;
5255 void *vertex_buffer;
5256 void *index_buffer;
5257 DWORD *attributes_buffer;
5258 int i, j;
5259 enum color { RED = 0xffff0000, GREEN = 0xff00ff00, BLUE = 0xff0000ff};
5260 struct vertex_pnc
5262 D3DXVECTOR3 position;
5263 D3DXVECTOR3 normal;
5264 enum color color; /* In case of manual visual inspection */
5266 D3DXVECTOR3 up = {0.0f, 0.0f, 1.0f};
5267 /* mesh0 (one face)
5269 * 0--1
5270 * | /
5271 * |/
5274 const struct vertex_pnc vertices0[] =
5276 {{ 0.0f, 3.0f, 0.f}, up, RED},
5277 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5278 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5280 const DWORD indices0[] = {0, 1, 2};
5281 const unsigned int num_vertices0 = ARRAY_SIZE(vertices0);
5282 const unsigned int num_faces0 = ARRAY_SIZE(indices0) / VERTS_PER_FACE;
5283 const DWORD adjacency0[] = {-1, -1, -1};
5284 const DWORD exp_point_rep0[] = {0, 1, 2};
5285 /* mesh1 (right)
5287 * 0--1 3
5288 * | / /|
5289 * |/ / |
5290 * 2 5--4
5292 const struct vertex_pnc vertices1[] =
5294 {{ 0.0f, 3.0f, 0.f}, up, RED},
5295 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5296 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5298 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5299 {{ 3.0f, 0.0f, 0.f}, up, RED},
5300 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5302 const DWORD indices1[] = {0, 1, 2, 3, 4, 5};
5303 const unsigned int num_vertices1 = ARRAY_SIZE(vertices1);
5304 const unsigned int num_faces1 = ARRAY_SIZE(indices1) / VERTS_PER_FACE;
5305 const DWORD adjacency1[] = {-1, 1, -1, -1, -1, 0};
5306 const DWORD exp_point_rep1[] = {0, 1, 2, 1, 4, 2};
5307 /* mesh2 (left)
5309 * 3 0--1
5310 * /| | /
5311 * / | |/
5312 * 5--4 2
5314 const struct vertex_pnc vertices2[] =
5316 {{ 0.0f, 3.0f, 0.f}, up, RED},
5317 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5318 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5320 {{-1.0f, 3.0f, 0.f}, up, RED},
5321 {{-1.0f, 0.0f, 0.f}, up, GREEN},
5322 {{-3.0f, 0.0f, 0.f}, up, BLUE},
5324 const DWORD indices2[] = {0, 1, 2, 3, 4, 5};
5325 const unsigned int num_vertices2 = ARRAY_SIZE(vertices2);
5326 const unsigned int num_faces2 = ARRAY_SIZE(indices2) / VERTS_PER_FACE;
5327 const DWORD adjacency2[] = {-1, -1, 1, 0, -1, -1};
5328 const DWORD exp_point_rep2[] = {0, 1, 2, 0, 2, 5};
5329 /* mesh3 (above)
5332 * /|
5333 * / |
5334 * 5--4
5335 * 0--1
5336 * | /
5337 * |/
5340 struct vertex_pnc vertices3[] =
5342 {{ 0.0f, 3.0f, 0.f}, up, RED},
5343 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5344 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5346 {{ 2.0f, 7.0f, 0.f}, up, BLUE},
5347 {{ 2.0f, 4.0f, 0.f}, up, GREEN},
5348 {{ 0.0f, 4.0f, 0.f}, up, RED},
5350 const DWORD indices3[] = {0, 1, 2, 3, 4, 5};
5351 const unsigned int num_vertices3 = ARRAY_SIZE(vertices3);
5352 const unsigned int num_faces3 = ARRAY_SIZE(indices3) / VERTS_PER_FACE;
5353 const DWORD adjacency3[] = {1, -1, -1, -1, 0, -1};
5354 const DWORD exp_point_rep3[] = {0, 1, 2, 3, 1, 0};
5355 /* mesh4 (below, tip against tip)
5357 * 0--1
5358 * | /
5359 * |/
5362 * |\
5363 * | \
5364 * 5--4
5366 struct vertex_pnc vertices4[] =
5368 {{ 0.0f, 3.0f, 0.f}, up, RED},
5369 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5370 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5372 {{ 0.0f, -4.0f, 0.f}, up, BLUE},
5373 {{ 2.0f, -7.0f, 0.f}, up, GREEN},
5374 {{ 0.0f, -7.0f, 0.f}, up, RED},
5376 const DWORD indices4[] = {0, 1, 2, 3, 4, 5};
5377 const unsigned int num_vertices4 = ARRAY_SIZE(vertices4);
5378 const unsigned int num_faces4 = ARRAY_SIZE(indices4) / VERTS_PER_FACE;
5379 const DWORD adjacency4[] = {-1, -1, -1, -1, -1, -1};
5380 const DWORD exp_point_rep4[] = {0, 1, 2, 3, 4, 5};
5381 /* mesh5 (gap in mesh)
5383 * 0 3-----4 15
5384 * / \ \ / / \
5385 * / \ \ / / \
5386 * 2-----1 5 17-----16
5387 * 6-----7 9 12-----13
5388 * \ / / \ \ /
5389 * \ / / \ \ /
5390 * 8 10-----11 14
5393 const struct vertex_pnc vertices5[] =
5395 {{ 0.0f, 1.0f, 0.f}, up, RED},
5396 {{ 1.0f, -1.0f, 0.f}, up, GREEN},
5397 {{-1.0f, -1.0f, 0.f}, up, BLUE},
5399 {{ 0.1f, 1.0f, 0.f}, up, RED},
5400 {{ 2.1f, 1.0f, 0.f}, up, BLUE},
5401 {{ 1.1f, -1.0f, 0.f}, up, GREEN},
5403 {{-1.0f, -1.1f, 0.f}, up, BLUE},
5404 {{ 1.0f, -1.1f, 0.f}, up, GREEN},
5405 {{ 0.0f, -3.1f, 0.f}, up, RED},
5407 {{ 1.1f, -1.1f, 0.f}, up, GREEN},
5408 {{ 2.1f, -3.1f, 0.f}, up, BLUE},
5409 {{ 0.1f, -3.1f, 0.f}, up, RED},
5411 {{ 1.2f, -1.1f, 0.f}, up, GREEN},
5412 {{ 3.2f, -1.1f, 0.f}, up, RED},
5413 {{ 2.2f, -3.1f, 0.f}, up, BLUE},
5415 {{ 2.2f, 1.0f, 0.f}, up, BLUE},
5416 {{ 3.2f, -1.0f, 0.f}, up, RED},
5417 {{ 1.2f, -1.0f, 0.f}, up, GREEN},
5419 const DWORD indices5[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17};
5420 const unsigned int num_vertices5 = ARRAY_SIZE(vertices5);
5421 const unsigned int num_faces5 = ARRAY_SIZE(indices5) / VERTS_PER_FACE;
5422 const DWORD adjacency5[] = {-1, 2, -1, -1, 5, -1, 0, -1, -1, 4, -1, -1, 5, -1, 3, -1, 4, 1};
5423 const DWORD exp_point_rep5[] = {0, 1, 2, 3, 4, 5, 2, 1, 8, 5, 10, 11, 5, 13, 10, 4, 13, 5};
5424 const WORD indices5_16bit[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17};
5425 /* mesh6 (indices re-ordering)
5427 * 0--1 6 3
5428 * | / /| |\
5429 * |/ / | | \
5430 * 2 8--7 5--4
5432 const struct vertex_pnc vertices6[] =
5434 {{ 0.0f, 3.0f, 0.f}, up, RED},
5435 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5436 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5438 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5439 {{ 3.0f, 0.0f, 0.f}, up, RED},
5440 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5442 {{ 4.0f, 3.0f, 0.f}, up, GREEN},
5443 {{ 6.0f, 0.0f, 0.f}, up, BLUE},
5444 {{ 4.0f, 0.0f, 0.f}, up, RED},
5446 const DWORD indices6[] = {0, 1, 2, 6, 7, 8, 3, 4, 5};
5447 const unsigned int num_vertices6 = ARRAY_SIZE(vertices6);
5448 const unsigned int num_faces6 = ARRAY_SIZE(indices6) / VERTS_PER_FACE;
5449 const DWORD adjacency6[] = {-1, 1, -1, 2, -1, 0, -1, -1, 1};
5450 const DWORD exp_point_rep6[] = {0, 1, 2, 1, 4, 5, 1, 5, 2};
5451 /* mesh7 (expands collapsed triangle)
5453 * 0--1 3
5454 * | / /|
5455 * |/ / |
5456 * 2 5--4
5458 const struct vertex_pnc vertices7[] =
5460 {{ 0.0f, 3.0f, 0.f}, up, RED},
5461 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5462 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5464 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5465 {{ 3.0f, 0.0f, 0.f}, up, RED},
5466 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5468 const DWORD indices7[] = {0, 1, 2, 3, 3, 3}; /* Face 1 is collapsed*/
5469 const unsigned int num_vertices7 = ARRAY_SIZE(vertices7);
5470 const unsigned int num_faces7 = ARRAY_SIZE(indices7) / VERTS_PER_FACE;
5471 const DWORD adjacency7[] = {-1, -1, -1, -1, -1, -1};
5472 const DWORD exp_point_rep7[] = {0, 1, 2, 3, 4, 5};
5473 /* mesh8 (indices re-ordering and double replacement)
5475 * 0--1 9 6
5476 * | / /| |\
5477 * |/ / | | \
5478 * 2 11-10 8--7
5479 * 3--4
5480 * | /
5481 * |/
5484 const struct vertex_pnc vertices8[] =
5486 {{ 0.0f, 3.0f, 0.f}, up, RED},
5487 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5488 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5490 {{ 4.0, -4.0, 0.f}, up, RED},
5491 {{ 6.0, -4.0, 0.f}, up, BLUE},
5492 {{ 4.0, -7.0, 0.f}, up, GREEN},
5494 {{ 4.0f, 3.0f, 0.f}, up, GREEN},
5495 {{ 6.0f, 0.0f, 0.f}, up, BLUE},
5496 {{ 4.0f, 0.0f, 0.f}, up, RED},
5498 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5499 {{ 3.0f, 0.0f, 0.f}, up, RED},
5500 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5502 const DWORD indices8[] = {0, 1, 2, 9, 10, 11, 6, 7, 8, 3, 4, 5};
5503 const unsigned int num_vertices8 = ARRAY_SIZE(vertices8);
5504 const unsigned int num_faces8 = ARRAY_SIZE(indices8) / VERTS_PER_FACE;
5505 const DWORD adjacency8[] = {-1, 1, -1, 2, -1, 0, -1, 3, 1, 2, -1, -1};
5506 const DWORD exp_point_rep8[] = {0, 1, 2, 3, 4, 5, 1, 4, 3, 1, 3, 2};
5507 /* mesh9 (right, shared vertices)
5509 * 0--1
5510 * | /|
5511 * |/ |
5512 * 2--3
5514 const struct vertex_pnc vertices9[] =
5516 {{ 0.0f, 3.0f, 0.f}, up, RED},
5517 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5518 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5520 {{ 2.0f, 0.0f, 0.f}, up, RED},
5522 const DWORD indices9[] = {0, 1, 2, 1, 3, 2};
5523 const unsigned int num_vertices9 = ARRAY_SIZE(vertices9);
5524 const unsigned int num_faces9 = ARRAY_SIZE(indices9) / VERTS_PER_FACE;
5525 const DWORD adjacency9[] = {-1, 1, -1, -1, -1, 0};
5526 const DWORD exp_point_rep9[] = {0, 1, 2, 3};
5527 /* All mesh data */
5528 ID3DXMesh *mesh = NULL;
5529 ID3DXMesh *mesh_null_check = NULL;
5530 unsigned int attributes[] = {0};
5531 struct
5533 const struct vertex_pnc *vertices;
5534 const DWORD *indices;
5535 const DWORD num_vertices;
5536 const DWORD num_faces;
5537 const DWORD *adjacency;
5538 const DWORD *exp_point_reps;
5539 const DWORD options;
5541 tc[] =
5544 vertices0,
5545 indices0,
5546 num_vertices0,
5547 num_faces0,
5548 adjacency0,
5549 exp_point_rep0,
5550 options
5553 vertices1,
5554 indices1,
5555 num_vertices1,
5556 num_faces1,
5557 adjacency1,
5558 exp_point_rep1,
5559 options
5562 vertices2,
5563 indices2,
5564 num_vertices2,
5565 num_faces2,
5566 adjacency2,
5567 exp_point_rep2,
5568 options
5571 vertices3,
5572 indices3,
5573 num_vertices3,
5574 num_faces3,
5575 adjacency3,
5576 exp_point_rep3,
5577 options
5580 vertices4,
5581 indices4,
5582 num_vertices4,
5583 num_faces4,
5584 adjacency4,
5585 exp_point_rep4,
5586 options
5589 vertices5,
5590 indices5,
5591 num_vertices5,
5592 num_faces5,
5593 adjacency5,
5594 exp_point_rep5,
5595 options
5598 vertices6,
5599 indices6,
5600 num_vertices6,
5601 num_faces6,
5602 adjacency6,
5603 exp_point_rep6,
5604 options
5607 vertices7,
5608 indices7,
5609 num_vertices7,
5610 num_faces7,
5611 adjacency7,
5612 exp_point_rep7,
5613 options
5616 vertices8,
5617 indices8,
5618 num_vertices8,
5619 num_faces8,
5620 adjacency8,
5621 exp_point_rep8,
5622 options
5625 vertices9,
5626 indices9,
5627 num_vertices9,
5628 num_faces9,
5629 adjacency9,
5630 exp_point_rep9,
5631 options
5634 vertices5,
5635 (DWORD*)indices5_16bit,
5636 num_vertices5,
5637 num_faces5,
5638 adjacency5,
5639 exp_point_rep5,
5640 options_16bit
5643 DWORD *point_reps = NULL;
5645 test_context = new_test_context();
5646 if (!test_context)
5648 skip("Couldn't create test context\n");
5649 goto cleanup;
5652 for (i = 0; i < ARRAY_SIZE(tc); i++)
5654 hr = D3DXCreateMesh(tc[i].num_faces, tc[i].num_vertices, tc[i].options, declaration,
5655 test_context->device, &mesh);
5656 if (FAILED(hr))
5658 skip("Couldn't create mesh %d. Got %x expected D3D_OK\n", i, hr);
5659 goto cleanup;
5662 if (i == 0) /* Save first mesh for later NULL checks */
5663 mesh_null_check = mesh;
5665 point_reps = HeapAlloc(GetProcessHeap(), 0, tc[i].num_vertices * sizeof(*point_reps));
5666 if (!point_reps)
5668 skip("Couldn't allocate point reps array.\n");
5669 goto cleanup;
5672 hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, &vertex_buffer);
5673 if (FAILED(hr))
5675 skip("Couldn't lock vertex buffer.\n");
5676 goto cleanup;
5678 memcpy(vertex_buffer, tc[i].vertices, tc[i].num_vertices * sizeof(*tc[i].vertices));
5679 hr = mesh->lpVtbl->UnlockVertexBuffer(mesh);
5680 if (FAILED(hr))
5682 skip("Couldn't unlock vertex buffer.\n");
5683 goto cleanup;
5686 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, &index_buffer);
5687 if (FAILED(hr))
5689 skip("Couldn't lock index buffer.\n");
5690 goto cleanup;
5692 if (tc[i].options & D3DXMESH_32BIT)
5694 memcpy(index_buffer, tc[i].indices, VERTS_PER_FACE * tc[i].num_faces * sizeof(DWORD));
5696 else
5698 memcpy(index_buffer, tc[i].indices, VERTS_PER_FACE * tc[i].num_faces * sizeof(WORD));
5700 hr = mesh->lpVtbl->UnlockIndexBuffer(mesh);
5701 if (FAILED(hr)) {
5702 skip("Couldn't unlock index buffer.\n");
5703 goto cleanup;
5706 hr = mesh->lpVtbl->LockAttributeBuffer(mesh, 0, &attributes_buffer);
5707 if (FAILED(hr))
5709 skip("Couldn't lock attributes buffer.\n");
5710 goto cleanup;
5712 memcpy(attributes_buffer, attributes, sizeof(attributes));
5713 hr = mesh->lpVtbl->UnlockAttributeBuffer(mesh);
5714 if (FAILED(hr))
5716 skip("Couldn't unlock attributes buffer.\n");
5717 goto cleanup;
5720 /* Convert adjacency to point representation */
5721 for (j = 0; j < tc[i].num_vertices; j++) point_reps[j] = -1;
5722 hr = mesh->lpVtbl->ConvertAdjacencyToPointReps(mesh, tc[i].adjacency, point_reps);
5723 ok(hr == D3D_OK, "ConvertAdjacencyToPointReps failed case %d. "
5724 "Got %x expected D3D_OK\n", i, hr);
5726 /* Check point representation */
5727 for (j = 0; j < tc[i].num_vertices; j++)
5729 ok(point_reps[j] == tc[i].exp_point_reps[j],
5730 "Unexpected point representation at (%d, %d)."
5731 " Got %d expected %d\n",
5732 i, j, point_reps[j], tc[i].exp_point_reps[j]);
5735 HeapFree(GetProcessHeap(), 0, point_reps);
5736 point_reps = NULL;
5738 if (i != 0) /* First mesh will be freed during cleanup */
5739 mesh->lpVtbl->Release(mesh);
5742 /* NULL checks */
5743 hr = mesh_null_check->lpVtbl->ConvertAdjacencyToPointReps(mesh_null_check, tc[0].adjacency, NULL);
5744 ok(hr == D3DERR_INVALIDCALL, "ConvertAdjacencyToPointReps point_reps NULL. "
5745 "Got %x expected D3DERR_INVALIDCALL\n", hr);
5746 hr = mesh_null_check->lpVtbl->ConvertAdjacencyToPointReps(mesh_null_check, NULL, NULL);
5747 ok(hr == D3DERR_INVALIDCALL, "ConvertAdjacencyToPointReps adjacency and point_reps NULL. "
5748 "Got %x expected D3DERR_INVALIDCALL\n", hr);
5750 cleanup:
5751 if (mesh_null_check)
5752 mesh_null_check->lpVtbl->Release(mesh_null_check);
5753 HeapFree(GetProcessHeap(), 0, point_reps);
5754 free_test_context(test_context);
5757 static void test_convert_point_reps_to_adjacency(void)
5759 HRESULT hr;
5760 struct test_context *test_context = NULL;
5761 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
5762 const DWORD options_16bit = D3DXMESH_SYSTEMMEM;
5763 const D3DVERTEXELEMENT9 declaration[] =
5765 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
5766 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
5767 {0, 24, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
5768 D3DDECL_END()
5770 const unsigned int VERTS_PER_FACE = 3;
5771 void *vertex_buffer;
5772 void *index_buffer;
5773 DWORD *attributes_buffer;
5774 int i, j;
5775 enum color { RED = 0xffff0000, GREEN = 0xff00ff00, BLUE = 0xff0000ff};
5776 struct vertex_pnc
5778 D3DXVECTOR3 position;
5779 D3DXVECTOR3 normal;
5780 enum color color; /* In case of manual visual inspection */
5782 D3DXVECTOR3 up = {0.0f, 0.0f, 1.0f};
5783 /* mesh0 (one face)
5785 * 0--1
5786 * | /
5787 * |/
5790 const struct vertex_pnc vertices0[] =
5792 {{ 0.0f, 3.0f, 0.f}, up, RED},
5793 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5794 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5796 const DWORD indices0[] = {0, 1, 2};
5797 const unsigned int num_vertices0 = ARRAY_SIZE(vertices0);
5798 const unsigned int num_faces0 = num_vertices0 / VERTS_PER_FACE;
5799 const DWORD exp_adjacency0[] = {-1, -1, -1};
5800 const DWORD exp_id_adjacency0[] = {-1, -1, -1};
5801 const DWORD point_rep0[] = {0, 1, 2};
5802 /* mesh1 (right)
5804 * 0--1 3
5805 * | / /|
5806 * |/ / |
5807 * 2 5--4
5809 const struct vertex_pnc vertices1[] =
5811 {{ 0.0f, 3.0f, 0.f}, up, RED},
5812 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5813 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5815 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5816 {{ 3.0f, 0.0f, 0.f}, up, RED},
5817 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5819 const DWORD indices1[] = {0, 1, 2, 3, 4, 5};
5820 const unsigned int num_vertices1 = ARRAY_SIZE(vertices1);
5821 const unsigned int num_faces1 = num_vertices1 / VERTS_PER_FACE;
5822 const DWORD exp_adjacency1[] = {-1, 1, -1, -1, -1, 0};
5823 const DWORD exp_id_adjacency1[] = {-1, -1, -1, -1, -1, -1};
5824 const DWORD point_rep1[] = {0, 1, 2, 1, 4, 2};
5825 /* mesh2 (left)
5827 * 3 0--1
5828 * /| | /
5829 * / | |/
5830 * 5--4 2
5832 const struct vertex_pnc vertices2[] =
5834 {{ 0.0f, 3.0f, 0.f}, up, RED},
5835 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5836 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5838 {{-1.0f, 3.0f, 0.f}, up, RED},
5839 {{-1.0f, 0.0f, 0.f}, up, GREEN},
5840 {{-3.0f, 0.0f, 0.f}, up, BLUE},
5842 const DWORD indices2[] = {0, 1, 2, 3, 4, 5};
5843 const unsigned int num_vertices2 = ARRAY_SIZE(vertices2);
5844 const unsigned int num_faces2 = num_vertices2 / VERTS_PER_FACE;
5845 const DWORD exp_adjacency2[] = {-1, -1, 1, 0, -1, -1};
5846 const DWORD exp_id_adjacency2[] = {-1, -1, -1, -1, -1, -1};
5847 const DWORD point_rep2[] = {0, 1, 2, 0, 2, 5};
5848 /* mesh3 (above)
5851 * /|
5852 * / |
5853 * 5--4
5854 * 0--1
5855 * | /
5856 * |/
5859 struct vertex_pnc vertices3[] =
5861 {{ 0.0f, 3.0f, 0.f}, up, RED},
5862 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5863 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5865 {{ 2.0f, 7.0f, 0.f}, up, BLUE},
5866 {{ 2.0f, 4.0f, 0.f}, up, GREEN},
5867 {{ 0.0f, 4.0f, 0.f}, up, RED},
5869 const DWORD indices3[] = {0, 1, 2, 3, 4, 5};
5870 const unsigned int num_vertices3 = ARRAY_SIZE(vertices3);
5871 const unsigned int num_faces3 = num_vertices3 / VERTS_PER_FACE;
5872 const DWORD exp_adjacency3[] = {1, -1, -1, -1, 0, -1};
5873 const DWORD exp_id_adjacency3[] = {-1, -1, -1, -1, -1, -1};
5874 const DWORD point_rep3[] = {0, 1, 2, 3, 1, 0};
5875 /* mesh4 (below, tip against tip)
5877 * 0--1
5878 * | /
5879 * |/
5882 * |\
5883 * | \
5884 * 5--4
5886 struct vertex_pnc vertices4[] =
5888 {{ 0.0f, 3.0f, 0.f}, up, RED},
5889 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5890 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5892 {{ 0.0f, -4.0f, 0.f}, up, BLUE},
5893 {{ 2.0f, -7.0f, 0.f}, up, GREEN},
5894 {{ 0.0f, -7.0f, 0.f}, up, RED},
5896 const DWORD indices4[] = {0, 1, 2, 3, 4, 5};
5897 const unsigned int num_vertices4 = ARRAY_SIZE(vertices4);
5898 const unsigned int num_faces4 = num_vertices4 / VERTS_PER_FACE;
5899 const DWORD exp_adjacency4[] = {-1, -1, -1, -1, -1, -1};
5900 const DWORD exp_id_adjacency4[] = {-1, -1, -1, -1, -1, -1};
5901 const DWORD point_rep4[] = {0, 1, 2, 3, 4, 5};
5902 /* mesh5 (gap in mesh)
5904 * 0 3-----4 15
5905 * / \ \ / / \
5906 * / \ \ / / \
5907 * 2-----1 5 17-----16
5908 * 6-----7 9 12-----13
5909 * \ / / \ \ /
5910 * \ / / \ \ /
5911 * 8 10-----11 14
5914 const struct vertex_pnc vertices5[] =
5916 {{ 0.0f, 1.0f, 0.f}, up, RED},
5917 {{ 1.0f, -1.0f, 0.f}, up, GREEN},
5918 {{-1.0f, -1.0f, 0.f}, up, BLUE},
5920 {{ 0.1f, 1.0f, 0.f}, up, RED},
5921 {{ 2.1f, 1.0f, 0.f}, up, BLUE},
5922 {{ 1.1f, -1.0f, 0.f}, up, GREEN},
5924 {{-1.0f, -1.1f, 0.f}, up, BLUE},
5925 {{ 1.0f, -1.1f, 0.f}, up, GREEN},
5926 {{ 0.0f, -3.1f, 0.f}, up, RED},
5928 {{ 1.1f, -1.1f, 0.f}, up, GREEN},
5929 {{ 2.1f, -3.1f, 0.f}, up, BLUE},
5930 {{ 0.1f, -3.1f, 0.f}, up, RED},
5932 {{ 1.2f, -1.1f, 0.f}, up, GREEN},
5933 {{ 3.2f, -1.1f, 0.f}, up, RED},
5934 {{ 2.2f, -3.1f, 0.f}, up, BLUE},
5936 {{ 2.2f, 1.0f, 0.f}, up, BLUE},
5937 {{ 3.2f, -1.0f, 0.f}, up, RED},
5938 {{ 1.2f, -1.0f, 0.f}, up, GREEN},
5940 const DWORD indices5[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17};
5941 const unsigned int num_vertices5 = ARRAY_SIZE(vertices5);
5942 const unsigned int num_faces5 = num_vertices5 / VERTS_PER_FACE;
5943 const DWORD exp_adjacency5[] = {-1, 2, -1, -1, 5, -1, 0, -1, -1, 4, -1, -1, 5, -1, 3, -1, 4, 1};
5944 const DWORD exp_id_adjacency5[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
5945 const DWORD point_rep5[] = {0, 1, 2, 3, 4, 5, 2, 1, 8, 5, 10, 11, 5, 13, 10, 4, 13, 5};
5946 /* mesh6 (indices re-ordering)
5948 * 0--1 6 3
5949 * | / /| |\
5950 * |/ / | | \
5951 * 2 8--7 5--4
5953 const struct vertex_pnc vertices6[] =
5955 {{ 0.0f, 3.0f, 0.f}, up, RED},
5956 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5957 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5959 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5960 {{ 3.0f, 0.0f, 0.f}, up, RED},
5961 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5963 {{ 4.0f, 3.0f, 0.f}, up, GREEN},
5964 {{ 6.0f, 0.0f, 0.f}, up, BLUE},
5965 {{ 4.0f, 0.0f, 0.f}, up, RED},
5967 const DWORD indices6[] = {0, 1, 2, 6, 7, 8, 3, 4, 5};
5968 const unsigned int num_vertices6 = ARRAY_SIZE(vertices6);
5969 const unsigned int num_faces6 = num_vertices6 / VERTS_PER_FACE;
5970 const DWORD exp_adjacency6[] = {-1, 1, -1, 2, -1, 0, -1, -1, 1};
5971 const DWORD exp_id_adjacency6[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1};
5972 const DWORD point_rep6[] = {0, 1, 2, 1, 4, 5, 1, 5, 2};
5973 /* mesh7 (expands collapsed triangle)
5975 * 0--1 3
5976 * | / /|
5977 * |/ / |
5978 * 2 5--4
5980 const struct vertex_pnc vertices7[] =
5982 {{ 0.0f, 3.0f, 0.f}, up, RED},
5983 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5984 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5986 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5987 {{ 3.0f, 0.0f, 0.f}, up, RED},
5988 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5990 const DWORD indices7[] = {0, 1, 2, 3, 3, 3}; /* Face 1 is collapsed*/
5991 const unsigned int num_vertices7 = ARRAY_SIZE(vertices7);
5992 const unsigned int num_faces7 = num_vertices7 / VERTS_PER_FACE;
5993 const DWORD exp_adjacency7[] = {-1, -1, -1, -1, -1, -1};
5994 const DWORD exp_id_adjacency7[] = {-1, -1, -1, -1, -1, -1};
5995 const DWORD point_rep7[] = {0, 1, 2, 3, 4, 5};
5996 /* mesh8 (indices re-ordering and double replacement)
5998 * 0--1 9 6
5999 * | / /| |\
6000 * |/ / | | \
6001 * 2 11-10 8--7
6002 * 3--4
6003 * | /
6004 * |/
6007 const struct vertex_pnc vertices8[] =
6009 {{ 0.0f, 3.0f, 0.f}, up, RED},
6010 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
6011 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
6013 {{ 4.0, -4.0, 0.f}, up, RED},
6014 {{ 6.0, -4.0, 0.f}, up, BLUE},
6015 {{ 4.0, -7.0, 0.f}, up, GREEN},
6017 {{ 4.0f, 3.0f, 0.f}, up, GREEN},
6018 {{ 6.0f, 0.0f, 0.f}, up, BLUE},
6019 {{ 4.0f, 0.0f, 0.f}, up, RED},
6021 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
6022 {{ 3.0f, 0.0f, 0.f}, up, RED},
6023 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
6025 const DWORD indices8[] = {0, 1, 2, 9, 10, 11, 6, 7, 8, 3, 4, 5};
6026 const WORD indices8_16bit[] = {0, 1, 2, 9, 10, 11, 6, 7, 8, 3, 4, 5};
6027 const unsigned int num_vertices8 = ARRAY_SIZE(vertices8);
6028 const unsigned int num_faces8 = num_vertices8 / VERTS_PER_FACE;
6029 const DWORD exp_adjacency8[] = {-1, 1, -1, 2, -1, 0, -1, 3, 1, 2, -1, -1};
6030 const DWORD exp_id_adjacency8[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
6031 const DWORD point_rep8[] = {0, 1, 2, 3, 4, 5, 1, 4, 3, 1, 3, 2};
6032 /* mesh9 (right, shared vertices)
6034 * 0--1
6035 * | /|
6036 * |/ |
6037 * 2--3
6039 const struct vertex_pnc vertices9[] =
6041 {{ 0.0f, 3.0f, 0.f}, up, RED},
6042 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
6043 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
6045 {{ 2.0f, 0.0f, 0.f}, up, RED},
6047 const DWORD indices9[] = {0, 1, 2, 1, 3, 2};
6048 const unsigned int num_vertices9 = ARRAY_SIZE(vertices9);
6049 const unsigned int num_faces9 = 2;
6050 const DWORD exp_adjacency9[] = {-1, 1, -1, -1, -1, 0};
6051 const DWORD exp_id_adjacency9[] = {-1, 1, -1, -1, -1, 0};
6052 const DWORD point_rep9[] = {0, 1, 2, 3};
6053 /* All mesh data */
6054 ID3DXMesh *mesh = NULL;
6055 ID3DXMesh *mesh_null_check = NULL;
6056 unsigned int attributes[] = {0};
6057 struct
6059 const struct vertex_pnc *vertices;
6060 const DWORD *indices;
6061 const DWORD num_vertices;
6062 const DWORD num_faces;
6063 const DWORD *point_reps;
6064 const DWORD *exp_adjacency;
6065 const DWORD *exp_id_adjacency;
6066 const DWORD options;
6068 tc[] =
6071 vertices0,
6072 indices0,
6073 num_vertices0,
6074 num_faces0,
6075 point_rep0,
6076 exp_adjacency0,
6077 exp_id_adjacency0,
6078 options
6081 vertices1,
6082 indices1,
6083 num_vertices1,
6084 num_faces1,
6085 point_rep1,
6086 exp_adjacency1,
6087 exp_id_adjacency1,
6088 options
6091 vertices2,
6092 indices2,
6093 num_vertices2,
6094 num_faces2,
6095 point_rep2,
6096 exp_adjacency2,
6097 exp_id_adjacency2,
6098 options
6101 vertices3,
6102 indices3,
6103 num_vertices3,
6104 num_faces3,
6105 point_rep3,
6106 exp_adjacency3,
6107 exp_id_adjacency3,
6108 options
6111 vertices4,
6112 indices4,
6113 num_vertices4,
6114 num_faces4,
6115 point_rep4,
6116 exp_adjacency4,
6117 exp_id_adjacency4,
6118 options
6121 vertices5,
6122 indices5,
6123 num_vertices5,
6124 num_faces5,
6125 point_rep5,
6126 exp_adjacency5,
6127 exp_id_adjacency5,
6128 options
6131 vertices6,
6132 indices6,
6133 num_vertices6,
6134 num_faces6,
6135 point_rep6,
6136 exp_adjacency6,
6137 exp_id_adjacency6,
6138 options
6141 vertices7,
6142 indices7,
6143 num_vertices7,
6144 num_faces7,
6145 point_rep7,
6146 exp_adjacency7,
6147 exp_id_adjacency7,
6148 options
6151 vertices8,
6152 indices8,
6153 num_vertices8,
6154 num_faces8,
6155 point_rep8,
6156 exp_adjacency8,
6157 exp_id_adjacency8,
6158 options
6161 vertices9,
6162 indices9,
6163 num_vertices9,
6164 num_faces9,
6165 point_rep9,
6166 exp_adjacency9,
6167 exp_id_adjacency9,
6168 options
6171 vertices8,
6172 (DWORD*)indices8_16bit,
6173 num_vertices8,
6174 num_faces8,
6175 point_rep8,
6176 exp_adjacency8,
6177 exp_id_adjacency8,
6178 options_16bit
6181 DWORD *adjacency = NULL;
6183 test_context = new_test_context();
6184 if (!test_context)
6186 skip("Couldn't create test context\n");
6187 goto cleanup;
6190 for (i = 0; i < ARRAY_SIZE(tc); i++)
6192 hr = D3DXCreateMesh(tc[i].num_faces, tc[i].num_vertices, tc[i].options,
6193 declaration, test_context->device, &mesh);
6194 if (FAILED(hr))
6196 skip("Couldn't create mesh %d. Got %x expected D3D_OK\n", i, hr);
6197 goto cleanup;
6200 if (i == 0) /* Save first mesh for later NULL checks */
6201 mesh_null_check = mesh;
6203 adjacency = HeapAlloc(GetProcessHeap(), 0, VERTS_PER_FACE * tc[i].num_faces * sizeof(*adjacency));
6204 if (!adjacency)
6206 skip("Couldn't allocate adjacency array.\n");
6207 goto cleanup;
6210 hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, &vertex_buffer);
6211 if (FAILED(hr))
6213 skip("Couldn't lock vertex buffer.\n");
6214 goto cleanup;
6216 memcpy(vertex_buffer, tc[i].vertices, tc[i].num_vertices * sizeof(*tc[i].vertices));
6217 hr = mesh->lpVtbl->UnlockVertexBuffer(mesh);
6218 if (FAILED(hr))
6220 skip("Couldn't unlock vertex buffer.\n");
6221 goto cleanup;
6223 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, &index_buffer);
6224 if (FAILED(hr))
6226 skip("Couldn't lock index buffer.\n");
6227 goto cleanup;
6229 if (tc[i].options & D3DXMESH_32BIT)
6231 memcpy(index_buffer, tc[i].indices, VERTS_PER_FACE * tc[i].num_faces * sizeof(DWORD));
6233 else
6235 memcpy(index_buffer, tc[i].indices, VERTS_PER_FACE * tc[i].num_faces * sizeof(WORD));
6237 hr = mesh->lpVtbl->UnlockIndexBuffer(mesh);
6238 if (FAILED(hr)) {
6239 skip("Couldn't unlock index buffer.\n");
6240 goto cleanup;
6243 hr = mesh->lpVtbl->LockAttributeBuffer(mesh, 0, &attributes_buffer);
6244 if (FAILED(hr))
6246 skip("Couldn't lock attributes buffer.\n");
6247 goto cleanup;
6249 memcpy(attributes_buffer, attributes, sizeof(attributes));
6250 hr = mesh->lpVtbl->UnlockAttributeBuffer(mesh);
6251 if (FAILED(hr))
6253 skip("Couldn't unlock attributes buffer.\n");
6254 goto cleanup;
6257 /* Convert point representation to adjacency*/
6258 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++) adjacency[j] = -2;
6260 hr = mesh->lpVtbl->ConvertPointRepsToAdjacency(mesh, tc[i].point_reps, adjacency);
6261 ok(hr == D3D_OK, "ConvertPointRepsToAdjacency failed case %d. "
6262 "Got %x expected D3D_OK\n", i, hr);
6263 /* Check adjacency */
6264 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
6266 ok(adjacency[j] == tc[i].exp_adjacency[j],
6267 "Unexpected adjacency information at (%d, %d)."
6268 " Got %d expected %d\n",
6269 i, j, adjacency[j], tc[i].exp_adjacency[j]);
6272 /* NULL point representation is considered identity. */
6273 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++) adjacency[j] = -2;
6274 hr = mesh_null_check->lpVtbl->ConvertPointRepsToAdjacency(mesh, NULL, adjacency);
6275 ok(hr == D3D_OK, "ConvertPointRepsToAdjacency NULL point_reps. "
6276 "Got %x expected D3D_OK\n", hr);
6277 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
6279 ok(adjacency[j] == tc[i].exp_id_adjacency[j],
6280 "Unexpected adjacency information (id) at (%d, %d)."
6281 " Got %d expected %d\n",
6282 i, j, adjacency[j], tc[i].exp_id_adjacency[j]);
6285 HeapFree(GetProcessHeap(), 0, adjacency);
6286 adjacency = NULL;
6287 if (i != 0) /* First mesh will be freed during cleanup */
6288 mesh->lpVtbl->Release(mesh);
6291 /* NULL checks */
6292 hr = mesh_null_check->lpVtbl->ConvertPointRepsToAdjacency(mesh_null_check, tc[0].point_reps, NULL);
6293 ok(hr == D3DERR_INVALIDCALL, "ConvertPointRepsToAdjacency NULL adjacency. "
6294 "Got %x expected D3DERR_INVALIDCALL\n", hr);
6295 hr = mesh_null_check->lpVtbl->ConvertPointRepsToAdjacency(mesh_null_check, NULL, NULL);
6296 ok(hr == D3DERR_INVALIDCALL, "ConvertPointRepsToAdjacency NULL point_reps and adjacency. "
6297 "Got %x expected D3DERR_INVALIDCALL\n", hr);
6299 cleanup:
6300 if (mesh_null_check)
6301 mesh_null_check->lpVtbl->Release(mesh_null_check);
6302 HeapFree(GetProcessHeap(), 0, adjacency);
6303 free_test_context(test_context);
6306 static HRESULT init_test_mesh(const DWORD num_faces, const DWORD num_vertices,
6307 const DWORD options,
6308 const D3DVERTEXELEMENT9 *declaration,
6309 IDirect3DDevice9 *device, ID3DXMesh **mesh_ptr,
6310 const void *vertices, const DWORD vertex_size,
6311 const DWORD *indices, const DWORD *attributes)
6313 HRESULT hr;
6314 void *vertex_buffer;
6315 void *index_buffer;
6316 DWORD *attributes_buffer;
6317 ID3DXMesh *mesh = NULL;
6319 hr = D3DXCreateMesh(num_faces, num_vertices, options, declaration, device, mesh_ptr);
6320 if (FAILED(hr))
6322 skip("Couldn't create mesh. Got %x expected D3D_OK\n", hr);
6323 goto cleanup;
6325 mesh = *mesh_ptr;
6327 hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, &vertex_buffer);
6328 if (FAILED(hr))
6330 skip("Couldn't lock vertex buffer.\n");
6331 goto cleanup;
6333 memcpy(vertex_buffer, vertices, num_vertices * vertex_size);
6334 hr = mesh->lpVtbl->UnlockVertexBuffer(mesh);
6335 if (FAILED(hr))
6337 skip("Couldn't unlock vertex buffer.\n");
6338 goto cleanup;
6341 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, &index_buffer);
6342 if (FAILED(hr))
6344 skip("Couldn't lock index buffer.\n");
6345 goto cleanup;
6347 if (options & D3DXMESH_32BIT)
6349 if (indices)
6350 memcpy(index_buffer, indices, 3 * num_faces * sizeof(DWORD));
6351 else
6353 /* Fill index buffer with 0, 1, 2, ...*/
6354 DWORD *indices_32bit = (DWORD*)index_buffer;
6355 UINT i;
6356 for (i = 0; i < 3 * num_faces; i++)
6357 indices_32bit[i] = i;
6360 else
6362 if (indices)
6363 memcpy(index_buffer, indices, 3 * num_faces * sizeof(WORD));
6364 else
6366 /* Fill index buffer with 0, 1, 2, ...*/
6367 WORD *indices_16bit = (WORD*)index_buffer;
6368 UINT i;
6369 for (i = 0; i < 3 * num_faces; i++)
6370 indices_16bit[i] = i;
6373 hr = mesh->lpVtbl->UnlockIndexBuffer(mesh);
6374 if (FAILED(hr)) {
6375 skip("Couldn't unlock index buffer.\n");
6376 goto cleanup;
6379 hr = mesh->lpVtbl->LockAttributeBuffer(mesh, 0, &attributes_buffer);
6380 if (FAILED(hr))
6382 skip("Couldn't lock attributes buffer.\n");
6383 goto cleanup;
6386 if (attributes)
6387 memcpy(attributes_buffer, attributes, num_faces * sizeof(*attributes));
6388 else
6389 memset(attributes_buffer, 0, num_faces * sizeof(*attributes));
6391 hr = mesh->lpVtbl->UnlockAttributeBuffer(mesh);
6392 if (FAILED(hr))
6394 skip("Couldn't unlock attributes buffer.\n");
6395 goto cleanup;
6398 hr = D3D_OK;
6399 cleanup:
6400 return hr;
6403 /* Using structs instead of bit-fields in order to avoid compiler issues. */
6404 struct udec3
6406 UINT x;
6407 UINT y;
6408 UINT z;
6409 UINT w;
6412 struct dec3n
6414 INT x;
6415 INT y;
6416 INT z;
6417 INT w;
6420 static DWORD init_udec3_dword(UINT x, UINT y, UINT z, UINT w)
6422 DWORD d = 0;
6424 d |= x & 0x3ff;
6425 d |= (y << 10) & 0xffc00;
6426 d |= (z << 20) & 0x3ff00000;
6427 d |= (w << 30) & 0xc0000000;
6429 return d;
6432 static DWORD init_dec3n_dword(INT x, INT y, INT z, INT w)
6434 DWORD d = 0;
6436 d |= x & 0x3ff;
6437 d |= (y << 10) & 0xffc00;
6438 d |= (z << 20) & 0x3ff00000;
6439 d |= (w << 30) & 0xc0000000;
6441 return d;
6444 static struct udec3 dword_to_udec3(DWORD d)
6446 struct udec3 v;
6448 v.x = d & 0x3ff;
6449 v.y = (d & 0xffc00) >> 10;
6450 v.z = (d & 0x3ff00000) >> 20;
6451 v.w = (d & 0xc0000000) >> 30;
6453 return v;
6456 static struct dec3n dword_to_dec3n(DWORD d)
6458 struct dec3n v;
6460 v.x = d & 0x3ff;
6461 v.y = (d & 0xffc00) >> 10;
6462 v.z = (d & 0x3ff00000) >> 20;
6463 v.w = (d & 0xc0000000) >> 30;
6465 return v;
6468 static void check_vertex_components(int line, int mesh_number, int vertex_number, BYTE *got_ptr, const BYTE *exp_ptr, D3DVERTEXELEMENT9 *declaration)
6470 const char *usage_strings[] =
6472 "position",
6473 "blend weight",
6474 "blend indices",
6475 "normal",
6476 "point size",
6477 "texture coordinates",
6478 "tangent",
6479 "binormal",
6480 "tessellation factor",
6481 "position transformed",
6482 "color",
6483 "fog",
6484 "depth",
6485 "sample"
6487 D3DVERTEXELEMENT9 *decl_ptr;
6488 const float PRECISION = 1e-5f;
6490 for (decl_ptr = declaration; decl_ptr->Stream != 0xFF; decl_ptr++)
6492 switch (decl_ptr->Type)
6494 case D3DDECLTYPE_FLOAT1:
6496 FLOAT *got = (FLOAT*)(got_ptr + decl_ptr->Offset);
6497 FLOAT *exp = (FLOAT*)(exp_ptr + decl_ptr->Offset);
6498 FLOAT diff = fabsf(*got - *exp);
6499 ok_(__FILE__,line)(diff <= PRECISION, "Mesh %d: Got %f for vertex %d %s, expected %f.\n",
6500 mesh_number, *got, vertex_number, usage_strings[decl_ptr->Usage], *exp);
6501 break;
6503 case D3DDECLTYPE_FLOAT2:
6505 D3DXVECTOR2 *got = (D3DXVECTOR2*)(got_ptr + decl_ptr->Offset);
6506 D3DXVECTOR2 *exp = (D3DXVECTOR2*)(exp_ptr + decl_ptr->Offset);
6507 FLOAT diff = max(fabsf(got->x - exp->x), fabsf(got->y - exp->y));
6508 ok_(__FILE__,line)(diff <= PRECISION, "Mesh %d: Got (%f, %f) for vertex %d %s, expected (%f, %f).\n",
6509 mesh_number, got->x, got->y, vertex_number, usage_strings[decl_ptr->Usage], exp->x, exp->y);
6510 break;
6512 case D3DDECLTYPE_FLOAT3:
6514 D3DXVECTOR3 *got = (D3DXVECTOR3*)(got_ptr + decl_ptr->Offset);
6515 D3DXVECTOR3 *exp = (D3DXVECTOR3*)(exp_ptr + decl_ptr->Offset);
6516 FLOAT diff = max(fabsf(got->x - exp->x), fabsf(got->y - exp->y));
6517 diff = max(diff, fabsf(got->z - exp->z));
6518 ok_(__FILE__,line)(diff <= PRECISION, "Mesh %d: Got (%f, %f, %f) for vertex %d %s, expected (%f, %f, %f).\n",
6519 mesh_number, got->x, got->y, got->z, vertex_number, usage_strings[decl_ptr->Usage], exp->x, exp->y, exp->z);
6520 break;
6522 case D3DDECLTYPE_FLOAT4:
6524 D3DXVECTOR4 *got = (D3DXVECTOR4*)(got_ptr + decl_ptr->Offset);
6525 D3DXVECTOR4 *exp = (D3DXVECTOR4*)(exp_ptr + decl_ptr->Offset);
6526 FLOAT diff = max(fabsf(got->x - exp->x), fabsf(got->y - exp->y));
6527 diff = max(diff, fabsf(got->z - exp->z));
6528 diff = max(diff, fabsf(got->w - exp->w));
6529 ok_(__FILE__,line)(diff <= PRECISION, "Mesh %d: Got (%f, %f, %f, %f) for vertex %d %s, expected (%f, %f, %f, %f).\n",
6530 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);
6531 break;
6533 case D3DDECLTYPE_D3DCOLOR:
6535 BYTE *got = got_ptr + decl_ptr->Offset;
6536 const BYTE *exp = exp_ptr + decl_ptr->Offset;
6537 BOOL same_color = got[0] == exp[0] && got[1] == exp[1]
6538 && got[2] == exp[2] && got[3] == exp[3];
6539 const char *color_types[] = {"diffuse", "specular", "undefined color"};
6540 BYTE usage_index = decl_ptr->UsageIndex;
6541 if (usage_index > 1) usage_index = 2;
6542 ok_(__FILE__,line)(same_color, "Mesh %d: Got (%u, %u, %u, %u) for vertex %d %s, expected (%u, %u, %u, %u).\n",
6543 mesh_number, got[0], got[1], got[2], got[3], vertex_number, color_types[usage_index], exp[0], exp[1], exp[2], exp[3]);
6544 break;
6546 case D3DDECLTYPE_UBYTE4:
6547 case D3DDECLTYPE_UBYTE4N:
6549 BYTE *got = got_ptr + decl_ptr->Offset;
6550 const BYTE *exp = exp_ptr + decl_ptr->Offset;
6551 BOOL same = got[0] == exp[0] && got[1] == exp[1]
6552 && got[2] == exp[2] && got[3] == exp[3];
6553 ok_(__FILE__,line)(same, "Mesh %d: Got (%u, %u, %u, %u) for vertex %d %s, expected (%u, %u, %u, %u).\n",
6554 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]);
6555 break;
6557 case D3DDECLTYPE_SHORT2:
6558 case D3DDECLTYPE_SHORT2N:
6560 SHORT *got = (SHORT*)(got_ptr + decl_ptr->Offset);
6561 SHORT *exp = (SHORT*)(exp_ptr + decl_ptr->Offset);
6562 BOOL same = got[0] == exp[0] && got[1] == exp[1];
6563 ok_(__FILE__,line)(same, "Mesh %d: Got (%hd, %hd) for vertex %d %s, expected (%hd, %hd).\n",
6564 mesh_number, got[0], got[1], vertex_number, usage_strings[decl_ptr->Usage], exp[0], exp[1]);
6565 break;
6567 case D3DDECLTYPE_SHORT4:
6568 case D3DDECLTYPE_SHORT4N:
6570 SHORT *got = (SHORT*)(got_ptr + decl_ptr->Offset);
6571 SHORT *exp = (SHORT*)(exp_ptr + decl_ptr->Offset);
6572 BOOL same = got[0] == exp[0] && got[1] == exp[1]
6573 && got[2] == exp[2] && got[3] == exp[3];
6574 ok_(__FILE__,line)(same, "Mesh %d: Got (%hd, %hd, %hd, %hd) for vertex %d %s, expected (%hd, %hd, %hd, %hd).\n",
6575 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]);
6576 break;
6578 case D3DDECLTYPE_USHORT2N:
6580 USHORT *got = (USHORT*)(got_ptr + decl_ptr->Offset);
6581 USHORT *exp = (USHORT*)(exp_ptr + decl_ptr->Offset);
6582 BOOL same = got[0] == exp[0] && got[1] == exp[1];
6583 ok_(__FILE__,line)(same, "Mesh %d: Got (%hu, %hu) for vertex %d %s, expected (%hu, %hu).\n",
6584 mesh_number, got[0], got[1], vertex_number, usage_strings[decl_ptr->Usage], exp[0], exp[1]);
6585 break;
6587 case D3DDECLTYPE_USHORT4N:
6589 USHORT *got = (USHORT*)(got_ptr + decl_ptr->Offset);
6590 USHORT *exp = (USHORT*)(exp_ptr + decl_ptr->Offset);
6591 BOOL same = got[0] == exp[0] && got[1] == exp[1]
6592 && got[2] == exp[2] && got[3] == exp[3];
6593 ok_(__FILE__,line)(same, "Mesh %d: Got (%hu, %hu, %hu, %hu) for vertex %d %s, expected (%hu, %hu, %hu, %hu).\n",
6594 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]);
6595 break;
6597 case D3DDECLTYPE_UDEC3:
6599 DWORD *got = (DWORD*)(got_ptr + decl_ptr->Offset);
6600 DWORD *exp = (DWORD*)(exp_ptr + decl_ptr->Offset);
6601 BOOL same = memcmp(got, exp, sizeof(*got)) == 0;
6602 struct udec3 got_udec3 = dword_to_udec3(*got);
6603 struct udec3 exp_udec3 = dword_to_udec3(*exp);
6604 ok_(__FILE__,line)(same, "Mesh %d: Got (%u, %u, %u, %u) for vertex %d %s, expected (%u, %u, %u, %u).\n",
6605 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);
6607 break;
6609 case D3DDECLTYPE_DEC3N:
6611 DWORD *got = (DWORD*)(got_ptr + decl_ptr->Offset);
6612 DWORD *exp = (DWORD*)(exp_ptr + decl_ptr->Offset);
6613 BOOL same = memcmp(got, exp, sizeof(*got)) == 0;
6614 struct dec3n got_dec3n = dword_to_dec3n(*got);
6615 struct dec3n exp_dec3n = dword_to_dec3n(*exp);
6616 ok_(__FILE__,line)(same, "Mesh %d: Got (%d, %d, %d, %d) for vertex %d %s, expected (%d, %d, %d, %d).\n",
6617 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);
6618 break;
6620 case D3DDECLTYPE_FLOAT16_2:
6622 WORD *got = (WORD*)(got_ptr + decl_ptr->Offset);
6623 WORD *exp = (WORD*)(exp_ptr + decl_ptr->Offset);
6624 BOOL same = got[0] == exp[0] && got[1] == exp[1];
6625 ok_(__FILE__,line)(same, "Mesh %d: Got (%hx, %hx) for vertex %d %s, expected (%hx, %hx).\n",
6626 mesh_number, got[0], got[1], vertex_number, usage_strings[decl_ptr->Usage], exp[0], exp[1]);
6627 break;
6629 case D3DDECLTYPE_FLOAT16_4:
6631 WORD *got = (WORD*)(got_ptr + decl_ptr->Offset);
6632 WORD *exp = (WORD*)(exp_ptr + decl_ptr->Offset);
6633 BOOL same = got[0] == exp[0] && got[1] == exp[1]
6634 && got[2] == exp[2] && got[3] == exp[3];
6635 ok_(__FILE__,line)(same, "Mesh %d: Got (%hx, %hx, %hx, %hx) for vertex %d %s, expected (%hx, %hx, %hx, %hx).\n",
6636 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]);
6637 break;
6639 default:
6640 break;
6645 static void test_weld_vertices(void)
6647 HRESULT hr;
6648 struct test_context *test_context = NULL;
6649 DWORD i;
6650 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
6651 const DWORD options_16bit = D3DXMESH_SYSTEMMEM;
6652 BYTE *vertices = NULL;
6653 DWORD *indices = NULL;
6654 WORD *indices_16bit = NULL;
6655 const UINT VERTS_PER_FACE = 3;
6656 const D3DXVECTOR3 up = {0.0f, 0.0f, 1.0f};
6657 struct vertex_normal
6659 D3DXVECTOR3 position;
6660 D3DXVECTOR3 normal;
6662 struct vertex_blendweight
6664 D3DXVECTOR3 position;
6665 FLOAT blendweight;
6667 struct vertex_texcoord
6669 D3DXVECTOR3 position;
6670 D3DXVECTOR2 texcoord;
6672 struct vertex_color
6674 D3DXVECTOR3 position;
6675 DWORD color;
6677 struct vertex_color_ubyte4
6679 D3DXVECTOR3 position;
6680 BYTE color[4];
6682 struct vertex_texcoord_short2
6684 D3DXVECTOR3 position;
6685 SHORT texcoord[2];
6687 struct vertex_texcoord_ushort2n
6689 D3DXVECTOR3 position;
6690 USHORT texcoord[2];
6692 struct vertex_normal_short4
6694 D3DXVECTOR3 position;
6695 SHORT normal[4];
6697 struct vertex_texcoord_float16_2
6699 D3DXVECTOR3 position;
6700 WORD texcoord[2];
6702 struct vertex_texcoord_float16_4
6704 D3DXVECTOR3 position;
6705 WORD texcoord[4];
6707 struct vertex_normal_udec3
6709 D3DXVECTOR3 position;
6710 DWORD normal;
6712 struct vertex_normal_dec3n
6714 D3DXVECTOR3 position;
6715 DWORD normal;
6717 UINT vertex_size_normal = sizeof(struct vertex_normal);
6718 UINT vertex_size_blendweight = sizeof(struct vertex_blendweight);
6719 UINT vertex_size_texcoord = sizeof(struct vertex_texcoord);
6720 UINT vertex_size_color = sizeof(struct vertex_color);
6721 UINT vertex_size_color_ubyte4 = sizeof(struct vertex_color_ubyte4);
6722 UINT vertex_size_texcoord_short2 = sizeof(struct vertex_texcoord_short2);
6723 UINT vertex_size_normal_short4 = sizeof(struct vertex_normal_short4);
6724 UINT vertex_size_texcoord_float16_2 = sizeof(struct vertex_texcoord_float16_2);
6725 UINT vertex_size_texcoord_float16_4 = sizeof(struct vertex_texcoord_float16_4);
6726 UINT vertex_size_normal_udec3 = sizeof(struct vertex_normal_udec3);
6727 UINT vertex_size_normal_dec3n = sizeof(struct vertex_normal_dec3n);
6728 D3DVERTEXELEMENT9 declaration_normal[] =
6730 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6731 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6732 D3DDECL_END()
6734 D3DVERTEXELEMENT9 declaration_normal3[] =
6736 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 3},
6737 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6738 D3DDECL_END()
6740 D3DVERTEXELEMENT9 declaration_blendweight[] =
6742 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6743 {0, 12, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BLENDWEIGHT, 0},
6744 D3DDECL_END()
6746 D3DVERTEXELEMENT9 declaration_texcoord[] =
6748 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6749 {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6750 D3DDECL_END()
6752 D3DVERTEXELEMENT9 declaration_color[] =
6754 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6755 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
6756 D3DDECL_END()
6758 D3DVERTEXELEMENT9 declaration_color_ubyte4n[] =
6760 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6761 {0, 12, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
6762 D3DDECL_END()
6764 D3DVERTEXELEMENT9 declaration_color_ubyte4[] =
6766 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6767 {0, 12, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
6768 D3DDECL_END()
6770 D3DVERTEXELEMENT9 declaration_texcoord_short2[] =
6772 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6773 {0, 12, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6774 D3DDECL_END()
6776 D3DVERTEXELEMENT9 declaration_texcoord_short2n[] =
6778 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6779 {0, 12, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6780 D3DDECL_END()
6782 D3DVERTEXELEMENT9 declaration_texcoord_ushort2n[] =
6784 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6785 {0, 12, D3DDECLTYPE_USHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6786 D3DDECL_END()
6788 D3DVERTEXELEMENT9 declaration_normal_short4[] =
6790 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6791 {0, 12, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6792 D3DDECL_END()
6794 D3DVERTEXELEMENT9 declaration_normal_short4n[] =
6796 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6797 {0, 12, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6798 D3DDECL_END()
6800 D3DVERTEXELEMENT9 declaration_normal_ushort4n[] =
6802 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6803 {0, 12, D3DDECLTYPE_USHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6804 D3DDECL_END()
6806 D3DVERTEXELEMENT9 declaration_texcoord10[] =
6808 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6809 {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 10},
6810 D3DDECL_END()
6812 D3DVERTEXELEMENT9 declaration_color2[] =
6814 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6815 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 2},
6816 D3DDECL_END()
6818 D3DVERTEXELEMENT9 declaration_color1[] =
6820 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6821 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 1},
6822 D3DDECL_END()
6824 D3DVERTEXELEMENT9 declaration_texcoord_float16_2[] =
6826 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6827 {0, 12, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6828 D3DDECL_END()
6830 D3DVERTEXELEMENT9 declaration_texcoord_float16_4[] =
6832 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6833 {0, 12, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6834 D3DDECL_END()
6836 D3DVERTEXELEMENT9 declaration_normal_udec3[] =
6838 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6839 {0, 12, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6840 D3DDECL_END()
6842 D3DVERTEXELEMENT9 declaration_normal_dec3n[] =
6844 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6845 {0, 12, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6846 D3DDECL_END()
6848 /* Test 0. One face and no welding.
6850 * 0--1
6851 * | /
6852 * |/
6855 const struct vertex vertices0[] =
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 const DWORD indices0[] = {0, 1, 2};
6862 const DWORD attributes0[] = {0};
6863 const DWORD exp_indices0[] = {0, 1, 2};
6864 const UINT num_vertices0 = ARRAY_SIZE(vertices0);
6865 const UINT num_faces0 = ARRAY_SIZE(indices0) / VERTS_PER_FACE;
6866 const DWORD flags0 = D3DXWELDEPSILONS_WELDALL;
6867 /* epsilons0 is NULL */
6868 const DWORD adjacency0[] = {-1, -1, -1};
6869 const struct vertex exp_vertices0[] =
6871 {{ 0.0f, 3.0f, 0.f}, up},
6872 {{ 2.0f, 3.0f, 0.f}, up},
6873 {{ 0.0f, 0.0f, 0.f}, up},
6875 const DWORD exp_face_remap0[] = {0};
6876 const DWORD exp_vertex_remap0[] = {0, 1, 2};
6877 const DWORD exp_new_num_vertices0 = ARRAY_SIZE(exp_vertices0);
6878 /* Test 1. Two vertices should be removed without regard to epsilon.
6880 * 0--1 3
6881 * | / /|
6882 * |/ / |
6883 * 2 5--4
6885 const struct vertex_normal vertices1[] =
6887 {{ 0.0f, 3.0f, 0.f}, up},
6888 {{ 2.0f, 3.0f, 0.f}, up},
6889 {{ 0.0f, 0.0f, 0.f}, up},
6891 {{ 3.0f, 3.0f, 0.f}, up},
6892 {{ 3.0f, 0.0f, 0.f}, up},
6893 {{ 1.0f, 0.0f, 0.f}, up},
6895 const DWORD indices1[] = {0, 1, 2, 3, 4, 5};
6896 const DWORD attributes1[] = {0, 0};
6897 const UINT num_vertices1 = ARRAY_SIZE(vertices1);
6898 const UINT num_faces1 = ARRAY_SIZE(indices1) / VERTS_PER_FACE;
6899 const DWORD flags1 = D3DXWELDEPSILONS_WELDALL;
6900 /* epsilons1 is NULL */
6901 const DWORD adjacency1[] = {-1, 1, -1, -1, -1, 0};
6902 const struct vertex_normal exp_vertices1[] =
6904 {{ 0.0f, 3.0f, 0.f}, up},
6905 {{ 2.0f, 3.0f, 0.f}, up},
6906 {{ 0.0f, 0.0f, 0.f}, up},
6908 {{ 3.0f, 0.0f, 0.f}, up}
6910 const DWORD exp_indices1[] = {0, 1, 2, 1, 3, 2};
6911 const DWORD exp_face_remap1[] = {0, 1};
6912 const DWORD exp_vertex_remap1[] = {0, 1, 2, 4, -1, -1};
6913 const DWORD exp_new_num_vertices1 = ARRAY_SIZE(exp_vertices1);
6914 /* Test 2. Two faces. No vertices should be removed because of normal
6915 * epsilon, but the positions should be replaced. */
6916 const struct vertex_normal vertices2[] =
6918 {{ 0.0f, 3.0f, 0.f}, up},
6919 {{ 2.0f, 3.0f, 0.f}, up},
6920 {{ 0.0f, 0.0f, 0.f}, up},
6922 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
6923 {{ 3.0f, 0.0f, 0.f}, up},
6924 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6926 const DWORD indices2[] = {0, 1, 2, 3, 4, 5};
6927 const DWORD attributes2[] = {0, 0};
6928 const UINT num_vertices2 = ARRAY_SIZE(vertices2);
6929 const UINT num_faces2 = ARRAY_SIZE(indices2) / VERTS_PER_FACE;
6930 DWORD flags2 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
6931 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};
6932 const DWORD adjacency2[] = {-1, 1, -1, -1, -1, 0};
6933 const struct vertex_normal exp_vertices2[] =
6935 {{ 0.0f, 3.0f, 0.f}, up},
6936 {{ 2.0f, 3.0f, 0.f}, up},
6937 {{ 0.0f, 0.0f, 0.f}, up},
6939 {{ 2.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
6940 {{ 3.0f, 0.0f, 0.f}, up},
6941 {{ 0.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6943 const DWORD exp_indices2[] = {0, 1, 2, 3, 4, 5};
6944 const DWORD exp_face_remap2[] = {0, 1};
6945 const DWORD exp_vertex_remap2[] = {0, 1, 2, 3, 4, 5};
6946 const DWORD exp_new_num_vertices2 = ARRAY_SIZE(exp_vertices2);
6947 /* Test 3. Two faces. One vertex should be removed because of normal epsilon. */
6948 const struct vertex_normal vertices3[] =
6950 {{ 0.0f, 3.0f, 0.f}, up},
6951 {{ 2.0f, 3.0f, 0.f}, up},
6952 {{ 0.0f, 0.0f, 0.f}, up},
6954 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
6955 {{ 3.0f, 0.0f, 0.f}, up},
6956 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6958 const DWORD indices3[] = {0, 1, 2, 3, 4, 5};
6959 const DWORD attributes3[] = {0, 0};
6960 const UINT num_vertices3 = ARRAY_SIZE(vertices3);
6961 const UINT num_faces3 = ARRAY_SIZE(indices3) / VERTS_PER_FACE;
6962 DWORD flags3 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
6963 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};
6964 const DWORD adjacency3[] = {-1, 1, -1, -1, -1, 0};
6965 const struct vertex_normal exp_vertices3[] =
6967 {{ 0.0f, 3.0f, 0.f}, up},
6968 {{ 2.0f, 3.0f, 0.f}, up},
6969 {{ 0.0f, 0.0f, 0.f}, up},
6971 {{ 3.0f, 0.0f, 0.f}, up},
6972 {{ 0.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6974 const DWORD exp_indices3[] = {0, 1, 2, 1, 3, 4};
6975 const DWORD exp_face_remap3[] = {0, 1};
6976 const DWORD exp_vertex_remap3[] = {0, 1, 2, 4, 5, -1};
6977 const DWORD exp_new_num_vertices3 = ARRAY_SIZE(exp_vertices3);
6978 /* Test 4 Two faces. Two vertices should be removed. */
6979 const struct vertex_normal vertices4[] =
6981 {{ 0.0f, 3.0f, 0.f}, up},
6982 {{ 2.0f, 3.0f, 0.f}, up},
6983 {{ 0.0f, 0.0f, 0.f}, up},
6985 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
6986 {{ 3.0f, 0.0f, 0.f}, up},
6987 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6989 const DWORD indices4[] = {0, 1, 2, 3, 4, 5};
6990 const DWORD attributes4[] = {0, 0};
6991 const UINT num_vertices4 = ARRAY_SIZE(vertices4);
6992 const UINT num_faces4 = ARRAY_SIZE(indices4) / VERTS_PER_FACE;
6993 DWORD flags4 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
6994 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};
6995 const DWORD adjacency4[] = {-1, 1, -1, -1, -1, 0};
6996 const struct vertex_normal exp_vertices4[] =
6998 {{ 0.0f, 3.0f, 0.f}, up},
6999 {{ 2.0f, 3.0f, 0.f}, up},
7000 {{ 0.0f, 0.0f, 0.f}, up},
7002 {{ 3.0f, 0.0f, 0.f}, up},
7004 const DWORD exp_indices4[] = {0, 1, 2, 1, 3, 2};
7005 const DWORD exp_face_remap4[] = {0, 1};
7006 const DWORD exp_vertex_remap4[] = {0, 1, 2, 4, -1, -1};
7007 const DWORD exp_new_num_vertices4 = ARRAY_SIZE(exp_vertices4);
7008 /* Test 5. Odd face ordering.
7010 * 0--1 6 3
7011 * | / /| |\
7012 * |/ / | | \
7013 * 2 8--7 5--4
7015 const struct vertex_normal vertices5[] =
7017 {{ 0.0f, 3.0f, 0.f}, up},
7018 {{ 2.0f, 3.0f, 0.f}, up},
7019 {{ 0.0f, 0.0f, 0.f}, up},
7021 {{ 3.0f, 3.0f, 0.f}, up},
7022 {{ 3.0f, 0.0f, 0.f}, up},
7023 {{ 1.0f, 0.0f, 0.f}, up},
7025 {{ 4.0f, 3.0f, 0.f}, up},
7026 {{ 6.0f, 0.0f, 0.f}, up},
7027 {{ 4.0f, 0.0f, 0.f}, up},
7029 const DWORD indices5[] = {0, 1, 2, 6, 7, 8, 3, 4, 5};
7030 const DWORD exp_indices5[] = {0, 1, 2, 1, 4, 2, 1, 3, 4};
7031 const DWORD attributes5[] = {0, 0, 0};
7032 const UINT num_vertices5 = ARRAY_SIZE(vertices5);
7033 const UINT num_faces5 = ARRAY_SIZE(indices5) / VERTS_PER_FACE;
7034 DWORD flags5 = D3DXWELDEPSILONS_WELDALL;
7035 const DWORD adjacency5[] = {-1, 1, -1, 2, -1, 0, -1, -1, 1};
7036 const struct vertex_normal exp_vertices5[] =
7038 {{ 0.0f, 3.0f, 0.f}, up},
7039 {{ 2.0f, 3.0f, 0.f}, up},
7040 {{ 0.0f, 0.0f, 0.f}, up},
7042 {{ 3.0f, 0.0f, 0.f}, up},
7043 {{ 1.0f, 0.0f, 0.f}, up},
7045 const DWORD exp_face_remap5[] = {0, 1, 2};
7046 const DWORD exp_vertex_remap5[] = {0, 1, 2, 4, 5, -1, -1, -1, -1};
7047 const DWORD exp_new_num_vertices5 = ARRAY_SIZE(exp_vertices5);
7048 /* Test 6. Two faces. Do not remove flag is used, so no vertices should be
7049 * removed. */
7050 const struct vertex_normal vertices6[] =
7052 {{ 0.0f, 3.0f, 0.f}, up},
7053 {{ 2.0f, 3.0f, 0.f}, up},
7054 {{ 0.0f, 0.0f, 0.f}, up},
7056 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
7057 {{ 3.0f, 0.0f, 0.f}, up},
7058 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
7060 const DWORD indices6[] = {0, 1, 2, 3, 4, 5};
7061 const DWORD attributes6[] = {0, 0};
7062 const UINT num_vertices6 = ARRAY_SIZE(vertices6);
7063 const UINT num_faces6 = ARRAY_SIZE(indices6) / VERTS_PER_FACE;
7064 DWORD flags6 = D3DXWELDEPSILONS_WELDPARTIALMATCHES | D3DXWELDEPSILONS_DONOTREMOVEVERTICES;
7065 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};
7066 const DWORD adjacency6[] = {-1, 1, -1, -1, -1, 0};
7067 const struct vertex_normal exp_vertices6[] =
7069 {{ 0.0f, 3.0f, 0.f}, up},
7070 {{ 2.0f, 3.0f, 0.f}, up},
7071 {{ 0.0f, 0.0f, 0.f}, up},
7073 {{ 2.0f, 3.0f, 0.f}, up},
7074 {{ 3.0f, 0.0f, 0.f}, up},
7075 {{ 0.0f, 0.0f, 0.f}, up},
7078 const DWORD exp_indices6[] = {0, 1, 2, 3, 4, 5};
7079 const DWORD exp_face_remap6[] = {0, 1};
7080 const DWORD exp_vertex_remap6[] = {0, 1, 2, 3, 4, 5};
7081 const DWORD exp_new_num_vertices6 = ARRAY_SIZE(exp_vertices6);
7082 /* Test 7. Same as test 6 but with 16 bit indices. */
7083 const WORD indices6_16bit[] = {0, 1, 2, 3, 4, 5};
7084 /* Test 8. No flags. Same result as D3DXWELDEPSILONS_WELDPARTIALMATCHES. */
7085 const struct vertex_normal vertices8[] =
7087 {{ 0.0f, 3.0f, 0.f}, up},
7088 {{ 2.0f, 3.0f, 0.f}, up},
7089 {{ 0.0f, 0.0f, 0.f}, up},
7091 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
7092 {{ 3.0f, 0.0f, 0.f}, up},
7093 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
7095 const DWORD indices8[] = {0, 1, 2, 1, 3, 4};
7096 const DWORD attributes8[] = {0, 0};
7097 const UINT num_vertices8 = ARRAY_SIZE(vertices8);
7098 const UINT num_faces8 = ARRAY_SIZE(indices8) / VERTS_PER_FACE;
7099 DWORD flags8 = 0;
7100 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};
7101 const DWORD adjacency8[] = {-1, 1, -1, -1, -1, 0};
7102 const struct vertex_normal exp_vertices8[] =
7104 {{ 0.0f, 3.0f, 0.f}, up},
7105 {{ 2.0f, 3.0f, 0.f}, up},
7106 {{ 0.0f, 0.0f, 0.f}, up},
7108 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
7109 {{ 3.0f, 0.0f, 0.f}, up},
7111 const DWORD exp_indices8[] = {0, 1, 2, 1, 3, 4};
7112 const DWORD exp_face_remap8[] = {0, 1};
7113 const DWORD exp_vertex_remap8[] = {0, 1, 2, 3, 4, -1};
7114 const DWORD exp_new_num_vertices8 = ARRAY_SIZE(exp_vertices8);
7115 /* Test 9. Vertices are removed even though they belong to separate
7116 * attribute groups if D3DXWELDEPSILONS_DONOTSPLIT is set. */
7117 const struct vertex_normal vertices9[] =
7119 {{ 0.0f, 3.0f, 0.f}, up},
7120 {{ 2.0f, 3.0f, 0.f}, up},
7121 {{ 0.0f, 0.0f, 0.f}, up},
7123 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
7124 {{ 3.0f, 0.0f, 0.f}, up},
7125 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
7127 const DWORD indices9[] = {0, 1, 2, 3, 4, 5};
7128 const DWORD attributes9[] = {0, 1};
7129 const UINT num_vertices9 = ARRAY_SIZE(vertices9);
7130 const UINT num_faces9 = ARRAY_SIZE(indices9) / VERTS_PER_FACE;
7131 DWORD flags9 = D3DXWELDEPSILONS_WELDPARTIALMATCHES | D3DXWELDEPSILONS_DONOTSPLIT;
7132 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};
7133 const DWORD adjacency9[] = {-1, 1, -1, -1, -1, 0};
7134 const struct vertex_normal exp_vertices9[] =
7136 {{ 0.0f, 3.0f, 0.f}, up},
7137 {{ 2.0f, 3.0f, 0.f}, up},
7138 {{ 0.0f, 0.0f, 0.f}, up},
7140 {{ 3.0f, 0.0f, 0.f}, up},
7142 const DWORD exp_indices9[] = {0, 1, 2, 1, 3, 2};
7143 const DWORD exp_face_remap9[] = {0, 1};
7144 const DWORD exp_vertex_remap9[] = {0, 1, 2, 4, -1, -1};
7145 const DWORD exp_new_num_vertices9 = ARRAY_SIZE(exp_vertices9);
7146 /* Test 10. Weld blendweight (FLOAT1). */
7147 const struct vertex_blendweight vertices10[] =
7149 {{ 0.0f, 3.0f, 0.f}, 1.0f},
7150 {{ 2.0f, 3.0f, 0.f}, 1.0f},
7151 {{ 0.0f, 0.0f, 0.f}, 1.0f},
7153 {{ 3.0f, 3.0f, 0.f}, 0.9},
7154 {{ 3.0f, 0.0f, 0.f}, 1.0},
7155 {{ 1.0f, 0.0f, 0.f}, 0.4},
7157 const DWORD indices10[] = {0, 1, 2, 3, 4, 5};
7158 const DWORD attributes10[] = {0, 0};
7159 const UINT num_vertices10 = ARRAY_SIZE(vertices10);
7160 const UINT num_faces10 = ARRAY_SIZE(indices10) / VERTS_PER_FACE;
7161 DWORD flags10 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7162 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};
7163 const DWORD adjacency10[] = {-1, 1, -1, -1, -1, 0};
7164 const struct vertex_blendweight exp_vertices10[] =
7166 {{ 0.0f, 3.0f, 0.f}, 1.0f},
7167 {{ 2.0f, 3.0f, 0.f}, 1.0f},
7168 {{ 0.0f, 0.0f, 0.f}, 1.0f},
7170 {{ 3.0f, 0.0f, 0.f}, 1.0},
7171 {{ 0.0f, 0.0f, 0.f}, 0.4},
7173 const DWORD exp_indices10[] = {0, 1, 2, 1, 3, 4};
7174 const DWORD exp_face_remap10[] = {0, 1};
7175 const DWORD exp_vertex_remap10[] = {0, 1, 2, 4, 5, -1};
7176 const DWORD exp_new_num_vertices10 = ARRAY_SIZE(exp_vertices10);
7177 /* Test 11. Weld texture coordinates. */
7178 const struct vertex_texcoord vertices11[] =
7180 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f}},
7181 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.7f}},
7182 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
7184 {{ 3.0f, 3.0f, 0.f}, {0.2f, 0.3f}},
7185 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f}},
7186 {{ 1.0f, 0.0f, 0.f}, {0.1f, 0.2f}}
7188 const DWORD indices11[] = {0, 1, 2, 3, 4, 5};
7189 const DWORD attributes11[] = {0, 0};
7190 const UINT num_vertices11 = ARRAY_SIZE(vertices11);
7191 const UINT num_faces11 = ARRAY_SIZE(indices11) / VERTS_PER_FACE;
7192 DWORD flags11 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7193 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};
7194 const DWORD adjacency11[] = {-1, 1, -1, -1, -1, 0};
7195 const struct vertex_texcoord exp_vertices11[] =
7197 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f}},
7198 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.7f}},
7199 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
7201 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f}},
7202 {{ 0.0f, 0.0f, 0.f}, {0.1f, 0.2f}},
7204 const DWORD exp_indices11[] = {0, 1, 2, 1, 3, 4};
7205 const DWORD exp_face_remap11[] = {0, 1};
7206 const DWORD exp_vertex_remap11[] = {0, 1, 2, 4, 5, -1};
7207 const DWORD exp_new_num_vertices11 = ARRAY_SIZE(exp_vertices11);
7208 /* Test 12. Weld with color. */
7209 const struct vertex_color vertices12[] =
7211 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7212 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7213 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7215 {{ 3.0f, 3.0f, 0.f}, 0x00000000},
7216 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7217 {{ 1.0f, 0.0f, 0.f}, 0x88888888},
7219 const DWORD indices12[] = {0, 1, 2, 3, 4, 5};
7220 const DWORD attributes12[] = {0, 0};
7221 const UINT num_vertices12 = ARRAY_SIZE(vertices12);
7222 const UINT num_faces12 = ARRAY_SIZE(indices12) / VERTS_PER_FACE;
7223 DWORD flags12 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7224 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};
7225 const DWORD adjacency12[] = {-1, 1, -1, -1, -1, 0};
7226 const struct vertex_color exp_vertices12[] =
7228 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7229 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7230 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7232 {{ 2.0f, 3.0f, 0.f}, 0x00000000},
7233 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7235 const DWORD exp_indices12[] = {0, 1, 2, 3, 4, 2};
7236 const DWORD exp_face_remap12[] = {0, 1};
7237 const DWORD exp_vertex_remap12[] = {0, 1, 2, 3, 4, -1};
7238 const DWORD exp_new_num_vertices12 = ARRAY_SIZE(exp_vertices12);
7239 /* Test 13. Two faces. One vertex should be removed because of normal epsilon.
7240 * This is similar to test 3, but the declaration has been changed to NORMAL3.
7242 const struct vertex_normal vertices13[] =
7244 {{ 0.0f, 3.0f, 0.f}, up},
7245 {{ 2.0f, 3.0f, 0.f}, up},
7246 {{ 0.0f, 0.0f, 0.f}, up},
7248 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
7249 {{ 3.0f, 0.0f, 0.f}, up},
7250 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
7252 const DWORD indices13[] = {0, 1, 2, 3, 4, 5};
7253 const DWORD attributes13[] = {0, 0};
7254 const UINT num_vertices13 = ARRAY_SIZE(vertices3);
7255 const UINT num_faces13 = ARRAY_SIZE(indices3) / VERTS_PER_FACE;
7256 DWORD flags13 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7257 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};
7258 const DWORD adjacency13[] = {-1, 1, -1, -1, -1, 0};
7259 const struct vertex_normal exp_vertices13[] =
7261 {{ 0.0f, 3.0f, 0.f}, up},
7262 {{ 2.0f, 3.0f, 0.f}, up},
7263 {{ 0.0f, 0.0f, 0.f}, up},
7265 {{ 3.0f, 0.0f, 0.f}, up},
7266 {{ 0.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
7268 const DWORD exp_indices13[] = {0, 1, 2, 1, 3, 4};
7269 const DWORD exp_face_remap13[] = {0, 1};
7270 const DWORD exp_vertex_remap13[] = {0, 1, 2, 4, 5, -1};
7271 const DWORD exp_new_num_vertices13 = ARRAY_SIZE(exp_vertices13);
7272 /* Test 14. Another test for welding with color. */
7273 const struct vertex_color vertices14[] =
7275 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7276 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7277 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7279 {{ 3.0f, 3.0f, 0.f}, 0x00000000},
7280 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7281 {{ 1.0f, 0.0f, 0.f}, 0x01010101},
7283 const DWORD indices14[] = {0, 1, 2, 3, 4, 5};
7284 const DWORD attributes14[] = {0, 0};
7285 const UINT num_vertices14 = ARRAY_SIZE(vertices14);
7286 const UINT num_faces14 = ARRAY_SIZE(indices14) / VERTS_PER_FACE;
7287 DWORD flags14 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7288 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};
7289 const DWORD adjacency14[] = {-1, 1, -1, -1, -1, 0};
7290 const struct vertex_color exp_vertices14[] =
7292 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7293 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7294 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7296 {{ 2.0f, 3.0f, 0.f}, 0x00000000},
7297 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7299 const DWORD exp_indices14[] = {0, 1, 2, 3, 4, 2};
7300 const DWORD exp_face_remap14[] = {0, 1};
7301 const DWORD exp_vertex_remap14[] = {0, 1, 2, 3, 4, -1};
7302 const DWORD exp_new_num_vertices14 = ARRAY_SIZE(exp_vertices14);
7303 /* Test 15. Weld with color, but as UBYTE4N instead of D3DCOLOR. It shows
7304 * that UBYTE4N and D3DCOLOR are compared the same way.
7306 const struct vertex_color_ubyte4 vertices15[] =
7308 {{ 0.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7309 {{ 2.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7310 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7312 {{ 3.0f, 3.0f, 0.f}, { 0, 0, 0, 0}},
7313 {{ 3.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7314 {{ 1.0f, 0.0f, 0.f}, { 1, 1, 1, 1}},
7316 const DWORD indices15[] = {0, 1, 2, 3, 4, 5};
7317 const DWORD attributes15[] = {0, 0};
7318 const UINT num_vertices15 = ARRAY_SIZE(vertices15);
7319 const UINT num_faces15 = ARRAY_SIZE(indices15) / VERTS_PER_FACE;
7320 DWORD flags15 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7321 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};
7322 const DWORD adjacency15[] = {-1, 1, -1, -1, -1, 0};
7323 const struct vertex_color_ubyte4 exp_vertices15[] =
7325 {{ 0.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7326 {{ 2.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7327 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7329 {{ 2.0f, 3.0f, 0.f}, { 0, 0, 0, 0}},
7330 {{ 3.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7332 const DWORD exp_indices15[] = {0, 1, 2, 3, 4, 2};
7333 const DWORD exp_face_remap15[] = {0, 1};
7334 const DWORD exp_vertex_remap15[] = {0, 1, 2, 3, 4, -1};
7335 const DWORD exp_new_num_vertices15 = ARRAY_SIZE(exp_vertices15);
7336 /* Test 16. Weld with color, but as UBYTE4 instead of D3DCOLOR. It shows
7337 * that UBYTE4 is not normalized and that epsilon is truncated and compared
7338 * directly to each of the four bytes.
7340 const struct vertex_color_ubyte4 vertices16[] =
7342 {{ 0.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7343 {{ 2.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7344 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7346 {{ 3.0f, 3.0f, 0.f}, { 0, 0, 0, 0}},
7347 {{ 3.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7348 {{ 1.0f, 0.0f, 0.f}, { 1, 1, 1, 1}},
7350 const DWORD indices16[] = {0, 1, 2, 3, 4, 5};
7351 const DWORD attributes16[] = {0, 0};
7352 const UINT num_vertices16 = ARRAY_SIZE(vertices16);
7353 const UINT num_faces16 = ARRAY_SIZE(indices16) / VERTS_PER_FACE;
7354 DWORD flags16 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7355 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};
7356 const DWORD adjacency16[] = {-1, 1, -1, -1, -1, 0};
7357 const struct vertex_color_ubyte4 exp_vertices16[] =
7359 {{ 0.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7360 {{ 2.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7361 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7363 {{ 2.0f, 3.0f, 0.f}, { 0, 0, 0, 0}},
7364 {{ 3.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7366 const DWORD exp_indices16[] = {0, 1, 2, 3, 4, 2};
7367 const DWORD exp_face_remap16[] = {0, 1};
7368 const DWORD exp_vertex_remap16[] = {0, 1, 2, 3, 4, -1};
7369 const DWORD exp_new_num_vertices16 = ARRAY_SIZE(exp_vertices16);
7370 /* Test 17. Weld texture coordinates but as SHORT2 instead of D3DXVECTOR2.*/
7371 const struct vertex_texcoord_short2 vertices17[] =
7373 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7374 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7375 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7377 {{ 3.0f, 3.0f, 0.f}, {32767, 32767}},
7378 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7379 {{ 1.0f, 0.0f, 0.f}, {32766, 32766}},
7381 const DWORD indices17[] = {0, 1, 2, 3, 4, 5};
7382 const DWORD attributes17[] = {0, 0};
7383 const UINT num_vertices17 = ARRAY_SIZE(vertices17);
7384 const UINT num_faces17 = ARRAY_SIZE(indices17) / VERTS_PER_FACE;
7385 DWORD flags17 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7386 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};
7387 const DWORD adjacency17[] = {-1, 1, -1, -1, -1, 0};
7388 const struct vertex_texcoord_short2 exp_vertices17[] =
7390 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7391 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7392 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7394 {{ 2.0f, 3.0f, 0.f}, {32767, 32767}},
7395 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7397 const DWORD exp_indices17[] = {0, 1, 2, 3, 4, 2};
7398 const DWORD exp_face_remap17[] = {0, 1};
7399 const DWORD exp_vertex_remap17[] = {0, 1, 2, 3, 4, -1};
7400 const DWORD exp_new_num_vertices17 = ARRAY_SIZE(exp_vertices17);
7401 /* Test 18. Weld texture coordinates but as SHORT2N instead of D3DXVECTOR2. */
7402 const struct vertex_texcoord_short2 vertices18[] =
7404 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7405 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7406 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7408 {{ 3.0f, 3.0f, 0.f}, {32767, 32767}},
7409 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7410 {{ 1.0f, 0.0f, 0.f}, {32766, 32766}},
7412 const DWORD indices18[] = {0, 1, 2, 3, 4, 5};
7413 const DWORD attributes18[] = {0, 0};
7414 const UINT num_vertices18 = ARRAY_SIZE(vertices18);
7415 const UINT num_faces18 = ARRAY_SIZE(indices18) / VERTS_PER_FACE;
7416 DWORD flags18 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7417 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};
7418 const DWORD adjacency18[] = {-1, 1, -1, -1, -1, 0};
7419 const struct vertex_texcoord_short2 exp_vertices18[] =
7421 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7422 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7423 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7425 {{ 2.0f, 3.0f, 0.f}, {32767, 32767}},
7426 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7428 const DWORD exp_indices18[] = {0, 1, 2, 3, 4, 2};
7429 const DWORD exp_face_remap18[] = {0, 1};
7430 const DWORD exp_vertex_remap18[] = {0, 1, 2, 3, 4, -1};
7431 const DWORD exp_new_num_vertices18 = ARRAY_SIZE(exp_vertices18);
7432 /* Test 19. Weld texture coordinates but as USHORT2N instead of D3DXVECTOR2. */
7433 const struct vertex_texcoord_ushort2n vertices19[] =
7435 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7436 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7437 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7439 {{ 3.0f, 3.0f, 0.f}, {65535, 65535}},
7440 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7441 {{ 1.0f, 0.0f, 0.f}, {65534, 65534}},
7443 const DWORD indices19[] = {0, 1, 2, 3, 4, 5};
7444 const DWORD attributes19[] = {0, 0};
7445 const UINT num_vertices19 = ARRAY_SIZE(vertices19);
7446 const UINT num_faces19 = ARRAY_SIZE(indices19) / VERTS_PER_FACE;
7447 DWORD flags19 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7448 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};
7449 const DWORD adjacency19[] = {-1, 1, -1, -1, -1, 0};
7450 const struct vertex_texcoord_ushort2n exp_vertices19[] =
7452 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7453 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7454 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7456 {{ 2.0f, 3.0f, 0.f}, {65535, 65535}},
7457 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7459 const DWORD exp_indices19[] = {0, 1, 2, 3, 4, 2};
7460 const DWORD exp_face_remap19[] = {0, 1};
7461 const DWORD exp_vertex_remap19[] = {0, 1, 2, 3, 4, -1};
7462 const DWORD exp_new_num_vertices19 = ARRAY_SIZE(exp_vertices19);
7463 /* Test 20. Weld normal as SHORT4 instead of D3DXVECTOR3. */
7464 const struct vertex_normal_short4 vertices20[] =
7466 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7467 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7468 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7470 {{ 3.0f, 3.0f, 0.f}, {32767, 32767, 32767, 32767}},
7471 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7472 {{ 1.0f, 0.0f, 0.f}, {32766, 32766, 32766, 32766}},
7474 const DWORD indices20[] = {0, 1, 2, 3, 4, 5};
7475 const DWORD attributes20[] = {0, 0};
7476 const UINT num_vertices20 = ARRAY_SIZE(vertices20);
7477 const UINT num_faces20 = ARRAY_SIZE(indices20) / VERTS_PER_FACE;
7478 DWORD flags20 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7479 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};
7480 const DWORD adjacency20[] = {-1, 1, -1, -1, -1, 0};
7481 const struct vertex_normal_short4 exp_vertices20[] =
7483 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7484 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7485 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7487 {{ 2.0f, 3.0f, 0.f}, {32767, 32767, 32767, 32767}},
7488 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7490 const DWORD exp_indices20[] = {0, 1, 2, 3, 4, 2};
7491 const DWORD exp_face_remap20[] = {0, 1};
7492 const DWORD exp_vertex_remap20[] = {0, 1, 2, 3, 4, -1};
7493 const DWORD exp_new_num_vertices20 = ARRAY_SIZE(exp_vertices20);
7494 /* Test 21. Weld normal as SHORT4N instead of D3DXVECTOR3. */
7495 const struct vertex_normal_short4 vertices21[] =
7497 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7498 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7499 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7501 {{ 3.0f, 3.0f, 0.f}, {32767, 32767, 32767, 32767}},
7502 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7503 {{ 1.0f, 0.0f, 0.f}, {32766, 32766, 32766, 32766}},
7505 const DWORD indices21[] = {0, 1, 2, 3, 4, 5};
7506 const DWORD attributes21[] = {0, 0};
7507 const UINT num_vertices21 = ARRAY_SIZE(vertices21);
7508 const UINT num_faces21 = ARRAY_SIZE(indices21) / VERTS_PER_FACE;
7509 DWORD flags21 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7510 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};
7511 const DWORD adjacency21[] = {-1, 1, -1, -1, -1, 0};
7512 const struct vertex_normal_short4 exp_vertices21[] =
7514 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7515 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7516 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7518 {{ 2.0f, 3.0f, 0.f}, {32767, 32767, 32767, 32767}},
7519 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7521 const DWORD exp_indices21[] = {0, 1, 2, 3, 4, 2};
7522 const DWORD exp_face_remap21[] = {0, 1};
7523 const DWORD exp_vertex_remap21[] = {0, 1, 2, 3, 4, -1};
7524 const DWORD exp_new_num_vertices21 = ARRAY_SIZE(exp_vertices21);
7525 /* Test 22. Weld normal as USHORT4N instead of D3DXVECTOR3. */
7526 const struct vertex_normal_short4 vertices22[] =
7528 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7529 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7530 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7532 {{ 3.0f, 3.0f, 0.f}, {65535, 65535, 65535, 65535}},
7533 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7534 {{ 1.0f, 0.0f, 0.f}, {65534, 65534, 65534, 65534}},
7536 const DWORD indices22[] = {0, 1, 2, 3, 4, 5};
7537 const DWORD attributes22[] = {0, 0};
7538 const UINT num_vertices22 = ARRAY_SIZE(vertices22);
7539 const UINT num_faces22 = ARRAY_SIZE(indices22) / VERTS_PER_FACE;
7540 DWORD flags22 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7541 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};
7542 const DWORD adjacency22[] = {-1, 1, -1, -1, -1, 0};
7543 const struct vertex_normal_short4 exp_vertices22[] =
7545 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7546 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7547 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7549 {{ 2.0f, 3.0f, 0.f}, {65535, 65535, 65535, 65535}},
7550 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7552 const DWORD exp_indices22[] = {0, 1, 2, 3, 4, 2};
7553 const DWORD exp_face_remap22[] = {0, 1};
7554 const DWORD exp_vertex_remap22[] = {0, 1, 2, 3, 4, -1};
7555 const DWORD exp_new_num_vertices22 = ARRAY_SIZE(exp_vertices22);
7556 /* Test 23. Weld texture coordinates as FLOAT16_2. Similar to test 11, but
7557 * with texture coordinates converted to float16 in hex. */
7558 const struct vertex_texcoord_float16_2 vertices23[] =
7560 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
7561 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */
7562 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */
7564 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd}}, /* {0.2f, 0.3f} */
7565 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
7566 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */
7568 const DWORD indices23[] = {0, 1, 2, 3, 4, 5};
7569 const DWORD attributes23[] = {0, 0};
7570 const UINT num_vertices23 = ARRAY_SIZE(vertices23);
7571 const UINT num_faces23 = ARRAY_SIZE(indices23) / VERTS_PER_FACE;
7572 DWORD flags23 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7573 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};
7574 const DWORD adjacency23[] = {-1, 1, -1, -1, -1, 0};
7575 const struct vertex_texcoord_float16_2 exp_vertices23[] =
7577 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
7578 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */
7579 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */
7581 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
7582 {{ 0.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */
7584 const DWORD exp_indices23[] = {0, 1, 2, 1, 3, 4};
7585 const DWORD exp_face_remap23[] = {0, 1};
7586 const DWORD exp_vertex_remap23[] = {0, 1, 2, 4, 5, -1};
7587 const DWORD exp_new_num_vertices23 = ARRAY_SIZE(exp_vertices23);
7588 /* Test 24. Weld texture coordinates as FLOAT16_4. Similar to test 24. */
7589 const struct vertex_texcoord_float16_4 vertices24[] =
7591 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}},
7592 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a, 0x3800, 0x399a}},
7593 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd, 0xb266, 0xb4cd}},
7595 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd, 0x3266, 0x34cd}},
7596 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}},
7597 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266, 0x2e66, 0x3266}},
7599 const DWORD indices24[] = {0, 1, 2, 3, 4, 5};
7600 const DWORD attributes24[] = {0, 0};
7601 const UINT num_vertices24 = ARRAY_SIZE(vertices24);
7602 const UINT num_faces24 = ARRAY_SIZE(indices24) / VERTS_PER_FACE;
7603 DWORD flags24 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7604 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};
7605 const DWORD adjacency24[] = {-1, 1, -1, -1, -1, 0};
7606 const struct vertex_texcoord_float16_4 exp_vertices24[] =
7608 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}},
7609 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a, 0x3800, 0x399a}},
7610 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd, 0xb266, 0xb4cd}},
7612 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}},
7613 {{ 0.0f, 0.0f, 0.f}, {0x2e66, 0x3266, 0x2e66, 0x3266}},
7615 const DWORD exp_indices24[] = {0, 1, 2, 1, 3, 4};
7616 const DWORD exp_face_remap24[] = {0, 1};
7617 const DWORD exp_vertex_remap24[] = {0, 1, 2, 4, 5, -1};
7618 const DWORD exp_new_num_vertices24 = ARRAY_SIZE(exp_vertices24);
7619 /* Test 25. Weld texture coordinates with usage index 10 (TEXCOORD10). The
7620 * usage index is capped at 7, so the epsilon for TEXCOORD7 is used instead.
7622 const struct vertex_texcoord vertices25[] =
7624 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f}},
7625 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.7f}},
7626 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
7628 {{ 3.0f, 3.0f, 0.f}, {0.2f, 0.3f}},
7629 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f}},
7630 {{ 1.0f, 0.0f, 0.f}, {0.1f, 0.2f}}
7632 const DWORD indices25[] = {0, 1, 2, 3, 4, 5};
7633 const DWORD attributes25[] = {0, 0};
7634 const UINT num_vertices25 = ARRAY_SIZE(vertices25);
7635 const UINT num_faces25 = ARRAY_SIZE(indices25) / VERTS_PER_FACE;
7636 DWORD flags25 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7637 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};
7638 const DWORD adjacency25[] = {-1, 1, -1, -1, -1, 0};
7639 const struct vertex_texcoord exp_vertices25[] =
7641 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f}},
7642 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.7f}},
7643 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
7645 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f}},
7646 {{ 0.0f, 0.0f, 0.f}, {0.1f, 0.2f}},
7648 const DWORD exp_indices25[] = {0, 1, 2, 1, 3, 4};
7649 const DWORD exp_face_remap25[] = {0, 1};
7650 const DWORD exp_vertex_remap25[] = {0, 1, 2, 4, 5, -1};
7651 const DWORD exp_new_num_vertices25 = ARRAY_SIZE(exp_vertices25);
7652 /* Test 26. Weld color with usage index larger than 1. Shows that none of
7653 * the epsilon values are used. */
7654 const struct vertex_color vertices26[] =
7656 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7657 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7658 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7660 {{ 3.0f, 3.0f, 0.f}, 0x00000000},
7661 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7662 {{ 1.0f, 0.0f, 0.f}, 0x01010101},
7664 const DWORD indices26[] = {0, 1, 2, 3, 4, 5};
7665 const DWORD attributes26[] = {0, 0};
7666 const UINT num_vertices26 = ARRAY_SIZE(vertices26);
7667 const UINT num_faces26 = ARRAY_SIZE(indices26) / VERTS_PER_FACE;
7668 DWORD flags26 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7669 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};
7670 const DWORD adjacency26[] = {-1, 1, -1, -1, -1, 0};
7671 const struct vertex_color exp_vertices26[] =
7673 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7674 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7675 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7677 {{ 2.0f, 3.0f, 0.f}, 0x00000000},
7678 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7679 {{ 0.0f, 0.0f, 0.f}, 0x01010101},
7681 const DWORD exp_indices26[] = {0, 1, 2, 3, 4, 5};
7682 const DWORD exp_face_remap26[] = {0, 1};
7683 const DWORD exp_vertex_remap26[] = {0, 1, 2, 3, 4, 5};
7684 const DWORD exp_new_num_vertices26 = ARRAY_SIZE(exp_vertices26);
7685 /* Test 27. Weld color with usage index 1 (specular). */
7686 /* Previously this test used float color values and index > 1 but that case
7687 * appears to be effectively unhandled in native so the test gave
7688 * inconsistent results. */
7689 const struct vertex_color vertices27[] =
7691 {{ 0.0f, 3.0f, 0.0f}, 0x00000000},
7692 {{ 2.0f, 3.0f, 0.0f}, 0x10203040},
7693 {{ 0.0f, 0.0f, 0.0f}, 0x50607080},
7695 {{ 3.0f, 3.0f, 0.0f}, 0x11213141},
7696 {{ 3.0f, 0.0f, 0.0f}, 0xffffffff},
7697 {{ 1.0f, 0.0f, 0.0f}, 0x51617181},
7699 const DWORD indices27[] = {0, 1, 2, 3, 4, 5};
7700 const DWORD attributes27[] = {0, 0};
7701 const UINT num_vertices27 = ARRAY_SIZE(vertices27);
7702 const UINT num_faces27 = ARRAY_SIZE(indices27) / VERTS_PER_FACE;
7703 DWORD flags27 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7704 const D3DXWELDEPSILONS epsilons27 =
7706 1.1f, 0.0f, 0.0f, 0.0f, 2.0f / 255.0f, 0.0f,
7707 {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, 0.0f, 0.0f, 0.0f
7709 const DWORD adjacency27[] = {-1, 1, -1, -1, -1, 0};
7710 const struct vertex_color exp_vertices27[] =
7712 {{ 0.0f, 3.0f, 0.0f}, 0x00000000},
7713 {{ 2.0f, 3.0f, 0.0f}, 0x10203040},
7714 {{ 0.0f, 0.0f, 0.0f}, 0x50607080},
7716 {{ 3.0f, 0.0f, 0.0f}, 0xffffffff},
7718 const DWORD exp_indices27[] = {0, 1, 2, 1, 3, 2};
7719 const DWORD exp_face_remap27[] = {0, 1};
7720 const DWORD exp_vertex_remap27[] = {0, 1, 2, 4, -1, -1};
7721 const DWORD exp_new_num_vertices27 = ARRAY_SIZE(exp_vertices27);
7722 /* Test 28. Weld one normal with UDEC3. */
7723 const DWORD dword_udec3_zero = init_udec3_dword(0, 0, 0, 1);
7724 const DWORD dword_udec3_1023 = init_udec3_dword(1023, 1023, 1023, 1);
7725 const DWORD dword_udec3_1022 = init_udec3_dword(1022, 1022, 1022, 1);
7726 const struct vertex_normal_udec3 vertices28[] =
7728 {{ 0.0f, 3.0f, 0.f}, dword_udec3_zero},
7729 {{ 2.0f, 3.0f, 0.f}, dword_udec3_zero},
7730 {{ 0.0f, 0.0f, 0.f}, dword_udec3_zero},
7732 {{ 3.0f, 3.0f, 0.f}, dword_udec3_1023},
7733 {{ 3.0f, 0.0f, 0.f}, dword_udec3_zero},
7734 {{ 1.0f, 0.0f, 0.f}, dword_udec3_1022},
7736 const DWORD indices28[] = {0, 1, 2, 3, 4, 5};
7737 const DWORD attributes28[] = {0, 0};
7738 const UINT num_vertices28 = ARRAY_SIZE(vertices28);
7739 const UINT num_faces28 = ARRAY_SIZE(indices28) / VERTS_PER_FACE;
7740 DWORD flags28 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7741 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};
7742 const DWORD adjacency28[] = {-1, 1, -1, -1, -1, 0};
7743 const struct vertex_normal_udec3 exp_vertices28[] =
7745 {{ 0.0f, 3.0f, 0.f}, dword_udec3_zero},
7746 {{ 2.0f, 3.0f, 0.f}, dword_udec3_zero},
7747 {{ 0.0f, 0.0f, 0.f}, dword_udec3_zero},
7749 {{ 2.0f, 3.0f, 0.f}, dword_udec3_1023},
7750 {{ 3.0f, 0.0f, 0.f}, dword_udec3_zero},
7752 const DWORD exp_indices28[] = {0, 1, 2, 3, 4, 2};
7753 const DWORD exp_face_remap28[] = {0, 1};
7754 const DWORD exp_vertex_remap28[] = {0, 1, 2, 3, 4, -1};
7755 const DWORD exp_new_num_vertices28 = ARRAY_SIZE(exp_vertices28);
7756 /* Test 29. Weld one normal with DEC3N. */
7757 const DWORD dword_dec3n_zero = init_dec3n_dword(0, 0, 0, 1);
7758 const DWORD dword_dec3n_511 = init_dec3n_dword(511, 511, 511, 1);
7759 const DWORD dword_dec3n_510 = init_dec3n_dword(510, 510, 510, 1);
7760 const struct vertex_normal_dec3n vertices29[] =
7762 {{ 0.0f, 3.0f, 0.f}, dword_dec3n_zero},
7763 {{ 2.0f, 3.0f, 0.f}, dword_dec3n_zero},
7764 {{ 0.0f, 0.0f, 0.f}, dword_dec3n_zero},
7766 {{ 3.0f, 3.0f, 0.f}, dword_dec3n_511},
7767 {{ 3.0f, 0.0f, 0.f}, dword_dec3n_zero},
7768 {{ 1.0f, 0.0f, 0.f}, dword_dec3n_510},
7770 const DWORD indices29[] = {0, 1, 2, 3, 4, 5};
7771 const DWORD attributes29[] = {0, 0};
7772 const UINT num_vertices29 = ARRAY_SIZE(vertices29);
7773 const UINT num_faces29 = ARRAY_SIZE(indices29) / VERTS_PER_FACE;
7774 DWORD flags29 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7775 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};
7776 const DWORD adjacency29[] = {-1, 1, -1, -1, -1, 0};
7777 const struct vertex_normal_dec3n exp_vertices29[] =
7779 {{ 0.0f, 3.0f, 0.f}, dword_dec3n_zero},
7780 {{ 2.0f, 3.0f, 0.f}, dword_dec3n_zero},
7781 {{ 0.0f, 0.0f, 0.f}, dword_dec3n_zero},
7783 {{ 2.0f, 3.0f, 0.f}, dword_dec3n_511},
7784 {{ 3.0f, 0.0f, 0.f}, dword_dec3n_zero},
7786 const DWORD exp_indices29[] = {0, 1, 2, 3, 4, 2};
7787 const DWORD exp_face_remap29[] = {0, 1};
7788 const DWORD exp_vertex_remap29[] = {0, 1, 2, 3, 4, -1};
7789 const DWORD exp_new_num_vertices29 = ARRAY_SIZE(exp_vertices29);
7790 /* All mesh data */
7791 DWORD *adjacency_out = NULL;
7792 DWORD *face_remap = NULL;
7793 ID3DXMesh *mesh = NULL;
7794 ID3DXBuffer *vertex_remap = NULL;
7795 struct
7797 const BYTE *vertices;
7798 const DWORD *indices;
7799 const DWORD *attributes;
7800 const DWORD num_vertices;
7801 const DWORD num_faces;
7802 const DWORD options;
7803 D3DVERTEXELEMENT9 *declaration;
7804 const UINT vertex_size;
7805 const DWORD flags;
7806 const D3DXWELDEPSILONS *epsilons;
7807 const DWORD *adjacency;
7808 const BYTE *exp_vertices;
7809 const DWORD *exp_indices;
7810 const DWORD *exp_face_remap;
7811 const DWORD *exp_vertex_remap;
7812 const DWORD exp_new_num_vertices;
7814 tc[] =
7817 (BYTE*)vertices0,
7818 indices0,
7819 attributes0,
7820 num_vertices0,
7821 num_faces0,
7822 options,
7823 declaration_normal,
7824 vertex_size_normal,
7825 flags0,
7826 NULL,
7827 adjacency0,
7828 (BYTE*)exp_vertices0,
7829 exp_indices0,
7830 exp_face_remap0,
7831 exp_vertex_remap0,
7832 exp_new_num_vertices0
7835 (BYTE*)vertices1,
7836 indices1,
7837 attributes1,
7838 num_vertices1,
7839 num_faces1,
7840 options,
7841 declaration_normal,
7842 vertex_size_normal,
7843 flags1,
7844 NULL,
7845 adjacency1,
7846 (BYTE*)exp_vertices1,
7847 exp_indices1,
7848 exp_face_remap1,
7849 exp_vertex_remap1,
7850 exp_new_num_vertices1
7853 (BYTE*)vertices2,
7854 indices2,
7855 attributes2,
7856 num_vertices2,
7857 num_faces2,
7858 options,
7859 declaration_normal,
7860 vertex_size_normal,
7861 flags2,
7862 &epsilons2,
7863 adjacency2,
7864 (BYTE*)exp_vertices2,
7865 exp_indices2,
7866 exp_face_remap2,
7867 exp_vertex_remap2,
7868 exp_new_num_vertices2
7871 (BYTE*)vertices3,
7872 indices3,
7873 attributes3,
7874 num_vertices3,
7875 num_faces3,
7876 options,
7877 declaration_normal,
7878 vertex_size_normal,
7879 flags3,
7880 &epsilons3,
7881 adjacency3,
7882 (BYTE*)exp_vertices3,
7883 exp_indices3,
7884 exp_face_remap3,
7885 exp_vertex_remap3,
7886 exp_new_num_vertices3
7889 (BYTE*)vertices4,
7890 indices4,
7891 attributes4,
7892 num_vertices4,
7893 num_faces4,
7894 options,
7895 declaration_normal,
7896 vertex_size_normal,
7897 flags4,
7898 &epsilons4,
7899 adjacency4,
7900 (BYTE*)exp_vertices4,
7901 exp_indices4,
7902 exp_face_remap4,
7903 exp_vertex_remap4,
7904 exp_new_num_vertices4
7906 /* Unusual ordering. */
7908 (BYTE*)vertices5,
7909 indices5,
7910 attributes5,
7911 num_vertices5,
7912 num_faces5,
7913 options,
7914 declaration_normal,
7915 vertex_size_normal,
7916 flags5,
7917 NULL,
7918 adjacency5,
7919 (BYTE*)exp_vertices5,
7920 exp_indices5,
7921 exp_face_remap5,
7922 exp_vertex_remap5,
7923 exp_new_num_vertices5
7926 (BYTE*)vertices6,
7927 indices6,
7928 attributes6,
7929 num_vertices6,
7930 num_faces6,
7931 options,
7932 declaration_normal,
7933 vertex_size_normal,
7934 flags6,
7935 &epsilons6,
7936 adjacency6,
7937 (BYTE*)exp_vertices6,
7938 exp_indices6,
7939 exp_face_remap6,
7940 exp_vertex_remap6,
7941 exp_new_num_vertices6
7944 (BYTE*)vertices6,
7945 (DWORD*)indices6_16bit,
7946 attributes6,
7947 num_vertices6,
7948 num_faces6,
7949 options_16bit,
7950 declaration_normal,
7951 vertex_size_normal,
7952 flags6,
7953 &epsilons6,
7954 adjacency6,
7955 (BYTE*)exp_vertices6,
7956 exp_indices6,
7957 exp_face_remap6,
7958 exp_vertex_remap6,
7959 exp_new_num_vertices6
7962 (BYTE*)vertices8,
7963 indices8,
7964 attributes8,
7965 num_vertices8,
7966 num_faces8,
7967 options,
7968 declaration_normal,
7969 vertex_size_normal,
7970 flags8,
7971 &epsilons8,
7972 adjacency8,
7973 (BYTE*)exp_vertices8,
7974 exp_indices8,
7975 exp_face_remap8,
7976 exp_vertex_remap8,
7977 exp_new_num_vertices8
7980 (BYTE*)vertices9,
7981 indices9,
7982 attributes9,
7983 num_vertices9,
7984 num_faces9,
7985 options,
7986 declaration_normal,
7987 vertex_size_normal,
7988 flags9,
7989 &epsilons9,
7990 adjacency9,
7991 (BYTE*)exp_vertices9,
7992 exp_indices9,
7993 exp_face_remap9,
7994 exp_vertex_remap9,
7995 exp_new_num_vertices9
7998 (BYTE*)vertices10,
7999 indices10,
8000 attributes10,
8001 num_vertices10,
8002 num_faces10,
8003 options,
8004 declaration_blendweight,
8005 vertex_size_blendweight,
8006 flags10,
8007 &epsilons10,
8008 adjacency10,
8009 (BYTE*)exp_vertices10,
8010 exp_indices10,
8011 exp_face_remap10,
8012 exp_vertex_remap10,
8013 exp_new_num_vertices10
8016 (BYTE*)vertices11,
8017 indices11,
8018 attributes11,
8019 num_vertices11,
8020 num_faces11,
8021 options,
8022 declaration_texcoord,
8023 vertex_size_texcoord,
8024 flags11,
8025 &epsilons11,
8026 adjacency11,
8027 (BYTE*)exp_vertices11,
8028 exp_indices11,
8029 exp_face_remap11,
8030 exp_vertex_remap11,
8031 exp_new_num_vertices11
8034 (BYTE*)vertices12,
8035 indices12,
8036 attributes12,
8037 num_vertices12,
8038 num_faces12,
8039 options,
8040 declaration_color,
8041 vertex_size_color,
8042 flags12,
8043 &epsilons12,
8044 adjacency12,
8045 (BYTE*)exp_vertices12,
8046 exp_indices12,
8047 exp_face_remap12,
8048 exp_vertex_remap12,
8049 exp_new_num_vertices12
8052 (BYTE*)vertices13,
8053 indices13,
8054 attributes13,
8055 num_vertices13,
8056 num_faces13,
8057 options,
8058 declaration_normal3,
8059 vertex_size_normal,
8060 flags13,
8061 &epsilons13,
8062 adjacency13,
8063 (BYTE*)exp_vertices13,
8064 exp_indices13,
8065 exp_face_remap13,
8066 exp_vertex_remap13,
8067 exp_new_num_vertices13
8070 (BYTE*)vertices14,
8071 indices14,
8072 attributes14,
8073 num_vertices14,
8074 num_faces14,
8075 options,
8076 declaration_color,
8077 vertex_size_color,
8078 flags14,
8079 &epsilons14,
8080 adjacency14,
8081 (BYTE*)exp_vertices14,
8082 exp_indices14,
8083 exp_face_remap14,
8084 exp_vertex_remap14,
8085 exp_new_num_vertices14
8088 (BYTE*)vertices15,
8089 indices15,
8090 attributes15,
8091 num_vertices15,
8092 num_faces15,
8093 options,
8094 declaration_color_ubyte4n,
8095 vertex_size_color_ubyte4, /* UBYTE4 same size as UBYTE4N */
8096 flags15,
8097 &epsilons15,
8098 adjacency15,
8099 (BYTE*)exp_vertices15,
8100 exp_indices15,
8101 exp_face_remap15,
8102 exp_vertex_remap15,
8103 exp_new_num_vertices15
8106 (BYTE*)vertices16,
8107 indices16,
8108 attributes16,
8109 num_vertices16,
8110 num_faces16,
8111 options,
8112 declaration_color_ubyte4,
8113 vertex_size_color_ubyte4,
8114 flags16,
8115 &epsilons16,
8116 adjacency16,
8117 (BYTE*)exp_vertices16,
8118 exp_indices16,
8119 exp_face_remap16,
8120 exp_vertex_remap16,
8121 exp_new_num_vertices16
8124 (BYTE*)vertices17,
8125 indices17,
8126 attributes17,
8127 num_vertices17,
8128 num_faces17,
8129 options,
8130 declaration_texcoord_short2,
8131 vertex_size_texcoord_short2,
8132 flags17,
8133 &epsilons17,
8134 adjacency17,
8135 (BYTE*)exp_vertices17,
8136 exp_indices17,
8137 exp_face_remap17,
8138 exp_vertex_remap17,
8139 exp_new_num_vertices17
8142 (BYTE*)vertices18,
8143 indices18,
8144 attributes18,
8145 num_vertices18,
8146 num_faces18,
8147 options,
8148 declaration_texcoord_short2n,
8149 vertex_size_texcoord_short2, /* SHORT2 same size as SHORT2N */
8150 flags18,
8151 &epsilons18,
8152 adjacency18,
8153 (BYTE*)exp_vertices18,
8154 exp_indices18,
8155 exp_face_remap18,
8156 exp_vertex_remap18,
8157 exp_new_num_vertices18
8160 (BYTE*)vertices19,
8161 indices19,
8162 attributes19,
8163 num_vertices19,
8164 num_faces19,
8165 options,
8166 declaration_texcoord_ushort2n,
8167 vertex_size_texcoord_short2, /* SHORT2 same size as USHORT2N */
8168 flags19,
8169 &epsilons19,
8170 adjacency19,
8171 (BYTE*)exp_vertices19,
8172 exp_indices19,
8173 exp_face_remap19,
8174 exp_vertex_remap19,
8175 exp_new_num_vertices19
8178 (BYTE*)vertices20,
8179 indices20,
8180 attributes20,
8181 num_vertices20,
8182 num_faces20,
8183 options,
8184 declaration_normal_short4,
8185 vertex_size_normal_short4,
8186 flags20,
8187 &epsilons20,
8188 adjacency20,
8189 (BYTE*)exp_vertices20,
8190 exp_indices20,
8191 exp_face_remap20,
8192 exp_vertex_remap20,
8193 exp_new_num_vertices20
8196 (BYTE*)vertices21,
8197 indices21,
8198 attributes21,
8199 num_vertices21,
8200 num_faces21,
8201 options,
8202 declaration_normal_short4n,
8203 vertex_size_normal_short4, /* SHORT4 same size as SHORT4N */
8204 flags21,
8205 &epsilons21,
8206 adjacency21,
8207 (BYTE*)exp_vertices21,
8208 exp_indices21,
8209 exp_face_remap21,
8210 exp_vertex_remap21,
8211 exp_new_num_vertices21
8214 (BYTE*)vertices22,
8215 indices22,
8216 attributes22,
8217 num_vertices22,
8218 num_faces22,
8219 options,
8220 declaration_normal_ushort4n,
8221 vertex_size_normal_short4, /* SHORT4 same size as USHORT4N */
8222 flags22,
8223 &epsilons22,
8224 adjacency22,
8225 (BYTE*)exp_vertices22,
8226 exp_indices22,
8227 exp_face_remap22,
8228 exp_vertex_remap22,
8229 exp_new_num_vertices22
8232 (BYTE*)vertices23,
8233 indices23,
8234 attributes23,
8235 num_vertices23,
8236 num_faces23,
8237 options,
8238 declaration_texcoord_float16_2,
8239 vertex_size_texcoord_float16_2,
8240 flags23,
8241 &epsilons23,
8242 adjacency23,
8243 (BYTE*)exp_vertices23,
8244 exp_indices23,
8245 exp_face_remap23,
8246 exp_vertex_remap23,
8247 exp_new_num_vertices23
8250 (BYTE*)vertices24,
8251 indices24,
8252 attributes24,
8253 num_vertices24,
8254 num_faces24,
8255 options,
8256 declaration_texcoord_float16_4,
8257 vertex_size_texcoord_float16_4,
8258 flags24,
8259 &epsilons24,
8260 adjacency24,
8261 (BYTE*)exp_vertices24,
8262 exp_indices24,
8263 exp_face_remap24,
8264 exp_vertex_remap24,
8265 exp_new_num_vertices24
8268 (BYTE*)vertices25,
8269 indices25,
8270 attributes25,
8271 num_vertices25,
8272 num_faces25,
8273 options,
8274 declaration_texcoord10,
8275 vertex_size_texcoord,
8276 flags25,
8277 &epsilons25,
8278 adjacency25,
8279 (BYTE*)exp_vertices25,
8280 exp_indices25,
8281 exp_face_remap25,
8282 exp_vertex_remap25,
8283 exp_new_num_vertices25
8286 (BYTE*)vertices26,
8287 indices26,
8288 attributes26,
8289 num_vertices26,
8290 num_faces26,
8291 options,
8292 declaration_color2,
8293 vertex_size_color,
8294 flags26,
8295 &epsilons26,
8296 adjacency26,
8297 (BYTE*)exp_vertices26,
8298 exp_indices26,
8299 exp_face_remap26,
8300 exp_vertex_remap26,
8301 exp_new_num_vertices26
8304 (BYTE*)vertices27,
8305 indices27,
8306 attributes27,
8307 num_vertices27,
8308 num_faces27,
8309 options,
8310 declaration_color1,
8311 vertex_size_color,
8312 flags27,
8313 &epsilons27,
8314 adjacency27,
8315 (BYTE*)exp_vertices27,
8316 exp_indices27,
8317 exp_face_remap27,
8318 exp_vertex_remap27,
8319 exp_new_num_vertices27
8322 (BYTE*)vertices28,
8323 indices28,
8324 attributes28,
8325 num_vertices28,
8326 num_faces28,
8327 options,
8328 declaration_normal_udec3,
8329 vertex_size_normal_udec3,
8330 flags28,
8331 &epsilons28,
8332 adjacency28,
8333 (BYTE*)exp_vertices28,
8334 exp_indices28,
8335 exp_face_remap28,
8336 exp_vertex_remap28,
8337 exp_new_num_vertices28
8340 (BYTE*)vertices29,
8341 indices29,
8342 attributes29,
8343 num_vertices29,
8344 num_faces29,
8345 options,
8346 declaration_normal_dec3n,
8347 vertex_size_normal_dec3n,
8348 flags29,
8349 &epsilons29,
8350 adjacency29,
8351 (BYTE*)exp_vertices29,
8352 exp_indices29,
8353 exp_face_remap29,
8354 exp_vertex_remap29,
8355 exp_new_num_vertices29
8359 test_context = new_test_context();
8360 if (!test_context)
8362 skip("Couldn't create test context\n");
8363 goto cleanup;
8366 for (i = 0; i < ARRAY_SIZE(tc); i++)
8368 DWORD j;
8369 DWORD *vertex_remap_ptr;
8370 DWORD new_num_vertices;
8372 hr = init_test_mesh(tc[i].num_faces, tc[i].num_vertices, tc[i].options,
8373 tc[i].declaration, test_context->device, &mesh,
8374 tc[i].vertices, tc[i].vertex_size,
8375 tc[i].indices, tc[i].attributes);
8376 if (FAILED(hr))
8378 skip("Couldn't initialize test mesh %d.\n", i);
8379 goto cleanup;
8382 /* Allocate out parameters */
8383 adjacency_out = HeapAlloc(GetProcessHeap(), 0, VERTS_PER_FACE * tc[i].num_faces * sizeof(*adjacency_out));
8384 if (!adjacency_out)
8386 skip("Couldn't allocate adjacency_out array.\n");
8387 goto cleanup;
8389 face_remap = HeapAlloc(GetProcessHeap(), 0, tc[i].num_faces * sizeof(*face_remap));
8390 if (!face_remap)
8392 skip("Couldn't allocate face_remap array.\n");
8393 goto cleanup;
8396 hr = D3DXWeldVertices(mesh, tc[i].flags, tc[i].epsilons, tc[i].adjacency,
8397 adjacency_out, face_remap, &vertex_remap);
8398 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
8399 /* Check number of vertices*/
8400 new_num_vertices = mesh->lpVtbl->GetNumVertices(mesh);
8401 ok(new_num_vertices == tc[i].exp_new_num_vertices,
8402 "Mesh %d: new_num_vertices == %d, expected %d.\n",
8403 i, new_num_vertices, tc[i].exp_new_num_vertices);
8404 /* Check index buffer */
8405 if (tc[i].options & D3DXMESH_32BIT)
8407 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, (void**)&indices);
8408 if (FAILED(hr))
8410 skip("Couldn't lock index buffer.\n");
8411 goto cleanup;
8413 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
8415 ok(indices[j] == tc[i].exp_indices[j],
8416 "Mesh %d: indices[%d] == %d, expected %d\n",
8417 i, j, indices[j], tc[i].exp_indices[j]);
8420 else
8422 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, (void**)&indices_16bit);
8423 if (FAILED(hr))
8425 skip("Couldn't lock index buffer.\n");
8426 goto cleanup;
8428 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
8430 ok(indices_16bit[j] == tc[i].exp_indices[j],
8431 "Mesh %d: indices_16bit[%d] == %d, expected %d\n",
8432 i, j, indices_16bit[j], tc[i].exp_indices[j]);
8435 mesh->lpVtbl->UnlockIndexBuffer(mesh);
8436 indices = NULL;
8437 indices_16bit = NULL;
8438 /* Check adjacency_out */
8439 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
8441 ok(adjacency_out[j] == tc[i].adjacency[j],
8442 "Mesh %d: adjacency_out[%d] == %d, expected %d\n",
8443 i, j, adjacency_out[j], tc[i].adjacency[j]);
8445 /* Check face_remap */
8446 for (j = 0; j < tc[i].num_faces; j++)
8448 ok(face_remap[j] == tc[i].exp_face_remap[j],
8449 "Mesh %d: face_remap[%d] == %d, expected %d\n",
8450 i, j, face_remap[j], tc[i].exp_face_remap[j]);
8452 /* Check vertex_remap */
8453 vertex_remap_ptr = vertex_remap->lpVtbl->GetBufferPointer(vertex_remap);
8454 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
8456 ok(vertex_remap_ptr[j] == tc[i].exp_vertex_remap[j],
8457 "Mesh %d: vertex_remap_ptr[%d] == %d, expected %d\n",
8458 i, j, vertex_remap_ptr[j], tc[i].exp_vertex_remap[j]);
8460 /* Check vertex buffer */
8461 hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, (void*)&vertices);
8462 if (FAILED(hr))
8464 skip("Couldn't lock vertex buffer.\n");
8465 goto cleanup;
8467 /* Check contents of re-ordered vertex buffer */
8468 for (j = 0; j < tc[i].exp_new_num_vertices; j++)
8470 int index = tc[i].vertex_size*j;
8471 check_vertex_components(__LINE__, i, j, &vertices[index], &tc[i].exp_vertices[index], tc[i].declaration);
8473 mesh->lpVtbl->UnlockVertexBuffer(mesh);
8474 vertices = NULL;
8476 /* Free mesh and output data */
8477 HeapFree(GetProcessHeap(), 0, adjacency_out);
8478 adjacency_out = NULL;
8479 HeapFree(GetProcessHeap(), 0, face_remap);
8480 face_remap = NULL;
8481 vertex_remap->lpVtbl->Release(vertex_remap);
8482 vertex_remap = NULL;
8483 mesh->lpVtbl->Release(mesh);
8484 mesh = NULL;
8487 cleanup:
8488 HeapFree(GetProcessHeap(), 0, adjacency_out);
8489 HeapFree(GetProcessHeap(), 0, face_remap);
8490 if (indices) mesh->lpVtbl->UnlockIndexBuffer(mesh);
8491 if (indices_16bit) mesh->lpVtbl->UnlockIndexBuffer(mesh);
8492 if (mesh) mesh->lpVtbl->Release(mesh);
8493 if (vertex_remap) vertex_remap->lpVtbl->Release(vertex_remap);
8494 if (vertices) mesh->lpVtbl->UnlockVertexBuffer(mesh);
8495 free_test_context(test_context);
8498 static void test_clone_mesh(void)
8500 HRESULT hr;
8501 struct test_context *test_context = NULL;
8502 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
8503 D3DVERTEXELEMENT9 declaration_pn[] =
8505 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8506 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
8507 D3DDECL_END()
8509 D3DVERTEXELEMENT9 declaration_pntc[] =
8511 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8512 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
8513 {0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8514 D3DDECL_END()
8516 D3DVERTEXELEMENT9 declaration_ptcn[] =
8518 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8519 {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8520 {0, 20, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
8521 D3DDECL_END()
8523 D3DVERTEXELEMENT9 declaration_ptc[] =
8525 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8526 {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8527 D3DDECL_END()
8529 D3DVERTEXELEMENT9 declaration_ptc_float16_2[] =
8531 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8532 {0, 12, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8533 D3DDECL_END()
8535 D3DVERTEXELEMENT9 declaration_ptc_float16_4[] =
8537 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8538 {0, 12, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8539 D3DDECL_END()
8541 D3DVERTEXELEMENT9 declaration_ptc_float1[] =
8543 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8544 {0, 12, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8545 D3DDECL_END()
8547 D3DVERTEXELEMENT9 declaration_ptc_float3[] =
8549 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8550 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8551 D3DDECL_END()
8553 D3DVERTEXELEMENT9 declaration_ptc_float4[] =
8555 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8556 {0, 12, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8557 D3DDECL_END()
8559 D3DVERTEXELEMENT9 declaration_ptc_d3dcolor[] =
8561 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8562 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8563 D3DDECL_END()
8565 D3DVERTEXELEMENT9 declaration_ptc_ubyte4[] =
8567 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8568 {0, 12, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8569 D3DDECL_END()
8571 D3DVERTEXELEMENT9 declaration_ptc_ubyte4n[] =
8573 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8574 {0, 12, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8575 D3DDECL_END()
8577 D3DVERTEXELEMENT9 declaration_ptc_short2[] =
8579 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8580 {0, 12, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8581 D3DDECL_END()
8583 D3DVERTEXELEMENT9 declaration_ptc_short4[] =
8585 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8586 {0, 12, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8587 D3DDECL_END()
8589 D3DVERTEXELEMENT9 declaration_ptc_short2n[] =
8591 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8592 {0, 12, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8593 D3DDECL_END()
8595 D3DVERTEXELEMENT9 declaration_ptc_short4n[] =
8597 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8598 {0, 12, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8599 D3DDECL_END()
8601 D3DVERTEXELEMENT9 declaration_ptc_ushort2n[] =
8603 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8604 {0, 12, D3DDECLTYPE_USHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8605 D3DDECL_END()
8607 D3DVERTEXELEMENT9 declaration_ptc_ushort4n[] =
8609 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8610 {0, 12, D3DDECLTYPE_USHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8611 D3DDECL_END()
8613 D3DVERTEXELEMENT9 declaration_ptc_float16_2_partialu[] =
8615 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8616 {0, 12, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_PARTIALU, D3DDECLUSAGE_TEXCOORD, 0},
8617 D3DDECL_END()
8619 D3DVERTEXELEMENT9 declaration_pntc1[] =
8621 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8622 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
8623 {0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
8624 D3DDECL_END()
8626 const unsigned int VERTS_PER_FACE = 3;
8627 BYTE *vertices = NULL;
8628 INT i;
8629 struct vertex_pn
8631 D3DXVECTOR3 position;
8632 D3DXVECTOR3 normal;
8634 struct vertex_pntc
8636 D3DXVECTOR3 position;
8637 D3DXVECTOR3 normal;
8638 D3DXVECTOR2 texcoords;
8640 struct vertex_ptcn
8642 D3DXVECTOR3 position;
8643 D3DXVECTOR2 texcoords;
8644 D3DXVECTOR3 normal;
8646 struct vertex_ptc
8648 D3DXVECTOR3 position;
8649 D3DXVECTOR2 texcoords;
8651 struct vertex_ptc_float16_2
8653 D3DXVECTOR3 position;
8654 WORD texcoords[2]; /* float16_2 */
8656 struct vertex_ptc_float16_4
8658 D3DXVECTOR3 position;
8659 WORD texcoords[4]; /* float16_4 */
8661 struct vertex_ptc_float1
8663 D3DXVECTOR3 position;
8664 FLOAT texcoords;
8666 struct vertex_ptc_float3
8668 D3DXVECTOR3 position;
8669 FLOAT texcoords[3];
8671 struct vertex_ptc_float4
8673 D3DXVECTOR3 position;
8674 FLOAT texcoords[4];
8676 struct vertex_ptc_d3dcolor
8678 D3DXVECTOR3 position;
8679 BYTE texcoords[4];
8681 struct vertex_ptc_ubyte4
8683 D3DXVECTOR3 position;
8684 BYTE texcoords[4];
8686 struct vertex_ptc_ubyte4n
8688 D3DXVECTOR3 position;
8689 BYTE texcoords[4];
8691 struct vertex_ptc_short2
8693 D3DXVECTOR3 position;
8694 SHORT texcoords[2];
8696 struct vertex_ptc_short4
8698 D3DXVECTOR3 position;
8699 SHORT texcoords[4];
8701 struct vertex_ptc_ushort2n
8703 D3DXVECTOR3 position;
8704 USHORT texcoords[2];
8706 struct vertex_ptc_ushort4n
8708 D3DXVECTOR3 position;
8709 USHORT texcoords[4];
8711 struct vertex_ptc_udec3
8713 D3DXVECTOR3 position;
8714 DWORD texcoords;
8716 struct vertex_ptc_dec3n
8718 D3DXVECTOR3 position;
8719 DWORD texcoords;
8721 D3DXVECTOR3 up = {0.0f, 0.0f, 1.0f};
8722 D3DXVECTOR2 zero_vec2 = {0.0f, 0.0f};
8723 /* Test 0. Check that a mesh can be cloned if the new declaration is the
8724 * same as the one used to create the mesh.
8726 * 0--1 3
8727 * | / /|
8728 * |/ / |
8729 * 2 5--4
8731 const struct vertex_pn vertices0[] =
8733 {{ 0.0f, 3.0f, 0.f}, up},
8734 {{ 2.0f, 3.0f, 0.f}, up},
8735 {{ 0.0f, 0.0f, 0.f}, up},
8737 {{ 3.0f, 3.0f, 0.f}, up},
8738 {{ 3.0f, 0.0f, 0.f}, up},
8739 {{ 1.0f, 0.0f, 0.f}, up},
8741 const UINT num_vertices0 = ARRAY_SIZE(vertices0);
8742 const UINT num_faces0 = ARRAY_SIZE(vertices0) / VERTS_PER_FACE;
8743 const UINT vertex_size0 = sizeof(*vertices0);
8744 /* Test 1. Check that 16-bit indices are handled. */
8745 const DWORD options_16bit = D3DXMESH_SYSTEMMEM;
8746 /* Test 2. Check that the size of each vertex is increased and the data
8747 * moved if the new declaration adds an element after the original elements.
8749 const struct vertex_pntc exp_vertices2[] =
8751 {{ 0.0f, 3.0f, 0.f}, up, zero_vec2},
8752 {{ 2.0f, 3.0f, 0.f}, up, zero_vec2},
8753 {{ 0.0f, 0.0f, 0.f}, up, zero_vec2},
8755 {{ 3.0f, 3.0f, 0.f}, up, zero_vec2},
8756 {{ 3.0f, 0.0f, 0.f}, up, zero_vec2},
8757 {{ 1.0f, 0.0f, 0.f}, up, zero_vec2},
8759 const UINT exp_vertex_size2 = sizeof(*exp_vertices2);
8760 /* Test 3. Check that the size of each vertex is increased and the data
8761 * moved if the new declaration adds an element between the original
8762 * elements.
8764 const struct vertex_ptcn exp_vertices3[] =
8766 {{ 0.0f, 3.0f, 0.f}, zero_vec2, up},
8767 {{ 2.0f, 3.0f, 0.f}, zero_vec2, up},
8768 {{ 0.0f, 0.0f, 0.f}, zero_vec2, up},
8770 {{ 3.0f, 3.0f, 0.f}, zero_vec2, up},
8771 {{ 3.0f, 0.0f, 0.f}, zero_vec2, up},
8772 {{ 1.0f, 0.0f, 0.f}, zero_vec2, up},
8774 const UINT exp_vertex_size3 = sizeof(*exp_vertices3);
8775 /* Test 4. Test that data types can be converted, e.g. FLOAT2 to FLOAT16_2. */
8776 const struct vertex_ptc vertices4[] =
8778 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8779 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8780 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
8782 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8783 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
8784 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
8786 const UINT num_vertices4 = ARRAY_SIZE(vertices4);
8787 const UINT num_faces4 = ARRAY_SIZE(vertices4) / VERTS_PER_FACE;
8788 const UINT vertex_size4 = sizeof(*vertices4);
8789 const struct vertex_ptc_float16_2 exp_vertices4[] =
8791 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
8792 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */
8793 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */
8795 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd}}, /* {0.2f, 0.3f} */
8796 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
8797 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */
8799 const UINT exp_vertex_size4 = sizeof(*exp_vertices4);
8800 /* Test 5. Convert FLOAT2 to FLOAT16_4. */
8801 const struct vertex_ptc vertices5[] =
8803 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8804 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8805 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
8807 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8808 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
8809 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
8811 const UINT num_vertices5 = ARRAY_SIZE(vertices5);
8812 const UINT num_faces5 = ARRAY_SIZE(vertices5) / VERTS_PER_FACE;
8813 const UINT vertex_size5 = sizeof(*vertices5);
8814 const struct vertex_ptc_float16_4 exp_vertices5[] =
8816 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00, 0, 0x3c00}}, /* {1.0f, 1.0f, 0.0f, 1.0f} */
8817 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a, 0, 0x3c00}}, /* {0.5f, 0.7f, 0.0f, 1.0f} */
8818 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd, 0, 0x3c00}}, /* {-0.2f, -0.3f, 0.0f, 1.0f} */
8820 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd, 0, 0x3c00}}, /* {0.2f, 0.3f, 0.0f, 1.0f} */
8821 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00, 0, 0x3c00}}, /* {1.0f, 1.0f, 0.0f, 1.0f} */
8822 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266, 0, 0x3c00}}, /* {0.1f, 0.2f, 0.0f, 1.0f} */
8824 const UINT exp_vertex_size5 = sizeof(*exp_vertices5);
8825 /* Test 6. Convert FLOAT2 to FLOAT1. */
8826 const struct vertex_ptc vertices6[] =
8828 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8829 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8830 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
8832 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8833 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
8834 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
8836 const UINT num_vertices6 = ARRAY_SIZE(vertices6);
8837 const UINT num_faces6 = ARRAY_SIZE(vertices6) / VERTS_PER_FACE;
8838 const UINT vertex_size6 = sizeof(*vertices6);
8839 const struct vertex_ptc_float1 exp_vertices6[] =
8841 {{ 0.0f, 3.0f, 0.f}, 1.0f},
8842 {{ 2.0f, 3.0f, 0.f}, 0.5f},
8843 {{ 0.0f, 0.0f, 0.f}, -0.2f},
8845 {{ 3.0f, 3.0f, 0.f}, 0.2f},
8846 {{ 3.0f, 0.0f, 0.f}, 1.0f},
8847 {{ 1.0f, 0.0f, 0.f}, 0.1f},
8849 const UINT exp_vertex_size6 = sizeof(*exp_vertices6);
8850 /* Test 7. Convert FLOAT2 to FLOAT3. */
8851 const struct vertex_ptc vertices7[] =
8853 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8854 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8855 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
8857 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8858 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
8859 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
8861 const UINT num_vertices7 = ARRAY_SIZE(vertices7);
8862 const UINT num_faces7 = ARRAY_SIZE(vertices7) / VERTS_PER_FACE;
8863 const UINT vertex_size7 = sizeof(*vertices7);
8864 const struct vertex_ptc_float3 exp_vertices7[] =
8866 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f, 0.0f}},
8867 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f, 0.0f}},
8868 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f, 0.0f}},
8870 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f, 0.0f}},
8871 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f, 0.0f}},
8872 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f, 0.0f}},
8874 const UINT exp_vertex_size7 = sizeof(*exp_vertices7);
8875 /* Test 8. Convert FLOAT2 to FLOAT4. */
8876 const struct vertex_ptc vertices8[] =
8878 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8879 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8880 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
8882 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8883 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
8884 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
8886 const UINT num_vertices8 = ARRAY_SIZE(vertices8);
8887 const UINT num_faces8 = ARRAY_SIZE(vertices8) / VERTS_PER_FACE;
8888 const UINT vertex_size8 = sizeof(*vertices8);
8889 const struct vertex_ptc_float4 exp_vertices8[] =
8891 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f, 0.0f, 1.0f}},
8892 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f, 0.0f, 1.0f}},
8893 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f, 0.0f, 1.0f}},
8895 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f, 0.0f, 1.0f}},
8896 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f, 0.0f, 1.0f}},
8897 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f, 0.0f, 1.0f}},
8899 const UINT exp_vertex_size8 = sizeof(*exp_vertices8);
8900 /* Test 9. Convert FLOAT2 to D3DCOLOR. */
8901 const struct vertex_ptc vertices9[] =
8903 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8904 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8905 {{ 0.0f, 0.0f, 0.f}, {-0.4f, -0.6f}},
8907 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8908 {{ 3.0f, 0.0f, 0.f}, { 2.0f, 256.0f}},
8909 {{ 1.0f, 0.0f, 0.f}, { 0.11f, 0.2f}},
8911 const UINT num_vertices9 = ARRAY_SIZE(vertices9);
8912 const UINT num_faces9 = ARRAY_SIZE(vertices9) / VERTS_PER_FACE;
8913 const UINT vertex_size9 = sizeof(*vertices9);
8914 const struct vertex_ptc_d3dcolor exp_vertices9[] =
8916 {{ 0.0f, 3.0f, 0.f}, {0, 255, 255, 255}},
8917 {{ 2.0f, 3.0f, 0.f}, {0, 179, 128, 255}},
8918 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 255}},
8920 {{ 3.0f, 3.0f, 0.f}, {0, 77, 51, 255}},
8921 {{ 3.0f, 0.0f, 0.f}, {0, 255, 255, 255}},
8922 {{ 1.0f, 0.0f, 0.f}, {0, 51, 28, 255}},
8924 const UINT exp_vertex_size9 = sizeof(*exp_vertices9);
8925 /* Test 10. Convert FLOAT2 to UBYTE4. */
8926 const struct vertex_ptc vertices10[] =
8928 {{ 0.0f, 3.0f, 0.f}, { 0.0f, 1.0f}},
8929 {{ 2.0f, 3.0f, 0.f}, { 2.0f, 3.0f}},
8930 {{ 0.0f, 0.0f, 0.f}, { 254.0f, 255.0f}},
8932 {{ 3.0f, 3.0f, 0.f}, { 256.0f, 257.0f}},
8933 {{ 3.0f, 0.0f, 0.f}, { 1.4f, 1.5f}},
8934 {{ 1.0f, 0.0f, 0.f}, {-4.0f, -5.0f}},
8936 const UINT num_vertices10 = ARRAY_SIZE(vertices10);
8937 const UINT num_faces10 = ARRAY_SIZE(vertices10) / VERTS_PER_FACE;
8938 const UINT vertex_size10 = sizeof(*vertices10);
8939 const struct vertex_ptc_ubyte4 exp_vertices10[] =
8941 {{ 0.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
8942 {{ 2.0f, 3.0f, 0.f}, {2, 3, 0, 1}},
8943 {{ 0.0f, 0.0f, 0.f}, {254, 255, 0, 1}},
8945 {{ 3.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
8946 {{ 3.0f, 0.0f, 0.f}, {1, 2, 0, 1}},
8947 {{ 1.0f, 0.0f, 0.f}, {0, 0, 0, 1}},
8949 const UINT exp_vertex_size10 = sizeof(*exp_vertices10);
8950 /* Test 11. Convert FLOAT2 to SHORT2. */
8951 const struct vertex_ptc vertices11[] =
8953 {{ 0.0f, 3.0f, 0.f}, { 1.0f, -1.0f}},
8954 {{ 2.0f, 3.0f, 0.f}, { 0.4f, 0.5f}},
8955 {{ 0.0f, 0.0f, 0.f}, {-0.5f, -5.0f}},
8957 {{ 3.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MIN}},
8958 {{ 3.0f, 0.0f, 0.f}, {SHRT_MAX + 1.0f, SHRT_MIN - 1.0f}},
8959 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX + 2.0f, SHRT_MIN - 2.0f}},
8961 {{ 4.0f, 3.0f, 0.f}, {2 * SHRT_MAX, 2 * SHRT_MIN}},
8962 {{ 6.0f, 0.0f, 0.f}, {3 * SHRT_MAX, 3 * SHRT_MIN}},
8963 {{ 4.0f, 0.0f, 0.f}, {4 * SHRT_MAX, 4 * SHRT_MIN}},
8965 const UINT num_vertices11 = ARRAY_SIZE(vertices11);
8966 const UINT num_faces11 = ARRAY_SIZE(vertices11) / VERTS_PER_FACE;
8967 const UINT vertex_size11 = sizeof(*vertices11);
8968 const struct vertex_ptc_short2 exp_vertices11[] =
8970 {{ 0.0f, 3.0f, 0.f}, {1, 0}},
8971 {{ 2.0f, 3.0f, 0.f}, {0, 1}},
8972 {{ 0.0f, 0.0f, 0.f}, {0, -4}},
8974 {{ 3.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MIN + 1}},
8975 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MIN}},
8976 {{ 1.0f, 0.0f, 0.f}, {SHRT_MIN + 1, SHRT_MAX}},
8978 {{ 4.0f, 3.0f, 0.f}, {-2, 1}},
8979 {{ 6.0f, 0.0f, 0.f}, {32765, -32767}},
8980 {{ 4.0f, 0.0f, 0.f}, {-4, 1}},
8982 const UINT exp_vertex_size11 = sizeof(*exp_vertices11);
8983 /* Test 12. Convert FLOAT2 to SHORT4. */
8984 const struct vertex_ptc vertices12[] =
8986 {{ 0.0f, 3.0f, 0.f}, { 1.0f, -1.0f}},
8987 {{ 2.0f, 3.0f, 0.f}, { 0.4f, 0.5f}},
8988 {{ 0.0f, 0.0f, 0.f}, {-0.5f, -5.0f}},
8990 {{ 3.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MIN}},
8991 {{ 3.0f, 0.0f, 0.f}, {SHRT_MAX + 1.0f, SHRT_MIN - 1.0f}},
8992 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX + 2.0f, SHRT_MIN - 2.0f}},
8994 {{ 4.0f, 3.0f, 0.f}, {2 * SHRT_MAX, 2 * SHRT_MIN}},
8995 {{ 6.0f, 0.0f, 0.f}, {3 * SHRT_MAX, 3 * SHRT_MIN}},
8996 {{ 4.0f, 0.0f, 0.f}, {4 * SHRT_MAX, 4 * SHRT_MIN}},
8998 const UINT num_vertices12 = ARRAY_SIZE(vertices12);
8999 const UINT num_faces12 = ARRAY_SIZE(vertices12) / VERTS_PER_FACE;
9000 const UINT vertex_size12 = sizeof(*vertices12);
9001 const struct vertex_ptc_short4 exp_vertices12[] =
9003 {{ 0.0f, 3.0f, 0.f}, {1, 0, 0, 1}},
9004 {{ 2.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
9005 {{ 0.0f, 0.0f, 0.f}, {0, -4, 0, 1}},
9007 {{ 3.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MIN + 1, 0, 1}},
9008 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MIN, 0, 1}},
9009 {{ 1.0f, 0.0f, 0.f}, {SHRT_MIN + 1, SHRT_MAX, 0, 1}},
9011 {{ 4.0f, 3.0f, 0.f}, {-2, 1, 0, 1}},
9012 {{ 6.0f, 0.0f, 0.f}, {32765, -32767, 0, 1}},
9013 {{ 4.0f, 0.0f, 0.f}, {-4, 1, 0, 1}},
9015 const UINT exp_vertex_size12 = sizeof(*exp_vertices12);
9016 /* Test 13. Convert FLOAT2 to UBYTE4N. */
9017 const struct vertex_ptc vertices13[] =
9019 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 2.0f}},
9020 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
9021 {{ 0.0f, 0.0f, 0.f}, {-0.4f, -0.5f}},
9023 {{ 3.0f, 3.0f, 0.f}, {-0.6f, -1.0f}},
9024 {{ 3.0f, 0.0f, 0.f}, {UCHAR_MAX, UCHAR_MAX + 1}},
9025 {{ 1.0f, 0.0f, 0.f}, {2 * UCHAR_MAX, -UCHAR_MAX}},
9027 const UINT num_vertices13 = ARRAY_SIZE(vertices13);
9028 const UINT num_faces13 = ARRAY_SIZE(vertices13) / VERTS_PER_FACE;
9029 const UINT vertex_size13 = sizeof(*vertices13);
9030 const struct vertex_ptc_ubyte4n exp_vertices13[] =
9032 {{ 0.0f, 3.0f, 0.f}, {255, 255, 0, 255}},
9033 {{ 2.0f, 3.0f, 0.f}, {128, 179, 0, 255}},
9034 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 255}},
9036 {{ 3.0f, 3.0f, 0.f}, {0, 0, 0, 255}},
9037 {{ 3.0f, 0.0f, 0.f}, {255, 255, 0, 255}},
9038 {{ 1.0f, 0.0f, 0.f}, {255, 0, 0, 255}},
9040 const UINT exp_vertex_size13 = sizeof(*exp_vertices13);
9041 /* Test 14. Convert FLOAT2 to SHORT2N. */
9042 const struct vertex_ptc vertices14[] =
9044 {{ 0.0f, 3.0f, 0.f}, {1.0f, 2.0f}},
9045 {{ 2.0f, 3.0f, 0.f}, {0.4f, 0.5f}},
9046 {{ 0.0f, 0.0f, 0.f}, {0.6f, -1.0f}},
9048 {{ 3.0f, 3.0f, 0.f}, {-0.4f, -0.5f}},
9049 {{ 3.0f, 0.0f, 0.f}, {-0.9f, -0.99997}},
9050 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX, SHRT_MIN}},
9052 const UINT num_vertices14 = ARRAY_SIZE(vertices14);
9053 const UINT num_faces14 = ARRAY_SIZE(vertices14) / VERTS_PER_FACE;
9054 const UINT vertex_size14 = sizeof(*vertices14);
9055 const struct vertex_ptc_short2 exp_vertices14[] =
9057 {{ 0.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MAX}},
9058 {{ 2.0f, 3.0f, 0.f}, {13107, 16384}},
9059 {{ 0.0f, 0.0f, 0.f}, {19660, SHRT_MIN + 2}},
9061 {{ 3.0f, 3.0f, 0.f}, {-13106, -16383}},
9062 {{ 3.0f, 0.0f, 0.f}, {-29489, SHRT_MIN + 3}},
9063 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX, SHRT_MIN + 2}},
9065 const UINT exp_vertex_size14 = sizeof(*exp_vertices14);
9066 /* Test 15. Convert FLOAT2 to SHORT4N. */
9067 const struct vertex_ptc vertices15[] =
9069 {{ 0.0f, 3.0f, 0.f}, {1.0f, 2.0f}},
9070 {{ 2.0f, 3.0f, 0.f}, {0.4f, 0.5f}},
9071 {{ 0.0f, 0.0f, 0.f}, {0.6f, -1.0f}},
9073 {{ 3.0f, 3.0f, 0.f}, {-0.4f, -0.5f}},
9074 {{ 3.0f, 0.0f, 0.f}, {-0.9f, -0.99997}},
9075 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX, SHRT_MIN}},
9077 const UINT num_vertices15 = ARRAY_SIZE(vertices15);
9078 const UINT num_faces15 = ARRAY_SIZE(vertices15) / VERTS_PER_FACE;
9079 const UINT vertex_size15 = sizeof(*vertices15);
9080 const struct vertex_ptc_short4 exp_vertices15[] =
9082 {{ 0.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MAX, 0, SHRT_MAX}},
9083 {{ 2.0f, 3.0f, 0.f}, {13107, 16384, 0, SHRT_MAX}},
9084 {{ 0.0f, 0.0f, 0.f}, {19660, SHRT_MIN + 2, 0, SHRT_MAX}},
9086 {{ 3.0f, 3.0f, 0.f}, {-13106, -16383, 0, SHRT_MAX}},
9087 {{ 3.0f, 0.0f, 0.f}, {-29489, SHRT_MIN + 3, 0, SHRT_MAX}},
9088 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX, SHRT_MIN + 2, 0, SHRT_MAX}},
9090 const UINT exp_vertex_size15 = sizeof(*exp_vertices15);
9091 /* Test 16. Convert FLOAT2 to USHORT2N. */
9092 const struct vertex_ptc vertices16[] =
9094 {{ 0.0f, 3.0f, 0.f}, {1.0f, 2.0f}},
9095 {{ 2.0f, 3.0f, 0.f}, {0.4f, 0.5f}},
9096 {{ 0.0f, 0.0f, 0.f}, {0.6f, -1.0f}},
9098 {{ 3.0f, 3.0f, 0.f}, {-0.4f, -0.5f}},
9099 {{ 3.0f, 0.0f, 0.f}, {-0.9f, 0.99998f}},
9100 {{ 1.0f, 0.0f, 0.f}, {USHRT_MAX, 0.0f}},
9102 const UINT num_vertices16 = ARRAY_SIZE(vertices16);
9103 const UINT num_faces16 = ARRAY_SIZE(vertices16) / VERTS_PER_FACE;
9104 const UINT vertex_size16 = sizeof(*vertices16);
9105 const struct vertex_ptc_ushort2n exp_vertices16[] =
9107 {{ 0.0f, 3.0f, 0.f}, {USHRT_MAX, USHRT_MAX}},
9108 {{ 2.0f, 3.0f, 0.f}, {26214, 32768}},
9109 {{ 0.0f, 0.0f, 0.f}, {39321, 0}},
9111 {{ 3.0f, 3.0f, 0.f}, {0, 0}},
9112 {{ 3.0f, 0.0f, 0.f}, {0, USHRT_MAX - 1}},
9113 {{ 1.0f, 0.0f, 0.f}, {USHRT_MAX, 0}},
9115 const UINT exp_vertex_size16 = sizeof(*exp_vertices16);
9116 /* Test 17. Convert FLOAT2 to USHORT4N. */
9117 const struct vertex_ptc vertices17[] =
9119 {{ 0.0f, 3.0f, 0.f}, {1.0f, 2.0f}},
9120 {{ 2.0f, 3.0f, 0.f}, {0.4f, 0.5f}},
9121 {{ 0.0f, 0.0f, 0.f}, {0.6f, -1.0f}},
9123 {{ 3.0f, 3.0f, 0.f}, {-0.4f, -0.5f}},
9124 {{ 3.0f, 0.0f, 0.f}, {-0.9f, 0.99998f}},
9125 {{ 1.0f, 0.0f, 0.f}, {USHRT_MAX, 0.0f}},
9127 const UINT num_vertices17 = ARRAY_SIZE(vertices17);
9128 const UINT num_faces17 = ARRAY_SIZE(vertices17) / VERTS_PER_FACE;
9129 const UINT vertex_size17 = sizeof(*vertices17);
9130 const struct vertex_ptc_ushort4n exp_vertices17[] =
9132 {{ 0.0f, 3.0f, 0.f}, {USHRT_MAX, USHRT_MAX, 0, USHRT_MAX}},
9133 {{ 2.0f, 3.0f, 0.f}, {26214, 32768, 0, USHRT_MAX}},
9134 {{ 0.0f, 0.0f, 0.f}, {39321, 0, 0, USHRT_MAX}},
9136 {{ 3.0f, 3.0f, 0.f}, {0, 0, 0, USHRT_MAX}},
9137 {{ 3.0f, 0.0f, 0.f}, {0, USHRT_MAX - 1, 0, USHRT_MAX}},
9138 {{ 1.0f, 0.0f, 0.f}, {USHRT_MAX, 0, 0, USHRT_MAX}},
9140 const UINT exp_vertex_size17 = sizeof(*exp_vertices17);
9141 /* Test 18. Test that the method field is compared by converting a FLOAT2 to
9142 * FLOAT16_2. where the method field has been change from
9143 * D3DDECLMETHOD_DEFAULT to D3DDECLMETHOD_PARTIALU. */
9144 const struct vertex_ptc vertices18[] =
9146 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
9147 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
9148 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
9150 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
9151 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
9152 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
9154 const UINT num_vertices18 = ARRAY_SIZE(vertices18);
9155 const UINT num_faces18 = ARRAY_SIZE(vertices18) / VERTS_PER_FACE;
9156 const UINT vertex_size18 = sizeof(*vertices18);
9157 const struct vertex_ptc_float16_2 exp_vertices18[] =
9159 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
9160 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */
9161 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */
9163 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd}}, /* {0.2f, 0.3f} */
9164 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
9165 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */
9167 const UINT exp_vertex_size18 = sizeof(*exp_vertices18);
9168 /* Test 19. Test that data is lost if usage index changes, e.g. TEXCOORD0
9169 * TEXCOORD1. */
9170 const struct vertex_pntc vertices19[] =
9172 {{ 0.0f, 3.0f, 0.f}, up, { 1.0f, 1.0f}},
9173 {{ 2.0f, 3.0f, 0.f}, up, { 0.5f, 0.7f}},
9174 {{ 0.0f, 0.0f, 0.f}, up, {-0.2f, -0.3f}},
9176 {{ 3.0f, 3.0f, 0.f}, up, { 0.2f, 0.3f}},
9177 {{ 3.0f, 0.0f, 0.f}, up, { 1.0f, 1.0f}},
9178 {{ 1.0f, 0.0f, 0.f}, up, { 0.1f, 0.2f}},
9180 const UINT num_vertices19 = ARRAY_SIZE(vertices19);
9181 const UINT num_faces19 = ARRAY_SIZE(vertices19) / VERTS_PER_FACE;
9182 const UINT vertex_size19 = sizeof(*vertices19);
9183 const struct vertex_pntc exp_vertices19[] =
9185 {{ 0.0f, 3.0f, 0.f}, up, zero_vec2},
9186 {{ 2.0f, 3.0f, 0.f}, up, zero_vec2},
9187 {{ 0.0f, 0.0f, 0.f}, up, zero_vec2},
9189 {{ 3.0f, 3.0f, 0.f}, up, zero_vec2},
9190 {{ 3.0f, 0.0f, 0.f}, up, zero_vec2},
9191 {{ 1.0f, 0.0f, 0.f}, up, zero_vec2},
9193 const UINT exp_vertex_size19 = sizeof(*exp_vertices19);
9194 /* Test 20. Another test that data is lost if usage index changes, e.g.
9195 * TEXCOORD1 to TEXCOORD0. */
9196 const struct vertex_pntc vertices20[] =
9198 {{ 0.0f, 3.0f, 0.f}, up, { 1.0f, 1.0f}},
9199 {{ 2.0f, 3.0f, 0.f}, up, { 0.5f, 0.7f}},
9200 {{ 0.0f, 0.0f, 0.f}, up, {-0.2f, -0.3f}},
9202 {{ 3.0f, 3.0f, 0.f}, up, { 0.2f, 0.3f}},
9203 {{ 3.0f, 0.0f, 0.f}, up, { 1.0f, 1.0f}},
9204 {{ 1.0f, 0.0f, 0.f}, up, { 0.1f, 0.2f}},
9206 const UINT num_vertices20 = ARRAY_SIZE(vertices20);
9207 const UINT num_faces20 = ARRAY_SIZE(vertices20) / VERTS_PER_FACE;
9208 const UINT vertex_size20 = sizeof(*vertices20);
9209 const struct vertex_pntc exp_vertices20[] =
9211 {{ 0.0f, 3.0f, 0.f}, up, zero_vec2},
9212 {{ 2.0f, 3.0f, 0.f}, up, zero_vec2},
9213 {{ 0.0f, 0.0f, 0.f}, up, zero_vec2},
9215 {{ 3.0f, 3.0f, 0.f}, up, zero_vec2},
9216 {{ 3.0f, 0.0f, 0.f}, up, zero_vec2},
9217 {{ 1.0f, 0.0f, 0.f}, up, zero_vec2},
9219 const UINT exp_vertex_size20 = sizeof(*exp_vertices20);
9220 /* Test 21. Convert FLOAT1 to FLOAT2. */
9221 const struct vertex_ptc_float1 vertices21[] =
9223 {{ 0.0f, 3.0f, 0.f}, 1.0f},
9224 {{ 2.0f, 3.0f, 0.f}, 0.5f},
9225 {{ 0.0f, 0.0f, 0.f}, -0.2f},
9227 {{ 3.0f, 3.0f, 0.f}, 0.2f},
9228 {{ 3.0f, 0.0f, 0.f}, 1.0f},
9229 {{ 1.0f, 0.0f, 0.f}, 0.1f},
9231 const UINT num_vertices21 = ARRAY_SIZE(vertices21);
9232 const UINT num_faces21 = ARRAY_SIZE(vertices21) / VERTS_PER_FACE;
9233 const UINT vertex_size21 = sizeof(*vertices21);
9234 const struct vertex_ptc exp_vertices21[] =
9236 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 0.0f}},
9237 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.0f}},
9238 {{ 0.0f, 0.0f, 0.f}, {-0.2f, 0.0f}},
9240 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.0f}},
9241 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 0.0f}},
9242 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.0f}},
9244 const UINT exp_vertex_size21 = sizeof(*exp_vertices21);
9245 /* Test 22. Convert FLOAT1 to FLOAT3. */
9246 const struct vertex_ptc_float1 vertices22[] =
9248 {{ 0.0f, 3.0f, 0.f}, 1.0f},
9249 {{ 2.0f, 3.0f, 0.f}, 0.5f},
9250 {{ 0.0f, 0.0f, 0.f}, -0.2f},
9252 {{ 3.0f, 3.0f, 0.f}, 0.2f},
9253 {{ 3.0f, 0.0f, 0.f}, 1.0f},
9254 {{ 1.0f, 0.0f, 0.f}, 0.1f},
9256 const UINT num_vertices22 = ARRAY_SIZE(vertices22);
9257 const UINT num_faces22 = ARRAY_SIZE(vertices22) / VERTS_PER_FACE;
9258 const UINT vertex_size22 = sizeof(*vertices22);
9259 const struct vertex_ptc_float3 exp_vertices22[] =
9261 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 0.0f, 0.0f}},
9262 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.0f, 0.0f}},
9263 {{ 0.0f, 0.0f, 0.f}, {-0.2f, 0.0f, 0.0f}},
9265 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.0f, 0.0f}},
9266 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 0.0f, 0.0f}},
9267 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.0f, 0.0f}},
9269 const UINT exp_vertex_size22 = sizeof(*exp_vertices22);
9270 /* Test 23. Convert FLOAT1 to FLOAT4. */
9271 const struct vertex_ptc_float1 vertices23[] =
9273 {{ 0.0f, 3.0f, 0.f}, 1.0f},
9274 {{ 2.0f, 3.0f, 0.f}, 0.5f},
9275 {{ 0.0f, 0.0f, 0.f}, -0.2f},
9277 {{ 3.0f, 3.0f, 0.f}, 0.2f},
9278 {{ 3.0f, 0.0f, 0.f}, 1.0f},
9279 {{ 1.0f, 0.0f, 0.f}, 0.1f},
9281 const UINT num_vertices23 = ARRAY_SIZE(vertices23);
9282 const UINT num_faces23 = ARRAY_SIZE(vertices23) / VERTS_PER_FACE;
9283 const UINT vertex_size23 = sizeof(*vertices23);
9284 const struct vertex_ptc_float4 exp_vertices23[] =
9286 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 0.0f, 0.0f, 1.0f}},
9287 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.0f, 0.0f, 1.0f}},
9288 {{ 0.0f, 0.0f, 0.f}, {-0.2f, 0.0f, 0.0f, 1.0f}},
9290 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.0f, 0.0f, 1.0f}},
9291 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 0.0f, 0.0f, 1.0f}},
9292 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.0f, 0.0f, 1.0f}},
9294 const UINT exp_vertex_size23 = sizeof(*exp_vertices23);
9295 /* Test 24. Convert FLOAT1 to D3DCOLOR. */
9296 const struct vertex_ptc_float1 vertices24[] =
9298 {{ 0.0f, 3.0f, 0.f}, 1.0f},
9299 {{ 2.0f, 3.0f, 0.f}, 0.5f},
9300 {{ 0.0f, 0.0f, 0.f}, -0.2f},
9302 {{ 3.0f, 3.0f, 0.f}, 0.2f},
9303 {{ 3.0f, 0.0f, 0.f}, 1.0f},
9304 {{ 1.0f, 0.0f, 0.f}, 0.11f},
9306 const UINT num_vertices24 = ARRAY_SIZE(vertices24);
9307 const UINT num_faces24 = ARRAY_SIZE(vertices24) / VERTS_PER_FACE;
9308 const UINT vertex_size24 = sizeof(*vertices24);
9309 const struct vertex_ptc_d3dcolor exp_vertices24[] =
9311 {{ 0.0f, 3.0f, 0.f}, {0, 0, 255, 255}},
9312 {{ 2.0f, 3.0f, 0.f}, {0, 0, 128, 255}},
9313 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 255}},
9315 {{ 3.0f, 3.0f, 0.f}, {0, 0, 51, 255}},
9316 {{ 3.0f, 0.0f, 0.f}, {0, 0, 255, 255}},
9317 {{ 1.0f, 0.0f, 0.f}, {0, 0, 28, 255}},
9319 const UINT exp_vertex_size24 = sizeof(*exp_vertices24);
9320 /* Test 25. Convert FLOAT1 to ubyte4. */
9321 const struct vertex_ptc_float1 vertices25[] =
9323 {{ 0.0f, 3.0f, 0.f}, 0.0f},
9324 {{ 2.0f, 3.0f, 0.f}, 1.4f},
9325 {{ 0.0f, 0.0f, 0.f}, 1.5f},
9327 {{ 3.0f, 3.0f, 0.f}, 255.0f},
9328 {{ 3.0f, 0.0f, 0.f}, 256.0f},
9329 {{ 1.0f, 0.0f, 0.f}, -1.0f},
9331 const UINT num_vertices25 = ARRAY_SIZE(vertices25);
9332 const UINT num_faces25 = ARRAY_SIZE(vertices25) / VERTS_PER_FACE;
9333 const UINT vertex_size25 = sizeof(*vertices25);
9334 const struct vertex_ptc_ubyte4 exp_vertices25[] =
9336 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 1}},
9337 {{ 2.0f, 3.0f, 0.f}, {1, 0, 0, 1}},
9338 {{ 0.0f, 0.0f, 0.f}, {2, 0, 0, 1}},
9340 {{ 3.0f, 3.0f, 0.f}, {255, 0, 0, 1}},
9341 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 1}},
9342 {{ 1.0f, 0.0f, 0.f}, {0, 0, 0, 1}},
9344 const UINT exp_vertex_size25 = sizeof(*exp_vertices25);
9345 /* Test 26. Convert FLOAT4 to D3DCOLOR. */
9346 const struct vertex_ptc_float4 vertices26[] =
9348 {{ 0.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.4f, 0.5f}},
9349 {{ 2.0f, 3.0f, 0.f}, {-0.4f, -0.5f, -1.0f, -2.0f}},
9350 {{ 0.0f, 0.0f, 0.f}, {254.0f, 255.0f, 256.0f, 257.0f}},
9352 {{ 3.0f, 3.0f, 0.f}, {0.1f, 0.2f, 0.3f, 0.4f}},
9353 {{ 3.0f, 0.0f, 0.f}, {0.5f, 0.6f, 0.7f, 0.8f}},
9354 {{ 1.0f, 0.0f, 0.f}, {0.9f, 0.99f, 0.995f, 0.999f}},
9356 const UINT num_vertices26 = ARRAY_SIZE(vertices26);
9357 const UINT num_faces26 = ARRAY_SIZE(vertices26) / VERTS_PER_FACE;
9358 const UINT vertex_size26 = sizeof(*vertices26);
9359 const struct vertex_ptc_d3dcolor exp_vertices26[] =
9361 {{ 0.0f, 3.0f, 0.f}, {102, 255, 0, 128}},
9362 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9363 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
9365 {{ 3.0f, 3.0f, 0.f}, {77, 51, 26, 102}},
9366 {{ 3.0f, 0.0f, 0.f}, {179, 153, 128, 204}},
9367 {{ 1.0f, 0.0f, 0.f}, {254, 252, 230, 255}},
9369 const UINT exp_vertex_size26 = sizeof(*exp_vertices26);
9370 /* Test 27. Convert D3DCOLOR to FLOAT4. */
9371 const struct vertex_ptc_d3dcolor vertices27[] =
9373 {{ 0.0f, 3.0f, 0.f}, {102, 255, 0, 128}},
9374 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9375 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
9377 {{ 3.0f, 3.0f, 0.f}, {77, 51, 26, 102}},
9378 {{ 3.0f, 0.0f, 0.f}, {179, 153, 128, 204}},
9379 {{ 1.0f, 0.0f, 0.f}, {254, 252, 230, 255}},
9381 const UINT num_vertices27 = ARRAY_SIZE(vertices27);
9382 const UINT num_faces27 = ARRAY_SIZE(vertices27) / VERTS_PER_FACE;
9383 const UINT vertex_size27 = sizeof(*vertices27);
9384 const struct vertex_ptc_float4 exp_vertices27[] =
9386 {{ 0.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.4f, 0.501961f}},
9387 {{ 2.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9388 {{ 0.0f, 0.0f, 0.f}, {1.0f, 1.0f, 1.0f, 1.0f}},
9390 {{ 3.0f, 3.0f, 0.f}, {0.101961f, 0.2f, 0.301961f, 0.4f}},
9391 {{ 3.0f, 0.0f, 0.f}, {0.501961f, 0.6f, 0.701961f, 0.8f}},
9392 {{ 1.0f, 0.0f, 0.f}, {0.901961f, 0.988235f, 0.996078f, 1.0f}},
9394 const UINT exp_vertex_size27 = sizeof(*exp_vertices27);
9395 /* Test 28. Convert UBYTE4 to FLOAT4. */
9396 const struct vertex_ptc_ubyte4 vertices28[] =
9398 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9399 {{ 2.0f, 3.0f, 0.f}, {1, 1, 1, 1}},
9400 {{ 0.0f, 0.0f, 0.f}, {1, 0, 1, 0}},
9402 {{ 3.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
9403 {{ 3.0f, 0.0f, 0.f}, {10, 20, 30, 40}},
9404 {{ 1.0f, 0.0f, 0.f}, {50, 60, 127, 255}},
9406 const UINT num_vertices28 = ARRAY_SIZE(vertices28);
9407 const UINT num_faces28 = ARRAY_SIZE(vertices28) / VERTS_PER_FACE;
9408 const UINT vertex_size28 = sizeof(*vertices28);
9409 const struct vertex_ptc_float4 exp_vertices28[] =
9411 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9412 {{ 2.0f, 3.0f, 0.f}, {1.0f, 1.0f, 1.0f, 1.0f}},
9413 {{ 0.0f, 0.0f, 0.f}, {1.0f, 0.0f, 1.0f, 0.0f}},
9415 {{ 3.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.0f, 1.0f}},
9416 {{ 3.0f, 0.0f, 0.f}, {10.0f, 20.0f, 30.0f, 40.0f}},
9417 {{ 1.0f, 0.0f, 0.f}, {50.0f, 60.0f, 127.0f, 255.0f}},
9419 const UINT exp_vertex_size28 = sizeof(*exp_vertices28);
9420 /* Test 29. Convert SHORT2 to FLOAT4. */
9421 const struct vertex_ptc_short2 vertices29[] =
9423 {{ 0.0f, 3.0f, 0.f}, {0, 0}},
9424 {{ 2.0f, 3.0f, 0.f}, {0, 1}},
9425 {{ 0.0f, 0.0f, 0.f}, {1, 0}},
9427 {{ 3.0f, 3.0f, 0.f}, {1, 1}},
9428 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MAX}},
9429 {{ 1.0f, 0.0f, 0.f}, {-42, 42}},
9431 const UINT num_vertices29 = ARRAY_SIZE(vertices29);
9432 const UINT num_faces29 = ARRAY_SIZE(vertices29) / VERTS_PER_FACE;
9433 const UINT vertex_size29 = sizeof(*vertices29);
9434 const struct vertex_ptc_float4 exp_vertices29[] =
9436 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 1.0f}},
9437 {{ 2.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.0f, 1.0f }},
9438 {{ 0.0f, 0.0f, 0.f}, {1.0f, 0.0f, 0.0f, 1.0f}},
9440 {{ 3.0f, 3.0f, 0.f}, {1.0f, 1.0f, 0.0f, 1.0f}},
9441 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MAX, 0.0f, 1.0f}},
9442 {{ 1.0f, 0.0f, 0.f}, {-42.0f, 42.0f, 0.0f, 1.0f}},
9444 const UINT exp_vertex_size29 = sizeof(*exp_vertices29);
9445 /* Test 29. Convert SHORT4 to FLOAT4. */
9446 const struct vertex_ptc_short4 vertices30[] =
9448 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9449 {{ 2.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
9450 {{ 0.0f, 0.0f, 0.f}, {1, 0, 1, 0}},
9452 {{ 3.0f, 3.0f, 0.f}, {1, 1, 1, 1}},
9453 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MAX, 1, 0}},
9454 {{ 1.0f, 0.0f, 0.f}, {-42, 42, SHRT_MAX, SHRT_MIN}},
9456 const UINT num_vertices30 = ARRAY_SIZE(vertices30);
9457 const UINT num_faces30 = ARRAY_SIZE(vertices30) / VERTS_PER_FACE;
9458 const UINT vertex_size30 = sizeof(*vertices30);
9459 const struct vertex_ptc_float4 exp_vertices30[] =
9461 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9462 {{ 2.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.0f, 1.0f }},
9463 {{ 0.0f, 0.0f, 0.f}, {1.0f, 0.0f, 1.0f, 0.0f}},
9465 {{ 3.0f, 3.0f, 0.f}, {1.0f, 1.0f, 1.0f, 1.0f}},
9466 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MAX, 1.0f, 0.0f}},
9467 {{ 1.0f, 0.0f, 0.f}, {-42.0f, 42.0f, SHRT_MAX, SHRT_MIN}},
9469 const UINT exp_vertex_size30 = sizeof(*exp_vertices30);
9470 /* Test 31. Convert UBYTE4N to FLOAT4. */
9471 const struct vertex_ptc_ubyte4n vertices31[] =
9473 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9474 {{ 2.0f, 3.0f, 0.f}, {1, 1, 1, 1}},
9475 {{ 0.0f, 0.0f, 0.f}, {1, 0, 1, 0}},
9477 {{ 3.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
9478 {{ 3.0f, 0.0f, 0.f}, {10, 20, 30, 40}},
9479 {{ 1.0f, 0.0f, 0.f}, {50, 60, 70, UCHAR_MAX}},
9481 const UINT num_vertices31 = ARRAY_SIZE(vertices31);
9482 const UINT num_faces31 = ARRAY_SIZE(vertices31) / VERTS_PER_FACE;
9483 const UINT vertex_size31 = sizeof(*vertices31);
9484 const struct vertex_ptc_float4 exp_vertices31[] =
9486 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9487 {{ 2.0f, 3.0f, 0.f}, {(FLOAT)1/UCHAR_MAX, (FLOAT)1/UCHAR_MAX, (FLOAT)1/UCHAR_MAX, (FLOAT)1/UCHAR_MAX}},
9488 {{ 0.0f, 0.0f, 0.f}, {(FLOAT)1/UCHAR_MAX, 0.0f, (FLOAT)1/UCHAR_MAX, 0.0f}},
9490 {{ 3.0f, 3.0f, 0.f}, {0.0f, (FLOAT)1/UCHAR_MAX, 0.0f, (FLOAT)1/UCHAR_MAX}},
9491 {{ 3.0f, 0.0f, 0.f}, {(FLOAT)10/UCHAR_MAX, (FLOAT)20/UCHAR_MAX, (FLOAT)30/UCHAR_MAX, (FLOAT)40/UCHAR_MAX}},
9492 {{ 1.0f, 0.0f, 0.f}, {(FLOAT)50/UCHAR_MAX, (FLOAT)60/UCHAR_MAX, (FLOAT)70/UCHAR_MAX, 1.0f}},
9494 const UINT exp_vertex_size31 = sizeof(*exp_vertices31);
9495 /* Test 32. Convert SHORT2N to FLOAT4. */
9496 const struct vertex_ptc_short2 vertices32[] =
9498 {{ 0.0f, 3.0f, 0.f}, {0, 0}},
9499 {{ 2.0f, 3.0f, 0.f}, {0, 1}},
9500 {{ 0.0f, 0.0f, 0.f}, {1, 0}},
9502 {{ 3.0f, 3.0f, 0.f}, {1, 1}},
9503 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN + 1, SHRT_MAX}},
9504 {{ 1.0f, 0.0f, 0.f}, {-42, 42}},
9506 const UINT num_vertices32 = ARRAY_SIZE(vertices32);
9507 const UINT num_faces32 = ARRAY_SIZE(vertices32) / VERTS_PER_FACE;
9508 const UINT vertex_size32 = sizeof(*vertices32);
9509 const struct vertex_ptc_float4 exp_vertices32[] =
9511 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 1.0f}},
9512 {{ 2.0f, 3.0f, 0.f}, {0.0f, 1.0f/SHRT_MAX, 0.0f, 1.0f}},
9513 {{ 0.0f, 0.0f, 0.f}, {1.0f/SHRT_MAX, 0.0f, 0.0f, 1.0f}},
9515 {{ 3.0f, 3.0f, 0.f}, {1.0f/SHRT_MAX, 1.0f/SHRT_MAX, 0.0f, 1.0f}},
9516 {{ 3.0f, 0.0f, 0.f}, {-1.0f, 1.0f, 0.0f, 1.0f}},
9517 {{ 1.0f, 0.0f, 0.f}, {-42.0f/SHRT_MAX, 42.0f/SHRT_MAX, 0.0f, 1.0f}},
9519 const UINT exp_vertex_size32 = sizeof(*exp_vertices32);
9520 /* Test 33. Convert SHORT4N to FLOAT4. */
9521 const struct vertex_ptc_short4 vertices33[] =
9523 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9524 {{ 2.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
9525 {{ 0.0f, 0.0f, 0.f}, {1, 0, 1, 0}},
9527 {{ 3.0f, 3.0f, 0.f}, {1, 1, 1, 1}},
9528 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN + 1, SHRT_MAX, SHRT_MIN + 1, SHRT_MAX}},
9529 {{ 1.0f, 0.0f, 0.f}, {-42, 42, 1, 1}},
9531 const UINT num_vertices33 = ARRAY_SIZE(vertices33);
9532 const UINT num_faces33 = ARRAY_SIZE(vertices33) / VERTS_PER_FACE;
9533 const UINT vertex_size33 = sizeof(*vertices33);
9534 const struct vertex_ptc_float4 exp_vertices33[] =
9536 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9537 {{ 2.0f, 3.0f, 0.f}, {0.0f, 1.0f/SHRT_MAX, 0.0f, 1.0f/SHRT_MAX}},
9538 {{ 0.0f, 0.0f, 0.f}, {1.0f/SHRT_MAX, 0.0f, 1.0f/SHRT_MAX, 0.0f}},
9540 {{ 3.0f, 3.0f, 0.f}, {1.0f/SHRT_MAX, 1.0f/SHRT_MAX, 1.0f/SHRT_MAX, 1.0f/SHRT_MAX}},
9541 {{ 3.0f, 0.0f, 0.f}, {-1.0f, 1.0f, -1.0f, 1.0f}},
9542 {{ 1.0f, 0.0f, 0.f}, {-42.0f/SHRT_MAX, 42.0f/SHRT_MAX, 1.0f/SHRT_MAX, 1.0f/SHRT_MAX}},
9544 const UINT exp_vertex_size33 = sizeof(*exp_vertices33);
9545 /* Test 34. Convert FLOAT16_2 to FLOAT4. */
9546 const struct vertex_ptc_float16_2 vertices34[] =
9548 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
9549 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */
9550 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */
9552 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd}}, /* {0.2f, 0.3f} */
9553 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
9554 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */
9556 const UINT num_vertices34 = ARRAY_SIZE(vertices34);
9557 const UINT num_faces34 = ARRAY_SIZE(vertices34) / VERTS_PER_FACE;
9558 const UINT vertex_size34 = sizeof(*vertices34);
9559 const struct vertex_ptc_float4 exp_vertices34[] =
9561 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f, 0.0f, 1.0f}},
9562 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.700195f, 0.0f, 1.0f}},
9563 {{ 0.0f, 0.0f, 0.f}, {-0.199951f, -0.300049f, 0.0f, 1.0f}},
9565 {{ 3.0f, 3.0f, 0.f}, {0.199951f, 0.300049f, 0.0f, 1.0f}},
9566 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f, 0.0f, 1.0f}},
9567 {{ 1.0f, 0.0f, 0.f}, {0.099976f, 0.199951f, 0.0f, 1.0f}},
9569 const UINT exp_vertex_size34 = sizeof(*exp_vertices34);
9570 /* Test 35. Convert FLOAT16_4 to FLOAT4. */
9571 const struct vertex_ptc_float16_4 vertices35[] =
9573 {{ 0.0f, 3.0f, 0.f}, {0x0000, 0x0000, 0x0000, 0x0000}},
9574 {{ 2.0f, 3.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}},
9575 {{ 0.0f, 0.0f, 0.f}, {0x3c00, 0x0000, 0x3c00, 0x0000}},
9577 {{ 3.0f, 3.0f, 0.f}, {0x0000, 0x3c00, 0x0000, 0x3c00}},
9578 {{ 3.0f, 0.0f, 0.f}, {0x3800, 0x399a, 0xb266, 0xb4cd}},
9579 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266, 0x2e66, 0x3266}},
9581 const UINT num_vertices35 = ARRAY_SIZE(vertices35);
9582 const UINT num_faces35 = ARRAY_SIZE(vertices35) / VERTS_PER_FACE;
9583 const UINT vertex_size35 = sizeof(*vertices35);
9584 const struct vertex_ptc_float4 exp_vertices35[] =
9586 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9587 {{ 2.0f, 3.0f, 0.f}, {1.0f, 1.0f, 1.0f, 1.0f}},
9588 {{ 0.0f, 0.0f, 0.f}, {1.0f, 0.0f, 1.0f, 0.0f}},
9590 {{ 3.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.0f, 1.0f}},
9591 {{ 3.0f, 0.0f, 0.f}, {0.5f, 0.700195f, -0.199951f, -0.300049f}},
9592 {{ 1.0f, 0.0f, 0.f}, {0.099976f, 0.199951f, 0.099976f, 0.199951f}},
9594 const UINT exp_vertex_size35 = sizeof(*exp_vertices35);
9595 /* Test 36. Check that vertex buffer sharing is ok. */
9596 const struct vertex_pn vertices36[] =
9598 {{ 0.0f, 3.0f, 0.f}, up},
9599 {{ 2.0f, 3.0f, 0.f}, up},
9600 {{ 0.0f, 0.0f, 0.f}, up},
9602 const UINT num_vertices36 = ARRAY_SIZE(vertices36);
9603 const UINT num_faces36 = ARRAY_SIZE(vertices36) / VERTS_PER_FACE;
9604 const UINT vertex_size36 = sizeof(*vertices36);
9605 const DWORD clone_options36 = options | D3DXMESH_VB_SHARE;
9606 /* Common mesh data */
9607 ID3DXMesh *mesh = NULL;
9608 ID3DXMesh *mesh_clone = NULL;
9609 struct
9611 const BYTE *vertices;
9612 const DWORD *indices;
9613 const DWORD *attributes;
9614 const UINT num_vertices;
9615 const UINT num_faces;
9616 const UINT vertex_size;
9617 const DWORD create_options;
9618 const DWORD clone_options;
9619 D3DVERTEXELEMENT9 *declaration;
9620 D3DVERTEXELEMENT9 *new_declaration;
9621 const BYTE *exp_vertices;
9622 const UINT exp_vertex_size;
9624 tc[] =
9627 (BYTE*)vertices0,
9628 NULL,
9629 NULL,
9630 num_vertices0,
9631 num_faces0,
9632 vertex_size0,
9633 options,
9634 options,
9635 declaration_pn,
9636 declaration_pn,
9637 (BYTE*)vertices0,
9638 vertex_size0
9641 (BYTE*)vertices0,
9642 NULL,
9643 NULL,
9644 num_vertices0,
9645 num_faces0,
9646 vertex_size0,
9647 options_16bit,
9648 options_16bit,
9649 declaration_pn,
9650 declaration_pn,
9651 (BYTE*)vertices0,
9652 vertex_size0
9655 (BYTE*)vertices0,
9656 NULL,
9657 NULL,
9658 num_vertices0,
9659 num_faces0,
9660 vertex_size0,
9661 options,
9662 options,
9663 declaration_pn,
9664 declaration_pntc,
9665 (BYTE*)exp_vertices2,
9666 exp_vertex_size2
9669 (BYTE*)vertices0,
9670 NULL,
9671 NULL,
9672 num_vertices0,
9673 num_faces0,
9674 vertex_size0,
9675 options,
9676 options,
9677 declaration_pn,
9678 declaration_ptcn,
9679 (BYTE*)exp_vertices3,
9680 exp_vertex_size3
9683 (BYTE*)vertices4,
9684 NULL,
9685 NULL,
9686 num_vertices4,
9687 num_faces4,
9688 vertex_size4,
9689 options,
9690 options,
9691 declaration_ptc,
9692 declaration_ptc_float16_2,
9693 (BYTE*)exp_vertices4,
9694 exp_vertex_size4
9697 (BYTE*)vertices5,
9698 NULL,
9699 NULL,
9700 num_vertices5,
9701 num_faces5,
9702 vertex_size5,
9703 options,
9704 options,
9705 declaration_ptc,
9706 declaration_ptc_float16_4,
9707 (BYTE*)exp_vertices5,
9708 exp_vertex_size5
9711 (BYTE*)vertices6,
9712 NULL,
9713 NULL,
9714 num_vertices6,
9715 num_faces6,
9716 vertex_size6,
9717 options,
9718 options,
9719 declaration_ptc,
9720 declaration_ptc_float1,
9721 (BYTE*)exp_vertices6,
9722 exp_vertex_size6
9725 (BYTE*)vertices7,
9726 NULL,
9727 NULL,
9728 num_vertices7,
9729 num_faces7,
9730 vertex_size7,
9731 options,
9732 options,
9733 declaration_ptc,
9734 declaration_ptc_float3,
9735 (BYTE*)exp_vertices7,
9736 exp_vertex_size7
9739 (BYTE*)vertices8,
9740 NULL,
9741 NULL,
9742 num_vertices8,
9743 num_faces8,
9744 vertex_size8,
9745 options,
9746 options,
9747 declaration_ptc,
9748 declaration_ptc_float4,
9749 (BYTE*)exp_vertices8,
9750 exp_vertex_size8
9753 (BYTE*)vertices9,
9754 NULL,
9755 NULL,
9756 num_vertices9,
9757 num_faces9,
9758 vertex_size9,
9759 options,
9760 options,
9761 declaration_ptc,
9762 declaration_ptc_d3dcolor,
9763 (BYTE*)exp_vertices9,
9764 exp_vertex_size9
9767 (BYTE*)vertices10,
9768 NULL,
9769 NULL,
9770 num_vertices10,
9771 num_faces10,
9772 vertex_size10,
9773 options,
9774 options,
9775 declaration_ptc,
9776 declaration_ptc_ubyte4,
9777 (BYTE*)exp_vertices10,
9778 exp_vertex_size10
9781 (BYTE*)vertices11,
9782 NULL,
9783 NULL,
9784 num_vertices11,
9785 num_faces11,
9786 vertex_size11,
9787 options,
9788 options,
9789 declaration_ptc,
9790 declaration_ptc_short2,
9791 (BYTE*)exp_vertices11,
9792 exp_vertex_size11
9795 (BYTE*)vertices12,
9796 NULL,
9797 NULL,
9798 num_vertices12,
9799 num_faces12,
9800 vertex_size12,
9801 options,
9802 options,
9803 declaration_ptc,
9804 declaration_ptc_short4,
9805 (BYTE*)exp_vertices12,
9806 exp_vertex_size12
9809 (BYTE*)vertices13,
9810 NULL,
9811 NULL,
9812 num_vertices13,
9813 num_faces13,
9814 vertex_size13,
9815 options,
9816 options,
9817 declaration_ptc,
9818 declaration_ptc_ubyte4n,
9819 (BYTE*)exp_vertices13,
9820 exp_vertex_size13
9823 (BYTE*)vertices14,
9824 NULL,
9825 NULL,
9826 num_vertices14,
9827 num_faces14,
9828 vertex_size14,
9829 options,
9830 options,
9831 declaration_ptc,
9832 declaration_ptc_short2n,
9833 (BYTE*)exp_vertices14,
9834 exp_vertex_size14
9837 (BYTE*)vertices15,
9838 NULL,
9839 NULL,
9840 num_vertices15,
9841 num_faces15,
9842 vertex_size15,
9843 options,
9844 options,
9845 declaration_ptc,
9846 declaration_ptc_short4n,
9847 (BYTE*)exp_vertices15,
9848 exp_vertex_size15
9851 (BYTE*)vertices16,
9852 NULL,
9853 NULL,
9854 num_vertices16,
9855 num_faces16,
9856 vertex_size16,
9857 options,
9858 options,
9859 declaration_ptc,
9860 declaration_ptc_ushort2n,
9861 (BYTE*)exp_vertices16,
9862 exp_vertex_size16
9865 (BYTE*)vertices17,
9866 NULL,
9867 NULL,
9868 num_vertices17,
9869 num_faces17,
9870 vertex_size17,
9871 options,
9872 options,
9873 declaration_ptc,
9874 declaration_ptc_ushort4n,
9875 (BYTE*)exp_vertices17,
9876 exp_vertex_size17
9879 (BYTE*)vertices18,
9880 NULL,
9881 NULL,
9882 num_vertices18,
9883 num_faces18,
9884 vertex_size18,
9885 options,
9886 options,
9887 declaration_ptc,
9888 declaration_ptc_float16_2_partialu,
9889 (BYTE*)exp_vertices18,
9890 exp_vertex_size18
9893 (BYTE*)vertices19,
9894 NULL,
9895 NULL,
9896 num_vertices19,
9897 num_faces19,
9898 vertex_size19,
9899 options,
9900 options,
9901 declaration_pntc,
9902 declaration_pntc1,
9903 (BYTE*)exp_vertices19,
9904 exp_vertex_size19
9907 (BYTE*)vertices20,
9908 NULL,
9909 NULL,
9910 num_vertices20,
9911 num_faces20,
9912 vertex_size20,
9913 options,
9914 options,
9915 declaration_pntc1,
9916 declaration_pntc,
9917 (BYTE*)exp_vertices20,
9918 exp_vertex_size20
9921 (BYTE*)vertices21,
9922 NULL,
9923 NULL,
9924 num_vertices21,
9925 num_faces21,
9926 vertex_size21,
9927 options,
9928 options,
9929 declaration_ptc_float1,
9930 declaration_ptc,
9931 (BYTE*)exp_vertices21,
9932 exp_vertex_size21
9935 (BYTE*)vertices22,
9936 NULL,
9937 NULL,
9938 num_vertices22,
9939 num_faces22,
9940 vertex_size22,
9941 options,
9942 options,
9943 declaration_ptc_float1,
9944 declaration_ptc_float3,
9945 (BYTE*)exp_vertices22,
9946 exp_vertex_size22
9949 (BYTE*)vertices23,
9950 NULL,
9951 NULL,
9952 num_vertices23,
9953 num_faces23,
9954 vertex_size23,
9955 options,
9956 options,
9957 declaration_ptc_float1,
9958 declaration_ptc_float4,
9959 (BYTE*)exp_vertices23,
9960 exp_vertex_size23
9963 (BYTE*)vertices24,
9964 NULL,
9965 NULL,
9966 num_vertices24,
9967 num_faces24,
9968 vertex_size24,
9969 options,
9970 options,
9971 declaration_ptc_float1,
9972 declaration_ptc_d3dcolor,
9973 (BYTE*)exp_vertices24,
9974 exp_vertex_size24
9977 (BYTE*)vertices25,
9978 NULL,
9979 NULL,
9980 num_vertices25,
9981 num_faces25,
9982 vertex_size25,
9983 options,
9984 options,
9985 declaration_ptc_float1,
9986 declaration_ptc_ubyte4,
9987 (BYTE*)exp_vertices25,
9988 exp_vertex_size25
9991 (BYTE*)vertices26,
9992 NULL,
9993 NULL,
9994 num_vertices26,
9995 num_faces26,
9996 vertex_size26,
9997 options,
9998 options,
9999 declaration_ptc_float4,
10000 declaration_ptc_d3dcolor,
10001 (BYTE*)exp_vertices26,
10002 exp_vertex_size26
10005 (BYTE*)vertices27,
10006 NULL,
10007 NULL,
10008 num_vertices27,
10009 num_faces27,
10010 vertex_size27,
10011 options,
10012 options,
10013 declaration_ptc_d3dcolor,
10014 declaration_ptc_float4,
10015 (BYTE*)exp_vertices27,
10016 exp_vertex_size27
10019 (BYTE*)vertices28,
10020 NULL,
10021 NULL,
10022 num_vertices28,
10023 num_faces28,
10024 vertex_size28,
10025 options,
10026 options,
10027 declaration_ptc_ubyte4,
10028 declaration_ptc_float4,
10029 (BYTE*)exp_vertices28,
10030 exp_vertex_size28
10033 (BYTE*)vertices29,
10034 NULL,
10035 NULL,
10036 num_vertices29,
10037 num_faces29,
10038 vertex_size29,
10039 options,
10040 options,
10041 declaration_ptc_short2,
10042 declaration_ptc_float4,
10043 (BYTE*)exp_vertices29,
10044 exp_vertex_size29
10047 (BYTE*)vertices30,
10048 NULL,
10049 NULL,
10050 num_vertices30,
10051 num_faces30,
10052 vertex_size30,
10053 options,
10054 options,
10055 declaration_ptc_short4,
10056 declaration_ptc_float4,
10057 (BYTE*)exp_vertices30,
10058 exp_vertex_size30
10061 (BYTE*)vertices31,
10062 NULL,
10063 NULL,
10064 num_vertices31,
10065 num_faces31,
10066 vertex_size31,
10067 options,
10068 options,
10069 declaration_ptc_ubyte4n,
10070 declaration_ptc_float4,
10071 (BYTE*)exp_vertices31,
10072 exp_vertex_size31
10075 (BYTE*)vertices32,
10076 NULL,
10077 NULL,
10078 num_vertices32,
10079 num_faces32,
10080 vertex_size32,
10081 options,
10082 options,
10083 declaration_ptc_short2n,
10084 declaration_ptc_float4,
10085 (BYTE*)exp_vertices32,
10086 exp_vertex_size32
10089 (BYTE*)vertices33,
10090 NULL,
10091 NULL,
10092 num_vertices33,
10093 num_faces33,
10094 vertex_size33,
10095 options,
10096 options,
10097 declaration_ptc_short4n,
10098 declaration_ptc_float4,
10099 (BYTE*)exp_vertices33,
10100 exp_vertex_size33
10103 (BYTE*)vertices34,
10104 NULL,
10105 NULL,
10106 num_vertices34,
10107 num_faces34,
10108 vertex_size34,
10109 options,
10110 options,
10111 declaration_ptc_float16_2,
10112 declaration_ptc_float4,
10113 (BYTE*)exp_vertices34,
10114 exp_vertex_size34
10117 (BYTE*)vertices35,
10118 NULL,
10119 NULL,
10120 num_vertices35,
10121 num_faces35,
10122 vertex_size35,
10123 options,
10124 options,
10125 declaration_ptc_float16_4,
10126 declaration_ptc_float4,
10127 (BYTE*)exp_vertices35,
10128 exp_vertex_size35
10131 (BYTE*)vertices36,
10132 NULL,
10133 NULL,
10134 num_vertices36,
10135 num_faces36,
10136 vertex_size36,
10137 options,
10138 clone_options36,
10139 declaration_pn,
10140 declaration_pn,
10141 (BYTE*)vertices36,
10142 vertex_size36
10146 test_context = new_test_context();
10147 if (!test_context)
10149 skip("Couldn't create test context\n");
10150 goto cleanup;
10153 for (i = 0; i < ARRAY_SIZE(tc); i++)
10155 UINT j;
10156 D3DVERTEXELEMENT9 new_declaration[MAX_FVF_DECL_SIZE];
10157 UINT exp_new_decl_length, new_decl_length;
10158 UINT exp_new_decl_size, new_decl_size;
10160 hr = init_test_mesh(tc[i].num_faces, tc[i].num_vertices,
10161 tc[i].create_options,
10162 tc[i].declaration,
10163 test_context->device, &mesh,
10164 tc[i].vertices, tc[i].vertex_size,
10165 tc[i].indices, tc[i].attributes);
10166 if (FAILED(hr))
10168 skip("Couldn't initialize test mesh %d. Got %x expected D3D_OK\n", i, hr);
10169 goto cleanup;
10172 hr = mesh->lpVtbl->CloneMesh(mesh, tc[i].clone_options, tc[i].new_declaration,
10173 test_context->device, &mesh_clone);
10174 ok(hr == D3D_OK, "CloneMesh test case %d failed. Got %x\n, expected D3D_OK\n", i, hr);
10176 hr = mesh_clone->lpVtbl->GetDeclaration(mesh_clone, new_declaration);
10177 ok(hr == D3D_OK, "GetDeclaration test case %d failed. Got %x\n, expected D3D_OK\n", i, hr);
10178 /* Check declaration elements */
10179 for (j = 0; tc[i].new_declaration[j].Stream != 0xFF; j++)
10181 ok(memcmp(&tc[i].new_declaration[j], &new_declaration[j], sizeof(*new_declaration)) == 0,
10182 "Test case %d failed. Declaration element %d did not match.\n", i, j);
10185 /* Check declaration length */
10186 exp_new_decl_length = D3DXGetDeclLength(tc[i].new_declaration);
10187 new_decl_length = D3DXGetDeclLength(new_declaration);
10188 ok(new_decl_length == exp_new_decl_length,
10189 "Test case %d failed. Got new declaration length %d, expected %d\n",
10190 i, new_decl_length, exp_new_decl_length);
10192 /* Check declaration size */
10193 exp_new_decl_size = D3DXGetDeclVertexSize(tc[i].new_declaration, 0);
10194 new_decl_size = D3DXGetDeclVertexSize(new_declaration, 0);
10195 ok(new_decl_size == exp_new_decl_size,
10196 "Test case %d failed. Got new declaration size %d, expected %d\n",
10197 i, new_decl_size, exp_new_decl_size);
10199 /* Check vertex data in cloned mesh */
10200 hr = mesh_clone->lpVtbl->LockVertexBuffer(mesh_clone, 0, (void**)&vertices);
10201 if (FAILED(hr))
10203 skip("Couldn't lock cloned vertex buffer.\n");
10204 goto cleanup;
10206 for (j = 0; j < tc[i].num_vertices; j++)
10208 UINT index = tc[i].exp_vertex_size * j;
10209 check_vertex_components(__LINE__, i, j, &vertices[index], &tc[i].exp_vertices[index], tc[i].new_declaration);
10211 hr = mesh_clone->lpVtbl->UnlockVertexBuffer(mesh_clone);
10212 if (FAILED(hr))
10214 skip("Couldn't unlock vertex buffer.\n");
10215 goto cleanup;
10217 vertices = NULL;
10218 mesh->lpVtbl->Release(mesh);
10219 mesh = NULL;
10220 mesh_clone->lpVtbl->Release(mesh_clone);
10221 mesh_clone = NULL;
10224 /* The following test shows that it is not possible to share a vertex buffer
10225 * with D3DXMESH_VB_SHARE and change the vertex declaration at the same
10226 * time. It reuses the test data from test 2.
10228 hr = init_test_mesh(tc[2].num_faces, tc[2].num_vertices,
10229 tc[2].create_options,
10230 tc[2].declaration,
10231 test_context->device, &mesh,
10232 tc[2].vertices, tc[2].vertex_size,
10233 tc[2].indices, tc[2].attributes);
10234 if (FAILED(hr))
10236 skip("Couldn't initialize test mesh for D3DXMESH_VB_SHARE case."
10237 " Got %x expected D3D_OK\n", hr);
10238 goto cleanup;
10241 hr = mesh->lpVtbl->CloneMesh(mesh, tc[2].create_options | D3DXMESH_VB_SHARE,
10242 tc[2].new_declaration, test_context->device,
10243 &mesh_clone);
10244 ok(hr == D3DERR_INVALIDCALL, "CloneMesh D3DXMESH_VB_SHARE with new"
10245 " declaration. Got %x, expected D3DERR_INVALIDCALL\n",
10246 hr);
10247 mesh->lpVtbl->Release(mesh);
10248 mesh = NULL;
10249 mesh_clone = NULL;
10251 cleanup:
10252 if (vertices) mesh->lpVtbl->UnlockVertexBuffer(mesh);
10253 if (mesh) mesh->lpVtbl->Release(mesh);
10254 if (mesh_clone) mesh_clone->lpVtbl->Release(mesh_clone);
10255 free_test_context(test_context);
10258 static void test_valid_mesh(void)
10260 HRESULT hr;
10261 struct test_context *test_context = NULL;
10262 UINT i;
10263 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
10264 const D3DVERTEXELEMENT9 declaration[] =
10266 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
10267 D3DDECL_END()
10269 const unsigned int VERTS_PER_FACE = 3;
10270 /* mesh0 (one face)
10272 * 0--1
10273 * | /
10274 * |/
10277 const D3DXVECTOR3 vertices0[] =
10279 { 0.0f, 3.0f, 0.f},
10280 { 2.0f, 3.0f, 0.f},
10281 { 0.0f, 0.0f, 0.f},
10283 const DWORD indices0[] = {0, 1, 2};
10284 const unsigned int num_vertices0 = ARRAY_SIZE(vertices0);
10285 const unsigned int num_faces0 = ARRAY_SIZE(indices0) / VERTS_PER_FACE;
10286 const DWORD adjacency0[] = {-1, -1, -1};
10287 const HRESULT exp_hr0 = D3D_OK;
10288 /* mesh1 (Simple bow-tie)
10290 * 0--1 1--3
10291 * | / \ |
10292 * |/ \|
10293 * 2 4
10295 const D3DXVECTOR3 vertices1[] =
10297 { 0.0f, 3.0f, 0.f},
10298 { 2.0f, 3.0f, 0.f},
10299 { 0.0f, 0.0f, 0.f},
10301 { 4.0f, 3.0f, 0.f},
10302 { 4.0f, 0.0f, 0.f},
10304 const DWORD indices1[] = {0, 1, 2, 1, 3, 4};
10305 const unsigned int num_vertices1 = ARRAY_SIZE(vertices1);
10306 const unsigned int num_faces1 = ARRAY_SIZE(indices1) / VERTS_PER_FACE;
10307 const DWORD adjacency1[] = {-1, -1, -1, -1, -1, -1};
10308 const HRESULT exp_hr1 = D3DXERR_INVALIDMESH;
10309 /* Common mesh data */
10310 ID3DXMesh *mesh = NULL;
10311 UINT vertex_size = sizeof(D3DXVECTOR3);
10312 ID3DXBuffer *errors_and_warnings = NULL;
10313 struct
10315 const D3DXVECTOR3 *vertices;
10316 const DWORD *indices;
10317 const UINT num_vertices;
10318 const UINT num_faces;
10319 const DWORD *adjacency;
10320 const HRESULT exp_hr;
10322 tc[] =
10325 vertices0,
10326 indices0,
10327 num_vertices0,
10328 num_faces0,
10329 adjacency0,
10330 exp_hr0,
10333 vertices1,
10334 indices1,
10335 num_vertices1,
10336 num_faces1,
10337 adjacency1,
10338 exp_hr1,
10342 test_context = new_test_context();
10343 if (!test_context)
10345 skip("Couldn't create test context\n");
10346 goto cleanup;
10349 for (i = 0; i < ARRAY_SIZE(tc); i++)
10351 hr = init_test_mesh(tc[i].num_faces, tc[i].num_vertices,
10352 options, declaration,
10353 test_context->device, &mesh,
10354 tc[i].vertices, vertex_size,
10355 tc[i].indices, NULL);
10356 if (FAILED(hr))
10358 skip("Couldn't initialize test mesh %d. Got %x expected D3D_OK\n", i, hr);
10359 goto cleanup;
10362 hr = D3DXValidMesh(mesh, tc[i].adjacency, &errors_and_warnings);
10363 todo_wine ok(hr == tc[i].exp_hr, "D3DXValidMesh test case %d failed. "
10364 "Got %x\n, expected %x\n", i, hr, tc[i].exp_hr);
10366 /* Note errors_and_warnings is deliberately not checked because that
10367 * would require copying wast amounts of the text output. */
10368 if (errors_and_warnings)
10370 ID3DXBuffer_Release(errors_and_warnings);
10371 errors_and_warnings = NULL;
10373 mesh->lpVtbl->Release(mesh);
10374 mesh = NULL;
10377 cleanup:
10378 if (mesh) mesh->lpVtbl->Release(mesh);
10379 free_test_context(test_context);
10382 static void test_optimize_faces(void)
10384 HRESULT hr;
10385 UINT i;
10386 DWORD smallest_face_remap;
10387 /* mesh0
10389 * 0--1
10390 * | /
10391 * |/
10394 const DWORD indices0[] = {0, 1, 2};
10395 const UINT num_faces0 = 1;
10396 const UINT num_vertices0 = 3;
10397 const DWORD exp_face_remap0[] = {0};
10398 /* mesh1
10400 * 0--1 3
10401 * | / /|
10402 * |/ / |
10403 * 2 5--4
10405 const DWORD indices1[] = {0, 1, 2, 3, 4, 5};
10406 const UINT num_faces1 = 2;
10407 const UINT num_vertices1 = 6;
10408 const DWORD exp_face_remap1[] = {1, 0};
10409 /* mesh2
10411 * 0--1
10412 * | /|
10413 * |/ |
10414 * 2--3
10416 const DWORD indices2[] = {0, 1, 2, 1, 3, 2};
10417 const UINT num_faces2 = 2;
10418 const UINT num_vertices2 = 4;
10419 const DWORD exp_face_remap2[] = {1, 0};
10420 /* mesh3
10422 * 0--1
10423 * | /|
10424 * |/ |
10425 * 2--3
10426 * | /|
10427 * |/ |
10428 * 4--5
10430 const DWORD indices3[] = {0, 1, 2, 1, 3, 2, 2, 3, 4, 3, 4, 5};
10431 const UINT num_faces3 = 4;
10432 const UINT num_vertices3 = 6;
10433 const DWORD exp_face_remap3[] = {3, 2, 1, 0};
10434 /* mesh4
10436 * 0--1
10437 * | /|
10438 * |/ |
10439 * 2--3
10440 * | /|
10441 * |/ |
10442 * 4--5
10444 const WORD indices4[] = {0, 1, 2, 1, 3, 2, 2, 3, 4, 3, 4, 5};
10445 const UINT num_faces4 = 4;
10446 const UINT num_vertices4 = 6;
10447 const DWORD exp_face_remap4[] = {3, 2, 1, 0};
10448 /* Test cases are stored in the tc array */
10449 struct
10451 const VOID *indices;
10452 const UINT num_faces;
10453 const UINT num_vertices;
10454 const BOOL indices_are_32bit;
10455 const DWORD *exp_face_remap;
10457 tc[] =
10460 indices0,
10461 num_faces0,
10462 num_vertices0,
10463 TRUE,
10464 exp_face_remap0
10467 indices1,
10468 num_faces1,
10469 num_vertices1,
10470 TRUE,
10471 exp_face_remap1
10474 indices2,
10475 num_faces2,
10476 num_vertices2,
10477 TRUE,
10478 exp_face_remap2
10481 indices3,
10482 num_faces3,
10483 num_vertices3,
10484 TRUE,
10485 exp_face_remap3
10488 indices4,
10489 num_faces4,
10490 num_vertices4,
10491 FALSE,
10492 exp_face_remap4
10496 /* Go through all test cases */
10497 for (i = 0; i < ARRAY_SIZE(tc); i++)
10499 DWORD j;
10500 DWORD *face_remap;
10501 face_remap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
10502 tc[i].num_faces*sizeof(*face_remap));
10504 hr = D3DXOptimizeFaces(tc[i].indices, tc[i].num_faces,
10505 tc[i].num_vertices, tc[i].indices_are_32bit,
10506 face_remap);
10507 ok(hr == D3D_OK, "D3DXOptimizeFaces test case %d failed. "
10508 "Got %x\n, expected D3D_OK\n", i, hr);
10510 /* Compare face remap with expected face remap */
10511 for (j = 0; j < tc[i].num_faces; j++)
10513 ok(tc[i].exp_face_remap[j] == face_remap[j],
10514 "Test case %d: Got face %d at %d, expected %d\n", i,
10515 face_remap[j], j, tc[i].exp_face_remap[j]);
10518 HeapFree(GetProcessHeap(), 0, face_remap);
10521 /* face_remap must not be NULL */
10522 hr = D3DXOptimizeFaces(tc[0].indices, tc[0].num_faces,
10523 tc[0].num_vertices, tc[0].indices_are_32bit,
10524 NULL);
10525 ok(hr == D3DERR_INVALIDCALL, "D3DXOptimizeFaces passed NULL face_remap "
10526 "pointer. Got %x\n, expected D3DERR_INVALIDCALL\n", hr);
10528 /* Number of faces must be smaller than 2^15 */
10529 hr = D3DXOptimizeFaces(tc[0].indices, 2 << 15,
10530 tc[0].num_vertices, FALSE,
10531 &smallest_face_remap);
10532 ok(hr == D3DERR_INVALIDCALL, "D3DXOptimizeFaces should not accept 2^15 "
10533 "faces when using 16-bit indices. Got %x\n, expected D3DERR_INVALIDCALL\n", hr);
10536 static HRESULT clear_normals(ID3DXMesh *mesh)
10538 HRESULT hr;
10539 BYTE *vertices;
10540 size_t normal_size;
10541 DWORD i, num_vertices, vertex_stride;
10542 const D3DXVECTOR4 normal = {NAN, NAN, NAN, NAN};
10543 D3DVERTEXELEMENT9 *normal_declaration = NULL;
10544 D3DVERTEXELEMENT9 declaration[MAX_FVF_DECL_SIZE] = {D3DDECL_END()};
10546 if (FAILED(hr = mesh->lpVtbl->GetDeclaration(mesh, declaration)))
10547 return hr;
10549 for (i = 0; declaration[i].Stream != 0xff; i++)
10551 if (declaration[i].Usage == D3DDECLUSAGE_NORMAL && !declaration[i].UsageIndex)
10553 normal_declaration = &declaration[i];
10554 break;
10558 if (!normal_declaration)
10559 return D3DERR_INVALIDCALL;
10561 if (normal_declaration->Type == D3DDECLTYPE_FLOAT3)
10563 normal_size = sizeof(D3DXVECTOR3);
10565 else if (normal_declaration->Type == D3DDECLTYPE_FLOAT4)
10567 normal_size = sizeof(D3DXVECTOR4);
10569 else
10571 trace("Cannot clear normals\n");
10572 return E_NOTIMPL;
10575 num_vertices = mesh->lpVtbl->GetNumVertices(mesh);
10576 vertex_stride = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
10578 if (FAILED(hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, (void **)&vertices)))
10579 return hr;
10581 vertices += normal_declaration->Offset;
10583 for (i = 0; i < num_vertices; i++, vertices += vertex_stride)
10584 memcpy(vertices, &normal, normal_size);
10586 return mesh->lpVtbl->UnlockVertexBuffer(mesh);
10589 static void compare_normals(unsigned int line, const char *test_name,
10590 ID3DXMesh *mesh, const D3DXVECTOR3 *normals, unsigned int num_normals)
10592 unsigned int i;
10593 BYTE *vertices;
10594 DWORD num_vertices, vertex_stride;
10595 D3DVERTEXELEMENT9 *normal_declaration = NULL;
10596 D3DVERTEXELEMENT9 declaration[MAX_FVF_DECL_SIZE] = {D3DDECL_END()};
10598 if (FAILED(mesh->lpVtbl->GetDeclaration(mesh, declaration)))
10600 ok_(__FILE__, line)(0, "%s: Failed to get declaration\n", test_name);
10601 return;
10604 for (i = 0; declaration[i].Stream != 0xff; i++)
10606 if (declaration[i].Usage == D3DDECLUSAGE_NORMAL && !declaration[i].UsageIndex)
10608 normal_declaration = &declaration[i];
10609 break;
10613 if (!normal_declaration)
10615 ok_(__FILE__, line)(0, "%s: Mesh has no normals\n", test_name);
10616 return;
10619 if (normal_declaration->Type != D3DDECLTYPE_FLOAT3 && normal_declaration->Type != D3DDECLTYPE_FLOAT4)
10621 ok_(__FILE__, line)(0, "%s: Mesh has invalid normals type\n", test_name);
10622 return;
10625 num_vertices = mesh->lpVtbl->GetNumVertices(mesh);
10626 vertex_stride = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
10628 ok_(__FILE__, line)(num_vertices == num_normals, "%s: Expected %u vertices, got %u\n", test_name,
10629 num_normals, num_vertices);
10631 if (FAILED(mesh->lpVtbl->LockVertexBuffer(mesh, 0, (void **)&vertices)))
10633 ok_(__FILE__, line)(0, "%s: Failed to compare normals\n", test_name);
10634 return;
10637 vertices += normal_declaration->Offset;
10639 for (i = 0; i < min(num_vertices, num_normals); i++, vertices += vertex_stride)
10641 if (normal_declaration->Type == D3DDECLTYPE_FLOAT3)
10643 const D3DXVECTOR3 *n = (D3DXVECTOR3 *)vertices;
10644 ok_(__FILE__, line)(compare_vec3(*n, normals[i]),
10645 "%s: normal %2u, expected (%f, %f, %f), got (%f, %f, %f)\n",
10646 test_name, i, normals[i].x, normals[i].y, normals[i].z, n->x, n->y, n->z);
10648 else
10650 const D3DXVECTOR4 *n = (D3DXVECTOR4 *)vertices;
10651 const D3DXVECTOR4 normal = {normals[i].x, normals[i].y, normals[i].z, 1.0f};
10652 ok_(__FILE__, line)(compare_vec4(*n, normal),
10653 "%s: normal %2u, expected (%f, %f, %f, %f), got (%f, %f, %f, %f)\n",
10654 test_name, i, normals[i].x, normals[i].y, normals[i].z, 1.0f,
10655 n->x, n->y, n->z, n->w);
10659 mesh->lpVtbl->UnlockVertexBuffer(mesh);
10662 static HRESULT compute_normals_D3DXComputeNormals(ID3DXMesh *mesh, const DWORD *adjacency)
10664 return D3DXComputeNormals((ID3DXBaseMesh *)mesh, adjacency);
10667 static HRESULT compute_normals_D3DXComputeTangentFrameEx(ID3DXMesh *mesh, const DWORD *adjacency)
10669 return D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
10670 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS,
10671 adjacency, -1.01f, -0.01f, -1.01f, NULL, NULL);
10674 static void test_compute_normals(void)
10676 HRESULT hr;
10677 ULONG refcount;
10678 ID3DXMesh *mesh, *cloned_mesh;
10679 ID3DXBuffer *adjacency;
10680 IDirect3DDevice9 *device;
10681 struct test_context *test_context;
10682 unsigned int i;
10684 static const struct compute_normals_func
10686 const char *name;
10687 HRESULT (*apply)(ID3DXMesh *mesh, const DWORD *adjacency);
10689 compute_normals_funcs[] =
10691 {"D3DXComputeNormals", compute_normals_D3DXComputeNormals },
10692 {"D3DXComputeTangentFrameEx", compute_normals_D3DXComputeTangentFrameEx}
10695 static const D3DXVECTOR3 box_normals[24] =
10697 {-1.0f, 0.0f, 0.0f}, {-1.0f, 0.0f, 0.0f}, {-1.0f, 0.0f, 0.0f}, {-1.0f, 0.0f, 0.0f},
10698 { 0.0f, 1.0f, 0.0f}, { 0.0f, 1.0f, 0.0f}, { 0.0f, 1.0f, 0.0f}, { 0.0f, 1.0f, 0.0f},
10699 { 1.0f, 0.0f, 0.0f}, { 1.0f, 0.0f, 0.0f}, { 1.0f, 0.0f, 0.0f}, { 1.0f, 0.0f, 0.0f},
10700 { 0.0f,-1.0f, 0.0f}, { 0.0f,-1.0f, 0.0f}, { 0.0f,-1.0f, 0.0f}, { 0.0f,-1.0f, 0.0f},
10701 { 0.0f, 0.0f, 1.0f}, { 0.0f, 0.0f, 1.0f}, { 0.0f, 0.0f, 1.0f}, { 0.0f, 0.0f, 1.0f},
10702 { 0.0f, 0.0f,-1.0f}, { 0.0f, 0.0f,-1.0f}, { 0.0f, 0.0f,-1.0f}, { 0.0f, 0.0f,-1.0f}
10704 const float box_normal_component = 1.0f / sqrtf(3.0f);
10705 const D3DXVECTOR3 box_normals_adjacency[24] =
10707 {-box_normal_component, -box_normal_component, -box_normal_component},
10708 {-box_normal_component, -box_normal_component, box_normal_component},
10709 {-box_normal_component, box_normal_component, box_normal_component},
10710 {-box_normal_component, box_normal_component, -box_normal_component},
10711 {-box_normal_component, box_normal_component, -box_normal_component},
10712 {-box_normal_component, box_normal_component, box_normal_component},
10713 { box_normal_component, box_normal_component, box_normal_component},
10714 { box_normal_component, box_normal_component, -box_normal_component},
10715 { box_normal_component, box_normal_component, -box_normal_component},
10716 { box_normal_component, box_normal_component, box_normal_component},
10717 { box_normal_component, -box_normal_component, box_normal_component},
10718 { box_normal_component, -box_normal_component, -box_normal_component},
10719 {-box_normal_component, -box_normal_component, box_normal_component},
10720 {-box_normal_component, -box_normal_component, -box_normal_component},
10721 { box_normal_component, -box_normal_component, -box_normal_component},
10722 { box_normal_component, -box_normal_component, box_normal_component},
10723 {-box_normal_component, -box_normal_component, box_normal_component},
10724 { box_normal_component, -box_normal_component, box_normal_component},
10725 { box_normal_component, box_normal_component, box_normal_component},
10726 {-box_normal_component, box_normal_component, box_normal_component},
10727 {-box_normal_component, -box_normal_component, -box_normal_component},
10728 {-box_normal_component, box_normal_component, -box_normal_component},
10729 { box_normal_component, box_normal_component, -box_normal_component},
10730 { box_normal_component, -box_normal_component, -box_normal_component}
10732 static const D3DXVECTOR3 box_normals_adjacency_area[24] =
10734 {-0.666667f, -0.333333f, -0.666667f}, {-0.333333f, -0.666667f, 0.666667f},
10735 {-0.816496f, 0.408248f, 0.408248f}, {-0.408248f, 0.816496f, -0.408248f},
10736 {-0.408248f, 0.816496f, -0.408248f}, {-0.816496f, 0.408248f, 0.408248f},
10737 { 0.333333f, 0.666667f, 0.666667f}, { 0.666667f, 0.333333f, -0.666667f},
10738 { 0.666667f, 0.333333f, -0.666667f}, { 0.333333f, 0.666667f, 0.666667f},
10739 { 0.816496f, -0.408248f, 0.408248f}, { 0.408248f, -0.816496f, -0.408248f},
10740 {-0.333333f, -0.666667f, 0.666667f}, {-0.666667f, -0.333333f, -0.666667f},
10741 { 0.408248f, -0.816496f, -0.408248f}, { 0.816496f, -0.408248f, 0.408248f},
10742 {-0.333333f, -0.666667f, 0.666667f}, { 0.816497f, -0.408248f, 0.408248f},
10743 { 0.333333f, 0.666667f, 0.666667f}, {-0.816497f, 0.408248f, 0.408248f},
10744 {-0.666667f, -0.333333f, -0.666667f}, {-0.408248f, 0.816497f, -0.408248f},
10745 { 0.666667f, 0.333333f, -0.666667f}, { 0.408248f, -0.816496f, -0.408248f}
10747 static const D3DXVECTOR3 box_normals_position1f[24] = {{0}};
10748 static const D3DXVECTOR3 box_normals_position2f[24] =
10750 {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f},
10751 {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, 1.0f},
10752 {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, -1.0f},
10753 {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f},
10754 {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, -1.0f},
10755 {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f},
10756 {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f},
10757 {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, -1.0f}
10760 static const D3DXVECTOR3 sphere_normals[22] =
10762 { 0.000000f, -0.000000f, 1.000000f}, { 0.000000f, 0.582244f, 0.813014f},
10763 { 0.582244f, -0.000000f, 0.813014f}, {-0.000000f, -0.582244f, 0.813014f},
10764 {-0.582244f, 0.000000f, 0.813014f}, {-0.000000f, 0.890608f, 0.454772f},
10765 { 0.890608f, 0.000000f, 0.454772f}, { 0.000000f, -0.890608f, 0.454772f},
10766 {-0.890608f, -0.000000f, 0.454772f}, { 0.000000f, 1.000000f, -0.000000f},
10767 { 1.000000f, -0.000000f, -0.000000f}, {-0.000000f, -1.000000f, -0.000000f},
10768 {-1.000000f, 0.000000f, -0.000000f}, { 0.000000f, 0.890608f, -0.454773f},
10769 { 0.890608f, -0.000000f, -0.454772f}, {-0.000000f, -0.890608f, -0.454773f},
10770 {-0.890608f, 0.000000f, -0.454773f}, { 0.000000f, 0.582244f, -0.813015f},
10771 { 0.582244f, -0.000000f, -0.813015f}, { 0.000000f, -0.582244f, -0.813015f},
10772 {-0.582243f, 0.000000f, -0.813015f}, { 0.000000f, 0.000000f, -1.000000f}
10774 static const D3DXVECTOR3 sphere_normals_area[22] =
10776 { 0.000000f, -0.000000f, 1.000000f}, {-0.215311f, 0.554931f, 0.803550f},
10777 { 0.554931f, 0.215311f, 0.803550f}, { 0.215311f, -0.554931f, 0.803550f},
10778 {-0.554931f, -0.215311f, 0.803550f}, {-0.126638f, 0.872121f, 0.472618f},
10779 { 0.872121f, 0.126638f, 0.472618f}, { 0.126638f, -0.872121f, 0.472618f},
10780 {-0.872121f, -0.126637f, 0.472618f}, { 0.000000f, 1.000000f, -0.000000f},
10781 { 1.000000f, -0.000000f, -0.000000f}, {-0.000000f, -1.000000f, -0.000000f},
10782 {-1.000000f, 0.000000f, -0.000000f}, { 0.126638f, 0.872121f, -0.472618f},
10783 { 0.872121f, -0.126638f, -0.472618f}, {-0.126638f, -0.872121f, -0.472618f},
10784 {-0.872121f, 0.126638f, -0.472618f}, { 0.215311f, 0.554931f, -0.803550f},
10785 { 0.554931f, -0.215311f, -0.803550f}, {-0.215311f, -0.554931f, -0.803550f},
10786 {-0.554931f, 0.215311f, -0.803550f}, { 0.000000f, 0.000000f, -1.000000f}
10788 static const D3DXVECTOR3 sphere_normals_equal[22] =
10790 { 0.000000f, -0.000000f, 1.000000f}, {-0.134974f, 0.522078f, 0.842150f},
10791 { 0.522078f, 0.134974f, 0.842150f}, { 0.134974f, -0.522078f, 0.842150f},
10792 {-0.522078f, -0.134974f, 0.842150f}, {-0.026367f, 0.857121f, 0.514440f},
10793 { 0.857121f, 0.026367f, 0.514440f}, { 0.026367f, -0.857121f, 0.514440f},
10794 {-0.857121f, -0.026367f, 0.514440f}, { 0.000000f, 1.000000f, -0.000000f},
10795 { 1.000000f, -0.000000f, -0.000000f}, {-0.000000f, -1.000000f, -0.000000f},
10796 {-1.000000f, 0.000000f, -0.000000f}, { 0.026367f, 0.857121f, -0.514440f},
10797 { 0.857121f, -0.026367f, -0.514440f}, {-0.026367f, -0.857121f, -0.514440f},
10798 {-0.857121f, 0.026367f, -0.514440f}, { 0.134975f, 0.522078f, -0.842150f},
10799 { 0.522078f, -0.134975f, -0.842150f}, {-0.134974f, -0.522078f, -0.842150f},
10800 {-0.522078f, 0.134974f, -0.842150f}, { 0.000000f, 0.000000f, -1.000000f}
10803 static const D3DVERTEXELEMENT9 position3f_normal1f_declaration[] =
10805 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
10806 {0, sizeof(D3DXVECTOR3), D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
10807 D3DDECL_END()
10809 static const D3DVERTEXELEMENT9 position3f_normal2f_declaration[] =
10811 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
10812 {0, sizeof(D3DXVECTOR3), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
10813 D3DDECL_END()
10815 static const D3DVERTEXELEMENT9 normal4f_position3f_declaration[] =
10817 {0, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
10818 {0, sizeof(D3DXVECTOR4), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
10819 D3DDECL_END()
10821 static const D3DVERTEXELEMENT9 position1f_normal3f_declaration[] =
10823 {0, 0, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
10824 {0, sizeof(float), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
10825 D3DDECL_END()
10827 static const D3DVERTEXELEMENT9 position2f_normal3f_declaration[] =
10829 {0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
10830 {0, sizeof(D3DXVECTOR2), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
10831 D3DDECL_END()
10833 static const D3DVERTEXELEMENT9 position4f_normal3f_declaration[] =
10835 {0, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
10836 {0, sizeof(D3DXVECTOR4), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
10837 D3DDECL_END()
10840 for (i = 0; i < ARRAY_SIZE(compute_normals_funcs); i++)
10842 hr = compute_normals_funcs[i].apply(NULL, NULL);
10843 ok(hr == D3DERR_INVALIDCALL, "%s returned %#x, expected D3DERR_INVALIDCALL\n", compute_normals_funcs[i].name, hr);
10846 if (!(test_context = new_test_context()))
10848 skip("Couldn't create test context\n");
10849 return;
10851 device = test_context->device;
10853 hr = D3DXCreateBox(device, 1.0f, 1.0f, 1.0f, &mesh, &adjacency);
10854 ok(SUCCEEDED(hr), "D3DXCreateBox failed %#x\n", hr);
10856 /* Check wrong input */
10857 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
10858 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE, NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
10859 todo_wine ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr);
10861 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DDECLUSAGE_NORMAL, 0,
10862 D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_BY_AREA | D3DXTANGENT_WEIGHT_EQUAL,
10863 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
10864 ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr);
10866 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
10867 D3DDECLUSAGE_NORMAL, 0, 0, NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
10868 todo_wine ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr);
10870 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
10871 D3DDECLUSAGE_NORMAL, 1, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS,
10872 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
10873 ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr);
10875 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
10876 D3DX_DEFAULT, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS,
10877 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
10878 ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr);
10880 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
10881 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_CALCULATE_NORMALS,
10882 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
10883 todo_wine ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr);
10885 for (i = 0; i < ARRAY_SIZE(compute_normals_funcs); i++)
10887 const struct compute_normals_func *func = &compute_normals_funcs[i];
10889 /* Mesh without normals */
10890 hr = mesh->lpVtbl->CloneMeshFVF(mesh, 0, D3DFVF_XYZ, device, &cloned_mesh);
10891 ok(SUCCEEDED(hr), "CloneMeshFVF failed %#x\n", hr);
10893 hr = func->apply(cloned_mesh, NULL);
10894 ok(hr == D3DERR_INVALIDCALL, "%s returned %#x, expected D3DERR_INVALIDCALL\n", func->name, hr);
10896 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh);
10897 ok(!refcount, "Mesh has %u references left\n", refcount);
10899 /* Mesh without positions */
10900 hr = mesh->lpVtbl->CloneMeshFVF(mesh, 0, D3DFVF_NORMAL, device, &cloned_mesh);
10901 ok(SUCCEEDED(hr), "CloneMeshFVF failed %#x\n", hr);
10903 hr = func->apply(cloned_mesh, NULL);
10904 ok(hr == D3DERR_INVALIDCALL, "%s returned %#x, expected D3DERR_INVALIDCALL\n", func->name, hr);
10906 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh);
10907 ok(!refcount, "Mesh has %u references left\n", refcount);
10909 /* Mesh with D3DDECLTYPE_FLOAT1 normals */
10910 hr = mesh->lpVtbl->CloneMesh(mesh, 0, position3f_normal1f_declaration, device, &cloned_mesh);
10911 ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr);
10913 hr = func->apply(cloned_mesh, NULL);
10914 ok(hr == D3DERR_INVALIDCALL, "%s returned %#x, expected D3DERR_INVALIDCALL\n", func->name, hr);
10916 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh);
10917 ok(!refcount, "Mesh has %u references left\n", refcount);
10919 /* Mesh with D3DDECLTYPE_FLOAT2 normals */
10920 hr = mesh->lpVtbl->CloneMesh(mesh, 0, position3f_normal2f_declaration, device, &cloned_mesh);
10921 ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr);
10923 hr = func->apply(cloned_mesh, NULL);
10924 ok(hr == D3DERR_INVALIDCALL, "%s returned %#x, expected D3DERR_INVALIDCALL\n", func->name, hr);
10926 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh);
10927 ok(!refcount, "Mesh has %u references left\n", refcount);
10929 /* Mesh without adjacency data */
10930 hr = clear_normals(mesh);
10931 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr);
10933 hr = func->apply(mesh, NULL);
10934 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr);
10936 compare_normals(__LINE__, func->name, mesh, box_normals, ARRAY_SIZE(box_normals));
10938 /* Mesh with adjacency data */
10939 hr = clear_normals(mesh);
10940 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr);
10942 hr = func->apply(mesh, ID3DXBuffer_GetBufferPointer(adjacency));
10943 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr);
10945 compare_normals(__LINE__, func->name, mesh, box_normals_adjacency, ARRAY_SIZE(box_normals_adjacency));
10947 /* Mesh with custom vertex format, D3DDECLTYPE_FLOAT4 normals and adjacency */
10948 hr = mesh->lpVtbl->CloneMesh(mesh, 0, normal4f_position3f_declaration, device, &cloned_mesh);
10949 ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr);
10951 hr = clear_normals(cloned_mesh);
10952 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr);
10954 hr = func->apply(cloned_mesh, ID3DXBuffer_GetBufferPointer(adjacency));
10955 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr);
10957 compare_normals(__LINE__, func->name, cloned_mesh, box_normals_adjacency, ARRAY_SIZE(box_normals_adjacency));
10959 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh);
10960 ok(!refcount, "Mesh has %u references left\n", refcount);
10962 /* Mesh with D3DDECLTYPE_FLOAT1 positions and D3DDECLTYPE_FLOAT3 normals */
10963 hr = mesh->lpVtbl->CloneMesh(mesh, 0, position1f_normal3f_declaration, device, &cloned_mesh);
10964 ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr);
10966 hr = clear_normals(cloned_mesh);
10967 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr);
10969 hr = func->apply(cloned_mesh, ID3DXBuffer_GetBufferPointer(adjacency));
10970 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr);
10972 compare_normals(__LINE__, func->name, cloned_mesh, box_normals_position1f, ARRAY_SIZE(box_normals_position1f));
10974 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh);
10975 ok(!refcount, "Mesh has %u references left\n", refcount);
10977 /* Mesh with D3DDECLTYPE_FLOAT2 positions and D3DDECLTYPE_FLOAT3 normals */
10978 hr = mesh->lpVtbl->CloneMesh(mesh, 0, position2f_normal3f_declaration, device, &cloned_mesh);
10979 ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr);
10981 hr = clear_normals(cloned_mesh);
10982 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr);
10984 hr = func->apply(cloned_mesh, ID3DXBuffer_GetBufferPointer(adjacency));
10985 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr);
10987 compare_normals(__LINE__, func->name, cloned_mesh, box_normals_position2f, ARRAY_SIZE(box_normals_position2f));
10989 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh);
10990 ok(!refcount, "Mesh has %u references left\n", refcount);
10992 /* Mesh with D3DDECLTYPE_FLOAT4 positions and D3DDECLTYPE_FLOAT3 normals */
10993 hr = mesh->lpVtbl->CloneMesh(mesh, 0, position4f_normal3f_declaration, device, &cloned_mesh);
10994 ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr);
10996 hr = clear_normals(cloned_mesh);
10997 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr);
10999 hr = func->apply(cloned_mesh, ID3DXBuffer_GetBufferPointer(adjacency));
11000 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr);
11002 compare_normals(__LINE__, func->name, cloned_mesh, box_normals_adjacency, ARRAY_SIZE(box_normals_adjacency));
11004 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh);
11005 ok(!refcount, "Mesh has %u references left\n", refcount);
11008 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
11009 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_BY_AREA,
11010 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
11011 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr);
11013 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, box_normals, ARRAY_SIZE(box_normals));
11015 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
11016 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_BY_AREA,
11017 ID3DXBuffer_GetBufferPointer(adjacency), -1.01f, -0.01f, -1.01f, NULL, NULL);
11018 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr);
11020 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, box_normals_adjacency_area, ARRAY_SIZE(box_normals_adjacency_area));
11022 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
11023 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_EQUAL,
11024 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
11025 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr);
11027 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, box_normals, ARRAY_SIZE(box_normals));
11029 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
11030 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_EQUAL,
11031 ID3DXBuffer_GetBufferPointer(adjacency), -1.01f, -0.01f, -1.01f, NULL, NULL);
11032 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr);
11034 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, box_normals_adjacency_area, ARRAY_SIZE(box_normals_adjacency_area));
11036 refcount = mesh->lpVtbl->Release(mesh);
11037 ok(!refcount, "Mesh has %u references left\n", refcount);
11038 refcount = ID3DXBuffer_Release(adjacency);
11039 ok(!refcount, "Buffer has %u references left\n", refcount);
11041 hr = D3DXCreateSphere(device, 1.0f, 4, 6, &mesh, &adjacency);
11042 ok(SUCCEEDED(hr), "D3DXCreateSphere failed %#x\n", hr);
11044 for (i = 0; i < ARRAY_SIZE(compute_normals_funcs); i++)
11046 const struct compute_normals_func *func = &compute_normals_funcs[i];
11048 /* Sphere without adjacency data */
11049 hr = clear_normals(mesh);
11050 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr);
11052 hr = func->apply(mesh, NULL);
11053 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr);
11055 compare_normals(__LINE__, func->name, mesh, sphere_normals, ARRAY_SIZE(sphere_normals));
11057 /* Sphere with adjacency data */
11058 hr = clear_normals(mesh);
11059 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr);
11061 hr = func->apply(mesh, ID3DXBuffer_GetBufferPointer(adjacency));
11062 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr);
11064 compare_normals(__LINE__, func->name, mesh, sphere_normals, ARRAY_SIZE(sphere_normals));
11067 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
11068 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_BY_AREA,
11069 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
11070 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr);
11072 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, sphere_normals_area, ARRAY_SIZE(sphere_normals_area));
11074 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
11075 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_BY_AREA,
11076 ID3DXBuffer_GetBufferPointer(adjacency), -1.01f, -0.01f, -1.01f, NULL, NULL);
11077 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr);
11079 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, sphere_normals_area, ARRAY_SIZE(sphere_normals_area));
11081 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
11082 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_EQUAL,
11083 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
11084 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr);
11086 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, sphere_normals_equal, ARRAY_SIZE(sphere_normals_equal));
11088 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
11089 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_EQUAL,
11090 ID3DXBuffer_GetBufferPointer(adjacency), -1.01f, -0.01f, -1.01f, NULL, NULL);
11091 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr);
11093 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, sphere_normals_equal, ARRAY_SIZE(sphere_normals_equal));
11095 refcount = mesh->lpVtbl->Release(mesh);
11096 ok(!refcount, "Mesh has %u references left\n", refcount);
11097 refcount = ID3DXBuffer_Release(adjacency);
11098 ok(!refcount, "Buffer has %u references left\n", refcount);
11100 free_test_context(test_context);
11103 START_TEST(mesh)
11105 D3DXBoundProbeTest();
11106 D3DXComputeBoundingBoxTest();
11107 D3DXComputeBoundingSphereTest();
11108 D3DXGetFVFVertexSizeTest();
11109 D3DXIntersectTriTest();
11110 D3DXCreateMeshTest();
11111 D3DXCreateMeshFVFTest();
11112 D3DXLoadMeshTest();
11113 D3DXCreateBoxTest();
11114 D3DXCreatePolygonTest();
11115 D3DXCreateSphereTest();
11116 D3DXCreateCylinderTest();
11117 D3DXCreateTextTest();
11118 D3DXCreateTorusTest();
11119 test_get_decl_length();
11120 test_get_decl_vertex_size();
11121 test_fvf_decl_conversion();
11122 D3DXGenerateAdjacencyTest();
11123 test_update_semantics();
11124 test_create_skin_info();
11125 test_convert_adjacency_to_point_reps();
11126 test_convert_point_reps_to_adjacency();
11127 test_weld_vertices();
11128 test_clone_mesh();
11129 test_valid_mesh();
11130 test_optimize_faces();
11131 test_compute_normals();