user32: Add stub for SetThreadDpiAwarenessContext.
[wine.git] / dlls / d3dx9_36 / tests / mesh.c
blob6ebd5b82156a480617949c8612e9d285f82565d2
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 < ARRAY_SIZE(test_data); ++i)
823 test_decl_to_fvf(test_data[i].decl, test_data[i].fvf, D3D_OK, __LINE__, i);
824 test_fvf_to_decl(test_data[i].fvf, test_data[i].decl, D3D_OK, __LINE__, i);
827 /* Usage indices for position and normal are apparently ignored. */
829 const D3DVERTEXELEMENT9 decl[] =
831 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 1},
832 D3DDECL_END(),
834 test_decl_to_fvf(decl, D3DFVF_XYZ, D3D_OK, __LINE__, 0);
837 const D3DVERTEXELEMENT9 decl[] =
839 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 1},
840 D3DDECL_END(),
842 test_decl_to_fvf(decl, D3DFVF_NORMAL, D3D_OK, __LINE__, 0);
844 /* D3DFVF_LASTBETA_UBYTE4 and D3DFVF_LASTBETA_D3DCOLOR are ignored if
845 * there are no blend matrices. */
847 const D3DVERTEXELEMENT9 decl[] =
849 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
850 D3DDECL_END(),
852 test_fvf_to_decl(D3DFVF_XYZ | D3DFVF_LASTBETA_UBYTE4, decl, D3D_OK, __LINE__, 0);
855 const D3DVERTEXELEMENT9 decl[] =
857 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
858 D3DDECL_END(),
860 test_fvf_to_decl(D3DFVF_XYZ | D3DFVF_LASTBETA_D3DCOLOR, decl, D3D_OK, __LINE__, 0);
862 /* D3DFVF_LASTBETA_UBYTE4 takes precedence over D3DFVF_LASTBETA_D3DCOLOR. */
864 const D3DVERTEXELEMENT9 decl[] =
866 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
867 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
868 {0, 28, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
869 D3DDECL_END(),
871 test_fvf_to_decl(D3DFVF_XYZB5 | D3DFVF_LASTBETA_D3DCOLOR | D3DFVF_LASTBETA_UBYTE4,
872 decl, D3D_OK, __LINE__, 0);
874 /* These are supposed to fail, both ways. */
876 const D3DVERTEXELEMENT9 decl[] =
878 {0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITION, 0},
879 D3DDECL_END(),
881 test_decl_to_fvf(decl, D3DFVF_XYZW, D3DERR_INVALIDCALL, __LINE__, 0);
882 test_fvf_to_decl(D3DFVF_XYZW, decl, D3DERR_INVALIDCALL, __LINE__, 0);
885 const D3DVERTEXELEMENT9 decl[] =
887 {0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITION, 0},
888 {0, 16, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
889 D3DDECL_END(),
891 test_decl_to_fvf(decl, D3DFVF_XYZW | D3DFVF_NORMAL, D3DERR_INVALIDCALL, __LINE__, 0);
892 test_fvf_to_decl(D3DFVF_XYZW | D3DFVF_NORMAL, decl, D3DERR_INVALIDCALL, __LINE__, 0);
895 const D3DVERTEXELEMENT9 decl[] =
897 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
898 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
899 {0, 28, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDINDICES, 0},
900 D3DDECL_END(),
902 test_decl_to_fvf(decl, D3DFVF_XYZB5, D3DERR_INVALIDCALL, __LINE__, 0);
903 test_fvf_to_decl(D3DFVF_XYZB5, decl, D3DERR_INVALIDCALL, __LINE__, 0);
905 /* Test a declaration that can't be converted to an FVF. */
907 const D3DVERTEXELEMENT9 decl[] =
909 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
910 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
911 {0, 24, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_PSIZE, 0},
912 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1},
913 {0, 32, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
914 /* 8 bytes padding */
915 {0, 44, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 1},
916 D3DDECL_END(),
918 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0);
920 /* Elements must be ordered by offset. */
922 const D3DVERTEXELEMENT9 decl[] =
924 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
925 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
926 D3DDECL_END(),
928 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0);
930 /* Basic tests for element order. */
932 const D3DVERTEXELEMENT9 decl[] =
934 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
935 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
936 {0, 16, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
937 D3DDECL_END(),
939 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0);
942 const D3DVERTEXELEMENT9 decl[] =
944 {0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
945 {0, 4, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
946 D3DDECL_END(),
948 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0);
951 const D3DVERTEXELEMENT9 decl[] =
953 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
954 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
955 D3DDECL_END(),
957 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0);
959 /* Textures must be ordered by texcoords. */
961 const D3DVERTEXELEMENT9 decl[] =
963 {0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
964 {0, 4, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 2},
965 {0, 16, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 1},
966 {0, 24, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 3},
967 D3DDECL_END(),
969 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0);
971 /* Duplicate elements are not allowed. */
973 const D3DVERTEXELEMENT9 decl[] =
975 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
976 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
977 {0, 16, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
978 D3DDECL_END(),
980 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0);
982 /* Invalid FVFs cannot be converted to a declarator. */
983 test_fvf_to_decl(0xdeadbeef, NULL, D3DERR_INVALIDCALL, __LINE__, 0);
986 static void D3DXGetFVFVertexSizeTest(void)
988 UINT got;
990 compare_vertex_sizes (D3DFVF_XYZ, 12);
992 compare_vertex_sizes (D3DFVF_XYZB3, 24);
994 compare_vertex_sizes (D3DFVF_XYZB5, 32);
996 compare_vertex_sizes (D3DFVF_XYZ | D3DFVF_NORMAL, 24);
998 compare_vertex_sizes (D3DFVF_XYZ | D3DFVF_DIFFUSE, 16);
1000 compare_vertex_sizes (
1001 D3DFVF_XYZ |
1002 D3DFVF_TEX1 |
1003 D3DFVF_TEXCOORDSIZE1(0), 16);
1004 compare_vertex_sizes (
1005 D3DFVF_XYZ |
1006 D3DFVF_TEX2 |
1007 D3DFVF_TEXCOORDSIZE1(0) |
1008 D3DFVF_TEXCOORDSIZE1(1), 20);
1010 compare_vertex_sizes (
1011 D3DFVF_XYZ |
1012 D3DFVF_TEX1 |
1013 D3DFVF_TEXCOORDSIZE2(0), 20);
1015 compare_vertex_sizes (
1016 D3DFVF_XYZ |
1017 D3DFVF_TEX2 |
1018 D3DFVF_TEXCOORDSIZE2(0) |
1019 D3DFVF_TEXCOORDSIZE2(1), 28);
1021 compare_vertex_sizes (
1022 D3DFVF_XYZ |
1023 D3DFVF_TEX6 |
1024 D3DFVF_TEXCOORDSIZE2(0) |
1025 D3DFVF_TEXCOORDSIZE2(1) |
1026 D3DFVF_TEXCOORDSIZE2(2) |
1027 D3DFVF_TEXCOORDSIZE2(3) |
1028 D3DFVF_TEXCOORDSIZE2(4) |
1029 D3DFVF_TEXCOORDSIZE2(5), 60);
1031 compare_vertex_sizes (
1032 D3DFVF_XYZ |
1033 D3DFVF_TEX8 |
1034 D3DFVF_TEXCOORDSIZE2(0) |
1035 D3DFVF_TEXCOORDSIZE2(1) |
1036 D3DFVF_TEXCOORDSIZE2(2) |
1037 D3DFVF_TEXCOORDSIZE2(3) |
1038 D3DFVF_TEXCOORDSIZE2(4) |
1039 D3DFVF_TEXCOORDSIZE2(5) |
1040 D3DFVF_TEXCOORDSIZE2(6) |
1041 D3DFVF_TEXCOORDSIZE2(7), 76);
1043 compare_vertex_sizes (
1044 D3DFVF_XYZ |
1045 D3DFVF_TEX1 |
1046 D3DFVF_TEXCOORDSIZE3(0), 24);
1048 compare_vertex_sizes (
1049 D3DFVF_XYZ |
1050 D3DFVF_TEX4 |
1051 D3DFVF_TEXCOORDSIZE3(0) |
1052 D3DFVF_TEXCOORDSIZE3(1) |
1053 D3DFVF_TEXCOORDSIZE3(2) |
1054 D3DFVF_TEXCOORDSIZE3(3), 60);
1056 compare_vertex_sizes (
1057 D3DFVF_XYZ |
1058 D3DFVF_TEX1 |
1059 D3DFVF_TEXCOORDSIZE4(0), 28);
1061 compare_vertex_sizes (
1062 D3DFVF_XYZ |
1063 D3DFVF_TEX2 |
1064 D3DFVF_TEXCOORDSIZE4(0) |
1065 D3DFVF_TEXCOORDSIZE4(1), 44);
1067 compare_vertex_sizes (
1068 D3DFVF_XYZ |
1069 D3DFVF_TEX3 |
1070 D3DFVF_TEXCOORDSIZE4(0) |
1071 D3DFVF_TEXCOORDSIZE4(1) |
1072 D3DFVF_TEXCOORDSIZE4(2), 60);
1074 compare_vertex_sizes (
1075 D3DFVF_XYZB5 |
1076 D3DFVF_NORMAL |
1077 D3DFVF_DIFFUSE |
1078 D3DFVF_SPECULAR |
1079 D3DFVF_TEX8 |
1080 D3DFVF_TEXCOORDSIZE4(0) |
1081 D3DFVF_TEXCOORDSIZE4(1) |
1082 D3DFVF_TEXCOORDSIZE4(2) |
1083 D3DFVF_TEXCOORDSIZE4(3) |
1084 D3DFVF_TEXCOORDSIZE4(4) |
1085 D3DFVF_TEXCOORDSIZE4(5) |
1086 D3DFVF_TEXCOORDSIZE4(6) |
1087 D3DFVF_TEXCOORDSIZE4(7), 180);
1090 static void D3DXIntersectTriTest(void)
1092 BOOL exp_res, got_res;
1093 D3DXVECTOR3 position, ray, vertex[3];
1094 FLOAT exp_dist, got_dist, exp_u, got_u, exp_v, got_v;
1096 vertex[0].x = 1.0f; vertex[0].y = 0.0f; vertex[0].z = 0.0f;
1097 vertex[1].x = 2.0f; vertex[1].y = 0.0f; vertex[1].z = 0.0f;
1098 vertex[2].x = 1.0f; vertex[2].y = 1.0f; vertex[2].z = 0.0f;
1100 position.x = -14.5f; position.y = -23.75f; position.z = -32.0f;
1102 ray.x = 2.0f; ray.y = 3.0f; ray.z = 4.0f;
1104 exp_res = TRUE; exp_u = 0.5f; exp_v = 0.25f; exp_dist = 8.0f;
1106 got_res = D3DXIntersectTri(&vertex[0], &vertex[1], &vertex[2], &position, &ray, &got_u, &got_v, &got_dist);
1107 ok(got_res == exp_res, "Expected result %d, got %d.\n", exp_res, got_res);
1108 ok(compare(exp_u, got_u), "Expected u %f, got %f.\n", exp_u, got_u);
1109 ok(compare(exp_v, got_v), "Expected v %f, got %f.\n", exp_v, got_v);
1110 ok(compare(exp_dist, got_dist), "Expected distance %f, got %f.\n", exp_dist, got_dist);
1112 got_res = D3DXIntersectTri(&vertex[0], &vertex[1], &vertex[2], &position, &ray, NULL, NULL, NULL);
1113 ok(got_res == exp_res, "Expected result %d, got %d.\n", exp_res, got_res);
1115 vertex[2].x = 1.0f; vertex[2].y = 0.0f; vertex[2].z = 0.0f;
1116 vertex[1].x = 2.0f; vertex[1].y = 0.0f; vertex[1].z = 0.0f;
1117 vertex[0].x = 1.0f; vertex[0].y = 1.0f; vertex[0].z = 0.0f;
1119 got_u = got_v = got_dist = 0.0f;
1120 got_res = D3DXIntersectTri(&vertex[0], &vertex[1], &vertex[2], &position, &ray, &got_u, &got_v, &got_dist);
1121 ok(got_res == exp_res, "Expected result %d, got %d.\n", exp_res, got_res);
1122 ok(compare(exp_u, got_u), "Expected u %f, got %f.\n", exp_u, got_u);
1123 ok(compare(exp_v, got_v), "Expected v %f, got %f.\n", exp_v, got_v);
1124 ok(compare(exp_dist, got_dist), "Expected distance %f, got %f.\n", exp_dist, got_dist);
1126 vertex[2].x = 1.0f; vertex[2].y = 0.0f; vertex[2].z = 0.0f;
1127 vertex[1].x = 2.0f; vertex[1].y = 0.0f; vertex[1].z = -0.5f;
1128 vertex[0].x = 1.0f; vertex[0].y = 1.0f; vertex[0].z = -1.0f;
1129 exp_u = 0.375f;
1130 exp_v = 0.5625f;
1131 exp_dist = 7.9375f;
1132 got_u = got_v = got_dist = 0.0f;
1133 got_res = D3DXIntersectTri(&vertex[0], &vertex[1], &vertex[2], &position, &ray, &got_u, &got_v, &got_dist);
1134 ok(got_res == exp_res, "Expected result %d, got %d.\n", exp_res, got_res);
1135 ok(compare(exp_u, got_u), "Expected u %f, got %f.\n", exp_u, got_u);
1136 ok(compare(exp_v, got_v), "Expected v %f, got %f.\n", exp_v, got_v);
1137 ok(compare(exp_dist, got_dist), "Expected distance %f, got %f.\n", exp_dist, got_dist);
1140 /*Only positive ray is taken in account*/
1142 vertex[0].x = 1.0f; vertex[0].y = 0.0f; vertex[0].z = 0.0f;
1143 vertex[1].x = 2.0f; vertex[1].y = 0.0f; vertex[1].z = 0.0f;
1144 vertex[2].x = 1.0f; vertex[2].y = 1.0f; vertex[2].z = 0.0f;
1146 position.x = 17.5f; position.y = 24.25f; position.z = 32.0f;
1148 ray.x = 2.0f; ray.y = 3.0f; ray.z = 4.0f;
1150 exp_res = FALSE;
1152 got_res = D3DXIntersectTri(&vertex[0],&vertex[1],&vertex[2],&position,&ray,&got_u,&got_v,&got_dist);
1153 ok( got_res == exp_res, "Expected result = %d, got %d\n",exp_res,got_res);
1155 got_res = D3DXIntersectTri(&vertex[0], &vertex[1], &vertex[2], &position, &ray, NULL, NULL, NULL);
1156 ok(got_res == exp_res, "Expected result = %d, got %d\n", exp_res, got_res);
1158 /*Intersection between ray and triangle in a same plane is considered as empty*/
1160 vertex[0].x = 4.0f; vertex[0].y = 0.0f; vertex[0].z = 0.0f;
1161 vertex[1].x = 6.0f; vertex[1].y = 0.0f; vertex[1].z = 0.0f;
1162 vertex[2].x = 4.0f; vertex[2].y = 2.0f; vertex[2].z = 0.0f;
1164 position.x = 1.0f; position.y = 1.0f; position.z = 0.0f;
1166 ray.x = 1.0f; ray.y = 0.0f; ray.z = 0.0f;
1168 exp_res = FALSE;
1170 got_res = D3DXIntersectTri(&vertex[0],&vertex[1],&vertex[2],&position,&ray,&got_u,&got_v,&got_dist);
1171 ok( got_res == exp_res, "Expected result = %d, got %d\n",exp_res,got_res);
1173 got_res = D3DXIntersectTri(&vertex[0], &vertex[1], &vertex[2], &position, &ray, NULL, NULL, NULL);
1174 ok(got_res == exp_res, "Expected result = %d, got %d\n", exp_res, got_res);
1177 static void D3DXCreateMeshTest(void)
1179 HRESULT hr;
1180 IDirect3DDevice9 *device, *test_device;
1181 ID3DXMesh *d3dxmesh;
1182 int i, size;
1183 D3DVERTEXELEMENT9 test_decl[MAX_FVF_DECL_SIZE];
1184 DWORD options;
1185 struct mesh mesh;
1186 struct test_context *test_context;
1188 static const D3DVERTEXELEMENT9 decl1[] =
1190 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1191 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
1192 D3DDECL_END(),
1195 static const D3DVERTEXELEMENT9 decl2[] =
1197 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1198 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
1199 {0, 24, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_PSIZE, 0},
1200 {0, 28, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 1},
1201 {0, 32, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
1202 /* 8 bytes padding */
1203 {0, 44, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
1204 D3DDECL_END(),
1207 static const D3DVERTEXELEMENT9 decl3[] =
1209 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1210 {1, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
1211 D3DDECL_END(),
1214 hr = D3DXCreateMesh(0, 0, 0, NULL, NULL, NULL);
1215 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1217 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl1, NULL, &d3dxmesh);
1218 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1220 test_context = new_test_context();
1221 if (!test_context)
1223 skip("Couldn't create test context\n");
1224 return;
1226 device = test_context->device;
1228 hr = D3DXCreateMesh(0, 3, D3DXMESH_MANAGED, decl1, device, &d3dxmesh);
1229 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1231 hr = D3DXCreateMesh(1, 0, D3DXMESH_MANAGED, decl1, device, &d3dxmesh);
1232 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1234 hr = D3DXCreateMesh(1, 3, 0, decl1, device, &d3dxmesh);
1235 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
1237 if (hr == D3D_OK)
1239 d3dxmesh->lpVtbl->Release(d3dxmesh);
1242 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, 0, device, &d3dxmesh);
1243 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1245 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl1, device, NULL);
1246 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1248 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl1, device, &d3dxmesh);
1249 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
1251 if (hr == D3D_OK)
1253 /* device */
1254 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, NULL);
1255 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1257 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, &test_device);
1258 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
1259 ok(test_device == device, "Got result %p, expected %p\n", test_device, device);
1261 if (hr == D3D_OK)
1263 IDirect3DDevice9_Release(device);
1266 /* declaration */
1267 hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, NULL);
1268 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1270 hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, test_decl);
1271 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
1273 if (hr == D3D_OK)
1275 size = ARRAY_SIZE(decl1);
1276 for (i = 0; i < size - 1; i++)
1278 ok(test_decl[i].Stream == decl1[i].Stream, "Returned stream %d, expected %d\n", test_decl[i].Stream, decl1[i].Stream);
1279 ok(test_decl[i].Type == decl1[i].Type, "Returned type %d, expected %d\n", test_decl[i].Type, decl1[i].Type);
1280 ok(test_decl[i].Method == decl1[i].Method, "Returned method %d, expected %d\n", test_decl[i].Method, decl1[i].Method);
1281 ok(test_decl[i].Usage == decl1[i].Usage, "Returned usage %d, expected %d\n", test_decl[i].Usage, decl1[i].Usage);
1282 ok(test_decl[i].UsageIndex == decl1[i].UsageIndex, "Returned usage index %d, expected %d\n", test_decl[i].UsageIndex, decl1[i].UsageIndex);
1283 ok(test_decl[i].Offset == decl1[i].Offset, "Returned offset %d, expected %d\n", test_decl[i].Offset, decl1[i].Offset);
1285 ok(decl1[size-1].Stream == 0xFF, "Returned too long vertex declaration\n"); /* end element */
1288 /* options */
1289 options = d3dxmesh->lpVtbl->GetOptions(d3dxmesh);
1290 ok(options == D3DXMESH_MANAGED, "Got result %x, expected %x (D3DXMESH_MANAGED)\n", options, D3DXMESH_MANAGED);
1292 /* rest */
1293 if (!new_mesh(&mesh, 3, 1))
1295 skip("Couldn't create mesh\n");
1297 else
1299 memset(mesh.vertices, 0, mesh.number_of_vertices * sizeof(*mesh.vertices));
1300 memset(mesh.faces, 0, mesh.number_of_faces * sizeof(*mesh.faces));
1301 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
1303 compare_mesh("createmesh1", d3dxmesh, &mesh);
1305 free_mesh(&mesh);
1308 d3dxmesh->lpVtbl->Release(d3dxmesh);
1311 /* Test a declaration that can't be converted to an FVF. */
1312 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl2, device, &d3dxmesh);
1313 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
1315 if (hr == D3D_OK)
1317 /* device */
1318 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, NULL);
1319 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1321 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, &test_device);
1322 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
1323 ok(test_device == device, "Got result %p, expected %p\n", test_device, device);
1325 if (hr == D3D_OK)
1327 IDirect3DDevice9_Release(device);
1330 /* declaration */
1331 hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, test_decl);
1332 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
1334 if (hr == D3D_OK)
1336 size = ARRAY_SIZE(decl2);
1337 for (i = 0; i < size - 1; i++)
1339 ok(test_decl[i].Stream == decl2[i].Stream, "Returned stream %d, expected %d\n", test_decl[i].Stream, decl2[i].Stream);
1340 ok(test_decl[i].Type == decl2[i].Type, "Returned type %d, expected %d\n", test_decl[i].Type, decl2[i].Type);
1341 ok(test_decl[i].Method == decl2[i].Method, "Returned method %d, expected %d\n", test_decl[i].Method, decl2[i].Method);
1342 ok(test_decl[i].Usage == decl2[i].Usage, "Returned usage %d, expected %d\n", test_decl[i].Usage, decl2[i].Usage);
1343 ok(test_decl[i].UsageIndex == decl2[i].UsageIndex, "Returned usage index %d, expected %d\n", test_decl[i].UsageIndex, decl2[i].UsageIndex);
1344 ok(test_decl[i].Offset == decl2[i].Offset, "Returned offset %d, expected %d\n", test_decl[i].Offset, decl2[i].Offset);
1346 ok(decl2[size-1].Stream == 0xFF, "Returned too long vertex declaration\n"); /* end element */
1349 /* options */
1350 options = d3dxmesh->lpVtbl->GetOptions(d3dxmesh);
1351 ok(options == D3DXMESH_MANAGED, "Got result %x, expected %x (D3DXMESH_MANAGED)\n", options, D3DXMESH_MANAGED);
1353 /* rest */
1354 if (!new_mesh(&mesh, 3, 1))
1356 skip("Couldn't create mesh\n");
1358 else
1360 memset(mesh.vertices, 0, mesh.number_of_vertices * sizeof(*mesh.vertices));
1361 memset(mesh.faces, 0, mesh.number_of_faces * sizeof(*mesh.faces));
1362 mesh.fvf = 0;
1363 mesh.vertex_size = 60;
1365 compare_mesh("createmesh2", d3dxmesh, &mesh);
1367 free_mesh(&mesh);
1370 mesh.vertex_size = d3dxmesh->lpVtbl->GetNumBytesPerVertex(d3dxmesh);
1371 ok(mesh.vertex_size == 60, "Got vertex size %u, expected %u\n", mesh.vertex_size, 60);
1373 d3dxmesh->lpVtbl->Release(d3dxmesh);
1376 /* Test a declaration with multiple streams. */
1377 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl3, device, &d3dxmesh);
1378 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1380 free_test_context(test_context);
1383 static void D3DXCreateMeshFVFTest(void)
1385 HRESULT hr;
1386 IDirect3DDevice9 *device, *test_device;
1387 ID3DXMesh *d3dxmesh;
1388 int i, size;
1389 D3DVERTEXELEMENT9 test_decl[MAX_FVF_DECL_SIZE];
1390 DWORD options;
1391 struct mesh mesh;
1392 struct test_context *test_context;
1394 static const D3DVERTEXELEMENT9 decl[] =
1396 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1397 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
1398 D3DDECL_END(),
1401 hr = D3DXCreateMeshFVF(0, 0, 0, 0, NULL, 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, NULL, &d3dxmesh);
1405 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1407 test_context = new_test_context();
1408 if (!test_context)
1410 skip("Couldn't create test context\n");
1411 return;
1413 device = test_context->device;
1415 hr = D3DXCreateMeshFVF(0, 3, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, device, &d3dxmesh);
1416 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1418 hr = D3DXCreateMeshFVF(1, 0, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, device, &d3dxmesh);
1419 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1421 hr = D3DXCreateMeshFVF(1, 3, 0, D3DFVF_XYZ | D3DFVF_NORMAL, device, &d3dxmesh);
1422 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
1424 if (hr == D3D_OK)
1426 d3dxmesh->lpVtbl->Release(d3dxmesh);
1429 hr = D3DXCreateMeshFVF(1, 3, D3DXMESH_MANAGED, 0xdeadbeef, device, &d3dxmesh);
1430 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1432 hr = D3DXCreateMeshFVF(1, 3, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, device, NULL);
1433 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1435 hr = D3DXCreateMeshFVF(1, 3, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, device, &d3dxmesh);
1436 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
1438 if (hr == D3D_OK)
1440 /* device */
1441 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, NULL);
1442 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1444 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, &test_device);
1445 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
1446 ok(test_device == device, "Got result %p, expected %p\n", test_device, device);
1448 if (hr == D3D_OK)
1450 IDirect3DDevice9_Release(device);
1453 /* declaration */
1454 hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, NULL);
1455 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1457 hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, test_decl);
1458 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
1460 if (hr == D3D_OK)
1462 size = ARRAY_SIZE(decl);
1463 for (i = 0; i < size - 1; i++)
1465 ok(test_decl[i].Stream == decl[i].Stream, "Returned stream %d, expected %d\n", test_decl[i].Stream, decl[i].Stream);
1466 ok(test_decl[i].Type == decl[i].Type, "Returned type %d, expected %d\n", test_decl[i].Type, decl[i].Type);
1467 ok(test_decl[i].Method == decl[i].Method, "Returned method %d, expected %d\n", test_decl[i].Method, decl[i].Method);
1468 ok(test_decl[i].Usage == decl[i].Usage, "Returned usage %d, expected %d\n", test_decl[i].Usage, decl[i].Usage);
1469 ok(test_decl[i].UsageIndex == decl[i].UsageIndex, "Returned usage index %d, expected %d\n",
1470 test_decl[i].UsageIndex, decl[i].UsageIndex);
1471 ok(test_decl[i].Offset == decl[i].Offset, "Returned offset %d, expected %d\n", test_decl[i].Offset, decl[i].Offset);
1473 ok(decl[size-1].Stream == 0xFF, "Returned too long vertex declaration\n"); /* end element */
1476 /* options */
1477 options = d3dxmesh->lpVtbl->GetOptions(d3dxmesh);
1478 ok(options == D3DXMESH_MANAGED, "Got result %x, expected %x (D3DXMESH_MANAGED)\n", options, D3DXMESH_MANAGED);
1480 /* rest */
1481 if (!new_mesh(&mesh, 3, 1))
1483 skip("Couldn't create mesh\n");
1485 else
1487 memset(mesh.vertices, 0, mesh.number_of_vertices * sizeof(*mesh.vertices));
1488 memset(mesh.faces, 0, mesh.number_of_faces * sizeof(*mesh.faces));
1489 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
1491 compare_mesh("createmeshfvf", d3dxmesh, &mesh);
1493 free_mesh(&mesh);
1496 d3dxmesh->lpVtbl->Release(d3dxmesh);
1499 free_test_context(test_context);
1502 #define check_vertex_buffer(mesh, vertices, num_vertices, fvf) \
1503 check_vertex_buffer_(__LINE__, mesh, vertices, num_vertices, fvf)
1504 static void check_vertex_buffer_(int line, ID3DXMesh *mesh, const void *vertices, DWORD num_vertices, DWORD fvf)
1506 DWORD mesh_num_vertices = mesh->lpVtbl->GetNumVertices(mesh);
1507 DWORD mesh_fvf = mesh->lpVtbl->GetFVF(mesh);
1508 const void *mesh_vertices;
1509 HRESULT hr;
1511 ok_(__FILE__,line)(fvf == mesh_fvf, "expected FVF %x, got %x\n", fvf, mesh_fvf);
1512 ok_(__FILE__,line)(num_vertices == mesh_num_vertices,
1513 "Expected %u vertices, got %u\n", num_vertices, mesh_num_vertices);
1515 hr = mesh->lpVtbl->LockVertexBuffer(mesh, D3DLOCK_READONLY, (void**)&mesh_vertices);
1516 ok_(__FILE__,line)(hr == D3D_OK, "LockVertexBuffer returned %x, expected %x (D3D_OK)\n", hr, D3D_OK);
1517 if (FAILED(hr))
1518 return;
1520 if (mesh_fvf == fvf) {
1521 DWORD vertex_size = D3DXGetFVFVertexSize(fvf), i;
1523 for (i = 0; i < min(num_vertices, mesh_num_vertices); i++)
1525 const FLOAT *exp_float = vertices;
1526 const FLOAT *got_float = mesh_vertices;
1527 DWORD texcount;
1528 DWORD pos_dim = 0;
1529 int j;
1530 BOOL last_beta_dword = FALSE;
1531 char prefix[128];
1533 switch (fvf & D3DFVF_POSITION_MASK) {
1534 case D3DFVF_XYZ: pos_dim = 3; break;
1535 case D3DFVF_XYZRHW: pos_dim = 4; break;
1536 case D3DFVF_XYZB1:
1537 case D3DFVF_XYZB2:
1538 case D3DFVF_XYZB3:
1539 case D3DFVF_XYZB4:
1540 case D3DFVF_XYZB5:
1541 pos_dim = (fvf & D3DFVF_POSITION_MASK) - D3DFVF_XYZB1 + 1;
1542 if (fvf & (D3DFVF_LASTBETA_UBYTE4 | D3DFVF_LASTBETA_D3DCOLOR))
1544 pos_dim--;
1545 last_beta_dword = TRUE;
1547 break;
1548 case D3DFVF_XYZW: pos_dim = 4; break;
1550 sprintf(prefix, "vertex[%u] position, ", i);
1551 check_floats_(line, prefix, got_float, exp_float, pos_dim);
1552 exp_float += pos_dim;
1553 got_float += pos_dim;
1555 if (last_beta_dword) {
1556 ok_(__FILE__,line)(*(DWORD*)exp_float == *(DWORD*)got_float,
1557 "Vertex[%u]: Expected last beta %08x, got %08x\n", i, *(DWORD*)exp_float, *(DWORD*)got_float);
1558 exp_float++;
1559 got_float++;
1562 if (fvf & D3DFVF_NORMAL) {
1563 sprintf(prefix, "vertex[%u] normal, ", i);
1564 check_floats_(line, prefix, got_float, exp_float, 3);
1565 exp_float += 3;
1566 got_float += 3;
1568 if (fvf & D3DFVF_PSIZE) {
1569 ok_(__FILE__,line)(compare(*exp_float, *got_float),
1570 "Vertex[%u]: Expected psize %g, got %g\n", i, *exp_float, *got_float);
1571 exp_float++;
1572 got_float++;
1574 if (fvf & D3DFVF_DIFFUSE) {
1575 ok_(__FILE__,line)(*(DWORD*)exp_float == *(DWORD*)got_float,
1576 "Vertex[%u]: Expected diffuse %08x, got %08x\n", i, *(DWORD*)exp_float, *(DWORD*)got_float);
1577 exp_float++;
1578 got_float++;
1580 if (fvf & D3DFVF_SPECULAR) {
1581 ok_(__FILE__,line)(*(DWORD*)exp_float == *(DWORD*)got_float,
1582 "Vertex[%u]: Expected specular %08x, got %08x\n", i, *(DWORD*)exp_float, *(DWORD*)got_float);
1583 exp_float++;
1584 got_float++;
1587 texcount = (fvf & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
1588 for (j = 0; j < texcount; j++) {
1589 DWORD dim = (((fvf >> (16 + 2 * j)) + 1) & 0x03) + 1;
1590 sprintf(prefix, "vertex[%u] texture, ", i);
1591 check_floats_(line, prefix, got_float, exp_float, dim);
1592 exp_float += dim;
1593 got_float += dim;
1596 vertices = (BYTE*)vertices + vertex_size;
1597 mesh_vertices = (BYTE*)mesh_vertices + vertex_size;
1601 mesh->lpVtbl->UnlockVertexBuffer(mesh);
1604 #define check_index_buffer(mesh, indices, num_indices, index_size) \
1605 check_index_buffer_(__LINE__, mesh, indices, num_indices, index_size)
1606 static void check_index_buffer_(int line, ID3DXMesh *mesh, const void *indices, DWORD num_indices, DWORD index_size)
1608 DWORD mesh_index_size = (mesh->lpVtbl->GetOptions(mesh) & D3DXMESH_32BIT) ? 4 : 2;
1609 DWORD mesh_num_indices = mesh->lpVtbl->GetNumFaces(mesh) * 3;
1610 const void *mesh_indices;
1611 HRESULT hr;
1612 DWORD i;
1614 ok_(__FILE__,line)(index_size == mesh_index_size,
1615 "Expected index size %u, got %u\n", index_size, mesh_index_size);
1616 ok_(__FILE__,line)(num_indices == mesh_num_indices,
1617 "Expected %u indices, got %u\n", num_indices, mesh_num_indices);
1619 hr = mesh->lpVtbl->LockIndexBuffer(mesh, D3DLOCK_READONLY, (void**)&mesh_indices);
1620 ok_(__FILE__,line)(hr == D3D_OK, "LockIndexBuffer returned %x, expected %x (D3D_OK)\n", hr, D3D_OK);
1621 if (FAILED(hr))
1622 return;
1624 if (mesh_index_size == index_size) {
1625 for (i = 0; i < min(num_indices, mesh_num_indices); i++)
1627 if (index_size == 4)
1628 ok_(__FILE__,line)(*(DWORD*)indices == *(DWORD*)mesh_indices,
1629 "Index[%u]: expected %u, got %u\n", i, *(DWORD*)indices, *(DWORD*)mesh_indices);
1630 else
1631 ok_(__FILE__,line)(*(WORD*)indices == *(WORD*)mesh_indices,
1632 "Index[%u]: expected %u, got %u\n", i, *(WORD*)indices, *(WORD*)mesh_indices);
1633 indices = (BYTE*)indices + index_size;
1634 mesh_indices = (BYTE*)mesh_indices + index_size;
1637 mesh->lpVtbl->UnlockIndexBuffer(mesh);
1640 #define check_matrix(got, expected) check_matrix_(__LINE__, got, expected)
1641 static void check_matrix_(int line, const D3DXMATRIX *got, const D3DXMATRIX *expected)
1643 int i, j;
1644 for (i = 0; i < 4; i++) {
1645 for (j = 0; j < 4; j++) {
1646 ok_(__FILE__,line)(compare(U(*expected).m[i][j], U(*got).m[i][j]),
1647 "matrix[%u][%u]: expected %g, got %g\n",
1648 i, j, U(*expected).m[i][j], U(*got).m[i][j]);
1653 static void check_colorvalue_(int line, const char *prefix, const D3DCOLORVALUE got, const D3DCOLORVALUE expected)
1655 ok_(__FILE__,line)(expected.r == got.r && expected.g == got.g && expected.b == got.b && expected.a == got.a,
1656 "%sExpected (%g, %g, %g, %g), got (%g, %g, %g, %g)\n", prefix,
1657 expected.r, expected.g, expected.b, expected.a, got.r, got.g, got.b, got.a);
1660 #define check_materials(got, got_count, expected, expected_count) \
1661 check_materials_(__LINE__, got, got_count, expected, expected_count)
1662 static void check_materials_(int line, const D3DXMATERIAL *got, DWORD got_count, const D3DXMATERIAL *expected, DWORD expected_count)
1664 int i;
1665 ok_(__FILE__,line)(expected_count == got_count, "Expected %u materials, got %u\n", expected_count, got_count);
1666 if (!expected) {
1667 ok_(__FILE__,line)(got == NULL, "Expected NULL material ptr, got %p\n", got);
1668 return;
1670 for (i = 0; i < min(expected_count, got_count); i++)
1672 if (!expected[i].pTextureFilename)
1673 ok_(__FILE__,line)(got[i].pTextureFilename == NULL,
1674 "Expected NULL pTextureFilename, got %p\n", got[i].pTextureFilename);
1675 else
1676 ok_(__FILE__,line)(!strcmp(expected[i].pTextureFilename, got[i].pTextureFilename),
1677 "Expected '%s' for pTextureFilename, got '%s'\n", expected[i].pTextureFilename, got[i].pTextureFilename);
1678 check_colorvalue_(line, "Diffuse: ", got[i].MatD3D.Diffuse, expected[i].MatD3D.Diffuse);
1679 check_colorvalue_(line, "Ambient: ", got[i].MatD3D.Ambient, expected[i].MatD3D.Ambient);
1680 check_colorvalue_(line, "Specular: ", got[i].MatD3D.Specular, expected[i].MatD3D.Specular);
1681 check_colorvalue_(line, "Emissive: ", got[i].MatD3D.Emissive, expected[i].MatD3D.Emissive);
1682 ok_(__FILE__,line)(expected[i].MatD3D.Power == got[i].MatD3D.Power,
1683 "Power: Expected %g, got %g\n", expected[i].MatD3D.Power, got[i].MatD3D.Power);
1687 #define check_generated_adjacency(mesh, got, epsilon) check_generated_adjacency_(__LINE__, mesh, got, epsilon)
1688 static void check_generated_adjacency_(int line, ID3DXMesh *mesh, const DWORD *got, FLOAT epsilon)
1690 DWORD *expected;
1691 DWORD num_faces = mesh->lpVtbl->GetNumFaces(mesh);
1692 HRESULT hr;
1694 expected = HeapAlloc(GetProcessHeap(), 0, num_faces * sizeof(DWORD) * 3);
1695 if (!expected) {
1696 skip_(__FILE__, line)("Out of memory\n");
1697 return;
1699 hr = mesh->lpVtbl->GenerateAdjacency(mesh, epsilon, expected);
1700 ok_(__FILE__, line)(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
1701 if (SUCCEEDED(hr))
1703 int i;
1704 for (i = 0; i < num_faces; i++)
1706 ok_(__FILE__, line)(expected[i * 3] == got[i * 3] &&
1707 expected[i * 3 + 1] == got[i * 3 + 1] &&
1708 expected[i * 3 + 2] == got[i * 3 + 2],
1709 "Face %u adjacencies: Expected (%u, %u, %u), got (%u, %u, %u)\n", i,
1710 expected[i * 3], expected[i * 3 + 1], expected[i * 3 + 2],
1711 got[i * 3], got[i * 3 + 1], got[i * 3 + 2]);
1714 HeapFree(GetProcessHeap(), 0, expected);
1717 #define check_generated_effects(materials, num_materials, effects) \
1718 check_generated_effects_(__LINE__, materials, num_materials, effects)
1719 static void check_generated_effects_(int line, const D3DXMATERIAL *materials, DWORD num_materials, const D3DXEFFECTINSTANCE *effects)
1721 int i;
1722 static const struct {
1723 const char *name;
1724 DWORD name_size;
1725 DWORD num_bytes;
1726 DWORD value_offset;
1727 } params[] = {
1728 #define EFFECT_TABLE_ENTRY(str, field) \
1729 {str, sizeof(str), sizeof(materials->MatD3D.field), offsetof(D3DXMATERIAL, MatD3D.field)}
1730 EFFECT_TABLE_ENTRY("Diffuse", Diffuse),
1731 EFFECT_TABLE_ENTRY("Power", Power),
1732 EFFECT_TABLE_ENTRY("Specular", Specular),
1733 EFFECT_TABLE_ENTRY("Emissive", Emissive),
1734 EFFECT_TABLE_ENTRY("Ambient", Ambient),
1735 #undef EFFECT_TABLE_ENTRY
1738 if (!num_materials) {
1739 ok_(__FILE__, line)(effects == NULL, "Expected NULL effects, got %p\n", effects);
1740 return;
1742 for (i = 0; i < num_materials; i++)
1744 int j;
1745 DWORD expected_num_defaults = ARRAY_SIZE(params) + (materials[i].pTextureFilename ? 1 : 0);
1747 ok_(__FILE__,line)(expected_num_defaults == effects[i].NumDefaults,
1748 "effect[%u] NumDefaults: Expected %u, got %u\n", i,
1749 expected_num_defaults, effects[i].NumDefaults);
1750 for (j = 0; j < min(ARRAY_SIZE(params), effects[i].NumDefaults); j++)
1752 int k;
1753 D3DXEFFECTDEFAULT *got_param = &effects[i].pDefaults[j];
1754 ok_(__FILE__,line)(!strcmp(params[j].name, got_param->pParamName),
1755 "effect[%u].pDefaults[%u].pParamName: Expected '%s', got '%s'\n", i, j,
1756 params[j].name, got_param->pParamName);
1757 ok_(__FILE__,line)(D3DXEDT_FLOATS == got_param->Type,
1758 "effect[%u].pDefaults[%u].Type: Expected %u, got %u\n", i, j,
1759 D3DXEDT_FLOATS, got_param->Type);
1760 ok_(__FILE__,line)(params[j].num_bytes == got_param->NumBytes,
1761 "effect[%u].pDefaults[%u].NumBytes: Expected %u, got %u\n", i, j,
1762 params[j].num_bytes, got_param->NumBytes);
1763 for (k = 0; k < min(params[j].num_bytes, got_param->NumBytes) / 4; k++)
1765 FLOAT expected = ((FLOAT*)((BYTE*)&materials[i] + params[j].value_offset))[k];
1766 FLOAT got = ((FLOAT*)got_param->pValue)[k];
1767 ok_(__FILE__,line)(compare(expected, got),
1768 "effect[%u].pDefaults[%u] float value %u: Expected %g, got %g\n", i, j, k, expected, got);
1771 if (effects[i].NumDefaults > ARRAY_SIZE(params)) {
1772 D3DXEFFECTDEFAULT *got_param = &effects[i].pDefaults[j];
1773 static const char *expected_name = "Texture0@Name";
1775 ok_(__FILE__,line)(!strcmp(expected_name, got_param->pParamName),
1776 "effect[%u].pDefaults[%u].pParamName: Expected '%s', got '%s'\n", i, j,
1777 expected_name, got_param->pParamName);
1778 ok_(__FILE__,line)(D3DXEDT_STRING == got_param->Type,
1779 "effect[%u].pDefaults[%u].Type: Expected %u, got %u\n", i, j,
1780 D3DXEDT_STRING, got_param->Type);
1781 if (materials[i].pTextureFilename) {
1782 ok_(__FILE__,line)(strlen(materials[i].pTextureFilename) + 1 == got_param->NumBytes,
1783 "effect[%u] texture filename length: Expected %u, got %u\n", i,
1784 (DWORD)strlen(materials[i].pTextureFilename) + 1, got_param->NumBytes);
1785 ok_(__FILE__,line)(!strcmp(materials[i].pTextureFilename, got_param->pValue),
1786 "effect[%u] texture filename: Expected '%s', got '%s'\n", i,
1787 materials[i].pTextureFilename, (char*)got_param->pValue);
1793 static char *strdupA(const char *p)
1795 char *ret;
1796 if (!p) return NULL;
1797 ret = HeapAlloc(GetProcessHeap(), 0, strlen(p) + 1);
1798 if (ret) strcpy(ret, p);
1799 return ret;
1802 static HRESULT CALLBACK ID3DXAllocateHierarchyImpl_DestroyFrame(ID3DXAllocateHierarchy *iface, LPD3DXFRAME frame)
1804 TRACECALLBACK("ID3DXAllocateHierarchyImpl_DestroyFrame(%p, %p)\n", iface, frame);
1805 if (frame) {
1806 HeapFree(GetProcessHeap(), 0, frame->Name);
1807 HeapFree(GetProcessHeap(), 0, frame);
1809 return D3D_OK;
1812 static HRESULT CALLBACK ID3DXAllocateHierarchyImpl_CreateFrame(ID3DXAllocateHierarchy *iface,
1813 const char *name, D3DXFRAME **new_frame)
1815 D3DXFRAME *frame;
1817 TRACECALLBACK("ID3DXAllocateHierarchyImpl_CreateFrame(%p, '%s', %p)\n", iface, name, new_frame);
1818 frame = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*frame));
1819 if (!frame)
1820 return E_OUTOFMEMORY;
1821 if (name) {
1822 frame->Name = strdupA(name);
1823 if (!frame->Name) {
1824 HeapFree(GetProcessHeap(), 0, frame);
1825 return E_OUTOFMEMORY;
1828 *new_frame = frame;
1829 return D3D_OK;
1832 static HRESULT destroy_mesh_container(LPD3DXMESHCONTAINER mesh_container)
1834 int i;
1836 if (!mesh_container)
1837 return D3D_OK;
1838 HeapFree(GetProcessHeap(), 0, mesh_container->Name);
1839 if (U(mesh_container->MeshData).pMesh)
1840 IUnknown_Release(U(mesh_container->MeshData).pMesh);
1841 if (mesh_container->pMaterials) {
1842 for (i = 0; i < mesh_container->NumMaterials; i++)
1843 HeapFree(GetProcessHeap(), 0, mesh_container->pMaterials[i].pTextureFilename);
1844 HeapFree(GetProcessHeap(), 0, mesh_container->pMaterials);
1846 if (mesh_container->pEffects) {
1847 for (i = 0; i < mesh_container->NumMaterials; i++) {
1848 HeapFree(GetProcessHeap(), 0, mesh_container->pEffects[i].pEffectFilename);
1849 if (mesh_container->pEffects[i].pDefaults) {
1850 int j;
1851 for (j = 0; j < mesh_container->pEffects[i].NumDefaults; j++) {
1852 HeapFree(GetProcessHeap(), 0, mesh_container->pEffects[i].pDefaults[j].pParamName);
1853 HeapFree(GetProcessHeap(), 0, mesh_container->pEffects[i].pDefaults[j].pValue);
1855 HeapFree(GetProcessHeap(), 0, mesh_container->pEffects[i].pDefaults);
1858 HeapFree(GetProcessHeap(), 0, mesh_container->pEffects);
1860 HeapFree(GetProcessHeap(), 0, mesh_container->pAdjacency);
1861 if (mesh_container->pSkinInfo)
1862 IUnknown_Release(mesh_container->pSkinInfo);
1863 HeapFree(GetProcessHeap(), 0, mesh_container);
1864 return D3D_OK;
1867 static HRESULT CALLBACK ID3DXAllocateHierarchyImpl_DestroyMeshContainer(ID3DXAllocateHierarchy *iface, LPD3DXMESHCONTAINER mesh_container)
1869 TRACECALLBACK("ID3DXAllocateHierarchyImpl_DestroyMeshContainer(%p, %p)\n", iface, mesh_container);
1870 return destroy_mesh_container(mesh_container);
1873 static HRESULT CALLBACK ID3DXAllocateHierarchyImpl_CreateMeshContainer(ID3DXAllocateHierarchy *iface,
1874 const char *name, const D3DXMESHDATA *mesh_data, const D3DXMATERIAL *materials,
1875 const D3DXEFFECTINSTANCE *effects, DWORD num_materials, const DWORD *adjacency,
1876 ID3DXSkinInfo *skin_info, D3DXMESHCONTAINER **new_mesh_container)
1878 LPD3DXMESHCONTAINER mesh_container = NULL;
1879 int i;
1881 TRACECALLBACK("ID3DXAllocateHierarchyImpl_CreateMeshContainer(%p, '%s', %u, %p, %p, %p, %d, %p, %p, %p)\n",
1882 iface, name, mesh_data->Type, U(*mesh_data).pMesh, materials, effects,
1883 num_materials, adjacency, skin_info, *new_mesh_container);
1885 mesh_container = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*mesh_container));
1886 if (!mesh_container)
1887 return E_OUTOFMEMORY;
1889 if (name) {
1890 mesh_container->Name = strdupA(name);
1891 if (!mesh_container->Name)
1892 goto error;
1895 mesh_container->NumMaterials = num_materials;
1896 if (num_materials) {
1897 mesh_container->pMaterials = HeapAlloc(GetProcessHeap(), 0, num_materials * sizeof(*materials));
1898 if (!mesh_container->pMaterials)
1899 goto error;
1901 memcpy(mesh_container->pMaterials, materials, num_materials * sizeof(*materials));
1902 for (i = 0; i < num_materials; i++)
1903 mesh_container->pMaterials[i].pTextureFilename = NULL;
1904 for (i = 0; i < num_materials; i++) {
1905 if (materials[i].pTextureFilename) {
1906 mesh_container->pMaterials[i].pTextureFilename = strdupA(materials[i].pTextureFilename);
1907 if (!mesh_container->pMaterials[i].pTextureFilename)
1908 goto error;
1912 mesh_container->pEffects = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, num_materials * sizeof(*effects));
1913 if (!mesh_container->pEffects)
1914 goto error;
1915 for (i = 0; i < num_materials; i++) {
1916 int j;
1917 const D3DXEFFECTINSTANCE *effect_src = &effects[i];
1918 D3DXEFFECTINSTANCE *effect_dest = &mesh_container->pEffects[i];
1920 if (effect_src->pEffectFilename) {
1921 effect_dest->pEffectFilename = strdupA(effect_src->pEffectFilename);
1922 if (!effect_dest->pEffectFilename)
1923 goto error;
1925 effect_dest->pDefaults = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1926 effect_src->NumDefaults * sizeof(*effect_src->pDefaults));
1927 if (!effect_dest->pDefaults)
1928 goto error;
1929 effect_dest->NumDefaults = effect_src->NumDefaults;
1930 for (j = 0; j < effect_src->NumDefaults; j++) {
1931 const D3DXEFFECTDEFAULT *default_src = &effect_src->pDefaults[j];
1932 D3DXEFFECTDEFAULT *default_dest = &effect_dest->pDefaults[j];
1934 if (default_src->pParamName) {
1935 default_dest->pParamName = strdupA(default_src->pParamName);
1936 if (!default_dest->pParamName)
1937 goto error;
1939 default_dest->NumBytes = default_src->NumBytes;
1940 default_dest->Type = default_src->Type;
1941 default_dest->pValue = HeapAlloc(GetProcessHeap(), 0, default_src->NumBytes);
1942 memcpy(default_dest->pValue, default_src->pValue, default_src->NumBytes);
1947 ok(adjacency != NULL, "Expected non-NULL adjacency, got NULL\n");
1948 if (adjacency) {
1949 if (mesh_data->Type == D3DXMESHTYPE_MESH || mesh_data->Type == D3DXMESHTYPE_PMESH) {
1950 ID3DXBaseMesh *basemesh = (ID3DXBaseMesh*)U(*mesh_data).pMesh;
1951 DWORD num_faces = basemesh->lpVtbl->GetNumFaces(basemesh);
1952 size_t size = num_faces * sizeof(DWORD) * 3;
1953 mesh_container->pAdjacency = HeapAlloc(GetProcessHeap(), 0, size);
1954 if (!mesh_container->pAdjacency)
1955 goto error;
1956 memcpy(mesh_container->pAdjacency, adjacency, size);
1957 } else {
1958 ok(mesh_data->Type == D3DXMESHTYPE_PATCHMESH, "Unknown mesh type %u\n", mesh_data->Type);
1959 if (mesh_data->Type == D3DXMESHTYPE_PATCHMESH)
1960 trace("FIXME: copying adjacency data for patch mesh not implemented\n");
1964 memcpy(&mesh_container->MeshData, mesh_data, sizeof(*mesh_data));
1965 if (U(*mesh_data).pMesh)
1966 IUnknown_AddRef(U(*mesh_data).pMesh);
1967 if (skin_info) {
1968 mesh_container->pSkinInfo = skin_info;
1969 skin_info->lpVtbl->AddRef(skin_info);
1971 *new_mesh_container = mesh_container;
1973 return S_OK;
1974 error:
1975 destroy_mesh_container(mesh_container);
1976 return E_OUTOFMEMORY;
1979 static ID3DXAllocateHierarchyVtbl ID3DXAllocateHierarchyImpl_Vtbl = {
1980 ID3DXAllocateHierarchyImpl_CreateFrame,
1981 ID3DXAllocateHierarchyImpl_CreateMeshContainer,
1982 ID3DXAllocateHierarchyImpl_DestroyFrame,
1983 ID3DXAllocateHierarchyImpl_DestroyMeshContainer,
1985 static ID3DXAllocateHierarchy alloc_hier = { &ID3DXAllocateHierarchyImpl_Vtbl };
1987 #define test_LoadMeshFromX(device, xfile_str, vertex_array, fvf, index_array, materials_array, check_adjacency) \
1988 test_LoadMeshFromX_(__LINE__, device, xfile_str, sizeof(xfile_str) - 1, vertex_array, ARRAY_SIZE(vertex_array), fvf, \
1989 index_array, ARRAY_SIZE(index_array), sizeof(*index_array), materials_array, ARRAY_SIZE(materials_array), \
1990 check_adjacency);
1991 static void test_LoadMeshFromX_(int line, IDirect3DDevice9 *device, const char *xfile_str, size_t xfile_strlen,
1992 const void *vertices, DWORD num_vertices, DWORD fvf, const void *indices, DWORD num_indices, size_t index_size,
1993 const D3DXMATERIAL *expected_materials, DWORD expected_num_materials, BOOL check_adjacency)
1995 HRESULT hr;
1996 ID3DXBuffer *materials = NULL;
1997 ID3DXBuffer *effects = NULL;
1998 ID3DXBuffer *adjacency = NULL;
1999 ID3DXMesh *mesh = NULL;
2000 DWORD num_materials = 0;
2002 /* Adjacency is not checked when the X file contains multiple meshes,
2003 * since calling GenerateAdjacency on the merged mesh is not equivalent
2004 * to calling GenerateAdjacency on the individual meshes and then merging
2005 * the adjacency data. */
2006 hr = D3DXLoadMeshFromXInMemory(xfile_str, xfile_strlen, D3DXMESH_MANAGED, device,
2007 check_adjacency ? &adjacency : NULL, &materials, &effects, &num_materials, &mesh);
2008 ok_(__FILE__,line)(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2009 if (SUCCEEDED(hr)) {
2010 D3DXMATERIAL *materials_ptr = materials ? ID3DXBuffer_GetBufferPointer(materials) : NULL;
2011 D3DXEFFECTINSTANCE *effects_ptr = effects ? ID3DXBuffer_GetBufferPointer(effects) : NULL;
2012 DWORD *adjacency_ptr = check_adjacency ? ID3DXBuffer_GetBufferPointer(adjacency) : NULL;
2014 check_vertex_buffer_(line, mesh, vertices, num_vertices, fvf);
2015 check_index_buffer_(line, mesh, indices, num_indices, index_size);
2016 check_materials_(line, materials_ptr, num_materials, expected_materials, expected_num_materials);
2017 check_generated_effects_(line, materials_ptr, num_materials, effects_ptr);
2018 if (check_adjacency)
2019 check_generated_adjacency_(line, mesh, adjacency_ptr, 0.0f);
2021 if (materials) ID3DXBuffer_Release(materials);
2022 if (effects) ID3DXBuffer_Release(effects);
2023 if (adjacency) ID3DXBuffer_Release(adjacency);
2024 IUnknown_Release(mesh);
2028 static void D3DXLoadMeshTest(void)
2030 static const char empty_xfile[] = "xof 0303txt 0032";
2031 /*________________________*/
2032 static const char simple_xfile[] =
2033 "xof 0303txt 0032"
2034 "Mesh {"
2035 "3;"
2036 "0.0; 0.0; 0.0;,"
2037 "0.0; 1.0; 0.0;,"
2038 "1.0; 1.0; 0.0;;"
2039 "1;"
2040 "3; 0, 1, 2;;"
2041 "}";
2042 static const WORD simple_index_buffer[] = {0, 1, 2};
2043 static const D3DXVECTOR3 simple_vertex_buffer[] = {
2044 {0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {1.0, 1.0, 0.0}
2046 const DWORD simple_fvf = D3DFVF_XYZ;
2047 static const char framed_xfile[] =
2048 "xof 0303txt 0032"
2049 "Frame {"
2050 "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;; }"
2051 "FrameTransformMatrix {" /* translation (0.0, 0.0, 2.0) */
2052 "1.0, 0.0, 0.0, 0.0,"
2053 "0.0, 1.0, 0.0, 0.0,"
2054 "0.0, 0.0, 1.0, 0.0,"
2055 "0.0, 0.0, 2.0, 1.0;;"
2057 "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;; }"
2058 "FrameTransformMatrix {" /* translation (0.0, 0.0, 3.0) */
2059 "1.0, 0.0, 0.0, 0.0,"
2060 "0.0, 1.0, 0.0, 0.0,"
2061 "0.0, 0.0, 1.0, 0.0,"
2062 "0.0, 0.0, 3.0, 1.0;;"
2064 "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;; }"
2065 "}";
2066 static const WORD framed_index_buffer[] = { 0, 1, 2 };
2067 static const D3DXVECTOR3 framed_vertex_buffers[3][3] = {
2068 {{0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {1.0, 1.0, 0.0}},
2069 {{0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {2.0, 1.0, 0.0}},
2070 {{0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {3.0, 1.0, 0.0}},
2072 static const WORD merged_index_buffer[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
2073 /* frame transforms accumulates for D3DXLoadMeshFromX */
2074 static const D3DXVECTOR3 merged_vertex_buffer[] = {
2075 {0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {1.0, 1.0, 0.0},
2076 {0.0, 0.0, 2.0}, {0.0, 1.0, 2.0}, {2.0, 1.0, 2.0},
2077 {0.0, 0.0, 5.0}, {0.0, 1.0, 5.0}, {3.0, 1.0, 5.0},
2079 const DWORD framed_fvf = D3DFVF_XYZ;
2080 /*________________________*/
2081 static const char box_xfile[] =
2082 "xof 0303txt 0032"
2083 "Mesh {"
2084 "8;" /* DWORD nVertices; */
2085 /* array Vector vertices[nVertices]; */
2086 "0.0; 0.0; 0.0;,"
2087 "0.0; 0.0; 1.0;,"
2088 "0.0; 1.0; 0.0;,"
2089 "0.0; 1.0; 1.0;,"
2090 "1.0; 0.0; 0.0;,"
2091 "1.0; 0.0; 1.0;,"
2092 "1.0; 1.0; 0.0;,"
2093 "1.0; 1.0; 1.0;;"
2094 "6;" /* DWORD nFaces; */
2095 /* array MeshFace faces[nFaces]; */
2096 "4; 0, 1, 3, 2;," /* (left side) */
2097 "4; 2, 3, 7, 6;," /* (top side) */
2098 "4; 6, 7, 5, 4;," /* (right side) */
2099 "4; 1, 0, 4, 5;," /* (bottom side) */
2100 "4; 1, 5, 7, 3;," /* (back side) */
2101 "4; 0, 2, 6, 4;;" /* (front side) */
2102 "MeshNormals {"
2103 "6;" /* DWORD nNormals; */
2104 /* array Vector normals[nNormals]; */
2105 "-1.0; 0.0; 0.0;,"
2106 "0.0; 1.0; 0.0;,"
2107 "1.0; 0.0; 0.0;,"
2108 "0.0; -1.0; 0.0;,"
2109 "0.0; 0.0; 1.0;,"
2110 "0.0; 0.0; -1.0;;"
2111 "6;" /* DWORD nFaceNormals; */
2112 /* array MeshFace faceNormals[nFaceNormals]; */
2113 "4; 0, 0, 0, 0;,"
2114 "4; 1, 1, 1, 1;,"
2115 "4; 2, 2, 2, 2;,"
2116 "4; 3, 3, 3, 3;,"
2117 "4; 4, 4, 4, 4;,"
2118 "4; 5, 5, 5, 5;;"
2120 "MeshMaterialList materials {"
2121 "2;" /* DWORD nMaterials; */
2122 "6;" /* DWORD nFaceIndexes; */
2123 /* array DWORD faceIndexes[nFaceIndexes]; */
2124 "0, 0, 0, 1, 1, 1;;"
2125 "Material {"
2126 /* ColorRGBA faceColor; */
2127 "0.0; 0.0; 1.0; 1.0;;"
2128 /* FLOAT power; */
2129 "0.5;"
2130 /* ColorRGB specularColor; */
2131 "1.0; 1.0; 1.0;;"
2132 /* ColorRGB emissiveColor; */
2133 "0.0; 0.0; 0.0;;"
2135 "Material {"
2136 /* ColorRGBA faceColor; */
2137 "1.0; 1.0; 1.0; 1.0;;"
2138 /* FLOAT power; */
2139 "1.0;"
2140 /* ColorRGB specularColor; */
2141 "1.0; 1.0; 1.0;;"
2142 /* ColorRGB emissiveColor; */
2143 "0.0; 0.0; 0.0;;"
2144 "TextureFilename { \"texture.jpg\"; }"
2147 "MeshVertexColors {"
2148 "8;" /* DWORD nVertexColors; */
2149 /* array IndexedColor vertexColors[nVertexColors]; */
2150 "0; 0.0; 0.0; 0.0; 0.0;;"
2151 "1; 0.0; 0.0; 1.0; 0.1;;"
2152 "2; 0.0; 1.0; 0.0; 0.2;;"
2153 "3; 0.0; 1.0; 1.0; 0.3;;"
2154 "4; 1.0; 0.0; 0.0; 0.4;;"
2155 "5; 1.0; 0.0; 1.0; 0.5;;"
2156 "6; 1.0; 1.0; 0.0; 0.6;;"
2157 "7; 1.0; 1.0; 1.0; 0.7;;"
2159 "MeshTextureCoords {"
2160 "8;" /* DWORD nTextureCoords; */
2161 /* array Coords2d textureCoords[nTextureCoords]; */
2162 "0.0; 1.0;,"
2163 "1.0; 1.0;,"
2164 "0.0; 0.0;,"
2165 "1.0; 0.0;,"
2166 "1.0; 1.0;,"
2167 "0.0; 1.0;,"
2168 "1.0; 0.0;,"
2169 "0.0; 0.0;;"
2171 "}";
2172 static const WORD box_index_buffer[] = {
2173 0, 1, 3,
2174 0, 3, 2,
2175 8, 9, 7,
2176 8, 7, 6,
2177 10, 11, 5,
2178 10, 5, 4,
2179 12, 13, 14,
2180 12, 14, 15,
2181 16, 17, 18,
2182 16, 18, 19,
2183 20, 21, 22,
2184 20, 22, 23,
2186 static const struct {
2187 D3DXVECTOR3 position;
2188 D3DXVECTOR3 normal;
2189 D3DCOLOR diffuse;
2190 D3DXVECTOR2 tex_coords;
2191 } box_vertex_buffer[] = {
2192 {{0.0, 0.0, 0.0}, {-1.0, 0.0, 0.0}, 0x00000000, {0.0, 1.0}},
2193 {{0.0, 0.0, 1.0}, {-1.0, 0.0, 0.0}, 0x1a0000ff, {1.0, 1.0}},
2194 {{0.0, 1.0, 0.0}, {-1.0, 0.0, 0.0}, 0x3300ff00, {0.0, 0.0}},
2195 {{0.0, 1.0, 1.0}, {-1.0, 0.0, 0.0}, 0x4d00ffff, {1.0, 0.0}},
2196 {{1.0, 0.0, 0.0}, {1.0, 0.0, 0.0}, 0x66ff0000, {1.0, 1.0}},
2197 {{1.0, 0.0, 1.0}, {1.0, 0.0, 0.0}, 0x80ff00ff, {0.0, 1.0}},
2198 {{1.0, 1.0, 0.0}, {0.0, 1.0, 0.0}, 0x99ffff00, {1.0, 0.0}},
2199 {{1.0, 1.0, 1.0}, {0.0, 1.0, 0.0}, 0xb3ffffff, {0.0, 0.0}},
2200 {{0.0, 1.0, 0.0}, {0.0, 1.0, 0.0}, 0x3300ff00, {0.0, 0.0}},
2201 {{0.0, 1.0, 1.0}, {0.0, 1.0, 0.0}, 0x4d00ffff, {1.0, 0.0}},
2202 {{1.0, 1.0, 0.0}, {1.0, 0.0, 0.0}, 0x99ffff00, {1.0, 0.0}},
2203 {{1.0, 1.0, 1.0}, {1.0, 0.0, 0.0}, 0xb3ffffff, {0.0, 0.0}},
2204 {{0.0, 0.0, 1.0}, {0.0, -1.0, 0.0}, 0x1a0000ff, {1.0, 1.0}},
2205 {{0.0, 0.0, 0.0}, {0.0, -1.0, 0.0}, 0x00000000, {0.0, 1.0}},
2206 {{1.0, 0.0, 0.0}, {0.0, -1.0, 0.0}, 0x66ff0000, {1.0, 1.0}},
2207 {{1.0, 0.0, 1.0}, {0.0, -1.0, 0.0}, 0x80ff00ff, {0.0, 1.0}},
2208 {{0.0, 0.0, 1.0}, {0.0, 0.0, 1.0}, 0x1a0000ff, {1.0, 1.0}},
2209 {{1.0, 0.0, 1.0}, {0.0, 0.0, 1.0}, 0x80ff00ff, {0.0, 1.0}},
2210 {{1.0, 1.0, 1.0}, {0.0, 0.0, 1.0}, 0xb3ffffff, {0.0, 0.0}},
2211 {{0.0, 1.0, 1.0}, {0.0, 0.0, 1.0}, 0x4d00ffff, {1.0, 0.0}},
2212 {{0.0, 0.0, 0.0}, {0.0, 0.0, -1.0}, 0x00000000, {0.0, 1.0}},
2213 {{0.0, 1.0, 0.0}, {0.0, 0.0, -1.0}, 0x3300ff00, {0.0, 0.0}},
2214 {{1.0, 1.0, 0.0}, {0.0, 0.0, -1.0}, 0x99ffff00, {1.0, 0.0}},
2215 {{1.0, 0.0, 0.0}, {0.0, 0.0, -1.0}, 0x66ff0000, {1.0, 1.0}},
2217 static const D3DXMATERIAL box_materials[] = {
2220 {0.0, 0.0, 1.0, 1.0}, /* Diffuse */
2221 {0.0, 0.0, 0.0, 1.0}, /* Ambient */
2222 {1.0, 1.0, 1.0, 1.0}, /* Specular */
2223 {0.0, 0.0, 0.0, 1.0}, /* Emissive */
2224 0.5, /* Power */
2226 NULL, /* pTextureFilename */
2230 {1.0, 1.0, 1.0, 1.0}, /* Diffuse */
2231 {0.0, 0.0, 0.0, 1.0}, /* Ambient */
2232 {1.0, 1.0, 1.0, 1.0}, /* Specular */
2233 {0.0, 0.0, 0.0, 1.0}, /* Emissive */
2234 1.0, /* Power */
2236 (char *)"texture.jpg", /* pTextureFilename */
2239 static const char box_anim_xfile[] =
2240 "xof 0303txt 0032"
2241 "Mesh CubeMesh {"
2242 "8;" /* DWORD nVertices; */
2243 /* array Vector vertices[nVertices]; */
2244 "0.0; 0.0; 0.0;,"
2245 "0.0; 0.0; 1.0;,"
2246 "0.0; 1.0; 0.0;,"
2247 "0.0; 1.0; 1.0;,"
2248 "1.0; 0.0; 0.0;,"
2249 "1.0; 0.0; 1.0;,"
2250 "1.0; 1.0; 0.0;,"
2251 "1.0; 1.0; 1.0;;"
2252 "6;" /* DWORD nFaces; */
2253 /* array MeshFace faces[nFaces]; */
2254 "4; 0, 1, 3, 2;," /* left side */
2255 "4; 2, 3, 7, 6;," /* top side */
2256 "4; 6, 7, 5, 4;," /* right side */
2257 "4; 1, 0, 4, 5;," /* bottom side */
2258 "4; 1, 5, 7, 3;," /* back side */
2259 "4; 0, 2, 6, 4;;" /* front side */
2260 "MeshNormals {"
2261 "6;" /* DWORD nNormals; */
2262 /* array Vector normals[nNormals]; */
2263 "-1.0; 0.0; 0.0;,"
2264 "0.0; 1.0; 0.0;,"
2265 "1.0; 0.0; 0.0;,"
2266 "0.0; -1.0; 0.0;,"
2267 "0.0; 0.0; 1.0;,"
2268 "0.0; 0.0; -1.0;;"
2269 "6;" /* DWORD nFaceNormals; */
2270 /* array MeshFace faceNormals[nFaceNormals]; */
2271 "4; 0, 0, 0, 0;,"
2272 "4; 1, 1, 1, 1;,"
2273 "4; 2, 2, 2, 2;,"
2274 "4; 3, 3, 3, 3;,"
2275 "4; 4, 4, 4, 4;,"
2276 "4; 5, 5, 5, 5;;"
2278 "MeshMaterialList materials {"
2279 "2;" /* DWORD nMaterials; */
2280 "6;" /* DWORD nFaceIndexes; */
2281 /* array DWORD faceIndexes[nFaceIndexes]; */
2282 "0, 0, 0, 1, 1, 1;;"
2283 "Material {"
2284 /* ColorRGBA faceColor; */
2285 "0.0; 0.0; 1.0; 1.0;;"
2286 /* FLOAT power; */
2287 "0.5;"
2288 /* ColorRGB specularColor; */
2289 "1.0; 1.0; 1.0;;"
2290 /* ColorRGB emissiveColor; */
2291 "0.0; 0.0; 0.0;;"
2293 "Material {"
2294 /* ColorRGBA faceColor; */
2295 "1.0; 1.0; 1.0; 1.0;;"
2296 /* FLOAT power; */
2297 "1.0;"
2298 /* ColorRGB specularColor; */
2299 "1.0; 1.0; 1.0;;"
2300 /* ColorRGB emissiveColor; */
2301 "0.0; 0.0; 0.0;;"
2302 "TextureFilename { \"texture.jpg\"; }"
2305 "MeshVertexColors {"
2306 "8;" /* DWORD nVertexColors; */
2307 /* array IndexedColor vertexColors[nVertexColors]; */
2308 "0; 0.0; 0.0; 0.0; 0.0;;"
2309 "1; 0.0; 0.0; 1.0; 0.1;;"
2310 "2; 0.0; 1.0; 0.0; 0.2;;"
2311 "3; 0.0; 1.0; 1.0; 0.3;;"
2312 "4; 1.0; 0.0; 0.0; 0.4;;"
2313 "5; 1.0; 0.0; 1.0; 0.5;;"
2314 "6; 1.0; 1.0; 0.0; 0.6;;"
2315 "7; 1.0; 1.0; 1.0; 0.7;;"
2317 "MeshTextureCoords {"
2318 "8;" /* DWORD nTextureCoords; */
2319 /* array Coords2d textureCoords[nTextureCoords]; */
2320 "0.0; 1.0;,"
2321 "1.0; 1.0;,"
2322 "0.0; 0.0;,"
2323 "1.0; 0.0;,"
2324 "1.0; 1.0;,"
2325 "0.0; 1.0;,"
2326 "1.0; 0.0;,"
2327 "0.0; 0.0;;"
2330 "Frame CubeFrame {"
2331 "FrameTransformMatrix {"
2332 /* Matrix4x4 frameMatrix; */
2333 "1.0, 0.0, 0.0, 0.0,"
2334 "0.0, 1.0, 0.0, 0.0,"
2335 "0.0, 0.0, 1.0, 0.0,"
2336 "0.0, 0.0, 0.0, 1.0;;"
2338 "{CubeMesh}"
2340 "AnimationSet AnimationSet0 {"
2341 "Animation Animation0 {"
2342 "{CubeFrame}"
2343 "AnimationKey {"
2344 "2;" /* DWORD keyType; */
2345 "9;" /* DWORD nKeys; */
2346 /* array TimedFloatKeys keys[nKeys]; */
2347 "10; 3; -100.0, 0.0, 0.0;;,"
2348 "20; 3; -75.0, 0.0, 0.0;;,"
2349 "30; 3; -50.0, 0.0, 0.0;;,"
2350 "40; 3; -25.5, 0.0, 0.0;;,"
2351 "50; 3; 0.0, 0.0, 0.0;;,"
2352 "60; 3; 25.5, 0.0, 0.0;;,"
2353 "70; 3; 50.0, 0.0, 0.0;;,"
2354 "80; 3; 75.5, 0.0, 0.0;;,"
2355 "90; 3; 100.0, 0.0, 0.0;;;"
2358 "}";
2360 const DWORD box_fvf = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_TEX1;
2361 /*________________________*/
2362 static const D3DXMATERIAL default_materials[] = {
2365 {0.5, 0.5, 0.5, 0.0}, /* Diffuse */
2366 {0.0, 0.0, 0.0, 0.0}, /* Ambient */
2367 {0.5, 0.5, 0.5, 0.0}, /* Specular */
2368 {0.0, 0.0, 0.0, 0.0}, /* Emissive */
2369 0.0, /* Power */
2371 NULL, /* pTextureFilename */
2374 HRESULT hr;
2375 IDirect3DDevice9 *device = NULL;
2376 ID3DXMesh *mesh = NULL;
2377 D3DXFRAME *frame_hier = NULL;
2378 D3DXMATRIX transform;
2379 struct test_context *test_context;
2380 ID3DXAnimationController *controller;
2382 if (!(test_context = new_test_context()))
2384 skip("Couldn't create test context\n");
2385 return;
2387 device = test_context->device;
2389 hr = D3DXLoadMeshHierarchyFromXInMemory(NULL, sizeof(simple_xfile) - 1,
2390 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
2391 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2393 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, 0,
2394 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
2395 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2397 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1,
2398 D3DXMESH_MANAGED, NULL, &alloc_hier, NULL, &frame_hier, NULL);
2399 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2401 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1,
2402 D3DXMESH_MANAGED, device, NULL, NULL, &frame_hier, NULL);
2403 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2405 hr = D3DXLoadMeshHierarchyFromXInMemory(empty_xfile, sizeof(empty_xfile) - 1,
2406 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
2407 ok(hr == E_FAIL, "Expected E_FAIL, got %#x\n", hr);
2409 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1,
2410 D3DXMESH_MANAGED, device, &alloc_hier, NULL, NULL, NULL);
2411 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2413 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1,
2414 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
2415 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2416 if (SUCCEEDED(hr)) {
2417 D3DXMESHCONTAINER *container = frame_hier->pMeshContainer;
2419 ok(frame_hier->Name == NULL, "Expected NULL, got '%s'\n", frame_hier->Name);
2420 D3DXMatrixIdentity(&transform);
2421 check_matrix(&frame_hier->TransformationMatrix, &transform);
2423 ok(!strcmp(container->Name, ""), "Expected '', got '%s'\n", container->Name);
2424 ok(container->MeshData.Type == D3DXMESHTYPE_MESH, "Expected %d, got %d\n",
2425 D3DXMESHTYPE_MESH, container->MeshData.Type);
2426 mesh = U(container->MeshData).pMesh;
2427 check_vertex_buffer(mesh, simple_vertex_buffer, ARRAY_SIZE(simple_vertex_buffer), simple_fvf);
2428 check_index_buffer(mesh, simple_index_buffer, ARRAY_SIZE(simple_index_buffer), sizeof(*simple_index_buffer));
2429 check_materials(container->pMaterials, container->NumMaterials, NULL, 0);
2430 check_generated_effects(container->pMaterials, container->NumMaterials, container->pEffects);
2431 check_generated_adjacency(mesh, container->pAdjacency, 0.0f);
2432 hr = D3DXFrameDestroy(frame_hier, &alloc_hier);
2433 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2434 frame_hier = NULL;
2437 controller = (ID3DXAnimationController *)0xdeadbeef;
2438 hr = D3DXLoadMeshHierarchyFromXInMemory(box_anim_xfile, sizeof(box_anim_xfile) - 1,
2439 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, &controller);
2440 todo_wine ok(hr == D3D_OK, "Expected D3D_OK, got %#x.\n", hr);
2441 if (SUCCEEDED(hr))
2443 ok(controller != NULL, "Animation Controller NULL.\n");
2445 hr = D3DXFrameDestroy(frame_hier, &alloc_hier);
2446 ok(hr == D3D_OK, "Expected D3D_OK, got %#x.\n", hr);
2447 if (controller)
2448 controller->lpVtbl->Release(controller);
2450 frame_hier = NULL;
2453 controller = (ID3DXAnimationController *)0xdeadbeef;
2454 hr = D3DXLoadMeshHierarchyFromXInMemory(box_xfile, sizeof(box_xfile) - 1,
2455 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, &controller);
2456 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2457 if (SUCCEEDED(hr))
2459 D3DXMESHCONTAINER *container = frame_hier->pMeshContainer;
2461 ok(!controller, "Animation Controller returned.\n");
2462 ok(frame_hier->Name == NULL, "Expected NULL, got '%s'\n", frame_hier->Name);
2463 D3DXMatrixIdentity(&transform);
2464 check_matrix(&frame_hier->TransformationMatrix, &transform);
2466 ok(!strcmp(container->Name, ""), "Expected '', got '%s'\n", container->Name);
2467 ok(container->MeshData.Type == D3DXMESHTYPE_MESH, "Expected %d, got %d\n",
2468 D3DXMESHTYPE_MESH, container->MeshData.Type);
2469 mesh = U(container->MeshData).pMesh;
2470 check_vertex_buffer(mesh, box_vertex_buffer, ARRAY_SIZE(box_vertex_buffer), box_fvf);
2471 check_index_buffer(mesh, box_index_buffer, ARRAY_SIZE(box_index_buffer), sizeof(*box_index_buffer));
2472 check_materials(container->pMaterials, container->NumMaterials, box_materials, ARRAY_SIZE(box_materials));
2473 check_generated_effects(container->pMaterials, container->NumMaterials, container->pEffects);
2474 check_generated_adjacency(mesh, container->pAdjacency, 0.0f);
2475 hr = D3DXFrameDestroy(frame_hier, &alloc_hier);
2476 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2477 frame_hier = NULL;
2480 hr = D3DXLoadMeshHierarchyFromXInMemory(framed_xfile, sizeof(framed_xfile) - 1,
2481 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
2482 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2483 if (SUCCEEDED(hr)) {
2484 D3DXMESHCONTAINER *container = frame_hier->pMeshContainer;
2485 int i;
2487 ok(!strcmp(frame_hier->Name, ""), "Expected '', got '%s'\n", frame_hier->Name);
2488 /* last frame transform replaces the first */
2489 D3DXMatrixIdentity(&transform);
2490 U(transform).m[3][2] = 3.0;
2491 check_matrix(&frame_hier->TransformationMatrix, &transform);
2493 for (i = 0; i < 3; i++) {
2494 ok(!strcmp(container->Name, ""), "Expected '', got '%s'\n", container->Name);
2495 ok(container->MeshData.Type == D3DXMESHTYPE_MESH, "Expected %d, got %d\n",
2496 D3DXMESHTYPE_MESH, container->MeshData.Type);
2497 mesh = U(container->MeshData).pMesh;
2498 check_vertex_buffer(mesh, framed_vertex_buffers[i], ARRAY_SIZE(framed_vertex_buffers[0]), framed_fvf);
2499 check_index_buffer(mesh, framed_index_buffer, ARRAY_SIZE(framed_index_buffer), sizeof(*framed_index_buffer));
2500 check_materials(container->pMaterials, container->NumMaterials, NULL, 0);
2501 check_generated_effects(container->pMaterials, container->NumMaterials, container->pEffects);
2502 check_generated_adjacency(mesh, container->pAdjacency, 0.0f);
2503 container = container->pNextMeshContainer;
2505 ok(container == NULL, "Expected NULL, got %p\n", container);
2506 hr = D3DXFrameDestroy(frame_hier, &alloc_hier);
2507 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2508 frame_hier = NULL;
2512 hr = D3DXLoadMeshFromXInMemory(NULL, 0, D3DXMESH_MANAGED,
2513 device, NULL, NULL, NULL, NULL, &mesh);
2514 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2516 hr = D3DXLoadMeshFromXInMemory(NULL, sizeof(simple_xfile) - 1, D3DXMESH_MANAGED,
2517 device, NULL, NULL, NULL, NULL, &mesh);
2518 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2520 hr = D3DXLoadMeshFromXInMemory(simple_xfile, 0, D3DXMESH_MANAGED,
2521 device, NULL, NULL, NULL, NULL, &mesh);
2522 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2524 hr = D3DXLoadMeshFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1, D3DXMESH_MANAGED,
2525 device, NULL, NULL, NULL, NULL, NULL);
2526 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2528 hr = D3DXLoadMeshFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1, D3DXMESH_MANAGED,
2529 NULL, NULL, NULL, NULL, NULL, &mesh);
2530 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2532 hr = D3DXLoadMeshFromXInMemory(empty_xfile, sizeof(empty_xfile) - 1, D3DXMESH_MANAGED,
2533 device, NULL, NULL, NULL, NULL, &mesh);
2534 ok(hr == E_FAIL, "Expected E_FAIL, got %#x\n", hr);
2536 hr = D3DXLoadMeshFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1, D3DXMESH_MANAGED,
2537 device, NULL, NULL, NULL, NULL, &mesh);
2538 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2539 if (SUCCEEDED(hr))
2540 IUnknown_Release(mesh);
2542 test_LoadMeshFromX(device, simple_xfile, simple_vertex_buffer, simple_fvf, simple_index_buffer, default_materials, TRUE);
2543 test_LoadMeshFromX(device, box_xfile, box_vertex_buffer, box_fvf, box_index_buffer, box_materials, TRUE);
2544 test_LoadMeshFromX(device, framed_xfile, merged_vertex_buffer, framed_fvf, merged_index_buffer, default_materials, FALSE);
2546 free_test_context(test_context);
2549 static BOOL compute_box(struct mesh *mesh, float width, float height, float depth)
2551 unsigned int i, face;
2552 static const D3DXVECTOR3 unit_box[] =
2554 {-1.0f, -1.0f, -1.0f}, {-1.0f, -1.0f, 1.0f}, {-1.0f, 1.0f, 1.0f}, {-1.0f, 1.0f, -1.0f},
2555 {-1.0f, 1.0f, -1.0f}, {-1.0f, 1.0f, 1.0f}, { 1.0f, 1.0f, 1.0f}, { 1.0f, 1.0f, -1.0f},
2556 { 1.0f, 1.0f, -1.0f}, { 1.0f, 1.0f, 1.0f}, { 1.0f, -1.0f, 1.0f}, { 1.0f, -1.0f, -1.0f},
2557 {-1.0f, -1.0f, 1.0f}, {-1.0f, -1.0f, -1.0f}, { 1.0f, -1.0f, -1.0f}, { 1.0f, -1.0f, 1.0f},
2558 {-1.0f, -1.0f, 1.0f}, { 1.0f, -1.0f, 1.0f}, { 1.0f, 1.0f, 1.0f}, {-1.0f, 1.0f, 1.0f},
2559 {-1.0f, -1.0f, -1.0f}, {-1.0f, 1.0f, -1.0f}, { 1.0f, 1.0f, -1.0f}, { 1.0f, -1.0f, -1.0f}
2561 static const D3DXVECTOR3 normals[] =
2563 {-1.0f, 0.0f, 0.0f}, { 0.0f, 1.0f, 0.0f}, { 1.0f, 0.0f, 0.0f},
2564 { 0.0f, -1.0f, 0.0f}, { 0.0f, 0.0f, 1.0f}, { 0.0f, 0.0f, -1.0f}
2567 if (!new_mesh(mesh, 24, 12))
2569 return FALSE;
2572 width /= 2.0f;
2573 height /= 2.0f;
2574 depth /= 2.0f;
2576 for (i = 0; i < 24; i++)
2578 mesh->vertices[i].position.x = width * unit_box[i].x;
2579 mesh->vertices[i].position.y = height * unit_box[i].y;
2580 mesh->vertices[i].position.z = depth * unit_box[i].z;
2581 mesh->vertices[i].normal.x = normals[i / 4].x;
2582 mesh->vertices[i].normal.y = normals[i / 4].y;
2583 mesh->vertices[i].normal.z = normals[i / 4].z;
2586 face = 0;
2587 for (i = 0; i < 12; i++)
2589 mesh->faces[i][0] = face++;
2590 mesh->faces[i][1] = face++;
2591 mesh->faces[i][2] = (i % 2) ? face - 4 : face;
2594 return TRUE;
2597 static void test_box(IDirect3DDevice9 *device, float width, float height, float depth)
2599 HRESULT hr;
2600 ID3DXMesh *box;
2601 struct mesh mesh;
2602 char name[256];
2604 hr = D3DXCreateBox(device, width, height, depth, &box, NULL);
2605 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
2606 if (hr != D3D_OK)
2608 skip("Couldn't create box\n");
2609 return;
2612 if (!compute_box(&mesh, width, height, depth))
2614 skip("Couldn't create mesh\n");
2615 box->lpVtbl->Release(box);
2616 return;
2619 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
2621 sprintf(name, "box (%g, %g, %g)", width, height, depth);
2622 compare_mesh(name, box, &mesh);
2624 free_mesh(&mesh);
2626 box->lpVtbl->Release(box);
2628 static void D3DXCreateBoxTest(void)
2630 HRESULT hr;
2631 IDirect3DDevice9* device;
2632 ID3DXMesh* box;
2633 ID3DXBuffer* ppBuffer;
2634 DWORD *buffer;
2635 static const DWORD adjacency[36]=
2636 {6, 9, 1, 2, 10, 0,
2637 1, 9, 3, 4, 10, 2,
2638 3, 8, 5, 7, 11, 4,
2639 0, 11, 7, 5, 8, 6,
2640 7, 4, 9, 2, 0, 8,
2641 1, 3, 11, 5, 6, 10};
2642 unsigned int i;
2643 struct test_context *test_context;
2645 if (!(test_context = new_test_context()))
2647 skip("Couldn't create test context\n");
2648 return;
2650 device = test_context->device;
2652 hr = D3DXCreateBox(device,2.0f,20.0f,4.9f,NULL, &ppBuffer);
2653 ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2655 hr = D3DXCreateBox(NULL,22.0f,20.0f,4.9f,&box, &ppBuffer);
2656 ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2658 hr = D3DXCreateBox(device,-2.0f,20.0f,4.9f,&box, &ppBuffer);
2659 ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2661 hr = D3DXCreateBox(device,22.0f,-20.0f,4.9f,&box, &ppBuffer);
2662 ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2664 hr = D3DXCreateBox(device,22.0f,20.0f,-4.9f,&box, &ppBuffer);
2665 ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2667 ppBuffer = NULL;
2668 hr = D3DXCreateBox(device,10.9f,20.0f,4.9f,&box, &ppBuffer);
2669 ok(hr==D3D_OK, "Expected D3D_OK, received %#x\n", hr);
2671 buffer = ID3DXBuffer_GetBufferPointer(ppBuffer);
2672 for(i=0; i<36; i++)
2673 ok(adjacency[i]==buffer[i], "expected adjacency %d: %#x, received %#x\n",i,adjacency[i], buffer[i]);
2675 box->lpVtbl->Release(box);
2676 ID3DXBuffer_Release(ppBuffer);
2678 test_box(device, 10.9f, 20.0f, 4.9f);
2680 free_test_context(test_context);
2683 static BOOL compute_polygon(struct mesh *mesh, float length, unsigned int sides)
2685 unsigned int i;
2686 float angle, scale;
2688 if (!new_mesh(mesh, sides + 1, sides))
2689 return FALSE;
2691 angle = D3DX_PI / sides;
2692 scale = 0.5f * length / sinf(angle);
2693 angle *= 2.0f;
2695 mesh->vertices[0].position.x = 0.0f;
2696 mesh->vertices[0].position.y = 0.0f;
2697 mesh->vertices[0].position.z = 0.0f;
2698 mesh->vertices[0].normal.x = 0.0f;
2699 mesh->vertices[0].normal.y = 0.0f;
2700 mesh->vertices[0].normal.z = 1.0f;
2702 for (i = 0; i < sides; ++i)
2704 mesh->vertices[i + 1].position.x = cosf(angle * i) * scale;
2705 mesh->vertices[i + 1].position.y = sinf(angle * i) * scale;
2706 mesh->vertices[i + 1].position.z = 0.0f;
2707 mesh->vertices[i + 1].normal.x = 0.0f;
2708 mesh->vertices[i + 1].normal.y = 0.0f;
2709 mesh->vertices[i + 1].normal.z = 1.0f;
2711 mesh->faces[i][0] = 0;
2712 mesh->faces[i][1] = i + 1;
2713 mesh->faces[i][2] = i + 2;
2716 mesh->faces[sides - 1][2] = 1;
2718 return TRUE;
2721 static void test_polygon(IDirect3DDevice9 *device, float length, unsigned int sides)
2723 HRESULT hr;
2724 ID3DXMesh *polygon;
2725 struct mesh mesh;
2726 char name[64];
2728 hr = D3DXCreatePolygon(device, length, sides, &polygon, NULL);
2729 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
2730 if (hr != D3D_OK)
2732 skip("Couldn't create polygon\n");
2733 return;
2736 if (!compute_polygon(&mesh, length, sides))
2738 skip("Couldn't create mesh\n");
2739 polygon->lpVtbl->Release(polygon);
2740 return;
2743 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
2745 sprintf(name, "polygon (%g, %u)", length, sides);
2746 compare_mesh(name, polygon, &mesh);
2748 free_mesh(&mesh);
2750 polygon->lpVtbl->Release(polygon);
2753 static void D3DXCreatePolygonTest(void)
2755 HRESULT hr;
2756 IDirect3DDevice9 *device;
2757 ID3DXMesh *polygon;
2758 ID3DXBuffer *adjacency;
2759 DWORD (*buffer)[3], buffer_size;
2760 unsigned int i;
2761 struct test_context *test_context;
2763 if (!(test_context = new_test_context()))
2765 skip("Couldn't create test context\n");
2766 return;
2768 device = test_context->device;
2770 hr = D3DXCreatePolygon(device, 2.0f, 11, NULL, &adjacency);
2771 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2773 hr = D3DXCreatePolygon(NULL, 2.0f, 11, &polygon, &adjacency);
2774 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2776 hr = D3DXCreatePolygon(device, -2.0f, 11, &polygon, &adjacency);
2777 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2779 polygon = (void *)0xdeadbeef;
2780 adjacency = (void *)0xdeadbeef;
2781 hr = D3DXCreatePolygon(device, 2.0f, 0, &polygon, &adjacency);
2782 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2783 ok(polygon == (void *)0xdeadbeef, "Polygon was changed to %p\n", polygon);
2784 ok(adjacency == (void *)0xdeadbeef, "Adjacency was changed to %p\n", adjacency);
2786 hr = D3DXCreatePolygon(device, 2.0f, 2, &polygon, &adjacency);
2787 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2789 adjacency = NULL;
2790 hr = D3DXCreatePolygon(device, 3.0f, 11, &polygon, &adjacency);
2791 ok(hr == D3D_OK, "Expected D3D_OK, received %#x\n", hr);
2793 buffer_size = ID3DXBuffer_GetBufferSize(adjacency);
2794 ok(buffer_size == 33 * sizeof(DWORD), "Wrong adjacency buffer size %u\n", buffer_size);
2796 buffer = ID3DXBuffer_GetBufferPointer(adjacency);
2797 for (i = 0; i < 11; ++i)
2799 ok(buffer[i][0] == (i + 10) % 11, "Wrong adjacency[%d][0] = %u\n", i, buffer[i][0]);
2800 ok(buffer[i][1] == ~0U, "Wrong adjacency[%d][1] = %u\n", i, buffer[i][1]);
2801 ok(buffer[i][2] == (i + 1) % 11, "Wrong adjacency[%d][2] = %u\n", i, buffer[i][2]);
2804 polygon->lpVtbl->Release(polygon);
2805 ID3DXBuffer_Release(adjacency);
2807 test_polygon(device, 2.0f, 3);
2808 test_polygon(device, 10.0f, 3);
2809 test_polygon(device, 10.0f, 5);
2810 test_polygon(device, 10.0f, 10);
2811 test_polygon(device, 20.0f, 10);
2812 test_polygon(device, 20.0f, 32000);
2814 free_test_context(test_context);
2817 struct sincos_table
2819 float *sin;
2820 float *cos;
2823 static void free_sincos_table(struct sincos_table *sincos_table)
2825 HeapFree(GetProcessHeap(), 0, sincos_table->cos);
2826 HeapFree(GetProcessHeap(), 0, sincos_table->sin);
2829 /* pre compute sine and cosine tables; caller must free */
2830 static BOOL compute_sincos_table(struct sincos_table *sincos_table, float angle_start, float angle_step, int n)
2832 float angle;
2833 int i;
2835 sincos_table->sin = HeapAlloc(GetProcessHeap(), 0, n * sizeof(*sincos_table->sin));
2836 if (!sincos_table->sin)
2838 return FALSE;
2840 sincos_table->cos = HeapAlloc(GetProcessHeap(), 0, n * sizeof(*sincos_table->cos));
2841 if (!sincos_table->cos)
2843 HeapFree(GetProcessHeap(), 0, sincos_table->sin);
2844 return FALSE;
2847 angle = angle_start;
2848 for (i = 0; i < n; i++)
2850 sincos_table->sin[i] = sin(angle);
2851 sincos_table->cos[i] = cos(angle);
2852 angle += angle_step;
2855 return TRUE;
2858 static WORD vertex_index(UINT slices, int slice, int stack)
2860 return stack*slices+slice+1;
2863 /* slices = subdivisions along xy plane, stacks = subdivisions along z axis */
2864 static BOOL compute_sphere(struct mesh *mesh, FLOAT radius, UINT slices, UINT stacks)
2866 float theta_step, theta_start;
2867 struct sincos_table theta;
2868 float phi_step, phi_start;
2869 struct sincos_table phi;
2870 DWORD number_of_vertices, number_of_faces;
2871 DWORD vertex, face;
2872 int slice, stack;
2874 /* theta = angle on xy plane wrt x axis */
2875 theta_step = D3DX_PI / stacks;
2876 theta_start = theta_step;
2878 /* phi = angle on xz plane wrt z axis */
2879 phi_step = -2 * D3DX_PI / slices;
2880 phi_start = D3DX_PI / 2;
2882 if (!compute_sincos_table(&theta, theta_start, theta_step, stacks))
2884 return FALSE;
2886 if (!compute_sincos_table(&phi, phi_start, phi_step, slices))
2888 free_sincos_table(&theta);
2889 return FALSE;
2892 number_of_vertices = 2 + slices * (stacks-1);
2893 number_of_faces = 2 * slices + (stacks - 2) * (2 * slices);
2895 if (!new_mesh(mesh, number_of_vertices, number_of_faces))
2897 free_sincos_table(&phi);
2898 free_sincos_table(&theta);
2899 return FALSE;
2902 vertex = 0;
2903 face = 0;
2905 mesh->vertices[vertex].normal.x = 0.0f;
2906 mesh->vertices[vertex].normal.y = 0.0f;
2907 mesh->vertices[vertex].normal.z = 1.0f;
2908 mesh->vertices[vertex].position.x = 0.0f;
2909 mesh->vertices[vertex].position.y = 0.0f;
2910 mesh->vertices[vertex].position.z = radius;
2911 vertex++;
2913 for (stack = 0; stack < stacks - 1; stack++)
2915 for (slice = 0; slice < slices; slice++)
2917 mesh->vertices[vertex].normal.x = theta.sin[stack] * phi.cos[slice];
2918 mesh->vertices[vertex].normal.y = theta.sin[stack] * phi.sin[slice];
2919 mesh->vertices[vertex].normal.z = theta.cos[stack];
2920 mesh->vertices[vertex].position.x = radius * theta.sin[stack] * phi.cos[slice];
2921 mesh->vertices[vertex].position.y = radius * theta.sin[stack] * phi.sin[slice];
2922 mesh->vertices[vertex].position.z = radius * theta.cos[stack];
2923 vertex++;
2925 if (slice > 0)
2927 if (stack == 0)
2929 /* top stack is triangle fan */
2930 mesh->faces[face][0] = 0;
2931 mesh->faces[face][1] = slice + 1;
2932 mesh->faces[face][2] = slice;
2933 face++;
2935 else
2937 /* stacks in between top and bottom are quad strips */
2938 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
2939 mesh->faces[face][1] = vertex_index(slices, slice, stack-1);
2940 mesh->faces[face][2] = vertex_index(slices, slice-1, stack);
2941 face++;
2943 mesh->faces[face][0] = vertex_index(slices, slice, stack-1);
2944 mesh->faces[face][1] = vertex_index(slices, slice, stack);
2945 mesh->faces[face][2] = vertex_index(slices, slice-1, stack);
2946 face++;
2951 if (stack == 0)
2953 mesh->faces[face][0] = 0;
2954 mesh->faces[face][1] = 1;
2955 mesh->faces[face][2] = slice;
2956 face++;
2958 else
2960 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
2961 mesh->faces[face][1] = vertex_index(slices, 0, stack-1);
2962 mesh->faces[face][2] = vertex_index(slices, slice-1, stack);
2963 face++;
2965 mesh->faces[face][0] = vertex_index(slices, 0, stack-1);
2966 mesh->faces[face][1] = vertex_index(slices, 0, stack);
2967 mesh->faces[face][2] = vertex_index(slices, slice-1, stack);
2968 face++;
2972 mesh->vertices[vertex].position.x = 0.0f;
2973 mesh->vertices[vertex].position.y = 0.0f;
2974 mesh->vertices[vertex].position.z = -radius;
2975 mesh->vertices[vertex].normal.x = 0.0f;
2976 mesh->vertices[vertex].normal.y = 0.0f;
2977 mesh->vertices[vertex].normal.z = -1.0f;
2979 /* bottom stack is triangle fan */
2980 for (slice = 1; slice < slices; slice++)
2982 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
2983 mesh->faces[face][1] = vertex_index(slices, slice, stack-1);
2984 mesh->faces[face][2] = vertex;
2985 face++;
2988 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
2989 mesh->faces[face][1] = vertex_index(slices, 0, stack-1);
2990 mesh->faces[face][2] = vertex;
2992 free_sincos_table(&phi);
2993 free_sincos_table(&theta);
2995 return TRUE;
2998 static void test_sphere(IDirect3DDevice9 *device, FLOAT radius, UINT slices, UINT stacks)
3000 HRESULT hr;
3001 ID3DXMesh *sphere;
3002 struct mesh mesh;
3003 char name[256];
3005 hr = D3DXCreateSphere(device, radius, slices, stacks, &sphere, NULL);
3006 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
3007 if (hr != D3D_OK)
3009 skip("Couldn't create sphere\n");
3010 return;
3013 if (!compute_sphere(&mesh, radius, slices, stacks))
3015 skip("Couldn't create mesh\n");
3016 sphere->lpVtbl->Release(sphere);
3017 return;
3020 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
3022 sprintf(name, "sphere (%g, %u, %u)", radius, slices, stacks);
3023 compare_mesh(name, sphere, &mesh);
3025 free_mesh(&mesh);
3027 sphere->lpVtbl->Release(sphere);
3030 static void D3DXCreateSphereTest(void)
3032 HRESULT hr;
3033 IDirect3DDevice9* device;
3034 ID3DXMesh* sphere = NULL;
3035 struct test_context *test_context;
3037 hr = D3DXCreateSphere(NULL, 0.0f, 0, 0, NULL, NULL);
3038 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3040 hr = D3DXCreateSphere(NULL, 0.1f, 0, 0, NULL, NULL);
3041 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3043 hr = D3DXCreateSphere(NULL, 0.0f, 1, 0, NULL, NULL);
3044 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3046 hr = D3DXCreateSphere(NULL, 0.0f, 0, 1, NULL, NULL);
3047 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3049 if (!(test_context = new_test_context()))
3051 skip("Couldn't create test context\n");
3052 return;
3054 device = test_context->device;
3056 hr = D3DXCreateSphere(device, 1.0f, 1, 1, &sphere, NULL);
3057 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3059 hr = D3DXCreateSphere(device, 1.0f, 2, 1, &sphere, NULL);
3060 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
3062 hr = D3DXCreateSphere(device, 1.0f, 1, 2, &sphere, NULL);
3063 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
3065 hr = D3DXCreateSphere(device, -0.1f, 1, 2, &sphere, NULL);
3066 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
3068 test_sphere(device, 0.0f, 2, 2);
3069 test_sphere(device, 1.0f, 2, 2);
3070 test_sphere(device, 1.0f, 3, 2);
3071 test_sphere(device, 1.0f, 4, 4);
3072 test_sphere(device, 1.0f, 3, 4);
3073 test_sphere(device, 5.0f, 6, 7);
3074 test_sphere(device, 10.0f, 11, 12);
3076 free_test_context(test_context);
3079 static BOOL compute_cylinder(struct mesh *mesh, FLOAT radius1, FLOAT radius2, FLOAT length, UINT slices, UINT stacks)
3081 float theta_step, theta_start;
3082 struct sincos_table theta;
3083 FLOAT delta_radius, radius, radius_step;
3084 FLOAT z, z_step, z_normal;
3085 DWORD number_of_vertices, number_of_faces;
3086 DWORD vertex, face;
3087 int slice, stack;
3089 /* theta = angle on xy plane wrt x axis */
3090 theta_step = -2 * D3DX_PI / slices;
3091 theta_start = D3DX_PI / 2;
3093 if (!compute_sincos_table(&theta, theta_start, theta_step, slices))
3095 return FALSE;
3098 number_of_vertices = 2 + (slices * (3 + stacks));
3099 number_of_faces = 2 * slices + stacks * (2 * slices);
3101 if (!new_mesh(mesh, number_of_vertices, number_of_faces))
3103 free_sincos_table(&theta);
3104 return FALSE;
3107 vertex = 0;
3108 face = 0;
3110 delta_radius = radius1 - radius2;
3111 radius = radius1;
3112 radius_step = delta_radius / stacks;
3114 z = -length / 2;
3115 z_step = length / stacks;
3116 z_normal = delta_radius / length;
3117 if (isnan(z_normal))
3119 z_normal = 0.0f;
3122 mesh->vertices[vertex].normal.x = 0.0f;
3123 mesh->vertices[vertex].normal.y = 0.0f;
3124 mesh->vertices[vertex].normal.z = -1.0f;
3125 mesh->vertices[vertex].position.x = 0.0f;
3126 mesh->vertices[vertex].position.y = 0.0f;
3127 mesh->vertices[vertex++].position.z = z;
3129 for (slice = 0; slice < slices; slice++, vertex++)
3131 mesh->vertices[vertex].normal.x = 0.0f;
3132 mesh->vertices[vertex].normal.y = 0.0f;
3133 mesh->vertices[vertex].normal.z = -1.0f;
3134 mesh->vertices[vertex].position.x = radius * theta.cos[slice];
3135 mesh->vertices[vertex].position.y = radius * theta.sin[slice];
3136 mesh->vertices[vertex].position.z = z;
3138 if (slice > 0)
3140 mesh->faces[face][0] = 0;
3141 mesh->faces[face][1] = slice;
3142 mesh->faces[face++][2] = slice + 1;
3146 mesh->faces[face][0] = 0;
3147 mesh->faces[face][1] = slice;
3148 mesh->faces[face++][2] = 1;
3150 for (stack = 1; stack <= stacks+1; stack++)
3152 for (slice = 0; slice < slices; slice++, vertex++)
3154 mesh->vertices[vertex].normal.x = theta.cos[slice];
3155 mesh->vertices[vertex].normal.y = theta.sin[slice];
3156 mesh->vertices[vertex].normal.z = z_normal;
3157 D3DXVec3Normalize(&mesh->vertices[vertex].normal, &mesh->vertices[vertex].normal);
3158 mesh->vertices[vertex].position.x = radius * theta.cos[slice];
3159 mesh->vertices[vertex].position.y = radius * theta.sin[slice];
3160 mesh->vertices[vertex].position.z = z;
3162 if (stack > 1 && slice > 0)
3164 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
3165 mesh->faces[face][1] = vertex_index(slices, slice-1, stack);
3166 mesh->faces[face++][2] = vertex_index(slices, slice, stack-1);
3168 mesh->faces[face][0] = vertex_index(slices, slice, stack-1);
3169 mesh->faces[face][1] = vertex_index(slices, slice-1, stack);
3170 mesh->faces[face++][2] = vertex_index(slices, slice, stack);
3174 if (stack > 1)
3176 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
3177 mesh->faces[face][1] = vertex_index(slices, slice-1, stack);
3178 mesh->faces[face++][2] = vertex_index(slices, 0, stack-1);
3180 mesh->faces[face][0] = vertex_index(slices, 0, stack-1);
3181 mesh->faces[face][1] = vertex_index(slices, slice-1, stack);
3182 mesh->faces[face++][2] = vertex_index(slices, 0, stack);
3185 if (stack < stacks + 1)
3187 z += z_step;
3188 radius -= radius_step;
3192 for (slice = 0; slice < slices; slice++, vertex++)
3194 mesh->vertices[vertex].normal.x = 0.0f;
3195 mesh->vertices[vertex].normal.y = 0.0f;
3196 mesh->vertices[vertex].normal.z = 1.0f;
3197 mesh->vertices[vertex].position.x = radius * theta.cos[slice];
3198 mesh->vertices[vertex].position.y = radius * theta.sin[slice];
3199 mesh->vertices[vertex].position.z = z;
3201 if (slice > 0)
3203 mesh->faces[face][0] = vertex_index(slices, slice-1, stack);
3204 mesh->faces[face][1] = number_of_vertices - 1;
3205 mesh->faces[face++][2] = vertex_index(slices, slice, stack);
3209 mesh->vertices[vertex].position.x = 0.0f;
3210 mesh->vertices[vertex].position.y = 0.0f;
3211 mesh->vertices[vertex].position.z = z;
3212 mesh->vertices[vertex].normal.x = 0.0f;
3213 mesh->vertices[vertex].normal.y = 0.0f;
3214 mesh->vertices[vertex].normal.z = 1.0f;
3216 mesh->faces[face][0] = vertex_index(slices, slice-1, stack);
3217 mesh->faces[face][1] = number_of_vertices - 1;
3218 mesh->faces[face][2] = vertex_index(slices, 0, stack);
3220 free_sincos_table(&theta);
3222 return TRUE;
3225 static void test_cylinder(IDirect3DDevice9 *device, FLOAT radius1, FLOAT radius2, FLOAT length, UINT slices, UINT stacks)
3227 HRESULT hr;
3228 ID3DXMesh *cylinder;
3229 struct mesh mesh;
3230 char name[256];
3232 hr = D3DXCreateCylinder(device, radius1, radius2, length, slices, stacks, &cylinder, NULL);
3233 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
3234 if (hr != D3D_OK)
3236 skip("Couldn't create cylinder\n");
3237 return;
3240 if (!compute_cylinder(&mesh, radius1, radius2, length, slices, stacks))
3242 skip("Couldn't create mesh\n");
3243 cylinder->lpVtbl->Release(cylinder);
3244 return;
3247 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
3249 sprintf(name, "cylinder (%g, %g, %g, %u, %u)", radius1, radius2, length, slices, stacks);
3250 compare_mesh(name, cylinder, &mesh);
3252 free_mesh(&mesh);
3254 cylinder->lpVtbl->Release(cylinder);
3257 static void D3DXCreateCylinderTest(void)
3259 HRESULT hr;
3260 IDirect3DDevice9* device;
3261 ID3DXMesh* cylinder = NULL;
3262 struct test_context *test_context;
3264 hr = D3DXCreateCylinder(NULL, 0.0f, 0.0f, 0.0f, 0, 0, NULL, NULL);
3265 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3267 hr = D3DXCreateCylinder(NULL, 1.0f, 1.0f, 1.0f, 2, 1, &cylinder, NULL);
3268 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3270 if (!(test_context = new_test_context()))
3272 skip("Couldn't create test context\n");
3273 return;
3275 device = test_context->device;
3277 hr = D3DXCreateCylinder(device, -0.1f, 1.0f, 1.0f, 2, 1, &cylinder, NULL);
3278 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3280 hr = D3DXCreateCylinder(device, 0.0f, 1.0f, 1.0f, 2, 1, &cylinder, NULL);
3281 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n",hr);
3283 if (SUCCEEDED(hr) && cylinder)
3285 cylinder->lpVtbl->Release(cylinder);
3288 hr = D3DXCreateCylinder(device, 1.0f, -0.1f, 1.0f, 2, 1, &cylinder, NULL);
3289 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3291 hr = D3DXCreateCylinder(device, 1.0f, 0.0f, 1.0f, 2, 1, &cylinder, NULL);
3292 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n",hr);
3294 if (SUCCEEDED(hr) && cylinder)
3296 cylinder->lpVtbl->Release(cylinder);
3299 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, -0.1f, 2, 1, &cylinder, NULL);
3300 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3302 /* Test with length == 0.0f succeeds */
3303 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, 0.0f, 2, 1, &cylinder, NULL);
3304 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n",hr);
3306 if (SUCCEEDED(hr) && cylinder)
3308 cylinder->lpVtbl->Release(cylinder);
3311 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, 1.0f, 1, 1, &cylinder, NULL);
3312 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3314 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, 1.0f, 2, 0, &cylinder, NULL);
3315 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3317 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, 1.0f, 2, 1, NULL, NULL);
3318 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3320 test_cylinder(device, 0.0f, 0.0f, 0.0f, 2, 1);
3321 test_cylinder(device, 1.0f, 1.0f, 1.0f, 2, 1);
3322 test_cylinder(device, 1.0f, 1.0f, 2.0f, 3, 4);
3323 test_cylinder(device, 3.0f, 2.0f, 4.0f, 3, 4);
3324 test_cylinder(device, 2.0f, 3.0f, 4.0f, 3, 4);
3325 test_cylinder(device, 3.0f, 4.0f, 5.0f, 11, 20);
3327 free_test_context(test_context);
3330 static BOOL compute_torus(struct mesh *mesh, float innerradius, float outerradius, UINT sides, UINT rings)
3332 float phi, phi_step, sin_phi, cos_phi;
3333 float theta, theta_step, sin_theta, cos_theta;
3334 unsigned int numvert, numfaces, i, j;
3336 numvert = sides * rings;
3337 numfaces = numvert * 2;
3339 if (!new_mesh(mesh, numvert, numfaces))
3340 return FALSE;
3342 phi_step = D3DX_PI / sides * 2.0f;
3343 theta_step = D3DX_PI / rings * -2.0f;
3345 theta = 0.0f;
3347 for (i = 0; i < rings; ++i)
3349 phi = 0.0f;
3351 cos_theta = cosf(theta);
3352 sin_theta = sinf(theta);
3354 for (j = 0; j < sides; ++j)
3356 sin_phi = sinf(phi);
3357 cos_phi = cosf(phi);
3359 mesh->vertices[i * sides + j].position.x = (innerradius * cos_phi + outerradius) * cos_theta;
3360 mesh->vertices[i * sides + j].position.y = (innerradius * cos_phi + outerradius) * sin_theta;
3361 mesh->vertices[i * sides + j].position.z = innerradius * sin_phi;
3362 mesh->vertices[i * sides + j].normal.x = cos_phi * cos_theta;
3363 mesh->vertices[i * sides + j].normal.y = cos_phi * sin_theta;
3364 mesh->vertices[i * sides + j].normal.z = sin_phi;
3366 phi += phi_step;
3369 theta += theta_step;
3372 for (i = 0; i < numfaces - sides * 2; ++i)
3374 mesh->faces[i][0] = i % 2 ? i / 2 + sides : i / 2;
3375 mesh->faces[i][1] = (i / 2 + 1) % sides ? i / 2 + 1 : i / 2 + 1 - sides;
3376 mesh->faces[i][2] = (i + 1) % (sides * 2) ? (i + 1) / 2 + sides : (i + 1) / 2;
3379 for (j = 0; i < numfaces; ++i, ++j)
3381 mesh->faces[i][0] = i % 2 ? j / 2 : i / 2;
3382 mesh->faces[i][1] = (i / 2 + 1) % sides ? i / 2 + 1 : i / 2 + 1 - sides;
3383 mesh->faces[i][2] = i == numfaces - 1 ? 0 : (j + 1) / 2;
3386 return TRUE;
3389 static void test_torus(IDirect3DDevice9 *device, float innerradius, float outerradius, UINT sides, UINT rings)
3391 HRESULT hr;
3392 ID3DXMesh *torus;
3393 struct mesh mesh;
3394 char name[256];
3396 hr = D3DXCreateTorus(device, innerradius, outerradius, sides, rings, &torus, NULL);
3397 ok(hr == D3D_OK, "Got result %#x, expected 0 (D3D_OK)\n", hr);
3398 if (hr != D3D_OK)
3400 skip("Couldn't create torus\n");
3401 return;
3404 if (!compute_torus(&mesh, innerradius, outerradius, sides, rings))
3406 skip("Couldn't create mesh\n");
3407 torus->lpVtbl->Release(torus);
3408 return;
3411 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
3413 sprintf(name, "torus (%g, %g, %u, %u)", innerradius, outerradius, sides, rings);
3414 compare_mesh(name, torus, &mesh);
3416 free_mesh(&mesh);
3418 torus->lpVtbl->Release(torus);
3421 static void D3DXCreateTorusTest(void)
3423 HRESULT hr;
3424 IDirect3DDevice9* device;
3425 ID3DXMesh* torus = NULL;
3426 struct test_context *test_context;
3428 if (!(test_context = new_test_context()))
3430 skip("Couldn't create test context\n");
3431 return;
3433 device = test_context->device;
3435 hr = D3DXCreateTorus(NULL, 0.0f, 0.0f, 3, 3, &torus, NULL);
3436 ok(hr == D3DERR_INVALIDCALL, "Got result %#x, expected %#x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
3438 hr = D3DXCreateTorus(device, -1.0f, 0.0f, 3, 3, &torus, NULL);
3439 ok(hr == D3DERR_INVALIDCALL, "Got result %#x, expected %#x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
3441 hr = D3DXCreateTorus(device, 0.0f, -1.0f, 3, 3, &torus, NULL);
3442 ok(hr == D3DERR_INVALIDCALL, "Got result %#x, expected %#x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
3444 hr = D3DXCreateTorus(device, 0.0f, 0.0f, 2, 3, &torus, NULL);
3445 ok(hr == D3DERR_INVALIDCALL, "Got result %#x, expected %#x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
3447 hr = D3DXCreateTorus(device, 0.0f, 0.0f, 3, 2, &torus, NULL);
3448 ok(hr == D3DERR_INVALIDCALL, "Got result %#x, expected %#x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
3450 hr = D3DXCreateTorus(device, 0.0f, 0.0f, 3, 3, NULL, NULL);
3451 ok(hr == D3DERR_INVALIDCALL, "Got result %#x, expected %#x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
3453 test_torus(device, 0.0f, 0.0f, 3, 3);
3454 test_torus(device, 1.0f, 1.0f, 3, 3);
3455 test_torus(device, 1.0f, 1.0f, 32, 64);
3456 test_torus(device, 0.0f, 1.0f, 5, 5);
3457 test_torus(device, 1.0f, 0.0f, 5, 5);
3458 test_torus(device, 5.0f, 0.2f, 8, 8);
3459 test_torus(device, 0.2f, 1.0f, 60, 3);
3460 test_torus(device, 0.2f, 1.0f, 8, 70);
3462 free_test_context(test_context);
3465 struct dynamic_array
3467 int count, capacity;
3468 void *items;
3471 enum pointtype {
3472 POINTTYPE_CURVE = 0,
3473 POINTTYPE_CORNER,
3474 POINTTYPE_CURVE_START,
3475 POINTTYPE_CURVE_END,
3476 POINTTYPE_CURVE_MIDDLE,
3479 struct point2d
3481 D3DXVECTOR2 pos;
3482 enum pointtype corner;
3485 /* is a dynamic_array */
3486 struct outline
3488 int count, capacity;
3489 struct point2d *items;
3492 /* is a dynamic_array */
3493 struct outline_array
3495 int count, capacity;
3496 struct outline *items;
3499 struct glyphinfo
3501 struct outline_array outlines;
3502 float offset_x;
3505 static BOOL reserve(struct dynamic_array *array, int count, int itemsize)
3507 if (count > array->capacity) {
3508 void *new_buffer;
3509 int new_capacity;
3510 if (array->items && array->capacity) {
3511 new_capacity = max(array->capacity * 2, count);
3512 new_buffer = HeapReAlloc(GetProcessHeap(), 0, array->items, new_capacity * itemsize);
3513 } else {
3514 new_capacity = max(16, count);
3515 new_buffer = HeapAlloc(GetProcessHeap(), 0, new_capacity * itemsize);
3517 if (!new_buffer)
3518 return FALSE;
3519 array->items = new_buffer;
3520 array->capacity = new_capacity;
3522 return TRUE;
3525 static struct point2d *add_point(struct outline *array)
3527 struct point2d *item;
3529 if (!reserve((struct dynamic_array *)array, array->count + 1, sizeof(array->items[0])))
3530 return NULL;
3532 item = &array->items[array->count++];
3533 ZeroMemory(item, sizeof(*item));
3534 return item;
3537 static struct outline *add_outline(struct outline_array *array)
3539 struct outline *item;
3541 if (!reserve((struct dynamic_array *)array, array->count + 1, sizeof(array->items[0])))
3542 return NULL;
3544 item = &array->items[array->count++];
3545 ZeroMemory(item, sizeof(*item));
3546 return item;
3549 static inline D3DXVECTOR2 *convert_fixed_to_float(POINTFX *pt, int count, float emsquare)
3551 D3DXVECTOR2 *ret = (D3DXVECTOR2*)pt;
3552 while (count--) {
3553 D3DXVECTOR2 *pt_flt = (D3DXVECTOR2*)pt;
3554 pt_flt->x = (pt->x.value + pt->x.fract / (float)0x10000) / emsquare;
3555 pt_flt->y = (pt->y.value + pt->y.fract / (float)0x10000) / emsquare;
3556 pt++;
3558 return ret;
3561 static HRESULT add_bezier_points(struct outline *outline, const D3DXVECTOR2 *p1,
3562 const D3DXVECTOR2 *p2, const D3DXVECTOR2 *p3,
3563 float max_deviation)
3565 D3DXVECTOR2 split1 = {0, 0}, split2 = {0, 0}, middle, vec;
3566 float deviation;
3568 D3DXVec2Scale(&split1, D3DXVec2Add(&split1, p1, p2), 0.5f);
3569 D3DXVec2Scale(&split2, D3DXVec2Add(&split2, p2, p3), 0.5f);
3570 D3DXVec2Scale(&middle, D3DXVec2Add(&middle, &split1, &split2), 0.5f);
3572 deviation = D3DXVec2Length(D3DXVec2Subtract(&vec, &middle, p2));
3573 if (deviation < max_deviation) {
3574 struct point2d *pt = add_point(outline);
3575 if (!pt) return E_OUTOFMEMORY;
3576 pt->pos = *p2;
3577 pt->corner = POINTTYPE_CURVE;
3578 /* the end point is omitted because the end line merges into the next segment of
3579 * the split bezier curve, and the end of the split bezier curve is added outside
3580 * this recursive function. */
3581 } else {
3582 HRESULT hr = add_bezier_points(outline, p1, &split1, &middle, max_deviation);
3583 if (hr != S_OK) return hr;
3584 hr = add_bezier_points(outline, &middle, &split2, p3, max_deviation);
3585 if (hr != S_OK) return hr;
3588 return S_OK;
3591 static inline BOOL is_direction_similar(D3DXVECTOR2 *dir1, D3DXVECTOR2 *dir2, float cos_theta)
3593 /* dot product = cos(theta) */
3594 return D3DXVec2Dot(dir1, dir2) > cos_theta;
3597 static inline D3DXVECTOR2 *unit_vec2(D3DXVECTOR2 *dir, const D3DXVECTOR2 *pt1, const D3DXVECTOR2 *pt2)
3599 return D3DXVec2Normalize(D3DXVec2Subtract(dir, pt2, pt1), dir);
3602 static BOOL attempt_line_merge(struct outline *outline,
3603 int pt_index,
3604 const D3DXVECTOR2 *nextpt,
3605 BOOL to_curve)
3607 D3DXVECTOR2 curdir, lastdir;
3608 struct point2d *prevpt, *pt;
3609 BOOL ret = FALSE;
3610 const float cos_half = cos(D3DXToRadian(0.5f));
3612 pt = &outline->items[pt_index];
3613 pt_index = (pt_index - 1 + outline->count) % outline->count;
3614 prevpt = &outline->items[pt_index];
3616 if (to_curve)
3617 pt->corner = pt->corner != POINTTYPE_CORNER ? POINTTYPE_CURVE_MIDDLE : POINTTYPE_CURVE_START;
3619 if (outline->count < 2)
3620 return FALSE;
3622 /* remove last point if the next line continues the last line */
3623 unit_vec2(&lastdir, &prevpt->pos, &pt->pos);
3624 unit_vec2(&curdir, &pt->pos, nextpt);
3625 if (is_direction_similar(&lastdir, &curdir, cos_half))
3627 outline->count--;
3628 if (pt->corner == POINTTYPE_CURVE_END)
3629 prevpt->corner = pt->corner;
3630 if (prevpt->corner == POINTTYPE_CURVE_END && to_curve)
3631 prevpt->corner = POINTTYPE_CURVE_MIDDLE;
3632 pt = prevpt;
3634 ret = TRUE;
3635 if (outline->count < 2)
3636 return ret;
3638 pt_index = (pt_index - 1 + outline->count) % outline->count;
3639 prevpt = &outline->items[pt_index];
3640 unit_vec2(&lastdir, &prevpt->pos, &pt->pos);
3641 unit_vec2(&curdir, &pt->pos, nextpt);
3643 return ret;
3646 static HRESULT create_outline(struct glyphinfo *glyph, void *raw_outline, int datasize,
3647 float max_deviation, float emsquare)
3649 const float cos_45 = cos(D3DXToRadian(45.0f));
3650 const float cos_90 = cos(D3DXToRadian(90.0f));
3651 TTPOLYGONHEADER *header = (TTPOLYGONHEADER *)raw_outline;
3653 while ((char *)header < (char *)raw_outline + datasize)
3655 TTPOLYCURVE *curve = (TTPOLYCURVE *)(header + 1);
3656 struct point2d *lastpt, *pt;
3657 D3DXVECTOR2 lastdir;
3658 D3DXVECTOR2 *pt_flt;
3659 int j;
3660 struct outline *outline = add_outline(&glyph->outlines);
3662 if (!outline)
3663 return E_OUTOFMEMORY;
3665 pt = add_point(outline);
3666 if (!pt)
3667 return E_OUTOFMEMORY;
3668 pt_flt = convert_fixed_to_float(&header->pfxStart, 1, emsquare);
3669 pt->pos = *pt_flt;
3670 pt->corner = POINTTYPE_CORNER;
3672 if (header->dwType != TT_POLYGON_TYPE)
3673 trace("Unknown header type %d\n", header->dwType);
3675 while ((char *)curve < (char *)header + header->cb)
3677 D3DXVECTOR2 bezier_start = outline->items[outline->count - 1].pos;
3678 BOOL to_curve = curve->wType != TT_PRIM_LINE && curve->cpfx > 1;
3680 if (!curve->cpfx) {
3681 curve = (TTPOLYCURVE *)&curve->apfx[curve->cpfx];
3682 continue;
3685 pt_flt = convert_fixed_to_float(curve->apfx, curve->cpfx, emsquare);
3687 attempt_line_merge(outline, outline->count - 1, &pt_flt[0], to_curve);
3689 if (to_curve)
3691 HRESULT hr;
3692 int count = curve->cpfx;
3693 j = 0;
3695 while (count > 2)
3697 D3DXVECTOR2 bezier_end;
3699 D3DXVec2Scale(&bezier_end, D3DXVec2Add(&bezier_end, &pt_flt[j], &pt_flt[j+1]), 0.5f);
3700 hr = add_bezier_points(outline, &bezier_start, &pt_flt[j], &bezier_end, max_deviation);
3701 if (hr != S_OK)
3702 return hr;
3703 bezier_start = bezier_end;
3704 count--;
3705 j++;
3707 hr = add_bezier_points(outline, &bezier_start, &pt_flt[j], &pt_flt[j+1], max_deviation);
3708 if (hr != S_OK)
3709 return hr;
3711 pt = add_point(outline);
3712 if (!pt)
3713 return E_OUTOFMEMORY;
3714 j++;
3715 pt->pos = pt_flt[j];
3716 pt->corner = POINTTYPE_CURVE_END;
3717 } else {
3718 for (j = 0; j < curve->cpfx; j++)
3720 pt = add_point(outline);
3721 if (!pt)
3722 return E_OUTOFMEMORY;
3723 pt->pos = pt_flt[j];
3724 pt->corner = POINTTYPE_CORNER;
3728 curve = (TTPOLYCURVE *)&curve->apfx[curve->cpfx];
3731 /* remove last point if the next line continues the last line */
3732 if (outline->count >= 3) {
3733 BOOL to_curve;
3735 lastpt = &outline->items[outline->count - 1];
3736 pt = &outline->items[0];
3737 if (pt->pos.x == lastpt->pos.x && pt->pos.y == lastpt->pos.y) {
3738 if (lastpt->corner == POINTTYPE_CURVE_END)
3740 if (pt->corner == POINTTYPE_CURVE_START)
3741 pt->corner = POINTTYPE_CURVE_MIDDLE;
3742 else
3743 pt->corner = POINTTYPE_CURVE_END;
3745 outline->count--;
3746 } else {
3747 /* outline closed with a line from end to start point */
3748 attempt_line_merge(outline, outline->count - 1, &pt->pos, FALSE);
3750 lastpt = &outline->items[0];
3751 to_curve = lastpt->corner != POINTTYPE_CORNER && lastpt->corner != POINTTYPE_CURVE_END;
3752 if (lastpt->corner == POINTTYPE_CURVE_START)
3753 lastpt->corner = POINTTYPE_CORNER;
3754 pt = &outline->items[1];
3755 if (attempt_line_merge(outline, 0, &pt->pos, to_curve))
3756 *lastpt = outline->items[outline->count];
3759 lastpt = &outline->items[outline->count - 1];
3760 pt = &outline->items[0];
3761 unit_vec2(&lastdir, &lastpt->pos, &pt->pos);
3762 for (j = 0; j < outline->count; j++)
3764 D3DXVECTOR2 curdir;
3766 lastpt = pt;
3767 pt = &outline->items[(j + 1) % outline->count];
3768 unit_vec2(&curdir, &lastpt->pos, &pt->pos);
3770 switch (lastpt->corner)
3772 case POINTTYPE_CURVE_START:
3773 case POINTTYPE_CURVE_END:
3774 if (!is_direction_similar(&lastdir, &curdir, cos_45))
3775 lastpt->corner = POINTTYPE_CORNER;
3776 break;
3777 case POINTTYPE_CURVE_MIDDLE:
3778 if (!is_direction_similar(&lastdir, &curdir, cos_90))
3779 lastpt->corner = POINTTYPE_CORNER;
3780 else
3781 lastpt->corner = POINTTYPE_CURVE;
3782 break;
3783 default:
3784 break;
3786 lastdir = curdir;
3789 header = (TTPOLYGONHEADER *)((char *)header + header->cb);
3791 return S_OK;
3794 static void free_outline(struct outline *outline)
3796 HeapFree(GetProcessHeap(), 0, outline->items);
3799 static void free_glyphinfo(struct glyphinfo *glyph)
3801 unsigned int i;
3803 for (i = 0; i < glyph->outlines.count; ++i)
3804 free_outline(&glyph->outlines.items[i]);
3805 HeapFree(GetProcessHeap(), 0, glyph->outlines.items);
3808 static void compute_text_mesh(struct mesh *mesh, const char *text,
3809 float deviation, float extrusion, float otmEMSquare, const struct glyphinfo *glyphs)
3811 DWORD nb_vertices, nb_faces;
3812 DWORD nb_corners, nb_outline_points;
3813 int textlen = 0;
3814 int i;
3815 struct vertex *vertex_ptr;
3816 face *face_ptr;
3818 textlen = strlen(text);
3820 /* corner points need an extra vertex for the different side faces normals */
3821 nb_corners = 0;
3822 nb_outline_points = 0;
3823 for (i = 0; i < textlen; i++)
3825 int j;
3826 for (j = 0; j < glyphs[i].outlines.count; j++)
3828 int k;
3829 struct outline *outline = &glyphs[i].outlines.items[j];
3830 nb_outline_points += outline->count;
3831 nb_corners++; /* first outline point always repeated as a corner */
3832 for (k = 1; k < outline->count; k++)
3833 if (outline->items[k].corner)
3834 nb_corners++;
3838 nb_vertices = (nb_outline_points + nb_corners) * 2 + textlen;
3839 nb_faces = nb_outline_points * 2;
3841 ok(new_mesh(mesh, nb_vertices, nb_faces), "Failed to create reference text mesh.\n");
3843 /* convert 2D vertices and faces into 3D mesh */
3844 vertex_ptr = mesh->vertices;
3845 face_ptr = mesh->faces;
3846 for (i = 0; i < textlen; i++)
3848 int j;
3850 /* side vertices and faces */
3851 for (j = 0; j < glyphs[i].outlines.count; j++)
3853 struct vertex *outline_vertices = vertex_ptr;
3854 struct outline *outline = &glyphs[i].outlines.items[j];
3855 int k;
3856 struct point2d *prevpt = &outline->items[outline->count - 1];
3857 struct point2d *pt = &outline->items[0];
3859 for (k = 1; k <= outline->count; k++)
3861 struct vertex vtx;
3862 struct point2d *nextpt = &outline->items[k % outline->count];
3863 WORD vtx_idx = vertex_ptr - mesh->vertices;
3864 D3DXVECTOR2 vec;
3866 if (pt->corner == POINTTYPE_CURVE_START)
3867 D3DXVec2Subtract(&vec, &pt->pos, &prevpt->pos);
3868 else if (pt->corner)
3869 D3DXVec2Subtract(&vec, &nextpt->pos, &pt->pos);
3870 else
3871 D3DXVec2Subtract(&vec, &nextpt->pos, &prevpt->pos);
3872 D3DXVec2Normalize(&vec, &vec);
3873 vtx.normal.x = -vec.y;
3874 vtx.normal.y = vec.x;
3875 vtx.normal.z = 0;
3877 vtx.position.x = pt->pos.x + glyphs[i].offset_x;
3878 vtx.position.y = pt->pos.y;
3879 vtx.position.z = 0;
3880 *vertex_ptr++ = vtx;
3882 vtx.position.z = -extrusion;
3883 *vertex_ptr++ = vtx;
3885 vtx.position.x = nextpt->pos.x + glyphs[i].offset_x;
3886 vtx.position.y = nextpt->pos.y;
3887 if (pt->corner && nextpt->corner && nextpt->corner != POINTTYPE_CURVE_END) {
3888 vtx.position.z = -extrusion;
3889 *vertex_ptr++ = vtx;
3890 vtx.position.z = 0;
3891 *vertex_ptr++ = vtx;
3893 (*face_ptr)[0] = vtx_idx;
3894 (*face_ptr)[1] = vtx_idx + 2;
3895 (*face_ptr)[2] = vtx_idx + 1;
3896 face_ptr++;
3898 (*face_ptr)[0] = vtx_idx;
3899 (*face_ptr)[1] = vtx_idx + 3;
3900 (*face_ptr)[2] = vtx_idx + 2;
3901 face_ptr++;
3902 } else {
3903 if (nextpt->corner) {
3904 if (nextpt->corner == POINTTYPE_CURVE_END) {
3905 struct point2d *nextpt2 = &outline->items[(k + 1) % outline->count];
3906 D3DXVec2Subtract(&vec, &nextpt2->pos, &nextpt->pos);
3907 } else {
3908 D3DXVec2Subtract(&vec, &nextpt->pos, &pt->pos);
3910 D3DXVec2Normalize(&vec, &vec);
3911 vtx.normal.x = -vec.y;
3912 vtx.normal.y = vec.x;
3914 vtx.position.z = 0;
3915 *vertex_ptr++ = vtx;
3916 vtx.position.z = -extrusion;
3917 *vertex_ptr++ = vtx;
3920 (*face_ptr)[0] = vtx_idx;
3921 (*face_ptr)[1] = vtx_idx + 3;
3922 (*face_ptr)[2] = vtx_idx + 1;
3923 face_ptr++;
3925 (*face_ptr)[0] = vtx_idx;
3926 (*face_ptr)[1] = vtx_idx + 2;
3927 (*face_ptr)[2] = vtx_idx + 3;
3928 face_ptr++;
3931 prevpt = pt;
3932 pt = nextpt;
3934 if (!pt->corner) {
3935 *vertex_ptr++ = *outline_vertices++;
3936 *vertex_ptr++ = *outline_vertices++;
3940 /* FIXME: compute expected faces */
3941 /* Add placeholder to separate glyph outlines */
3942 vertex_ptr->position.x = 0;
3943 vertex_ptr->position.y = 0;
3944 vertex_ptr->position.z = 0;
3945 vertex_ptr->normal.x = 0;
3946 vertex_ptr->normal.y = 0;
3947 vertex_ptr->normal.z = 1;
3948 vertex_ptr++;
3952 static void compare_text_outline_mesh(const char *name, ID3DXMesh *d3dxmesh, struct mesh *mesh,
3953 size_t textlen, float extrusion, const struct glyphinfo *glyphs)
3955 HRESULT hr;
3956 DWORD number_of_vertices, number_of_faces;
3957 IDirect3DVertexBuffer9 *vertex_buffer = NULL;
3958 IDirect3DIndexBuffer9 *index_buffer = NULL;
3959 D3DVERTEXBUFFER_DESC vertex_buffer_description;
3960 D3DINDEXBUFFER_DESC index_buffer_description;
3961 struct vertex *vertices = NULL;
3962 face *faces = NULL;
3963 int expected, i;
3964 int vtx_idx1, face_idx1, vtx_idx2, face_idx2;
3966 number_of_vertices = d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh);
3967 number_of_faces = d3dxmesh->lpVtbl->GetNumFaces(d3dxmesh);
3969 hr = d3dxmesh->lpVtbl->GetVertexBuffer(d3dxmesh, &vertex_buffer);
3970 ok(hr == D3D_OK, "Test %s, unexpected hr %#x.\n", name, hr);
3971 hr = IDirect3DVertexBuffer9_GetDesc(vertex_buffer, &vertex_buffer_description);
3972 ok(hr == D3D_OK, "Test %s, unexpected hr %#x.\n", name, hr);
3973 ok(vertex_buffer_description.Format == D3DFMT_VERTEXDATA, "Test %s, unexpected format %u.\n",
3974 name, vertex_buffer_description.Format);
3975 ok(vertex_buffer_description.Type == D3DRTYPE_VERTEXBUFFER, "Test %s, unexpected resource type %u.\n",
3976 name, vertex_buffer_description.Type);
3977 ok(!vertex_buffer_description.Usage, "Test %s, unexpected usage %#x.\n", name, vertex_buffer_description.Usage);
3978 ok(vertex_buffer_description.Pool == D3DPOOL_MANAGED, "Test %s, unexpected pool %u.\n",
3979 name, vertex_buffer_description.Pool);
3980 ok(vertex_buffer_description.FVF == mesh->fvf, "Test %s, unexpected FVF %#x (expected %#x).\n",
3981 name, vertex_buffer_description.FVF, mesh->fvf);
3982 if (!mesh->fvf)
3983 expected = number_of_vertices * mesh->vertex_size;
3984 else
3985 expected = number_of_vertices * D3DXGetFVFVertexSize(mesh->fvf);
3986 ok(vertex_buffer_description.Size == expected, "Test %s, unexpected size %u (expected %u).\n",
3987 name, vertex_buffer_description.Size, expected);
3989 hr = d3dxmesh->lpVtbl->GetIndexBuffer(d3dxmesh, &index_buffer);
3990 ok(hr == D3D_OK, "Test %s, unexpected hr %#x.\n", name, hr);
3991 hr = IDirect3DIndexBuffer9_GetDesc(index_buffer, &index_buffer_description);
3992 ok(hr == D3D_OK, "Test %s, unexpected hr %#x.\n", name, hr);
3993 ok(index_buffer_description.Format == D3DFMT_INDEX16, "Test %s, unexpected format %u.\n",
3994 name, index_buffer_description.Format);
3995 ok(index_buffer_description.Type == D3DRTYPE_INDEXBUFFER, "Test %s, unexpected resource type %u.\n",
3996 name, index_buffer_description.Type);
3997 ok(!index_buffer_description.Usage, "Test %s, unexpected usage %#x.\n",
3998 name, index_buffer_description.Usage);
3999 ok(index_buffer_description.Pool == D3DPOOL_MANAGED, "Test %s, unexpected pool %u.\n",
4000 name, index_buffer_description.Pool);
4001 expected = number_of_faces * sizeof(WORD) * 3;
4002 ok(index_buffer_description.Size == expected, "Test %s, unexpected size %u.\n",
4003 name, index_buffer_description.Size);
4005 hr = IDirect3DVertexBuffer9_Lock(vertex_buffer, 0, number_of_vertices * sizeof(D3DXVECTOR3) * 2,
4006 (void **)&vertices, D3DLOCK_DISCARD);
4007 ok(hr == D3D_OK, "Test %s, unexpected hr %#x.\n", name, hr);
4008 hr = IDirect3DIndexBuffer9_Lock(index_buffer, 0, number_of_faces * sizeof(WORD) * 3,
4009 (void **)&faces, D3DLOCK_DISCARD);
4010 ok(hr == D3D_OK, "Test %s, unexpected hr %#x.\n", name, hr);
4011 face_idx1 = 0;
4012 vtx_idx2 = 0;
4013 face_idx2 = 0;
4014 vtx_idx1 = 0;
4015 for (i = 0; i < textlen; i++)
4017 int nb_outline_vertices1, nb_outline_faces1;
4018 int nb_outline_vertices2, nb_outline_faces2;
4019 int nb_back_vertices, nb_back_faces;
4020 int first_vtx1, first_vtx2;
4021 int first_face1, first_face2;
4022 int j;
4024 first_vtx1 = vtx_idx1;
4025 first_vtx2 = vtx_idx2;
4026 /* Glyphs without outlines do not generate any vertices. */
4027 if (glyphs[i].outlines.count > 0)
4029 for (; vtx_idx1 < number_of_vertices; vtx_idx1++)
4031 if (vertices[vtx_idx1].normal.z != 0)
4032 break;
4035 for (; vtx_idx2 < mesh->number_of_vertices; vtx_idx2++)
4037 if (mesh->vertices[vtx_idx2].normal.z != 0)
4038 break;
4041 nb_outline_vertices1 = vtx_idx1 - first_vtx1;
4042 nb_outline_vertices2 = vtx_idx2 - first_vtx2;
4043 ok(nb_outline_vertices1 == nb_outline_vertices2,
4044 "Test %s, glyph %d, outline vertex count result %d, expected %d\n", name, i,
4045 nb_outline_vertices1, nb_outline_vertices2);
4047 for (j = 0; j < min(nb_outline_vertices1, nb_outline_vertices2); j++)
4049 vtx_idx1 = first_vtx1 + j;
4050 vtx_idx2 = first_vtx2 + j;
4051 ok(compare_vec3(vertices[vtx_idx1].position, mesh->vertices[vtx_idx2].position),
4052 "Test %s, glyph %d, vertex position %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1,
4053 vertices[vtx_idx1].position.x, vertices[vtx_idx1].position.y, vertices[vtx_idx1].position.z,
4054 mesh->vertices[vtx_idx2].position.x, mesh->vertices[vtx_idx2].position.y, mesh->vertices[vtx_idx2].position.z);
4055 ok(compare_vec3(vertices[vtx_idx1].normal, mesh->vertices[first_vtx2 + j].normal),
4056 "Test %s, glyph %d, vertex normal %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1,
4057 vertices[vtx_idx1].normal.x, vertices[vtx_idx1].normal.y, vertices[vtx_idx1].normal.z,
4058 mesh->vertices[vtx_idx2].normal.x, mesh->vertices[vtx_idx2].normal.y, mesh->vertices[vtx_idx2].normal.z);
4060 vtx_idx1 = first_vtx1 + nb_outline_vertices1;
4061 vtx_idx2 = first_vtx2 + nb_outline_vertices2;
4063 first_face1 = face_idx1;
4064 first_face2 = face_idx2;
4065 for (; face_idx1 < number_of_faces; face_idx1++)
4067 if (faces[face_idx1][0] >= vtx_idx1 ||
4068 faces[face_idx1][1] >= vtx_idx1 ||
4069 faces[face_idx1][2] >= vtx_idx1)
4070 break;
4072 for (; face_idx2 < mesh->number_of_faces; face_idx2++)
4074 if (mesh->faces[face_idx2][0] >= vtx_idx2 ||
4075 mesh->faces[face_idx2][1] >= vtx_idx2 ||
4076 mesh->faces[face_idx2][2] >= vtx_idx2)
4077 break;
4079 nb_outline_faces1 = face_idx1 - first_face1;
4080 nb_outline_faces2 = face_idx2 - first_face2;
4081 ok(nb_outline_faces1 == nb_outline_faces2,
4082 "Test %s, glyph %d, outline face count result %d, expected %d\n", name, i,
4083 nb_outline_faces1, nb_outline_faces2);
4085 for (j = 0; j < min(nb_outline_faces1, nb_outline_faces2); j++)
4087 face_idx1 = first_face1 + j;
4088 face_idx2 = first_face2 + j;
4089 ok(faces[face_idx1][0] - first_vtx1 == mesh->faces[face_idx2][0] - first_vtx2 &&
4090 faces[face_idx1][1] - first_vtx1 == mesh->faces[face_idx2][1] - first_vtx2 &&
4091 faces[face_idx1][2] - first_vtx1 == mesh->faces[face_idx2][2] - first_vtx2,
4092 "Test %s, glyph %d, face %d, result (%d, %d, %d), expected (%d, %d, %d)\n", name, i, face_idx1,
4093 faces[face_idx1][0], faces[face_idx1][1], faces[face_idx1][2],
4094 mesh->faces[face_idx2][0] - first_vtx2 + first_vtx1,
4095 mesh->faces[face_idx2][1] - first_vtx2 + first_vtx1,
4096 mesh->faces[face_idx2][2] - first_vtx2 + first_vtx1);
4098 face_idx1 = first_face1 + nb_outline_faces1;
4099 face_idx2 = first_face2 + nb_outline_faces2;
4101 /* partial test on back vertices and faces */
4102 first_vtx1 = vtx_idx1;
4103 for (; vtx_idx1 < number_of_vertices; vtx_idx1++) {
4104 struct vertex vtx;
4106 if (vertices[vtx_idx1].normal.z != 1.0f)
4107 break;
4109 vtx.position.z = 0.0f;
4110 vtx.normal.x = 0.0f;
4111 vtx.normal.y = 0.0f;
4112 vtx.normal.z = 1.0f;
4113 ok(compare(vertices[vtx_idx1].position.z, vtx.position.z),
4114 "Test %s, glyph %d, vertex position.z %d, result %g, expected %g\n", name, i, vtx_idx1,
4115 vertices[vtx_idx1].position.z, vtx.position.z);
4116 ok(compare_vec3(vertices[vtx_idx1].normal, vtx.normal),
4117 "Test %s, glyph %d, vertex normal %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1,
4118 vertices[vtx_idx1].normal.x, vertices[vtx_idx1].normal.y, vertices[vtx_idx1].normal.z,
4119 vtx.normal.x, vtx.normal.y, vtx.normal.z);
4121 nb_back_vertices = vtx_idx1 - first_vtx1;
4122 first_face1 = face_idx1;
4123 for (; face_idx1 < number_of_faces; face_idx1++)
4125 const D3DXVECTOR3 *vtx1, *vtx2, *vtx3;
4126 D3DXVECTOR3 normal;
4127 D3DXVECTOR3 v1 = {0, 0, 0};
4128 D3DXVECTOR3 v2 = {0, 0, 0};
4129 D3DXVECTOR3 forward = {0.0f, 0.0f, 1.0f};
4131 if (faces[face_idx1][0] >= vtx_idx1 ||
4132 faces[face_idx1][1] >= vtx_idx1 ||
4133 faces[face_idx1][2] >= vtx_idx1)
4134 break;
4136 vtx1 = &vertices[faces[face_idx1][0]].position;
4137 vtx2 = &vertices[faces[face_idx1][1]].position;
4138 vtx3 = &vertices[faces[face_idx1][2]].position;
4140 D3DXVec3Subtract(&v1, vtx2, vtx1);
4141 D3DXVec3Subtract(&v2, vtx3, vtx2);
4142 D3DXVec3Cross(&normal, &v1, &v2);
4143 D3DXVec3Normalize(&normal, &normal);
4144 ok(!D3DXVec3Length(&normal) || compare_vec3(normal, forward),
4145 "Test %s, glyph %d, face %d normal, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, face_idx1,
4146 normal.x, normal.y, normal.z, forward.x, forward.y, forward.z);
4148 nb_back_faces = face_idx1 - first_face1;
4150 /* compare front and back faces & vertices */
4151 if (extrusion == 0.0f) {
4152 /* Oddly there are only back faces in this case */
4153 nb_back_vertices /= 2;
4154 nb_back_faces /= 2;
4155 face_idx1 -= nb_back_faces;
4156 vtx_idx1 -= nb_back_vertices;
4158 for (j = 0; j < nb_back_vertices; j++)
4160 struct vertex vtx = vertices[first_vtx1];
4161 vtx.position.z = -extrusion;
4162 vtx.normal.x = 0.0f;
4163 vtx.normal.y = 0.0f;
4164 vtx.normal.z = extrusion == 0.0f ? 1.0f : -1.0f;
4165 ok(compare_vec3(vertices[vtx_idx1].position, vtx.position),
4166 "Test %s, glyph %d, vertex position %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1,
4167 vertices[vtx_idx1].position.x, vertices[vtx_idx1].position.y, vertices[vtx_idx1].position.z,
4168 vtx.position.x, vtx.position.y, vtx.position.z);
4169 ok(compare_vec3(vertices[vtx_idx1].normal, vtx.normal),
4170 "Test %s, glyph %d, vertex normal %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1,
4171 vertices[vtx_idx1].normal.x, vertices[vtx_idx1].normal.y, vertices[vtx_idx1].normal.z,
4172 vtx.normal.x, vtx.normal.y, vtx.normal.z);
4173 vtx_idx1++;
4174 first_vtx1++;
4176 for (j = 0; j < nb_back_faces; j++)
4178 int f1, f2;
4179 if (extrusion == 0.0f) {
4180 f1 = 1;
4181 f2 = 2;
4182 } else {
4183 f1 = 2;
4184 f2 = 1;
4186 ok(faces[face_idx1][0] == faces[first_face1][0] + nb_back_vertices &&
4187 faces[face_idx1][1] == faces[first_face1][f1] + nb_back_vertices &&
4188 faces[face_idx1][2] == faces[first_face1][f2] + nb_back_vertices,
4189 "Test %s, glyph %d, face %d, result (%d, %d, %d), expected (%d, %d, %d)\n", name, i, face_idx1,
4190 faces[face_idx1][0], faces[face_idx1][1], faces[face_idx1][2],
4191 faces[first_face1][0] - nb_back_faces,
4192 faces[first_face1][f1] - nb_back_faces,
4193 faces[first_face1][f2] - nb_back_faces);
4194 first_face1++;
4195 face_idx1++;
4198 /* skip to the outline for the next glyph */
4199 for (; vtx_idx2 < mesh->number_of_vertices; vtx_idx2++) {
4200 if (mesh->vertices[vtx_idx2].normal.z == 0)
4201 break;
4203 for (; face_idx2 < mesh->number_of_faces; face_idx2++)
4205 if (mesh->faces[face_idx2][0] >= vtx_idx2 ||
4206 mesh->faces[face_idx2][1] >= vtx_idx2 ||
4207 mesh->faces[face_idx2][2] >= vtx_idx2) break;
4211 IDirect3DIndexBuffer9_Unlock(index_buffer);
4212 IDirect3DVertexBuffer9_Unlock(vertex_buffer);
4213 IDirect3DIndexBuffer9_Release(index_buffer);
4214 IDirect3DVertexBuffer9_Release(vertex_buffer);
4217 static void test_createtext(IDirect3DDevice9 *device, HDC hdc, const char *text, float deviation, float extrusion)
4219 static const MAT2 identity = {{0, 1}, {0, 0}, {0, 0}, {0, 1}};
4220 HRESULT hr;
4221 ID3DXMesh *d3dxmesh = NULL;
4222 struct mesh mesh = {0};
4223 char name[256];
4224 OUTLINETEXTMETRICA otm;
4225 GLYPHMETRICS gm;
4226 struct glyphinfo *glyphs;
4227 GLYPHMETRICSFLOAT *glyphmetrics_float = HeapAlloc(GetProcessHeap(), 0, sizeof(GLYPHMETRICSFLOAT) * strlen(text));
4228 int i;
4229 LOGFONTA lf;
4230 float offset_x;
4231 size_t textlen;
4232 HFONT font = NULL, oldfont = NULL;
4233 char *raw_outline;
4235 sprintf(name, "text ('%s', %f, %f)", text, deviation, extrusion);
4237 hr = D3DXCreateTextA(device, hdc, text, deviation, extrusion, &d3dxmesh, NULL, glyphmetrics_float);
4238 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
4240 /* must select a modified font having lfHeight = otm.otmEMSquare before
4241 * calling GetGlyphOutline to get the expected values */
4242 ok(GetObjectA(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf), "Failed to get current DC font.\n");
4243 ok(GetOutlineTextMetricsA(hdc, sizeof(otm), &otm), "Failed to get DC font outline.\n");
4244 lf.lfHeight = otm.otmEMSquare;
4245 lf.lfWidth = 0;
4246 ok(!!(font = CreateFontIndirectA(&lf)), "Failed to create font.\n");
4248 textlen = strlen(text);
4249 glyphs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, textlen * sizeof(*glyphs));
4250 oldfont = SelectObject(hdc, font);
4252 for (i = 0; i < textlen; i++)
4254 GetGlyphOutlineA(hdc, text[i], GGO_NATIVE, &gm, 0, NULL, &identity);
4255 compare_float(glyphmetrics_float[i].gmfBlackBoxX, gm.gmBlackBoxX / (float)otm.otmEMSquare);
4256 compare_float(glyphmetrics_float[i].gmfBlackBoxY, gm.gmBlackBoxY / (float)otm.otmEMSquare);
4257 compare_float(glyphmetrics_float[i].gmfptGlyphOrigin.x, gm.gmptGlyphOrigin.x / (float)otm.otmEMSquare);
4258 compare_float(glyphmetrics_float[i].gmfptGlyphOrigin.y, gm.gmptGlyphOrigin.y / (float)otm.otmEMSquare);
4259 compare_float(glyphmetrics_float[i].gmfCellIncX, gm.gmCellIncX / (float)otm.otmEMSquare);
4260 compare_float(glyphmetrics_float[i].gmfCellIncY, gm.gmCellIncY / (float)otm.otmEMSquare);
4263 if (deviation == 0.0f)
4264 deviation = 1.0f / otm.otmEMSquare;
4266 offset_x = 0.0f;
4267 for (i = 0; i < textlen; i++)
4269 DWORD datasize;
4271 glyphs[i].offset_x = offset_x;
4273 datasize = GetGlyphOutlineA(hdc, text[i], GGO_NATIVE, &gm, 0, NULL, &identity);
4274 ok(datasize != GDI_ERROR, "Failed to retrieve GDI glyph outline size.\n");
4275 raw_outline = HeapAlloc(GetProcessHeap(), 0, datasize);
4276 datasize = GetGlyphOutlineA(hdc, text[i], GGO_NATIVE, &gm, datasize, raw_outline, &identity);
4277 ok(datasize != GDI_ERROR, "Failed to retrieve GDI glyph outline.\n");
4278 create_outline(&glyphs[i], raw_outline, datasize, deviation, otm.otmEMSquare);
4279 HeapFree(GetProcessHeap(), 0, raw_outline);
4281 offset_x += gm.gmCellIncX / (float)otm.otmEMSquare;
4284 SelectObject(hdc, oldfont);
4286 compute_text_mesh(&mesh, text, deviation, extrusion, otm.otmEMSquare, glyphs);
4287 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
4289 compare_text_outline_mesh(name, d3dxmesh, &mesh, textlen, extrusion, glyphs);
4291 free_mesh(&mesh);
4292 d3dxmesh->lpVtbl->Release(d3dxmesh);
4293 DeleteObject(font);
4294 HeapFree(GetProcessHeap(), 0, glyphmetrics_float);
4296 for (i = 0; i < textlen; i++)
4297 free_glyphinfo(&glyphs[i]);
4298 HeapFree(GetProcessHeap(), 0, glyphs);
4301 static void D3DXCreateTextTest(void)
4303 HRESULT hr;
4304 HDC hdc;
4305 IDirect3DDevice9* device;
4306 ID3DXMesh* d3dxmesh = NULL;
4307 HFONT hFont;
4308 OUTLINETEXTMETRICA otm;
4309 int number_of_vertices;
4310 int number_of_faces;
4311 struct test_context *test_context;
4313 if (!(test_context = new_test_context()))
4315 skip("Couldn't create test context\n");
4316 return;
4318 device = test_context->device;
4320 hdc = CreateCompatibleDC(NULL);
4322 hFont = CreateFontA(12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
4323 CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, "Arial");
4324 SelectObject(hdc, hFont);
4325 GetOutlineTextMetricsA(hdc, sizeof(otm), &otm);
4327 hr = D3DXCreateTextA(device, hdc, "wine", 0.001f, 0.4f, NULL, NULL, NULL);
4328 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4330 /* D3DXCreateTextA page faults from passing NULL text */
4332 hr = D3DXCreateTextW(device, hdc, NULL, 0.001f, 0.4f, &d3dxmesh, NULL, NULL);
4333 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4335 hr = D3DXCreateTextA(device, hdc, "", 0.001f, 0.4f, &d3dxmesh, NULL, NULL);
4336 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4338 hr = D3DXCreateTextA(device, hdc, " ", 0.001f, 0.4f, &d3dxmesh, NULL, NULL);
4339 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4341 hr = D3DXCreateTextA(NULL, hdc, "wine", 0.001f, 0.4f, &d3dxmesh, NULL, NULL);
4342 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4344 hr = D3DXCreateTextA(device, NULL, "wine", 0.001f, 0.4f, &d3dxmesh, NULL, NULL);
4345 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4347 hr = D3DXCreateTextA(device, hdc, "wine", -FLT_MIN, 0.4f, &d3dxmesh, NULL, NULL);
4348 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4350 hr = D3DXCreateTextA(device, hdc, "wine", 0.001f, -FLT_MIN, &d3dxmesh, NULL, NULL);
4351 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4353 /* deviation = 0.0f treated as if deviation = 1.0f / otm.otmEMSquare */
4354 hr = D3DXCreateTextA(device, hdc, "wine", 1.0f / otm.otmEMSquare, 0.4f, &d3dxmesh, NULL, NULL);
4355 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
4356 number_of_vertices = d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh);
4357 number_of_faces = d3dxmesh->lpVtbl->GetNumFaces(d3dxmesh);
4358 d3dxmesh->lpVtbl->Release(d3dxmesh);
4360 hr = D3DXCreateTextA(device, hdc, "wine", 0.0f, 0.4f, &d3dxmesh, NULL, NULL);
4361 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
4362 ok(number_of_vertices == d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh),
4363 "Got %d vertices, expected %d\n",
4364 d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh), number_of_vertices);
4365 ok(number_of_faces == d3dxmesh->lpVtbl->GetNumFaces(d3dxmesh),
4366 "Got %d faces, expected %d\n",
4367 d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh), number_of_faces);
4368 d3dxmesh->lpVtbl->Release(d3dxmesh);
4370 if (0)
4372 /* too much detail requested, so will appear to hang */
4373 trace("Waiting for D3DXCreateText to finish with deviation = FLT_MIN ...\n");
4374 hr = D3DXCreateTextA(device, hdc, "wine", FLT_MIN, 0.4f, &d3dxmesh, NULL, NULL);
4375 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
4376 if (SUCCEEDED(hr) && d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh);
4377 trace("D3DXCreateText finish with deviation = FLT_MIN\n");
4380 hr = D3DXCreateTextA(device, hdc, "wine", 0.001f, 0.4f, &d3dxmesh, NULL, NULL);
4381 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
4382 if (SUCCEEDED(hr) && d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh);
4384 test_createtext(device, hdc, "wine", FLT_MAX, 0.4f);
4385 test_createtext(device, hdc, "wine", 0.001f, FLT_MIN);
4386 test_createtext(device, hdc, "wine", 0.001f, 0.0f);
4387 test_createtext(device, hdc, "wine", 0.001f, FLT_MAX);
4388 test_createtext(device, hdc, "wine", 0.0f, 1.0f);
4389 test_createtext(device, hdc, " wine", 1.0f, 0.0f);
4390 test_createtext(device, hdc, "wine ", 1.0f, 0.0f);
4391 test_createtext(device, hdc, "wi ne", 1.0f, 0.0f);
4393 DeleteDC(hdc);
4394 DeleteObject(hFont);
4396 free_test_context(test_context);
4399 static void test_get_decl_length(void)
4401 static const D3DVERTEXELEMENT9 declaration1[] =
4403 {0, 0, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4404 {1, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4405 {2, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4406 {3, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4407 {4, 0, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4408 {5, 0, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4409 {6, 0, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4410 {7, 0, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4411 {8, 0, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4412 {9, 0, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4413 {10, 0, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4414 {11, 0, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4415 {12, 0, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4416 {13, 0, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4417 {14, 0, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4418 D3DDECL_END(),
4420 static const D3DVERTEXELEMENT9 declaration2[] =
4422 {0, 8, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4423 {1, 8, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4424 {2, 8, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4425 {3, 8, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4426 {4, 8, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4427 {5, 8, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4428 {6, 8, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4429 {7, 8, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4430 {0, 8, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4431 {1, 8, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4432 {2, 8, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4433 {3, 8, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4434 {4, 8, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4435 {5, 8, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4436 {6, 8, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4437 {7, 8, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4438 D3DDECL_END(),
4440 UINT size;
4442 size = D3DXGetDeclLength(declaration1);
4443 ok(size == 15, "Got size %u, expected 15.\n", size);
4445 size = D3DXGetDeclLength(declaration2);
4446 ok(size == 16, "Got size %u, expected 16.\n", size);
4449 static void test_get_decl_vertex_size(void)
4451 static const D3DVERTEXELEMENT9 declaration1[] =
4453 {0, 0, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4454 {1, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4455 {2, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4456 {3, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4457 {4, 0, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4458 {5, 0, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4459 {6, 0, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4460 {7, 0, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4461 {8, 0, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4462 {9, 0, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4463 {10, 0, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4464 {11, 0, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4465 {12, 0, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4466 {13, 0, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4467 {14, 0, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4468 D3DDECL_END(),
4470 static const D3DVERTEXELEMENT9 declaration2[] =
4472 {0, 8, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4473 {1, 8, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4474 {2, 8, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4475 {3, 8, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4476 {4, 8, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4477 {5, 8, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4478 {6, 8, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4479 {7, 8, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4480 {0, 8, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4481 {1, 8, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4482 {2, 8, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4483 {3, 8, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4484 {4, 8, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4485 {5, 8, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4486 {6, 8, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4487 {7, 8, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4488 D3DDECL_END(),
4490 static const UINT sizes1[] =
4492 4, 8, 12, 16,
4493 4, 4, 4, 8,
4494 4, 4, 8, 4,
4495 4, 4, 8, 0,
4497 static const UINT sizes2[] =
4499 12, 16, 20, 24,
4500 12, 12, 16, 16,
4502 unsigned int i;
4503 UINT size;
4505 size = D3DXGetDeclVertexSize(NULL, 0);
4506 ok(size == 0, "Got size %#x, expected 0.\n", size);
4508 for (i = 0; i < 16; ++i)
4510 size = D3DXGetDeclVertexSize(declaration1, i);
4511 ok(size == sizes1[i], "Got size %u for stream %u, expected %u.\n", size, i, sizes1[i]);
4514 for (i = 0; i < 8; ++i)
4516 size = D3DXGetDeclVertexSize(declaration2, i);
4517 ok(size == sizes2[i], "Got size %u for stream %u, expected %u.\n", size, i, sizes2[i]);
4521 static void D3DXGenerateAdjacencyTest(void)
4523 HRESULT hr;
4524 IDirect3DDevice9 *device;
4525 ID3DXMesh *d3dxmesh = NULL;
4526 D3DXVECTOR3 *vertices = NULL;
4527 WORD *indices = NULL;
4528 int i;
4529 struct {
4530 DWORD num_vertices;
4531 D3DXVECTOR3 vertices[6];
4532 DWORD num_faces;
4533 WORD indices[3 * 3];
4534 FLOAT epsilon;
4535 DWORD adjacency[3 * 3];
4536 } test_data[] = {
4537 { /* for epsilon < 0, indices must match for faces to be adjacent */
4538 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}},
4539 2, {0, 1, 2, 0, 2, 3},
4540 -1.0,
4541 {-1, -1, 1, 0, -1, -1},
4544 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}},
4545 2, {0, 1, 2, 3, 4, 5},
4546 -1.0,
4547 {-1, -1, -1, -1, -1, -1},
4549 { /* for epsilon == 0, indices or vertices must match for faces to be adjacent */
4550 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}},
4551 2, {0, 1, 2, 3, 4, 5},
4552 0.0,
4553 {-1, -1, 1, 0, -1, -1},
4555 { /* for epsilon > 0, vertices must be less than (but NOT equal to) epsilon distance away */
4556 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}},
4557 2, {0, 1, 2, 3, 4, 5},
4558 0.25,
4559 {-1, -1, -1, -1, -1, -1},
4561 { /* for epsilon > 0, vertices must be less than (but NOT equal to) epsilon distance away */
4562 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}},
4563 2, {0, 1, 2, 3, 4, 5},
4564 0.250001,
4565 {-1, -1, 1, 0, -1, -1},
4567 { /* length between vertices are compared to epsilon, not the individual dimension deltas */
4568 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}},
4569 2, {0, 1, 2, 3, 4, 5},
4570 0.353, /* < sqrt(0.25*0.25 + 0.25*0.25) */
4571 {-1, -1, -1, -1, -1, -1},
4574 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}},
4575 2, {0, 1, 2, 3, 4, 5},
4576 0.354, /* > sqrt(0.25*0.25 + 0.25*0.25) */
4577 {-1, -1, 1, 0, -1, -1},
4579 { /* adjacent faces must have opposite winding orders at the shared edge */
4580 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}},
4581 2, {0, 1, 2, 0, 3, 2},
4582 0.0,
4583 {-1, -1, -1, -1, -1, -1},
4586 struct test_context *test_context;
4588 if (!(test_context = new_test_context()))
4590 skip("Couldn't create test context\n");
4591 return;
4593 device = test_context->device;
4595 for (i = 0; i < ARRAY_SIZE(test_data); i++)
4597 DWORD adjacency[ARRAY_SIZE(test_data[0].adjacency)];
4598 int j;
4600 if (d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh);
4601 d3dxmesh = NULL;
4603 hr = D3DXCreateMeshFVF(test_data[i].num_faces, test_data[i].num_vertices, 0, D3DFVF_XYZ, device, &d3dxmesh);
4604 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
4606 hr = d3dxmesh->lpVtbl->LockVertexBuffer(d3dxmesh, D3DLOCK_DISCARD, (void**)&vertices);
4607 ok(hr == D3D_OK, "test %d: Got result %x, expected %x (D3D_OK)\n", i, hr, D3D_OK);
4608 if (FAILED(hr)) continue;
4609 CopyMemory(vertices, test_data[i].vertices, test_data[i].num_vertices * sizeof(test_data[0].vertices[0]));
4610 d3dxmesh->lpVtbl->UnlockVertexBuffer(d3dxmesh);
4612 hr = d3dxmesh->lpVtbl->LockIndexBuffer(d3dxmesh, D3DLOCK_DISCARD, (void**)&indices);
4613 ok(hr == D3D_OK, "test %d: Got result %x, expected %x (D3D_OK)\n", i, hr, D3D_OK);
4614 if (FAILED(hr)) continue;
4615 CopyMemory(indices, test_data[i].indices, test_data[i].num_faces * 3 * sizeof(test_data[0].indices[0]));
4616 d3dxmesh->lpVtbl->UnlockIndexBuffer(d3dxmesh);
4618 if (i == 0) {
4619 hr = d3dxmesh->lpVtbl->GenerateAdjacency(d3dxmesh, 0.0f, NULL);
4620 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4623 hr = d3dxmesh->lpVtbl->GenerateAdjacency(d3dxmesh, test_data[i].epsilon, adjacency);
4624 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
4625 if (FAILED(hr)) continue;
4627 for (j = 0; j < test_data[i].num_faces * 3; j++)
4628 ok(adjacency[j] == test_data[i].adjacency[j],
4629 "Test %d adjacency %d: Got result %u, expected %u\n", i, j,
4630 adjacency[j], test_data[i].adjacency[j]);
4632 if (d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh);
4634 free_test_context(test_context);
4637 static void test_update_semantics(void)
4639 HRESULT hr;
4640 struct test_context *test_context = NULL;
4641 ID3DXMesh *mesh = NULL;
4642 D3DVERTEXELEMENT9 declaration0[] =
4644 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4645 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4646 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4647 D3DDECL_END()
4649 D3DVERTEXELEMENT9 declaration_pos_type_color[] =
4651 {0, 0, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4652 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4653 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4654 D3DDECL_END()
4656 D3DVERTEXELEMENT9 declaration_smaller[] =
4658 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4659 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4660 D3DDECL_END()
4662 D3DVERTEXELEMENT9 declaration_larger[] =
4664 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4665 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4666 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4667 {0, 40, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT, 0},
4668 D3DDECL_END()
4670 D3DVERTEXELEMENT9 declaration_multiple_streams[] =
4672 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4673 {1, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT, 0},
4674 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4675 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4677 D3DDECL_END()
4679 D3DVERTEXELEMENT9 declaration_double_usage[] =
4681 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4682 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4683 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4684 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4685 D3DDECL_END()
4687 D3DVERTEXELEMENT9 declaration_undefined_type[] =
4689 {0, 0, D3DDECLTYPE_UNUSED+1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4690 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4691 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4692 D3DDECL_END()
4694 D3DVERTEXELEMENT9 declaration_not_4_byte_aligned_offset[] =
4696 {0, 3, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4697 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4698 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4699 D3DDECL_END()
4701 static const struct
4703 D3DXVECTOR3 position0;
4704 D3DXVECTOR3 position1;
4705 D3DXVECTOR3 normal;
4706 DWORD color;
4708 vertices[] =
4710 { { 0.0f, 1.0f, 0.f}, { 1.0f, 0.0f, 0.f}, {0.0f, 0.0f, 1.0f}, 0xffff0000 },
4711 { { 1.0f, -1.0f, 0.f}, {-1.0f, -1.0f, 0.f}, {0.0f, 0.0f, 1.0f}, 0xff00ff00 },
4712 { {-1.0f, -1.0f, 0.f}, {-1.0f, 1.0f, 0.f}, {0.0f, 0.0f, 1.0f}, 0xff0000ff },
4714 unsigned int faces[] = {0, 1, 2};
4715 unsigned int attributes[] = {0};
4716 unsigned int num_faces = ARRAY_SIZE(faces) / 3;
4717 unsigned int num_vertices = ARRAY_SIZE(vertices);
4718 int offset = sizeof(D3DXVECTOR3);
4719 DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
4720 void *vertex_buffer;
4721 void *index_buffer;
4722 DWORD *attributes_buffer;
4723 D3DVERTEXELEMENT9 declaration[MAX_FVF_DECL_SIZE];
4724 D3DVERTEXELEMENT9 *decl_ptr;
4725 DWORD exp_vertex_size = sizeof(*vertices);
4726 DWORD vertex_size = 0;
4727 int equal;
4728 int i = 0;
4729 int *decl_mem;
4730 int filler_a = 0xaaaaaaaa;
4731 int filler_b = 0xbbbbbbbb;
4733 test_context = new_test_context();
4734 if (!test_context)
4736 skip("Couldn't create a test_context\n");
4737 goto cleanup;
4740 hr = D3DXCreateMesh(num_faces, num_vertices, options, declaration0,
4741 test_context->device, &mesh);
4742 if (FAILED(hr))
4744 skip("Couldn't create test mesh %#x\n", hr);
4745 goto cleanup;
4748 mesh->lpVtbl->LockVertexBuffer(mesh, 0, &vertex_buffer);
4749 memcpy(vertex_buffer, vertices, sizeof(vertices));
4750 mesh->lpVtbl->UnlockVertexBuffer(mesh);
4752 mesh->lpVtbl->LockIndexBuffer(mesh, 0, &index_buffer);
4753 memcpy(index_buffer, faces, sizeof(faces));
4754 mesh->lpVtbl->UnlockIndexBuffer(mesh);
4756 mesh->lpVtbl->LockAttributeBuffer(mesh, 0, &attributes_buffer);
4757 memcpy(attributes_buffer, attributes, sizeof(attributes));
4758 mesh->lpVtbl->UnlockAttributeBuffer(mesh);
4760 /* Get the declaration and try to change it */
4761 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4762 if (FAILED(hr))
4764 skip("Couldn't get vertex declaration %#x\n", hr);
4765 goto cleanup;
4767 equal = memcmp(declaration, declaration0, sizeof(declaration0));
4768 ok(equal == 0, "Vertex declarations were not equal\n");
4770 for (decl_ptr = declaration; decl_ptr->Stream != 0xFF; decl_ptr++)
4772 if (decl_ptr->Usage == D3DDECLUSAGE_POSITION)
4774 /* Use second vertex position instead of first */
4775 decl_ptr->Offset = offset;
4779 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration);
4780 ok(hr == D3D_OK, "Test UpdateSemantics, got %#x expected %#x\n", hr, D3D_OK);
4782 /* Check that declaration was written by getting it again */
4783 memset(declaration, 0, sizeof(declaration));
4784 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4785 if (FAILED(hr))
4787 skip("Couldn't get vertex declaration %#x\n", hr);
4788 goto cleanup;
4791 for (decl_ptr = declaration; decl_ptr->Stream != 0xFF; decl_ptr++)
4793 if (decl_ptr->Usage == D3DDECLUSAGE_POSITION)
4795 ok(decl_ptr->Offset == offset, "Test UpdateSemantics, got offset %d expected %d\n",
4796 decl_ptr->Offset, offset);
4800 /* Check that GetDeclaration only writes up to the D3DDECL_END() marker and
4801 * not the full MAX_FVF_DECL_SIZE elements.
4803 memset(declaration, filler_a, sizeof(declaration));
4804 memcpy(declaration, declaration0, sizeof(declaration0));
4805 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration);
4806 ok(hr == D3D_OK, "Test UpdateSemantics, "
4807 "got %#x expected D3D_OK\n", hr);
4808 memset(declaration, filler_b, sizeof(declaration));
4809 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4810 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4811 decl_mem = (int*)declaration;
4812 for (i = sizeof(declaration0)/sizeof(*decl_mem); i < sizeof(declaration)/sizeof(*decl_mem); i++)
4814 equal = memcmp(&decl_mem[i], &filler_b, sizeof(filler_b));
4815 ok(equal == 0,
4816 "GetDeclaration wrote past the D3DDECL_END() marker. "
4817 "Got %#x, expected %#x\n", decl_mem[i], filler_b);
4818 if (equal != 0) break;
4821 /* UpdateSemantics does not check for overlapping fields */
4822 memset(declaration, 0, sizeof(declaration));
4823 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4824 if (FAILED(hr))
4826 skip("Couldn't get vertex declaration %#x\n", hr);
4827 goto cleanup;
4830 for (decl_ptr = declaration; decl_ptr->Stream != 0xFF; decl_ptr++)
4832 if (decl_ptr->Type == D3DDECLTYPE_FLOAT3)
4834 decl_ptr->Type = D3DDECLTYPE_FLOAT4;
4838 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration);
4839 ok(hr == D3D_OK, "Test UpdateSemantics for overlapping fields, "
4840 "got %#x expected D3D_OK\n", hr);
4842 /* Set the position type to color instead of float3 */
4843 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_pos_type_color);
4844 ok(hr == D3D_OK, "Test UpdateSemantics position type color, "
4845 "got %#x expected D3D_OK\n", hr);
4847 /* The following test cases show that NULL, smaller or larger declarations,
4848 * and declarations with non-zero Stream values are not accepted.
4849 * UpdateSemantics returns D3DERR_INVALIDCALL and the previously set
4850 * declaration will be used by DrawSubset, GetNumBytesPerVertex, and
4851 * GetDeclaration.
4854 /* Null declaration (invalid declaration) */
4855 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4856 hr = mesh->lpVtbl->UpdateSemantics(mesh, NULL);
4857 ok(hr == D3DERR_INVALIDCALL, "Test UpdateSemantics null pointer declaration, "
4858 "got %#x expected D3DERR_INVALIDCALL\n", hr);
4859 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4860 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4861 vertex_size, exp_vertex_size);
4862 memset(declaration, 0, sizeof(declaration));
4863 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4864 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4865 equal = memcmp(declaration, declaration0, sizeof(declaration0));
4866 ok(equal == 0, "Vertex declarations were not equal\n");
4868 /* Smaller vertex declaration (invalid declaration) */
4869 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4870 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_smaller);
4871 ok(hr == D3DERR_INVALIDCALL, "Test UpdateSemantics for smaller vertex declaration, "
4872 "got %#x expected D3DERR_INVALIDCALL\n", hr);
4873 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4874 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4875 vertex_size, exp_vertex_size);
4876 memset(declaration, 0, sizeof(declaration));
4877 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4878 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4879 equal = memcmp(declaration, declaration0, sizeof(declaration0));
4880 ok(equal == 0, "Vertex declarations were not equal\n");
4882 /* Larger vertex declaration (invalid declaration) */
4883 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4884 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_larger);
4885 ok(hr == D3DERR_INVALIDCALL, "Test UpdateSemantics for larger vertex declaration, "
4886 "got %#x expected D3DERR_INVALIDCALL\n", hr);
4887 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4888 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4889 vertex_size, exp_vertex_size);
4890 memset(declaration, 0, sizeof(declaration));
4891 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4892 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4893 equal = memcmp(declaration, declaration0, sizeof(declaration0));
4894 ok(equal == 0, "Vertex declarations were not equal\n");
4896 /* Use multiple streams and keep the same vertex size (invalid declaration) */
4897 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4898 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_multiple_streams);
4899 ok(hr == D3DERR_INVALIDCALL, "Test UpdateSemantics using multiple streams, "
4900 "got %#x expected D3DERR_INVALIDCALL\n", hr);
4901 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4902 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4903 vertex_size, exp_vertex_size);
4904 memset(declaration, 0, sizeof(declaration));
4905 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4906 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4907 equal = memcmp(declaration, declaration0, sizeof(declaration0));
4908 ok(equal == 0, "Vertex declarations were not equal\n");
4910 /* The next following test cases show that some invalid declarations are
4911 * accepted with a D3D_OK. An access violation is thrown on Windows if
4912 * DrawSubset is called. The methods GetNumBytesPerVertex and GetDeclaration
4913 * are not affected, which indicates that the declaration is cached.
4916 /* Double usage (invalid declaration) */
4917 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4918 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_double_usage);
4919 ok(hr == D3D_OK, "Test UpdateSemantics double usage, "
4920 "got %#x expected D3D_OK\n", hr);
4921 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4922 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4923 vertex_size, exp_vertex_size);
4924 memset(declaration, 0, sizeof(declaration));
4925 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4926 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4927 equal = memcmp(declaration, declaration_double_usage, sizeof(declaration_double_usage));
4928 ok(equal == 0, "Vertex declarations were not equal\n");
4930 /* Set the position to an undefined type (invalid declaration) */
4931 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4932 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_undefined_type);
4933 ok(hr == D3D_OK, "Test UpdateSemantics undefined type, "
4934 "got %#x expected D3D_OK\n", hr);
4935 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4936 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4937 vertex_size, exp_vertex_size);
4938 memset(declaration, 0, sizeof(declaration));
4939 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4940 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4941 equal = memcmp(declaration, declaration_undefined_type, sizeof(declaration_undefined_type));
4942 ok(equal == 0, "Vertex declarations were not equal\n");
4944 /* Use a not 4 byte aligned offset (invalid declaration) */
4945 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4946 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_not_4_byte_aligned_offset);
4947 ok(hr == D3D_OK, "Test UpdateSemantics not 4 byte aligned offset, "
4948 "got %#x expected D3D_OK\n", hr);
4949 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4950 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4951 vertex_size, exp_vertex_size);
4952 memset(declaration, 0, sizeof(declaration));
4953 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4954 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4955 equal = memcmp(declaration, declaration_not_4_byte_aligned_offset,
4956 sizeof(declaration_not_4_byte_aligned_offset));
4957 ok(equal == 0, "Vertex declarations were not equal\n");
4959 cleanup:
4960 if (mesh)
4961 mesh->lpVtbl->Release(mesh);
4963 free_test_context(test_context);
4966 static void test_create_skin_info(void)
4968 HRESULT hr;
4969 ID3DXSkinInfo *skininfo = NULL;
4970 D3DVERTEXELEMENT9 empty_declaration[] = { D3DDECL_END() };
4971 D3DVERTEXELEMENT9 declaration_out[MAX_FVF_DECL_SIZE];
4972 const D3DVERTEXELEMENT9 declaration_with_nonzero_stream[] = {
4973 {1, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
4974 D3DDECL_END()
4977 hr = D3DXCreateSkinInfo(0, empty_declaration, 0, &skininfo);
4978 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4979 if (skininfo) IUnknown_Release(skininfo);
4980 skininfo = NULL;
4982 hr = D3DXCreateSkinInfo(1, NULL, 1, &skininfo);
4983 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4985 hr = D3DXCreateSkinInfo(1, declaration_with_nonzero_stream, 1, &skininfo);
4986 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4988 hr = D3DXCreateSkinInfoFVF(1, 0, 1, &skininfo);
4989 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4990 if (skininfo)
4992 DWORD dword_result;
4993 float flt_result;
4994 const char *string_result;
4995 D3DXMATRIX *transform;
4996 D3DXMATRIX identity_matrix;
4998 /* test initial values */
4999 hr = skininfo->lpVtbl->GetDeclaration(skininfo, declaration_out);
5000 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5001 if (SUCCEEDED(hr))
5002 compare_elements(declaration_out, empty_declaration, __LINE__, 0);
5004 dword_result = skininfo->lpVtbl->GetNumBones(skininfo);
5005 ok(dword_result == 1, "Expected 1, got %u\n", dword_result);
5007 flt_result = skininfo->lpVtbl->GetMinBoneInfluence(skininfo);
5008 ok(flt_result == 0.0f, "Expected 0.0, got %g\n", flt_result);
5010 string_result = skininfo->lpVtbl->GetBoneName(skininfo, 0);
5011 ok(string_result == NULL, "Expected NULL, got %p\n", string_result);
5013 dword_result = skininfo->lpVtbl->GetFVF(skininfo);
5014 ok(dword_result == 0, "Expected 0, got %u\n", dword_result);
5016 dword_result = skininfo->lpVtbl->GetNumBoneInfluences(skininfo, 0);
5017 ok(dword_result == 0, "Expected 0, got %u\n", dword_result);
5019 dword_result = skininfo->lpVtbl->GetNumBoneInfluences(skininfo, 1);
5020 ok(dword_result == 0, "Expected 0, got %u\n", dword_result);
5022 transform = skininfo->lpVtbl->GetBoneOffsetMatrix(skininfo, -1);
5023 ok(transform == NULL, "Expected NULL, got %p\n", transform);
5026 /* test [GS]etBoneOffsetMatrix */
5027 hr = skininfo->lpVtbl->SetBoneOffsetMatrix(skininfo, 1, &identity_matrix);
5028 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5030 hr = skininfo->lpVtbl->SetBoneOffsetMatrix(skininfo, 0, NULL);
5031 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5033 D3DXMatrixIdentity(&identity_matrix);
5034 hr = skininfo->lpVtbl->SetBoneOffsetMatrix(skininfo, 0, &identity_matrix);
5035 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5037 transform = skininfo->lpVtbl->GetBoneOffsetMatrix(skininfo, 0);
5038 check_matrix(transform, &identity_matrix);
5042 /* test [GS]etBoneName */
5043 const char *name_in = "testBoneName";
5044 const char *string_result2;
5046 hr = skininfo->lpVtbl->SetBoneName(skininfo, 1, name_in);
5047 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5049 hr = skininfo->lpVtbl->SetBoneName(skininfo, 0, NULL);
5050 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5052 hr = skininfo->lpVtbl->SetBoneName(skininfo, 0, name_in);
5053 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5055 string_result = skininfo->lpVtbl->GetBoneName(skininfo, 0);
5056 ok(string_result != NULL, "Expected non-NULL string, got %p\n", string_result);
5057 ok(!strcmp(string_result, name_in), "Expected '%s', got '%s'\n", name_in, string_result);
5059 string_result2 = skininfo->lpVtbl->GetBoneName(skininfo, 0);
5060 ok(string_result == string_result2, "Expected %p, got %p\n", string_result, string_result2);
5062 string_result = skininfo->lpVtbl->GetBoneName(skininfo, 1);
5063 ok(string_result == NULL, "Expected NULL, got %p\n", string_result);
5067 /* test [GS]etBoneInfluence */
5068 DWORD vertices[2];
5069 FLOAT weights[2];
5070 int i;
5071 DWORD num_influences;
5072 DWORD exp_vertices[2];
5073 FLOAT exp_weights[2];
5075 /* vertex and weight arrays untouched when num_influences is 0 */
5076 vertices[0] = 0xdeadbeef;
5077 weights[0] = FLT_MAX;
5078 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, vertices, weights);
5079 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5080 ok(vertices[0] == 0xdeadbeef, "expected 0xdeadbeef, got %#x\n", vertices[0]);
5081 ok(weights[0] == FLT_MAX, "expected %g, got %g\n", FLT_MAX, weights[0]);
5083 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 1, vertices, weights);
5084 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5086 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, NULL, NULL);
5087 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5089 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, vertices, NULL);
5090 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5092 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, NULL, weights);
5093 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5096 /* no vertex or weight value checking */
5097 exp_vertices[0] = 0;
5098 exp_vertices[1] = 0x87654321;
5099 exp_weights[0] = 0.5;
5100 exp_weights[1] = NAN;
5101 num_influences = 2;
5103 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 1, num_influences, vertices, weights);
5104 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5106 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, num_influences, NULL, weights);
5107 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5109 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, num_influences, vertices, NULL);
5110 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5112 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, num_influences, NULL, NULL);
5113 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5115 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, num_influences, exp_vertices, exp_weights);
5116 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5118 memset(vertices, 0, sizeof(vertices));
5119 memset(weights, 0, sizeof(weights));
5120 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, vertices, weights);
5121 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5122 for (i = 0; i < num_influences; i++) {
5123 ok(exp_vertices[i] == vertices[i],
5124 "influence[%d]: expected vertex %u, got %u\n", i, exp_vertices[i], vertices[i]);
5125 ok((isnan(exp_weights[i]) && isnan(weights[i])) || exp_weights[i] == weights[i],
5126 "influence[%d]: expected weights %g, got %g\n", i, exp_weights[i], weights[i]);
5129 /* vertices and weights aren't returned after setting num_influences to 0 */
5130 memset(vertices, 0, sizeof(vertices));
5131 memset(weights, 0, sizeof(weights));
5132 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, 0, vertices, weights);
5133 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5135 vertices[0] = 0xdeadbeef;
5136 weights[0] = FLT_MAX;
5137 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, vertices, weights);
5138 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5139 ok(vertices[0] == 0xdeadbeef, "expected vertex 0xdeadbeef, got %u\n", vertices[0]);
5140 ok(weights[0] == FLT_MAX, "expected weight %g, got %g\n", FLT_MAX, weights[0]);
5144 /* test [GS]etFVF and [GS]etDeclaration */
5145 D3DVERTEXELEMENT9 declaration_in[MAX_FVF_DECL_SIZE];
5146 DWORD fvf = D3DFVF_XYZ;
5147 DWORD got_fvf;
5149 hr = skininfo->lpVtbl->SetDeclaration(skininfo, NULL);
5150 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5152 hr = skininfo->lpVtbl->SetDeclaration(skininfo, declaration_with_nonzero_stream);
5153 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5155 hr = skininfo->lpVtbl->SetFVF(skininfo, 0);
5156 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5158 hr = D3DXDeclaratorFromFVF(fvf, declaration_in);
5159 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5160 hr = skininfo->lpVtbl->SetDeclaration(skininfo, declaration_in);
5161 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5162 got_fvf = skininfo->lpVtbl->GetFVF(skininfo);
5163 ok(fvf == got_fvf, "Expected %#x, got %#x\n", fvf, got_fvf);
5164 hr = skininfo->lpVtbl->GetDeclaration(skininfo, declaration_out);
5165 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5166 compare_elements(declaration_out, declaration_in, __LINE__, 0);
5168 hr = skininfo->lpVtbl->SetDeclaration(skininfo, empty_declaration);
5169 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5170 got_fvf = skininfo->lpVtbl->GetFVF(skininfo);
5171 ok(got_fvf == 0, "Expected 0, got %#x\n", got_fvf);
5172 hr = skininfo->lpVtbl->GetDeclaration(skininfo, declaration_out);
5173 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5174 compare_elements(declaration_out, empty_declaration, __LINE__, 0);
5176 hr = skininfo->lpVtbl->SetFVF(skininfo, fvf);
5177 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5178 got_fvf = skininfo->lpVtbl->GetFVF(skininfo);
5179 ok(fvf == got_fvf, "Expected %#x, got %#x\n", fvf, got_fvf);
5180 hr = skininfo->lpVtbl->GetDeclaration(skininfo, declaration_out);
5181 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5182 compare_elements(declaration_out, declaration_in, __LINE__, 0);
5185 if (skininfo) IUnknown_Release(skininfo);
5186 skininfo = NULL;
5188 hr = D3DXCreateSkinInfoFVF(1, D3DFVF_XYZ, 1, NULL);
5189 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5191 hr = D3DXCreateSkinInfo(1, NULL, 1, &skininfo);
5192 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5195 static void test_convert_adjacency_to_point_reps(void)
5197 HRESULT hr;
5198 struct test_context *test_context = NULL;
5199 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
5200 const DWORD options_16bit = D3DXMESH_SYSTEMMEM;
5201 const D3DVERTEXELEMENT9 declaration[] =
5203 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
5204 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
5205 {0, 24, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
5206 D3DDECL_END()
5208 const unsigned int VERTS_PER_FACE = 3;
5209 void *vertex_buffer;
5210 void *index_buffer;
5211 DWORD *attributes_buffer;
5212 int i, j;
5213 enum color { RED = 0xffff0000, GREEN = 0xff00ff00, BLUE = 0xff0000ff};
5214 struct vertex_pnc
5216 D3DXVECTOR3 position;
5217 D3DXVECTOR3 normal;
5218 enum color color; /* In case of manual visual inspection */
5220 D3DXVECTOR3 up = {0.0f, 0.0f, 1.0f};
5221 /* mesh0 (one face)
5223 * 0--1
5224 * | /
5225 * |/
5228 const struct vertex_pnc vertices0[] =
5230 {{ 0.0f, 3.0f, 0.f}, up, RED},
5231 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5232 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5234 const DWORD indices0[] = {0, 1, 2};
5235 const unsigned int num_vertices0 = ARRAY_SIZE(vertices0);
5236 const unsigned int num_faces0 = ARRAY_SIZE(indices0) / VERTS_PER_FACE;
5237 const DWORD adjacency0[] = {-1, -1, -1};
5238 const DWORD exp_point_rep0[] = {0, 1, 2};
5239 /* mesh1 (right)
5241 * 0--1 3
5242 * | / /|
5243 * |/ / |
5244 * 2 5--4
5246 const struct vertex_pnc vertices1[] =
5248 {{ 0.0f, 3.0f, 0.f}, up, RED},
5249 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5250 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5252 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5253 {{ 3.0f, 0.0f, 0.f}, up, RED},
5254 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5256 const DWORD indices1[] = {0, 1, 2, 3, 4, 5};
5257 const unsigned int num_vertices1 = ARRAY_SIZE(vertices1);
5258 const unsigned int num_faces1 = ARRAY_SIZE(indices1) / VERTS_PER_FACE;
5259 const DWORD adjacency1[] = {-1, 1, -1, -1, -1, 0};
5260 const DWORD exp_point_rep1[] = {0, 1, 2, 1, 4, 2};
5261 /* mesh2 (left)
5263 * 3 0--1
5264 * /| | /
5265 * / | |/
5266 * 5--4 2
5268 const struct vertex_pnc vertices2[] =
5270 {{ 0.0f, 3.0f, 0.f}, up, RED},
5271 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5272 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5274 {{-1.0f, 3.0f, 0.f}, up, RED},
5275 {{-1.0f, 0.0f, 0.f}, up, GREEN},
5276 {{-3.0f, 0.0f, 0.f}, up, BLUE},
5278 const DWORD indices2[] = {0, 1, 2, 3, 4, 5};
5279 const unsigned int num_vertices2 = ARRAY_SIZE(vertices2);
5280 const unsigned int num_faces2 = ARRAY_SIZE(indices2) / VERTS_PER_FACE;
5281 const DWORD adjacency2[] = {-1, -1, 1, 0, -1, -1};
5282 const DWORD exp_point_rep2[] = {0, 1, 2, 0, 2, 5};
5283 /* mesh3 (above)
5286 * /|
5287 * / |
5288 * 5--4
5289 * 0--1
5290 * | /
5291 * |/
5294 struct vertex_pnc vertices3[] =
5296 {{ 0.0f, 3.0f, 0.f}, up, RED},
5297 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5298 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5300 {{ 2.0f, 7.0f, 0.f}, up, BLUE},
5301 {{ 2.0f, 4.0f, 0.f}, up, GREEN},
5302 {{ 0.0f, 4.0f, 0.f}, up, RED},
5304 const DWORD indices3[] = {0, 1, 2, 3, 4, 5};
5305 const unsigned int num_vertices3 = ARRAY_SIZE(vertices3);
5306 const unsigned int num_faces3 = ARRAY_SIZE(indices3) / VERTS_PER_FACE;
5307 const DWORD adjacency3[] = {1, -1, -1, -1, 0, -1};
5308 const DWORD exp_point_rep3[] = {0, 1, 2, 3, 1, 0};
5309 /* mesh4 (below, tip against tip)
5311 * 0--1
5312 * | /
5313 * |/
5316 * |\
5317 * | \
5318 * 5--4
5320 struct vertex_pnc vertices4[] =
5322 {{ 0.0f, 3.0f, 0.f}, up, RED},
5323 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5324 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5326 {{ 0.0f, -4.0f, 0.f}, up, BLUE},
5327 {{ 2.0f, -7.0f, 0.f}, up, GREEN},
5328 {{ 0.0f, -7.0f, 0.f}, up, RED},
5330 const DWORD indices4[] = {0, 1, 2, 3, 4, 5};
5331 const unsigned int num_vertices4 = ARRAY_SIZE(vertices4);
5332 const unsigned int num_faces4 = ARRAY_SIZE(indices4) / VERTS_PER_FACE;
5333 const DWORD adjacency4[] = {-1, -1, -1, -1, -1, -1};
5334 const DWORD exp_point_rep4[] = {0, 1, 2, 3, 4, 5};
5335 /* mesh5 (gap in mesh)
5337 * 0 3-----4 15
5338 * / \ \ / / \
5339 * / \ \ / / \
5340 * 2-----1 5 17-----16
5341 * 6-----7 9 12-----13
5342 * \ / / \ \ /
5343 * \ / / \ \ /
5344 * 8 10-----11 14
5347 const struct vertex_pnc vertices5[] =
5349 {{ 0.0f, 1.0f, 0.f}, up, RED},
5350 {{ 1.0f, -1.0f, 0.f}, up, GREEN},
5351 {{-1.0f, -1.0f, 0.f}, up, BLUE},
5353 {{ 0.1f, 1.0f, 0.f}, up, RED},
5354 {{ 2.1f, 1.0f, 0.f}, up, BLUE},
5355 {{ 1.1f, -1.0f, 0.f}, up, GREEN},
5357 {{-1.0f, -1.1f, 0.f}, up, BLUE},
5358 {{ 1.0f, -1.1f, 0.f}, up, GREEN},
5359 {{ 0.0f, -3.1f, 0.f}, up, RED},
5361 {{ 1.1f, -1.1f, 0.f}, up, GREEN},
5362 {{ 2.1f, -3.1f, 0.f}, up, BLUE},
5363 {{ 0.1f, -3.1f, 0.f}, up, RED},
5365 {{ 1.2f, -1.1f, 0.f}, up, GREEN},
5366 {{ 3.2f, -1.1f, 0.f}, up, RED},
5367 {{ 2.2f, -3.1f, 0.f}, up, BLUE},
5369 {{ 2.2f, 1.0f, 0.f}, up, BLUE},
5370 {{ 3.2f, -1.0f, 0.f}, up, RED},
5371 {{ 1.2f, -1.0f, 0.f}, up, GREEN},
5373 const DWORD indices5[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17};
5374 const unsigned int num_vertices5 = ARRAY_SIZE(vertices5);
5375 const unsigned int num_faces5 = ARRAY_SIZE(indices5) / VERTS_PER_FACE;
5376 const DWORD adjacency5[] = {-1, 2, -1, -1, 5, -1, 0, -1, -1, 4, -1, -1, 5, -1, 3, -1, 4, 1};
5377 const DWORD exp_point_rep5[] = {0, 1, 2, 3, 4, 5, 2, 1, 8, 5, 10, 11, 5, 13, 10, 4, 13, 5};
5378 const WORD indices5_16bit[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17};
5379 /* mesh6 (indices re-ordering)
5381 * 0--1 6 3
5382 * | / /| |\
5383 * |/ / | | \
5384 * 2 8--7 5--4
5386 const struct vertex_pnc vertices6[] =
5388 {{ 0.0f, 3.0f, 0.f}, up, RED},
5389 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5390 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5392 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5393 {{ 3.0f, 0.0f, 0.f}, up, RED},
5394 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5396 {{ 4.0f, 3.0f, 0.f}, up, GREEN},
5397 {{ 6.0f, 0.0f, 0.f}, up, BLUE},
5398 {{ 4.0f, 0.0f, 0.f}, up, RED},
5400 const DWORD indices6[] = {0, 1, 2, 6, 7, 8, 3, 4, 5};
5401 const unsigned int num_vertices6 = ARRAY_SIZE(vertices6);
5402 const unsigned int num_faces6 = ARRAY_SIZE(indices6) / VERTS_PER_FACE;
5403 const DWORD adjacency6[] = {-1, 1, -1, 2, -1, 0, -1, -1, 1};
5404 const DWORD exp_point_rep6[] = {0, 1, 2, 1, 4, 5, 1, 5, 2};
5405 /* mesh7 (expands collapsed triangle)
5407 * 0--1 3
5408 * | / /|
5409 * |/ / |
5410 * 2 5--4
5412 const struct vertex_pnc vertices7[] =
5414 {{ 0.0f, 3.0f, 0.f}, up, RED},
5415 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5416 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5418 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5419 {{ 3.0f, 0.0f, 0.f}, up, RED},
5420 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5422 const DWORD indices7[] = {0, 1, 2, 3, 3, 3}; /* Face 1 is collapsed*/
5423 const unsigned int num_vertices7 = ARRAY_SIZE(vertices7);
5424 const unsigned int num_faces7 = ARRAY_SIZE(indices7) / VERTS_PER_FACE;
5425 const DWORD adjacency7[] = {-1, -1, -1, -1, -1, -1};
5426 const DWORD exp_point_rep7[] = {0, 1, 2, 3, 4, 5};
5427 /* mesh8 (indices re-ordering and double replacement)
5429 * 0--1 9 6
5430 * | / /| |\
5431 * |/ / | | \
5432 * 2 11-10 8--7
5433 * 3--4
5434 * | /
5435 * |/
5438 const struct vertex_pnc vertices8[] =
5440 {{ 0.0f, 3.0f, 0.f}, up, RED},
5441 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5442 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5444 {{ 4.0, -4.0, 0.f}, up, RED},
5445 {{ 6.0, -4.0, 0.f}, up, BLUE},
5446 {{ 4.0, -7.0, 0.f}, up, GREEN},
5448 {{ 4.0f, 3.0f, 0.f}, up, GREEN},
5449 {{ 6.0f, 0.0f, 0.f}, up, BLUE},
5450 {{ 4.0f, 0.0f, 0.f}, up, RED},
5452 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5453 {{ 3.0f, 0.0f, 0.f}, up, RED},
5454 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5456 const DWORD indices8[] = {0, 1, 2, 9, 10, 11, 6, 7, 8, 3, 4, 5};
5457 const unsigned int num_vertices8 = ARRAY_SIZE(vertices8);
5458 const unsigned int num_faces8 = ARRAY_SIZE(indices8) / VERTS_PER_FACE;
5459 const DWORD adjacency8[] = {-1, 1, -1, 2, -1, 0, -1, 3, 1, 2, -1, -1};
5460 const DWORD exp_point_rep8[] = {0, 1, 2, 3, 4, 5, 1, 4, 3, 1, 3, 2};
5461 /* mesh9 (right, shared vertices)
5463 * 0--1
5464 * | /|
5465 * |/ |
5466 * 2--3
5468 const struct vertex_pnc vertices9[] =
5470 {{ 0.0f, 3.0f, 0.f}, up, RED},
5471 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5472 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5474 {{ 2.0f, 0.0f, 0.f}, up, RED},
5476 const DWORD indices9[] = {0, 1, 2, 1, 3, 2};
5477 const unsigned int num_vertices9 = ARRAY_SIZE(vertices9);
5478 const unsigned int num_faces9 = ARRAY_SIZE(indices9) / VERTS_PER_FACE;
5479 const DWORD adjacency9[] = {-1, 1, -1, -1, -1, 0};
5480 const DWORD exp_point_rep9[] = {0, 1, 2, 3};
5481 /* All mesh data */
5482 ID3DXMesh *mesh = NULL;
5483 ID3DXMesh *mesh_null_check = NULL;
5484 unsigned int attributes[] = {0};
5485 struct
5487 const struct vertex_pnc *vertices;
5488 const DWORD *indices;
5489 const DWORD num_vertices;
5490 const DWORD num_faces;
5491 const DWORD *adjacency;
5492 const DWORD *exp_point_reps;
5493 const DWORD options;
5495 tc[] =
5498 vertices0,
5499 indices0,
5500 num_vertices0,
5501 num_faces0,
5502 adjacency0,
5503 exp_point_rep0,
5504 options
5507 vertices1,
5508 indices1,
5509 num_vertices1,
5510 num_faces1,
5511 adjacency1,
5512 exp_point_rep1,
5513 options
5516 vertices2,
5517 indices2,
5518 num_vertices2,
5519 num_faces2,
5520 adjacency2,
5521 exp_point_rep2,
5522 options
5525 vertices3,
5526 indices3,
5527 num_vertices3,
5528 num_faces3,
5529 adjacency3,
5530 exp_point_rep3,
5531 options
5534 vertices4,
5535 indices4,
5536 num_vertices4,
5537 num_faces4,
5538 adjacency4,
5539 exp_point_rep4,
5540 options
5543 vertices5,
5544 indices5,
5545 num_vertices5,
5546 num_faces5,
5547 adjacency5,
5548 exp_point_rep5,
5549 options
5552 vertices6,
5553 indices6,
5554 num_vertices6,
5555 num_faces6,
5556 adjacency6,
5557 exp_point_rep6,
5558 options
5561 vertices7,
5562 indices7,
5563 num_vertices7,
5564 num_faces7,
5565 adjacency7,
5566 exp_point_rep7,
5567 options
5570 vertices8,
5571 indices8,
5572 num_vertices8,
5573 num_faces8,
5574 adjacency8,
5575 exp_point_rep8,
5576 options
5579 vertices9,
5580 indices9,
5581 num_vertices9,
5582 num_faces9,
5583 adjacency9,
5584 exp_point_rep9,
5585 options
5588 vertices5,
5589 (DWORD*)indices5_16bit,
5590 num_vertices5,
5591 num_faces5,
5592 adjacency5,
5593 exp_point_rep5,
5594 options_16bit
5597 DWORD *point_reps = NULL;
5599 test_context = new_test_context();
5600 if (!test_context)
5602 skip("Couldn't create test context\n");
5603 goto cleanup;
5606 for (i = 0; i < ARRAY_SIZE(tc); i++)
5608 hr = D3DXCreateMesh(tc[i].num_faces, tc[i].num_vertices, tc[i].options, declaration,
5609 test_context->device, &mesh);
5610 if (FAILED(hr))
5612 skip("Couldn't create mesh %d. Got %x expected D3D_OK\n", i, hr);
5613 goto cleanup;
5616 if (i == 0) /* Save first mesh for later NULL checks */
5617 mesh_null_check = mesh;
5619 point_reps = HeapAlloc(GetProcessHeap(), 0, tc[i].num_vertices * sizeof(*point_reps));
5620 if (!point_reps)
5622 skip("Couldn't allocate point reps array.\n");
5623 goto cleanup;
5626 hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, &vertex_buffer);
5627 if (FAILED(hr))
5629 skip("Couldn't lock vertex buffer.\n");
5630 goto cleanup;
5632 memcpy(vertex_buffer, tc[i].vertices, tc[i].num_vertices * sizeof(*tc[i].vertices));
5633 hr = mesh->lpVtbl->UnlockVertexBuffer(mesh);
5634 if (FAILED(hr))
5636 skip("Couldn't unlock vertex buffer.\n");
5637 goto cleanup;
5640 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, &index_buffer);
5641 if (FAILED(hr))
5643 skip("Couldn't lock index buffer.\n");
5644 goto cleanup;
5646 if (tc[i].options & D3DXMESH_32BIT)
5648 memcpy(index_buffer, tc[i].indices, VERTS_PER_FACE * tc[i].num_faces * sizeof(DWORD));
5650 else
5652 memcpy(index_buffer, tc[i].indices, VERTS_PER_FACE * tc[i].num_faces * sizeof(WORD));
5654 hr = mesh->lpVtbl->UnlockIndexBuffer(mesh);
5655 if (FAILED(hr)) {
5656 skip("Couldn't unlock index buffer.\n");
5657 goto cleanup;
5660 hr = mesh->lpVtbl->LockAttributeBuffer(mesh, 0, &attributes_buffer);
5661 if (FAILED(hr))
5663 skip("Couldn't lock attributes buffer.\n");
5664 goto cleanup;
5666 memcpy(attributes_buffer, attributes, sizeof(attributes));
5667 hr = mesh->lpVtbl->UnlockAttributeBuffer(mesh);
5668 if (FAILED(hr))
5670 skip("Couldn't unlock attributes buffer.\n");
5671 goto cleanup;
5674 /* Convert adjacency to point representation */
5675 for (j = 0; j < tc[i].num_vertices; j++) point_reps[j] = -1;
5676 hr = mesh->lpVtbl->ConvertAdjacencyToPointReps(mesh, tc[i].adjacency, point_reps);
5677 ok(hr == D3D_OK, "ConvertAdjacencyToPointReps failed case %d. "
5678 "Got %x expected D3D_OK\n", i, hr);
5680 /* Check point representation */
5681 for (j = 0; j < tc[i].num_vertices; j++)
5683 ok(point_reps[j] == tc[i].exp_point_reps[j],
5684 "Unexpected point representation at (%d, %d)."
5685 " Got %d expected %d\n",
5686 i, j, point_reps[j], tc[i].exp_point_reps[j]);
5689 HeapFree(GetProcessHeap(), 0, point_reps);
5690 point_reps = NULL;
5692 if (i != 0) /* First mesh will be freed during cleanup */
5693 mesh->lpVtbl->Release(mesh);
5696 /* NULL checks */
5697 hr = mesh_null_check->lpVtbl->ConvertAdjacencyToPointReps(mesh_null_check, tc[0].adjacency, NULL);
5698 ok(hr == D3DERR_INVALIDCALL, "ConvertAdjacencyToPointReps point_reps NULL. "
5699 "Got %x expected D3DERR_INVALIDCALL\n", hr);
5700 hr = mesh_null_check->lpVtbl->ConvertAdjacencyToPointReps(mesh_null_check, NULL, NULL);
5701 ok(hr == D3DERR_INVALIDCALL, "ConvertAdjacencyToPointReps adjacency and point_reps NULL. "
5702 "Got %x expected D3DERR_INVALIDCALL\n", hr);
5704 cleanup:
5705 if (mesh_null_check)
5706 mesh_null_check->lpVtbl->Release(mesh_null_check);
5707 HeapFree(GetProcessHeap(), 0, point_reps);
5708 free_test_context(test_context);
5711 static void test_convert_point_reps_to_adjacency(void)
5713 HRESULT hr;
5714 struct test_context *test_context = NULL;
5715 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
5716 const DWORD options_16bit = D3DXMESH_SYSTEMMEM;
5717 const D3DVERTEXELEMENT9 declaration[] =
5719 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
5720 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
5721 {0, 24, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
5722 D3DDECL_END()
5724 const unsigned int VERTS_PER_FACE = 3;
5725 void *vertex_buffer;
5726 void *index_buffer;
5727 DWORD *attributes_buffer;
5728 int i, j;
5729 enum color { RED = 0xffff0000, GREEN = 0xff00ff00, BLUE = 0xff0000ff};
5730 struct vertex_pnc
5732 D3DXVECTOR3 position;
5733 D3DXVECTOR3 normal;
5734 enum color color; /* In case of manual visual inspection */
5736 D3DXVECTOR3 up = {0.0f, 0.0f, 1.0f};
5737 /* mesh0 (one face)
5739 * 0--1
5740 * | /
5741 * |/
5744 const struct vertex_pnc vertices0[] =
5746 {{ 0.0f, 3.0f, 0.f}, up, RED},
5747 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5748 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5750 const DWORD indices0[] = {0, 1, 2};
5751 const unsigned int num_vertices0 = ARRAY_SIZE(vertices0);
5752 const unsigned int num_faces0 = num_vertices0 / VERTS_PER_FACE;
5753 const DWORD exp_adjacency0[] = {-1, -1, -1};
5754 const DWORD exp_id_adjacency0[] = {-1, -1, -1};
5755 const DWORD point_rep0[] = {0, 1, 2};
5756 /* mesh1 (right)
5758 * 0--1 3
5759 * | / /|
5760 * |/ / |
5761 * 2 5--4
5763 const struct vertex_pnc vertices1[] =
5765 {{ 0.0f, 3.0f, 0.f}, up, RED},
5766 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5767 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5769 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5770 {{ 3.0f, 0.0f, 0.f}, up, RED},
5771 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5773 const DWORD indices1[] = {0, 1, 2, 3, 4, 5};
5774 const unsigned int num_vertices1 = ARRAY_SIZE(vertices1);
5775 const unsigned int num_faces1 = num_vertices1 / VERTS_PER_FACE;
5776 const DWORD exp_adjacency1[] = {-1, 1, -1, -1, -1, 0};
5777 const DWORD exp_id_adjacency1[] = {-1, -1, -1, -1, -1, -1};
5778 const DWORD point_rep1[] = {0, 1, 2, 1, 4, 2};
5779 /* mesh2 (left)
5781 * 3 0--1
5782 * /| | /
5783 * / | |/
5784 * 5--4 2
5786 const struct vertex_pnc vertices2[] =
5788 {{ 0.0f, 3.0f, 0.f}, up, RED},
5789 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5790 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5792 {{-1.0f, 3.0f, 0.f}, up, RED},
5793 {{-1.0f, 0.0f, 0.f}, up, GREEN},
5794 {{-3.0f, 0.0f, 0.f}, up, BLUE},
5796 const DWORD indices2[] = {0, 1, 2, 3, 4, 5};
5797 const unsigned int num_vertices2 = ARRAY_SIZE(vertices2);
5798 const unsigned int num_faces2 = num_vertices2 / VERTS_PER_FACE;
5799 const DWORD exp_adjacency2[] = {-1, -1, 1, 0, -1, -1};
5800 const DWORD exp_id_adjacency2[] = {-1, -1, -1, -1, -1, -1};
5801 const DWORD point_rep2[] = {0, 1, 2, 0, 2, 5};
5802 /* mesh3 (above)
5805 * /|
5806 * / |
5807 * 5--4
5808 * 0--1
5809 * | /
5810 * |/
5813 struct vertex_pnc vertices3[] =
5815 {{ 0.0f, 3.0f, 0.f}, up, RED},
5816 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5817 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5819 {{ 2.0f, 7.0f, 0.f}, up, BLUE},
5820 {{ 2.0f, 4.0f, 0.f}, up, GREEN},
5821 {{ 0.0f, 4.0f, 0.f}, up, RED},
5823 const DWORD indices3[] = {0, 1, 2, 3, 4, 5};
5824 const unsigned int num_vertices3 = ARRAY_SIZE(vertices3);
5825 const unsigned int num_faces3 = num_vertices3 / VERTS_PER_FACE;
5826 const DWORD exp_adjacency3[] = {1, -1, -1, -1, 0, -1};
5827 const DWORD exp_id_adjacency3[] = {-1, -1, -1, -1, -1, -1};
5828 const DWORD point_rep3[] = {0, 1, 2, 3, 1, 0};
5829 /* mesh4 (below, tip against tip)
5831 * 0--1
5832 * | /
5833 * |/
5836 * |\
5837 * | \
5838 * 5--4
5840 struct vertex_pnc vertices4[] =
5842 {{ 0.0f, 3.0f, 0.f}, up, RED},
5843 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5844 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5846 {{ 0.0f, -4.0f, 0.f}, up, BLUE},
5847 {{ 2.0f, -7.0f, 0.f}, up, GREEN},
5848 {{ 0.0f, -7.0f, 0.f}, up, RED},
5850 const DWORD indices4[] = {0, 1, 2, 3, 4, 5};
5851 const unsigned int num_vertices4 = ARRAY_SIZE(vertices4);
5852 const unsigned int num_faces4 = num_vertices4 / VERTS_PER_FACE;
5853 const DWORD exp_adjacency4[] = {-1, -1, -1, -1, -1, -1};
5854 const DWORD exp_id_adjacency4[] = {-1, -1, -1, -1, -1, -1};
5855 const DWORD point_rep4[] = {0, 1, 2, 3, 4, 5};
5856 /* mesh5 (gap in mesh)
5858 * 0 3-----4 15
5859 * / \ \ / / \
5860 * / \ \ / / \
5861 * 2-----1 5 17-----16
5862 * 6-----7 9 12-----13
5863 * \ / / \ \ /
5864 * \ / / \ \ /
5865 * 8 10-----11 14
5868 const struct vertex_pnc vertices5[] =
5870 {{ 0.0f, 1.0f, 0.f}, up, RED},
5871 {{ 1.0f, -1.0f, 0.f}, up, GREEN},
5872 {{-1.0f, -1.0f, 0.f}, up, BLUE},
5874 {{ 0.1f, 1.0f, 0.f}, up, RED},
5875 {{ 2.1f, 1.0f, 0.f}, up, BLUE},
5876 {{ 1.1f, -1.0f, 0.f}, up, GREEN},
5878 {{-1.0f, -1.1f, 0.f}, up, BLUE},
5879 {{ 1.0f, -1.1f, 0.f}, up, GREEN},
5880 {{ 0.0f, -3.1f, 0.f}, up, RED},
5882 {{ 1.1f, -1.1f, 0.f}, up, GREEN},
5883 {{ 2.1f, -3.1f, 0.f}, up, BLUE},
5884 {{ 0.1f, -3.1f, 0.f}, up, RED},
5886 {{ 1.2f, -1.1f, 0.f}, up, GREEN},
5887 {{ 3.2f, -1.1f, 0.f}, up, RED},
5888 {{ 2.2f, -3.1f, 0.f}, up, BLUE},
5890 {{ 2.2f, 1.0f, 0.f}, up, BLUE},
5891 {{ 3.2f, -1.0f, 0.f}, up, RED},
5892 {{ 1.2f, -1.0f, 0.f}, up, GREEN},
5894 const DWORD indices5[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17};
5895 const unsigned int num_vertices5 = ARRAY_SIZE(vertices5);
5896 const unsigned int num_faces5 = num_vertices5 / VERTS_PER_FACE;
5897 const DWORD exp_adjacency5[] = {-1, 2, -1, -1, 5, -1, 0, -1, -1, 4, -1, -1, 5, -1, 3, -1, 4, 1};
5898 const DWORD exp_id_adjacency5[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
5899 const DWORD point_rep5[] = {0, 1, 2, 3, 4, 5, 2, 1, 8, 5, 10, 11, 5, 13, 10, 4, 13, 5};
5900 /* mesh6 (indices re-ordering)
5902 * 0--1 6 3
5903 * | / /| |\
5904 * |/ / | | \
5905 * 2 8--7 5--4
5907 const struct vertex_pnc vertices6[] =
5909 {{ 0.0f, 3.0f, 0.f}, up, RED},
5910 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5911 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5913 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5914 {{ 3.0f, 0.0f, 0.f}, up, RED},
5915 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5917 {{ 4.0f, 3.0f, 0.f}, up, GREEN},
5918 {{ 6.0f, 0.0f, 0.f}, up, BLUE},
5919 {{ 4.0f, 0.0f, 0.f}, up, RED},
5921 const DWORD indices6[] = {0, 1, 2, 6, 7, 8, 3, 4, 5};
5922 const unsigned int num_vertices6 = ARRAY_SIZE(vertices6);
5923 const unsigned int num_faces6 = num_vertices6 / VERTS_PER_FACE;
5924 const DWORD exp_adjacency6[] = {-1, 1, -1, 2, -1, 0, -1, -1, 1};
5925 const DWORD exp_id_adjacency6[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1};
5926 const DWORD point_rep6[] = {0, 1, 2, 1, 4, 5, 1, 5, 2};
5927 /* mesh7 (expands collapsed triangle)
5929 * 0--1 3
5930 * | / /|
5931 * |/ / |
5932 * 2 5--4
5934 const struct vertex_pnc vertices7[] =
5936 {{ 0.0f, 3.0f, 0.f}, up, RED},
5937 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5938 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5940 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5941 {{ 3.0f, 0.0f, 0.f}, up, RED},
5942 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5944 const DWORD indices7[] = {0, 1, 2, 3, 3, 3}; /* Face 1 is collapsed*/
5945 const unsigned int num_vertices7 = ARRAY_SIZE(vertices7);
5946 const unsigned int num_faces7 = num_vertices7 / VERTS_PER_FACE;
5947 const DWORD exp_adjacency7[] = {-1, -1, -1, -1, -1, -1};
5948 const DWORD exp_id_adjacency7[] = {-1, -1, -1, -1, -1, -1};
5949 const DWORD point_rep7[] = {0, 1, 2, 3, 4, 5};
5950 /* mesh8 (indices re-ordering and double replacement)
5952 * 0--1 9 6
5953 * | / /| |\
5954 * |/ / | | \
5955 * 2 11-10 8--7
5956 * 3--4
5957 * | /
5958 * |/
5961 const struct vertex_pnc vertices8[] =
5963 {{ 0.0f, 3.0f, 0.f}, up, RED},
5964 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5965 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5967 {{ 4.0, -4.0, 0.f}, up, RED},
5968 {{ 6.0, -4.0, 0.f}, up, BLUE},
5969 {{ 4.0, -7.0, 0.f}, up, GREEN},
5971 {{ 4.0f, 3.0f, 0.f}, up, GREEN},
5972 {{ 6.0f, 0.0f, 0.f}, up, BLUE},
5973 {{ 4.0f, 0.0f, 0.f}, up, RED},
5975 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5976 {{ 3.0f, 0.0f, 0.f}, up, RED},
5977 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5979 const DWORD indices8[] = {0, 1, 2, 9, 10, 11, 6, 7, 8, 3, 4, 5};
5980 const WORD indices8_16bit[] = {0, 1, 2, 9, 10, 11, 6, 7, 8, 3, 4, 5};
5981 const unsigned int num_vertices8 = ARRAY_SIZE(vertices8);
5982 const unsigned int num_faces8 = num_vertices8 / VERTS_PER_FACE;
5983 const DWORD exp_adjacency8[] = {-1, 1, -1, 2, -1, 0, -1, 3, 1, 2, -1, -1};
5984 const DWORD exp_id_adjacency8[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
5985 const DWORD point_rep8[] = {0, 1, 2, 3, 4, 5, 1, 4, 3, 1, 3, 2};
5986 /* mesh9 (right, shared vertices)
5988 * 0--1
5989 * | /|
5990 * |/ |
5991 * 2--3
5993 const struct vertex_pnc vertices9[] =
5995 {{ 0.0f, 3.0f, 0.f}, up, RED},
5996 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5997 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5999 {{ 2.0f, 0.0f, 0.f}, up, RED},
6001 const DWORD indices9[] = {0, 1, 2, 1, 3, 2};
6002 const unsigned int num_vertices9 = ARRAY_SIZE(vertices9);
6003 const unsigned int num_faces9 = 2;
6004 const DWORD exp_adjacency9[] = {-1, 1, -1, -1, -1, 0};
6005 const DWORD exp_id_adjacency9[] = {-1, 1, -1, -1, -1, 0};
6006 const DWORD point_rep9[] = {0, 1, 2, 3};
6007 /* All mesh data */
6008 ID3DXMesh *mesh = NULL;
6009 ID3DXMesh *mesh_null_check = NULL;
6010 unsigned int attributes[] = {0};
6011 struct
6013 const struct vertex_pnc *vertices;
6014 const DWORD *indices;
6015 const DWORD num_vertices;
6016 const DWORD num_faces;
6017 const DWORD *point_reps;
6018 const DWORD *exp_adjacency;
6019 const DWORD *exp_id_adjacency;
6020 const DWORD options;
6022 tc[] =
6025 vertices0,
6026 indices0,
6027 num_vertices0,
6028 num_faces0,
6029 point_rep0,
6030 exp_adjacency0,
6031 exp_id_adjacency0,
6032 options
6035 vertices1,
6036 indices1,
6037 num_vertices1,
6038 num_faces1,
6039 point_rep1,
6040 exp_adjacency1,
6041 exp_id_adjacency1,
6042 options
6045 vertices2,
6046 indices2,
6047 num_vertices2,
6048 num_faces2,
6049 point_rep2,
6050 exp_adjacency2,
6051 exp_id_adjacency2,
6052 options
6055 vertices3,
6056 indices3,
6057 num_vertices3,
6058 num_faces3,
6059 point_rep3,
6060 exp_adjacency3,
6061 exp_id_adjacency3,
6062 options
6065 vertices4,
6066 indices4,
6067 num_vertices4,
6068 num_faces4,
6069 point_rep4,
6070 exp_adjacency4,
6071 exp_id_adjacency4,
6072 options
6075 vertices5,
6076 indices5,
6077 num_vertices5,
6078 num_faces5,
6079 point_rep5,
6080 exp_adjacency5,
6081 exp_id_adjacency5,
6082 options
6085 vertices6,
6086 indices6,
6087 num_vertices6,
6088 num_faces6,
6089 point_rep6,
6090 exp_adjacency6,
6091 exp_id_adjacency6,
6092 options
6095 vertices7,
6096 indices7,
6097 num_vertices7,
6098 num_faces7,
6099 point_rep7,
6100 exp_adjacency7,
6101 exp_id_adjacency7,
6102 options
6105 vertices8,
6106 indices8,
6107 num_vertices8,
6108 num_faces8,
6109 point_rep8,
6110 exp_adjacency8,
6111 exp_id_adjacency8,
6112 options
6115 vertices9,
6116 indices9,
6117 num_vertices9,
6118 num_faces9,
6119 point_rep9,
6120 exp_adjacency9,
6121 exp_id_adjacency9,
6122 options
6125 vertices8,
6126 (DWORD*)indices8_16bit,
6127 num_vertices8,
6128 num_faces8,
6129 point_rep8,
6130 exp_adjacency8,
6131 exp_id_adjacency8,
6132 options_16bit
6135 DWORD *adjacency = NULL;
6137 test_context = new_test_context();
6138 if (!test_context)
6140 skip("Couldn't create test context\n");
6141 goto cleanup;
6144 for (i = 0; i < ARRAY_SIZE(tc); i++)
6146 hr = D3DXCreateMesh(tc[i].num_faces, tc[i].num_vertices, tc[i].options,
6147 declaration, test_context->device, &mesh);
6148 if (FAILED(hr))
6150 skip("Couldn't create mesh %d. Got %x expected D3D_OK\n", i, hr);
6151 goto cleanup;
6154 if (i == 0) /* Save first mesh for later NULL checks */
6155 mesh_null_check = mesh;
6157 adjacency = HeapAlloc(GetProcessHeap(), 0, VERTS_PER_FACE * tc[i].num_faces * sizeof(*adjacency));
6158 if (!adjacency)
6160 skip("Couldn't allocate adjacency array.\n");
6161 goto cleanup;
6164 hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, &vertex_buffer);
6165 if (FAILED(hr))
6167 skip("Couldn't lock vertex buffer.\n");
6168 goto cleanup;
6170 memcpy(vertex_buffer, tc[i].vertices, tc[i].num_vertices * sizeof(*tc[i].vertices));
6171 hr = mesh->lpVtbl->UnlockVertexBuffer(mesh);
6172 if (FAILED(hr))
6174 skip("Couldn't unlock vertex buffer.\n");
6175 goto cleanup;
6177 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, &index_buffer);
6178 if (FAILED(hr))
6180 skip("Couldn't lock index buffer.\n");
6181 goto cleanup;
6183 if (tc[i].options & D3DXMESH_32BIT)
6185 memcpy(index_buffer, tc[i].indices, VERTS_PER_FACE * tc[i].num_faces * sizeof(DWORD));
6187 else
6189 memcpy(index_buffer, tc[i].indices, VERTS_PER_FACE * tc[i].num_faces * sizeof(WORD));
6191 hr = mesh->lpVtbl->UnlockIndexBuffer(mesh);
6192 if (FAILED(hr)) {
6193 skip("Couldn't unlock index buffer.\n");
6194 goto cleanup;
6197 hr = mesh->lpVtbl->LockAttributeBuffer(mesh, 0, &attributes_buffer);
6198 if (FAILED(hr))
6200 skip("Couldn't lock attributes buffer.\n");
6201 goto cleanup;
6203 memcpy(attributes_buffer, attributes, sizeof(attributes));
6204 hr = mesh->lpVtbl->UnlockAttributeBuffer(mesh);
6205 if (FAILED(hr))
6207 skip("Couldn't unlock attributes buffer.\n");
6208 goto cleanup;
6211 /* Convert point representation to adjacency*/
6212 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++) adjacency[j] = -2;
6214 hr = mesh->lpVtbl->ConvertPointRepsToAdjacency(mesh, tc[i].point_reps, adjacency);
6215 ok(hr == D3D_OK, "ConvertPointRepsToAdjacency failed case %d. "
6216 "Got %x expected D3D_OK\n", i, hr);
6217 /* Check adjacency */
6218 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
6220 ok(adjacency[j] == tc[i].exp_adjacency[j],
6221 "Unexpected adjacency information at (%d, %d)."
6222 " Got %d expected %d\n",
6223 i, j, adjacency[j], tc[i].exp_adjacency[j]);
6226 /* NULL point representation is considered identity. */
6227 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++) adjacency[j] = -2;
6228 hr = mesh_null_check->lpVtbl->ConvertPointRepsToAdjacency(mesh, NULL, adjacency);
6229 ok(hr == D3D_OK, "ConvertPointRepsToAdjacency NULL point_reps. "
6230 "Got %x expected D3D_OK\n", hr);
6231 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
6233 ok(adjacency[j] == tc[i].exp_id_adjacency[j],
6234 "Unexpected adjacency information (id) at (%d, %d)."
6235 " Got %d expected %d\n",
6236 i, j, adjacency[j], tc[i].exp_id_adjacency[j]);
6239 HeapFree(GetProcessHeap(), 0, adjacency);
6240 adjacency = NULL;
6241 if (i != 0) /* First mesh will be freed during cleanup */
6242 mesh->lpVtbl->Release(mesh);
6245 /* NULL checks */
6246 hr = mesh_null_check->lpVtbl->ConvertPointRepsToAdjacency(mesh_null_check, tc[0].point_reps, NULL);
6247 ok(hr == D3DERR_INVALIDCALL, "ConvertPointRepsToAdjacency NULL adjacency. "
6248 "Got %x expected D3DERR_INVALIDCALL\n", hr);
6249 hr = mesh_null_check->lpVtbl->ConvertPointRepsToAdjacency(mesh_null_check, NULL, NULL);
6250 ok(hr == D3DERR_INVALIDCALL, "ConvertPointRepsToAdjacency NULL point_reps and adjacency. "
6251 "Got %x expected D3DERR_INVALIDCALL\n", hr);
6253 cleanup:
6254 if (mesh_null_check)
6255 mesh_null_check->lpVtbl->Release(mesh_null_check);
6256 HeapFree(GetProcessHeap(), 0, adjacency);
6257 free_test_context(test_context);
6260 static HRESULT init_test_mesh(const DWORD num_faces, const DWORD num_vertices,
6261 const DWORD options,
6262 const D3DVERTEXELEMENT9 *declaration,
6263 IDirect3DDevice9 *device, ID3DXMesh **mesh_ptr,
6264 const void *vertices, const DWORD vertex_size,
6265 const DWORD *indices, const DWORD *attributes)
6267 HRESULT hr;
6268 void *vertex_buffer;
6269 void *index_buffer;
6270 DWORD *attributes_buffer;
6271 ID3DXMesh *mesh = NULL;
6273 hr = D3DXCreateMesh(num_faces, num_vertices, options, declaration, device, mesh_ptr);
6274 if (FAILED(hr))
6276 skip("Couldn't create mesh. Got %x expected D3D_OK\n", hr);
6277 goto cleanup;
6279 mesh = *mesh_ptr;
6281 hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, &vertex_buffer);
6282 if (FAILED(hr))
6284 skip("Couldn't lock vertex buffer.\n");
6285 goto cleanup;
6287 memcpy(vertex_buffer, vertices, num_vertices * vertex_size);
6288 hr = mesh->lpVtbl->UnlockVertexBuffer(mesh);
6289 if (FAILED(hr))
6291 skip("Couldn't unlock vertex buffer.\n");
6292 goto cleanup;
6295 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, &index_buffer);
6296 if (FAILED(hr))
6298 skip("Couldn't lock index buffer.\n");
6299 goto cleanup;
6301 if (options & D3DXMESH_32BIT)
6303 if (indices)
6304 memcpy(index_buffer, indices, 3 * num_faces * sizeof(DWORD));
6305 else
6307 /* Fill index buffer with 0, 1, 2, ...*/
6308 DWORD *indices_32bit = (DWORD*)index_buffer;
6309 UINT i;
6310 for (i = 0; i < 3 * num_faces; i++)
6311 indices_32bit[i] = i;
6314 else
6316 if (indices)
6317 memcpy(index_buffer, indices, 3 * num_faces * sizeof(WORD));
6318 else
6320 /* Fill index buffer with 0, 1, 2, ...*/
6321 WORD *indices_16bit = (WORD*)index_buffer;
6322 UINT i;
6323 for (i = 0; i < 3 * num_faces; i++)
6324 indices_16bit[i] = i;
6327 hr = mesh->lpVtbl->UnlockIndexBuffer(mesh);
6328 if (FAILED(hr)) {
6329 skip("Couldn't unlock index buffer.\n");
6330 goto cleanup;
6333 hr = mesh->lpVtbl->LockAttributeBuffer(mesh, 0, &attributes_buffer);
6334 if (FAILED(hr))
6336 skip("Couldn't lock attributes buffer.\n");
6337 goto cleanup;
6340 if (attributes)
6341 memcpy(attributes_buffer, attributes, num_faces * sizeof(*attributes));
6342 else
6343 memset(attributes_buffer, 0, num_faces * sizeof(*attributes));
6345 hr = mesh->lpVtbl->UnlockAttributeBuffer(mesh);
6346 if (FAILED(hr))
6348 skip("Couldn't unlock attributes buffer.\n");
6349 goto cleanup;
6352 hr = D3D_OK;
6353 cleanup:
6354 return hr;
6357 /* Using structs instead of bit-fields in order to avoid compiler issues. */
6358 struct udec3
6360 UINT x;
6361 UINT y;
6362 UINT z;
6363 UINT w;
6366 struct dec3n
6368 INT x;
6369 INT y;
6370 INT z;
6371 INT w;
6374 static DWORD init_udec3_dword(UINT x, UINT y, UINT z, UINT w)
6376 DWORD d = 0;
6378 d |= x & 0x3ff;
6379 d |= (y << 10) & 0xffc00;
6380 d |= (z << 20) & 0x3ff00000;
6381 d |= (w << 30) & 0xc0000000;
6383 return d;
6386 static DWORD init_dec3n_dword(INT x, INT y, INT z, INT w)
6388 DWORD d = 0;
6390 d |= x & 0x3ff;
6391 d |= (y << 10) & 0xffc00;
6392 d |= (z << 20) & 0x3ff00000;
6393 d |= (w << 30) & 0xc0000000;
6395 return d;
6398 static struct udec3 dword_to_udec3(DWORD d)
6400 struct udec3 v;
6402 v.x = d & 0x3ff;
6403 v.y = (d & 0xffc00) >> 10;
6404 v.z = (d & 0x3ff00000) >> 20;
6405 v.w = (d & 0xc0000000) >> 30;
6407 return v;
6410 static struct dec3n dword_to_dec3n(DWORD d)
6412 struct dec3n v;
6414 v.x = d & 0x3ff;
6415 v.y = (d & 0xffc00) >> 10;
6416 v.z = (d & 0x3ff00000) >> 20;
6417 v.w = (d & 0xc0000000) >> 30;
6419 return v;
6422 static void check_vertex_components(int line, int mesh_number, int vertex_number, BYTE *got_ptr, const BYTE *exp_ptr, D3DVERTEXELEMENT9 *declaration)
6424 const char *usage_strings[] =
6426 "position",
6427 "blend weight",
6428 "blend indices",
6429 "normal",
6430 "point size",
6431 "texture coordinates",
6432 "tangent",
6433 "binormal",
6434 "tessellation factor",
6435 "position transformed",
6436 "color",
6437 "fog",
6438 "depth",
6439 "sample"
6441 D3DVERTEXELEMENT9 *decl_ptr;
6442 const float PRECISION = 1e-5f;
6444 for (decl_ptr = declaration; decl_ptr->Stream != 0xFF; decl_ptr++)
6446 switch (decl_ptr->Type)
6448 case D3DDECLTYPE_FLOAT1:
6450 FLOAT *got = (FLOAT*)(got_ptr + decl_ptr->Offset);
6451 FLOAT *exp = (FLOAT*)(exp_ptr + decl_ptr->Offset);
6452 FLOAT diff = fabsf(*got - *exp);
6453 ok_(__FILE__,line)(diff <= PRECISION, "Mesh %d: Got %f for vertex %d %s, expected %f.\n",
6454 mesh_number, *got, vertex_number, usage_strings[decl_ptr->Usage], *exp);
6455 break;
6457 case D3DDECLTYPE_FLOAT2:
6459 D3DXVECTOR2 *got = (D3DXVECTOR2*)(got_ptr + decl_ptr->Offset);
6460 D3DXVECTOR2 *exp = (D3DXVECTOR2*)(exp_ptr + decl_ptr->Offset);
6461 FLOAT diff = max(fabsf(got->x - exp->x), fabsf(got->y - exp->y));
6462 ok_(__FILE__,line)(diff <= PRECISION, "Mesh %d: Got (%f, %f) for vertex %d %s, expected (%f, %f).\n",
6463 mesh_number, got->x, got->y, vertex_number, usage_strings[decl_ptr->Usage], exp->x, exp->y);
6464 break;
6466 case D3DDECLTYPE_FLOAT3:
6468 D3DXVECTOR3 *got = (D3DXVECTOR3*)(got_ptr + decl_ptr->Offset);
6469 D3DXVECTOR3 *exp = (D3DXVECTOR3*)(exp_ptr + decl_ptr->Offset);
6470 FLOAT diff = max(fabsf(got->x - exp->x), fabsf(got->y - exp->y));
6471 diff = max(diff, fabsf(got->z - exp->z));
6472 ok_(__FILE__,line)(diff <= PRECISION, "Mesh %d: Got (%f, %f, %f) for vertex %d %s, expected (%f, %f, %f).\n",
6473 mesh_number, got->x, got->y, got->z, vertex_number, usage_strings[decl_ptr->Usage], exp->x, exp->y, exp->z);
6474 break;
6476 case D3DDECLTYPE_FLOAT4:
6478 D3DXVECTOR4 *got = (D3DXVECTOR4*)(got_ptr + decl_ptr->Offset);
6479 D3DXVECTOR4 *exp = (D3DXVECTOR4*)(exp_ptr + decl_ptr->Offset);
6480 FLOAT diff = max(fabsf(got->x - exp->x), fabsf(got->y - exp->y));
6481 diff = max(diff, fabsf(got->z - exp->z));
6482 diff = max(diff, fabsf(got->w - exp->w));
6483 ok_(__FILE__,line)(diff <= PRECISION, "Mesh %d: Got (%f, %f, %f, %f) for vertex %d %s, expected (%f, %f, %f, %f).\n",
6484 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);
6485 break;
6487 case D3DDECLTYPE_D3DCOLOR:
6489 BYTE *got = got_ptr + decl_ptr->Offset;
6490 const BYTE *exp = exp_ptr + decl_ptr->Offset;
6491 BOOL same_color = got[0] == exp[0] && got[1] == exp[1]
6492 && got[2] == exp[2] && got[3] == exp[3];
6493 const char *color_types[] = {"diffuse", "specular", "undefined color"};
6494 BYTE usage_index = decl_ptr->UsageIndex;
6495 if (usage_index > 1) usage_index = 2;
6496 ok_(__FILE__,line)(same_color, "Mesh %d: Got (%u, %u, %u, %u) for vertex %d %s, expected (%u, %u, %u, %u).\n",
6497 mesh_number, got[0], got[1], got[2], got[3], vertex_number, color_types[usage_index], exp[0], exp[1], exp[2], exp[3]);
6498 break;
6500 case D3DDECLTYPE_UBYTE4:
6501 case D3DDECLTYPE_UBYTE4N:
6503 BYTE *got = got_ptr + decl_ptr->Offset;
6504 const BYTE *exp = exp_ptr + decl_ptr->Offset;
6505 BOOL same = got[0] == exp[0] && got[1] == exp[1]
6506 && got[2] == exp[2] && got[3] == exp[3];
6507 ok_(__FILE__,line)(same, "Mesh %d: Got (%u, %u, %u, %u) for vertex %d %s, expected (%u, %u, %u, %u).\n",
6508 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]);
6509 break;
6511 case D3DDECLTYPE_SHORT2:
6512 case D3DDECLTYPE_SHORT2N:
6514 SHORT *got = (SHORT*)(got_ptr + decl_ptr->Offset);
6515 SHORT *exp = (SHORT*)(exp_ptr + decl_ptr->Offset);
6516 BOOL same = got[0] == exp[0] && got[1] == exp[1];
6517 ok_(__FILE__,line)(same, "Mesh %d: Got (%hd, %hd) for vertex %d %s, expected (%hd, %hd).\n",
6518 mesh_number, got[0], got[1], vertex_number, usage_strings[decl_ptr->Usage], exp[0], exp[1]);
6519 break;
6521 case D3DDECLTYPE_SHORT4:
6522 case D3DDECLTYPE_SHORT4N:
6524 SHORT *got = (SHORT*)(got_ptr + decl_ptr->Offset);
6525 SHORT *exp = (SHORT*)(exp_ptr + decl_ptr->Offset);
6526 BOOL same = got[0] == exp[0] && got[1] == exp[1]
6527 && got[2] == exp[2] && got[3] == exp[3];
6528 ok_(__FILE__,line)(same, "Mesh %d: Got (%hd, %hd, %hd, %hd) for vertex %d %s, expected (%hd, %hd, %hd, %hd).\n",
6529 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]);
6530 break;
6532 case D3DDECLTYPE_USHORT2N:
6534 USHORT *got = (USHORT*)(got_ptr + decl_ptr->Offset);
6535 USHORT *exp = (USHORT*)(exp_ptr + decl_ptr->Offset);
6536 BOOL same = got[0] == exp[0] && got[1] == exp[1];
6537 ok_(__FILE__,line)(same, "Mesh %d: Got (%hu, %hu) for vertex %d %s, expected (%hu, %hu).\n",
6538 mesh_number, got[0], got[1], vertex_number, usage_strings[decl_ptr->Usage], exp[0], exp[1]);
6539 break;
6541 case D3DDECLTYPE_USHORT4N:
6543 USHORT *got = (USHORT*)(got_ptr + decl_ptr->Offset);
6544 USHORT *exp = (USHORT*)(exp_ptr + decl_ptr->Offset);
6545 BOOL same = got[0] == exp[0] && got[1] == exp[1]
6546 && got[2] == exp[2] && got[3] == exp[3];
6547 ok_(__FILE__,line)(same, "Mesh %d: Got (%hu, %hu, %hu, %hu) for vertex %d %s, expected (%hu, %hu, %hu, %hu).\n",
6548 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]);
6549 break;
6551 case D3DDECLTYPE_UDEC3:
6553 DWORD *got = (DWORD*)(got_ptr + decl_ptr->Offset);
6554 DWORD *exp = (DWORD*)(exp_ptr + decl_ptr->Offset);
6555 BOOL same = memcmp(got, exp, sizeof(*got)) == 0;
6556 struct udec3 got_udec3 = dword_to_udec3(*got);
6557 struct udec3 exp_udec3 = dword_to_udec3(*exp);
6558 ok_(__FILE__,line)(same, "Mesh %d: Got (%u, %u, %u, %u) for vertex %d %s, expected (%u, %u, %u, %u).\n",
6559 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);
6561 break;
6563 case D3DDECLTYPE_DEC3N:
6565 DWORD *got = (DWORD*)(got_ptr + decl_ptr->Offset);
6566 DWORD *exp = (DWORD*)(exp_ptr + decl_ptr->Offset);
6567 BOOL same = memcmp(got, exp, sizeof(*got)) == 0;
6568 struct dec3n got_dec3n = dword_to_dec3n(*got);
6569 struct dec3n exp_dec3n = dword_to_dec3n(*exp);
6570 ok_(__FILE__,line)(same, "Mesh %d: Got (%d, %d, %d, %d) for vertex %d %s, expected (%d, %d, %d, %d).\n",
6571 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);
6572 break;
6574 case D3DDECLTYPE_FLOAT16_2:
6576 WORD *got = (WORD*)(got_ptr + decl_ptr->Offset);
6577 WORD *exp = (WORD*)(exp_ptr + decl_ptr->Offset);
6578 BOOL same = got[0] == exp[0] && got[1] == exp[1];
6579 ok_(__FILE__,line)(same, "Mesh %d: Got (%hx, %hx) for vertex %d %s, expected (%hx, %hx).\n",
6580 mesh_number, got[0], got[1], vertex_number, usage_strings[decl_ptr->Usage], exp[0], exp[1]);
6581 break;
6583 case D3DDECLTYPE_FLOAT16_4:
6585 WORD *got = (WORD*)(got_ptr + decl_ptr->Offset);
6586 WORD *exp = (WORD*)(exp_ptr + decl_ptr->Offset);
6587 BOOL same = got[0] == exp[0] && got[1] == exp[1]
6588 && got[2] == exp[2] && got[3] == exp[3];
6589 ok_(__FILE__,line)(same, "Mesh %d: Got (%hx, %hx, %hx, %hx) for vertex %d %s, expected (%hx, %hx, %hx, %hx).\n",
6590 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]);
6591 break;
6593 default:
6594 break;
6599 static void test_weld_vertices(void)
6601 HRESULT hr;
6602 struct test_context *test_context = NULL;
6603 DWORD i;
6604 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
6605 const DWORD options_16bit = D3DXMESH_SYSTEMMEM;
6606 BYTE *vertices = NULL;
6607 DWORD *indices = NULL;
6608 WORD *indices_16bit = NULL;
6609 const UINT VERTS_PER_FACE = 3;
6610 const D3DXVECTOR3 up = {0.0f, 0.0f, 1.0f};
6611 struct vertex_normal
6613 D3DXVECTOR3 position;
6614 D3DXVECTOR3 normal;
6616 struct vertex_blendweight
6618 D3DXVECTOR3 position;
6619 FLOAT blendweight;
6621 struct vertex_texcoord
6623 D3DXVECTOR3 position;
6624 D3DXVECTOR2 texcoord;
6626 struct vertex_color
6628 D3DXVECTOR3 position;
6629 DWORD color;
6631 struct vertex_color_ubyte4
6633 D3DXVECTOR3 position;
6634 BYTE color[4];
6636 struct vertex_texcoord_short2
6638 D3DXVECTOR3 position;
6639 SHORT texcoord[2];
6641 struct vertex_texcoord_ushort2n
6643 D3DXVECTOR3 position;
6644 USHORT texcoord[2];
6646 struct vertex_normal_short4
6648 D3DXVECTOR3 position;
6649 SHORT normal[4];
6651 struct vertex_texcoord_float16_2
6653 D3DXVECTOR3 position;
6654 WORD texcoord[2];
6656 struct vertex_texcoord_float16_4
6658 D3DXVECTOR3 position;
6659 WORD texcoord[4];
6661 struct vertex_normal_udec3
6663 D3DXVECTOR3 position;
6664 DWORD normal;
6666 struct vertex_normal_dec3n
6668 D3DXVECTOR3 position;
6669 DWORD normal;
6671 UINT vertex_size_normal = sizeof(struct vertex_normal);
6672 UINT vertex_size_blendweight = sizeof(struct vertex_blendweight);
6673 UINT vertex_size_texcoord = sizeof(struct vertex_texcoord);
6674 UINT vertex_size_color = sizeof(struct vertex_color);
6675 UINT vertex_size_color_ubyte4 = sizeof(struct vertex_color_ubyte4);
6676 UINT vertex_size_texcoord_short2 = sizeof(struct vertex_texcoord_short2);
6677 UINT vertex_size_normal_short4 = sizeof(struct vertex_normal_short4);
6678 UINT vertex_size_texcoord_float16_2 = sizeof(struct vertex_texcoord_float16_2);
6679 UINT vertex_size_texcoord_float16_4 = sizeof(struct vertex_texcoord_float16_4);
6680 UINT vertex_size_normal_udec3 = sizeof(struct vertex_normal_udec3);
6681 UINT vertex_size_normal_dec3n = sizeof(struct vertex_normal_dec3n);
6682 D3DVERTEXELEMENT9 declaration_normal[] =
6684 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6685 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6686 D3DDECL_END()
6688 D3DVERTEXELEMENT9 declaration_normal3[] =
6690 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 3},
6691 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6692 D3DDECL_END()
6694 D3DVERTEXELEMENT9 declaration_blendweight[] =
6696 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6697 {0, 12, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BLENDWEIGHT, 0},
6698 D3DDECL_END()
6700 D3DVERTEXELEMENT9 declaration_texcoord[] =
6702 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6703 {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6704 D3DDECL_END()
6706 D3DVERTEXELEMENT9 declaration_color[] =
6708 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6709 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
6710 D3DDECL_END()
6712 D3DVERTEXELEMENT9 declaration_color_ubyte4n[] =
6714 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6715 {0, 12, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
6716 D3DDECL_END()
6718 D3DVERTEXELEMENT9 declaration_color_ubyte4[] =
6720 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6721 {0, 12, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
6722 D3DDECL_END()
6724 D3DVERTEXELEMENT9 declaration_texcoord_short2[] =
6726 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6727 {0, 12, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6728 D3DDECL_END()
6730 D3DVERTEXELEMENT9 declaration_texcoord_short2n[] =
6732 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6733 {0, 12, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6734 D3DDECL_END()
6736 D3DVERTEXELEMENT9 declaration_texcoord_ushort2n[] =
6738 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6739 {0, 12, D3DDECLTYPE_USHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6740 D3DDECL_END()
6742 D3DVERTEXELEMENT9 declaration_normal_short4[] =
6744 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6745 {0, 12, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6746 D3DDECL_END()
6748 D3DVERTEXELEMENT9 declaration_normal_short4n[] =
6750 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6751 {0, 12, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6752 D3DDECL_END()
6754 D3DVERTEXELEMENT9 declaration_normal_ushort4n[] =
6756 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6757 {0, 12, D3DDECLTYPE_USHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6758 D3DDECL_END()
6760 D3DVERTEXELEMENT9 declaration_texcoord10[] =
6762 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6763 {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 10},
6764 D3DDECL_END()
6766 D3DVERTEXELEMENT9 declaration_color2[] =
6768 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6769 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 2},
6770 D3DDECL_END()
6772 D3DVERTEXELEMENT9 declaration_color1[] =
6774 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6775 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 1},
6776 D3DDECL_END()
6778 D3DVERTEXELEMENT9 declaration_texcoord_float16_2[] =
6780 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6781 {0, 12, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6782 D3DDECL_END()
6784 D3DVERTEXELEMENT9 declaration_texcoord_float16_4[] =
6786 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6787 {0, 12, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6788 D3DDECL_END()
6790 D3DVERTEXELEMENT9 declaration_normal_udec3[] =
6792 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6793 {0, 12, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6794 D3DDECL_END()
6796 D3DVERTEXELEMENT9 declaration_normal_dec3n[] =
6798 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6799 {0, 12, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6800 D3DDECL_END()
6802 /* Test 0. One face and no welding.
6804 * 0--1
6805 * | /
6806 * |/
6809 const struct vertex vertices0[] =
6811 {{ 0.0f, 3.0f, 0.f}, up},
6812 {{ 2.0f, 3.0f, 0.f}, up},
6813 {{ 0.0f, 0.0f, 0.f}, up},
6815 const DWORD indices0[] = {0, 1, 2};
6816 const DWORD attributes0[] = {0};
6817 const DWORD exp_indices0[] = {0, 1, 2};
6818 const UINT num_vertices0 = ARRAY_SIZE(vertices0);
6819 const UINT num_faces0 = ARRAY_SIZE(indices0) / VERTS_PER_FACE;
6820 const DWORD flags0 = D3DXWELDEPSILONS_WELDALL;
6821 /* epsilons0 is NULL */
6822 const DWORD adjacency0[] = {-1, -1, -1};
6823 const struct vertex exp_vertices0[] =
6825 {{ 0.0f, 3.0f, 0.f}, up},
6826 {{ 2.0f, 3.0f, 0.f}, up},
6827 {{ 0.0f, 0.0f, 0.f}, up},
6829 const DWORD exp_face_remap0[] = {0};
6830 const DWORD exp_vertex_remap0[] = {0, 1, 2};
6831 const DWORD exp_new_num_vertices0 = ARRAY_SIZE(exp_vertices0);
6832 /* Test 1. Two vertices should be removed without regard to epsilon.
6834 * 0--1 3
6835 * | / /|
6836 * |/ / |
6837 * 2 5--4
6839 const struct vertex_normal vertices1[] =
6841 {{ 0.0f, 3.0f, 0.f}, up},
6842 {{ 2.0f, 3.0f, 0.f}, up},
6843 {{ 0.0f, 0.0f, 0.f}, up},
6845 {{ 3.0f, 3.0f, 0.f}, up},
6846 {{ 3.0f, 0.0f, 0.f}, up},
6847 {{ 1.0f, 0.0f, 0.f}, up},
6849 const DWORD indices1[] = {0, 1, 2, 3, 4, 5};
6850 const DWORD attributes1[] = {0, 0};
6851 const UINT num_vertices1 = ARRAY_SIZE(vertices1);
6852 const UINT num_faces1 = ARRAY_SIZE(indices1) / VERTS_PER_FACE;
6853 const DWORD flags1 = D3DXWELDEPSILONS_WELDALL;
6854 /* epsilons1 is NULL */
6855 const DWORD adjacency1[] = {-1, 1, -1, -1, -1, 0};
6856 const struct vertex_normal exp_vertices1[] =
6858 {{ 0.0f, 3.0f, 0.f}, up},
6859 {{ 2.0f, 3.0f, 0.f}, up},
6860 {{ 0.0f, 0.0f, 0.f}, up},
6862 {{ 3.0f, 0.0f, 0.f}, up}
6864 const DWORD exp_indices1[] = {0, 1, 2, 1, 3, 2};
6865 const DWORD exp_face_remap1[] = {0, 1};
6866 const DWORD exp_vertex_remap1[] = {0, 1, 2, 4, -1, -1};
6867 const DWORD exp_new_num_vertices1 = ARRAY_SIZE(exp_vertices1);
6868 /* Test 2. Two faces. No vertices should be removed because of normal
6869 * epsilon, but the positions should be replaced. */
6870 const struct vertex_normal vertices2[] =
6872 {{ 0.0f, 3.0f, 0.f}, up},
6873 {{ 2.0f, 3.0f, 0.f}, up},
6874 {{ 0.0f, 0.0f, 0.f}, up},
6876 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
6877 {{ 3.0f, 0.0f, 0.f}, up},
6878 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6880 const DWORD indices2[] = {0, 1, 2, 3, 4, 5};
6881 const DWORD attributes2[] = {0, 0};
6882 const UINT num_vertices2 = ARRAY_SIZE(vertices2);
6883 const UINT num_faces2 = ARRAY_SIZE(indices2) / VERTS_PER_FACE;
6884 DWORD flags2 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
6885 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};
6886 const DWORD adjacency2[] = {-1, 1, -1, -1, -1, 0};
6887 const struct vertex_normal exp_vertices2[] =
6889 {{ 0.0f, 3.0f, 0.f}, up},
6890 {{ 2.0f, 3.0f, 0.f}, up},
6891 {{ 0.0f, 0.0f, 0.f}, up},
6893 {{ 2.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
6894 {{ 3.0f, 0.0f, 0.f}, up},
6895 {{ 0.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6897 const DWORD exp_indices2[] = {0, 1, 2, 3, 4, 5};
6898 const DWORD exp_face_remap2[] = {0, 1};
6899 const DWORD exp_vertex_remap2[] = {0, 1, 2, 3, 4, 5};
6900 const DWORD exp_new_num_vertices2 = ARRAY_SIZE(exp_vertices2);
6901 /* Test 3. Two faces. One vertex should be removed because of normal epsilon. */
6902 const struct vertex_normal vertices3[] =
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, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
6909 {{ 3.0f, 0.0f, 0.f}, up},
6910 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6912 const DWORD indices3[] = {0, 1, 2, 3, 4, 5};
6913 const DWORD attributes3[] = {0, 0};
6914 const UINT num_vertices3 = ARRAY_SIZE(vertices3);
6915 const UINT num_faces3 = ARRAY_SIZE(indices3) / VERTS_PER_FACE;
6916 DWORD flags3 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
6917 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};
6918 const DWORD adjacency3[] = {-1, 1, -1, -1, -1, 0};
6919 const struct vertex_normal exp_vertices3[] =
6921 {{ 0.0f, 3.0f, 0.f}, up},
6922 {{ 2.0f, 3.0f, 0.f}, up},
6923 {{ 0.0f, 0.0f, 0.f}, up},
6925 {{ 3.0f, 0.0f, 0.f}, up},
6926 {{ 0.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6928 const DWORD exp_indices3[] = {0, 1, 2, 1, 3, 4};
6929 const DWORD exp_face_remap3[] = {0, 1};
6930 const DWORD exp_vertex_remap3[] = {0, 1, 2, 4, 5, -1};
6931 const DWORD exp_new_num_vertices3 = ARRAY_SIZE(exp_vertices3);
6932 /* Test 4 Two faces. Two vertices should be removed. */
6933 const struct vertex_normal vertices4[] =
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 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
6940 {{ 3.0f, 0.0f, 0.f}, up},
6941 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6943 const DWORD indices4[] = {0, 1, 2, 3, 4, 5};
6944 const DWORD attributes4[] = {0, 0};
6945 const UINT num_vertices4 = ARRAY_SIZE(vertices4);
6946 const UINT num_faces4 = ARRAY_SIZE(indices4) / VERTS_PER_FACE;
6947 DWORD flags4 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
6948 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};
6949 const DWORD adjacency4[] = {-1, 1, -1, -1, -1, 0};
6950 const struct vertex_normal exp_vertices4[] =
6952 {{ 0.0f, 3.0f, 0.f}, up},
6953 {{ 2.0f, 3.0f, 0.f}, up},
6954 {{ 0.0f, 0.0f, 0.f}, up},
6956 {{ 3.0f, 0.0f, 0.f}, up},
6958 const DWORD exp_indices4[] = {0, 1, 2, 1, 3, 2};
6959 const DWORD exp_face_remap4[] = {0, 1};
6960 const DWORD exp_vertex_remap4[] = {0, 1, 2, 4, -1, -1};
6961 const DWORD exp_new_num_vertices4 = ARRAY_SIZE(exp_vertices4);
6962 /* Test 5. Odd face ordering.
6964 * 0--1 6 3
6965 * | / /| |\
6966 * |/ / | | \
6967 * 2 8--7 5--4
6969 const struct vertex_normal vertices5[] =
6971 {{ 0.0f, 3.0f, 0.f}, up},
6972 {{ 2.0f, 3.0f, 0.f}, up},
6973 {{ 0.0f, 0.0f, 0.f}, up},
6975 {{ 3.0f, 3.0f, 0.f}, up},
6976 {{ 3.0f, 0.0f, 0.f}, up},
6977 {{ 1.0f, 0.0f, 0.f}, up},
6979 {{ 4.0f, 3.0f, 0.f}, up},
6980 {{ 6.0f, 0.0f, 0.f}, up},
6981 {{ 4.0f, 0.0f, 0.f}, up},
6983 const DWORD indices5[] = {0, 1, 2, 6, 7, 8, 3, 4, 5};
6984 const DWORD exp_indices5[] = {0, 1, 2, 1, 4, 2, 1, 3, 4};
6985 const DWORD attributes5[] = {0, 0, 0};
6986 const UINT num_vertices5 = ARRAY_SIZE(vertices5);
6987 const UINT num_faces5 = ARRAY_SIZE(indices5) / VERTS_PER_FACE;
6988 DWORD flags5 = D3DXWELDEPSILONS_WELDALL;
6989 const DWORD adjacency5[] = {-1, 1, -1, 2, -1, 0, -1, -1, 1};
6990 const struct vertex_normal exp_vertices5[] =
6992 {{ 0.0f, 3.0f, 0.f}, up},
6993 {{ 2.0f, 3.0f, 0.f}, up},
6994 {{ 0.0f, 0.0f, 0.f}, up},
6996 {{ 3.0f, 0.0f, 0.f}, up},
6997 {{ 1.0f, 0.0f, 0.f}, up},
6999 const DWORD exp_face_remap5[] = {0, 1, 2};
7000 const DWORD exp_vertex_remap5[] = {0, 1, 2, 4, 5, -1, -1, -1, -1};
7001 const DWORD exp_new_num_vertices5 = ARRAY_SIZE(exp_vertices5);
7002 /* Test 6. Two faces. Do not remove flag is used, so no vertices should be
7003 * removed. */
7004 const struct vertex_normal vertices6[] =
7006 {{ 0.0f, 3.0f, 0.f}, up},
7007 {{ 2.0f, 3.0f, 0.f}, up},
7008 {{ 0.0f, 0.0f, 0.f}, up},
7010 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
7011 {{ 3.0f, 0.0f, 0.f}, up},
7012 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
7014 const DWORD indices6[] = {0, 1, 2, 3, 4, 5};
7015 const DWORD attributes6[] = {0, 0};
7016 const UINT num_vertices6 = ARRAY_SIZE(vertices6);
7017 const UINT num_faces6 = ARRAY_SIZE(indices6) / VERTS_PER_FACE;
7018 DWORD flags6 = D3DXWELDEPSILONS_WELDPARTIALMATCHES | D3DXWELDEPSILONS_DONOTREMOVEVERTICES;
7019 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};
7020 const DWORD adjacency6[] = {-1, 1, -1, -1, -1, 0};
7021 const struct vertex_normal exp_vertices6[] =
7023 {{ 0.0f, 3.0f, 0.f}, up},
7024 {{ 2.0f, 3.0f, 0.f}, up},
7025 {{ 0.0f, 0.0f, 0.f}, up},
7027 {{ 2.0f, 3.0f, 0.f}, up},
7028 {{ 3.0f, 0.0f, 0.f}, up},
7029 {{ 0.0f, 0.0f, 0.f}, up},
7032 const DWORD exp_indices6[] = {0, 1, 2, 3, 4, 5};
7033 const DWORD exp_face_remap6[] = {0, 1};
7034 const DWORD exp_vertex_remap6[] = {0, 1, 2, 3, 4, 5};
7035 const DWORD exp_new_num_vertices6 = ARRAY_SIZE(exp_vertices6);
7036 /* Test 7. Same as test 6 but with 16 bit indices. */
7037 const WORD indices6_16bit[] = {0, 1, 2, 3, 4, 5};
7038 /* Test 8. No flags. Same result as D3DXWELDEPSILONS_WELDPARTIALMATCHES. */
7039 const struct vertex_normal vertices8[] =
7041 {{ 0.0f, 3.0f, 0.f}, up},
7042 {{ 2.0f, 3.0f, 0.f}, up},
7043 {{ 0.0f, 0.0f, 0.f}, up},
7045 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
7046 {{ 3.0f, 0.0f, 0.f}, up},
7047 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
7049 const DWORD indices8[] = {0, 1, 2, 1, 3, 4};
7050 const DWORD attributes8[] = {0, 0};
7051 const UINT num_vertices8 = ARRAY_SIZE(vertices8);
7052 const UINT num_faces8 = ARRAY_SIZE(indices8) / VERTS_PER_FACE;
7053 DWORD flags8 = 0;
7054 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};
7055 const DWORD adjacency8[] = {-1, 1, -1, -1, -1, 0};
7056 const struct vertex_normal exp_vertices8[] =
7058 {{ 0.0f, 3.0f, 0.f}, up},
7059 {{ 2.0f, 3.0f, 0.f}, up},
7060 {{ 0.0f, 0.0f, 0.f}, up},
7062 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
7063 {{ 3.0f, 0.0f, 0.f}, up},
7065 const DWORD exp_indices8[] = {0, 1, 2, 1, 3, 4};
7066 const DWORD exp_face_remap8[] = {0, 1};
7067 const DWORD exp_vertex_remap8[] = {0, 1, 2, 3, 4, -1};
7068 const DWORD exp_new_num_vertices8 = ARRAY_SIZE(exp_vertices8);
7069 /* Test 9. Vertices are removed even though they belong to separate
7070 * attribute groups if D3DXWELDEPSILONS_DONOTSPLIT is set. */
7071 const struct vertex_normal vertices9[] =
7073 {{ 0.0f, 3.0f, 0.f}, up},
7074 {{ 2.0f, 3.0f, 0.f}, up},
7075 {{ 0.0f, 0.0f, 0.f}, up},
7077 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
7078 {{ 3.0f, 0.0f, 0.f}, up},
7079 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
7081 const DWORD indices9[] = {0, 1, 2, 3, 4, 5};
7082 const DWORD attributes9[] = {0, 1};
7083 const UINT num_vertices9 = ARRAY_SIZE(vertices9);
7084 const UINT num_faces9 = ARRAY_SIZE(indices9) / VERTS_PER_FACE;
7085 DWORD flags9 = D3DXWELDEPSILONS_WELDPARTIALMATCHES | D3DXWELDEPSILONS_DONOTSPLIT;
7086 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};
7087 const DWORD adjacency9[] = {-1, 1, -1, -1, -1, 0};
7088 const struct vertex_normal exp_vertices9[] =
7090 {{ 0.0f, 3.0f, 0.f}, up},
7091 {{ 2.0f, 3.0f, 0.f}, up},
7092 {{ 0.0f, 0.0f, 0.f}, up},
7094 {{ 3.0f, 0.0f, 0.f}, up},
7096 const DWORD exp_indices9[] = {0, 1, 2, 1, 3, 2};
7097 const DWORD exp_face_remap9[] = {0, 1};
7098 const DWORD exp_vertex_remap9[] = {0, 1, 2, 4, -1, -1};
7099 const DWORD exp_new_num_vertices9 = ARRAY_SIZE(exp_vertices9);
7100 /* Test 10. Weld blendweight (FLOAT1). */
7101 const struct vertex_blendweight vertices10[] =
7103 {{ 0.0f, 3.0f, 0.f}, 1.0f},
7104 {{ 2.0f, 3.0f, 0.f}, 1.0f},
7105 {{ 0.0f, 0.0f, 0.f}, 1.0f},
7107 {{ 3.0f, 3.0f, 0.f}, 0.9},
7108 {{ 3.0f, 0.0f, 0.f}, 1.0},
7109 {{ 1.0f, 0.0f, 0.f}, 0.4},
7111 const DWORD indices10[] = {0, 1, 2, 3, 4, 5};
7112 const DWORD attributes10[] = {0, 0};
7113 const UINT num_vertices10 = ARRAY_SIZE(vertices10);
7114 const UINT num_faces10 = ARRAY_SIZE(indices10) / VERTS_PER_FACE;
7115 DWORD flags10 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7116 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};
7117 const DWORD adjacency10[] = {-1, 1, -1, -1, -1, 0};
7118 const struct vertex_blendweight exp_vertices10[] =
7120 {{ 0.0f, 3.0f, 0.f}, 1.0f},
7121 {{ 2.0f, 3.0f, 0.f}, 1.0f},
7122 {{ 0.0f, 0.0f, 0.f}, 1.0f},
7124 {{ 3.0f, 0.0f, 0.f}, 1.0},
7125 {{ 0.0f, 0.0f, 0.f}, 0.4},
7127 const DWORD exp_indices10[] = {0, 1, 2, 1, 3, 4};
7128 const DWORD exp_face_remap10[] = {0, 1};
7129 const DWORD exp_vertex_remap10[] = {0, 1, 2, 4, 5, -1};
7130 const DWORD exp_new_num_vertices10 = ARRAY_SIZE(exp_vertices10);
7131 /* Test 11. Weld texture coordinates. */
7132 const struct vertex_texcoord vertices11[] =
7134 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f}},
7135 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.7f}},
7136 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
7138 {{ 3.0f, 3.0f, 0.f}, {0.2f, 0.3f}},
7139 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f}},
7140 {{ 1.0f, 0.0f, 0.f}, {0.1f, 0.2f}}
7142 const DWORD indices11[] = {0, 1, 2, 3, 4, 5};
7143 const DWORD attributes11[] = {0, 0};
7144 const UINT num_vertices11 = ARRAY_SIZE(vertices11);
7145 const UINT num_faces11 = ARRAY_SIZE(indices11) / VERTS_PER_FACE;
7146 DWORD flags11 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7147 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};
7148 const DWORD adjacency11[] = {-1, 1, -1, -1, -1, 0};
7149 const struct vertex_texcoord exp_vertices11[] =
7151 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f}},
7152 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.7f}},
7153 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
7155 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f}},
7156 {{ 0.0f, 0.0f, 0.f}, {0.1f, 0.2f}},
7158 const DWORD exp_indices11[] = {0, 1, 2, 1, 3, 4};
7159 const DWORD exp_face_remap11[] = {0, 1};
7160 const DWORD exp_vertex_remap11[] = {0, 1, 2, 4, 5, -1};
7161 const DWORD exp_new_num_vertices11 = ARRAY_SIZE(exp_vertices11);
7162 /* Test 12. Weld with color. */
7163 const struct vertex_color vertices12[] =
7165 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7166 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7167 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7169 {{ 3.0f, 3.0f, 0.f}, 0x00000000},
7170 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7171 {{ 1.0f, 0.0f, 0.f}, 0x88888888},
7173 const DWORD indices12[] = {0, 1, 2, 3, 4, 5};
7174 const DWORD attributes12[] = {0, 0};
7175 const UINT num_vertices12 = ARRAY_SIZE(vertices12);
7176 const UINT num_faces12 = ARRAY_SIZE(indices12) / VERTS_PER_FACE;
7177 DWORD flags12 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7178 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};
7179 const DWORD adjacency12[] = {-1, 1, -1, -1, -1, 0};
7180 const struct vertex_color exp_vertices12[] =
7182 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7183 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7184 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7186 {{ 2.0f, 3.0f, 0.f}, 0x00000000},
7187 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7189 const DWORD exp_indices12[] = {0, 1, 2, 3, 4, 2};
7190 const DWORD exp_face_remap12[] = {0, 1};
7191 const DWORD exp_vertex_remap12[] = {0, 1, 2, 3, 4, -1};
7192 const DWORD exp_new_num_vertices12 = ARRAY_SIZE(exp_vertices12);
7193 /* Test 13. Two faces. One vertex should be removed because of normal epsilon.
7194 * This is similar to test 3, but the declaration has been changed to NORMAL3.
7196 const struct vertex_normal vertices13[] =
7198 {{ 0.0f, 3.0f, 0.f}, up},
7199 {{ 2.0f, 3.0f, 0.f}, up},
7200 {{ 0.0f, 0.0f, 0.f}, up},
7202 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
7203 {{ 3.0f, 0.0f, 0.f}, up},
7204 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
7206 const DWORD indices13[] = {0, 1, 2, 3, 4, 5};
7207 const DWORD attributes13[] = {0, 0};
7208 const UINT num_vertices13 = ARRAY_SIZE(vertices3);
7209 const UINT num_faces13 = ARRAY_SIZE(indices3) / VERTS_PER_FACE;
7210 DWORD flags13 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7211 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};
7212 const DWORD adjacency13[] = {-1, 1, -1, -1, -1, 0};
7213 const struct vertex_normal exp_vertices13[] =
7215 {{ 0.0f, 3.0f, 0.f}, up},
7216 {{ 2.0f, 3.0f, 0.f}, up},
7217 {{ 0.0f, 0.0f, 0.f}, up},
7219 {{ 3.0f, 0.0f, 0.f}, up},
7220 {{ 0.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
7222 const DWORD exp_indices13[] = {0, 1, 2, 1, 3, 4};
7223 const DWORD exp_face_remap13[] = {0, 1};
7224 const DWORD exp_vertex_remap13[] = {0, 1, 2, 4, 5, -1};
7225 const DWORD exp_new_num_vertices13 = ARRAY_SIZE(exp_vertices13);
7226 /* Test 14. Another test for welding with color. */
7227 const struct vertex_color vertices14[] =
7229 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7230 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7231 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7233 {{ 3.0f, 3.0f, 0.f}, 0x00000000},
7234 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7235 {{ 1.0f, 0.0f, 0.f}, 0x01010101},
7237 const DWORD indices14[] = {0, 1, 2, 3, 4, 5};
7238 const DWORD attributes14[] = {0, 0};
7239 const UINT num_vertices14 = ARRAY_SIZE(vertices14);
7240 const UINT num_faces14 = ARRAY_SIZE(indices14) / VERTS_PER_FACE;
7241 DWORD flags14 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7242 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};
7243 const DWORD adjacency14[] = {-1, 1, -1, -1, -1, 0};
7244 const struct vertex_color exp_vertices14[] =
7246 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7247 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7248 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7250 {{ 2.0f, 3.0f, 0.f}, 0x00000000},
7251 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7253 const DWORD exp_indices14[] = {0, 1, 2, 3, 4, 2};
7254 const DWORD exp_face_remap14[] = {0, 1};
7255 const DWORD exp_vertex_remap14[] = {0, 1, 2, 3, 4, -1};
7256 const DWORD exp_new_num_vertices14 = ARRAY_SIZE(exp_vertices14);
7257 /* Test 15. Weld with color, but as UBYTE4N instead of D3DCOLOR. It shows
7258 * that UBYTE4N and D3DCOLOR are compared the same way.
7260 const struct vertex_color_ubyte4 vertices15[] =
7262 {{ 0.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7263 {{ 2.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7264 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7266 {{ 3.0f, 3.0f, 0.f}, { 0, 0, 0, 0}},
7267 {{ 3.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7268 {{ 1.0f, 0.0f, 0.f}, { 1, 1, 1, 1}},
7270 const DWORD indices15[] = {0, 1, 2, 3, 4, 5};
7271 const DWORD attributes15[] = {0, 0};
7272 const UINT num_vertices15 = ARRAY_SIZE(vertices15);
7273 const UINT num_faces15 = ARRAY_SIZE(indices15) / VERTS_PER_FACE;
7274 DWORD flags15 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7275 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};
7276 const DWORD adjacency15[] = {-1, 1, -1, -1, -1, 0};
7277 const struct vertex_color_ubyte4 exp_vertices15[] =
7279 {{ 0.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7280 {{ 2.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7281 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7283 {{ 2.0f, 3.0f, 0.f}, { 0, 0, 0, 0}},
7284 {{ 3.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7286 const DWORD exp_indices15[] = {0, 1, 2, 3, 4, 2};
7287 const DWORD exp_face_remap15[] = {0, 1};
7288 const DWORD exp_vertex_remap15[] = {0, 1, 2, 3, 4, -1};
7289 const DWORD exp_new_num_vertices15 = ARRAY_SIZE(exp_vertices15);
7290 /* Test 16. Weld with color, but as UBYTE4 instead of D3DCOLOR. It shows
7291 * that UBYTE4 is not normalized and that epsilon is truncated and compared
7292 * directly to each of the four bytes.
7294 const struct vertex_color_ubyte4 vertices16[] =
7296 {{ 0.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7297 {{ 2.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7298 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7300 {{ 3.0f, 3.0f, 0.f}, { 0, 0, 0, 0}},
7301 {{ 3.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7302 {{ 1.0f, 0.0f, 0.f}, { 1, 1, 1, 1}},
7304 const DWORD indices16[] = {0, 1, 2, 3, 4, 5};
7305 const DWORD attributes16[] = {0, 0};
7306 const UINT num_vertices16 = ARRAY_SIZE(vertices16);
7307 const UINT num_faces16 = ARRAY_SIZE(indices16) / VERTS_PER_FACE;
7308 DWORD flags16 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7309 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};
7310 const DWORD adjacency16[] = {-1, 1, -1, -1, -1, 0};
7311 const struct vertex_color_ubyte4 exp_vertices16[] =
7313 {{ 0.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7314 {{ 2.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7315 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7317 {{ 2.0f, 3.0f, 0.f}, { 0, 0, 0, 0}},
7318 {{ 3.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7320 const DWORD exp_indices16[] = {0, 1, 2, 3, 4, 2};
7321 const DWORD exp_face_remap16[] = {0, 1};
7322 const DWORD exp_vertex_remap16[] = {0, 1, 2, 3, 4, -1};
7323 const DWORD exp_new_num_vertices16 = ARRAY_SIZE(exp_vertices16);
7324 /* Test 17. Weld texture coordinates but as SHORT2 instead of D3DXVECTOR2.*/
7325 const struct vertex_texcoord_short2 vertices17[] =
7327 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7328 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7329 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7331 {{ 3.0f, 3.0f, 0.f}, {32767, 32767}},
7332 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7333 {{ 1.0f, 0.0f, 0.f}, {32766, 32766}},
7335 const DWORD indices17[] = {0, 1, 2, 3, 4, 5};
7336 const DWORD attributes17[] = {0, 0};
7337 const UINT num_vertices17 = ARRAY_SIZE(vertices17);
7338 const UINT num_faces17 = ARRAY_SIZE(indices17) / VERTS_PER_FACE;
7339 DWORD flags17 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7340 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};
7341 const DWORD adjacency17[] = {-1, 1, -1, -1, -1, 0};
7342 const struct vertex_texcoord_short2 exp_vertices17[] =
7344 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7345 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7346 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7348 {{ 2.0f, 3.0f, 0.f}, {32767, 32767}},
7349 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7351 const DWORD exp_indices17[] = {0, 1, 2, 3, 4, 2};
7352 const DWORD exp_face_remap17[] = {0, 1};
7353 const DWORD exp_vertex_remap17[] = {0, 1, 2, 3, 4, -1};
7354 const DWORD exp_new_num_vertices17 = ARRAY_SIZE(exp_vertices17);
7355 /* Test 18. Weld texture coordinates but as SHORT2N instead of D3DXVECTOR2. */
7356 const struct vertex_texcoord_short2 vertices18[] =
7358 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7359 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7360 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7362 {{ 3.0f, 3.0f, 0.f}, {32767, 32767}},
7363 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7364 {{ 1.0f, 0.0f, 0.f}, {32766, 32766}},
7366 const DWORD indices18[] = {0, 1, 2, 3, 4, 5};
7367 const DWORD attributes18[] = {0, 0};
7368 const UINT num_vertices18 = ARRAY_SIZE(vertices18);
7369 const UINT num_faces18 = ARRAY_SIZE(indices18) / VERTS_PER_FACE;
7370 DWORD flags18 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7371 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};
7372 const DWORD adjacency18[] = {-1, 1, -1, -1, -1, 0};
7373 const struct vertex_texcoord_short2 exp_vertices18[] =
7375 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7376 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7377 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7379 {{ 2.0f, 3.0f, 0.f}, {32767, 32767}},
7380 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7382 const DWORD exp_indices18[] = {0, 1, 2, 3, 4, 2};
7383 const DWORD exp_face_remap18[] = {0, 1};
7384 const DWORD exp_vertex_remap18[] = {0, 1, 2, 3, 4, -1};
7385 const DWORD exp_new_num_vertices18 = ARRAY_SIZE(exp_vertices18);
7386 /* Test 19. Weld texture coordinates but as USHORT2N instead of D3DXVECTOR2. */
7387 const struct vertex_texcoord_ushort2n vertices19[] =
7389 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7390 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7391 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7393 {{ 3.0f, 3.0f, 0.f}, {65535, 65535}},
7394 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7395 {{ 1.0f, 0.0f, 0.f}, {65534, 65534}},
7397 const DWORD indices19[] = {0, 1, 2, 3, 4, 5};
7398 const DWORD attributes19[] = {0, 0};
7399 const UINT num_vertices19 = ARRAY_SIZE(vertices19);
7400 const UINT num_faces19 = ARRAY_SIZE(indices19) / VERTS_PER_FACE;
7401 DWORD flags19 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7402 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};
7403 const DWORD adjacency19[] = {-1, 1, -1, -1, -1, 0};
7404 const struct vertex_texcoord_ushort2n exp_vertices19[] =
7406 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7407 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7408 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7410 {{ 2.0f, 3.0f, 0.f}, {65535, 65535}},
7411 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7413 const DWORD exp_indices19[] = {0, 1, 2, 3, 4, 2};
7414 const DWORD exp_face_remap19[] = {0, 1};
7415 const DWORD exp_vertex_remap19[] = {0, 1, 2, 3, 4, -1};
7416 const DWORD exp_new_num_vertices19 = ARRAY_SIZE(exp_vertices19);
7417 /* Test 20. Weld normal as SHORT4 instead of D3DXVECTOR3. */
7418 const struct vertex_normal_short4 vertices20[] =
7420 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7421 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7422 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7424 {{ 3.0f, 3.0f, 0.f}, {32767, 32767, 32767, 32767}},
7425 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7426 {{ 1.0f, 0.0f, 0.f}, {32766, 32766, 32766, 32766}},
7428 const DWORD indices20[] = {0, 1, 2, 3, 4, 5};
7429 const DWORD attributes20[] = {0, 0};
7430 const UINT num_vertices20 = ARRAY_SIZE(vertices20);
7431 const UINT num_faces20 = ARRAY_SIZE(indices20) / VERTS_PER_FACE;
7432 DWORD flags20 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7433 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};
7434 const DWORD adjacency20[] = {-1, 1, -1, -1, -1, 0};
7435 const struct vertex_normal_short4 exp_vertices20[] =
7437 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7438 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7439 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7441 {{ 2.0f, 3.0f, 0.f}, {32767, 32767, 32767, 32767}},
7442 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7444 const DWORD exp_indices20[] = {0, 1, 2, 3, 4, 2};
7445 const DWORD exp_face_remap20[] = {0, 1};
7446 const DWORD exp_vertex_remap20[] = {0, 1, 2, 3, 4, -1};
7447 const DWORD exp_new_num_vertices20 = ARRAY_SIZE(exp_vertices20);
7448 /* Test 21. Weld normal as SHORT4N instead of D3DXVECTOR3. */
7449 const struct vertex_normal_short4 vertices21[] =
7451 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7452 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7453 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7455 {{ 3.0f, 3.0f, 0.f}, {32767, 32767, 32767, 32767}},
7456 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7457 {{ 1.0f, 0.0f, 0.f}, {32766, 32766, 32766, 32766}},
7459 const DWORD indices21[] = {0, 1, 2, 3, 4, 5};
7460 const DWORD attributes21[] = {0, 0};
7461 const UINT num_vertices21 = ARRAY_SIZE(vertices21);
7462 const UINT num_faces21 = ARRAY_SIZE(indices21) / VERTS_PER_FACE;
7463 DWORD flags21 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7464 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};
7465 const DWORD adjacency21[] = {-1, 1, -1, -1, -1, 0};
7466 const struct vertex_normal_short4 exp_vertices21[] =
7468 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7469 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7470 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7472 {{ 2.0f, 3.0f, 0.f}, {32767, 32767, 32767, 32767}},
7473 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7475 const DWORD exp_indices21[] = {0, 1, 2, 3, 4, 2};
7476 const DWORD exp_face_remap21[] = {0, 1};
7477 const DWORD exp_vertex_remap21[] = {0, 1, 2, 3, 4, -1};
7478 const DWORD exp_new_num_vertices21 = ARRAY_SIZE(exp_vertices21);
7479 /* Test 22. Weld normal as USHORT4N instead of D3DXVECTOR3. */
7480 const struct vertex_normal_short4 vertices22[] =
7482 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7483 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7484 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7486 {{ 3.0f, 3.0f, 0.f}, {65535, 65535, 65535, 65535}},
7487 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7488 {{ 1.0f, 0.0f, 0.f}, {65534, 65534, 65534, 65534}},
7490 const DWORD indices22[] = {0, 1, 2, 3, 4, 5};
7491 const DWORD attributes22[] = {0, 0};
7492 const UINT num_vertices22 = ARRAY_SIZE(vertices22);
7493 const UINT num_faces22 = ARRAY_SIZE(indices22) / VERTS_PER_FACE;
7494 DWORD flags22 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7495 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};
7496 const DWORD adjacency22[] = {-1, 1, -1, -1, -1, 0};
7497 const struct vertex_normal_short4 exp_vertices22[] =
7499 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7500 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7501 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7503 {{ 2.0f, 3.0f, 0.f}, {65535, 65535, 65535, 65535}},
7504 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7506 const DWORD exp_indices22[] = {0, 1, 2, 3, 4, 2};
7507 const DWORD exp_face_remap22[] = {0, 1};
7508 const DWORD exp_vertex_remap22[] = {0, 1, 2, 3, 4, -1};
7509 const DWORD exp_new_num_vertices22 = ARRAY_SIZE(exp_vertices22);
7510 /* Test 23. Weld texture coordinates as FLOAT16_2. Similar to test 11, but
7511 * with texture coordinates converted to float16 in hex. */
7512 const struct vertex_texcoord_float16_2 vertices23[] =
7514 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
7515 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */
7516 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */
7518 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd}}, /* {0.2f, 0.3f} */
7519 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
7520 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */
7522 const DWORD indices23[] = {0, 1, 2, 3, 4, 5};
7523 const DWORD attributes23[] = {0, 0};
7524 const UINT num_vertices23 = ARRAY_SIZE(vertices23);
7525 const UINT num_faces23 = ARRAY_SIZE(indices23) / VERTS_PER_FACE;
7526 DWORD flags23 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7527 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};
7528 const DWORD adjacency23[] = {-1, 1, -1, -1, -1, 0};
7529 const struct vertex_texcoord_float16_2 exp_vertices23[] =
7531 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
7532 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */
7533 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */
7535 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
7536 {{ 0.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */
7538 const DWORD exp_indices23[] = {0, 1, 2, 1, 3, 4};
7539 const DWORD exp_face_remap23[] = {0, 1};
7540 const DWORD exp_vertex_remap23[] = {0, 1, 2, 4, 5, -1};
7541 const DWORD exp_new_num_vertices23 = ARRAY_SIZE(exp_vertices23);
7542 /* Test 24. Weld texture coordinates as FLOAT16_4. Similar to test 24. */
7543 const struct vertex_texcoord_float16_4 vertices24[] =
7545 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}},
7546 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a, 0x3800, 0x399a}},
7547 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd, 0xb266, 0xb4cd}},
7549 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd, 0x3266, 0x34cd}},
7550 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}},
7551 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266, 0x2e66, 0x3266}},
7553 const DWORD indices24[] = {0, 1, 2, 3, 4, 5};
7554 const DWORD attributes24[] = {0, 0};
7555 const UINT num_vertices24 = ARRAY_SIZE(vertices24);
7556 const UINT num_faces24 = ARRAY_SIZE(indices24) / VERTS_PER_FACE;
7557 DWORD flags24 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7558 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};
7559 const DWORD adjacency24[] = {-1, 1, -1, -1, -1, 0};
7560 const struct vertex_texcoord_float16_4 exp_vertices24[] =
7562 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}},
7563 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a, 0x3800, 0x399a}},
7564 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd, 0xb266, 0xb4cd}},
7566 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}},
7567 {{ 0.0f, 0.0f, 0.f}, {0x2e66, 0x3266, 0x2e66, 0x3266}},
7569 const DWORD exp_indices24[] = {0, 1, 2, 1, 3, 4};
7570 const DWORD exp_face_remap24[] = {0, 1};
7571 const DWORD exp_vertex_remap24[] = {0, 1, 2, 4, 5, -1};
7572 const DWORD exp_new_num_vertices24 = ARRAY_SIZE(exp_vertices24);
7573 /* Test 25. Weld texture coordinates with usage index 10 (TEXCOORD10). The
7574 * usage index is capped at 7, so the epsilon for TEXCOORD7 is used instead.
7576 const struct vertex_texcoord vertices25[] =
7578 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f}},
7579 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.7f}},
7580 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
7582 {{ 3.0f, 3.0f, 0.f}, {0.2f, 0.3f}},
7583 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f}},
7584 {{ 1.0f, 0.0f, 0.f}, {0.1f, 0.2f}}
7586 const DWORD indices25[] = {0, 1, 2, 3, 4, 5};
7587 const DWORD attributes25[] = {0, 0};
7588 const UINT num_vertices25 = ARRAY_SIZE(vertices25);
7589 const UINT num_faces25 = ARRAY_SIZE(indices25) / VERTS_PER_FACE;
7590 DWORD flags25 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7591 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};
7592 const DWORD adjacency25[] = {-1, 1, -1, -1, -1, 0};
7593 const struct vertex_texcoord exp_vertices25[] =
7595 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f}},
7596 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.7f}},
7597 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
7599 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f}},
7600 {{ 0.0f, 0.0f, 0.f}, {0.1f, 0.2f}},
7602 const DWORD exp_indices25[] = {0, 1, 2, 1, 3, 4};
7603 const DWORD exp_face_remap25[] = {0, 1};
7604 const DWORD exp_vertex_remap25[] = {0, 1, 2, 4, 5, -1};
7605 const DWORD exp_new_num_vertices25 = ARRAY_SIZE(exp_vertices25);
7606 /* Test 26. Weld color with usage index larger than 1. Shows that none of
7607 * the epsilon values are used. */
7608 const struct vertex_color vertices26[] =
7610 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7611 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7612 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7614 {{ 3.0f, 3.0f, 0.f}, 0x00000000},
7615 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7616 {{ 1.0f, 0.0f, 0.f}, 0x01010101},
7618 const DWORD indices26[] = {0, 1, 2, 3, 4, 5};
7619 const DWORD attributes26[] = {0, 0};
7620 const UINT num_vertices26 = ARRAY_SIZE(vertices26);
7621 const UINT num_faces26 = ARRAY_SIZE(indices26) / VERTS_PER_FACE;
7622 DWORD flags26 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7623 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};
7624 const DWORD adjacency26[] = {-1, 1, -1, -1, -1, 0};
7625 const struct vertex_color exp_vertices26[] =
7627 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7628 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7629 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7631 {{ 2.0f, 3.0f, 0.f}, 0x00000000},
7632 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7633 {{ 0.0f, 0.0f, 0.f}, 0x01010101},
7635 const DWORD exp_indices26[] = {0, 1, 2, 3, 4, 5};
7636 const DWORD exp_face_remap26[] = {0, 1};
7637 const DWORD exp_vertex_remap26[] = {0, 1, 2, 3, 4, 5};
7638 const DWORD exp_new_num_vertices26 = ARRAY_SIZE(exp_vertices26);
7639 /* Test 27. Weld color with usage index 1 (specular). */
7640 /* Previously this test used float color values and index > 1 but that case
7641 * appears to be effectively unhandled in native so the test gave
7642 * inconsistent results. */
7643 const struct vertex_color vertices27[] =
7645 {{ 0.0f, 3.0f, 0.0f}, 0x00000000},
7646 {{ 2.0f, 3.0f, 0.0f}, 0x10203040},
7647 {{ 0.0f, 0.0f, 0.0f}, 0x50607080},
7649 {{ 3.0f, 3.0f, 0.0f}, 0x11213141},
7650 {{ 3.0f, 0.0f, 0.0f}, 0xffffffff},
7651 {{ 1.0f, 0.0f, 0.0f}, 0x51617181},
7653 const DWORD indices27[] = {0, 1, 2, 3, 4, 5};
7654 const DWORD attributes27[] = {0, 0};
7655 const UINT num_vertices27 = ARRAY_SIZE(vertices27);
7656 const UINT num_faces27 = ARRAY_SIZE(indices27) / VERTS_PER_FACE;
7657 DWORD flags27 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7658 const D3DXWELDEPSILONS epsilons27 =
7660 1.1f, 0.0f, 0.0f, 0.0f, 2.0f / 255.0f, 0.0f,
7661 {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, 0.0f, 0.0f, 0.0f
7663 const DWORD adjacency27[] = {-1, 1, -1, -1, -1, 0};
7664 const struct vertex_color exp_vertices27[] =
7666 {{ 0.0f, 3.0f, 0.0f}, 0x00000000},
7667 {{ 2.0f, 3.0f, 0.0f}, 0x10203040},
7668 {{ 0.0f, 0.0f, 0.0f}, 0x50607080},
7670 {{ 3.0f, 0.0f, 0.0f}, 0xffffffff},
7672 const DWORD exp_indices27[] = {0, 1, 2, 1, 3, 2};
7673 const DWORD exp_face_remap27[] = {0, 1};
7674 const DWORD exp_vertex_remap27[] = {0, 1, 2, 4, -1, -1};
7675 const DWORD exp_new_num_vertices27 = ARRAY_SIZE(exp_vertices27);
7676 /* Test 28. Weld one normal with UDEC3. */
7677 const DWORD dword_udec3_zero = init_udec3_dword(0, 0, 0, 1);
7678 const DWORD dword_udec3_1023 = init_udec3_dword(1023, 1023, 1023, 1);
7679 const DWORD dword_udec3_1022 = init_udec3_dword(1022, 1022, 1022, 1);
7680 const struct vertex_normal_udec3 vertices28[] =
7682 {{ 0.0f, 3.0f, 0.f}, dword_udec3_zero},
7683 {{ 2.0f, 3.0f, 0.f}, dword_udec3_zero},
7684 {{ 0.0f, 0.0f, 0.f}, dword_udec3_zero},
7686 {{ 3.0f, 3.0f, 0.f}, dword_udec3_1023},
7687 {{ 3.0f, 0.0f, 0.f}, dword_udec3_zero},
7688 {{ 1.0f, 0.0f, 0.f}, dword_udec3_1022},
7690 const DWORD indices28[] = {0, 1, 2, 3, 4, 5};
7691 const DWORD attributes28[] = {0, 0};
7692 const UINT num_vertices28 = ARRAY_SIZE(vertices28);
7693 const UINT num_faces28 = ARRAY_SIZE(indices28) / VERTS_PER_FACE;
7694 DWORD flags28 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7695 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};
7696 const DWORD adjacency28[] = {-1, 1, -1, -1, -1, 0};
7697 const struct vertex_normal_udec3 exp_vertices28[] =
7699 {{ 0.0f, 3.0f, 0.f}, dword_udec3_zero},
7700 {{ 2.0f, 3.0f, 0.f}, dword_udec3_zero},
7701 {{ 0.0f, 0.0f, 0.f}, dword_udec3_zero},
7703 {{ 2.0f, 3.0f, 0.f}, dword_udec3_1023},
7704 {{ 3.0f, 0.0f, 0.f}, dword_udec3_zero},
7706 const DWORD exp_indices28[] = {0, 1, 2, 3, 4, 2};
7707 const DWORD exp_face_remap28[] = {0, 1};
7708 const DWORD exp_vertex_remap28[] = {0, 1, 2, 3, 4, -1};
7709 const DWORD exp_new_num_vertices28 = ARRAY_SIZE(exp_vertices28);
7710 /* Test 29. Weld one normal with DEC3N. */
7711 const DWORD dword_dec3n_zero = init_dec3n_dword(0, 0, 0, 1);
7712 const DWORD dword_dec3n_511 = init_dec3n_dword(511, 511, 511, 1);
7713 const DWORD dword_dec3n_510 = init_dec3n_dword(510, 510, 510, 1);
7714 const struct vertex_normal_dec3n vertices29[] =
7716 {{ 0.0f, 3.0f, 0.f}, dword_dec3n_zero},
7717 {{ 2.0f, 3.0f, 0.f}, dword_dec3n_zero},
7718 {{ 0.0f, 0.0f, 0.f}, dword_dec3n_zero},
7720 {{ 3.0f, 3.0f, 0.f}, dword_dec3n_511},
7721 {{ 3.0f, 0.0f, 0.f}, dword_dec3n_zero},
7722 {{ 1.0f, 0.0f, 0.f}, dword_dec3n_510},
7724 const DWORD indices29[] = {0, 1, 2, 3, 4, 5};
7725 const DWORD attributes29[] = {0, 0};
7726 const UINT num_vertices29 = ARRAY_SIZE(vertices29);
7727 const UINT num_faces29 = ARRAY_SIZE(indices29) / VERTS_PER_FACE;
7728 DWORD flags29 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7729 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};
7730 const DWORD adjacency29[] = {-1, 1, -1, -1, -1, 0};
7731 const struct vertex_normal_dec3n exp_vertices29[] =
7733 {{ 0.0f, 3.0f, 0.f}, dword_dec3n_zero},
7734 {{ 2.0f, 3.0f, 0.f}, dword_dec3n_zero},
7735 {{ 0.0f, 0.0f, 0.f}, dword_dec3n_zero},
7737 {{ 2.0f, 3.0f, 0.f}, dword_dec3n_511},
7738 {{ 3.0f, 0.0f, 0.f}, dword_dec3n_zero},
7740 const DWORD exp_indices29[] = {0, 1, 2, 3, 4, 2};
7741 const DWORD exp_face_remap29[] = {0, 1};
7742 const DWORD exp_vertex_remap29[] = {0, 1, 2, 3, 4, -1};
7743 const DWORD exp_new_num_vertices29 = ARRAY_SIZE(exp_vertices29);
7744 /* All mesh data */
7745 DWORD *adjacency_out = NULL;
7746 DWORD *face_remap = NULL;
7747 ID3DXMesh *mesh = NULL;
7748 ID3DXBuffer *vertex_remap = NULL;
7749 struct
7751 const BYTE *vertices;
7752 const DWORD *indices;
7753 const DWORD *attributes;
7754 const DWORD num_vertices;
7755 const DWORD num_faces;
7756 const DWORD options;
7757 D3DVERTEXELEMENT9 *declaration;
7758 const UINT vertex_size;
7759 const DWORD flags;
7760 const D3DXWELDEPSILONS *epsilons;
7761 const DWORD *adjacency;
7762 const BYTE *exp_vertices;
7763 const DWORD *exp_indices;
7764 const DWORD *exp_face_remap;
7765 const DWORD *exp_vertex_remap;
7766 const DWORD exp_new_num_vertices;
7768 tc[] =
7771 (BYTE*)vertices0,
7772 indices0,
7773 attributes0,
7774 num_vertices0,
7775 num_faces0,
7776 options,
7777 declaration_normal,
7778 vertex_size_normal,
7779 flags0,
7780 NULL,
7781 adjacency0,
7782 (BYTE*)exp_vertices0,
7783 exp_indices0,
7784 exp_face_remap0,
7785 exp_vertex_remap0,
7786 exp_new_num_vertices0
7789 (BYTE*)vertices1,
7790 indices1,
7791 attributes1,
7792 num_vertices1,
7793 num_faces1,
7794 options,
7795 declaration_normal,
7796 vertex_size_normal,
7797 flags1,
7798 NULL,
7799 adjacency1,
7800 (BYTE*)exp_vertices1,
7801 exp_indices1,
7802 exp_face_remap1,
7803 exp_vertex_remap1,
7804 exp_new_num_vertices1
7807 (BYTE*)vertices2,
7808 indices2,
7809 attributes2,
7810 num_vertices2,
7811 num_faces2,
7812 options,
7813 declaration_normal,
7814 vertex_size_normal,
7815 flags2,
7816 &epsilons2,
7817 adjacency2,
7818 (BYTE*)exp_vertices2,
7819 exp_indices2,
7820 exp_face_remap2,
7821 exp_vertex_remap2,
7822 exp_new_num_vertices2
7825 (BYTE*)vertices3,
7826 indices3,
7827 attributes3,
7828 num_vertices3,
7829 num_faces3,
7830 options,
7831 declaration_normal,
7832 vertex_size_normal,
7833 flags3,
7834 &epsilons3,
7835 adjacency3,
7836 (BYTE*)exp_vertices3,
7837 exp_indices3,
7838 exp_face_remap3,
7839 exp_vertex_remap3,
7840 exp_new_num_vertices3
7843 (BYTE*)vertices4,
7844 indices4,
7845 attributes4,
7846 num_vertices4,
7847 num_faces4,
7848 options,
7849 declaration_normal,
7850 vertex_size_normal,
7851 flags4,
7852 &epsilons4,
7853 adjacency4,
7854 (BYTE*)exp_vertices4,
7855 exp_indices4,
7856 exp_face_remap4,
7857 exp_vertex_remap4,
7858 exp_new_num_vertices4
7860 /* Unusual ordering. */
7862 (BYTE*)vertices5,
7863 indices5,
7864 attributes5,
7865 num_vertices5,
7866 num_faces5,
7867 options,
7868 declaration_normal,
7869 vertex_size_normal,
7870 flags5,
7871 NULL,
7872 adjacency5,
7873 (BYTE*)exp_vertices5,
7874 exp_indices5,
7875 exp_face_remap5,
7876 exp_vertex_remap5,
7877 exp_new_num_vertices5
7880 (BYTE*)vertices6,
7881 indices6,
7882 attributes6,
7883 num_vertices6,
7884 num_faces6,
7885 options,
7886 declaration_normal,
7887 vertex_size_normal,
7888 flags6,
7889 &epsilons6,
7890 adjacency6,
7891 (BYTE*)exp_vertices6,
7892 exp_indices6,
7893 exp_face_remap6,
7894 exp_vertex_remap6,
7895 exp_new_num_vertices6
7898 (BYTE*)vertices6,
7899 (DWORD*)indices6_16bit,
7900 attributes6,
7901 num_vertices6,
7902 num_faces6,
7903 options_16bit,
7904 declaration_normal,
7905 vertex_size_normal,
7906 flags6,
7907 &epsilons6,
7908 adjacency6,
7909 (BYTE*)exp_vertices6,
7910 exp_indices6,
7911 exp_face_remap6,
7912 exp_vertex_remap6,
7913 exp_new_num_vertices6
7916 (BYTE*)vertices8,
7917 indices8,
7918 attributes8,
7919 num_vertices8,
7920 num_faces8,
7921 options,
7922 declaration_normal,
7923 vertex_size_normal,
7924 flags8,
7925 &epsilons8,
7926 adjacency8,
7927 (BYTE*)exp_vertices8,
7928 exp_indices8,
7929 exp_face_remap8,
7930 exp_vertex_remap8,
7931 exp_new_num_vertices8
7934 (BYTE*)vertices9,
7935 indices9,
7936 attributes9,
7937 num_vertices9,
7938 num_faces9,
7939 options,
7940 declaration_normal,
7941 vertex_size_normal,
7942 flags9,
7943 &epsilons9,
7944 adjacency9,
7945 (BYTE*)exp_vertices9,
7946 exp_indices9,
7947 exp_face_remap9,
7948 exp_vertex_remap9,
7949 exp_new_num_vertices9
7952 (BYTE*)vertices10,
7953 indices10,
7954 attributes10,
7955 num_vertices10,
7956 num_faces10,
7957 options,
7958 declaration_blendweight,
7959 vertex_size_blendweight,
7960 flags10,
7961 &epsilons10,
7962 adjacency10,
7963 (BYTE*)exp_vertices10,
7964 exp_indices10,
7965 exp_face_remap10,
7966 exp_vertex_remap10,
7967 exp_new_num_vertices10
7970 (BYTE*)vertices11,
7971 indices11,
7972 attributes11,
7973 num_vertices11,
7974 num_faces11,
7975 options,
7976 declaration_texcoord,
7977 vertex_size_texcoord,
7978 flags11,
7979 &epsilons11,
7980 adjacency11,
7981 (BYTE*)exp_vertices11,
7982 exp_indices11,
7983 exp_face_remap11,
7984 exp_vertex_remap11,
7985 exp_new_num_vertices11
7988 (BYTE*)vertices12,
7989 indices12,
7990 attributes12,
7991 num_vertices12,
7992 num_faces12,
7993 options,
7994 declaration_color,
7995 vertex_size_color,
7996 flags12,
7997 &epsilons12,
7998 adjacency12,
7999 (BYTE*)exp_vertices12,
8000 exp_indices12,
8001 exp_face_remap12,
8002 exp_vertex_remap12,
8003 exp_new_num_vertices12
8006 (BYTE*)vertices13,
8007 indices13,
8008 attributes13,
8009 num_vertices13,
8010 num_faces13,
8011 options,
8012 declaration_normal3,
8013 vertex_size_normal,
8014 flags13,
8015 &epsilons13,
8016 adjacency13,
8017 (BYTE*)exp_vertices13,
8018 exp_indices13,
8019 exp_face_remap13,
8020 exp_vertex_remap13,
8021 exp_new_num_vertices13
8024 (BYTE*)vertices14,
8025 indices14,
8026 attributes14,
8027 num_vertices14,
8028 num_faces14,
8029 options,
8030 declaration_color,
8031 vertex_size_color,
8032 flags14,
8033 &epsilons14,
8034 adjacency14,
8035 (BYTE*)exp_vertices14,
8036 exp_indices14,
8037 exp_face_remap14,
8038 exp_vertex_remap14,
8039 exp_new_num_vertices14
8042 (BYTE*)vertices15,
8043 indices15,
8044 attributes15,
8045 num_vertices15,
8046 num_faces15,
8047 options,
8048 declaration_color_ubyte4n,
8049 vertex_size_color_ubyte4, /* UBYTE4 same size as UBYTE4N */
8050 flags15,
8051 &epsilons15,
8052 adjacency15,
8053 (BYTE*)exp_vertices15,
8054 exp_indices15,
8055 exp_face_remap15,
8056 exp_vertex_remap15,
8057 exp_new_num_vertices15
8060 (BYTE*)vertices16,
8061 indices16,
8062 attributes16,
8063 num_vertices16,
8064 num_faces16,
8065 options,
8066 declaration_color_ubyte4,
8067 vertex_size_color_ubyte4,
8068 flags16,
8069 &epsilons16,
8070 adjacency16,
8071 (BYTE*)exp_vertices16,
8072 exp_indices16,
8073 exp_face_remap16,
8074 exp_vertex_remap16,
8075 exp_new_num_vertices16
8078 (BYTE*)vertices17,
8079 indices17,
8080 attributes17,
8081 num_vertices17,
8082 num_faces17,
8083 options,
8084 declaration_texcoord_short2,
8085 vertex_size_texcoord_short2,
8086 flags17,
8087 &epsilons17,
8088 adjacency17,
8089 (BYTE*)exp_vertices17,
8090 exp_indices17,
8091 exp_face_remap17,
8092 exp_vertex_remap17,
8093 exp_new_num_vertices17
8096 (BYTE*)vertices18,
8097 indices18,
8098 attributes18,
8099 num_vertices18,
8100 num_faces18,
8101 options,
8102 declaration_texcoord_short2n,
8103 vertex_size_texcoord_short2, /* SHORT2 same size as SHORT2N */
8104 flags18,
8105 &epsilons18,
8106 adjacency18,
8107 (BYTE*)exp_vertices18,
8108 exp_indices18,
8109 exp_face_remap18,
8110 exp_vertex_remap18,
8111 exp_new_num_vertices18
8114 (BYTE*)vertices19,
8115 indices19,
8116 attributes19,
8117 num_vertices19,
8118 num_faces19,
8119 options,
8120 declaration_texcoord_ushort2n,
8121 vertex_size_texcoord_short2, /* SHORT2 same size as USHORT2N */
8122 flags19,
8123 &epsilons19,
8124 adjacency19,
8125 (BYTE*)exp_vertices19,
8126 exp_indices19,
8127 exp_face_remap19,
8128 exp_vertex_remap19,
8129 exp_new_num_vertices19
8132 (BYTE*)vertices20,
8133 indices20,
8134 attributes20,
8135 num_vertices20,
8136 num_faces20,
8137 options,
8138 declaration_normal_short4,
8139 vertex_size_normal_short4,
8140 flags20,
8141 &epsilons20,
8142 adjacency20,
8143 (BYTE*)exp_vertices20,
8144 exp_indices20,
8145 exp_face_remap20,
8146 exp_vertex_remap20,
8147 exp_new_num_vertices20
8150 (BYTE*)vertices21,
8151 indices21,
8152 attributes21,
8153 num_vertices21,
8154 num_faces21,
8155 options,
8156 declaration_normal_short4n,
8157 vertex_size_normal_short4, /* SHORT4 same size as SHORT4N */
8158 flags21,
8159 &epsilons21,
8160 adjacency21,
8161 (BYTE*)exp_vertices21,
8162 exp_indices21,
8163 exp_face_remap21,
8164 exp_vertex_remap21,
8165 exp_new_num_vertices21
8168 (BYTE*)vertices22,
8169 indices22,
8170 attributes22,
8171 num_vertices22,
8172 num_faces22,
8173 options,
8174 declaration_normal_ushort4n,
8175 vertex_size_normal_short4, /* SHORT4 same size as USHORT4N */
8176 flags22,
8177 &epsilons22,
8178 adjacency22,
8179 (BYTE*)exp_vertices22,
8180 exp_indices22,
8181 exp_face_remap22,
8182 exp_vertex_remap22,
8183 exp_new_num_vertices22
8186 (BYTE*)vertices23,
8187 indices23,
8188 attributes23,
8189 num_vertices23,
8190 num_faces23,
8191 options,
8192 declaration_texcoord_float16_2,
8193 vertex_size_texcoord_float16_2,
8194 flags23,
8195 &epsilons23,
8196 adjacency23,
8197 (BYTE*)exp_vertices23,
8198 exp_indices23,
8199 exp_face_remap23,
8200 exp_vertex_remap23,
8201 exp_new_num_vertices23
8204 (BYTE*)vertices24,
8205 indices24,
8206 attributes24,
8207 num_vertices24,
8208 num_faces24,
8209 options,
8210 declaration_texcoord_float16_4,
8211 vertex_size_texcoord_float16_4,
8212 flags24,
8213 &epsilons24,
8214 adjacency24,
8215 (BYTE*)exp_vertices24,
8216 exp_indices24,
8217 exp_face_remap24,
8218 exp_vertex_remap24,
8219 exp_new_num_vertices24
8222 (BYTE*)vertices25,
8223 indices25,
8224 attributes25,
8225 num_vertices25,
8226 num_faces25,
8227 options,
8228 declaration_texcoord10,
8229 vertex_size_texcoord,
8230 flags25,
8231 &epsilons25,
8232 adjacency25,
8233 (BYTE*)exp_vertices25,
8234 exp_indices25,
8235 exp_face_remap25,
8236 exp_vertex_remap25,
8237 exp_new_num_vertices25
8240 (BYTE*)vertices26,
8241 indices26,
8242 attributes26,
8243 num_vertices26,
8244 num_faces26,
8245 options,
8246 declaration_color2,
8247 vertex_size_color,
8248 flags26,
8249 &epsilons26,
8250 adjacency26,
8251 (BYTE*)exp_vertices26,
8252 exp_indices26,
8253 exp_face_remap26,
8254 exp_vertex_remap26,
8255 exp_new_num_vertices26
8258 (BYTE*)vertices27,
8259 indices27,
8260 attributes27,
8261 num_vertices27,
8262 num_faces27,
8263 options,
8264 declaration_color1,
8265 vertex_size_color,
8266 flags27,
8267 &epsilons27,
8268 adjacency27,
8269 (BYTE*)exp_vertices27,
8270 exp_indices27,
8271 exp_face_remap27,
8272 exp_vertex_remap27,
8273 exp_new_num_vertices27
8276 (BYTE*)vertices28,
8277 indices28,
8278 attributes28,
8279 num_vertices28,
8280 num_faces28,
8281 options,
8282 declaration_normal_udec3,
8283 vertex_size_normal_udec3,
8284 flags28,
8285 &epsilons28,
8286 adjacency28,
8287 (BYTE*)exp_vertices28,
8288 exp_indices28,
8289 exp_face_remap28,
8290 exp_vertex_remap28,
8291 exp_new_num_vertices28
8294 (BYTE*)vertices29,
8295 indices29,
8296 attributes29,
8297 num_vertices29,
8298 num_faces29,
8299 options,
8300 declaration_normal_dec3n,
8301 vertex_size_normal_dec3n,
8302 flags29,
8303 &epsilons29,
8304 adjacency29,
8305 (BYTE*)exp_vertices29,
8306 exp_indices29,
8307 exp_face_remap29,
8308 exp_vertex_remap29,
8309 exp_new_num_vertices29
8313 test_context = new_test_context();
8314 if (!test_context)
8316 skip("Couldn't create test context\n");
8317 goto cleanup;
8320 for (i = 0; i < ARRAY_SIZE(tc); i++)
8322 DWORD j;
8323 DWORD *vertex_remap_ptr;
8324 DWORD new_num_vertices;
8326 hr = init_test_mesh(tc[i].num_faces, tc[i].num_vertices, tc[i].options,
8327 tc[i].declaration, test_context->device, &mesh,
8328 tc[i].vertices, tc[i].vertex_size,
8329 tc[i].indices, tc[i].attributes);
8330 if (FAILED(hr))
8332 skip("Couldn't initialize test mesh %d.\n", i);
8333 goto cleanup;
8336 /* Allocate out parameters */
8337 adjacency_out = HeapAlloc(GetProcessHeap(), 0, VERTS_PER_FACE * tc[i].num_faces * sizeof(*adjacency_out));
8338 if (!adjacency_out)
8340 skip("Couldn't allocate adjacency_out array.\n");
8341 goto cleanup;
8343 face_remap = HeapAlloc(GetProcessHeap(), 0, tc[i].num_faces * sizeof(*face_remap));
8344 if (!face_remap)
8346 skip("Couldn't allocate face_remap array.\n");
8347 goto cleanup;
8350 hr = D3DXWeldVertices(mesh, tc[i].flags, tc[i].epsilons, tc[i].adjacency,
8351 adjacency_out, face_remap, &vertex_remap);
8352 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
8353 /* Check number of vertices*/
8354 new_num_vertices = mesh->lpVtbl->GetNumVertices(mesh);
8355 ok(new_num_vertices == tc[i].exp_new_num_vertices,
8356 "Mesh %d: new_num_vertices == %d, expected %d.\n",
8357 i, new_num_vertices, tc[i].exp_new_num_vertices);
8358 /* Check index buffer */
8359 if (tc[i].options & D3DXMESH_32BIT)
8361 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, (void**)&indices);
8362 if (FAILED(hr))
8364 skip("Couldn't lock index buffer.\n");
8365 goto cleanup;
8367 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
8369 ok(indices[j] == tc[i].exp_indices[j],
8370 "Mesh %d: indices[%d] == %d, expected %d\n",
8371 i, j, indices[j], tc[i].exp_indices[j]);
8374 else
8376 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, (void**)&indices_16bit);
8377 if (FAILED(hr))
8379 skip("Couldn't lock index buffer.\n");
8380 goto cleanup;
8382 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
8384 ok(indices_16bit[j] == tc[i].exp_indices[j],
8385 "Mesh %d: indices_16bit[%d] == %d, expected %d\n",
8386 i, j, indices_16bit[j], tc[i].exp_indices[j]);
8389 mesh->lpVtbl->UnlockIndexBuffer(mesh);
8390 indices = NULL;
8391 indices_16bit = NULL;
8392 /* Check adjacency_out */
8393 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
8395 ok(adjacency_out[j] == tc[i].adjacency[j],
8396 "Mesh %d: adjacency_out[%d] == %d, expected %d\n",
8397 i, j, adjacency_out[j], tc[i].adjacency[j]);
8399 /* Check face_remap */
8400 for (j = 0; j < tc[i].num_faces; j++)
8402 ok(face_remap[j] == tc[i].exp_face_remap[j],
8403 "Mesh %d: face_remap[%d] == %d, expected %d\n",
8404 i, j, face_remap[j], tc[i].exp_face_remap[j]);
8406 /* Check vertex_remap */
8407 vertex_remap_ptr = vertex_remap->lpVtbl->GetBufferPointer(vertex_remap);
8408 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
8410 ok(vertex_remap_ptr[j] == tc[i].exp_vertex_remap[j],
8411 "Mesh %d: vertex_remap_ptr[%d] == %d, expected %d\n",
8412 i, j, vertex_remap_ptr[j], tc[i].exp_vertex_remap[j]);
8414 /* Check vertex buffer */
8415 hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, (void*)&vertices);
8416 if (FAILED(hr))
8418 skip("Couldn't lock vertex buffer.\n");
8419 goto cleanup;
8421 /* Check contents of re-ordered vertex buffer */
8422 for (j = 0; j < tc[i].exp_new_num_vertices; j++)
8424 int index = tc[i].vertex_size*j;
8425 check_vertex_components(__LINE__, i, j, &vertices[index], &tc[i].exp_vertices[index], tc[i].declaration);
8427 mesh->lpVtbl->UnlockVertexBuffer(mesh);
8428 vertices = NULL;
8430 /* Free mesh and output data */
8431 HeapFree(GetProcessHeap(), 0, adjacency_out);
8432 adjacency_out = NULL;
8433 HeapFree(GetProcessHeap(), 0, face_remap);
8434 face_remap = NULL;
8435 vertex_remap->lpVtbl->Release(vertex_remap);
8436 vertex_remap = NULL;
8437 mesh->lpVtbl->Release(mesh);
8438 mesh = NULL;
8441 cleanup:
8442 HeapFree(GetProcessHeap(), 0, adjacency_out);
8443 HeapFree(GetProcessHeap(), 0, face_remap);
8444 if (indices) mesh->lpVtbl->UnlockIndexBuffer(mesh);
8445 if (indices_16bit) mesh->lpVtbl->UnlockIndexBuffer(mesh);
8446 if (mesh) mesh->lpVtbl->Release(mesh);
8447 if (vertex_remap) vertex_remap->lpVtbl->Release(vertex_remap);
8448 if (vertices) mesh->lpVtbl->UnlockVertexBuffer(mesh);
8449 free_test_context(test_context);
8452 static void test_clone_mesh(void)
8454 HRESULT hr;
8455 struct test_context *test_context = NULL;
8456 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
8457 D3DVERTEXELEMENT9 declaration_pn[] =
8459 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8460 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
8461 D3DDECL_END()
8463 D3DVERTEXELEMENT9 declaration_pntc[] =
8465 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8466 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
8467 {0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8468 D3DDECL_END()
8470 D3DVERTEXELEMENT9 declaration_ptcn[] =
8472 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8473 {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8474 {0, 20, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
8475 D3DDECL_END()
8477 D3DVERTEXELEMENT9 declaration_ptc[] =
8479 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8480 {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8481 D3DDECL_END()
8483 D3DVERTEXELEMENT9 declaration_ptc_float16_2[] =
8485 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8486 {0, 12, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8487 D3DDECL_END()
8489 D3DVERTEXELEMENT9 declaration_ptc_float16_4[] =
8491 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8492 {0, 12, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8493 D3DDECL_END()
8495 D3DVERTEXELEMENT9 declaration_ptc_float1[] =
8497 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8498 {0, 12, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8499 D3DDECL_END()
8501 D3DVERTEXELEMENT9 declaration_ptc_float3[] =
8503 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8504 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8505 D3DDECL_END()
8507 D3DVERTEXELEMENT9 declaration_ptc_float4[] =
8509 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8510 {0, 12, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8511 D3DDECL_END()
8513 D3DVERTEXELEMENT9 declaration_ptc_d3dcolor[] =
8515 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8516 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8517 D3DDECL_END()
8519 D3DVERTEXELEMENT9 declaration_ptc_ubyte4[] =
8521 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8522 {0, 12, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8523 D3DDECL_END()
8525 D3DVERTEXELEMENT9 declaration_ptc_ubyte4n[] =
8527 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8528 {0, 12, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8529 D3DDECL_END()
8531 D3DVERTEXELEMENT9 declaration_ptc_short2[] =
8533 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8534 {0, 12, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8535 D3DDECL_END()
8537 D3DVERTEXELEMENT9 declaration_ptc_short4[] =
8539 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8540 {0, 12, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8541 D3DDECL_END()
8543 D3DVERTEXELEMENT9 declaration_ptc_short2n[] =
8545 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8546 {0, 12, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8547 D3DDECL_END()
8549 D3DVERTEXELEMENT9 declaration_ptc_short4n[] =
8551 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8552 {0, 12, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8553 D3DDECL_END()
8555 D3DVERTEXELEMENT9 declaration_ptc_ushort2n[] =
8557 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8558 {0, 12, D3DDECLTYPE_USHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8559 D3DDECL_END()
8561 D3DVERTEXELEMENT9 declaration_ptc_ushort4n[] =
8563 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8564 {0, 12, D3DDECLTYPE_USHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8565 D3DDECL_END()
8567 D3DVERTEXELEMENT9 declaration_ptc_float16_2_partialu[] =
8569 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8570 {0, 12, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_PARTIALU, D3DDECLUSAGE_TEXCOORD, 0},
8571 D3DDECL_END()
8573 D3DVERTEXELEMENT9 declaration_pntc1[] =
8575 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8576 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
8577 {0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
8578 D3DDECL_END()
8580 const unsigned int VERTS_PER_FACE = 3;
8581 BYTE *vertices = NULL;
8582 INT i;
8583 struct vertex_pn
8585 D3DXVECTOR3 position;
8586 D3DXVECTOR3 normal;
8588 struct vertex_pntc
8590 D3DXVECTOR3 position;
8591 D3DXVECTOR3 normal;
8592 D3DXVECTOR2 texcoords;
8594 struct vertex_ptcn
8596 D3DXVECTOR3 position;
8597 D3DXVECTOR2 texcoords;
8598 D3DXVECTOR3 normal;
8600 struct vertex_ptc
8602 D3DXVECTOR3 position;
8603 D3DXVECTOR2 texcoords;
8605 struct vertex_ptc_float16_2
8607 D3DXVECTOR3 position;
8608 WORD texcoords[2]; /* float16_2 */
8610 struct vertex_ptc_float16_4
8612 D3DXVECTOR3 position;
8613 WORD texcoords[4]; /* float16_4 */
8615 struct vertex_ptc_float1
8617 D3DXVECTOR3 position;
8618 FLOAT texcoords;
8620 struct vertex_ptc_float3
8622 D3DXVECTOR3 position;
8623 FLOAT texcoords[3];
8625 struct vertex_ptc_float4
8627 D3DXVECTOR3 position;
8628 FLOAT texcoords[4];
8630 struct vertex_ptc_d3dcolor
8632 D3DXVECTOR3 position;
8633 BYTE texcoords[4];
8635 struct vertex_ptc_ubyte4
8637 D3DXVECTOR3 position;
8638 BYTE texcoords[4];
8640 struct vertex_ptc_ubyte4n
8642 D3DXVECTOR3 position;
8643 BYTE texcoords[4];
8645 struct vertex_ptc_short2
8647 D3DXVECTOR3 position;
8648 SHORT texcoords[2];
8650 struct vertex_ptc_short4
8652 D3DXVECTOR3 position;
8653 SHORT texcoords[4];
8655 struct vertex_ptc_ushort2n
8657 D3DXVECTOR3 position;
8658 USHORT texcoords[2];
8660 struct vertex_ptc_ushort4n
8662 D3DXVECTOR3 position;
8663 USHORT texcoords[4];
8665 struct vertex_ptc_udec3
8667 D3DXVECTOR3 position;
8668 DWORD texcoords;
8670 struct vertex_ptc_dec3n
8672 D3DXVECTOR3 position;
8673 DWORD texcoords;
8675 D3DXVECTOR3 up = {0.0f, 0.0f, 1.0f};
8676 D3DXVECTOR2 zero_vec2 = {0.0f, 0.0f};
8677 /* Test 0. Check that a mesh can be cloned if the new declaration is the
8678 * same as the one used to create the mesh.
8680 * 0--1 3
8681 * | / /|
8682 * |/ / |
8683 * 2 5--4
8685 const struct vertex_pn vertices0[] =
8687 {{ 0.0f, 3.0f, 0.f}, up},
8688 {{ 2.0f, 3.0f, 0.f}, up},
8689 {{ 0.0f, 0.0f, 0.f}, up},
8691 {{ 3.0f, 3.0f, 0.f}, up},
8692 {{ 3.0f, 0.0f, 0.f}, up},
8693 {{ 1.0f, 0.0f, 0.f}, up},
8695 const UINT num_vertices0 = ARRAY_SIZE(vertices0);
8696 const UINT num_faces0 = ARRAY_SIZE(vertices0) / VERTS_PER_FACE;
8697 const UINT vertex_size0 = sizeof(*vertices0);
8698 /* Test 1. Check that 16-bit indices are handled. */
8699 const DWORD options_16bit = D3DXMESH_SYSTEMMEM;
8700 /* Test 2. Check that the size of each vertex is increased and the data
8701 * moved if the new declaration adds an element after the original elements.
8703 const struct vertex_pntc exp_vertices2[] =
8705 {{ 0.0f, 3.0f, 0.f}, up, zero_vec2},
8706 {{ 2.0f, 3.0f, 0.f}, up, zero_vec2},
8707 {{ 0.0f, 0.0f, 0.f}, up, zero_vec2},
8709 {{ 3.0f, 3.0f, 0.f}, up, zero_vec2},
8710 {{ 3.0f, 0.0f, 0.f}, up, zero_vec2},
8711 {{ 1.0f, 0.0f, 0.f}, up, zero_vec2},
8713 const UINT exp_vertex_size2 = sizeof(*exp_vertices2);
8714 /* Test 3. Check that the size of each vertex is increased and the data
8715 * moved if the new declaration adds an element between the original
8716 * elements.
8718 const struct vertex_ptcn exp_vertices3[] =
8720 {{ 0.0f, 3.0f, 0.f}, zero_vec2, up},
8721 {{ 2.0f, 3.0f, 0.f}, zero_vec2, up},
8722 {{ 0.0f, 0.0f, 0.f}, zero_vec2, up},
8724 {{ 3.0f, 3.0f, 0.f}, zero_vec2, up},
8725 {{ 3.0f, 0.0f, 0.f}, zero_vec2, up},
8726 {{ 1.0f, 0.0f, 0.f}, zero_vec2, up},
8728 const UINT exp_vertex_size3 = sizeof(*exp_vertices3);
8729 /* Test 4. Test that data types can be converted, e.g. FLOAT2 to FLOAT16_2. */
8730 const struct vertex_ptc vertices4[] =
8732 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8733 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8734 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
8736 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8737 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
8738 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
8740 const UINT num_vertices4 = ARRAY_SIZE(vertices4);
8741 const UINT num_faces4 = ARRAY_SIZE(vertices4) / VERTS_PER_FACE;
8742 const UINT vertex_size4 = sizeof(*vertices4);
8743 const struct vertex_ptc_float16_2 exp_vertices4[] =
8745 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
8746 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */
8747 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */
8749 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd}}, /* {0.2f, 0.3f} */
8750 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
8751 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */
8753 const UINT exp_vertex_size4 = sizeof(*exp_vertices4);
8754 /* Test 5. Convert FLOAT2 to FLOAT16_4. */
8755 const struct vertex_ptc vertices5[] =
8757 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8758 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8759 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
8761 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8762 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
8763 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
8765 const UINT num_vertices5 = ARRAY_SIZE(vertices5);
8766 const UINT num_faces5 = ARRAY_SIZE(vertices5) / VERTS_PER_FACE;
8767 const UINT vertex_size5 = sizeof(*vertices5);
8768 const struct vertex_ptc_float16_4 exp_vertices5[] =
8770 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00, 0, 0x3c00}}, /* {1.0f, 1.0f, 0.0f, 1.0f} */
8771 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a, 0, 0x3c00}}, /* {0.5f, 0.7f, 0.0f, 1.0f} */
8772 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd, 0, 0x3c00}}, /* {-0.2f, -0.3f, 0.0f, 1.0f} */
8774 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd, 0, 0x3c00}}, /* {0.2f, 0.3f, 0.0f, 1.0f} */
8775 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00, 0, 0x3c00}}, /* {1.0f, 1.0f, 0.0f, 1.0f} */
8776 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266, 0, 0x3c00}}, /* {0.1f, 0.2f, 0.0f, 1.0f} */
8778 const UINT exp_vertex_size5 = sizeof(*exp_vertices5);
8779 /* Test 6. Convert FLOAT2 to FLOAT1. */
8780 const struct vertex_ptc vertices6[] =
8782 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8783 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8784 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
8786 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8787 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
8788 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
8790 const UINT num_vertices6 = ARRAY_SIZE(vertices6);
8791 const UINT num_faces6 = ARRAY_SIZE(vertices6) / VERTS_PER_FACE;
8792 const UINT vertex_size6 = sizeof(*vertices6);
8793 const struct vertex_ptc_float1 exp_vertices6[] =
8795 {{ 0.0f, 3.0f, 0.f}, 1.0f},
8796 {{ 2.0f, 3.0f, 0.f}, 0.5f},
8797 {{ 0.0f, 0.0f, 0.f}, -0.2f},
8799 {{ 3.0f, 3.0f, 0.f}, 0.2f},
8800 {{ 3.0f, 0.0f, 0.f}, 1.0f},
8801 {{ 1.0f, 0.0f, 0.f}, 0.1f},
8803 const UINT exp_vertex_size6 = sizeof(*exp_vertices6);
8804 /* Test 7. Convert FLOAT2 to FLOAT3. */
8805 const struct vertex_ptc vertices7[] =
8807 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8808 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8809 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
8811 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8812 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
8813 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
8815 const UINT num_vertices7 = ARRAY_SIZE(vertices7);
8816 const UINT num_faces7 = ARRAY_SIZE(vertices7) / VERTS_PER_FACE;
8817 const UINT vertex_size7 = sizeof(*vertices7);
8818 const struct vertex_ptc_float3 exp_vertices7[] =
8820 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f, 0.0f}},
8821 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f, 0.0f}},
8822 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f, 0.0f}},
8824 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f, 0.0f}},
8825 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f, 0.0f}},
8826 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f, 0.0f}},
8828 const UINT exp_vertex_size7 = sizeof(*exp_vertices7);
8829 /* Test 8. Convert FLOAT2 to FLOAT4. */
8830 const struct vertex_ptc vertices8[] =
8832 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8833 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8834 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
8836 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8837 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
8838 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
8840 const UINT num_vertices8 = ARRAY_SIZE(vertices8);
8841 const UINT num_faces8 = ARRAY_SIZE(vertices8) / VERTS_PER_FACE;
8842 const UINT vertex_size8 = sizeof(*vertices8);
8843 const struct vertex_ptc_float4 exp_vertices8[] =
8845 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f, 0.0f, 1.0f}},
8846 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f, 0.0f, 1.0f}},
8847 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f, 0.0f, 1.0f}},
8849 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f, 0.0f, 1.0f}},
8850 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f, 0.0f, 1.0f}},
8851 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f, 0.0f, 1.0f}},
8853 const UINT exp_vertex_size8 = sizeof(*exp_vertices8);
8854 /* Test 9. Convert FLOAT2 to D3DCOLOR. */
8855 const struct vertex_ptc vertices9[] =
8857 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8858 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8859 {{ 0.0f, 0.0f, 0.f}, {-0.4f, -0.6f}},
8861 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8862 {{ 3.0f, 0.0f, 0.f}, { 2.0f, 256.0f}},
8863 {{ 1.0f, 0.0f, 0.f}, { 0.11f, 0.2f}},
8865 const UINT num_vertices9 = ARRAY_SIZE(vertices9);
8866 const UINT num_faces9 = ARRAY_SIZE(vertices9) / VERTS_PER_FACE;
8867 const UINT vertex_size9 = sizeof(*vertices9);
8868 const struct vertex_ptc_d3dcolor exp_vertices9[] =
8870 {{ 0.0f, 3.0f, 0.f}, {0, 255, 255, 255}},
8871 {{ 2.0f, 3.0f, 0.f}, {0, 179, 128, 255}},
8872 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 255}},
8874 {{ 3.0f, 3.0f, 0.f}, {0, 77, 51, 255}},
8875 {{ 3.0f, 0.0f, 0.f}, {0, 255, 255, 255}},
8876 {{ 1.0f, 0.0f, 0.f}, {0, 51, 28, 255}},
8878 const UINT exp_vertex_size9 = sizeof(*exp_vertices9);
8879 /* Test 10. Convert FLOAT2 to UBYTE4. */
8880 const struct vertex_ptc vertices10[] =
8882 {{ 0.0f, 3.0f, 0.f}, { 0.0f, 1.0f}},
8883 {{ 2.0f, 3.0f, 0.f}, { 2.0f, 3.0f}},
8884 {{ 0.0f, 0.0f, 0.f}, { 254.0f, 255.0f}},
8886 {{ 3.0f, 3.0f, 0.f}, { 256.0f, 257.0f}},
8887 {{ 3.0f, 0.0f, 0.f}, { 1.4f, 1.5f}},
8888 {{ 1.0f, 0.0f, 0.f}, {-4.0f, -5.0f}},
8890 const UINT num_vertices10 = ARRAY_SIZE(vertices10);
8891 const UINT num_faces10 = ARRAY_SIZE(vertices10) / VERTS_PER_FACE;
8892 const UINT vertex_size10 = sizeof(*vertices10);
8893 const struct vertex_ptc_ubyte4 exp_vertices10[] =
8895 {{ 0.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
8896 {{ 2.0f, 3.0f, 0.f}, {2, 3, 0, 1}},
8897 {{ 0.0f, 0.0f, 0.f}, {254, 255, 0, 1}},
8899 {{ 3.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
8900 {{ 3.0f, 0.0f, 0.f}, {1, 2, 0, 1}},
8901 {{ 1.0f, 0.0f, 0.f}, {0, 0, 0, 1}},
8903 const UINT exp_vertex_size10 = sizeof(*exp_vertices10);
8904 /* Test 11. Convert FLOAT2 to SHORT2. */
8905 const struct vertex_ptc vertices11[] =
8907 {{ 0.0f, 3.0f, 0.f}, { 1.0f, -1.0f}},
8908 {{ 2.0f, 3.0f, 0.f}, { 0.4f, 0.5f}},
8909 {{ 0.0f, 0.0f, 0.f}, {-0.5f, -5.0f}},
8911 {{ 3.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MIN}},
8912 {{ 3.0f, 0.0f, 0.f}, {SHRT_MAX + 1.0f, SHRT_MIN - 1.0f}},
8913 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX + 2.0f, SHRT_MIN - 2.0f}},
8915 {{ 4.0f, 3.0f, 0.f}, {2 * SHRT_MAX, 2 * SHRT_MIN}},
8916 {{ 6.0f, 0.0f, 0.f}, {3 * SHRT_MAX, 3 * SHRT_MIN}},
8917 {{ 4.0f, 0.0f, 0.f}, {4 * SHRT_MAX, 4 * SHRT_MIN}},
8919 const UINT num_vertices11 = ARRAY_SIZE(vertices11);
8920 const UINT num_faces11 = ARRAY_SIZE(vertices11) / VERTS_PER_FACE;
8921 const UINT vertex_size11 = sizeof(*vertices11);
8922 const struct vertex_ptc_short2 exp_vertices11[] =
8924 {{ 0.0f, 3.0f, 0.f}, {1, 0}},
8925 {{ 2.0f, 3.0f, 0.f}, {0, 1}},
8926 {{ 0.0f, 0.0f, 0.f}, {0, -4}},
8928 {{ 3.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MIN + 1}},
8929 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MIN}},
8930 {{ 1.0f, 0.0f, 0.f}, {SHRT_MIN + 1, SHRT_MAX}},
8932 {{ 4.0f, 3.0f, 0.f}, {-2, 1}},
8933 {{ 6.0f, 0.0f, 0.f}, {32765, -32767}},
8934 {{ 4.0f, 0.0f, 0.f}, {-4, 1}},
8936 const UINT exp_vertex_size11 = sizeof(*exp_vertices11);
8937 /* Test 12. Convert FLOAT2 to SHORT4. */
8938 const struct vertex_ptc vertices12[] =
8940 {{ 0.0f, 3.0f, 0.f}, { 1.0f, -1.0f}},
8941 {{ 2.0f, 3.0f, 0.f}, { 0.4f, 0.5f}},
8942 {{ 0.0f, 0.0f, 0.f}, {-0.5f, -5.0f}},
8944 {{ 3.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MIN}},
8945 {{ 3.0f, 0.0f, 0.f}, {SHRT_MAX + 1.0f, SHRT_MIN - 1.0f}},
8946 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX + 2.0f, SHRT_MIN - 2.0f}},
8948 {{ 4.0f, 3.0f, 0.f}, {2 * SHRT_MAX, 2 * SHRT_MIN}},
8949 {{ 6.0f, 0.0f, 0.f}, {3 * SHRT_MAX, 3 * SHRT_MIN}},
8950 {{ 4.0f, 0.0f, 0.f}, {4 * SHRT_MAX, 4 * SHRT_MIN}},
8952 const UINT num_vertices12 = ARRAY_SIZE(vertices12);
8953 const UINT num_faces12 = ARRAY_SIZE(vertices12) / VERTS_PER_FACE;
8954 const UINT vertex_size12 = sizeof(*vertices12);
8955 const struct vertex_ptc_short4 exp_vertices12[] =
8957 {{ 0.0f, 3.0f, 0.f}, {1, 0, 0, 1}},
8958 {{ 2.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
8959 {{ 0.0f, 0.0f, 0.f}, {0, -4, 0, 1}},
8961 {{ 3.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MIN + 1, 0, 1}},
8962 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MIN, 0, 1}},
8963 {{ 1.0f, 0.0f, 0.f}, {SHRT_MIN + 1, SHRT_MAX, 0, 1}},
8965 {{ 4.0f, 3.0f, 0.f}, {-2, 1, 0, 1}},
8966 {{ 6.0f, 0.0f, 0.f}, {32765, -32767, 0, 1}},
8967 {{ 4.0f, 0.0f, 0.f}, {-4, 1, 0, 1}},
8969 const UINT exp_vertex_size12 = sizeof(*exp_vertices12);
8970 /* Test 13. Convert FLOAT2 to UBYTE4N. */
8971 const struct vertex_ptc vertices13[] =
8973 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 2.0f}},
8974 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8975 {{ 0.0f, 0.0f, 0.f}, {-0.4f, -0.5f}},
8977 {{ 3.0f, 3.0f, 0.f}, {-0.6f, -1.0f}},
8978 {{ 3.0f, 0.0f, 0.f}, {UCHAR_MAX, UCHAR_MAX + 1}},
8979 {{ 1.0f, 0.0f, 0.f}, {2 * UCHAR_MAX, -UCHAR_MAX}},
8981 const UINT num_vertices13 = ARRAY_SIZE(vertices13);
8982 const UINT num_faces13 = ARRAY_SIZE(vertices13) / VERTS_PER_FACE;
8983 const UINT vertex_size13 = sizeof(*vertices13);
8984 const struct vertex_ptc_ubyte4n exp_vertices13[] =
8986 {{ 0.0f, 3.0f, 0.f}, {255, 255, 0, 255}},
8987 {{ 2.0f, 3.0f, 0.f}, {128, 179, 0, 255}},
8988 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 255}},
8990 {{ 3.0f, 3.0f, 0.f}, {0, 0, 0, 255}},
8991 {{ 3.0f, 0.0f, 0.f}, {255, 255, 0, 255}},
8992 {{ 1.0f, 0.0f, 0.f}, {255, 0, 0, 255}},
8994 const UINT exp_vertex_size13 = sizeof(*exp_vertices13);
8995 /* Test 14. Convert FLOAT2 to SHORT2N. */
8996 const struct vertex_ptc vertices14[] =
8998 {{ 0.0f, 3.0f, 0.f}, {1.0f, 2.0f}},
8999 {{ 2.0f, 3.0f, 0.f}, {0.4f, 0.5f}},
9000 {{ 0.0f, 0.0f, 0.f}, {0.6f, -1.0f}},
9002 {{ 3.0f, 3.0f, 0.f}, {-0.4f, -0.5f}},
9003 {{ 3.0f, 0.0f, 0.f}, {-0.9f, -0.99997}},
9004 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX, SHRT_MIN}},
9006 const UINT num_vertices14 = ARRAY_SIZE(vertices14);
9007 const UINT num_faces14 = ARRAY_SIZE(vertices14) / VERTS_PER_FACE;
9008 const UINT vertex_size14 = sizeof(*vertices14);
9009 const struct vertex_ptc_short2 exp_vertices14[] =
9011 {{ 0.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MAX}},
9012 {{ 2.0f, 3.0f, 0.f}, {13107, 16384}},
9013 {{ 0.0f, 0.0f, 0.f}, {19660, SHRT_MIN + 2}},
9015 {{ 3.0f, 3.0f, 0.f}, {-13106, -16383}},
9016 {{ 3.0f, 0.0f, 0.f}, {-29489, SHRT_MIN + 3}},
9017 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX, SHRT_MIN + 2}},
9019 const UINT exp_vertex_size14 = sizeof(*exp_vertices14);
9020 /* Test 15. Convert FLOAT2 to SHORT4N. */
9021 const struct vertex_ptc vertices15[] =
9023 {{ 0.0f, 3.0f, 0.f}, {1.0f, 2.0f}},
9024 {{ 2.0f, 3.0f, 0.f}, {0.4f, 0.5f}},
9025 {{ 0.0f, 0.0f, 0.f}, {0.6f, -1.0f}},
9027 {{ 3.0f, 3.0f, 0.f}, {-0.4f, -0.5f}},
9028 {{ 3.0f, 0.0f, 0.f}, {-0.9f, -0.99997}},
9029 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX, SHRT_MIN}},
9031 const UINT num_vertices15 = ARRAY_SIZE(vertices15);
9032 const UINT num_faces15 = ARRAY_SIZE(vertices15) / VERTS_PER_FACE;
9033 const UINT vertex_size15 = sizeof(*vertices15);
9034 const struct vertex_ptc_short4 exp_vertices15[] =
9036 {{ 0.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MAX, 0, SHRT_MAX}},
9037 {{ 2.0f, 3.0f, 0.f}, {13107, 16384, 0, SHRT_MAX}},
9038 {{ 0.0f, 0.0f, 0.f}, {19660, SHRT_MIN + 2, 0, SHRT_MAX}},
9040 {{ 3.0f, 3.0f, 0.f}, {-13106, -16383, 0, SHRT_MAX}},
9041 {{ 3.0f, 0.0f, 0.f}, {-29489, SHRT_MIN + 3, 0, SHRT_MAX}},
9042 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX, SHRT_MIN + 2, 0, SHRT_MAX}},
9044 const UINT exp_vertex_size15 = sizeof(*exp_vertices15);
9045 /* Test 16. Convert FLOAT2 to USHORT2N. */
9046 const struct vertex_ptc vertices16[] =
9048 {{ 0.0f, 3.0f, 0.f}, {1.0f, 2.0f}},
9049 {{ 2.0f, 3.0f, 0.f}, {0.4f, 0.5f}},
9050 {{ 0.0f, 0.0f, 0.f}, {0.6f, -1.0f}},
9052 {{ 3.0f, 3.0f, 0.f}, {-0.4f, -0.5f}},
9053 {{ 3.0f, 0.0f, 0.f}, {-0.9f, 0.99998f}},
9054 {{ 1.0f, 0.0f, 0.f}, {USHRT_MAX, 0.0f}},
9056 const UINT num_vertices16 = ARRAY_SIZE(vertices16);
9057 const UINT num_faces16 = ARRAY_SIZE(vertices16) / VERTS_PER_FACE;
9058 const UINT vertex_size16 = sizeof(*vertices16);
9059 const struct vertex_ptc_ushort2n exp_vertices16[] =
9061 {{ 0.0f, 3.0f, 0.f}, {USHRT_MAX, USHRT_MAX}},
9062 {{ 2.0f, 3.0f, 0.f}, {26214, 32768}},
9063 {{ 0.0f, 0.0f, 0.f}, {39321, 0}},
9065 {{ 3.0f, 3.0f, 0.f}, {0, 0}},
9066 {{ 3.0f, 0.0f, 0.f}, {0, USHRT_MAX - 1}},
9067 {{ 1.0f, 0.0f, 0.f}, {USHRT_MAX, 0}},
9069 const UINT exp_vertex_size16 = sizeof(*exp_vertices16);
9070 /* Test 17. Convert FLOAT2 to USHORT4N. */
9071 const struct vertex_ptc vertices17[] =
9073 {{ 0.0f, 3.0f, 0.f}, {1.0f, 2.0f}},
9074 {{ 2.0f, 3.0f, 0.f}, {0.4f, 0.5f}},
9075 {{ 0.0f, 0.0f, 0.f}, {0.6f, -1.0f}},
9077 {{ 3.0f, 3.0f, 0.f}, {-0.4f, -0.5f}},
9078 {{ 3.0f, 0.0f, 0.f}, {-0.9f, 0.99998f}},
9079 {{ 1.0f, 0.0f, 0.f}, {USHRT_MAX, 0.0f}},
9081 const UINT num_vertices17 = ARRAY_SIZE(vertices17);
9082 const UINT num_faces17 = ARRAY_SIZE(vertices17) / VERTS_PER_FACE;
9083 const UINT vertex_size17 = sizeof(*vertices17);
9084 const struct vertex_ptc_ushort4n exp_vertices17[] =
9086 {{ 0.0f, 3.0f, 0.f}, {USHRT_MAX, USHRT_MAX, 0, USHRT_MAX}},
9087 {{ 2.0f, 3.0f, 0.f}, {26214, 32768, 0, USHRT_MAX}},
9088 {{ 0.0f, 0.0f, 0.f}, {39321, 0, 0, USHRT_MAX}},
9090 {{ 3.0f, 3.0f, 0.f}, {0, 0, 0, USHRT_MAX}},
9091 {{ 3.0f, 0.0f, 0.f}, {0, USHRT_MAX - 1, 0, USHRT_MAX}},
9092 {{ 1.0f, 0.0f, 0.f}, {USHRT_MAX, 0, 0, USHRT_MAX}},
9094 const UINT exp_vertex_size17 = sizeof(*exp_vertices17);
9095 /* Test 18. Test that the method field is compared by converting a FLOAT2 to
9096 * FLOAT16_2. where the method field has been change from
9097 * D3DDECLMETHOD_DEFAULT to D3DDECLMETHOD_PARTIALU. */
9098 const struct vertex_ptc vertices18[] =
9100 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
9101 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
9102 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
9104 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
9105 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
9106 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
9108 const UINT num_vertices18 = ARRAY_SIZE(vertices18);
9109 const UINT num_faces18 = ARRAY_SIZE(vertices18) / VERTS_PER_FACE;
9110 const UINT vertex_size18 = sizeof(*vertices18);
9111 const struct vertex_ptc_float16_2 exp_vertices18[] =
9113 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
9114 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */
9115 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */
9117 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd}}, /* {0.2f, 0.3f} */
9118 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
9119 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */
9121 const UINT exp_vertex_size18 = sizeof(*exp_vertices18);
9122 /* Test 19. Test that data is lost if usage index changes, e.g. TEXCOORD0
9123 * TEXCOORD1. */
9124 const struct vertex_pntc vertices19[] =
9126 {{ 0.0f, 3.0f, 0.f}, up, { 1.0f, 1.0f}},
9127 {{ 2.0f, 3.0f, 0.f}, up, { 0.5f, 0.7f}},
9128 {{ 0.0f, 0.0f, 0.f}, up, {-0.2f, -0.3f}},
9130 {{ 3.0f, 3.0f, 0.f}, up, { 0.2f, 0.3f}},
9131 {{ 3.0f, 0.0f, 0.f}, up, { 1.0f, 1.0f}},
9132 {{ 1.0f, 0.0f, 0.f}, up, { 0.1f, 0.2f}},
9134 const UINT num_vertices19 = ARRAY_SIZE(vertices19);
9135 const UINT num_faces19 = ARRAY_SIZE(vertices19) / VERTS_PER_FACE;
9136 const UINT vertex_size19 = sizeof(*vertices19);
9137 const struct vertex_pntc exp_vertices19[] =
9139 {{ 0.0f, 3.0f, 0.f}, up, zero_vec2},
9140 {{ 2.0f, 3.0f, 0.f}, up, zero_vec2},
9141 {{ 0.0f, 0.0f, 0.f}, up, zero_vec2},
9143 {{ 3.0f, 3.0f, 0.f}, up, zero_vec2},
9144 {{ 3.0f, 0.0f, 0.f}, up, zero_vec2},
9145 {{ 1.0f, 0.0f, 0.f}, up, zero_vec2},
9147 const UINT exp_vertex_size19 = sizeof(*exp_vertices19);
9148 /* Test 20. Another test that data is lost if usage index changes, e.g.
9149 * TEXCOORD1 to TEXCOORD0. */
9150 const struct vertex_pntc vertices20[] =
9152 {{ 0.0f, 3.0f, 0.f}, up, { 1.0f, 1.0f}},
9153 {{ 2.0f, 3.0f, 0.f}, up, { 0.5f, 0.7f}},
9154 {{ 0.0f, 0.0f, 0.f}, up, {-0.2f, -0.3f}},
9156 {{ 3.0f, 3.0f, 0.f}, up, { 0.2f, 0.3f}},
9157 {{ 3.0f, 0.0f, 0.f}, up, { 1.0f, 1.0f}},
9158 {{ 1.0f, 0.0f, 0.f}, up, { 0.1f, 0.2f}},
9160 const UINT num_vertices20 = ARRAY_SIZE(vertices20);
9161 const UINT num_faces20 = ARRAY_SIZE(vertices20) / VERTS_PER_FACE;
9162 const UINT vertex_size20 = sizeof(*vertices20);
9163 const struct vertex_pntc exp_vertices20[] =
9165 {{ 0.0f, 3.0f, 0.f}, up, zero_vec2},
9166 {{ 2.0f, 3.0f, 0.f}, up, zero_vec2},
9167 {{ 0.0f, 0.0f, 0.f}, up, zero_vec2},
9169 {{ 3.0f, 3.0f, 0.f}, up, zero_vec2},
9170 {{ 3.0f, 0.0f, 0.f}, up, zero_vec2},
9171 {{ 1.0f, 0.0f, 0.f}, up, zero_vec2},
9173 const UINT exp_vertex_size20 = sizeof(*exp_vertices20);
9174 /* Test 21. Convert FLOAT1 to FLOAT2. */
9175 const struct vertex_ptc_float1 vertices21[] =
9177 {{ 0.0f, 3.0f, 0.f}, 1.0f},
9178 {{ 2.0f, 3.0f, 0.f}, 0.5f},
9179 {{ 0.0f, 0.0f, 0.f}, -0.2f},
9181 {{ 3.0f, 3.0f, 0.f}, 0.2f},
9182 {{ 3.0f, 0.0f, 0.f}, 1.0f},
9183 {{ 1.0f, 0.0f, 0.f}, 0.1f},
9185 const UINT num_vertices21 = ARRAY_SIZE(vertices21);
9186 const UINT num_faces21 = ARRAY_SIZE(vertices21) / VERTS_PER_FACE;
9187 const UINT vertex_size21 = sizeof(*vertices21);
9188 const struct vertex_ptc exp_vertices21[] =
9190 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 0.0f}},
9191 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.0f}},
9192 {{ 0.0f, 0.0f, 0.f}, {-0.2f, 0.0f}},
9194 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.0f}},
9195 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 0.0f}},
9196 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.0f}},
9198 const UINT exp_vertex_size21 = sizeof(*exp_vertices21);
9199 /* Test 22. Convert FLOAT1 to FLOAT3. */
9200 const struct vertex_ptc_float1 vertices22[] =
9202 {{ 0.0f, 3.0f, 0.f}, 1.0f},
9203 {{ 2.0f, 3.0f, 0.f}, 0.5f},
9204 {{ 0.0f, 0.0f, 0.f}, -0.2f},
9206 {{ 3.0f, 3.0f, 0.f}, 0.2f},
9207 {{ 3.0f, 0.0f, 0.f}, 1.0f},
9208 {{ 1.0f, 0.0f, 0.f}, 0.1f},
9210 const UINT num_vertices22 = ARRAY_SIZE(vertices22);
9211 const UINT num_faces22 = ARRAY_SIZE(vertices22) / VERTS_PER_FACE;
9212 const UINT vertex_size22 = sizeof(*vertices22);
9213 const struct vertex_ptc_float3 exp_vertices22[] =
9215 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 0.0f, 0.0f}},
9216 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.0f, 0.0f}},
9217 {{ 0.0f, 0.0f, 0.f}, {-0.2f, 0.0f, 0.0f}},
9219 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.0f, 0.0f}},
9220 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 0.0f, 0.0f}},
9221 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.0f, 0.0f}},
9223 const UINT exp_vertex_size22 = sizeof(*exp_vertices22);
9224 /* Test 23. Convert FLOAT1 to FLOAT4. */
9225 const struct vertex_ptc_float1 vertices23[] =
9227 {{ 0.0f, 3.0f, 0.f}, 1.0f},
9228 {{ 2.0f, 3.0f, 0.f}, 0.5f},
9229 {{ 0.0f, 0.0f, 0.f}, -0.2f},
9231 {{ 3.0f, 3.0f, 0.f}, 0.2f},
9232 {{ 3.0f, 0.0f, 0.f}, 1.0f},
9233 {{ 1.0f, 0.0f, 0.f}, 0.1f},
9235 const UINT num_vertices23 = ARRAY_SIZE(vertices23);
9236 const UINT num_faces23 = ARRAY_SIZE(vertices23) / VERTS_PER_FACE;
9237 const UINT vertex_size23 = sizeof(*vertices23);
9238 const struct vertex_ptc_float4 exp_vertices23[] =
9240 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 0.0f, 0.0f, 1.0f}},
9241 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.0f, 0.0f, 1.0f}},
9242 {{ 0.0f, 0.0f, 0.f}, {-0.2f, 0.0f, 0.0f, 1.0f}},
9244 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.0f, 0.0f, 1.0f}},
9245 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 0.0f, 0.0f, 1.0f}},
9246 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.0f, 0.0f, 1.0f}},
9248 const UINT exp_vertex_size23 = sizeof(*exp_vertices23);
9249 /* Test 24. Convert FLOAT1 to D3DCOLOR. */
9250 const struct vertex_ptc_float1 vertices24[] =
9252 {{ 0.0f, 3.0f, 0.f}, 1.0f},
9253 {{ 2.0f, 3.0f, 0.f}, 0.5f},
9254 {{ 0.0f, 0.0f, 0.f}, -0.2f},
9256 {{ 3.0f, 3.0f, 0.f}, 0.2f},
9257 {{ 3.0f, 0.0f, 0.f}, 1.0f},
9258 {{ 1.0f, 0.0f, 0.f}, 0.11f},
9260 const UINT num_vertices24 = ARRAY_SIZE(vertices24);
9261 const UINT num_faces24 = ARRAY_SIZE(vertices24) / VERTS_PER_FACE;
9262 const UINT vertex_size24 = sizeof(*vertices24);
9263 const struct vertex_ptc_d3dcolor exp_vertices24[] =
9265 {{ 0.0f, 3.0f, 0.f}, {0, 0, 255, 255}},
9266 {{ 2.0f, 3.0f, 0.f}, {0, 0, 128, 255}},
9267 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 255}},
9269 {{ 3.0f, 3.0f, 0.f}, {0, 0, 51, 255}},
9270 {{ 3.0f, 0.0f, 0.f}, {0, 0, 255, 255}},
9271 {{ 1.0f, 0.0f, 0.f}, {0, 0, 28, 255}},
9273 const UINT exp_vertex_size24 = sizeof(*exp_vertices24);
9274 /* Test 25. Convert FLOAT1 to ubyte4. */
9275 const struct vertex_ptc_float1 vertices25[] =
9277 {{ 0.0f, 3.0f, 0.f}, 0.0f},
9278 {{ 2.0f, 3.0f, 0.f}, 1.4f},
9279 {{ 0.0f, 0.0f, 0.f}, 1.5f},
9281 {{ 3.0f, 3.0f, 0.f}, 255.0f},
9282 {{ 3.0f, 0.0f, 0.f}, 256.0f},
9283 {{ 1.0f, 0.0f, 0.f}, -1.0f},
9285 const UINT num_vertices25 = ARRAY_SIZE(vertices25);
9286 const UINT num_faces25 = ARRAY_SIZE(vertices25) / VERTS_PER_FACE;
9287 const UINT vertex_size25 = sizeof(*vertices25);
9288 const struct vertex_ptc_ubyte4 exp_vertices25[] =
9290 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 1}},
9291 {{ 2.0f, 3.0f, 0.f}, {1, 0, 0, 1}},
9292 {{ 0.0f, 0.0f, 0.f}, {2, 0, 0, 1}},
9294 {{ 3.0f, 3.0f, 0.f}, {255, 0, 0, 1}},
9295 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 1}},
9296 {{ 1.0f, 0.0f, 0.f}, {0, 0, 0, 1}},
9298 const UINT exp_vertex_size25 = sizeof(*exp_vertices25);
9299 /* Test 26. Convert FLOAT4 to D3DCOLOR. */
9300 const struct vertex_ptc_float4 vertices26[] =
9302 {{ 0.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.4f, 0.5f}},
9303 {{ 2.0f, 3.0f, 0.f}, {-0.4f, -0.5f, -1.0f, -2.0f}},
9304 {{ 0.0f, 0.0f, 0.f}, {254.0f, 255.0f, 256.0f, 257.0f}},
9306 {{ 3.0f, 3.0f, 0.f}, {0.1f, 0.2f, 0.3f, 0.4f}},
9307 {{ 3.0f, 0.0f, 0.f}, {0.5f, 0.6f, 0.7f, 0.8f}},
9308 {{ 1.0f, 0.0f, 0.f}, {0.9f, 0.99f, 0.995f, 0.999f}},
9310 const UINT num_vertices26 = ARRAY_SIZE(vertices26);
9311 const UINT num_faces26 = ARRAY_SIZE(vertices26) / VERTS_PER_FACE;
9312 const UINT vertex_size26 = sizeof(*vertices26);
9313 const struct vertex_ptc_d3dcolor exp_vertices26[] =
9315 {{ 0.0f, 3.0f, 0.f}, {102, 255, 0, 128}},
9316 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9317 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
9319 {{ 3.0f, 3.0f, 0.f}, {77, 51, 26, 102}},
9320 {{ 3.0f, 0.0f, 0.f}, {179, 153, 128, 204}},
9321 {{ 1.0f, 0.0f, 0.f}, {254, 252, 230, 255}},
9323 const UINT exp_vertex_size26 = sizeof(*exp_vertices26);
9324 /* Test 27. Convert D3DCOLOR to FLOAT4. */
9325 const struct vertex_ptc_d3dcolor vertices27[] =
9327 {{ 0.0f, 3.0f, 0.f}, {102, 255, 0, 128}},
9328 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9329 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
9331 {{ 3.0f, 3.0f, 0.f}, {77, 51, 26, 102}},
9332 {{ 3.0f, 0.0f, 0.f}, {179, 153, 128, 204}},
9333 {{ 1.0f, 0.0f, 0.f}, {254, 252, 230, 255}},
9335 const UINT num_vertices27 = ARRAY_SIZE(vertices27);
9336 const UINT num_faces27 = ARRAY_SIZE(vertices27) / VERTS_PER_FACE;
9337 const UINT vertex_size27 = sizeof(*vertices27);
9338 const struct vertex_ptc_float4 exp_vertices27[] =
9340 {{ 0.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.4f, 0.501961f}},
9341 {{ 2.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9342 {{ 0.0f, 0.0f, 0.f}, {1.0f, 1.0f, 1.0f, 1.0f}},
9344 {{ 3.0f, 3.0f, 0.f}, {0.101961f, 0.2f, 0.301961f, 0.4f}},
9345 {{ 3.0f, 0.0f, 0.f}, {0.501961f, 0.6f, 0.701961f, 0.8f}},
9346 {{ 1.0f, 0.0f, 0.f}, {0.901961f, 0.988235f, 0.996078f, 1.0f}},
9348 const UINT exp_vertex_size27 = sizeof(*exp_vertices27);
9349 /* Test 28. Convert UBYTE4 to FLOAT4. */
9350 const struct vertex_ptc_ubyte4 vertices28[] =
9352 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9353 {{ 2.0f, 3.0f, 0.f}, {1, 1, 1, 1}},
9354 {{ 0.0f, 0.0f, 0.f}, {1, 0, 1, 0}},
9356 {{ 3.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
9357 {{ 3.0f, 0.0f, 0.f}, {10, 20, 30, 40}},
9358 {{ 1.0f, 0.0f, 0.f}, {50, 60, 127, 255}},
9360 const UINT num_vertices28 = ARRAY_SIZE(vertices28);
9361 const UINT num_faces28 = ARRAY_SIZE(vertices28) / VERTS_PER_FACE;
9362 const UINT vertex_size28 = sizeof(*vertices28);
9363 const struct vertex_ptc_float4 exp_vertices28[] =
9365 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9366 {{ 2.0f, 3.0f, 0.f}, {1.0f, 1.0f, 1.0f, 1.0f}},
9367 {{ 0.0f, 0.0f, 0.f}, {1.0f, 0.0f, 1.0f, 0.0f}},
9369 {{ 3.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.0f, 1.0f}},
9370 {{ 3.0f, 0.0f, 0.f}, {10.0f, 20.0f, 30.0f, 40.0f}},
9371 {{ 1.0f, 0.0f, 0.f}, {50.0f, 60.0f, 127.0f, 255.0f}},
9373 const UINT exp_vertex_size28 = sizeof(*exp_vertices28);
9374 /* Test 29. Convert SHORT2 to FLOAT4. */
9375 const struct vertex_ptc_short2 vertices29[] =
9377 {{ 0.0f, 3.0f, 0.f}, {0, 0}},
9378 {{ 2.0f, 3.0f, 0.f}, {0, 1}},
9379 {{ 0.0f, 0.0f, 0.f}, {1, 0}},
9381 {{ 3.0f, 3.0f, 0.f}, {1, 1}},
9382 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MAX}},
9383 {{ 1.0f, 0.0f, 0.f}, {-42, 42}},
9385 const UINT num_vertices29 = ARRAY_SIZE(vertices29);
9386 const UINT num_faces29 = ARRAY_SIZE(vertices29) / VERTS_PER_FACE;
9387 const UINT vertex_size29 = sizeof(*vertices29);
9388 const struct vertex_ptc_float4 exp_vertices29[] =
9390 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 1.0f}},
9391 {{ 2.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.0f, 1.0f }},
9392 {{ 0.0f, 0.0f, 0.f}, {1.0f, 0.0f, 0.0f, 1.0f}},
9394 {{ 3.0f, 3.0f, 0.f}, {1.0f, 1.0f, 0.0f, 1.0f}},
9395 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MAX, 0.0f, 1.0f}},
9396 {{ 1.0f, 0.0f, 0.f}, {-42.0f, 42.0f, 0.0f, 1.0f}},
9398 const UINT exp_vertex_size29 = sizeof(*exp_vertices29);
9399 /* Test 29. Convert SHORT4 to FLOAT4. */
9400 const struct vertex_ptc_short4 vertices30[] =
9402 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9403 {{ 2.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
9404 {{ 0.0f, 0.0f, 0.f}, {1, 0, 1, 0}},
9406 {{ 3.0f, 3.0f, 0.f}, {1, 1, 1, 1}},
9407 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MAX, 1, 0}},
9408 {{ 1.0f, 0.0f, 0.f}, {-42, 42, SHRT_MAX, SHRT_MIN}},
9410 const UINT num_vertices30 = ARRAY_SIZE(vertices30);
9411 const UINT num_faces30 = ARRAY_SIZE(vertices30) / VERTS_PER_FACE;
9412 const UINT vertex_size30 = sizeof(*vertices30);
9413 const struct vertex_ptc_float4 exp_vertices30[] =
9415 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9416 {{ 2.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.0f, 1.0f }},
9417 {{ 0.0f, 0.0f, 0.f}, {1.0f, 0.0f, 1.0f, 0.0f}},
9419 {{ 3.0f, 3.0f, 0.f}, {1.0f, 1.0f, 1.0f, 1.0f}},
9420 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MAX, 1.0f, 0.0f}},
9421 {{ 1.0f, 0.0f, 0.f}, {-42.0f, 42.0f, SHRT_MAX, SHRT_MIN}},
9423 const UINT exp_vertex_size30 = sizeof(*exp_vertices30);
9424 /* Test 31. Convert UBYTE4N to FLOAT4. */
9425 const struct vertex_ptc_ubyte4n vertices31[] =
9427 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9428 {{ 2.0f, 3.0f, 0.f}, {1, 1, 1, 1}},
9429 {{ 0.0f, 0.0f, 0.f}, {1, 0, 1, 0}},
9431 {{ 3.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
9432 {{ 3.0f, 0.0f, 0.f}, {10, 20, 30, 40}},
9433 {{ 1.0f, 0.0f, 0.f}, {50, 60, 70, UCHAR_MAX}},
9435 const UINT num_vertices31 = ARRAY_SIZE(vertices31);
9436 const UINT num_faces31 = ARRAY_SIZE(vertices31) / VERTS_PER_FACE;
9437 const UINT vertex_size31 = sizeof(*vertices31);
9438 const struct vertex_ptc_float4 exp_vertices31[] =
9440 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9441 {{ 2.0f, 3.0f, 0.f}, {(FLOAT)1/UCHAR_MAX, (FLOAT)1/UCHAR_MAX, (FLOAT)1/UCHAR_MAX, (FLOAT)1/UCHAR_MAX}},
9442 {{ 0.0f, 0.0f, 0.f}, {(FLOAT)1/UCHAR_MAX, 0.0f, (FLOAT)1/UCHAR_MAX, 0.0f}},
9444 {{ 3.0f, 3.0f, 0.f}, {0.0f, (FLOAT)1/UCHAR_MAX, 0.0f, (FLOAT)1/UCHAR_MAX}},
9445 {{ 3.0f, 0.0f, 0.f}, {(FLOAT)10/UCHAR_MAX, (FLOAT)20/UCHAR_MAX, (FLOAT)30/UCHAR_MAX, (FLOAT)40/UCHAR_MAX}},
9446 {{ 1.0f, 0.0f, 0.f}, {(FLOAT)50/UCHAR_MAX, (FLOAT)60/UCHAR_MAX, (FLOAT)70/UCHAR_MAX, 1.0f}},
9448 const UINT exp_vertex_size31 = sizeof(*exp_vertices31);
9449 /* Test 32. Convert SHORT2N to FLOAT4. */
9450 const struct vertex_ptc_short2 vertices32[] =
9452 {{ 0.0f, 3.0f, 0.f}, {0, 0}},
9453 {{ 2.0f, 3.0f, 0.f}, {0, 1}},
9454 {{ 0.0f, 0.0f, 0.f}, {1, 0}},
9456 {{ 3.0f, 3.0f, 0.f}, {1, 1}},
9457 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN + 1, SHRT_MAX}},
9458 {{ 1.0f, 0.0f, 0.f}, {-42, 42}},
9460 const UINT num_vertices32 = ARRAY_SIZE(vertices32);
9461 const UINT num_faces32 = ARRAY_SIZE(vertices32) / VERTS_PER_FACE;
9462 const UINT vertex_size32 = sizeof(*vertices32);
9463 const struct vertex_ptc_float4 exp_vertices32[] =
9465 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 1.0f}},
9466 {{ 2.0f, 3.0f, 0.f}, {0.0f, 1.0f/SHRT_MAX, 0.0f, 1.0f}},
9467 {{ 0.0f, 0.0f, 0.f}, {1.0f/SHRT_MAX, 0.0f, 0.0f, 1.0f}},
9469 {{ 3.0f, 3.0f, 0.f}, {1.0f/SHRT_MAX, 1.0f/SHRT_MAX, 0.0f, 1.0f}},
9470 {{ 3.0f, 0.0f, 0.f}, {-1.0f, 1.0f, 0.0f, 1.0f}},
9471 {{ 1.0f, 0.0f, 0.f}, {-42.0f/SHRT_MAX, 42.0f/SHRT_MAX, 0.0f, 1.0f}},
9473 const UINT exp_vertex_size32 = sizeof(*exp_vertices32);
9474 /* Test 33. Convert SHORT4N to FLOAT4. */
9475 const struct vertex_ptc_short4 vertices33[] =
9477 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9478 {{ 2.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
9479 {{ 0.0f, 0.0f, 0.f}, {1, 0, 1, 0}},
9481 {{ 3.0f, 3.0f, 0.f}, {1, 1, 1, 1}},
9482 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN + 1, SHRT_MAX, SHRT_MIN + 1, SHRT_MAX}},
9483 {{ 1.0f, 0.0f, 0.f}, {-42, 42, 1, 1}},
9485 const UINT num_vertices33 = ARRAY_SIZE(vertices33);
9486 const UINT num_faces33 = ARRAY_SIZE(vertices33) / VERTS_PER_FACE;
9487 const UINT vertex_size33 = sizeof(*vertices33);
9488 const struct vertex_ptc_float4 exp_vertices33[] =
9490 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9491 {{ 2.0f, 3.0f, 0.f}, {0.0f, 1.0f/SHRT_MAX, 0.0f, 1.0f/SHRT_MAX}},
9492 {{ 0.0f, 0.0f, 0.f}, {1.0f/SHRT_MAX, 0.0f, 1.0f/SHRT_MAX, 0.0f}},
9494 {{ 3.0f, 3.0f, 0.f}, {1.0f/SHRT_MAX, 1.0f/SHRT_MAX, 1.0f/SHRT_MAX, 1.0f/SHRT_MAX}},
9495 {{ 3.0f, 0.0f, 0.f}, {-1.0f, 1.0f, -1.0f, 1.0f}},
9496 {{ 1.0f, 0.0f, 0.f}, {-42.0f/SHRT_MAX, 42.0f/SHRT_MAX, 1.0f/SHRT_MAX, 1.0f/SHRT_MAX}},
9498 const UINT exp_vertex_size33 = sizeof(*exp_vertices33);
9499 /* Test 34. Convert FLOAT16_2 to FLOAT4. */
9500 const struct vertex_ptc_float16_2 vertices34[] =
9502 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
9503 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */
9504 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */
9506 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd}}, /* {0.2f, 0.3f} */
9507 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
9508 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */
9510 const UINT num_vertices34 = ARRAY_SIZE(vertices34);
9511 const UINT num_faces34 = ARRAY_SIZE(vertices34) / VERTS_PER_FACE;
9512 const UINT vertex_size34 = sizeof(*vertices34);
9513 const struct vertex_ptc_float4 exp_vertices34[] =
9515 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f, 0.0f, 1.0f}},
9516 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.700195f, 0.0f, 1.0f}},
9517 {{ 0.0f, 0.0f, 0.f}, {-0.199951f, -0.300049f, 0.0f, 1.0f}},
9519 {{ 3.0f, 3.0f, 0.f}, {0.199951f, 0.300049f, 0.0f, 1.0f}},
9520 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f, 0.0f, 1.0f}},
9521 {{ 1.0f, 0.0f, 0.f}, {0.099976f, 0.199951f, 0.0f, 1.0f}},
9523 const UINT exp_vertex_size34 = sizeof(*exp_vertices34);
9524 /* Test 35. Convert FLOAT16_4 to FLOAT4. */
9525 const struct vertex_ptc_float16_4 vertices35[] =
9527 {{ 0.0f, 3.0f, 0.f}, {0x0000, 0x0000, 0x0000, 0x0000}},
9528 {{ 2.0f, 3.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}},
9529 {{ 0.0f, 0.0f, 0.f}, {0x3c00, 0x0000, 0x3c00, 0x0000}},
9531 {{ 3.0f, 3.0f, 0.f}, {0x0000, 0x3c00, 0x0000, 0x3c00}},
9532 {{ 3.0f, 0.0f, 0.f}, {0x3800, 0x399a, 0xb266, 0xb4cd}},
9533 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266, 0x2e66, 0x3266}},
9535 const UINT num_vertices35 = ARRAY_SIZE(vertices35);
9536 const UINT num_faces35 = ARRAY_SIZE(vertices35) / VERTS_PER_FACE;
9537 const UINT vertex_size35 = sizeof(*vertices35);
9538 const struct vertex_ptc_float4 exp_vertices35[] =
9540 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9541 {{ 2.0f, 3.0f, 0.f}, {1.0f, 1.0f, 1.0f, 1.0f}},
9542 {{ 0.0f, 0.0f, 0.f}, {1.0f, 0.0f, 1.0f, 0.0f}},
9544 {{ 3.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.0f, 1.0f}},
9545 {{ 3.0f, 0.0f, 0.f}, {0.5f, 0.700195f, -0.199951f, -0.300049f}},
9546 {{ 1.0f, 0.0f, 0.f}, {0.099976f, 0.199951f, 0.099976f, 0.199951f}},
9548 const UINT exp_vertex_size35 = sizeof(*exp_vertices35);
9549 /* Test 36. Check that vertex buffer sharing is ok. */
9550 const struct vertex_pn vertices36[] =
9552 {{ 0.0f, 3.0f, 0.f}, up},
9553 {{ 2.0f, 3.0f, 0.f}, up},
9554 {{ 0.0f, 0.0f, 0.f}, up},
9556 const UINT num_vertices36 = ARRAY_SIZE(vertices36);
9557 const UINT num_faces36 = ARRAY_SIZE(vertices36) / VERTS_PER_FACE;
9558 const UINT vertex_size36 = sizeof(*vertices36);
9559 const DWORD clone_options36 = options | D3DXMESH_VB_SHARE;
9560 /* Common mesh data */
9561 ID3DXMesh *mesh = NULL;
9562 ID3DXMesh *mesh_clone = NULL;
9563 struct
9565 const BYTE *vertices;
9566 const DWORD *indices;
9567 const DWORD *attributes;
9568 const UINT num_vertices;
9569 const UINT num_faces;
9570 const UINT vertex_size;
9571 const DWORD create_options;
9572 const DWORD clone_options;
9573 D3DVERTEXELEMENT9 *declaration;
9574 D3DVERTEXELEMENT9 *new_declaration;
9575 const BYTE *exp_vertices;
9576 const UINT exp_vertex_size;
9578 tc[] =
9581 (BYTE*)vertices0,
9582 NULL,
9583 NULL,
9584 num_vertices0,
9585 num_faces0,
9586 vertex_size0,
9587 options,
9588 options,
9589 declaration_pn,
9590 declaration_pn,
9591 (BYTE*)vertices0,
9592 vertex_size0
9595 (BYTE*)vertices0,
9596 NULL,
9597 NULL,
9598 num_vertices0,
9599 num_faces0,
9600 vertex_size0,
9601 options_16bit,
9602 options_16bit,
9603 declaration_pn,
9604 declaration_pn,
9605 (BYTE*)vertices0,
9606 vertex_size0
9609 (BYTE*)vertices0,
9610 NULL,
9611 NULL,
9612 num_vertices0,
9613 num_faces0,
9614 vertex_size0,
9615 options,
9616 options,
9617 declaration_pn,
9618 declaration_pntc,
9619 (BYTE*)exp_vertices2,
9620 exp_vertex_size2
9623 (BYTE*)vertices0,
9624 NULL,
9625 NULL,
9626 num_vertices0,
9627 num_faces0,
9628 vertex_size0,
9629 options,
9630 options,
9631 declaration_pn,
9632 declaration_ptcn,
9633 (BYTE*)exp_vertices3,
9634 exp_vertex_size3
9637 (BYTE*)vertices4,
9638 NULL,
9639 NULL,
9640 num_vertices4,
9641 num_faces4,
9642 vertex_size4,
9643 options,
9644 options,
9645 declaration_ptc,
9646 declaration_ptc_float16_2,
9647 (BYTE*)exp_vertices4,
9648 exp_vertex_size4
9651 (BYTE*)vertices5,
9652 NULL,
9653 NULL,
9654 num_vertices5,
9655 num_faces5,
9656 vertex_size5,
9657 options,
9658 options,
9659 declaration_ptc,
9660 declaration_ptc_float16_4,
9661 (BYTE*)exp_vertices5,
9662 exp_vertex_size5
9665 (BYTE*)vertices6,
9666 NULL,
9667 NULL,
9668 num_vertices6,
9669 num_faces6,
9670 vertex_size6,
9671 options,
9672 options,
9673 declaration_ptc,
9674 declaration_ptc_float1,
9675 (BYTE*)exp_vertices6,
9676 exp_vertex_size6
9679 (BYTE*)vertices7,
9680 NULL,
9681 NULL,
9682 num_vertices7,
9683 num_faces7,
9684 vertex_size7,
9685 options,
9686 options,
9687 declaration_ptc,
9688 declaration_ptc_float3,
9689 (BYTE*)exp_vertices7,
9690 exp_vertex_size7
9693 (BYTE*)vertices8,
9694 NULL,
9695 NULL,
9696 num_vertices8,
9697 num_faces8,
9698 vertex_size8,
9699 options,
9700 options,
9701 declaration_ptc,
9702 declaration_ptc_float4,
9703 (BYTE*)exp_vertices8,
9704 exp_vertex_size8
9707 (BYTE*)vertices9,
9708 NULL,
9709 NULL,
9710 num_vertices9,
9711 num_faces9,
9712 vertex_size9,
9713 options,
9714 options,
9715 declaration_ptc,
9716 declaration_ptc_d3dcolor,
9717 (BYTE*)exp_vertices9,
9718 exp_vertex_size9
9721 (BYTE*)vertices10,
9722 NULL,
9723 NULL,
9724 num_vertices10,
9725 num_faces10,
9726 vertex_size10,
9727 options,
9728 options,
9729 declaration_ptc,
9730 declaration_ptc_ubyte4,
9731 (BYTE*)exp_vertices10,
9732 exp_vertex_size10
9735 (BYTE*)vertices11,
9736 NULL,
9737 NULL,
9738 num_vertices11,
9739 num_faces11,
9740 vertex_size11,
9741 options,
9742 options,
9743 declaration_ptc,
9744 declaration_ptc_short2,
9745 (BYTE*)exp_vertices11,
9746 exp_vertex_size11
9749 (BYTE*)vertices12,
9750 NULL,
9751 NULL,
9752 num_vertices12,
9753 num_faces12,
9754 vertex_size12,
9755 options,
9756 options,
9757 declaration_ptc,
9758 declaration_ptc_short4,
9759 (BYTE*)exp_vertices12,
9760 exp_vertex_size12
9763 (BYTE*)vertices13,
9764 NULL,
9765 NULL,
9766 num_vertices13,
9767 num_faces13,
9768 vertex_size13,
9769 options,
9770 options,
9771 declaration_ptc,
9772 declaration_ptc_ubyte4n,
9773 (BYTE*)exp_vertices13,
9774 exp_vertex_size13
9777 (BYTE*)vertices14,
9778 NULL,
9779 NULL,
9780 num_vertices14,
9781 num_faces14,
9782 vertex_size14,
9783 options,
9784 options,
9785 declaration_ptc,
9786 declaration_ptc_short2n,
9787 (BYTE*)exp_vertices14,
9788 exp_vertex_size14
9791 (BYTE*)vertices15,
9792 NULL,
9793 NULL,
9794 num_vertices15,
9795 num_faces15,
9796 vertex_size15,
9797 options,
9798 options,
9799 declaration_ptc,
9800 declaration_ptc_short4n,
9801 (BYTE*)exp_vertices15,
9802 exp_vertex_size15
9805 (BYTE*)vertices16,
9806 NULL,
9807 NULL,
9808 num_vertices16,
9809 num_faces16,
9810 vertex_size16,
9811 options,
9812 options,
9813 declaration_ptc,
9814 declaration_ptc_ushort2n,
9815 (BYTE*)exp_vertices16,
9816 exp_vertex_size16
9819 (BYTE*)vertices17,
9820 NULL,
9821 NULL,
9822 num_vertices17,
9823 num_faces17,
9824 vertex_size17,
9825 options,
9826 options,
9827 declaration_ptc,
9828 declaration_ptc_ushort4n,
9829 (BYTE*)exp_vertices17,
9830 exp_vertex_size17
9833 (BYTE*)vertices18,
9834 NULL,
9835 NULL,
9836 num_vertices18,
9837 num_faces18,
9838 vertex_size18,
9839 options,
9840 options,
9841 declaration_ptc,
9842 declaration_ptc_float16_2_partialu,
9843 (BYTE*)exp_vertices18,
9844 exp_vertex_size18
9847 (BYTE*)vertices19,
9848 NULL,
9849 NULL,
9850 num_vertices19,
9851 num_faces19,
9852 vertex_size19,
9853 options,
9854 options,
9855 declaration_pntc,
9856 declaration_pntc1,
9857 (BYTE*)exp_vertices19,
9858 exp_vertex_size19
9861 (BYTE*)vertices20,
9862 NULL,
9863 NULL,
9864 num_vertices20,
9865 num_faces20,
9866 vertex_size20,
9867 options,
9868 options,
9869 declaration_pntc1,
9870 declaration_pntc,
9871 (BYTE*)exp_vertices20,
9872 exp_vertex_size20
9875 (BYTE*)vertices21,
9876 NULL,
9877 NULL,
9878 num_vertices21,
9879 num_faces21,
9880 vertex_size21,
9881 options,
9882 options,
9883 declaration_ptc_float1,
9884 declaration_ptc,
9885 (BYTE*)exp_vertices21,
9886 exp_vertex_size21
9889 (BYTE*)vertices22,
9890 NULL,
9891 NULL,
9892 num_vertices22,
9893 num_faces22,
9894 vertex_size22,
9895 options,
9896 options,
9897 declaration_ptc_float1,
9898 declaration_ptc_float3,
9899 (BYTE*)exp_vertices22,
9900 exp_vertex_size22
9903 (BYTE*)vertices23,
9904 NULL,
9905 NULL,
9906 num_vertices23,
9907 num_faces23,
9908 vertex_size23,
9909 options,
9910 options,
9911 declaration_ptc_float1,
9912 declaration_ptc_float4,
9913 (BYTE*)exp_vertices23,
9914 exp_vertex_size23
9917 (BYTE*)vertices24,
9918 NULL,
9919 NULL,
9920 num_vertices24,
9921 num_faces24,
9922 vertex_size24,
9923 options,
9924 options,
9925 declaration_ptc_float1,
9926 declaration_ptc_d3dcolor,
9927 (BYTE*)exp_vertices24,
9928 exp_vertex_size24
9931 (BYTE*)vertices25,
9932 NULL,
9933 NULL,
9934 num_vertices25,
9935 num_faces25,
9936 vertex_size25,
9937 options,
9938 options,
9939 declaration_ptc_float1,
9940 declaration_ptc_ubyte4,
9941 (BYTE*)exp_vertices25,
9942 exp_vertex_size25
9945 (BYTE*)vertices26,
9946 NULL,
9947 NULL,
9948 num_vertices26,
9949 num_faces26,
9950 vertex_size26,
9951 options,
9952 options,
9953 declaration_ptc_float4,
9954 declaration_ptc_d3dcolor,
9955 (BYTE*)exp_vertices26,
9956 exp_vertex_size26
9959 (BYTE*)vertices27,
9960 NULL,
9961 NULL,
9962 num_vertices27,
9963 num_faces27,
9964 vertex_size27,
9965 options,
9966 options,
9967 declaration_ptc_d3dcolor,
9968 declaration_ptc_float4,
9969 (BYTE*)exp_vertices27,
9970 exp_vertex_size27
9973 (BYTE*)vertices28,
9974 NULL,
9975 NULL,
9976 num_vertices28,
9977 num_faces28,
9978 vertex_size28,
9979 options,
9980 options,
9981 declaration_ptc_ubyte4,
9982 declaration_ptc_float4,
9983 (BYTE*)exp_vertices28,
9984 exp_vertex_size28
9987 (BYTE*)vertices29,
9988 NULL,
9989 NULL,
9990 num_vertices29,
9991 num_faces29,
9992 vertex_size29,
9993 options,
9994 options,
9995 declaration_ptc_short2,
9996 declaration_ptc_float4,
9997 (BYTE*)exp_vertices29,
9998 exp_vertex_size29
10001 (BYTE*)vertices30,
10002 NULL,
10003 NULL,
10004 num_vertices30,
10005 num_faces30,
10006 vertex_size30,
10007 options,
10008 options,
10009 declaration_ptc_short4,
10010 declaration_ptc_float4,
10011 (BYTE*)exp_vertices30,
10012 exp_vertex_size30
10015 (BYTE*)vertices31,
10016 NULL,
10017 NULL,
10018 num_vertices31,
10019 num_faces31,
10020 vertex_size31,
10021 options,
10022 options,
10023 declaration_ptc_ubyte4n,
10024 declaration_ptc_float4,
10025 (BYTE*)exp_vertices31,
10026 exp_vertex_size31
10029 (BYTE*)vertices32,
10030 NULL,
10031 NULL,
10032 num_vertices32,
10033 num_faces32,
10034 vertex_size32,
10035 options,
10036 options,
10037 declaration_ptc_short2n,
10038 declaration_ptc_float4,
10039 (BYTE*)exp_vertices32,
10040 exp_vertex_size32
10043 (BYTE*)vertices33,
10044 NULL,
10045 NULL,
10046 num_vertices33,
10047 num_faces33,
10048 vertex_size33,
10049 options,
10050 options,
10051 declaration_ptc_short4n,
10052 declaration_ptc_float4,
10053 (BYTE*)exp_vertices33,
10054 exp_vertex_size33
10057 (BYTE*)vertices34,
10058 NULL,
10059 NULL,
10060 num_vertices34,
10061 num_faces34,
10062 vertex_size34,
10063 options,
10064 options,
10065 declaration_ptc_float16_2,
10066 declaration_ptc_float4,
10067 (BYTE*)exp_vertices34,
10068 exp_vertex_size34
10071 (BYTE*)vertices35,
10072 NULL,
10073 NULL,
10074 num_vertices35,
10075 num_faces35,
10076 vertex_size35,
10077 options,
10078 options,
10079 declaration_ptc_float16_4,
10080 declaration_ptc_float4,
10081 (BYTE*)exp_vertices35,
10082 exp_vertex_size35
10085 (BYTE*)vertices36,
10086 NULL,
10087 NULL,
10088 num_vertices36,
10089 num_faces36,
10090 vertex_size36,
10091 options,
10092 clone_options36,
10093 declaration_pn,
10094 declaration_pn,
10095 (BYTE*)vertices36,
10096 vertex_size36
10100 test_context = new_test_context();
10101 if (!test_context)
10103 skip("Couldn't create test context\n");
10104 goto cleanup;
10107 for (i = 0; i < ARRAY_SIZE(tc); i++)
10109 UINT j;
10110 D3DVERTEXELEMENT9 new_declaration[MAX_FVF_DECL_SIZE];
10111 UINT exp_new_decl_length, new_decl_length;
10112 UINT exp_new_decl_size, new_decl_size;
10114 hr = init_test_mesh(tc[i].num_faces, tc[i].num_vertices,
10115 tc[i].create_options,
10116 tc[i].declaration,
10117 test_context->device, &mesh,
10118 tc[i].vertices, tc[i].vertex_size,
10119 tc[i].indices, tc[i].attributes);
10120 if (FAILED(hr))
10122 skip("Couldn't initialize test mesh %d. Got %x expected D3D_OK\n", i, hr);
10123 goto cleanup;
10126 hr = mesh->lpVtbl->CloneMesh(mesh, tc[i].clone_options, tc[i].new_declaration,
10127 test_context->device, &mesh_clone);
10128 ok(hr == D3D_OK, "CloneMesh test case %d failed. Got %x\n, expected D3D_OK\n", i, hr);
10130 hr = mesh_clone->lpVtbl->GetDeclaration(mesh_clone, new_declaration);
10131 ok(hr == D3D_OK, "GetDeclaration test case %d failed. Got %x\n, expected D3D_OK\n", i, hr);
10132 /* Check declaration elements */
10133 for (j = 0; tc[i].new_declaration[j].Stream != 0xFF; j++)
10135 ok(memcmp(&tc[i].new_declaration[j], &new_declaration[j], sizeof(*new_declaration)) == 0,
10136 "Test case %d failed. Declaration element %d did not match.\n", i, j);
10139 /* Check declaration length */
10140 exp_new_decl_length = D3DXGetDeclLength(tc[i].new_declaration);
10141 new_decl_length = D3DXGetDeclLength(new_declaration);
10142 ok(new_decl_length == exp_new_decl_length,
10143 "Test case %d failed. Got new declaration length %d, expected %d\n",
10144 i, new_decl_length, exp_new_decl_length);
10146 /* Check declaration size */
10147 exp_new_decl_size = D3DXGetDeclVertexSize(tc[i].new_declaration, 0);
10148 new_decl_size = D3DXGetDeclVertexSize(new_declaration, 0);
10149 ok(new_decl_size == exp_new_decl_size,
10150 "Test case %d failed. Got new declaration size %d, expected %d\n",
10151 i, new_decl_size, exp_new_decl_size);
10153 /* Check vertex data in cloned mesh */
10154 hr = mesh_clone->lpVtbl->LockVertexBuffer(mesh_clone, 0, (void**)&vertices);
10155 if (FAILED(hr))
10157 skip("Couldn't lock cloned vertex buffer.\n");
10158 goto cleanup;
10160 for (j = 0; j < tc[i].num_vertices; j++)
10162 UINT index = tc[i].exp_vertex_size * j;
10163 check_vertex_components(__LINE__, i, j, &vertices[index], &tc[i].exp_vertices[index], tc[i].new_declaration);
10165 hr = mesh_clone->lpVtbl->UnlockVertexBuffer(mesh_clone);
10166 if (FAILED(hr))
10168 skip("Couldn't unlock vertex buffer.\n");
10169 goto cleanup;
10171 vertices = NULL;
10172 mesh->lpVtbl->Release(mesh);
10173 mesh = NULL;
10174 mesh_clone->lpVtbl->Release(mesh_clone);
10175 mesh_clone = NULL;
10178 /* The following test shows that it is not possible to share a vertex buffer
10179 * with D3DXMESH_VB_SHARE and change the vertex declaration at the same
10180 * time. It reuses the test data from test 2.
10182 hr = init_test_mesh(tc[2].num_faces, tc[2].num_vertices,
10183 tc[2].create_options,
10184 tc[2].declaration,
10185 test_context->device, &mesh,
10186 tc[2].vertices, tc[2].vertex_size,
10187 tc[2].indices, tc[2].attributes);
10188 if (FAILED(hr))
10190 skip("Couldn't initialize test mesh for D3DXMESH_VB_SHARE case."
10191 " Got %x expected D3D_OK\n", hr);
10192 goto cleanup;
10195 hr = mesh->lpVtbl->CloneMesh(mesh, tc[2].create_options | D3DXMESH_VB_SHARE,
10196 tc[2].new_declaration, test_context->device,
10197 &mesh_clone);
10198 ok(hr == D3DERR_INVALIDCALL, "CloneMesh D3DXMESH_VB_SHARE with new"
10199 " declaration. Got %x, expected D3DERR_INVALIDCALL\n",
10200 hr);
10201 mesh->lpVtbl->Release(mesh);
10202 mesh = NULL;
10203 mesh_clone = NULL;
10205 cleanup:
10206 if (vertices) mesh->lpVtbl->UnlockVertexBuffer(mesh);
10207 if (mesh) mesh->lpVtbl->Release(mesh);
10208 if (mesh_clone) mesh_clone->lpVtbl->Release(mesh_clone);
10209 free_test_context(test_context);
10212 static void test_valid_mesh(void)
10214 HRESULT hr;
10215 struct test_context *test_context = NULL;
10216 UINT i;
10217 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
10218 const D3DVERTEXELEMENT9 declaration[] =
10220 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
10221 D3DDECL_END()
10223 const unsigned int VERTS_PER_FACE = 3;
10224 /* mesh0 (one face)
10226 * 0--1
10227 * | /
10228 * |/
10231 const D3DXVECTOR3 vertices0[] =
10233 { 0.0f, 3.0f, 0.f},
10234 { 2.0f, 3.0f, 0.f},
10235 { 0.0f, 0.0f, 0.f},
10237 const DWORD indices0[] = {0, 1, 2};
10238 const unsigned int num_vertices0 = ARRAY_SIZE(vertices0);
10239 const unsigned int num_faces0 = ARRAY_SIZE(indices0) / VERTS_PER_FACE;
10240 const DWORD adjacency0[] = {-1, -1, -1};
10241 const HRESULT exp_hr0 = D3D_OK;
10242 /* mesh1 (Simple bow-tie)
10244 * 0--1 1--3
10245 * | / \ |
10246 * |/ \|
10247 * 2 4
10249 const D3DXVECTOR3 vertices1[] =
10251 { 0.0f, 3.0f, 0.f},
10252 { 2.0f, 3.0f, 0.f},
10253 { 0.0f, 0.0f, 0.f},
10255 { 4.0f, 3.0f, 0.f},
10256 { 4.0f, 0.0f, 0.f},
10258 const DWORD indices1[] = {0, 1, 2, 1, 3, 4};
10259 const unsigned int num_vertices1 = ARRAY_SIZE(vertices1);
10260 const unsigned int num_faces1 = ARRAY_SIZE(indices1) / VERTS_PER_FACE;
10261 const DWORD adjacency1[] = {-1, -1, -1, -1, -1, -1};
10262 const HRESULT exp_hr1 = D3DXERR_INVALIDMESH;
10263 /* Common mesh data */
10264 ID3DXMesh *mesh = NULL;
10265 UINT vertex_size = sizeof(D3DXVECTOR3);
10266 ID3DXBuffer *errors_and_warnings = NULL;
10267 struct
10269 const D3DXVECTOR3 *vertices;
10270 const DWORD *indices;
10271 const UINT num_vertices;
10272 const UINT num_faces;
10273 const DWORD *adjacency;
10274 const HRESULT exp_hr;
10276 tc[] =
10279 vertices0,
10280 indices0,
10281 num_vertices0,
10282 num_faces0,
10283 adjacency0,
10284 exp_hr0,
10287 vertices1,
10288 indices1,
10289 num_vertices1,
10290 num_faces1,
10291 adjacency1,
10292 exp_hr1,
10296 test_context = new_test_context();
10297 if (!test_context)
10299 skip("Couldn't create test context\n");
10300 goto cleanup;
10303 for (i = 0; i < ARRAY_SIZE(tc); i++)
10305 hr = init_test_mesh(tc[i].num_faces, tc[i].num_vertices,
10306 options, declaration,
10307 test_context->device, &mesh,
10308 tc[i].vertices, vertex_size,
10309 tc[i].indices, NULL);
10310 if (FAILED(hr))
10312 skip("Couldn't initialize test mesh %d. Got %x expected D3D_OK\n", i, hr);
10313 goto cleanup;
10316 hr = D3DXValidMesh(mesh, tc[i].adjacency, &errors_and_warnings);
10317 todo_wine ok(hr == tc[i].exp_hr, "D3DXValidMesh test case %d failed. "
10318 "Got %x\n, expected %x\n", i, hr, tc[i].exp_hr);
10320 /* Note errors_and_warnings is deliberately not checked because that
10321 * would require copying wast amounts of the text output. */
10322 if (errors_and_warnings)
10324 ID3DXBuffer_Release(errors_and_warnings);
10325 errors_and_warnings = NULL;
10327 mesh->lpVtbl->Release(mesh);
10328 mesh = NULL;
10331 cleanup:
10332 if (mesh) mesh->lpVtbl->Release(mesh);
10333 free_test_context(test_context);
10336 static void test_optimize_faces(void)
10338 HRESULT hr;
10339 UINT i;
10340 DWORD smallest_face_remap;
10341 /* mesh0
10343 * 0--1
10344 * | /
10345 * |/
10348 const DWORD indices0[] = {0, 1, 2};
10349 const UINT num_faces0 = 1;
10350 const UINT num_vertices0 = 3;
10351 const DWORD exp_face_remap0[] = {0};
10352 /* mesh1
10354 * 0--1 3
10355 * | / /|
10356 * |/ / |
10357 * 2 5--4
10359 const DWORD indices1[] = {0, 1, 2, 3, 4, 5};
10360 const UINT num_faces1 = 2;
10361 const UINT num_vertices1 = 6;
10362 const DWORD exp_face_remap1[] = {1, 0};
10363 /* mesh2
10365 * 0--1
10366 * | /|
10367 * |/ |
10368 * 2--3
10370 const DWORD indices2[] = {0, 1, 2, 1, 3, 2};
10371 const UINT num_faces2 = 2;
10372 const UINT num_vertices2 = 4;
10373 const DWORD exp_face_remap2[] = {1, 0};
10374 /* mesh3
10376 * 0--1
10377 * | /|
10378 * |/ |
10379 * 2--3
10380 * | /|
10381 * |/ |
10382 * 4--5
10384 const DWORD indices3[] = {0, 1, 2, 1, 3, 2, 2, 3, 4, 3, 4, 5};
10385 const UINT num_faces3 = 4;
10386 const UINT num_vertices3 = 6;
10387 const DWORD exp_face_remap3[] = {3, 2, 1, 0};
10388 /* mesh4
10390 * 0--1
10391 * | /|
10392 * |/ |
10393 * 2--3
10394 * | /|
10395 * |/ |
10396 * 4--5
10398 const WORD indices4[] = {0, 1, 2, 1, 3, 2, 2, 3, 4, 3, 4, 5};
10399 const UINT num_faces4 = 4;
10400 const UINT num_vertices4 = 6;
10401 const DWORD exp_face_remap4[] = {3, 2, 1, 0};
10402 /* Test cases are stored in the tc array */
10403 struct
10405 const VOID *indices;
10406 const UINT num_faces;
10407 const UINT num_vertices;
10408 const BOOL indices_are_32bit;
10409 const DWORD *exp_face_remap;
10411 tc[] =
10414 indices0,
10415 num_faces0,
10416 num_vertices0,
10417 TRUE,
10418 exp_face_remap0
10421 indices1,
10422 num_faces1,
10423 num_vertices1,
10424 TRUE,
10425 exp_face_remap1
10428 indices2,
10429 num_faces2,
10430 num_vertices2,
10431 TRUE,
10432 exp_face_remap2
10435 indices3,
10436 num_faces3,
10437 num_vertices3,
10438 TRUE,
10439 exp_face_remap3
10442 indices4,
10443 num_faces4,
10444 num_vertices4,
10445 FALSE,
10446 exp_face_remap4
10450 /* Go through all test cases */
10451 for (i = 0; i < ARRAY_SIZE(tc); i++)
10453 DWORD j;
10454 DWORD *face_remap;
10455 face_remap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
10456 tc[i].num_faces*sizeof(*face_remap));
10458 hr = D3DXOptimizeFaces(tc[i].indices, tc[i].num_faces,
10459 tc[i].num_vertices, tc[i].indices_are_32bit,
10460 face_remap);
10461 ok(hr == D3D_OK, "D3DXOptimizeFaces test case %d failed. "
10462 "Got %x\n, expected D3D_OK\n", i, hr);
10464 /* Compare face remap with expected face remap */
10465 for (j = 0; j < tc[i].num_faces; j++)
10467 ok(tc[i].exp_face_remap[j] == face_remap[j],
10468 "Test case %d: Got face %d at %d, expected %d\n", i,
10469 face_remap[j], j, tc[i].exp_face_remap[j]);
10472 HeapFree(GetProcessHeap(), 0, face_remap);
10475 /* face_remap must not be NULL */
10476 hr = D3DXOptimizeFaces(tc[0].indices, tc[0].num_faces,
10477 tc[0].num_vertices, tc[0].indices_are_32bit,
10478 NULL);
10479 ok(hr == D3DERR_INVALIDCALL, "D3DXOptimizeFaces passed NULL face_remap "
10480 "pointer. Got %x\n, expected D3DERR_INVALIDCALL\n", hr);
10482 /* Number of faces must be smaller than 2^15 */
10483 hr = D3DXOptimizeFaces(tc[0].indices, 2 << 15,
10484 tc[0].num_vertices, FALSE,
10485 &smallest_face_remap);
10486 ok(hr == D3DERR_INVALIDCALL, "D3DXOptimizeFaces should not accept 2^15 "
10487 "faces when using 16-bit indices. Got %x\n, expected D3DERR_INVALIDCALL\n", hr);
10490 static HRESULT clear_normals(ID3DXMesh *mesh)
10492 HRESULT hr;
10493 BYTE *vertices;
10494 size_t normal_size;
10495 DWORD i, num_vertices, vertex_stride;
10496 const D3DXVECTOR4 normal = {NAN, NAN, NAN, NAN};
10497 D3DVERTEXELEMENT9 *normal_declaration = NULL;
10498 D3DVERTEXELEMENT9 declaration[MAX_FVF_DECL_SIZE] = {D3DDECL_END()};
10500 if (FAILED(hr = mesh->lpVtbl->GetDeclaration(mesh, declaration)))
10501 return hr;
10503 for (i = 0; declaration[i].Stream != 0xff; i++)
10505 if (declaration[i].Usage == D3DDECLUSAGE_NORMAL && !declaration[i].UsageIndex)
10507 normal_declaration = &declaration[i];
10508 break;
10512 if (!normal_declaration)
10513 return D3DERR_INVALIDCALL;
10515 if (normal_declaration->Type == D3DDECLTYPE_FLOAT3)
10517 normal_size = sizeof(D3DXVECTOR3);
10519 else if (normal_declaration->Type == D3DDECLTYPE_FLOAT4)
10521 normal_size = sizeof(D3DXVECTOR4);
10523 else
10525 trace("Cannot clear normals\n");
10526 return E_NOTIMPL;
10529 num_vertices = mesh->lpVtbl->GetNumVertices(mesh);
10530 vertex_stride = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
10532 if (FAILED(hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, (void **)&vertices)))
10533 return hr;
10535 vertices += normal_declaration->Offset;
10537 for (i = 0; i < num_vertices; i++, vertices += vertex_stride)
10538 memcpy(vertices, &normal, normal_size);
10540 return mesh->lpVtbl->UnlockVertexBuffer(mesh);
10543 static void compare_normals(unsigned int line, const char *test_name,
10544 ID3DXMesh *mesh, const D3DXVECTOR3 *normals, unsigned int num_normals)
10546 unsigned int i;
10547 BYTE *vertices;
10548 DWORD num_vertices, vertex_stride;
10549 D3DVERTEXELEMENT9 *normal_declaration = NULL;
10550 D3DVERTEXELEMENT9 declaration[MAX_FVF_DECL_SIZE] = {D3DDECL_END()};
10552 if (FAILED(mesh->lpVtbl->GetDeclaration(mesh, declaration)))
10554 ok_(__FILE__, line)(0, "%s: Failed to get declaration\n", test_name);
10555 return;
10558 for (i = 0; declaration[i].Stream != 0xff; i++)
10560 if (declaration[i].Usage == D3DDECLUSAGE_NORMAL && !declaration[i].UsageIndex)
10562 normal_declaration = &declaration[i];
10563 break;
10567 if (!normal_declaration)
10569 ok_(__FILE__, line)(0, "%s: Mesh has no normals\n", test_name);
10570 return;
10573 if (normal_declaration->Type != D3DDECLTYPE_FLOAT3 && normal_declaration->Type != D3DDECLTYPE_FLOAT4)
10575 ok_(__FILE__, line)(0, "%s: Mesh has invalid normals type\n", test_name);
10576 return;
10579 num_vertices = mesh->lpVtbl->GetNumVertices(mesh);
10580 vertex_stride = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
10582 ok_(__FILE__, line)(num_vertices == num_normals, "%s: Expected %u vertices, got %u\n", test_name,
10583 num_normals, num_vertices);
10585 if (FAILED(mesh->lpVtbl->LockVertexBuffer(mesh, 0, (void **)&vertices)))
10587 ok_(__FILE__, line)(0, "%s: Failed to compare normals\n", test_name);
10588 return;
10591 vertices += normal_declaration->Offset;
10593 for (i = 0; i < min(num_vertices, num_normals); i++, vertices += vertex_stride)
10595 if (normal_declaration->Type == D3DDECLTYPE_FLOAT3)
10597 const D3DXVECTOR3 *n = (D3DXVECTOR3 *)vertices;
10598 ok_(__FILE__, line)(compare_vec3(*n, normals[i]),
10599 "%s: normal %2u, expected (%f, %f, %f), got (%f, %f, %f)\n",
10600 test_name, i, normals[i].x, normals[i].y, normals[i].z, n->x, n->y, n->z);
10602 else
10604 const D3DXVECTOR4 *n = (D3DXVECTOR4 *)vertices;
10605 const D3DXVECTOR4 normal = {normals[i].x, normals[i].y, normals[i].z, 1.0f};
10606 ok_(__FILE__, line)(compare_vec4(*n, normal),
10607 "%s: normal %2u, expected (%f, %f, %f, %f), got (%f, %f, %f, %f)\n",
10608 test_name, i, normals[i].x, normals[i].y, normals[i].z, 1.0f,
10609 n->x, n->y, n->z, n->w);
10613 mesh->lpVtbl->UnlockVertexBuffer(mesh);
10616 static HRESULT compute_normals_D3DXComputeNormals(ID3DXMesh *mesh, const DWORD *adjacency)
10618 return D3DXComputeNormals((ID3DXBaseMesh *)mesh, adjacency);
10621 static HRESULT compute_normals_D3DXComputeTangentFrameEx(ID3DXMesh *mesh, const DWORD *adjacency)
10623 return D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
10624 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS,
10625 adjacency, -1.01f, -0.01f, -1.01f, NULL, NULL);
10628 static void test_compute_normals(void)
10630 HRESULT hr;
10631 ULONG refcount;
10632 ID3DXMesh *mesh, *cloned_mesh;
10633 ID3DXBuffer *adjacency;
10634 IDirect3DDevice9 *device;
10635 struct test_context *test_context;
10636 unsigned int i;
10638 static const struct compute_normals_func
10640 const char *name;
10641 HRESULT (*apply)(ID3DXMesh *mesh, const DWORD *adjacency);
10643 compute_normals_funcs[] =
10645 {"D3DXComputeNormals", compute_normals_D3DXComputeNormals },
10646 {"D3DXComputeTangentFrameEx", compute_normals_D3DXComputeTangentFrameEx}
10649 static const D3DXVECTOR3 box_normals[24] =
10651 {-1.0f, 0.0f, 0.0f}, {-1.0f, 0.0f, 0.0f}, {-1.0f, 0.0f, 0.0f}, {-1.0f, 0.0f, 0.0f},
10652 { 0.0f, 1.0f, 0.0f}, { 0.0f, 1.0f, 0.0f}, { 0.0f, 1.0f, 0.0f}, { 0.0f, 1.0f, 0.0f},
10653 { 1.0f, 0.0f, 0.0f}, { 1.0f, 0.0f, 0.0f}, { 1.0f, 0.0f, 0.0f}, { 1.0f, 0.0f, 0.0f},
10654 { 0.0f,-1.0f, 0.0f}, { 0.0f,-1.0f, 0.0f}, { 0.0f,-1.0f, 0.0f}, { 0.0f,-1.0f, 0.0f},
10655 { 0.0f, 0.0f, 1.0f}, { 0.0f, 0.0f, 1.0f}, { 0.0f, 0.0f, 1.0f}, { 0.0f, 0.0f, 1.0f},
10656 { 0.0f, 0.0f,-1.0f}, { 0.0f, 0.0f,-1.0f}, { 0.0f, 0.0f,-1.0f}, { 0.0f, 0.0f,-1.0f}
10658 const float box_normal_component = 1.0f / sqrtf(3.0f);
10659 const D3DXVECTOR3 box_normals_adjacency[24] =
10661 {-box_normal_component, -box_normal_component, -box_normal_component},
10662 {-box_normal_component, -box_normal_component, box_normal_component},
10663 {-box_normal_component, box_normal_component, box_normal_component},
10664 {-box_normal_component, box_normal_component, -box_normal_component},
10665 {-box_normal_component, box_normal_component, -box_normal_component},
10666 {-box_normal_component, box_normal_component, box_normal_component},
10667 { box_normal_component, box_normal_component, box_normal_component},
10668 { box_normal_component, box_normal_component, -box_normal_component},
10669 { box_normal_component, box_normal_component, -box_normal_component},
10670 { box_normal_component, box_normal_component, box_normal_component},
10671 { box_normal_component, -box_normal_component, box_normal_component},
10672 { box_normal_component, -box_normal_component, -box_normal_component},
10673 {-box_normal_component, -box_normal_component, box_normal_component},
10674 {-box_normal_component, -box_normal_component, -box_normal_component},
10675 { box_normal_component, -box_normal_component, -box_normal_component},
10676 { box_normal_component, -box_normal_component, box_normal_component},
10677 {-box_normal_component, -box_normal_component, box_normal_component},
10678 { box_normal_component, -box_normal_component, box_normal_component},
10679 { box_normal_component, box_normal_component, box_normal_component},
10680 {-box_normal_component, box_normal_component, box_normal_component},
10681 {-box_normal_component, -box_normal_component, -box_normal_component},
10682 {-box_normal_component, box_normal_component, -box_normal_component},
10683 { box_normal_component, box_normal_component, -box_normal_component},
10684 { box_normal_component, -box_normal_component, -box_normal_component}
10686 static const D3DXVECTOR3 box_normals_adjacency_area[24] =
10688 {-0.666667f, -0.333333f, -0.666667f}, {-0.333333f, -0.666667f, 0.666667f},
10689 {-0.816496f, 0.408248f, 0.408248f}, {-0.408248f, 0.816496f, -0.408248f},
10690 {-0.408248f, 0.816496f, -0.408248f}, {-0.816496f, 0.408248f, 0.408248f},
10691 { 0.333333f, 0.666667f, 0.666667f}, { 0.666667f, 0.333333f, -0.666667f},
10692 { 0.666667f, 0.333333f, -0.666667f}, { 0.333333f, 0.666667f, 0.666667f},
10693 { 0.816496f, -0.408248f, 0.408248f}, { 0.408248f, -0.816496f, -0.408248f},
10694 {-0.333333f, -0.666667f, 0.666667f}, {-0.666667f, -0.333333f, -0.666667f},
10695 { 0.408248f, -0.816496f, -0.408248f}, { 0.816496f, -0.408248f, 0.408248f},
10696 {-0.333333f, -0.666667f, 0.666667f}, { 0.816497f, -0.408248f, 0.408248f},
10697 { 0.333333f, 0.666667f, 0.666667f}, {-0.816497f, 0.408248f, 0.408248f},
10698 {-0.666667f, -0.333333f, -0.666667f}, {-0.408248f, 0.816497f, -0.408248f},
10699 { 0.666667f, 0.333333f, -0.666667f}, { 0.408248f, -0.816496f, -0.408248f}
10701 static const D3DXVECTOR3 box_normals_position1f[24] = {{0}};
10702 static const D3DXVECTOR3 box_normals_position2f[24] =
10704 {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f},
10705 {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, 1.0f},
10706 {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, -1.0f},
10707 {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f},
10708 {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, -1.0f},
10709 {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f},
10710 {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f},
10711 {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, -1.0f}
10714 static const D3DXVECTOR3 sphere_normals[22] =
10716 { 0.000000f, -0.000000f, 1.000000f}, { 0.000000f, 0.582244f, 0.813014f},
10717 { 0.582244f, -0.000000f, 0.813014f}, {-0.000000f, -0.582244f, 0.813014f},
10718 {-0.582244f, 0.000000f, 0.813014f}, {-0.000000f, 0.890608f, 0.454772f},
10719 { 0.890608f, 0.000000f, 0.454772f}, { 0.000000f, -0.890608f, 0.454772f},
10720 {-0.890608f, -0.000000f, 0.454772f}, { 0.000000f, 1.000000f, -0.000000f},
10721 { 1.000000f, -0.000000f, -0.000000f}, {-0.000000f, -1.000000f, -0.000000f},
10722 {-1.000000f, 0.000000f, -0.000000f}, { 0.000000f, 0.890608f, -0.454773f},
10723 { 0.890608f, -0.000000f, -0.454772f}, {-0.000000f, -0.890608f, -0.454773f},
10724 {-0.890608f, 0.000000f, -0.454773f}, { 0.000000f, 0.582244f, -0.813015f},
10725 { 0.582244f, -0.000000f, -0.813015f}, { 0.000000f, -0.582244f, -0.813015f},
10726 {-0.582243f, 0.000000f, -0.813015f}, { 0.000000f, 0.000000f, -1.000000f}
10728 static const D3DXVECTOR3 sphere_normals_area[22] =
10730 { 0.000000f, -0.000000f, 1.000000f}, {-0.215311f, 0.554931f, 0.803550f},
10731 { 0.554931f, 0.215311f, 0.803550f}, { 0.215311f, -0.554931f, 0.803550f},
10732 {-0.554931f, -0.215311f, 0.803550f}, {-0.126638f, 0.872121f, 0.472618f},
10733 { 0.872121f, 0.126638f, 0.472618f}, { 0.126638f, -0.872121f, 0.472618f},
10734 {-0.872121f, -0.126637f, 0.472618f}, { 0.000000f, 1.000000f, -0.000000f},
10735 { 1.000000f, -0.000000f, -0.000000f}, {-0.000000f, -1.000000f, -0.000000f},
10736 {-1.000000f, 0.000000f, -0.000000f}, { 0.126638f, 0.872121f, -0.472618f},
10737 { 0.872121f, -0.126638f, -0.472618f}, {-0.126638f, -0.872121f, -0.472618f},
10738 {-0.872121f, 0.126638f, -0.472618f}, { 0.215311f, 0.554931f, -0.803550f},
10739 { 0.554931f, -0.215311f, -0.803550f}, {-0.215311f, -0.554931f, -0.803550f},
10740 {-0.554931f, 0.215311f, -0.803550f}, { 0.000000f, 0.000000f, -1.000000f}
10742 static const D3DXVECTOR3 sphere_normals_equal[22] =
10744 { 0.000000f, -0.000000f, 1.000000f}, {-0.134974f, 0.522078f, 0.842150f},
10745 { 0.522078f, 0.134974f, 0.842150f}, { 0.134974f, -0.522078f, 0.842150f},
10746 {-0.522078f, -0.134974f, 0.842150f}, {-0.026367f, 0.857121f, 0.514440f},
10747 { 0.857121f, 0.026367f, 0.514440f}, { 0.026367f, -0.857121f, 0.514440f},
10748 {-0.857121f, -0.026367f, 0.514440f}, { 0.000000f, 1.000000f, -0.000000f},
10749 { 1.000000f, -0.000000f, -0.000000f}, {-0.000000f, -1.000000f, -0.000000f},
10750 {-1.000000f, 0.000000f, -0.000000f}, { 0.026367f, 0.857121f, -0.514440f},
10751 { 0.857121f, -0.026367f, -0.514440f}, {-0.026367f, -0.857121f, -0.514440f},
10752 {-0.857121f, 0.026367f, -0.514440f}, { 0.134975f, 0.522078f, -0.842150f},
10753 { 0.522078f, -0.134975f, -0.842150f}, {-0.134974f, -0.522078f, -0.842150f},
10754 {-0.522078f, 0.134974f, -0.842150f}, { 0.000000f, 0.000000f, -1.000000f}
10757 static const D3DVERTEXELEMENT9 position3f_normal1f_declaration[] =
10759 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
10760 {0, sizeof(D3DXVECTOR3), D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
10761 D3DDECL_END()
10763 static const D3DVERTEXELEMENT9 position3f_normal2f_declaration[] =
10765 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
10766 {0, sizeof(D3DXVECTOR3), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
10767 D3DDECL_END()
10769 static const D3DVERTEXELEMENT9 normal4f_position3f_declaration[] =
10771 {0, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
10772 {0, sizeof(D3DXVECTOR4), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
10773 D3DDECL_END()
10775 static const D3DVERTEXELEMENT9 position1f_normal3f_declaration[] =
10777 {0, 0, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
10778 {0, sizeof(float), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
10779 D3DDECL_END()
10781 static const D3DVERTEXELEMENT9 position2f_normal3f_declaration[] =
10783 {0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
10784 {0, sizeof(D3DXVECTOR2), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
10785 D3DDECL_END()
10787 static const D3DVERTEXELEMENT9 position4f_normal3f_declaration[] =
10789 {0, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
10790 {0, sizeof(D3DXVECTOR4), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
10791 D3DDECL_END()
10794 for (i = 0; i < ARRAY_SIZE(compute_normals_funcs); i++)
10796 hr = compute_normals_funcs[i].apply(NULL, NULL);
10797 ok(hr == D3DERR_INVALIDCALL, "%s returned %#x, expected D3DERR_INVALIDCALL\n", compute_normals_funcs[i].name, hr);
10800 if (!(test_context = new_test_context()))
10802 skip("Couldn't create test context\n");
10803 return;
10805 device = test_context->device;
10807 hr = D3DXCreateBox(device, 1.0f, 1.0f, 1.0f, &mesh, &adjacency);
10808 ok(SUCCEEDED(hr), "D3DXCreateBox failed %#x\n", hr);
10810 /* Check wrong input */
10811 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
10812 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE, NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
10813 todo_wine ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr);
10815 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DDECLUSAGE_NORMAL, 0,
10816 D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_BY_AREA | D3DXTANGENT_WEIGHT_EQUAL,
10817 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
10818 ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr);
10820 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
10821 D3DDECLUSAGE_NORMAL, 0, 0, NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
10822 todo_wine ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr);
10824 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
10825 D3DDECLUSAGE_NORMAL, 1, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS,
10826 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
10827 ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr);
10829 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
10830 D3DX_DEFAULT, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS,
10831 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
10832 ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr);
10834 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
10835 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_CALCULATE_NORMALS,
10836 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
10837 todo_wine ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr);
10839 for (i = 0; i < ARRAY_SIZE(compute_normals_funcs); i++)
10841 const struct compute_normals_func *func = &compute_normals_funcs[i];
10843 /* Mesh without normals */
10844 hr = mesh->lpVtbl->CloneMeshFVF(mesh, 0, D3DFVF_XYZ, device, &cloned_mesh);
10845 ok(SUCCEEDED(hr), "CloneMeshFVF failed %#x\n", hr);
10847 hr = func->apply(cloned_mesh, NULL);
10848 ok(hr == D3DERR_INVALIDCALL, "%s returned %#x, expected D3DERR_INVALIDCALL\n", func->name, hr);
10850 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh);
10851 ok(!refcount, "Mesh has %u references left\n", refcount);
10853 /* Mesh without positions */
10854 hr = mesh->lpVtbl->CloneMeshFVF(mesh, 0, D3DFVF_NORMAL, device, &cloned_mesh);
10855 ok(SUCCEEDED(hr), "CloneMeshFVF failed %#x\n", hr);
10857 hr = func->apply(cloned_mesh, NULL);
10858 ok(hr == D3DERR_INVALIDCALL, "%s returned %#x, expected D3DERR_INVALIDCALL\n", func->name, hr);
10860 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh);
10861 ok(!refcount, "Mesh has %u references left\n", refcount);
10863 /* Mesh with D3DDECLTYPE_FLOAT1 normals */
10864 hr = mesh->lpVtbl->CloneMesh(mesh, 0, position3f_normal1f_declaration, device, &cloned_mesh);
10865 ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr);
10867 hr = func->apply(cloned_mesh, NULL);
10868 ok(hr == D3DERR_INVALIDCALL, "%s returned %#x, expected D3DERR_INVALIDCALL\n", func->name, hr);
10870 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh);
10871 ok(!refcount, "Mesh has %u references left\n", refcount);
10873 /* Mesh with D3DDECLTYPE_FLOAT2 normals */
10874 hr = mesh->lpVtbl->CloneMesh(mesh, 0, position3f_normal2f_declaration, device, &cloned_mesh);
10875 ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr);
10877 hr = func->apply(cloned_mesh, NULL);
10878 ok(hr == D3DERR_INVALIDCALL, "%s returned %#x, expected D3DERR_INVALIDCALL\n", func->name, hr);
10880 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh);
10881 ok(!refcount, "Mesh has %u references left\n", refcount);
10883 /* Mesh without adjacency data */
10884 hr = clear_normals(mesh);
10885 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr);
10887 hr = func->apply(mesh, NULL);
10888 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr);
10890 compare_normals(__LINE__, func->name, mesh, box_normals, ARRAY_SIZE(box_normals));
10892 /* Mesh with adjacency data */
10893 hr = clear_normals(mesh);
10894 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr);
10896 hr = func->apply(mesh, ID3DXBuffer_GetBufferPointer(adjacency));
10897 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr);
10899 compare_normals(__LINE__, func->name, mesh, box_normals_adjacency, ARRAY_SIZE(box_normals_adjacency));
10901 /* Mesh with custom vertex format, D3DDECLTYPE_FLOAT4 normals and adjacency */
10902 hr = mesh->lpVtbl->CloneMesh(mesh, 0, normal4f_position3f_declaration, device, &cloned_mesh);
10903 ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr);
10905 hr = clear_normals(cloned_mesh);
10906 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr);
10908 hr = func->apply(cloned_mesh, ID3DXBuffer_GetBufferPointer(adjacency));
10909 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr);
10911 compare_normals(__LINE__, func->name, cloned_mesh, box_normals_adjacency, ARRAY_SIZE(box_normals_adjacency));
10913 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh);
10914 ok(!refcount, "Mesh has %u references left\n", refcount);
10916 /* Mesh with D3DDECLTYPE_FLOAT1 positions and D3DDECLTYPE_FLOAT3 normals */
10917 hr = mesh->lpVtbl->CloneMesh(mesh, 0, position1f_normal3f_declaration, device, &cloned_mesh);
10918 ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr);
10920 hr = clear_normals(cloned_mesh);
10921 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr);
10923 hr = func->apply(cloned_mesh, ID3DXBuffer_GetBufferPointer(adjacency));
10924 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr);
10926 compare_normals(__LINE__, func->name, cloned_mesh, box_normals_position1f, ARRAY_SIZE(box_normals_position1f));
10928 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh);
10929 ok(!refcount, "Mesh has %u references left\n", refcount);
10931 /* Mesh with D3DDECLTYPE_FLOAT2 positions and D3DDECLTYPE_FLOAT3 normals */
10932 hr = mesh->lpVtbl->CloneMesh(mesh, 0, position2f_normal3f_declaration, device, &cloned_mesh);
10933 ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr);
10935 hr = clear_normals(cloned_mesh);
10936 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr);
10938 hr = func->apply(cloned_mesh, ID3DXBuffer_GetBufferPointer(adjacency));
10939 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr);
10941 compare_normals(__LINE__, func->name, cloned_mesh, box_normals_position2f, ARRAY_SIZE(box_normals_position2f));
10943 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh);
10944 ok(!refcount, "Mesh has %u references left\n", refcount);
10946 /* Mesh with D3DDECLTYPE_FLOAT4 positions and D3DDECLTYPE_FLOAT3 normals */
10947 hr = mesh->lpVtbl->CloneMesh(mesh, 0, position4f_normal3f_declaration, device, &cloned_mesh);
10948 ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr);
10950 hr = clear_normals(cloned_mesh);
10951 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr);
10953 hr = func->apply(cloned_mesh, ID3DXBuffer_GetBufferPointer(adjacency));
10954 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr);
10956 compare_normals(__LINE__, func->name, cloned_mesh, box_normals_adjacency, ARRAY_SIZE(box_normals_adjacency));
10958 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh);
10959 ok(!refcount, "Mesh has %u references left\n", refcount);
10962 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
10963 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_BY_AREA,
10964 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
10965 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr);
10967 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, box_normals, ARRAY_SIZE(box_normals));
10969 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
10970 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_BY_AREA,
10971 ID3DXBuffer_GetBufferPointer(adjacency), -1.01f, -0.01f, -1.01f, NULL, NULL);
10972 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr);
10974 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, box_normals_adjacency_area, ARRAY_SIZE(box_normals_adjacency_area));
10976 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
10977 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_EQUAL,
10978 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
10979 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr);
10981 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, box_normals, ARRAY_SIZE(box_normals));
10983 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
10984 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_EQUAL,
10985 ID3DXBuffer_GetBufferPointer(adjacency), -1.01f, -0.01f, -1.01f, NULL, NULL);
10986 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr);
10988 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, box_normals_adjacency_area, ARRAY_SIZE(box_normals_adjacency_area));
10990 refcount = mesh->lpVtbl->Release(mesh);
10991 ok(!refcount, "Mesh has %u references left\n", refcount);
10992 refcount = ID3DXBuffer_Release(adjacency);
10993 ok(!refcount, "Buffer has %u references left\n", refcount);
10995 hr = D3DXCreateSphere(device, 1.0f, 4, 6, &mesh, &adjacency);
10996 ok(SUCCEEDED(hr), "D3DXCreateSphere failed %#x\n", hr);
10998 for (i = 0; i < ARRAY_SIZE(compute_normals_funcs); i++)
11000 const struct compute_normals_func *func = &compute_normals_funcs[i];
11002 /* Sphere without adjacency data */
11003 hr = clear_normals(mesh);
11004 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr);
11006 hr = func->apply(mesh, NULL);
11007 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr);
11009 compare_normals(__LINE__, func->name, mesh, sphere_normals, ARRAY_SIZE(sphere_normals));
11011 /* Sphere with adjacency data */
11012 hr = clear_normals(mesh);
11013 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr);
11015 hr = func->apply(mesh, ID3DXBuffer_GetBufferPointer(adjacency));
11016 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr);
11018 compare_normals(__LINE__, func->name, mesh, sphere_normals, ARRAY_SIZE(sphere_normals));
11021 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
11022 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_BY_AREA,
11023 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
11024 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr);
11026 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, sphere_normals_area, ARRAY_SIZE(sphere_normals_area));
11028 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
11029 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_BY_AREA,
11030 ID3DXBuffer_GetBufferPointer(adjacency), -1.01f, -0.01f, -1.01f, NULL, NULL);
11031 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr);
11033 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, sphere_normals_area, ARRAY_SIZE(sphere_normals_area));
11035 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
11036 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_EQUAL,
11037 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
11038 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr);
11040 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, sphere_normals_equal, ARRAY_SIZE(sphere_normals_equal));
11042 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
11043 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_EQUAL,
11044 ID3DXBuffer_GetBufferPointer(adjacency), -1.01f, -0.01f, -1.01f, NULL, NULL);
11045 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr);
11047 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, sphere_normals_equal, ARRAY_SIZE(sphere_normals_equal));
11049 refcount = mesh->lpVtbl->Release(mesh);
11050 ok(!refcount, "Mesh has %u references left\n", refcount);
11051 refcount = ID3DXBuffer_Release(adjacency);
11052 ok(!refcount, "Buffer has %u references left\n", refcount);
11054 free_test_context(test_context);
11057 static void D3DXCreateAnimationControllerTest(void)
11059 HRESULT hr;
11060 ID3DXAnimationController *animation;
11061 UINT value;
11063 hr = D3DXCreateAnimationController(0, 0, 0, 0, NULL);
11064 ok(hr == D3D_OK, "Got unexpected hr returned %#x.\n", hr);
11066 animation = (void*)0xdeadbeef;
11067 hr = D3DXCreateAnimationController(0, 1, 1, 1, &animation);
11068 ok(hr == D3D_OK, "Got unexpected hr returned %#x.\n", hr);
11069 ok(animation == (void*)0xdeadbeef, "Got unexpected animation %p.\n", animation);
11071 animation = (void*)0xdeadbeef;
11072 hr = D3DXCreateAnimationController(1, 0, 1, 1, &animation);
11073 ok(hr == D3D_OK, "Got unexpected hr returned %#x.\n", hr);
11074 ok(animation == (void*)0xdeadbeef, "Got unexpected animation %p.\n", animation);
11076 animation = (void*)0xdeadbeef;
11077 hr = D3DXCreateAnimationController(1, 1, 0, 1, &animation);
11078 ok(hr == D3D_OK, "Got unexpected hr returned %#x.\n", hr);
11079 ok(animation == (void*)0xdeadbeef, "Got unexpected animation %p.\n", animation);
11081 animation = (void*)0xdeadbeef;
11082 hr = D3DXCreateAnimationController(1, 1, 1, 0, &animation);
11083 ok(hr == D3D_OK, "Got unexpected hr returned %#x.\n", hr);
11084 ok(animation == (void*)0xdeadbeef, "Got unexpected animation %p.\n", animation);
11086 hr = D3DXCreateAnimationController(1, 1, 1, 1, &animation);
11087 ok(hr == D3D_OK, "Got unexpected hr returned %#x.\n", hr);
11089 value = animation->lpVtbl->GetMaxNumAnimationOutputs(animation);
11090 ok(value == 1, "Got unexpected value %u.\n", value);
11092 value = animation->lpVtbl->GetMaxNumAnimationSets(animation);
11093 ok(value == 1, "Got unexpected value %u.\n", value);
11095 value = animation->lpVtbl->GetMaxNumTracks(animation);
11096 ok(value == 1, "Got unexpected value %u.\n", value);
11098 value = animation->lpVtbl->GetMaxNumEvents(animation);
11099 ok(value == 1, "Got unexpected value %u.\n", value);
11101 animation->lpVtbl->Release(animation);
11103 hr = D3DXCreateAnimationController(100, 101, 102, 103, &animation);
11104 ok(hr == D3D_OK, "Got unexpected hr returned %#x.\n", hr);
11106 value = animation->lpVtbl->GetMaxNumAnimationOutputs(animation);
11107 ok(value == 100, "Got unexpected value %u.\n", value);
11109 value = animation->lpVtbl->GetMaxNumAnimationSets(animation);
11110 ok(value == 101, "Got unexpected value %u.\n", value);
11112 value = animation->lpVtbl->GetMaxNumTracks(animation);
11113 ok(value == 102, "Got unexpected value %u.\n", value);
11115 value = animation->lpVtbl->GetMaxNumEvents(animation);
11116 ok(value == 103, "Got unexpected value %u.\n", value);
11118 animation->lpVtbl->Release(animation);
11121 static void test_D3DXFrameFind(void)
11123 static char n1[] = "name1";
11124 static char n2[] = "name2";
11125 static char n3[] = "name3";
11126 static char n4[] = "name4";
11127 static char n5[] = "name5";
11128 static char n6[] = "name6";
11129 static char N1[] = "Name1";
11130 D3DXFRAME root, sibling, sibling2, child, *ret;
11131 D3DXFRAME child2, child3;
11133 ret = D3DXFrameFind(NULL, NULL);
11134 ok(ret == NULL, "Unexpected frame, %p.\n", ret);
11136 ret = D3DXFrameFind(NULL, "test");
11137 ok(ret == NULL, "Unexpected frame, %p.\n", ret);
11139 memset(&root, 0, sizeof(root));
11141 ret = D3DXFrameFind(&root, NULL);
11142 ok(ret == &root, "Unexpected frame, %p.\n", ret);
11144 root.Name = n1;
11145 ret = D3DXFrameFind(&root, NULL);
11146 ok(ret == NULL, "Unexpected frame, %p.\n", ret);
11148 ret = D3DXFrameFind(&root, n1);
11149 ok(ret == &root, "Unexpected frame, %p.\n", ret);
11151 ret = D3DXFrameFind(&root, N1);
11152 ok(ret == NULL, "Unexpected frame, %p.\n", ret);
11154 /* Test siblings order traversal. */
11155 memset(&sibling, 0, sizeof(sibling));
11156 sibling.Name = n2;
11157 root.pFrameSibling = &sibling;
11158 ret = D3DXFrameFind(&root, n2);
11159 ok(ret == &sibling, "Unexpected frame, %p.\n", ret);
11161 memset(&sibling2, 0, sizeof(sibling2));
11162 sibling2.Name = n2;
11163 sibling.pFrameSibling = &sibling2;
11164 ret = D3DXFrameFind(&root, n2);
11165 ok(ret == &sibling, "Unexpected frame, %p.\n", ret);
11167 sibling2.Name = n3;
11168 ret = D3DXFrameFind(&root, n3);
11169 ok(ret == &sibling2, "Unexpected frame, %p.\n", ret);
11171 /* Siblings first. */
11172 memset(&child, 0, sizeof(child));
11173 child.Name = n2;
11174 root.pFrameFirstChild = &child;
11175 ret = D3DXFrameFind(&root, n2);
11176 ok(ret == &sibling, "Unexpected frame, %p.\n", ret);
11178 child.Name = n4;
11179 ret = D3DXFrameFind(&root, n4);
11180 ok(ret == &child, "Unexpected frame, %p.\n", ret);
11182 /* Link a grandchild and another one for sibling. */
11183 memset(&child2, 0, sizeof(child2));
11184 memset(&child3, 0, sizeof(child3));
11185 child2.Name = child3.Name = n5;
11186 sibling.pFrameFirstChild = &child2;
11187 child.pFrameFirstChild = &child3;
11188 ret = D3DXFrameFind(&root, n5);
11189 ok(ret == &child2, "Unexpected frame, %p.\n", ret);
11191 child3.Name = n6;
11192 ret = D3DXFrameFind(&root, n6);
11193 ok(ret == &child3, "Unexpected frame, %p.\n", ret);
11196 START_TEST(mesh)
11198 D3DXBoundProbeTest();
11199 D3DXComputeBoundingBoxTest();
11200 D3DXComputeBoundingSphereTest();
11201 D3DXGetFVFVertexSizeTest();
11202 D3DXIntersectTriTest();
11203 D3DXCreateMeshTest();
11204 D3DXCreateMeshFVFTest();
11205 D3DXLoadMeshTest();
11206 D3DXCreateBoxTest();
11207 D3DXCreatePolygonTest();
11208 D3DXCreateSphereTest();
11209 D3DXCreateCylinderTest();
11210 D3DXCreateTextTest();
11211 D3DXCreateTorusTest();
11212 D3DXCreateAnimationControllerTest();
11213 test_get_decl_length();
11214 test_get_decl_vertex_size();
11215 test_fvf_decl_conversion();
11216 D3DXGenerateAdjacencyTest();
11217 test_update_semantics();
11218 test_create_skin_info();
11219 test_convert_adjacency_to_point_reps();
11220 test_convert_point_reps_to_adjacency();
11221 test_weld_vertices();
11222 test_clone_mesh();
11223 test_valid_mesh();
11224 test_optimize_faces();
11225 test_compute_normals();
11226 test_D3DXFrameFind();