kernel32: GetLongPathName should fail when called with a wildcard.
[wine.git] / dlls / d3dx9_36 / tests / mesh.c
blob3fcd65ffbbb5628b4e0504c9e2e17d0762517e3d
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 compare_vertex_sizes(type, exp) \
46 got=D3DXGetFVFVertexSize(type); \
47 ok(got==exp, "Expected: %d, Got: %d\n", exp, got);
49 #define compare_float(got, exp) \
50 do { \
51 float _got = (got); \
52 float _exp = (exp); \
53 ok(_got == _exp, "Expected: %g, Got: %g\n", _exp, _got); \
54 } while (0)
56 static BOOL compare(FLOAT u, FLOAT v)
58 return (fabs(u-v) < admitted_error);
61 static BOOL compare_vec3(D3DXVECTOR3 u, D3DXVECTOR3 v)
63 return ( compare(u.x, v.x) && compare(u.y, v.y) && compare(u.z, v.z) );
66 static BOOL compare_vec4(D3DXVECTOR4 u, D3DXVECTOR4 v)
68 return compare(u.x, v.x) && compare(u.y, v.y) && compare(u.z, v.z) && compare(u.w, v.w);
71 #define check_floats(got, exp, dim) check_floats_(__LINE__, "", got, exp, dim)
72 static void check_floats_(int line, const char *prefix, const float *got, const float *exp, int dim)
74 int i;
75 char exp_buffer[256] = "";
76 char got_buffer[256] = "";
77 char *exp_buffer_ptr = exp_buffer;
78 char *got_buffer_ptr = got_buffer;
79 BOOL equal = TRUE;
81 for (i = 0; i < dim; i++) {
82 if (i) {
83 exp_buffer_ptr += sprintf(exp_buffer_ptr, ", ");
84 got_buffer_ptr += sprintf(got_buffer_ptr, ", ");
86 equal = equal && compare(*exp, *got);
87 exp_buffer_ptr += sprintf(exp_buffer_ptr, "%g", *exp);
88 got_buffer_ptr += sprintf(got_buffer_ptr, "%g", *got);
89 exp++, got++;
91 ok_(__FILE__,line)(equal, "%sExpected (%s), got (%s)", prefix, exp_buffer, got_buffer);
94 struct vertex
96 D3DXVECTOR3 position;
97 D3DXVECTOR3 normal;
100 typedef WORD face[3];
102 static BOOL compare_face(face a, face b)
104 return (a[0]==b[0] && a[1] == b[1] && a[2] == b[2]);
107 struct test_context
109 HWND hwnd;
110 IDirect3D9 *d3d;
111 IDirect3DDevice9 *device;
114 /* Initializes a test context struct. Use it to initialize DirectX.
116 * Returns NULL if an error occurred.
118 static struct test_context *new_test_context(void)
120 HRESULT hr;
121 HWND hwnd = NULL;
122 IDirect3D9 *d3d = NULL;
123 IDirect3DDevice9 *device = NULL;
124 D3DPRESENT_PARAMETERS d3dpp = {0};
125 struct test_context *test_context;
127 if (!(hwnd = CreateWindowA("static", "d3dx9_test", WS_OVERLAPPEDWINDOW, 0, 0,
128 640, 480, NULL, NULL, NULL, NULL)))
130 skip("Couldn't create application window\n");
131 goto error;
134 d3d = Direct3DCreate9(D3D_SDK_VERSION);
135 if (!d3d)
137 skip("Couldn't create IDirect3D9 object\n");
138 goto error;
141 memset(&d3dpp, 0, sizeof(d3dpp));
142 d3dpp.Windowed = TRUE;
143 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
144 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
145 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device);
146 if (FAILED(hr))
148 skip("Couldn't create IDirect3DDevice9 object %#x\n", hr);
149 goto error;
152 test_context = HeapAlloc(GetProcessHeap(), 0, sizeof(*test_context));
153 if (!test_context)
155 skip("Couldn't allocate memory for test_context\n");
156 goto error;
158 test_context->hwnd = hwnd;
159 test_context->d3d = d3d;
160 test_context->device = device;
162 return test_context;
164 error:
165 if (device)
166 IDirect3DDevice9_Release(device);
168 if (d3d)
169 IDirect3D9_Release(d3d);
171 if (hwnd)
172 DestroyWindow(hwnd);
174 return NULL;
177 static void free_test_context(struct test_context *test_context)
179 if (!test_context)
180 return;
182 if (test_context->device)
183 IDirect3DDevice9_Release(test_context->device);
185 if (test_context->d3d)
186 IDirect3D9_Release(test_context->d3d);
188 if (test_context->hwnd)
189 DestroyWindow(test_context->hwnd);
191 HeapFree(GetProcessHeap(), 0, test_context);
194 struct mesh
196 DWORD number_of_vertices;
197 struct vertex *vertices;
199 DWORD number_of_faces;
200 face *faces;
202 DWORD fvf;
203 UINT vertex_size;
206 static void free_mesh(struct mesh *mesh)
208 HeapFree(GetProcessHeap(), 0, mesh->faces);
209 HeapFree(GetProcessHeap(), 0, mesh->vertices);
212 static BOOL new_mesh(struct mesh *mesh, DWORD number_of_vertices, DWORD number_of_faces)
214 mesh->vertices = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, number_of_vertices * sizeof(*mesh->vertices));
215 if (!mesh->vertices)
217 return FALSE;
219 mesh->number_of_vertices = number_of_vertices;
221 mesh->faces = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, number_of_faces * sizeof(*mesh->faces));
222 if (!mesh->faces)
224 HeapFree(GetProcessHeap(), 0, mesh->vertices);
225 return FALSE;
227 mesh->number_of_faces = number_of_faces;
229 return TRUE;
232 static void compare_mesh(const char *name, ID3DXMesh *d3dxmesh, struct mesh *mesh)
234 HRESULT hr;
235 DWORD number_of_vertices, number_of_faces;
236 IDirect3DVertexBuffer9 *vertex_buffer;
237 IDirect3DIndexBuffer9 *index_buffer;
238 D3DVERTEXBUFFER_DESC vertex_buffer_description;
239 D3DINDEXBUFFER_DESC index_buffer_description;
240 struct vertex *vertices;
241 face *faces;
242 int expected, i;
244 number_of_vertices = d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh);
245 ok(number_of_vertices == mesh->number_of_vertices, "Test %s, result %u, expected %d\n",
246 name, number_of_vertices, mesh->number_of_vertices);
248 number_of_faces = d3dxmesh->lpVtbl->GetNumFaces(d3dxmesh);
249 ok(number_of_faces == mesh->number_of_faces, "Test %s, result %u, expected %d\n",
250 name, number_of_faces, mesh->number_of_faces);
252 /* vertex buffer */
253 hr = d3dxmesh->lpVtbl->GetVertexBuffer(d3dxmesh, &vertex_buffer);
254 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
256 if (hr != D3D_OK)
258 skip("Couldn't get vertex buffer\n");
260 else
262 hr = IDirect3DVertexBuffer9_GetDesc(vertex_buffer, &vertex_buffer_description);
263 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
265 if (hr != D3D_OK)
267 skip("Couldn't get vertex buffer description\n");
269 else
271 ok(vertex_buffer_description.Format == D3DFMT_VERTEXDATA, "Test %s, result %x, expected %x (D3DFMT_VERTEXDATA)\n",
272 name, vertex_buffer_description.Format, D3DFMT_VERTEXDATA);
273 ok(vertex_buffer_description.Type == D3DRTYPE_VERTEXBUFFER, "Test %s, result %x, expected %x (D3DRTYPE_VERTEXBUFFER)\n",
274 name, vertex_buffer_description.Type, D3DRTYPE_VERTEXBUFFER);
275 ok(vertex_buffer_description.Usage == 0, "Test %s, result %x, expected %x\n", name, vertex_buffer_description.Usage, 0);
276 ok(vertex_buffer_description.Pool == D3DPOOL_MANAGED, "Test %s, result %x, expected %x (D3DPOOL_MANAGED)\n",
277 name, vertex_buffer_description.Pool, D3DPOOL_MANAGED);
278 ok(vertex_buffer_description.FVF == mesh->fvf, "Test %s, result %x, expected %x\n",
279 name, vertex_buffer_description.FVF, mesh->fvf);
280 if (mesh->fvf == 0)
282 expected = number_of_vertices * mesh->vertex_size;
284 else
286 expected = number_of_vertices * D3DXGetFVFVertexSize(mesh->fvf);
288 ok(vertex_buffer_description.Size == expected, "Test %s, result %x, expected %x\n",
289 name, vertex_buffer_description.Size, expected);
292 /* specify offset and size to avoid potential overruns */
293 hr = IDirect3DVertexBuffer9_Lock(vertex_buffer, 0, number_of_vertices * sizeof(D3DXVECTOR3) * 2,
294 (void **)&vertices, D3DLOCK_DISCARD);
295 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
297 if (hr != D3D_OK)
299 skip("Couldn't lock vertex buffer\n");
301 else
303 for (i = 0; i < number_of_vertices; i++)
305 ok(compare_vec3(vertices[i].position, mesh->vertices[i].position),
306 "Test %s, vertex position %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i,
307 vertices[i].position.x, vertices[i].position.y, vertices[i].position.z,
308 mesh->vertices[i].position.x, mesh->vertices[i].position.y, mesh->vertices[i].position.z);
309 ok(compare_vec3(vertices[i].normal, mesh->vertices[i].normal),
310 "Test %s, vertex normal %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i,
311 vertices[i].normal.x, vertices[i].normal.y, vertices[i].normal.z,
312 mesh->vertices[i].normal.x, mesh->vertices[i].normal.y, mesh->vertices[i].normal.z);
315 IDirect3DVertexBuffer9_Unlock(vertex_buffer);
318 IDirect3DVertexBuffer9_Release(vertex_buffer);
321 /* index buffer */
322 hr = d3dxmesh->lpVtbl->GetIndexBuffer(d3dxmesh, &index_buffer);
323 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
325 if (!index_buffer)
327 skip("Couldn't get index buffer\n");
329 else
331 hr = IDirect3DIndexBuffer9_GetDesc(index_buffer, &index_buffer_description);
332 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
334 if (hr != D3D_OK)
336 skip("Couldn't get index buffer description\n");
338 else
340 ok(index_buffer_description.Format == D3DFMT_INDEX16, "Test %s, result %x, expected %x (D3DFMT_INDEX16)\n",
341 name, index_buffer_description.Format, D3DFMT_INDEX16);
342 ok(index_buffer_description.Type == D3DRTYPE_INDEXBUFFER, "Test %s, result %x, expected %x (D3DRTYPE_INDEXBUFFER)\n",
343 name, index_buffer_description.Type, D3DRTYPE_INDEXBUFFER);
344 ok(index_buffer_description.Usage == 0, "Test %s, result %#x, expected %#x.\n",
345 name, index_buffer_description.Usage, 0);
346 ok(index_buffer_description.Pool == D3DPOOL_MANAGED, "Test %s, result %x, expected %x (D3DPOOL_MANAGED)\n",
347 name, index_buffer_description.Pool, D3DPOOL_MANAGED);
348 expected = number_of_faces * sizeof(WORD) * 3;
349 ok(index_buffer_description.Size == expected, "Test %s, result %x, expected %x\n",
350 name, index_buffer_description.Size, expected);
353 /* specify offset and size to avoid potential overruns */
354 hr = IDirect3DIndexBuffer9_Lock(index_buffer, 0, number_of_faces * sizeof(WORD) * 3,
355 (void **)&faces, D3DLOCK_DISCARD);
356 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
358 if (hr != D3D_OK)
360 skip("Couldn't lock index buffer\n");
362 else
364 for (i = 0; i < number_of_faces; i++)
366 ok(compare_face(faces[i], mesh->faces[i]),
367 "Test %s, face %d, result (%u, %u, %u), expected (%u, %u, %u)\n", name, i,
368 faces[i][0], faces[i][1], faces[i][2],
369 mesh->faces[i][0], mesh->faces[i][1], mesh->faces[i][2]);
372 IDirect3DIndexBuffer9_Unlock(index_buffer);
375 IDirect3DIndexBuffer9_Release(index_buffer);
379 static void D3DXBoundProbeTest(void)
381 BOOL result;
382 D3DXVECTOR3 bottom_point, center, top_point, raydirection, rayposition;
383 FLOAT radius;
385 /*____________Test the Box case___________________________*/
386 bottom_point.x = -3.0f; bottom_point.y = -2.0f; bottom_point.z = -1.0f;
387 top_point.x = 7.0f; top_point.y = 8.0f; top_point.z = 9.0f;
389 raydirection.x = -4.0f; raydirection.y = -5.0f; raydirection.z = -6.0f;
390 rayposition.x = 5.0f; rayposition.y = 5.0f; rayposition.z = 11.0f;
391 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection);
392 ok(result == TRUE, "expected TRUE, received FALSE\n");
394 raydirection.x = 4.0f; raydirection.y = 5.0f; raydirection.z = 6.0f;
395 rayposition.x = 5.0f; rayposition.y = 5.0f; rayposition.z = 11.0f;
396 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection);
397 ok(result == FALSE, "expected FALSE, received TRUE\n");
399 rayposition.x = -4.0f; rayposition.y = 1.0f; rayposition.z = -2.0f;
400 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection);
401 ok(result == TRUE, "expected TRUE, received FALSE\n");
403 bottom_point.x = 1.0f; bottom_point.y = 0.0f; bottom_point.z = 0.0f;
404 top_point.x = 1.0f; top_point.y = 0.0f; top_point.z = 0.0f;
405 rayposition.x = 0.0f; rayposition.y = 1.0f; rayposition.z = 0.0f;
406 raydirection.x = 0.0f; raydirection.y = 3.0f; raydirection.z = 0.0f;
407 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection);
408 ok(result == FALSE, "expected FALSE, received TRUE\n");
410 bottom_point.x = 1.0f; bottom_point.y = 2.0f; bottom_point.z = 3.0f;
411 top_point.x = 10.0f; top_point.y = 15.0f; top_point.z = 20.0f;
413 raydirection.x = 7.0f; raydirection.y = 8.0f; raydirection.z = 9.0f;
414 rayposition.x = 3.0f; rayposition.y = 7.0f; rayposition.z = -6.0f;
415 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection);
416 ok(result == TRUE, "expected TRUE, received FALSE\n");
418 bottom_point.x = 0.0f; bottom_point.y = 0.0f; bottom_point.z = 0.0f;
419 top_point.x = 1.0f; top_point.y = 1.0f; top_point.z = 1.0f;
421 raydirection.x = 0.0f; raydirection.y = 1.0f; raydirection.z = .0f;
422 rayposition.x = -3.0f; rayposition.y = 0.0f; rayposition.z = 0.0f;
423 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection);
424 ok(result == FALSE, "expected FALSE, received TRUE\n");
426 raydirection.x = 1.0f; raydirection.y = 0.0f; raydirection.z = .0f;
427 rayposition.x = -3.0f; rayposition.y = 0.0f; rayposition.z = 0.0f;
428 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection);
429 ok(result == TRUE, "expected TRUE, received FALSE\n");
431 /*____________Test the Sphere case________________________*/
432 radius = sqrt(77.0f);
433 center.x = 1.0f; center.y = 2.0f; center.z = 3.0f;
434 raydirection.x = 2.0f; raydirection.y = -4.0f; raydirection.z = 2.0f;
436 rayposition.x = 5.0f; rayposition.y = 5.0f; rayposition.z = 9.0f;
437 result = D3DXSphereBoundProbe(&center, radius, &rayposition, &raydirection);
438 ok(result == TRUE, "expected TRUE, received FALSE\n");
440 rayposition.x = 45.0f; rayposition.y = -75.0f; rayposition.z = 49.0f;
441 result = D3DXSphereBoundProbe(&center, radius, &rayposition, &raydirection);
442 ok(result == FALSE, "expected FALSE, received TRUE\n");
444 rayposition.x = 5.0f; rayposition.y = 11.0f; rayposition.z = 9.0f;
445 result = D3DXSphereBoundProbe(&center, radius, &rayposition, &raydirection);
446 ok(result == FALSE, "expected FALSE, received TRUE\n");
449 static void D3DXComputeBoundingBoxTest(void)
451 D3DXVECTOR3 exp_max, exp_min, got_max, got_min, vertex[5];
452 HRESULT hr;
454 vertex[0].x = 1.0f; vertex[0].y = 1.0f; vertex[0].z = 1.0f;
455 vertex[1].x = 1.0f; vertex[1].y = 1.0f; vertex[1].z = 1.0f;
456 vertex[2].x = 1.0f; vertex[2].y = 1.0f; vertex[2].z = 1.0f;
457 vertex[3].x = 1.0f; vertex[3].y = 1.0f; vertex[3].z = 1.0f;
458 vertex[4].x = 9.0f; vertex[4].y = 9.0f; vertex[4].z = 9.0f;
460 exp_min.x = 1.0f; exp_min.y = 1.0f; exp_min.z = 1.0f;
461 exp_max.x = 9.0f; exp_max.y = 9.0f; exp_max.z = 9.0f;
463 hr = D3DXComputeBoundingBox(&vertex[3],2,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_min,&got_max);
465 ok( hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
466 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);
467 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);
469 /*________________________*/
471 vertex[0].x = 2.0f; vertex[0].y = 5.9f; vertex[0].z = -1.2f;
472 vertex[1].x = -1.87f; vertex[1].y = 7.9f; vertex[1].z = 7.4f;
473 vertex[2].x = 7.43f; vertex[2].y = -0.9f; vertex[2].z = 11.9f;
474 vertex[3].x = -6.92f; vertex[3].y = 6.3f; vertex[3].z = -3.8f;
475 vertex[4].x = 11.4f; vertex[4].y = -8.1f; vertex[4].z = 4.5f;
477 exp_min.x = -6.92f; exp_min.y = -8.1f; exp_min.z = -3.80f;
478 exp_max.x = 11.4f; exp_max.y = 7.90f; exp_max.z = 11.9f;
480 hr = D3DXComputeBoundingBox(&vertex[0],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_min,&got_max);
482 ok( hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
483 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);
484 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);
486 /*________________________*/
488 vertex[0].x = 2.0f; vertex[0].y = 5.9f; vertex[0].z = -1.2f;
489 vertex[1].x = -1.87f; vertex[1].y = 7.9f; vertex[1].z = 7.4f;
490 vertex[2].x = 7.43f; vertex[2].y = -0.9f; vertex[2].z = 11.9f;
491 vertex[3].x = -6.92f; vertex[3].y = 6.3f; vertex[3].z = -3.8f;
492 vertex[4].x = 11.4f; vertex[4].y = -8.1f; vertex[4].z = 4.5f;
494 exp_min.x = -6.92f; exp_min.y = -0.9f; exp_min.z = -3.8f;
495 exp_max.x = 7.43f; exp_max.y = 7.90f; exp_max.z = 11.9f;
497 hr = D3DXComputeBoundingBox(&vertex[0],4,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_min,&got_max);
499 ok( hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
500 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);
501 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);
503 /*________________________*/
504 hr = D3DXComputeBoundingBox(NULL,5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_min,&got_max);
505 ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
507 /*________________________*/
508 hr = D3DXComputeBoundingBox(&vertex[3],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),NULL,&got_max);
509 ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
511 /*________________________*/
512 hr = D3DXComputeBoundingBox(&vertex[3],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_min,NULL);
513 ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
516 static void D3DXComputeBoundingSphereTest(void)
518 D3DXVECTOR3 exp_cen, got_cen, vertex[5];
519 FLOAT exp_rad, got_rad;
520 HRESULT hr;
522 vertex[0].x = 1.0f; vertex[0].y = 1.0f; vertex[0].z = 1.0f;
523 vertex[1].x = 1.0f; vertex[1].y = 1.0f; vertex[1].z = 1.0f;
524 vertex[2].x = 1.0f; vertex[2].y = 1.0f; vertex[2].z = 1.0f;
525 vertex[3].x = 1.0f; vertex[3].y = 1.0f; vertex[3].z = 1.0f;
526 vertex[4].x = 9.0f; vertex[4].y = 9.0f; vertex[4].z = 9.0f;
528 exp_rad = 6.928203f;
529 exp_cen.x = 5.0; exp_cen.y = 5.0; exp_cen.z = 5.0;
531 hr = D3DXComputeBoundingSphere(&vertex[3],2,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_cen,&got_rad);
533 ok( hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
534 ok( compare(exp_rad, got_rad), "Expected radius: %f, got radius: %f\n", exp_rad, got_rad);
535 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);
537 /*________________________*/
539 vertex[0].x = 2.0f; vertex[0].y = 5.9f; vertex[0].z = -1.2f;
540 vertex[1].x = -1.87f; vertex[1].y = 7.9f; vertex[1].z = 7.4f;
541 vertex[2].x = 7.43f; vertex[2].y = -0.9f; vertex[2].z = 11.9f;
542 vertex[3].x = -6.92f; vertex[3].y = 6.3f; vertex[3].z = -3.8f;
543 vertex[4].x = 11.4f; vertex[4].y = -8.1f; vertex[4].z = 4.5f;
545 exp_rad = 13.707883f;
546 exp_cen.x = 2.408f; exp_cen.y = 2.22f; exp_cen.z = 3.76f;
548 hr = D3DXComputeBoundingSphere(&vertex[0],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_cen,&got_rad);
550 ok( hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
551 ok( compare(exp_rad, got_rad), "Expected radius: %f, got radius: %f\n", exp_rad, got_rad);
552 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);
554 /*________________________*/
555 hr = D3DXComputeBoundingSphere(NULL,5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_cen,&got_rad);
556 ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
558 /*________________________*/
559 hr = D3DXComputeBoundingSphere(&vertex[3],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),NULL,&got_rad);
560 ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
562 /*________________________*/
563 hr = D3DXComputeBoundingSphere(&vertex[3],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_cen,NULL);
564 ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
567 static void print_elements(const D3DVERTEXELEMENT9 *elements)
569 D3DVERTEXELEMENT9 last = D3DDECL_END();
570 const D3DVERTEXELEMENT9 *ptr = elements;
571 int count = 0;
573 while (memcmp(ptr, &last, sizeof(D3DVERTEXELEMENT9)))
575 trace(
576 "[Element %d] Stream = %d, Offset = %d, Type = %d, Method = %d, Usage = %d, UsageIndex = %d\n",
577 count, ptr->Stream, ptr->Offset, ptr->Type, ptr->Method, ptr->Usage, ptr->UsageIndex);
578 ptr++;
579 count++;
583 static void compare_elements(const D3DVERTEXELEMENT9 *elements, const D3DVERTEXELEMENT9 *expected_elements,
584 unsigned int line, unsigned int test_id)
586 D3DVERTEXELEMENT9 last = D3DDECL_END();
587 unsigned int i;
589 for (i = 0; i < MAX_FVF_DECL_SIZE; i++)
591 int end1 = memcmp(&elements[i], &last, sizeof(last));
592 int end2 = memcmp(&expected_elements[i], &last, sizeof(last));
593 int status;
595 if (!end1 && !end2) break;
597 status = !end1 ^ !end2;
598 ok(!status, "Line %u, test %u: Mismatch in size, test declaration is %s than expected.\n",
599 line, test_id, end1 ? "shorter" : "longer");
600 if (status)
602 print_elements(elements);
603 break;
606 status = memcmp(&elements[i], &expected_elements[i], sizeof(D3DVERTEXELEMENT9));
607 ok(!status, "Line %u, test %u: Mismatch in element %u.\n", line, test_id, i);
608 if (status)
610 print_elements(elements);
611 break;
616 static void test_fvf_to_decl(DWORD test_fvf, const D3DVERTEXELEMENT9 expected_elements[],
617 HRESULT expected_hr, unsigned int line, unsigned int test_id)
619 HRESULT hr;
620 D3DVERTEXELEMENT9 decl[MAX_FVF_DECL_SIZE];
622 hr = D3DXDeclaratorFromFVF(test_fvf, decl);
623 ok(hr == expected_hr,
624 "Line %u, test %u: D3DXDeclaratorFromFVF returned %#x, expected %#x.\n",
625 line, test_id, hr, expected_hr);
626 if (SUCCEEDED(hr)) compare_elements(decl, expected_elements, line, test_id);
629 static void test_decl_to_fvf(const D3DVERTEXELEMENT9 *decl, DWORD expected_fvf,
630 HRESULT expected_hr, unsigned int line, unsigned int test_id)
632 HRESULT hr;
633 DWORD result_fvf = 0xdeadbeef;
635 hr = D3DXFVFFromDeclarator(decl, &result_fvf);
636 ok(hr == expected_hr,
637 "Line %u, test %u: D3DXFVFFromDeclarator returned %#x, expected %#x.\n",
638 line, test_id, hr, expected_hr);
639 if (SUCCEEDED(hr))
641 ok(expected_fvf == result_fvf, "Line %u, test %u: Got FVF %#x, expected %#x.\n",
642 line, test_id, result_fvf, expected_fvf);
646 static void test_fvf_decl_conversion(void)
648 static const struct
650 D3DVERTEXELEMENT9 decl[MAXD3DDECLLENGTH + 1];
651 DWORD fvf;
653 test_data[] =
656 D3DDECL_END(),
657 }, 0},
659 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
660 D3DDECL_END(),
661 }, D3DFVF_XYZ},
663 {0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITIONT, 0},
664 D3DDECL_END(),
665 }, D3DFVF_XYZRHW},
667 {0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITIONT, 0},
668 D3DDECL_END(),
669 }, D3DFVF_XYZRHW},
671 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
672 {0, 12, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
673 D3DDECL_END(),
674 }, D3DFVF_XYZB1},
676 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
677 {0, 12, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
678 D3DDECL_END(),
679 }, D3DFVF_XYZB1 | D3DFVF_LASTBETA_UBYTE4},
681 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
682 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
683 D3DDECL_END(),
684 }, D3DFVF_XYZB1 | D3DFVF_LASTBETA_D3DCOLOR},
686 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
687 {0, 12, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
688 D3DDECL_END(),
689 }, D3DFVF_XYZB2},
691 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
692 {0, 12, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
693 {0, 16, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
694 D3DDECL_END(),
695 }, D3DFVF_XYZB2 | D3DFVF_LASTBETA_UBYTE4},
697 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
698 {0, 12, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
699 {0, 16, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
700 D3DDECL_END(),
701 }, D3DFVF_XYZB2 | D3DFVF_LASTBETA_D3DCOLOR},
703 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
704 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
705 D3DDECL_END(),
706 }, D3DFVF_XYZB3},
708 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
709 {0, 12, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
710 {0, 20, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
711 D3DDECL_END(),
712 }, D3DFVF_XYZB3 | D3DFVF_LASTBETA_UBYTE4},
714 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
715 {0, 12, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
716 {0, 20, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
717 D3DDECL_END(),
718 }, D3DFVF_XYZB3 | D3DFVF_LASTBETA_D3DCOLOR},
720 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
721 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
722 D3DDECL_END(),
723 }, D3DFVF_XYZB4},
725 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
726 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
727 {0, 24, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
728 D3DDECL_END(),
729 }, D3DFVF_XYZB4 | D3DFVF_LASTBETA_UBYTE4},
731 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
732 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
733 {0, 24, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
734 D3DDECL_END(),
735 }, D3DFVF_XYZB4 | D3DFVF_LASTBETA_D3DCOLOR},
737 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
738 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
739 {0, 28, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
740 D3DDECL_END(),
741 }, D3DFVF_XYZB5 | D3DFVF_LASTBETA_UBYTE4},
743 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
744 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
745 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
746 D3DDECL_END(),
747 }, D3DFVF_XYZB5 | D3DFVF_LASTBETA_D3DCOLOR},
749 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
750 D3DDECL_END(),
751 }, D3DFVF_NORMAL},
753 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
754 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
755 D3DDECL_END(),
756 }, D3DFVF_NORMAL | D3DFVF_DIFFUSE},
758 {0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_PSIZE, 0},
759 D3DDECL_END(),
760 }, D3DFVF_PSIZE},
762 {0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
763 D3DDECL_END(),
764 }, D3DFVF_DIFFUSE},
766 {0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1},
767 D3DDECL_END(),
768 }, D3DFVF_SPECULAR},
769 /* Make sure textures of different sizes work. */
771 {0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
772 D3DDECL_END(),
773 }, D3DFVF_TEXCOORDSIZE1(0) | D3DFVF_TEX1},
775 {0, 0, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 0},
776 D3DDECL_END(),
777 }, D3DFVF_TEXCOORDSIZE2(0) | D3DFVF_TEX1},
779 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 0},
780 D3DDECL_END(),
781 }, D3DFVF_TEXCOORDSIZE3(0) | D3DFVF_TEX1},
783 {0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 0},
784 D3DDECL_END(),
785 }, D3DFVF_TEXCOORDSIZE4(0) | D3DFVF_TEX1},
786 /* Make sure the TEXCOORD index works correctly - try several textures. */
788 {0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
789 {0, 4, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 1},
790 {0, 16, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 2},
791 {0, 24, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 3},
792 D3DDECL_END(),
793 }, D3DFVF_TEX4 | D3DFVF_TEXCOORDSIZE1(0) | D3DFVF_TEXCOORDSIZE3(1)
794 | D3DFVF_TEXCOORDSIZE2(2) | D3DFVF_TEXCOORDSIZE4(3)},
795 /* Now try some combination tests. */
797 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
798 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
799 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
800 {0, 32, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1},
801 {0, 36, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 0},
802 {0, 44, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 1},
803 D3DDECL_END(),
804 }, D3DFVF_XYZB4 | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_TEX2
805 | D3DFVF_TEXCOORDSIZE2(0) | D3DFVF_TEXCOORDSIZE3(1)},
807 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
808 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
809 {0, 24, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_PSIZE, 0},
810 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1},
811 {0, 32, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
812 {0, 36, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 1},
813 D3DDECL_END(),
814 }, D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_PSIZE | D3DFVF_SPECULAR | D3DFVF_TEX2
815 | D3DFVF_TEXCOORDSIZE1(0) | D3DFVF_TEXCOORDSIZE4(1)},
817 unsigned int i;
819 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
821 test_decl_to_fvf(test_data[i].decl, test_data[i].fvf, D3D_OK, __LINE__, i);
822 test_fvf_to_decl(test_data[i].fvf, test_data[i].decl, D3D_OK, __LINE__, i);
825 /* Usage indices for position and normal are apparently ignored. */
827 const D3DVERTEXELEMENT9 decl[] =
829 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 1},
830 D3DDECL_END(),
832 test_decl_to_fvf(decl, D3DFVF_XYZ, D3D_OK, __LINE__, 0);
835 const D3DVERTEXELEMENT9 decl[] =
837 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 1},
838 D3DDECL_END(),
840 test_decl_to_fvf(decl, D3DFVF_NORMAL, D3D_OK, __LINE__, 0);
842 /* D3DFVF_LASTBETA_UBYTE4 and D3DFVF_LASTBETA_D3DCOLOR are ignored if
843 * there are no blend matrices. */
845 const D3DVERTEXELEMENT9 decl[] =
847 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
848 D3DDECL_END(),
850 test_fvf_to_decl(D3DFVF_XYZ | D3DFVF_LASTBETA_UBYTE4, decl, D3D_OK, __LINE__, 0);
853 const D3DVERTEXELEMENT9 decl[] =
855 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
856 D3DDECL_END(),
858 test_fvf_to_decl(D3DFVF_XYZ | D3DFVF_LASTBETA_D3DCOLOR, decl, D3D_OK, __LINE__, 0);
860 /* D3DFVF_LASTBETA_UBYTE4 takes precedence over D3DFVF_LASTBETA_D3DCOLOR. */
862 const D3DVERTEXELEMENT9 decl[] =
864 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
865 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
866 {0, 28, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
867 D3DDECL_END(),
869 test_fvf_to_decl(D3DFVF_XYZB5 | D3DFVF_LASTBETA_D3DCOLOR | D3DFVF_LASTBETA_UBYTE4,
870 decl, D3D_OK, __LINE__, 0);
872 /* These are supposed to fail, both ways. */
874 const D3DVERTEXELEMENT9 decl[] =
876 {0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITION, 0},
877 D3DDECL_END(),
879 test_decl_to_fvf(decl, D3DFVF_XYZW, D3DERR_INVALIDCALL, __LINE__, 0);
880 test_fvf_to_decl(D3DFVF_XYZW, decl, D3DERR_INVALIDCALL, __LINE__, 0);
883 const D3DVERTEXELEMENT9 decl[] =
885 {0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITION, 0},
886 {0, 16, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
887 D3DDECL_END(),
889 test_decl_to_fvf(decl, D3DFVF_XYZW | D3DFVF_NORMAL, D3DERR_INVALIDCALL, __LINE__, 0);
890 test_fvf_to_decl(D3DFVF_XYZW | D3DFVF_NORMAL, decl, D3DERR_INVALIDCALL, __LINE__, 0);
893 const D3DVERTEXELEMENT9 decl[] =
895 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
896 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
897 {0, 28, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDINDICES, 0},
898 D3DDECL_END(),
900 test_decl_to_fvf(decl, D3DFVF_XYZB5, D3DERR_INVALIDCALL, __LINE__, 0);
901 test_fvf_to_decl(D3DFVF_XYZB5, decl, D3DERR_INVALIDCALL, __LINE__, 0);
903 /* Test a declaration that can't be converted to an FVF. */
905 const D3DVERTEXELEMENT9 decl[] =
907 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
908 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
909 {0, 24, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_PSIZE, 0},
910 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1},
911 {0, 32, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
912 /* 8 bytes padding */
913 {0, 44, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 1},
914 D3DDECL_END(),
916 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0);
918 /* Elements must be ordered by offset. */
920 const D3DVERTEXELEMENT9 decl[] =
922 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
923 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
924 D3DDECL_END(),
926 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0);
928 /* Basic tests for element order. */
930 const D3DVERTEXELEMENT9 decl[] =
932 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
933 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
934 {0, 16, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
935 D3DDECL_END(),
937 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0);
940 const D3DVERTEXELEMENT9 decl[] =
942 {0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
943 {0, 4, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
944 D3DDECL_END(),
946 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0);
949 const D3DVERTEXELEMENT9 decl[] =
951 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
952 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
953 D3DDECL_END(),
955 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0);
957 /* Textures must be ordered by texcoords. */
959 const D3DVERTEXELEMENT9 decl[] =
961 {0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
962 {0, 4, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 2},
963 {0, 16, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 1},
964 {0, 24, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 3},
965 D3DDECL_END(),
967 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0);
969 /* Duplicate elements are not allowed. */
971 const D3DVERTEXELEMENT9 decl[] =
973 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
974 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
975 {0, 16, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
976 D3DDECL_END(),
978 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0);
980 /* Invalid FVFs cannot be converted to a declarator. */
981 test_fvf_to_decl(0xdeadbeef, NULL, D3DERR_INVALIDCALL, __LINE__, 0);
984 static void D3DXGetFVFVertexSizeTest(void)
986 UINT got;
988 compare_vertex_sizes (D3DFVF_XYZ, 12);
990 compare_vertex_sizes (D3DFVF_XYZB3, 24);
992 compare_vertex_sizes (D3DFVF_XYZB5, 32);
994 compare_vertex_sizes (D3DFVF_XYZ | D3DFVF_NORMAL, 24);
996 compare_vertex_sizes (D3DFVF_XYZ | D3DFVF_DIFFUSE, 16);
998 compare_vertex_sizes (
999 D3DFVF_XYZ |
1000 D3DFVF_TEX1 |
1001 D3DFVF_TEXCOORDSIZE1(0), 16);
1002 compare_vertex_sizes (
1003 D3DFVF_XYZ |
1004 D3DFVF_TEX2 |
1005 D3DFVF_TEXCOORDSIZE1(0) |
1006 D3DFVF_TEXCOORDSIZE1(1), 20);
1008 compare_vertex_sizes (
1009 D3DFVF_XYZ |
1010 D3DFVF_TEX1 |
1011 D3DFVF_TEXCOORDSIZE2(0), 20);
1013 compare_vertex_sizes (
1014 D3DFVF_XYZ |
1015 D3DFVF_TEX2 |
1016 D3DFVF_TEXCOORDSIZE2(0) |
1017 D3DFVF_TEXCOORDSIZE2(1), 28);
1019 compare_vertex_sizes (
1020 D3DFVF_XYZ |
1021 D3DFVF_TEX6 |
1022 D3DFVF_TEXCOORDSIZE2(0) |
1023 D3DFVF_TEXCOORDSIZE2(1) |
1024 D3DFVF_TEXCOORDSIZE2(2) |
1025 D3DFVF_TEXCOORDSIZE2(3) |
1026 D3DFVF_TEXCOORDSIZE2(4) |
1027 D3DFVF_TEXCOORDSIZE2(5), 60);
1029 compare_vertex_sizes (
1030 D3DFVF_XYZ |
1031 D3DFVF_TEX8 |
1032 D3DFVF_TEXCOORDSIZE2(0) |
1033 D3DFVF_TEXCOORDSIZE2(1) |
1034 D3DFVF_TEXCOORDSIZE2(2) |
1035 D3DFVF_TEXCOORDSIZE2(3) |
1036 D3DFVF_TEXCOORDSIZE2(4) |
1037 D3DFVF_TEXCOORDSIZE2(5) |
1038 D3DFVF_TEXCOORDSIZE2(6) |
1039 D3DFVF_TEXCOORDSIZE2(7), 76);
1041 compare_vertex_sizes (
1042 D3DFVF_XYZ |
1043 D3DFVF_TEX1 |
1044 D3DFVF_TEXCOORDSIZE3(0), 24);
1046 compare_vertex_sizes (
1047 D3DFVF_XYZ |
1048 D3DFVF_TEX4 |
1049 D3DFVF_TEXCOORDSIZE3(0) |
1050 D3DFVF_TEXCOORDSIZE3(1) |
1051 D3DFVF_TEXCOORDSIZE3(2) |
1052 D3DFVF_TEXCOORDSIZE3(3), 60);
1054 compare_vertex_sizes (
1055 D3DFVF_XYZ |
1056 D3DFVF_TEX1 |
1057 D3DFVF_TEXCOORDSIZE4(0), 28);
1059 compare_vertex_sizes (
1060 D3DFVF_XYZ |
1061 D3DFVF_TEX2 |
1062 D3DFVF_TEXCOORDSIZE4(0) |
1063 D3DFVF_TEXCOORDSIZE4(1), 44);
1065 compare_vertex_sizes (
1066 D3DFVF_XYZ |
1067 D3DFVF_TEX3 |
1068 D3DFVF_TEXCOORDSIZE4(0) |
1069 D3DFVF_TEXCOORDSIZE4(1) |
1070 D3DFVF_TEXCOORDSIZE4(2), 60);
1072 compare_vertex_sizes (
1073 D3DFVF_XYZB5 |
1074 D3DFVF_NORMAL |
1075 D3DFVF_DIFFUSE |
1076 D3DFVF_SPECULAR |
1077 D3DFVF_TEX8 |
1078 D3DFVF_TEXCOORDSIZE4(0) |
1079 D3DFVF_TEXCOORDSIZE4(1) |
1080 D3DFVF_TEXCOORDSIZE4(2) |
1081 D3DFVF_TEXCOORDSIZE4(3) |
1082 D3DFVF_TEXCOORDSIZE4(4) |
1083 D3DFVF_TEXCOORDSIZE4(5) |
1084 D3DFVF_TEXCOORDSIZE4(6) |
1085 D3DFVF_TEXCOORDSIZE4(7), 180);
1088 static void D3DXIntersectTriTest(void)
1090 BOOL exp_res, got_res;
1091 D3DXVECTOR3 position, ray, vertex[3];
1092 FLOAT exp_dist, got_dist, exp_u, got_u, exp_v, got_v;
1094 vertex[0].x = 1.0f; vertex[0].y = 0.0f; vertex[0].z = 0.0f;
1095 vertex[1].x = 2.0f; vertex[1].y = 0.0f; vertex[1].z = 0.0f;
1096 vertex[2].x = 1.0f; vertex[2].y = 1.0f; vertex[2].z = 0.0f;
1098 position.x = -14.5f; position.y = -23.75f; position.z = -32.0f;
1100 ray.x = 2.0f; ray.y = 3.0f; ray.z = 4.0f;
1102 exp_res = TRUE; exp_u = 0.5f; exp_v = 0.25f; exp_dist = 8.0f;
1104 got_res = D3DXIntersectTri(&vertex[0], &vertex[1], &vertex[2], &position, &ray, &got_u, &got_v, &got_dist);
1105 ok(got_res == exp_res, "Expected result %d, got %d.\n", exp_res, got_res);
1106 ok(compare(exp_u, got_u), "Expected u %f, got %f.\n", exp_u, got_u);
1107 ok(compare(exp_v, got_v), "Expected v %f, got %f.\n", exp_v, got_v);
1108 ok(compare(exp_dist, got_dist), "Expected distance %f, got %f.\n", exp_dist, got_dist);
1110 got_res = D3DXIntersectTri(&vertex[0], &vertex[1], &vertex[2], &position, &ray, NULL, NULL, NULL);
1111 ok(got_res == exp_res, "Expected result %d, got %d.\n", exp_res, got_res);
1113 vertex[2].x = 1.0f; vertex[2].y = 0.0f; vertex[2].z = 0.0f;
1114 vertex[1].x = 2.0f; vertex[1].y = 0.0f; vertex[1].z = 0.0f;
1115 vertex[0].x = 1.0f; vertex[0].y = 1.0f; vertex[0].z = 0.0f;
1117 got_u = got_v = got_dist = 0.0f;
1118 got_res = D3DXIntersectTri(&vertex[0], &vertex[1], &vertex[2], &position, &ray, &got_u, &got_v, &got_dist);
1119 ok(got_res == exp_res, "Expected result %d, got %d.\n", exp_res, got_res);
1120 ok(compare(exp_u, got_u), "Expected u %f, got %f.\n", exp_u, got_u);
1121 ok(compare(exp_v, got_v), "Expected v %f, got %f.\n", exp_v, got_v);
1122 ok(compare(exp_dist, got_dist), "Expected distance %f, got %f.\n", exp_dist, got_dist);
1124 vertex[2].x = 1.0f; vertex[2].y = 0.0f; vertex[2].z = 0.0f;
1125 vertex[1].x = 2.0f; vertex[1].y = 0.0f; vertex[1].z = -0.5f;
1126 vertex[0].x = 1.0f; vertex[0].y = 1.0f; vertex[0].z = -1.0f;
1127 exp_u = 0.375f;
1128 exp_v = 0.5625f;
1129 exp_dist = 7.9375f;
1130 got_u = got_v = got_dist = 0.0f;
1131 got_res = D3DXIntersectTri(&vertex[0], &vertex[1], &vertex[2], &position, &ray, &got_u, &got_v, &got_dist);
1132 ok(got_res == exp_res, "Expected result %d, got %d.\n", exp_res, got_res);
1133 ok(compare(exp_u, got_u), "Expected u %f, got %f.\n", exp_u, got_u);
1134 ok(compare(exp_v, got_v), "Expected v %f, got %f.\n", exp_v, got_v);
1135 ok(compare(exp_dist, got_dist), "Expected distance %f, got %f.\n", exp_dist, got_dist);
1138 /*Only positive ray is taken in account*/
1140 vertex[0].x = 1.0f; vertex[0].y = 0.0f; vertex[0].z = 0.0f;
1141 vertex[1].x = 2.0f; vertex[1].y = 0.0f; vertex[1].z = 0.0f;
1142 vertex[2].x = 1.0f; vertex[2].y = 1.0f; vertex[2].z = 0.0f;
1144 position.x = 17.5f; position.y = 24.25f; position.z = 32.0f;
1146 ray.x = 2.0f; ray.y = 3.0f; ray.z = 4.0f;
1148 exp_res = FALSE;
1150 got_res = D3DXIntersectTri(&vertex[0],&vertex[1],&vertex[2],&position,&ray,&got_u,&got_v,&got_dist);
1151 ok( got_res == exp_res, "Expected result = %d, got %d\n",exp_res,got_res);
1153 got_res = D3DXIntersectTri(&vertex[0], &vertex[1], &vertex[2], &position, &ray, NULL, NULL, NULL);
1154 ok(got_res == exp_res, "Expected result = %d, got %d\n", exp_res, got_res);
1156 /*Intersection between ray and triangle in a same plane is considered as empty*/
1158 vertex[0].x = 4.0f; vertex[0].y = 0.0f; vertex[0].z = 0.0f;
1159 vertex[1].x = 6.0f; vertex[1].y = 0.0f; vertex[1].z = 0.0f;
1160 vertex[2].x = 4.0f; vertex[2].y = 2.0f; vertex[2].z = 0.0f;
1162 position.x = 1.0f; position.y = 1.0f; position.z = 0.0f;
1164 ray.x = 1.0f; ray.y = 0.0f; ray.z = 0.0f;
1166 exp_res = FALSE;
1168 got_res = D3DXIntersectTri(&vertex[0],&vertex[1],&vertex[2],&position,&ray,&got_u,&got_v,&got_dist);
1169 ok( got_res == exp_res, "Expected result = %d, got %d\n",exp_res,got_res);
1171 got_res = D3DXIntersectTri(&vertex[0], &vertex[1], &vertex[2], &position, &ray, NULL, NULL, NULL);
1172 ok(got_res == exp_res, "Expected result = %d, got %d\n", exp_res, got_res);
1175 static void D3DXCreateMeshTest(void)
1177 HRESULT hr;
1178 IDirect3DDevice9 *device, *test_device;
1179 ID3DXMesh *d3dxmesh;
1180 int i, size;
1181 D3DVERTEXELEMENT9 test_decl[MAX_FVF_DECL_SIZE];
1182 DWORD options;
1183 struct mesh mesh;
1184 struct test_context *test_context;
1186 static const D3DVERTEXELEMENT9 decl1[] =
1188 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1189 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
1190 D3DDECL_END(),
1193 static const D3DVERTEXELEMENT9 decl2[] =
1195 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1196 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
1197 {0, 24, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_PSIZE, 0},
1198 {0, 28, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 1},
1199 {0, 32, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
1200 /* 8 bytes padding */
1201 {0, 44, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
1202 D3DDECL_END(),
1205 static const D3DVERTEXELEMENT9 decl3[] =
1207 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1208 {1, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
1209 D3DDECL_END(),
1212 hr = D3DXCreateMesh(0, 0, 0, NULL, NULL, NULL);
1213 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1215 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl1, NULL, &d3dxmesh);
1216 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1218 test_context = new_test_context();
1219 if (!test_context)
1221 skip("Couldn't create test context\n");
1222 return;
1224 device = test_context->device;
1226 hr = D3DXCreateMesh(0, 3, D3DXMESH_MANAGED, decl1, device, &d3dxmesh);
1227 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1229 hr = D3DXCreateMesh(1, 0, D3DXMESH_MANAGED, decl1, device, &d3dxmesh);
1230 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1232 hr = D3DXCreateMesh(1, 3, 0, decl1, device, &d3dxmesh);
1233 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
1235 if (hr == D3D_OK)
1237 d3dxmesh->lpVtbl->Release(d3dxmesh);
1240 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, 0, device, &d3dxmesh);
1241 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1243 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl1, device, NULL);
1244 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1246 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl1, device, &d3dxmesh);
1247 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
1249 if (hr == D3D_OK)
1251 /* device */
1252 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, NULL);
1253 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1255 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, &test_device);
1256 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
1257 ok(test_device == device, "Got result %p, expected %p\n", test_device, device);
1259 if (hr == D3D_OK)
1261 IDirect3DDevice9_Release(device);
1264 /* declaration */
1265 hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, NULL);
1266 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1268 hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, test_decl);
1269 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
1271 if (hr == D3D_OK)
1273 size = ARRAY_SIZE(decl1);
1274 for (i = 0; i < size - 1; i++)
1276 ok(test_decl[i].Stream == decl1[i].Stream, "Returned stream %d, expected %d\n", test_decl[i].Stream, decl1[i].Stream);
1277 ok(test_decl[i].Type == decl1[i].Type, "Returned type %d, expected %d\n", test_decl[i].Type, decl1[i].Type);
1278 ok(test_decl[i].Method == decl1[i].Method, "Returned method %d, expected %d\n", test_decl[i].Method, decl1[i].Method);
1279 ok(test_decl[i].Usage == decl1[i].Usage, "Returned usage %d, expected %d\n", test_decl[i].Usage, decl1[i].Usage);
1280 ok(test_decl[i].UsageIndex == decl1[i].UsageIndex, "Returned usage index %d, expected %d\n", test_decl[i].UsageIndex, decl1[i].UsageIndex);
1281 ok(test_decl[i].Offset == decl1[i].Offset, "Returned offset %d, expected %d\n", test_decl[i].Offset, decl1[i].Offset);
1283 ok(decl1[size-1].Stream == 0xFF, "Returned too long vertex declaration\n"); /* end element */
1286 /* options */
1287 options = d3dxmesh->lpVtbl->GetOptions(d3dxmesh);
1288 ok(options == D3DXMESH_MANAGED, "Got result %x, expected %x (D3DXMESH_MANAGED)\n", options, D3DXMESH_MANAGED);
1290 /* rest */
1291 if (!new_mesh(&mesh, 3, 1))
1293 skip("Couldn't create mesh\n");
1295 else
1297 memset(mesh.vertices, 0, mesh.number_of_vertices * sizeof(*mesh.vertices));
1298 memset(mesh.faces, 0, mesh.number_of_faces * sizeof(*mesh.faces));
1299 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
1301 compare_mesh("createmesh1", d3dxmesh, &mesh);
1303 free_mesh(&mesh);
1306 d3dxmesh->lpVtbl->Release(d3dxmesh);
1309 /* Test a declaration that can't be converted to an FVF. */
1310 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl2, device, &d3dxmesh);
1311 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
1313 if (hr == D3D_OK)
1315 /* device */
1316 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, NULL);
1317 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1319 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, &test_device);
1320 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
1321 ok(test_device == device, "Got result %p, expected %p\n", test_device, device);
1323 if (hr == D3D_OK)
1325 IDirect3DDevice9_Release(device);
1328 /* declaration */
1329 hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, test_decl);
1330 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
1332 if (hr == D3D_OK)
1334 size = ARRAY_SIZE(decl2);
1335 for (i = 0; i < size - 1; i++)
1337 ok(test_decl[i].Stream == decl2[i].Stream, "Returned stream %d, expected %d\n", test_decl[i].Stream, decl2[i].Stream);
1338 ok(test_decl[i].Type == decl2[i].Type, "Returned type %d, expected %d\n", test_decl[i].Type, decl2[i].Type);
1339 ok(test_decl[i].Method == decl2[i].Method, "Returned method %d, expected %d\n", test_decl[i].Method, decl2[i].Method);
1340 ok(test_decl[i].Usage == decl2[i].Usage, "Returned usage %d, expected %d\n", test_decl[i].Usage, decl2[i].Usage);
1341 ok(test_decl[i].UsageIndex == decl2[i].UsageIndex, "Returned usage index %d, expected %d\n", test_decl[i].UsageIndex, decl2[i].UsageIndex);
1342 ok(test_decl[i].Offset == decl2[i].Offset, "Returned offset %d, expected %d\n", test_decl[i].Offset, decl2[i].Offset);
1344 ok(decl2[size-1].Stream == 0xFF, "Returned too long vertex declaration\n"); /* end element */
1347 /* options */
1348 options = d3dxmesh->lpVtbl->GetOptions(d3dxmesh);
1349 ok(options == D3DXMESH_MANAGED, "Got result %x, expected %x (D3DXMESH_MANAGED)\n", options, D3DXMESH_MANAGED);
1351 /* rest */
1352 if (!new_mesh(&mesh, 3, 1))
1354 skip("Couldn't create mesh\n");
1356 else
1358 memset(mesh.vertices, 0, mesh.number_of_vertices * sizeof(*mesh.vertices));
1359 memset(mesh.faces, 0, mesh.number_of_faces * sizeof(*mesh.faces));
1360 mesh.fvf = 0;
1361 mesh.vertex_size = 60;
1363 compare_mesh("createmesh2", d3dxmesh, &mesh);
1365 free_mesh(&mesh);
1368 mesh.vertex_size = d3dxmesh->lpVtbl->GetNumBytesPerVertex(d3dxmesh);
1369 ok(mesh.vertex_size == 60, "Got vertex size %u, expected %u\n", mesh.vertex_size, 60);
1371 d3dxmesh->lpVtbl->Release(d3dxmesh);
1374 /* Test a declaration with multiple streams. */
1375 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl3, device, &d3dxmesh);
1376 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1378 free_test_context(test_context);
1381 static void D3DXCreateMeshFVFTest(void)
1383 HRESULT hr;
1384 IDirect3DDevice9 *device, *test_device;
1385 ID3DXMesh *d3dxmesh;
1386 int i, size;
1387 D3DVERTEXELEMENT9 test_decl[MAX_FVF_DECL_SIZE];
1388 DWORD options;
1389 struct mesh mesh;
1390 struct test_context *test_context;
1392 static const D3DVERTEXELEMENT9 decl[] =
1394 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1395 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
1396 D3DDECL_END(),
1399 hr = D3DXCreateMeshFVF(0, 0, 0, 0, NULL, NULL);
1400 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1402 hr = D3DXCreateMeshFVF(1, 3, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, NULL, &d3dxmesh);
1403 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1405 test_context = new_test_context();
1406 if (!test_context)
1408 skip("Couldn't create test context\n");
1409 return;
1411 device = test_context->device;
1413 hr = D3DXCreateMeshFVF(0, 3, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, device, &d3dxmesh);
1414 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1416 hr = D3DXCreateMeshFVF(1, 0, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, device, &d3dxmesh);
1417 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1419 hr = D3DXCreateMeshFVF(1, 3, 0, D3DFVF_XYZ | D3DFVF_NORMAL, device, &d3dxmesh);
1420 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
1422 if (hr == D3D_OK)
1424 d3dxmesh->lpVtbl->Release(d3dxmesh);
1427 hr = D3DXCreateMeshFVF(1, 3, D3DXMESH_MANAGED, 0xdeadbeef, device, &d3dxmesh);
1428 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1430 hr = D3DXCreateMeshFVF(1, 3, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, device, NULL);
1431 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1433 hr = D3DXCreateMeshFVF(1, 3, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, device, &d3dxmesh);
1434 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
1436 if (hr == D3D_OK)
1438 /* device */
1439 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, NULL);
1440 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1442 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, &test_device);
1443 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
1444 ok(test_device == device, "Got result %p, expected %p\n", test_device, device);
1446 if (hr == D3D_OK)
1448 IDirect3DDevice9_Release(device);
1451 /* declaration */
1452 hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, NULL);
1453 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1455 hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, test_decl);
1456 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
1458 if (hr == D3D_OK)
1460 size = ARRAY_SIZE(decl);
1461 for (i = 0; i < size - 1; i++)
1463 ok(test_decl[i].Stream == decl[i].Stream, "Returned stream %d, expected %d\n", test_decl[i].Stream, decl[i].Stream);
1464 ok(test_decl[i].Type == decl[i].Type, "Returned type %d, expected %d\n", test_decl[i].Type, decl[i].Type);
1465 ok(test_decl[i].Method == decl[i].Method, "Returned method %d, expected %d\n", test_decl[i].Method, decl[i].Method);
1466 ok(test_decl[i].Usage == decl[i].Usage, "Returned usage %d, expected %d\n", test_decl[i].Usage, decl[i].Usage);
1467 ok(test_decl[i].UsageIndex == decl[i].UsageIndex, "Returned usage index %d, expected %d\n",
1468 test_decl[i].UsageIndex, decl[i].UsageIndex);
1469 ok(test_decl[i].Offset == decl[i].Offset, "Returned offset %d, expected %d\n", test_decl[i].Offset, decl[i].Offset);
1471 ok(decl[size-1].Stream == 0xFF, "Returned too long vertex declaration\n"); /* end element */
1474 /* options */
1475 options = d3dxmesh->lpVtbl->GetOptions(d3dxmesh);
1476 ok(options == D3DXMESH_MANAGED, "Got result %x, expected %x (D3DXMESH_MANAGED)\n", options, D3DXMESH_MANAGED);
1478 /* rest */
1479 if (!new_mesh(&mesh, 3, 1))
1481 skip("Couldn't create mesh\n");
1483 else
1485 memset(mesh.vertices, 0, mesh.number_of_vertices * sizeof(*mesh.vertices));
1486 memset(mesh.faces, 0, mesh.number_of_faces * sizeof(*mesh.faces));
1487 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
1489 compare_mesh("createmeshfvf", d3dxmesh, &mesh);
1491 free_mesh(&mesh);
1494 d3dxmesh->lpVtbl->Release(d3dxmesh);
1497 free_test_context(test_context);
1500 #define check_vertex_buffer(mesh, vertices, num_vertices, fvf) \
1501 check_vertex_buffer_(__LINE__, mesh, vertices, num_vertices, fvf)
1502 static void check_vertex_buffer_(int line, ID3DXMesh *mesh, const void *vertices, DWORD num_vertices, DWORD fvf)
1504 DWORD mesh_num_vertices = mesh->lpVtbl->GetNumVertices(mesh);
1505 DWORD mesh_fvf = mesh->lpVtbl->GetFVF(mesh);
1506 const void *mesh_vertices;
1507 HRESULT hr;
1509 ok_(__FILE__,line)(fvf == mesh_fvf, "expected FVF %x, got %x\n", fvf, mesh_fvf);
1510 ok_(__FILE__,line)(num_vertices == mesh_num_vertices,
1511 "Expected %u vertices, got %u\n", num_vertices, mesh_num_vertices);
1513 hr = mesh->lpVtbl->LockVertexBuffer(mesh, D3DLOCK_READONLY, (void**)&mesh_vertices);
1514 ok_(__FILE__,line)(hr == D3D_OK, "LockVertexBuffer returned %x, expected %x (D3D_OK)\n", hr, D3D_OK);
1515 if (FAILED(hr))
1516 return;
1518 if (mesh_fvf == fvf) {
1519 DWORD vertex_size = D3DXGetFVFVertexSize(fvf), i;
1521 for (i = 0; i < min(num_vertices, mesh_num_vertices); i++)
1523 const FLOAT *exp_float = vertices;
1524 const FLOAT *got_float = mesh_vertices;
1525 DWORD texcount;
1526 DWORD pos_dim = 0;
1527 int j;
1528 BOOL last_beta_dword = FALSE;
1529 char prefix[128];
1531 switch (fvf & D3DFVF_POSITION_MASK) {
1532 case D3DFVF_XYZ: pos_dim = 3; break;
1533 case D3DFVF_XYZRHW: pos_dim = 4; break;
1534 case D3DFVF_XYZB1:
1535 case D3DFVF_XYZB2:
1536 case D3DFVF_XYZB3:
1537 case D3DFVF_XYZB4:
1538 case D3DFVF_XYZB5:
1539 pos_dim = (fvf & D3DFVF_POSITION_MASK) - D3DFVF_XYZB1 + 1;
1540 if (fvf & (D3DFVF_LASTBETA_UBYTE4 | D3DFVF_LASTBETA_D3DCOLOR))
1542 pos_dim--;
1543 last_beta_dword = TRUE;
1545 break;
1546 case D3DFVF_XYZW: pos_dim = 4; break;
1548 sprintf(prefix, "vertex[%u] position, ", i);
1549 check_floats_(line, prefix, got_float, exp_float, pos_dim);
1550 exp_float += pos_dim;
1551 got_float += pos_dim;
1553 if (last_beta_dword) {
1554 ok_(__FILE__,line)(*(DWORD*)exp_float == *(DWORD*)got_float,
1555 "Vertex[%u]: Expected last beta %08x, got %08x\n", i, *(DWORD*)exp_float, *(DWORD*)got_float);
1556 exp_float++;
1557 got_float++;
1560 if (fvf & D3DFVF_NORMAL) {
1561 sprintf(prefix, "vertex[%u] normal, ", i);
1562 check_floats_(line, prefix, got_float, exp_float, 3);
1563 exp_float += 3;
1564 got_float += 3;
1566 if (fvf & D3DFVF_PSIZE) {
1567 ok_(__FILE__,line)(compare(*exp_float, *got_float),
1568 "Vertex[%u]: Expected psize %g, got %g\n", i, *exp_float, *got_float);
1569 exp_float++;
1570 got_float++;
1572 if (fvf & D3DFVF_DIFFUSE) {
1573 ok_(__FILE__,line)(*(DWORD*)exp_float == *(DWORD*)got_float,
1574 "Vertex[%u]: Expected diffuse %08x, got %08x\n", i, *(DWORD*)exp_float, *(DWORD*)got_float);
1575 exp_float++;
1576 got_float++;
1578 if (fvf & D3DFVF_SPECULAR) {
1579 ok_(__FILE__,line)(*(DWORD*)exp_float == *(DWORD*)got_float,
1580 "Vertex[%u]: Expected specular %08x, got %08x\n", i, *(DWORD*)exp_float, *(DWORD*)got_float);
1581 exp_float++;
1582 got_float++;
1585 texcount = (fvf & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
1586 for (j = 0; j < texcount; j++) {
1587 DWORD dim = (((fvf >> (16 + 2 * j)) + 1) & 0x03) + 1;
1588 sprintf(prefix, "vertex[%u] texture, ", i);
1589 check_floats_(line, prefix, got_float, exp_float, dim);
1590 exp_float += dim;
1591 got_float += dim;
1594 vertices = (BYTE*)vertices + vertex_size;
1595 mesh_vertices = (BYTE*)mesh_vertices + vertex_size;
1599 mesh->lpVtbl->UnlockVertexBuffer(mesh);
1602 #define check_index_buffer(mesh, indices, num_indices, index_size) \
1603 check_index_buffer_(__LINE__, mesh, indices, num_indices, index_size)
1604 static void check_index_buffer_(int line, ID3DXMesh *mesh, const void *indices, DWORD num_indices, DWORD index_size)
1606 DWORD mesh_index_size = (mesh->lpVtbl->GetOptions(mesh) & D3DXMESH_32BIT) ? 4 : 2;
1607 DWORD mesh_num_indices = mesh->lpVtbl->GetNumFaces(mesh) * 3;
1608 const void *mesh_indices;
1609 HRESULT hr;
1610 DWORD i;
1612 ok_(__FILE__,line)(index_size == mesh_index_size,
1613 "Expected index size %u, got %u\n", index_size, mesh_index_size);
1614 ok_(__FILE__,line)(num_indices == mesh_num_indices,
1615 "Expected %u indices, got %u\n", num_indices, mesh_num_indices);
1617 hr = mesh->lpVtbl->LockIndexBuffer(mesh, D3DLOCK_READONLY, (void**)&mesh_indices);
1618 ok_(__FILE__,line)(hr == D3D_OK, "LockIndexBuffer returned %x, expected %x (D3D_OK)\n", hr, D3D_OK);
1619 if (FAILED(hr))
1620 return;
1622 if (mesh_index_size == index_size) {
1623 for (i = 0; i < min(num_indices, mesh_num_indices); i++)
1625 if (index_size == 4)
1626 ok_(__FILE__,line)(*(DWORD*)indices == *(DWORD*)mesh_indices,
1627 "Index[%u]: expected %u, got %u\n", i, *(DWORD*)indices, *(DWORD*)mesh_indices);
1628 else
1629 ok_(__FILE__,line)(*(WORD*)indices == *(WORD*)mesh_indices,
1630 "Index[%u]: expected %u, got %u\n", i, *(WORD*)indices, *(WORD*)mesh_indices);
1631 indices = (BYTE*)indices + index_size;
1632 mesh_indices = (BYTE*)mesh_indices + index_size;
1635 mesh->lpVtbl->UnlockIndexBuffer(mesh);
1638 #define check_matrix(got, expected) check_matrix_(__LINE__, got, expected)
1639 static void check_matrix_(int line, const D3DXMATRIX *got, const D3DXMATRIX *expected)
1641 int i, j;
1642 for (i = 0; i < 4; i++) {
1643 for (j = 0; j < 4; j++) {
1644 ok_(__FILE__,line)(compare(U(*expected).m[i][j], U(*got).m[i][j]),
1645 "matrix[%u][%u]: expected %g, got %g\n",
1646 i, j, U(*expected).m[i][j], U(*got).m[i][j]);
1651 static void check_colorvalue_(int line, const char *prefix, const D3DCOLORVALUE got, const D3DCOLORVALUE expected)
1653 ok_(__FILE__,line)(expected.r == got.r && expected.g == got.g && expected.b == got.b && expected.a == got.a,
1654 "%sExpected (%g, %g, %g, %g), got (%g, %g, %g, %g)\n", prefix,
1655 expected.r, expected.g, expected.b, expected.a, got.r, got.g, got.b, got.a);
1658 #define check_materials(got, got_count, expected, expected_count) \
1659 check_materials_(__LINE__, got, got_count, expected, expected_count)
1660 static void check_materials_(int line, const D3DXMATERIAL *got, DWORD got_count, const D3DXMATERIAL *expected, DWORD expected_count)
1662 int i;
1663 ok_(__FILE__,line)(expected_count == got_count, "Expected %u materials, got %u\n", expected_count, got_count);
1664 if (!expected) {
1665 ok_(__FILE__,line)(got == NULL, "Expected NULL material ptr, got %p\n", got);
1666 return;
1668 for (i = 0; i < min(expected_count, got_count); i++)
1670 if (!expected[i].pTextureFilename)
1671 ok_(__FILE__,line)(got[i].pTextureFilename == NULL,
1672 "Expected NULL pTextureFilename, got %p\n", got[i].pTextureFilename);
1673 else
1674 ok_(__FILE__,line)(!strcmp(expected[i].pTextureFilename, got[i].pTextureFilename),
1675 "Expected '%s' for pTextureFilename, got '%s'\n", expected[i].pTextureFilename, got[i].pTextureFilename);
1676 check_colorvalue_(line, "Diffuse: ", got[i].MatD3D.Diffuse, expected[i].MatD3D.Diffuse);
1677 check_colorvalue_(line, "Ambient: ", got[i].MatD3D.Ambient, expected[i].MatD3D.Ambient);
1678 check_colorvalue_(line, "Specular: ", got[i].MatD3D.Specular, expected[i].MatD3D.Specular);
1679 check_colorvalue_(line, "Emissive: ", got[i].MatD3D.Emissive, expected[i].MatD3D.Emissive);
1680 ok_(__FILE__,line)(expected[i].MatD3D.Power == got[i].MatD3D.Power,
1681 "Power: Expected %g, got %g\n", expected[i].MatD3D.Power, got[i].MatD3D.Power);
1685 #define check_generated_adjacency(mesh, got, epsilon) check_generated_adjacency_(__LINE__, mesh, got, epsilon)
1686 static void check_generated_adjacency_(int line, ID3DXMesh *mesh, const DWORD *got, FLOAT epsilon)
1688 DWORD *expected;
1689 DWORD num_faces = mesh->lpVtbl->GetNumFaces(mesh);
1690 HRESULT hr;
1692 expected = HeapAlloc(GetProcessHeap(), 0, num_faces * sizeof(DWORD) * 3);
1693 if (!expected) {
1694 skip_(__FILE__, line)("Out of memory\n");
1695 return;
1697 hr = mesh->lpVtbl->GenerateAdjacency(mesh, epsilon, expected);
1698 ok_(__FILE__, line)(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
1699 if (SUCCEEDED(hr))
1701 int i;
1702 for (i = 0; i < num_faces; i++)
1704 ok_(__FILE__, line)(expected[i * 3] == got[i * 3] &&
1705 expected[i * 3 + 1] == got[i * 3 + 1] &&
1706 expected[i * 3 + 2] == got[i * 3 + 2],
1707 "Face %u adjacencies: Expected (%u, %u, %u), got (%u, %u, %u)\n", i,
1708 expected[i * 3], expected[i * 3 + 1], expected[i * 3 + 2],
1709 got[i * 3], got[i * 3 + 1], got[i * 3 + 2]);
1712 HeapFree(GetProcessHeap(), 0, expected);
1715 #define check_generated_effects(materials, num_materials, effects) \
1716 check_generated_effects_(__LINE__, materials, num_materials, effects)
1717 static void check_generated_effects_(int line, const D3DXMATERIAL *materials, DWORD num_materials, const D3DXEFFECTINSTANCE *effects)
1719 int i;
1720 static const struct {
1721 const char *name;
1722 DWORD name_size;
1723 DWORD num_bytes;
1724 DWORD value_offset;
1725 } params[] = {
1726 #define EFFECT_TABLE_ENTRY(str, field) \
1727 {str, sizeof(str), sizeof(materials->MatD3D.field), offsetof(D3DXMATERIAL, MatD3D.field)}
1728 EFFECT_TABLE_ENTRY("Diffuse", Diffuse),
1729 EFFECT_TABLE_ENTRY("Power", Power),
1730 EFFECT_TABLE_ENTRY("Specular", Specular),
1731 EFFECT_TABLE_ENTRY("Emissive", Emissive),
1732 EFFECT_TABLE_ENTRY("Ambient", Ambient),
1733 #undef EFFECT_TABLE_ENTRY
1736 if (!num_materials) {
1737 ok_(__FILE__, line)(effects == NULL, "Expected NULL effects, got %p\n", effects);
1738 return;
1740 for (i = 0; i < num_materials; i++)
1742 int j;
1743 DWORD expected_num_defaults = ARRAY_SIZE(params) + (materials[i].pTextureFilename ? 1 : 0);
1745 ok_(__FILE__,line)(expected_num_defaults == effects[i].NumDefaults,
1746 "effect[%u] NumDefaults: Expected %u, got %u\n", i,
1747 expected_num_defaults, effects[i].NumDefaults);
1748 for (j = 0; j < min(ARRAY_SIZE(params), effects[i].NumDefaults); j++)
1750 int k;
1751 D3DXEFFECTDEFAULT *got_param = &effects[i].pDefaults[j];
1752 ok_(__FILE__,line)(!strcmp(params[j].name, got_param->pParamName),
1753 "effect[%u].pDefaults[%u].pParamName: Expected '%s', got '%s'\n", i, j,
1754 params[j].name, got_param->pParamName);
1755 ok_(__FILE__,line)(D3DXEDT_FLOATS == got_param->Type,
1756 "effect[%u].pDefaults[%u].Type: Expected %u, got %u\n", i, j,
1757 D3DXEDT_FLOATS, got_param->Type);
1758 ok_(__FILE__,line)(params[j].num_bytes == got_param->NumBytes,
1759 "effect[%u].pDefaults[%u].NumBytes: Expected %u, got %u\n", i, j,
1760 params[j].num_bytes, got_param->NumBytes);
1761 for (k = 0; k < min(params[j].num_bytes, got_param->NumBytes) / 4; k++)
1763 FLOAT expected = ((FLOAT*)((BYTE*)&materials[i] + params[j].value_offset))[k];
1764 FLOAT got = ((FLOAT*)got_param->pValue)[k];
1765 ok_(__FILE__,line)(compare(expected, got),
1766 "effect[%u].pDefaults[%u] float value %u: Expected %g, got %g\n", i, j, k, expected, got);
1769 if (effects[i].NumDefaults > ARRAY_SIZE(params)) {
1770 D3DXEFFECTDEFAULT *got_param = &effects[i].pDefaults[j];
1771 static const char *expected_name = "Texture0@Name";
1773 ok_(__FILE__,line)(!strcmp(expected_name, got_param->pParamName),
1774 "effect[%u].pDefaults[%u].pParamName: Expected '%s', got '%s'\n", i, j,
1775 expected_name, got_param->pParamName);
1776 ok_(__FILE__,line)(D3DXEDT_STRING == got_param->Type,
1777 "effect[%u].pDefaults[%u].Type: Expected %u, got %u\n", i, j,
1778 D3DXEDT_STRING, got_param->Type);
1779 if (materials[i].pTextureFilename) {
1780 ok_(__FILE__,line)(strlen(materials[i].pTextureFilename) + 1 == got_param->NumBytes,
1781 "effect[%u] texture filename length: Expected %u, got %u\n", i,
1782 (DWORD)strlen(materials[i].pTextureFilename) + 1, got_param->NumBytes);
1783 ok_(__FILE__,line)(!strcmp(materials[i].pTextureFilename, got_param->pValue),
1784 "effect[%u] texture filename: Expected '%s', got '%s'\n", i,
1785 materials[i].pTextureFilename, (char*)got_param->pValue);
1791 static char *strdupA(const char *p)
1793 char *ret;
1794 if (!p) return NULL;
1795 ret = HeapAlloc(GetProcessHeap(), 0, strlen(p) + 1);
1796 if (ret) strcpy(ret, p);
1797 return ret;
1800 static HRESULT CALLBACK ID3DXAllocateHierarchyImpl_DestroyFrame(ID3DXAllocateHierarchy *iface, LPD3DXFRAME frame)
1802 TRACECALLBACK("ID3DXAllocateHierarchyImpl_DestroyFrame(%p, %p)\n", iface, frame);
1803 if (frame) {
1804 HeapFree(GetProcessHeap(), 0, frame->Name);
1805 HeapFree(GetProcessHeap(), 0, frame);
1807 return D3D_OK;
1810 static HRESULT CALLBACK ID3DXAllocateHierarchyImpl_CreateFrame(ID3DXAllocateHierarchy *iface,
1811 const char *name, D3DXFRAME **new_frame)
1813 D3DXFRAME *frame;
1815 TRACECALLBACK("ID3DXAllocateHierarchyImpl_CreateFrame(%p, '%s', %p)\n", iface, name, new_frame);
1816 frame = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*frame));
1817 if (!frame)
1818 return E_OUTOFMEMORY;
1819 if (name) {
1820 frame->Name = strdupA(name);
1821 if (!frame->Name) {
1822 HeapFree(GetProcessHeap(), 0, frame);
1823 return E_OUTOFMEMORY;
1826 *new_frame = frame;
1827 return D3D_OK;
1830 static HRESULT destroy_mesh_container(LPD3DXMESHCONTAINER mesh_container)
1832 int i;
1834 if (!mesh_container)
1835 return D3D_OK;
1836 HeapFree(GetProcessHeap(), 0, mesh_container->Name);
1837 if (U(mesh_container->MeshData).pMesh)
1838 IUnknown_Release(U(mesh_container->MeshData).pMesh);
1839 if (mesh_container->pMaterials) {
1840 for (i = 0; i < mesh_container->NumMaterials; i++)
1841 HeapFree(GetProcessHeap(), 0, mesh_container->pMaterials[i].pTextureFilename);
1842 HeapFree(GetProcessHeap(), 0, mesh_container->pMaterials);
1844 if (mesh_container->pEffects) {
1845 for (i = 0; i < mesh_container->NumMaterials; i++) {
1846 HeapFree(GetProcessHeap(), 0, mesh_container->pEffects[i].pEffectFilename);
1847 if (mesh_container->pEffects[i].pDefaults) {
1848 int j;
1849 for (j = 0; j < mesh_container->pEffects[i].NumDefaults; j++) {
1850 HeapFree(GetProcessHeap(), 0, mesh_container->pEffects[i].pDefaults[j].pParamName);
1851 HeapFree(GetProcessHeap(), 0, mesh_container->pEffects[i].pDefaults[j].pValue);
1853 HeapFree(GetProcessHeap(), 0, mesh_container->pEffects[i].pDefaults);
1856 HeapFree(GetProcessHeap(), 0, mesh_container->pEffects);
1858 HeapFree(GetProcessHeap(), 0, mesh_container->pAdjacency);
1859 if (mesh_container->pSkinInfo)
1860 IUnknown_Release(mesh_container->pSkinInfo);
1861 HeapFree(GetProcessHeap(), 0, mesh_container);
1862 return D3D_OK;
1865 static HRESULT CALLBACK ID3DXAllocateHierarchyImpl_DestroyMeshContainer(ID3DXAllocateHierarchy *iface, LPD3DXMESHCONTAINER mesh_container)
1867 TRACECALLBACK("ID3DXAllocateHierarchyImpl_DestroyMeshContainer(%p, %p)\n", iface, mesh_container);
1868 return destroy_mesh_container(mesh_container);
1871 static HRESULT CALLBACK ID3DXAllocateHierarchyImpl_CreateMeshContainer(ID3DXAllocateHierarchy *iface,
1872 const char *name, const D3DXMESHDATA *mesh_data, const D3DXMATERIAL *materials,
1873 const D3DXEFFECTINSTANCE *effects, DWORD num_materials, const DWORD *adjacency,
1874 ID3DXSkinInfo *skin_info, D3DXMESHCONTAINER **new_mesh_container)
1876 LPD3DXMESHCONTAINER mesh_container = NULL;
1877 int i;
1879 TRACECALLBACK("ID3DXAllocateHierarchyImpl_CreateMeshContainer(%p, '%s', %u, %p, %p, %p, %d, %p, %p, %p)\n",
1880 iface, name, mesh_data->Type, U(*mesh_data).pMesh, materials, effects,
1881 num_materials, adjacency, skin_info, *new_mesh_container);
1883 mesh_container = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*mesh_container));
1884 if (!mesh_container)
1885 return E_OUTOFMEMORY;
1887 if (name) {
1888 mesh_container->Name = strdupA(name);
1889 if (!mesh_container->Name)
1890 goto error;
1893 mesh_container->NumMaterials = num_materials;
1894 if (num_materials) {
1895 mesh_container->pMaterials = HeapAlloc(GetProcessHeap(), 0, num_materials * sizeof(*materials));
1896 if (!mesh_container->pMaterials)
1897 goto error;
1899 memcpy(mesh_container->pMaterials, materials, num_materials * sizeof(*materials));
1900 for (i = 0; i < num_materials; i++)
1901 mesh_container->pMaterials[i].pTextureFilename = NULL;
1902 for (i = 0; i < num_materials; i++) {
1903 if (materials[i].pTextureFilename) {
1904 mesh_container->pMaterials[i].pTextureFilename = strdupA(materials[i].pTextureFilename);
1905 if (!mesh_container->pMaterials[i].pTextureFilename)
1906 goto error;
1910 mesh_container->pEffects = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, num_materials * sizeof(*effects));
1911 if (!mesh_container->pEffects)
1912 goto error;
1913 for (i = 0; i < num_materials; i++) {
1914 int j;
1915 const D3DXEFFECTINSTANCE *effect_src = &effects[i];
1916 D3DXEFFECTINSTANCE *effect_dest = &mesh_container->pEffects[i];
1918 if (effect_src->pEffectFilename) {
1919 effect_dest->pEffectFilename = strdupA(effect_src->pEffectFilename);
1920 if (!effect_dest->pEffectFilename)
1921 goto error;
1923 effect_dest->pDefaults = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1924 effect_src->NumDefaults * sizeof(*effect_src->pDefaults));
1925 if (!effect_dest->pDefaults)
1926 goto error;
1927 effect_dest->NumDefaults = effect_src->NumDefaults;
1928 for (j = 0; j < effect_src->NumDefaults; j++) {
1929 const D3DXEFFECTDEFAULT *default_src = &effect_src->pDefaults[j];
1930 D3DXEFFECTDEFAULT *default_dest = &effect_dest->pDefaults[j];
1932 if (default_src->pParamName) {
1933 default_dest->pParamName = strdupA(default_src->pParamName);
1934 if (!default_dest->pParamName)
1935 goto error;
1937 default_dest->NumBytes = default_src->NumBytes;
1938 default_dest->Type = default_src->Type;
1939 default_dest->pValue = HeapAlloc(GetProcessHeap(), 0, default_src->NumBytes);
1940 memcpy(default_dest->pValue, default_src->pValue, default_src->NumBytes);
1945 ok(adjacency != NULL, "Expected non-NULL adjacency, got NULL\n");
1946 if (adjacency) {
1947 if (mesh_data->Type == D3DXMESHTYPE_MESH || mesh_data->Type == D3DXMESHTYPE_PMESH) {
1948 ID3DXBaseMesh *basemesh = (ID3DXBaseMesh*)U(*mesh_data).pMesh;
1949 DWORD num_faces = basemesh->lpVtbl->GetNumFaces(basemesh);
1950 size_t size = num_faces * sizeof(DWORD) * 3;
1951 mesh_container->pAdjacency = HeapAlloc(GetProcessHeap(), 0, size);
1952 if (!mesh_container->pAdjacency)
1953 goto error;
1954 memcpy(mesh_container->pAdjacency, adjacency, size);
1955 } else {
1956 ok(mesh_data->Type == D3DXMESHTYPE_PATCHMESH, "Unknown mesh type %u\n", mesh_data->Type);
1957 if (mesh_data->Type == D3DXMESHTYPE_PATCHMESH)
1958 trace("FIXME: copying adjacency data for patch mesh not implemented\n");
1962 memcpy(&mesh_container->MeshData, mesh_data, sizeof(*mesh_data));
1963 if (U(*mesh_data).pMesh)
1964 IUnknown_AddRef(U(*mesh_data).pMesh);
1965 if (skin_info) {
1966 mesh_container->pSkinInfo = skin_info;
1967 skin_info->lpVtbl->AddRef(skin_info);
1969 *new_mesh_container = mesh_container;
1971 return S_OK;
1972 error:
1973 destroy_mesh_container(mesh_container);
1974 return E_OUTOFMEMORY;
1977 static ID3DXAllocateHierarchyVtbl ID3DXAllocateHierarchyImpl_Vtbl = {
1978 ID3DXAllocateHierarchyImpl_CreateFrame,
1979 ID3DXAllocateHierarchyImpl_CreateMeshContainer,
1980 ID3DXAllocateHierarchyImpl_DestroyFrame,
1981 ID3DXAllocateHierarchyImpl_DestroyMeshContainer,
1983 static ID3DXAllocateHierarchy alloc_hier = { &ID3DXAllocateHierarchyImpl_Vtbl };
1985 #define test_LoadMeshFromX(device, xfile_str, vertex_array, fvf, index_array, materials_array, check_adjacency) \
1986 test_LoadMeshFromX_(__LINE__, device, xfile_str, sizeof(xfile_str) - 1, vertex_array, ARRAY_SIZE(vertex_array), fvf, \
1987 index_array, ARRAY_SIZE(index_array), sizeof(*index_array), materials_array, ARRAY_SIZE(materials_array), \
1988 check_adjacency);
1989 static void test_LoadMeshFromX_(int line, IDirect3DDevice9 *device, const char *xfile_str, size_t xfile_strlen,
1990 const void *vertices, DWORD num_vertices, DWORD fvf, const void *indices, DWORD num_indices, size_t index_size,
1991 const D3DXMATERIAL *expected_materials, DWORD expected_num_materials, BOOL check_adjacency)
1993 HRESULT hr;
1994 ID3DXBuffer *materials = NULL;
1995 ID3DXBuffer *effects = NULL;
1996 ID3DXBuffer *adjacency = NULL;
1997 ID3DXMesh *mesh = NULL;
1998 DWORD num_materials = 0;
2000 /* Adjacency is not checked when the X file contains multiple meshes,
2001 * since calling GenerateAdjacency on the merged mesh is not equivalent
2002 * to calling GenerateAdjacency on the individual meshes and then merging
2003 * the adjacency data. */
2004 hr = D3DXLoadMeshFromXInMemory(xfile_str, xfile_strlen, D3DXMESH_MANAGED, device,
2005 check_adjacency ? &adjacency : NULL, &materials, &effects, &num_materials, &mesh);
2006 ok_(__FILE__,line)(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2007 if (SUCCEEDED(hr)) {
2008 D3DXMATERIAL *materials_ptr = materials ? ID3DXBuffer_GetBufferPointer(materials) : NULL;
2009 D3DXEFFECTINSTANCE *effects_ptr = effects ? ID3DXBuffer_GetBufferPointer(effects) : NULL;
2010 DWORD *adjacency_ptr = check_adjacency ? ID3DXBuffer_GetBufferPointer(adjacency) : NULL;
2012 check_vertex_buffer_(line, mesh, vertices, num_vertices, fvf);
2013 check_index_buffer_(line, mesh, indices, num_indices, index_size);
2014 check_materials_(line, materials_ptr, num_materials, expected_materials, expected_num_materials);
2015 check_generated_effects_(line, materials_ptr, num_materials, effects_ptr);
2016 if (check_adjacency)
2017 check_generated_adjacency_(line, mesh, adjacency_ptr, 0.0f);
2019 if (materials) ID3DXBuffer_Release(materials);
2020 if (effects) ID3DXBuffer_Release(effects);
2021 if (adjacency) ID3DXBuffer_Release(adjacency);
2022 IUnknown_Release(mesh);
2026 static void D3DXLoadMeshTest(void)
2028 static const char empty_xfile[] = "xof 0303txt 0032";
2029 /*________________________*/
2030 static const char simple_xfile[] =
2031 "xof 0303txt 0032"
2032 "Mesh {"
2033 "3;"
2034 "0.0; 0.0; 0.0;,"
2035 "0.0; 1.0; 0.0;,"
2036 "1.0; 1.0; 0.0;;"
2037 "1;"
2038 "3; 0, 1, 2;;"
2039 "}";
2040 static const WORD simple_index_buffer[] = {0, 1, 2};
2041 static const D3DXVECTOR3 simple_vertex_buffer[] = {
2042 {0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {1.0, 1.0, 0.0}
2044 const DWORD simple_fvf = D3DFVF_XYZ;
2045 static const char framed_xfile[] =
2046 "xof 0303txt 0032"
2047 "Frame {"
2048 "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;; }"
2049 "FrameTransformMatrix {" /* translation (0.0, 0.0, 2.0) */
2050 "1.0, 0.0, 0.0, 0.0,"
2051 "0.0, 1.0, 0.0, 0.0,"
2052 "0.0, 0.0, 1.0, 0.0,"
2053 "0.0, 0.0, 2.0, 1.0;;"
2055 "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;; }"
2056 "FrameTransformMatrix {" /* translation (0.0, 0.0, 3.0) */
2057 "1.0, 0.0, 0.0, 0.0,"
2058 "0.0, 1.0, 0.0, 0.0,"
2059 "0.0, 0.0, 1.0, 0.0,"
2060 "0.0, 0.0, 3.0, 1.0;;"
2062 "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;; }"
2063 "}";
2064 static const WORD framed_index_buffer[] = { 0, 1, 2 };
2065 static const D3DXVECTOR3 framed_vertex_buffers[3][3] = {
2066 {{0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {1.0, 1.0, 0.0}},
2067 {{0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {2.0, 1.0, 0.0}},
2068 {{0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {3.0, 1.0, 0.0}},
2070 static const WORD merged_index_buffer[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
2071 /* frame transforms accumulates for D3DXLoadMeshFromX */
2072 static const D3DXVECTOR3 merged_vertex_buffer[] = {
2073 {0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {1.0, 1.0, 0.0},
2074 {0.0, 0.0, 2.0}, {0.0, 1.0, 2.0}, {2.0, 1.0, 2.0},
2075 {0.0, 0.0, 5.0}, {0.0, 1.0, 5.0}, {3.0, 1.0, 5.0},
2077 const DWORD framed_fvf = D3DFVF_XYZ;
2078 /*________________________*/
2079 static const char box_xfile[] =
2080 "xof 0303txt 0032"
2081 "Mesh {"
2082 "8;" /* DWORD nVertices; */
2083 /* array Vector vertices[nVertices]; */
2084 "0.0; 0.0; 0.0;,"
2085 "0.0; 0.0; 1.0;,"
2086 "0.0; 1.0; 0.0;,"
2087 "0.0; 1.0; 1.0;,"
2088 "1.0; 0.0; 0.0;,"
2089 "1.0; 0.0; 1.0;,"
2090 "1.0; 1.0; 0.0;,"
2091 "1.0; 1.0; 1.0;;"
2092 "6;" /* DWORD nFaces; */
2093 /* array MeshFace faces[nFaces]; */
2094 "4; 0, 1, 3, 2;," /* (left side) */
2095 "4; 2, 3, 7, 6;," /* (top side) */
2096 "4; 6, 7, 5, 4;," /* (right side) */
2097 "4; 1, 0, 4, 5;," /* (bottom side) */
2098 "4; 1, 5, 7, 3;," /* (back side) */
2099 "4; 0, 2, 6, 4;;" /* (front side) */
2100 "MeshNormals {"
2101 "6;" /* DWORD nNormals; */
2102 /* array Vector normals[nNormals]; */
2103 "-1.0; 0.0; 0.0;,"
2104 "0.0; 1.0; 0.0;,"
2105 "1.0; 0.0; 0.0;,"
2106 "0.0; -1.0; 0.0;,"
2107 "0.0; 0.0; 1.0;,"
2108 "0.0; 0.0; -1.0;;"
2109 "6;" /* DWORD nFaceNormals; */
2110 /* array MeshFace faceNormals[nFaceNormals]; */
2111 "4; 0, 0, 0, 0;,"
2112 "4; 1, 1, 1, 1;,"
2113 "4; 2, 2, 2, 2;,"
2114 "4; 3, 3, 3, 3;,"
2115 "4; 4, 4, 4, 4;,"
2116 "4; 5, 5, 5, 5;;"
2118 "MeshMaterialList materials {"
2119 "2;" /* DWORD nMaterials; */
2120 "6;" /* DWORD nFaceIndexes; */
2121 /* array DWORD faceIndexes[nFaceIndexes]; */
2122 "0, 0, 0, 1, 1, 1;;"
2123 "Material {"
2124 /* ColorRGBA faceColor; */
2125 "0.0; 0.0; 1.0; 1.0;;"
2126 /* FLOAT power; */
2127 "0.5;"
2128 /* ColorRGB specularColor; */
2129 "1.0; 1.0; 1.0;;"
2130 /* ColorRGB emissiveColor; */
2131 "0.0; 0.0; 0.0;;"
2133 "Material {"
2134 /* ColorRGBA faceColor; */
2135 "1.0; 1.0; 1.0; 1.0;;"
2136 /* FLOAT power; */
2137 "1.0;"
2138 /* ColorRGB specularColor; */
2139 "1.0; 1.0; 1.0;;"
2140 /* ColorRGB emissiveColor; */
2141 "0.0; 0.0; 0.0;;"
2142 "TextureFilename { \"texture.jpg\"; }"
2145 "MeshVertexColors {"
2146 "8;" /* DWORD nVertexColors; */
2147 /* array IndexedColor vertexColors[nVertexColors]; */
2148 "0; 0.0; 0.0; 0.0; 0.0;;"
2149 "1; 0.0; 0.0; 1.0; 0.1;;"
2150 "2; 0.0; 1.0; 0.0; 0.2;;"
2151 "3; 0.0; 1.0; 1.0; 0.3;;"
2152 "4; 1.0; 0.0; 0.0; 0.4;;"
2153 "5; 1.0; 0.0; 1.0; 0.5;;"
2154 "6; 1.0; 1.0; 0.0; 0.6;;"
2155 "7; 1.0; 1.0; 1.0; 0.7;;"
2157 "MeshTextureCoords {"
2158 "8;" /* DWORD nTextureCoords; */
2159 /* array Coords2d textureCoords[nTextureCoords]; */
2160 "0.0; 1.0;,"
2161 "1.0; 1.0;,"
2162 "0.0; 0.0;,"
2163 "1.0; 0.0;,"
2164 "1.0; 1.0;,"
2165 "0.0; 1.0;,"
2166 "1.0; 0.0;,"
2167 "0.0; 0.0;;"
2169 "}";
2170 static const WORD box_index_buffer[] = {
2171 0, 1, 3,
2172 0, 3, 2,
2173 8, 9, 7,
2174 8, 7, 6,
2175 10, 11, 5,
2176 10, 5, 4,
2177 12, 13, 14,
2178 12, 14, 15,
2179 16, 17, 18,
2180 16, 18, 19,
2181 20, 21, 22,
2182 20, 22, 23,
2184 static const struct {
2185 D3DXVECTOR3 position;
2186 D3DXVECTOR3 normal;
2187 D3DCOLOR diffuse;
2188 D3DXVECTOR2 tex_coords;
2189 } box_vertex_buffer[] = {
2190 {{0.0, 0.0, 0.0}, {-1.0, 0.0, 0.0}, 0x00000000, {0.0, 1.0}},
2191 {{0.0, 0.0, 1.0}, {-1.0, 0.0, 0.0}, 0x1a0000ff, {1.0, 1.0}},
2192 {{0.0, 1.0, 0.0}, {-1.0, 0.0, 0.0}, 0x3300ff00, {0.0, 0.0}},
2193 {{0.0, 1.0, 1.0}, {-1.0, 0.0, 0.0}, 0x4d00ffff, {1.0, 0.0}},
2194 {{1.0, 0.0, 0.0}, {1.0, 0.0, 0.0}, 0x66ff0000, {1.0, 1.0}},
2195 {{1.0, 0.0, 1.0}, {1.0, 0.0, 0.0}, 0x80ff00ff, {0.0, 1.0}},
2196 {{1.0, 1.0, 0.0}, {0.0, 1.0, 0.0}, 0x99ffff00, {1.0, 0.0}},
2197 {{1.0, 1.0, 1.0}, {0.0, 1.0, 0.0}, 0xb3ffffff, {0.0, 0.0}},
2198 {{0.0, 1.0, 0.0}, {0.0, 1.0, 0.0}, 0x3300ff00, {0.0, 0.0}},
2199 {{0.0, 1.0, 1.0}, {0.0, 1.0, 0.0}, 0x4d00ffff, {1.0, 0.0}},
2200 {{1.0, 1.0, 0.0}, {1.0, 0.0, 0.0}, 0x99ffff00, {1.0, 0.0}},
2201 {{1.0, 1.0, 1.0}, {1.0, 0.0, 0.0}, 0xb3ffffff, {0.0, 0.0}},
2202 {{0.0, 0.0, 1.0}, {0.0, -1.0, 0.0}, 0x1a0000ff, {1.0, 1.0}},
2203 {{0.0, 0.0, 0.0}, {0.0, -1.0, 0.0}, 0x00000000, {0.0, 1.0}},
2204 {{1.0, 0.0, 0.0}, {0.0, -1.0, 0.0}, 0x66ff0000, {1.0, 1.0}},
2205 {{1.0, 0.0, 1.0}, {0.0, -1.0, 0.0}, 0x80ff00ff, {0.0, 1.0}},
2206 {{0.0, 0.0, 1.0}, {0.0, 0.0, 1.0}, 0x1a0000ff, {1.0, 1.0}},
2207 {{1.0, 0.0, 1.0}, {0.0, 0.0, 1.0}, 0x80ff00ff, {0.0, 1.0}},
2208 {{1.0, 1.0, 1.0}, {0.0, 0.0, 1.0}, 0xb3ffffff, {0.0, 0.0}},
2209 {{0.0, 1.0, 1.0}, {0.0, 0.0, 1.0}, 0x4d00ffff, {1.0, 0.0}},
2210 {{0.0, 0.0, 0.0}, {0.0, 0.0, -1.0}, 0x00000000, {0.0, 1.0}},
2211 {{0.0, 1.0, 0.0}, {0.0, 0.0, -1.0}, 0x3300ff00, {0.0, 0.0}},
2212 {{1.0, 1.0, 0.0}, {0.0, 0.0, -1.0}, 0x99ffff00, {1.0, 0.0}},
2213 {{1.0, 0.0, 0.0}, {0.0, 0.0, -1.0}, 0x66ff0000, {1.0, 1.0}},
2215 static const D3DXMATERIAL box_materials[] = {
2218 {0.0, 0.0, 1.0, 1.0}, /* Diffuse */
2219 {0.0, 0.0, 0.0, 1.0}, /* Ambient */
2220 {1.0, 1.0, 1.0, 1.0}, /* Specular */
2221 {0.0, 0.0, 0.0, 1.0}, /* Emissive */
2222 0.5, /* Power */
2224 NULL, /* pTextureFilename */
2228 {1.0, 1.0, 1.0, 1.0}, /* Diffuse */
2229 {0.0, 0.0, 0.0, 1.0}, /* Ambient */
2230 {1.0, 1.0, 1.0, 1.0}, /* Specular */
2231 {0.0, 0.0, 0.0, 1.0}, /* Emissive */
2232 1.0, /* Power */
2234 (char *)"texture.jpg", /* pTextureFilename */
2237 static const char box_anim_xfile[] =
2238 "xof 0303txt 0032"
2239 "Mesh CubeMesh {"
2240 "8;" /* DWORD nVertices; */
2241 /* array Vector vertices[nVertices]; */
2242 "0.0; 0.0; 0.0;,"
2243 "0.0; 0.0; 1.0;,"
2244 "0.0; 1.0; 0.0;,"
2245 "0.0; 1.0; 1.0;,"
2246 "1.0; 0.0; 0.0;,"
2247 "1.0; 0.0; 1.0;,"
2248 "1.0; 1.0; 0.0;,"
2249 "1.0; 1.0; 1.0;;"
2250 "6;" /* DWORD nFaces; */
2251 /* array MeshFace faces[nFaces]; */
2252 "4; 0, 1, 3, 2;," /* left side */
2253 "4; 2, 3, 7, 6;," /* top side */
2254 "4; 6, 7, 5, 4;," /* right side */
2255 "4; 1, 0, 4, 5;," /* bottom side */
2256 "4; 1, 5, 7, 3;," /* back side */
2257 "4; 0, 2, 6, 4;;" /* front side */
2258 "MeshNormals {"
2259 "6;" /* DWORD nNormals; */
2260 /* array Vector normals[nNormals]; */
2261 "-1.0; 0.0; 0.0;,"
2262 "0.0; 1.0; 0.0;,"
2263 "1.0; 0.0; 0.0;,"
2264 "0.0; -1.0; 0.0;,"
2265 "0.0; 0.0; 1.0;,"
2266 "0.0; 0.0; -1.0;;"
2267 "6;" /* DWORD nFaceNormals; */
2268 /* array MeshFace faceNormals[nFaceNormals]; */
2269 "4; 0, 0, 0, 0;,"
2270 "4; 1, 1, 1, 1;,"
2271 "4; 2, 2, 2, 2;,"
2272 "4; 3, 3, 3, 3;,"
2273 "4; 4, 4, 4, 4;,"
2274 "4; 5, 5, 5, 5;;"
2276 "MeshMaterialList materials {"
2277 "2;" /* DWORD nMaterials; */
2278 "6;" /* DWORD nFaceIndexes; */
2279 /* array DWORD faceIndexes[nFaceIndexes]; */
2280 "0, 0, 0, 1, 1, 1;;"
2281 "Material {"
2282 /* ColorRGBA faceColor; */
2283 "0.0; 0.0; 1.0; 1.0;;"
2284 /* FLOAT power; */
2285 "0.5;"
2286 /* ColorRGB specularColor; */
2287 "1.0; 1.0; 1.0;;"
2288 /* ColorRGB emissiveColor; */
2289 "0.0; 0.0; 0.0;;"
2291 "Material {"
2292 /* ColorRGBA faceColor; */
2293 "1.0; 1.0; 1.0; 1.0;;"
2294 /* FLOAT power; */
2295 "1.0;"
2296 /* ColorRGB specularColor; */
2297 "1.0; 1.0; 1.0;;"
2298 /* ColorRGB emissiveColor; */
2299 "0.0; 0.0; 0.0;;"
2300 "TextureFilename { \"texture.jpg\"; }"
2303 "MeshVertexColors {"
2304 "8;" /* DWORD nVertexColors; */
2305 /* array IndexedColor vertexColors[nVertexColors]; */
2306 "0; 0.0; 0.0; 0.0; 0.0;;"
2307 "1; 0.0; 0.0; 1.0; 0.1;;"
2308 "2; 0.0; 1.0; 0.0; 0.2;;"
2309 "3; 0.0; 1.0; 1.0; 0.3;;"
2310 "4; 1.0; 0.0; 0.0; 0.4;;"
2311 "5; 1.0; 0.0; 1.0; 0.5;;"
2312 "6; 1.0; 1.0; 0.0; 0.6;;"
2313 "7; 1.0; 1.0; 1.0; 0.7;;"
2315 "MeshTextureCoords {"
2316 "8;" /* DWORD nTextureCoords; */
2317 /* array Coords2d textureCoords[nTextureCoords]; */
2318 "0.0; 1.0;,"
2319 "1.0; 1.0;,"
2320 "0.0; 0.0;,"
2321 "1.0; 0.0;,"
2322 "1.0; 1.0;,"
2323 "0.0; 1.0;,"
2324 "1.0; 0.0;,"
2325 "0.0; 0.0;;"
2328 "Frame CubeFrame {"
2329 "FrameTransformMatrix {"
2330 /* Matrix4x4 frameMatrix; */
2331 "1.0, 0.0, 0.0, 0.0,"
2332 "0.0, 1.0, 0.0, 0.0,"
2333 "0.0, 0.0, 1.0, 0.0,"
2334 "0.0, 0.0, 0.0, 1.0;;"
2336 "{CubeMesh}"
2338 "AnimationSet AnimationSet0 {"
2339 "Animation Animation0 {"
2340 "{CubeFrame}"
2341 "AnimationKey {"
2342 "2;" /* DWORD keyType; */
2343 "9;" /* DWORD nKeys; */
2344 /* array TimedFloatKeys keys[nKeys]; */
2345 "10; 3; -100.0, 0.0, 0.0;;,"
2346 "20; 3; -75.0, 0.0, 0.0;;,"
2347 "30; 3; -50.0, 0.0, 0.0;;,"
2348 "40; 3; -25.5, 0.0, 0.0;;,"
2349 "50; 3; 0.0, 0.0, 0.0;;,"
2350 "60; 3; 25.5, 0.0, 0.0;;,"
2351 "70; 3; 50.0, 0.0, 0.0;;,"
2352 "80; 3; 75.5, 0.0, 0.0;;,"
2353 "90; 3; 100.0, 0.0, 0.0;;;"
2356 "}";
2358 const DWORD box_fvf = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_TEX1;
2359 /*________________________*/
2360 static const D3DXMATERIAL default_materials[] = {
2363 {0.5, 0.5, 0.5, 0.0}, /* Diffuse */
2364 {0.0, 0.0, 0.0, 0.0}, /* Ambient */
2365 {0.5, 0.5, 0.5, 0.0}, /* Specular */
2366 {0.0, 0.0, 0.0, 0.0}, /* Emissive */
2367 0.0, /* Power */
2369 NULL, /* pTextureFilename */
2372 HRESULT hr;
2373 IDirect3DDevice9 *device = NULL;
2374 ID3DXMesh *mesh = NULL;
2375 D3DXFRAME *frame_hier = NULL;
2376 D3DXMATRIX transform;
2377 struct test_context *test_context;
2378 ID3DXAnimationController *controller;
2380 if (!(test_context = new_test_context()))
2382 skip("Couldn't create test context\n");
2383 return;
2385 device = test_context->device;
2387 hr = D3DXLoadMeshHierarchyFromXInMemory(NULL, sizeof(simple_xfile) - 1,
2388 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
2389 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2391 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, 0,
2392 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
2393 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2395 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1,
2396 D3DXMESH_MANAGED, NULL, &alloc_hier, NULL, &frame_hier, NULL);
2397 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2399 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1,
2400 D3DXMESH_MANAGED, device, NULL, NULL, &frame_hier, NULL);
2401 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2403 hr = D3DXLoadMeshHierarchyFromXInMemory(empty_xfile, sizeof(empty_xfile) - 1,
2404 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
2405 ok(hr == E_FAIL, "Expected E_FAIL, got %#x\n", hr);
2407 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1,
2408 D3DXMESH_MANAGED, device, &alloc_hier, NULL, NULL, NULL);
2409 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2411 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1,
2412 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
2413 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2414 if (SUCCEEDED(hr)) {
2415 D3DXMESHCONTAINER *container = frame_hier->pMeshContainer;
2417 ok(frame_hier->Name == NULL, "Expected NULL, got '%s'\n", frame_hier->Name);
2418 D3DXMatrixIdentity(&transform);
2419 check_matrix(&frame_hier->TransformationMatrix, &transform);
2421 ok(!strcmp(container->Name, ""), "Expected '', got '%s'\n", container->Name);
2422 ok(container->MeshData.Type == D3DXMESHTYPE_MESH, "Expected %d, got %d\n",
2423 D3DXMESHTYPE_MESH, container->MeshData.Type);
2424 mesh = U(container->MeshData).pMesh;
2425 check_vertex_buffer(mesh, simple_vertex_buffer, ARRAY_SIZE(simple_vertex_buffer), simple_fvf);
2426 check_index_buffer(mesh, simple_index_buffer, ARRAY_SIZE(simple_index_buffer), sizeof(*simple_index_buffer));
2427 check_materials(container->pMaterials, container->NumMaterials, NULL, 0);
2428 check_generated_effects(container->pMaterials, container->NumMaterials, container->pEffects);
2429 check_generated_adjacency(mesh, container->pAdjacency, 0.0f);
2430 hr = D3DXFrameDestroy(frame_hier, &alloc_hier);
2431 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2432 frame_hier = NULL;
2435 controller = (ID3DXAnimationController *)0xdeadbeef;
2436 hr = D3DXLoadMeshHierarchyFromXInMemory(box_anim_xfile, sizeof(box_anim_xfile) - 1,
2437 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, &controller);
2438 todo_wine ok(hr == D3D_OK, "Expected D3D_OK, got %#x.\n", hr);
2439 if (SUCCEEDED(hr))
2441 ok(controller != NULL, "Animation Controller NULL.\n");
2443 hr = D3DXFrameDestroy(frame_hier, &alloc_hier);
2444 ok(hr == D3D_OK, "Expected D3D_OK, got %#x.\n", hr);
2445 if (controller)
2446 controller->lpVtbl->Release(controller);
2448 frame_hier = NULL;
2451 controller = (ID3DXAnimationController *)0xdeadbeef;
2452 hr = D3DXLoadMeshHierarchyFromXInMemory(box_xfile, sizeof(box_xfile) - 1,
2453 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, &controller);
2454 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2455 if (SUCCEEDED(hr))
2457 D3DXMESHCONTAINER *container = frame_hier->pMeshContainer;
2459 ok(!controller, "Animation Controller returned.\n");
2460 ok(frame_hier->Name == NULL, "Expected NULL, got '%s'\n", frame_hier->Name);
2461 D3DXMatrixIdentity(&transform);
2462 check_matrix(&frame_hier->TransformationMatrix, &transform);
2464 ok(!strcmp(container->Name, ""), "Expected '', got '%s'\n", container->Name);
2465 ok(container->MeshData.Type == D3DXMESHTYPE_MESH, "Expected %d, got %d\n",
2466 D3DXMESHTYPE_MESH, container->MeshData.Type);
2467 mesh = U(container->MeshData).pMesh;
2468 check_vertex_buffer(mesh, box_vertex_buffer, ARRAY_SIZE(box_vertex_buffer), box_fvf);
2469 check_index_buffer(mesh, box_index_buffer, ARRAY_SIZE(box_index_buffer), sizeof(*box_index_buffer));
2470 check_materials(container->pMaterials, container->NumMaterials, box_materials, ARRAY_SIZE(box_materials));
2471 check_generated_effects(container->pMaterials, container->NumMaterials, container->pEffects);
2472 check_generated_adjacency(mesh, container->pAdjacency, 0.0f);
2473 hr = D3DXFrameDestroy(frame_hier, &alloc_hier);
2474 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2475 frame_hier = NULL;
2478 hr = D3DXLoadMeshHierarchyFromXInMemory(framed_xfile, sizeof(framed_xfile) - 1,
2479 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
2480 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2481 if (SUCCEEDED(hr)) {
2482 D3DXMESHCONTAINER *container = frame_hier->pMeshContainer;
2483 int i;
2485 ok(!strcmp(frame_hier->Name, ""), "Expected '', got '%s'\n", frame_hier->Name);
2486 /* last frame transform replaces the first */
2487 D3DXMatrixIdentity(&transform);
2488 U(transform).m[3][2] = 3.0;
2489 check_matrix(&frame_hier->TransformationMatrix, &transform);
2491 for (i = 0; i < 3; i++) {
2492 ok(!strcmp(container->Name, ""), "Expected '', got '%s'\n", container->Name);
2493 ok(container->MeshData.Type == D3DXMESHTYPE_MESH, "Expected %d, got %d\n",
2494 D3DXMESHTYPE_MESH, container->MeshData.Type);
2495 mesh = U(container->MeshData).pMesh;
2496 check_vertex_buffer(mesh, framed_vertex_buffers[i], ARRAY_SIZE(framed_vertex_buffers[0]), framed_fvf);
2497 check_index_buffer(mesh, framed_index_buffer, ARRAY_SIZE(framed_index_buffer), sizeof(*framed_index_buffer));
2498 check_materials(container->pMaterials, container->NumMaterials, NULL, 0);
2499 check_generated_effects(container->pMaterials, container->NumMaterials, container->pEffects);
2500 check_generated_adjacency(mesh, container->pAdjacency, 0.0f);
2501 container = container->pNextMeshContainer;
2503 ok(container == NULL, "Expected NULL, got %p\n", container);
2504 hr = D3DXFrameDestroy(frame_hier, &alloc_hier);
2505 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2506 frame_hier = NULL;
2510 hr = D3DXLoadMeshFromXInMemory(NULL, 0, D3DXMESH_MANAGED,
2511 device, NULL, NULL, NULL, NULL, &mesh);
2512 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2514 hr = D3DXLoadMeshFromXInMemory(NULL, sizeof(simple_xfile) - 1, D3DXMESH_MANAGED,
2515 device, NULL, NULL, NULL, NULL, &mesh);
2516 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2518 hr = D3DXLoadMeshFromXInMemory(simple_xfile, 0, D3DXMESH_MANAGED,
2519 device, NULL, NULL, NULL, NULL, &mesh);
2520 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2522 hr = D3DXLoadMeshFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1, D3DXMESH_MANAGED,
2523 device, NULL, NULL, NULL, NULL, NULL);
2524 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2526 hr = D3DXLoadMeshFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1, D3DXMESH_MANAGED,
2527 NULL, NULL, NULL, NULL, NULL, &mesh);
2528 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2530 hr = D3DXLoadMeshFromXInMemory(empty_xfile, sizeof(empty_xfile) - 1, D3DXMESH_MANAGED,
2531 device, NULL, NULL, NULL, NULL, &mesh);
2532 ok(hr == E_FAIL, "Expected E_FAIL, got %#x\n", hr);
2534 hr = D3DXLoadMeshFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1, D3DXMESH_MANAGED,
2535 device, NULL, NULL, NULL, NULL, &mesh);
2536 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2537 if (SUCCEEDED(hr))
2538 IUnknown_Release(mesh);
2540 test_LoadMeshFromX(device, simple_xfile, simple_vertex_buffer, simple_fvf, simple_index_buffer, default_materials, TRUE);
2541 test_LoadMeshFromX(device, box_xfile, box_vertex_buffer, box_fvf, box_index_buffer, box_materials, TRUE);
2542 test_LoadMeshFromX(device, framed_xfile, merged_vertex_buffer, framed_fvf, merged_index_buffer, default_materials, FALSE);
2544 free_test_context(test_context);
2547 static BOOL compute_box(struct mesh *mesh, float width, float height, float depth)
2549 unsigned int i, face;
2550 static const D3DXVECTOR3 unit_box[] =
2552 {-1.0f, -1.0f, -1.0f}, {-1.0f, -1.0f, 1.0f}, {-1.0f, 1.0f, 1.0f}, {-1.0f, 1.0f, -1.0f},
2553 {-1.0f, 1.0f, -1.0f}, {-1.0f, 1.0f, 1.0f}, { 1.0f, 1.0f, 1.0f}, { 1.0f, 1.0f, -1.0f},
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}
2559 static const D3DXVECTOR3 normals[] =
2561 {-1.0f, 0.0f, 0.0f}, { 0.0f, 1.0f, 0.0f}, { 1.0f, 0.0f, 0.0f},
2562 { 0.0f, -1.0f, 0.0f}, { 0.0f, 0.0f, 1.0f}, { 0.0f, 0.0f, -1.0f}
2565 if (!new_mesh(mesh, 24, 12))
2567 return FALSE;
2570 width /= 2.0f;
2571 height /= 2.0f;
2572 depth /= 2.0f;
2574 for (i = 0; i < 24; i++)
2576 mesh->vertices[i].position.x = width * unit_box[i].x;
2577 mesh->vertices[i].position.y = height * unit_box[i].y;
2578 mesh->vertices[i].position.z = depth * unit_box[i].z;
2579 mesh->vertices[i].normal.x = normals[i / 4].x;
2580 mesh->vertices[i].normal.y = normals[i / 4].y;
2581 mesh->vertices[i].normal.z = normals[i / 4].z;
2584 face = 0;
2585 for (i = 0; i < 12; i++)
2587 mesh->faces[i][0] = face++;
2588 mesh->faces[i][1] = face++;
2589 mesh->faces[i][2] = (i % 2) ? face - 4 : face;
2592 return TRUE;
2595 static void test_box(IDirect3DDevice9 *device, float width, float height, float depth)
2597 HRESULT hr;
2598 ID3DXMesh *box;
2599 struct mesh mesh;
2600 char name[256];
2602 hr = D3DXCreateBox(device, width, height, depth, &box, NULL);
2603 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
2604 if (hr != D3D_OK)
2606 skip("Couldn't create box\n");
2607 return;
2610 if (!compute_box(&mesh, width, height, depth))
2612 skip("Couldn't create mesh\n");
2613 box->lpVtbl->Release(box);
2614 return;
2617 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
2619 sprintf(name, "box (%g, %g, %g)", width, height, depth);
2620 compare_mesh(name, box, &mesh);
2622 free_mesh(&mesh);
2624 box->lpVtbl->Release(box);
2626 static void D3DXCreateBoxTest(void)
2628 HRESULT hr;
2629 IDirect3DDevice9* device;
2630 ID3DXMesh* box;
2631 ID3DXBuffer* ppBuffer;
2632 DWORD *buffer;
2633 static const DWORD adjacency[36]=
2634 {6, 9, 1, 2, 10, 0,
2635 1, 9, 3, 4, 10, 2,
2636 3, 8, 5, 7, 11, 4,
2637 0, 11, 7, 5, 8, 6,
2638 7, 4, 9, 2, 0, 8,
2639 1, 3, 11, 5, 6, 10};
2640 unsigned int i;
2641 struct test_context *test_context;
2643 if (!(test_context = new_test_context()))
2645 skip("Couldn't create test context\n");
2646 return;
2648 device = test_context->device;
2650 hr = D3DXCreateBox(device,2.0f,20.0f,4.9f,NULL, &ppBuffer);
2651 ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2653 hr = D3DXCreateBox(NULL,22.0f,20.0f,4.9f,&box, &ppBuffer);
2654 ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2656 hr = D3DXCreateBox(device,-2.0f,20.0f,4.9f,&box, &ppBuffer);
2657 ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2659 hr = D3DXCreateBox(device,22.0f,-20.0f,4.9f,&box, &ppBuffer);
2660 ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2662 hr = D3DXCreateBox(device,22.0f,20.0f,-4.9f,&box, &ppBuffer);
2663 ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2665 ppBuffer = NULL;
2666 hr = D3DXCreateBox(device,10.9f,20.0f,4.9f,&box, &ppBuffer);
2667 ok(hr==D3D_OK, "Expected D3D_OK, received %#x\n", hr);
2669 buffer = ID3DXBuffer_GetBufferPointer(ppBuffer);
2670 for(i=0; i<36; i++)
2671 ok(adjacency[i]==buffer[i], "expected adjacency %d: %#x, received %#x\n",i,adjacency[i], buffer[i]);
2673 box->lpVtbl->Release(box);
2674 ID3DXBuffer_Release(ppBuffer);
2676 test_box(device, 10.9f, 20.0f, 4.9f);
2678 free_test_context(test_context);
2681 static BOOL compute_polygon(struct mesh *mesh, float length, unsigned int sides)
2683 unsigned int i;
2684 float angle, scale;
2686 if (!new_mesh(mesh, sides + 1, sides))
2687 return FALSE;
2689 angle = D3DX_PI / sides;
2690 scale = 0.5f * length / sinf(angle);
2691 angle *= 2.0f;
2693 mesh->vertices[0].position.x = 0.0f;
2694 mesh->vertices[0].position.y = 0.0f;
2695 mesh->vertices[0].position.z = 0.0f;
2696 mesh->vertices[0].normal.x = 0.0f;
2697 mesh->vertices[0].normal.y = 0.0f;
2698 mesh->vertices[0].normal.z = 1.0f;
2700 for (i = 0; i < sides; ++i)
2702 mesh->vertices[i + 1].position.x = cosf(angle * i) * scale;
2703 mesh->vertices[i + 1].position.y = sinf(angle * i) * scale;
2704 mesh->vertices[i + 1].position.z = 0.0f;
2705 mesh->vertices[i + 1].normal.x = 0.0f;
2706 mesh->vertices[i + 1].normal.y = 0.0f;
2707 mesh->vertices[i + 1].normal.z = 1.0f;
2709 mesh->faces[i][0] = 0;
2710 mesh->faces[i][1] = i + 1;
2711 mesh->faces[i][2] = i + 2;
2714 mesh->faces[sides - 1][2] = 1;
2716 return TRUE;
2719 static void test_polygon(IDirect3DDevice9 *device, float length, unsigned int sides)
2721 HRESULT hr;
2722 ID3DXMesh *polygon;
2723 struct mesh mesh;
2724 char name[64];
2726 hr = D3DXCreatePolygon(device, length, sides, &polygon, NULL);
2727 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
2728 if (hr != D3D_OK)
2730 skip("Couldn't create polygon\n");
2731 return;
2734 if (!compute_polygon(&mesh, length, sides))
2736 skip("Couldn't create mesh\n");
2737 polygon->lpVtbl->Release(polygon);
2738 return;
2741 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
2743 sprintf(name, "polygon (%g, %u)", length, sides);
2744 compare_mesh(name, polygon, &mesh);
2746 free_mesh(&mesh);
2748 polygon->lpVtbl->Release(polygon);
2751 static void D3DXCreatePolygonTest(void)
2753 HRESULT hr;
2754 IDirect3DDevice9 *device;
2755 ID3DXMesh *polygon;
2756 ID3DXBuffer *adjacency;
2757 DWORD (*buffer)[3], buffer_size;
2758 unsigned int i;
2759 struct test_context *test_context;
2761 if (!(test_context = new_test_context()))
2763 skip("Couldn't create test context\n");
2764 return;
2766 device = test_context->device;
2768 hr = D3DXCreatePolygon(device, 2.0f, 11, NULL, &adjacency);
2769 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2771 hr = D3DXCreatePolygon(NULL, 2.0f, 11, &polygon, &adjacency);
2772 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2774 hr = D3DXCreatePolygon(device, -2.0f, 11, &polygon, &adjacency);
2775 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2777 polygon = (void *)0xdeadbeef;
2778 adjacency = (void *)0xdeadbeef;
2779 hr = D3DXCreatePolygon(device, 2.0f, 0, &polygon, &adjacency);
2780 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2781 ok(polygon == (void *)0xdeadbeef, "Polygon was changed to %p\n", polygon);
2782 ok(adjacency == (void *)0xdeadbeef, "Adjacency was changed to %p\n", adjacency);
2784 hr = D3DXCreatePolygon(device, 2.0f, 2, &polygon, &adjacency);
2785 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2787 adjacency = NULL;
2788 hr = D3DXCreatePolygon(device, 3.0f, 11, &polygon, &adjacency);
2789 ok(hr == D3D_OK, "Expected D3D_OK, received %#x\n", hr);
2791 buffer_size = ID3DXBuffer_GetBufferSize(adjacency);
2792 ok(buffer_size == 33 * sizeof(DWORD), "Wrong adjacency buffer size %u\n", buffer_size);
2794 buffer = ID3DXBuffer_GetBufferPointer(adjacency);
2795 for (i = 0; i < 11; ++i)
2797 ok(buffer[i][0] == (i + 10) % 11, "Wrong adjacency[%d][0] = %u\n", i, buffer[i][0]);
2798 ok(buffer[i][1] == ~0U, "Wrong adjacency[%d][1] = %u\n", i, buffer[i][1]);
2799 ok(buffer[i][2] == (i + 1) % 11, "Wrong adjacency[%d][2] = %u\n", i, buffer[i][2]);
2802 polygon->lpVtbl->Release(polygon);
2803 ID3DXBuffer_Release(adjacency);
2805 test_polygon(device, 2.0f, 3);
2806 test_polygon(device, 10.0f, 3);
2807 test_polygon(device, 10.0f, 5);
2808 test_polygon(device, 10.0f, 10);
2809 test_polygon(device, 20.0f, 10);
2810 test_polygon(device, 20.0f, 32000);
2812 free_test_context(test_context);
2815 struct sincos_table
2817 float *sin;
2818 float *cos;
2821 static void free_sincos_table(struct sincos_table *sincos_table)
2823 HeapFree(GetProcessHeap(), 0, sincos_table->cos);
2824 HeapFree(GetProcessHeap(), 0, sincos_table->sin);
2827 /* pre compute sine and cosine tables; caller must free */
2828 static BOOL compute_sincos_table(struct sincos_table *sincos_table, float angle_start, float angle_step, int n)
2830 float angle;
2831 int i;
2833 sincos_table->sin = HeapAlloc(GetProcessHeap(), 0, n * sizeof(*sincos_table->sin));
2834 if (!sincos_table->sin)
2836 return FALSE;
2838 sincos_table->cos = HeapAlloc(GetProcessHeap(), 0, n * sizeof(*sincos_table->cos));
2839 if (!sincos_table->cos)
2841 HeapFree(GetProcessHeap(), 0, sincos_table->sin);
2842 return FALSE;
2845 angle = angle_start;
2846 for (i = 0; i < n; i++)
2848 sincos_table->sin[i] = sin(angle);
2849 sincos_table->cos[i] = cos(angle);
2850 angle += angle_step;
2853 return TRUE;
2856 static WORD vertex_index(UINT slices, int slice, int stack)
2858 return stack*slices+slice+1;
2861 /* slices = subdivisions along xy plane, stacks = subdivisions along z axis */
2862 static BOOL compute_sphere(struct mesh *mesh, FLOAT radius, UINT slices, UINT stacks)
2864 float theta_step, theta_start;
2865 struct sincos_table theta;
2866 float phi_step, phi_start;
2867 struct sincos_table phi;
2868 DWORD number_of_vertices, number_of_faces;
2869 DWORD vertex, face;
2870 int slice, stack;
2872 /* theta = angle on xy plane wrt x axis */
2873 theta_step = D3DX_PI / stacks;
2874 theta_start = theta_step;
2876 /* phi = angle on xz plane wrt z axis */
2877 phi_step = -2 * D3DX_PI / slices;
2878 phi_start = D3DX_PI / 2;
2880 if (!compute_sincos_table(&theta, theta_start, theta_step, stacks))
2882 return FALSE;
2884 if (!compute_sincos_table(&phi, phi_start, phi_step, slices))
2886 free_sincos_table(&theta);
2887 return FALSE;
2890 number_of_vertices = 2 + slices * (stacks-1);
2891 number_of_faces = 2 * slices + (stacks - 2) * (2 * slices);
2893 if (!new_mesh(mesh, number_of_vertices, number_of_faces))
2895 free_sincos_table(&phi);
2896 free_sincos_table(&theta);
2897 return FALSE;
2900 vertex = 0;
2901 face = 0;
2903 mesh->vertices[vertex].normal.x = 0.0f;
2904 mesh->vertices[vertex].normal.y = 0.0f;
2905 mesh->vertices[vertex].normal.z = 1.0f;
2906 mesh->vertices[vertex].position.x = 0.0f;
2907 mesh->vertices[vertex].position.y = 0.0f;
2908 mesh->vertices[vertex].position.z = radius;
2909 vertex++;
2911 for (stack = 0; stack < stacks - 1; stack++)
2913 for (slice = 0; slice < slices; slice++)
2915 mesh->vertices[vertex].normal.x = theta.sin[stack] * phi.cos[slice];
2916 mesh->vertices[vertex].normal.y = theta.sin[stack] * phi.sin[slice];
2917 mesh->vertices[vertex].normal.z = theta.cos[stack];
2918 mesh->vertices[vertex].position.x = radius * theta.sin[stack] * phi.cos[slice];
2919 mesh->vertices[vertex].position.y = radius * theta.sin[stack] * phi.sin[slice];
2920 mesh->vertices[vertex].position.z = radius * theta.cos[stack];
2921 vertex++;
2923 if (slice > 0)
2925 if (stack == 0)
2927 /* top stack is triangle fan */
2928 mesh->faces[face][0] = 0;
2929 mesh->faces[face][1] = slice + 1;
2930 mesh->faces[face][2] = slice;
2931 face++;
2933 else
2935 /* stacks in between top and bottom are quad strips */
2936 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
2937 mesh->faces[face][1] = vertex_index(slices, slice, stack-1);
2938 mesh->faces[face][2] = vertex_index(slices, slice-1, stack);
2939 face++;
2941 mesh->faces[face][0] = vertex_index(slices, slice, stack-1);
2942 mesh->faces[face][1] = vertex_index(slices, slice, stack);
2943 mesh->faces[face][2] = vertex_index(slices, slice-1, stack);
2944 face++;
2949 if (stack == 0)
2951 mesh->faces[face][0] = 0;
2952 mesh->faces[face][1] = 1;
2953 mesh->faces[face][2] = slice;
2954 face++;
2956 else
2958 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
2959 mesh->faces[face][1] = vertex_index(slices, 0, stack-1);
2960 mesh->faces[face][2] = vertex_index(slices, slice-1, stack);
2961 face++;
2963 mesh->faces[face][0] = vertex_index(slices, 0, stack-1);
2964 mesh->faces[face][1] = vertex_index(slices, 0, stack);
2965 mesh->faces[face][2] = vertex_index(slices, slice-1, stack);
2966 face++;
2970 mesh->vertices[vertex].position.x = 0.0f;
2971 mesh->vertices[vertex].position.y = 0.0f;
2972 mesh->vertices[vertex].position.z = -radius;
2973 mesh->vertices[vertex].normal.x = 0.0f;
2974 mesh->vertices[vertex].normal.y = 0.0f;
2975 mesh->vertices[vertex].normal.z = -1.0f;
2977 /* bottom stack is triangle fan */
2978 for (slice = 1; slice < slices; slice++)
2980 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
2981 mesh->faces[face][1] = vertex_index(slices, slice, stack-1);
2982 mesh->faces[face][2] = vertex;
2983 face++;
2986 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
2987 mesh->faces[face][1] = vertex_index(slices, 0, stack-1);
2988 mesh->faces[face][2] = vertex;
2990 free_sincos_table(&phi);
2991 free_sincos_table(&theta);
2993 return TRUE;
2996 static void test_sphere(IDirect3DDevice9 *device, FLOAT radius, UINT slices, UINT stacks)
2998 HRESULT hr;
2999 ID3DXMesh *sphere;
3000 struct mesh mesh;
3001 char name[256];
3003 hr = D3DXCreateSphere(device, radius, slices, stacks, &sphere, NULL);
3004 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
3005 if (hr != D3D_OK)
3007 skip("Couldn't create sphere\n");
3008 return;
3011 if (!compute_sphere(&mesh, radius, slices, stacks))
3013 skip("Couldn't create mesh\n");
3014 sphere->lpVtbl->Release(sphere);
3015 return;
3018 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
3020 sprintf(name, "sphere (%g, %u, %u)", radius, slices, stacks);
3021 compare_mesh(name, sphere, &mesh);
3023 free_mesh(&mesh);
3025 sphere->lpVtbl->Release(sphere);
3028 static void D3DXCreateSphereTest(void)
3030 HRESULT hr;
3031 IDirect3DDevice9* device;
3032 ID3DXMesh* sphere = NULL;
3033 struct test_context *test_context;
3035 hr = D3DXCreateSphere(NULL, 0.0f, 0, 0, NULL, NULL);
3036 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3038 hr = D3DXCreateSphere(NULL, 0.1f, 0, 0, NULL, NULL);
3039 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3041 hr = D3DXCreateSphere(NULL, 0.0f, 1, 0, NULL, NULL);
3042 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3044 hr = D3DXCreateSphere(NULL, 0.0f, 0, 1, NULL, NULL);
3045 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3047 if (!(test_context = new_test_context()))
3049 skip("Couldn't create test context\n");
3050 return;
3052 device = test_context->device;
3054 hr = D3DXCreateSphere(device, 1.0f, 1, 1, &sphere, NULL);
3055 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3057 hr = D3DXCreateSphere(device, 1.0f, 2, 1, &sphere, NULL);
3058 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
3060 hr = D3DXCreateSphere(device, 1.0f, 1, 2, &sphere, NULL);
3061 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
3063 hr = D3DXCreateSphere(device, -0.1f, 1, 2, &sphere, NULL);
3064 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
3066 test_sphere(device, 0.0f, 2, 2);
3067 test_sphere(device, 1.0f, 2, 2);
3068 test_sphere(device, 1.0f, 3, 2);
3069 test_sphere(device, 1.0f, 4, 4);
3070 test_sphere(device, 1.0f, 3, 4);
3071 test_sphere(device, 5.0f, 6, 7);
3072 test_sphere(device, 10.0f, 11, 12);
3074 free_test_context(test_context);
3077 static BOOL compute_cylinder(struct mesh *mesh, FLOAT radius1, FLOAT radius2, FLOAT length, UINT slices, UINT stacks)
3079 float theta_step, theta_start;
3080 struct sincos_table theta;
3081 FLOAT delta_radius, radius, radius_step;
3082 FLOAT z, z_step, z_normal;
3083 DWORD number_of_vertices, number_of_faces;
3084 DWORD vertex, face;
3085 int slice, stack;
3087 /* theta = angle on xy plane wrt x axis */
3088 theta_step = -2 * D3DX_PI / slices;
3089 theta_start = D3DX_PI / 2;
3091 if (!compute_sincos_table(&theta, theta_start, theta_step, slices))
3093 return FALSE;
3096 number_of_vertices = 2 + (slices * (3 + stacks));
3097 number_of_faces = 2 * slices + stacks * (2 * slices);
3099 if (!new_mesh(mesh, number_of_vertices, number_of_faces))
3101 free_sincos_table(&theta);
3102 return FALSE;
3105 vertex = 0;
3106 face = 0;
3108 delta_radius = radius1 - radius2;
3109 radius = radius1;
3110 radius_step = delta_radius / stacks;
3112 z = -length / 2;
3113 z_step = length / stacks;
3114 z_normal = delta_radius / length;
3115 if (isnan(z_normal))
3117 z_normal = 0.0f;
3120 mesh->vertices[vertex].normal.x = 0.0f;
3121 mesh->vertices[vertex].normal.y = 0.0f;
3122 mesh->vertices[vertex].normal.z = -1.0f;
3123 mesh->vertices[vertex].position.x = 0.0f;
3124 mesh->vertices[vertex].position.y = 0.0f;
3125 mesh->vertices[vertex++].position.z = z;
3127 for (slice = 0; slice < slices; slice++, vertex++)
3129 mesh->vertices[vertex].normal.x = 0.0f;
3130 mesh->vertices[vertex].normal.y = 0.0f;
3131 mesh->vertices[vertex].normal.z = -1.0f;
3132 mesh->vertices[vertex].position.x = radius * theta.cos[slice];
3133 mesh->vertices[vertex].position.y = radius * theta.sin[slice];
3134 mesh->vertices[vertex].position.z = z;
3136 if (slice > 0)
3138 mesh->faces[face][0] = 0;
3139 mesh->faces[face][1] = slice;
3140 mesh->faces[face++][2] = slice + 1;
3144 mesh->faces[face][0] = 0;
3145 mesh->faces[face][1] = slice;
3146 mesh->faces[face++][2] = 1;
3148 for (stack = 1; stack <= stacks+1; stack++)
3150 for (slice = 0; slice < slices; slice++, vertex++)
3152 mesh->vertices[vertex].normal.x = theta.cos[slice];
3153 mesh->vertices[vertex].normal.y = theta.sin[slice];
3154 mesh->vertices[vertex].normal.z = z_normal;
3155 D3DXVec3Normalize(&mesh->vertices[vertex].normal, &mesh->vertices[vertex].normal);
3156 mesh->vertices[vertex].position.x = radius * theta.cos[slice];
3157 mesh->vertices[vertex].position.y = radius * theta.sin[slice];
3158 mesh->vertices[vertex].position.z = z;
3160 if (stack > 1 && slice > 0)
3162 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
3163 mesh->faces[face][1] = vertex_index(slices, slice-1, stack);
3164 mesh->faces[face++][2] = vertex_index(slices, slice, stack-1);
3166 mesh->faces[face][0] = vertex_index(slices, slice, stack-1);
3167 mesh->faces[face][1] = vertex_index(slices, slice-1, stack);
3168 mesh->faces[face++][2] = vertex_index(slices, slice, stack);
3172 if (stack > 1)
3174 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
3175 mesh->faces[face][1] = vertex_index(slices, slice-1, stack);
3176 mesh->faces[face++][2] = vertex_index(slices, 0, stack-1);
3178 mesh->faces[face][0] = vertex_index(slices, 0, stack-1);
3179 mesh->faces[face][1] = vertex_index(slices, slice-1, stack);
3180 mesh->faces[face++][2] = vertex_index(slices, 0, stack);
3183 if (stack < stacks + 1)
3185 z += z_step;
3186 radius -= radius_step;
3190 for (slice = 0; slice < slices; slice++, vertex++)
3192 mesh->vertices[vertex].normal.x = 0.0f;
3193 mesh->vertices[vertex].normal.y = 0.0f;
3194 mesh->vertices[vertex].normal.z = 1.0f;
3195 mesh->vertices[vertex].position.x = radius * theta.cos[slice];
3196 mesh->vertices[vertex].position.y = radius * theta.sin[slice];
3197 mesh->vertices[vertex].position.z = z;
3199 if (slice > 0)
3201 mesh->faces[face][0] = vertex_index(slices, slice-1, stack);
3202 mesh->faces[face][1] = number_of_vertices - 1;
3203 mesh->faces[face++][2] = vertex_index(slices, slice, stack);
3207 mesh->vertices[vertex].position.x = 0.0f;
3208 mesh->vertices[vertex].position.y = 0.0f;
3209 mesh->vertices[vertex].position.z = z;
3210 mesh->vertices[vertex].normal.x = 0.0f;
3211 mesh->vertices[vertex].normal.y = 0.0f;
3212 mesh->vertices[vertex].normal.z = 1.0f;
3214 mesh->faces[face][0] = vertex_index(slices, slice-1, stack);
3215 mesh->faces[face][1] = number_of_vertices - 1;
3216 mesh->faces[face][2] = vertex_index(slices, 0, stack);
3218 free_sincos_table(&theta);
3220 return TRUE;
3223 static void test_cylinder(IDirect3DDevice9 *device, FLOAT radius1, FLOAT radius2, FLOAT length, UINT slices, UINT stacks)
3225 HRESULT hr;
3226 ID3DXMesh *cylinder;
3227 struct mesh mesh;
3228 char name[256];
3230 hr = D3DXCreateCylinder(device, radius1, radius2, length, slices, stacks, &cylinder, NULL);
3231 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
3232 if (hr != D3D_OK)
3234 skip("Couldn't create cylinder\n");
3235 return;
3238 if (!compute_cylinder(&mesh, radius1, radius2, length, slices, stacks))
3240 skip("Couldn't create mesh\n");
3241 cylinder->lpVtbl->Release(cylinder);
3242 return;
3245 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
3247 sprintf(name, "cylinder (%g, %g, %g, %u, %u)", radius1, radius2, length, slices, stacks);
3248 compare_mesh(name, cylinder, &mesh);
3250 free_mesh(&mesh);
3252 cylinder->lpVtbl->Release(cylinder);
3255 static void D3DXCreateCylinderTest(void)
3257 HRESULT hr;
3258 IDirect3DDevice9* device;
3259 ID3DXMesh* cylinder = NULL;
3260 struct test_context *test_context;
3262 hr = D3DXCreateCylinder(NULL, 0.0f, 0.0f, 0.0f, 0, 0, NULL, NULL);
3263 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3265 hr = D3DXCreateCylinder(NULL, 1.0f, 1.0f, 1.0f, 2, 1, &cylinder, NULL);
3266 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3268 if (!(test_context = new_test_context()))
3270 skip("Couldn't create test context\n");
3271 return;
3273 device = test_context->device;
3275 hr = D3DXCreateCylinder(device, -0.1f, 1.0f, 1.0f, 2, 1, &cylinder, NULL);
3276 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3278 hr = D3DXCreateCylinder(device, 0.0f, 1.0f, 1.0f, 2, 1, &cylinder, NULL);
3279 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n",hr);
3281 if (SUCCEEDED(hr) && cylinder)
3283 cylinder->lpVtbl->Release(cylinder);
3286 hr = D3DXCreateCylinder(device, 1.0f, -0.1f, 1.0f, 2, 1, &cylinder, NULL);
3287 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3289 hr = D3DXCreateCylinder(device, 1.0f, 0.0f, 1.0f, 2, 1, &cylinder, NULL);
3290 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n",hr);
3292 if (SUCCEEDED(hr) && cylinder)
3294 cylinder->lpVtbl->Release(cylinder);
3297 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, -0.1f, 2, 1, &cylinder, NULL);
3298 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3300 /* Test with length == 0.0f succeeds */
3301 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, 0.0f, 2, 1, &cylinder, NULL);
3302 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n",hr);
3304 if (SUCCEEDED(hr) && cylinder)
3306 cylinder->lpVtbl->Release(cylinder);
3309 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, 1.0f, 1, 1, &cylinder, NULL);
3310 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3312 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, 1.0f, 2, 0, &cylinder, NULL);
3313 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3315 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, 1.0f, 2, 1, NULL, NULL);
3316 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3318 test_cylinder(device, 0.0f, 0.0f, 0.0f, 2, 1);
3319 test_cylinder(device, 1.0f, 1.0f, 1.0f, 2, 1);
3320 test_cylinder(device, 1.0f, 1.0f, 2.0f, 3, 4);
3321 test_cylinder(device, 3.0f, 2.0f, 4.0f, 3, 4);
3322 test_cylinder(device, 2.0f, 3.0f, 4.0f, 3, 4);
3323 test_cylinder(device, 3.0f, 4.0f, 5.0f, 11, 20);
3325 free_test_context(test_context);
3328 static BOOL compute_torus(struct mesh *mesh, float innerradius, float outerradius, UINT sides, UINT rings)
3330 float phi, phi_step, sin_phi, cos_phi;
3331 float theta, theta_step, sin_theta, cos_theta;
3332 unsigned int numvert, numfaces, i, j;
3334 numvert = sides * rings;
3335 numfaces = numvert * 2;
3337 if (!new_mesh(mesh, numvert, numfaces))
3338 return FALSE;
3340 phi_step = D3DX_PI / sides * 2.0f;
3341 theta_step = D3DX_PI / rings * -2.0f;
3343 theta = 0.0f;
3345 for (i = 0; i < rings; ++i)
3347 phi = 0.0f;
3349 cos_theta = cosf(theta);
3350 sin_theta = sinf(theta);
3352 for (j = 0; j < sides; ++j)
3354 sin_phi = sinf(phi);
3355 cos_phi = cosf(phi);
3357 mesh->vertices[i * sides + j].position.x = (innerradius * cos_phi + outerradius) * cos_theta;
3358 mesh->vertices[i * sides + j].position.y = (innerradius * cos_phi + outerradius) * sin_theta;
3359 mesh->vertices[i * sides + j].position.z = innerradius * sin_phi;
3360 mesh->vertices[i * sides + j].normal.x = cos_phi * cos_theta;
3361 mesh->vertices[i * sides + j].normal.y = cos_phi * sin_theta;
3362 mesh->vertices[i * sides + j].normal.z = sin_phi;
3364 phi += phi_step;
3367 theta += theta_step;
3370 for (i = 0; i < numfaces - sides * 2; ++i)
3372 mesh->faces[i][0] = i % 2 ? i / 2 + sides : i / 2;
3373 mesh->faces[i][1] = (i / 2 + 1) % sides ? i / 2 + 1 : i / 2 + 1 - sides;
3374 mesh->faces[i][2] = (i + 1) % (sides * 2) ? (i + 1) / 2 + sides : (i + 1) / 2;
3377 for (j = 0; i < numfaces; ++i, ++j)
3379 mesh->faces[i][0] = i % 2 ? j / 2 : i / 2;
3380 mesh->faces[i][1] = (i / 2 + 1) % sides ? i / 2 + 1 : i / 2 + 1 - sides;
3381 mesh->faces[i][2] = i == numfaces - 1 ? 0 : (j + 1) / 2;
3384 return TRUE;
3387 static void test_torus(IDirect3DDevice9 *device, float innerradius, float outerradius, UINT sides, UINT rings)
3389 HRESULT hr;
3390 ID3DXMesh *torus;
3391 struct mesh mesh;
3392 char name[256];
3394 hr = D3DXCreateTorus(device, innerradius, outerradius, sides, rings, &torus, NULL);
3395 ok(hr == D3D_OK, "Got result %#x, expected 0 (D3D_OK)\n", hr);
3396 if (hr != D3D_OK)
3398 skip("Couldn't create torus\n");
3399 return;
3402 if (!compute_torus(&mesh, innerradius, outerradius, sides, rings))
3404 skip("Couldn't create mesh\n");
3405 torus->lpVtbl->Release(torus);
3406 return;
3409 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
3411 sprintf(name, "torus (%g, %g, %u, %u)", innerradius, outerradius, sides, rings);
3412 compare_mesh(name, torus, &mesh);
3414 free_mesh(&mesh);
3416 torus->lpVtbl->Release(torus);
3419 static void D3DXCreateTorusTest(void)
3421 HRESULT hr;
3422 IDirect3DDevice9* device;
3423 ID3DXMesh* torus = NULL;
3424 struct test_context *test_context;
3426 if (!(test_context = new_test_context()))
3428 skip("Couldn't create test context\n");
3429 return;
3431 device = test_context->device;
3433 hr = D3DXCreateTorus(NULL, 0.0f, 0.0f, 3, 3, &torus, NULL);
3434 ok(hr == D3DERR_INVALIDCALL, "Got result %#x, expected %#x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
3436 hr = D3DXCreateTorus(device, -1.0f, 0.0f, 3, 3, &torus, NULL);
3437 ok(hr == D3DERR_INVALIDCALL, "Got result %#x, expected %#x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
3439 hr = D3DXCreateTorus(device, 0.0f, -1.0f, 3, 3, &torus, NULL);
3440 ok(hr == D3DERR_INVALIDCALL, "Got result %#x, expected %#x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
3442 hr = D3DXCreateTorus(device, 0.0f, 0.0f, 2, 3, &torus, NULL);
3443 ok(hr == D3DERR_INVALIDCALL, "Got result %#x, expected %#x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
3445 hr = D3DXCreateTorus(device, 0.0f, 0.0f, 3, 2, &torus, NULL);
3446 ok(hr == D3DERR_INVALIDCALL, "Got result %#x, expected %#x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
3448 hr = D3DXCreateTorus(device, 0.0f, 0.0f, 3, 3, NULL, NULL);
3449 ok(hr == D3DERR_INVALIDCALL, "Got result %#x, expected %#x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
3451 test_torus(device, 0.0f, 0.0f, 3, 3);
3452 test_torus(device, 1.0f, 1.0f, 3, 3);
3453 test_torus(device, 1.0f, 1.0f, 32, 64);
3454 test_torus(device, 0.0f, 1.0f, 5, 5);
3455 test_torus(device, 1.0f, 0.0f, 5, 5);
3456 test_torus(device, 5.0f, 0.2f, 8, 8);
3457 test_torus(device, 0.2f, 1.0f, 60, 3);
3458 test_torus(device, 0.2f, 1.0f, 8, 70);
3460 free_test_context(test_context);
3463 struct dynamic_array
3465 int count, capacity;
3466 void *items;
3469 enum pointtype {
3470 POINTTYPE_CURVE = 0,
3471 POINTTYPE_CORNER,
3472 POINTTYPE_CURVE_START,
3473 POINTTYPE_CURVE_END,
3474 POINTTYPE_CURVE_MIDDLE,
3477 struct point2d
3479 D3DXVECTOR2 pos;
3480 enum pointtype corner;
3483 /* is a dynamic_array */
3484 struct outline
3486 int count, capacity;
3487 struct point2d *items;
3490 /* is a dynamic_array */
3491 struct outline_array
3493 int count, capacity;
3494 struct outline *items;
3497 struct glyphinfo
3499 struct outline_array outlines;
3500 float offset_x;
3503 static BOOL reserve(struct dynamic_array *array, int count, int itemsize)
3505 if (count > array->capacity) {
3506 void *new_buffer;
3507 int new_capacity;
3508 if (array->items && array->capacity) {
3509 new_capacity = max(array->capacity * 2, count);
3510 new_buffer = HeapReAlloc(GetProcessHeap(), 0, array->items, new_capacity * itemsize);
3511 } else {
3512 new_capacity = max(16, count);
3513 new_buffer = HeapAlloc(GetProcessHeap(), 0, new_capacity * itemsize);
3515 if (!new_buffer)
3516 return FALSE;
3517 array->items = new_buffer;
3518 array->capacity = new_capacity;
3520 return TRUE;
3523 static struct point2d *add_point(struct outline *array)
3525 struct point2d *item;
3527 if (!reserve((struct dynamic_array *)array, array->count + 1, sizeof(array->items[0])))
3528 return NULL;
3530 item = &array->items[array->count++];
3531 ZeroMemory(item, sizeof(*item));
3532 return item;
3535 static struct outline *add_outline(struct outline_array *array)
3537 struct outline *item;
3539 if (!reserve((struct dynamic_array *)array, array->count + 1, sizeof(array->items[0])))
3540 return NULL;
3542 item = &array->items[array->count++];
3543 ZeroMemory(item, sizeof(*item));
3544 return item;
3547 static inline D3DXVECTOR2 *convert_fixed_to_float(POINTFX *pt, int count, float emsquare)
3549 D3DXVECTOR2 *ret = (D3DXVECTOR2*)pt;
3550 while (count--) {
3551 D3DXVECTOR2 *pt_flt = (D3DXVECTOR2*)pt;
3552 pt_flt->x = (pt->x.value + pt->x.fract / (float)0x10000) / emsquare;
3553 pt_flt->y = (pt->y.value + pt->y.fract / (float)0x10000) / emsquare;
3554 pt++;
3556 return ret;
3559 static HRESULT add_bezier_points(struct outline *outline, const D3DXVECTOR2 *p1,
3560 const D3DXVECTOR2 *p2, const D3DXVECTOR2 *p3,
3561 float max_deviation)
3563 D3DXVECTOR2 split1 = {0, 0}, split2 = {0, 0}, middle, vec;
3564 float deviation;
3566 D3DXVec2Scale(&split1, D3DXVec2Add(&split1, p1, p2), 0.5f);
3567 D3DXVec2Scale(&split2, D3DXVec2Add(&split2, p2, p3), 0.5f);
3568 D3DXVec2Scale(&middle, D3DXVec2Add(&middle, &split1, &split2), 0.5f);
3570 deviation = D3DXVec2Length(D3DXVec2Subtract(&vec, &middle, p2));
3571 if (deviation < max_deviation) {
3572 struct point2d *pt = add_point(outline);
3573 if (!pt) return E_OUTOFMEMORY;
3574 pt->pos = *p2;
3575 pt->corner = POINTTYPE_CURVE;
3576 /* the end point is omitted because the end line merges into the next segment of
3577 * the split bezier curve, and the end of the split bezier curve is added outside
3578 * this recursive function. */
3579 } else {
3580 HRESULT hr = add_bezier_points(outline, p1, &split1, &middle, max_deviation);
3581 if (hr != S_OK) return hr;
3582 hr = add_bezier_points(outline, &middle, &split2, p3, max_deviation);
3583 if (hr != S_OK) return hr;
3586 return S_OK;
3589 static inline BOOL is_direction_similar(D3DXVECTOR2 *dir1, D3DXVECTOR2 *dir2, float cos_theta)
3591 /* dot product = cos(theta) */
3592 return D3DXVec2Dot(dir1, dir2) > cos_theta;
3595 static inline D3DXVECTOR2 *unit_vec2(D3DXVECTOR2 *dir, const D3DXVECTOR2 *pt1, const D3DXVECTOR2 *pt2)
3597 return D3DXVec2Normalize(D3DXVec2Subtract(dir, pt2, pt1), dir);
3600 static BOOL attempt_line_merge(struct outline *outline,
3601 int pt_index,
3602 const D3DXVECTOR2 *nextpt,
3603 BOOL to_curve)
3605 D3DXVECTOR2 curdir, lastdir;
3606 struct point2d *prevpt, *pt;
3607 BOOL ret = FALSE;
3608 const float cos_half = cos(D3DXToRadian(0.5f));
3610 pt = &outline->items[pt_index];
3611 pt_index = (pt_index - 1 + outline->count) % outline->count;
3612 prevpt = &outline->items[pt_index];
3614 if (to_curve)
3615 pt->corner = pt->corner != POINTTYPE_CORNER ? POINTTYPE_CURVE_MIDDLE : POINTTYPE_CURVE_START;
3617 if (outline->count < 2)
3618 return FALSE;
3620 /* remove last point if the next line continues the last line */
3621 unit_vec2(&lastdir, &prevpt->pos, &pt->pos);
3622 unit_vec2(&curdir, &pt->pos, nextpt);
3623 if (is_direction_similar(&lastdir, &curdir, cos_half))
3625 outline->count--;
3626 if (pt->corner == POINTTYPE_CURVE_END)
3627 prevpt->corner = pt->corner;
3628 if (prevpt->corner == POINTTYPE_CURVE_END && to_curve)
3629 prevpt->corner = POINTTYPE_CURVE_MIDDLE;
3630 pt = prevpt;
3632 ret = TRUE;
3633 if (outline->count < 2)
3634 return ret;
3636 pt_index = (pt_index - 1 + outline->count) % outline->count;
3637 prevpt = &outline->items[pt_index];
3638 unit_vec2(&lastdir, &prevpt->pos, &pt->pos);
3639 unit_vec2(&curdir, &pt->pos, nextpt);
3641 return ret;
3644 static HRESULT create_outline(struct glyphinfo *glyph, void *raw_outline, int datasize,
3645 float max_deviation, float emsquare)
3647 const float cos_45 = cos(D3DXToRadian(45.0f));
3648 const float cos_90 = cos(D3DXToRadian(90.0f));
3649 TTPOLYGONHEADER *header = (TTPOLYGONHEADER *)raw_outline;
3651 while ((char *)header < (char *)raw_outline + datasize)
3653 TTPOLYCURVE *curve = (TTPOLYCURVE *)(header + 1);
3654 struct point2d *lastpt, *pt;
3655 D3DXVECTOR2 lastdir;
3656 D3DXVECTOR2 *pt_flt;
3657 int j;
3658 struct outline *outline = add_outline(&glyph->outlines);
3660 if (!outline)
3661 return E_OUTOFMEMORY;
3663 pt = add_point(outline);
3664 if (!pt)
3665 return E_OUTOFMEMORY;
3666 pt_flt = convert_fixed_to_float(&header->pfxStart, 1, emsquare);
3667 pt->pos = *pt_flt;
3668 pt->corner = POINTTYPE_CORNER;
3670 if (header->dwType != TT_POLYGON_TYPE)
3671 trace("Unknown header type %d\n", header->dwType);
3673 while ((char *)curve < (char *)header + header->cb)
3675 D3DXVECTOR2 bezier_start = outline->items[outline->count - 1].pos;
3676 BOOL to_curve = curve->wType != TT_PRIM_LINE && curve->cpfx > 1;
3678 if (!curve->cpfx) {
3679 curve = (TTPOLYCURVE *)&curve->apfx[curve->cpfx];
3680 continue;
3683 pt_flt = convert_fixed_to_float(curve->apfx, curve->cpfx, emsquare);
3685 attempt_line_merge(outline, outline->count - 1, &pt_flt[0], to_curve);
3687 if (to_curve)
3689 HRESULT hr;
3690 int count = curve->cpfx;
3691 j = 0;
3693 while (count > 2)
3695 D3DXVECTOR2 bezier_end;
3697 D3DXVec2Scale(&bezier_end, D3DXVec2Add(&bezier_end, &pt_flt[j], &pt_flt[j+1]), 0.5f);
3698 hr = add_bezier_points(outline, &bezier_start, &pt_flt[j], &bezier_end, max_deviation);
3699 if (hr != S_OK)
3700 return hr;
3701 bezier_start = bezier_end;
3702 count--;
3703 j++;
3705 hr = add_bezier_points(outline, &bezier_start, &pt_flt[j], &pt_flt[j+1], max_deviation);
3706 if (hr != S_OK)
3707 return hr;
3709 pt = add_point(outline);
3710 if (!pt)
3711 return E_OUTOFMEMORY;
3712 j++;
3713 pt->pos = pt_flt[j];
3714 pt->corner = POINTTYPE_CURVE_END;
3715 } else {
3716 for (j = 0; j < curve->cpfx; j++)
3718 pt = add_point(outline);
3719 if (!pt)
3720 return E_OUTOFMEMORY;
3721 pt->pos = pt_flt[j];
3722 pt->corner = POINTTYPE_CORNER;
3726 curve = (TTPOLYCURVE *)&curve->apfx[curve->cpfx];
3729 /* remove last point if the next line continues the last line */
3730 if (outline->count >= 3) {
3731 BOOL to_curve;
3733 lastpt = &outline->items[outline->count - 1];
3734 pt = &outline->items[0];
3735 if (pt->pos.x == lastpt->pos.x && pt->pos.y == lastpt->pos.y) {
3736 if (lastpt->corner == POINTTYPE_CURVE_END)
3738 if (pt->corner == POINTTYPE_CURVE_START)
3739 pt->corner = POINTTYPE_CURVE_MIDDLE;
3740 else
3741 pt->corner = POINTTYPE_CURVE_END;
3743 outline->count--;
3744 } else {
3745 /* outline closed with a line from end to start point */
3746 attempt_line_merge(outline, outline->count - 1, &pt->pos, FALSE);
3748 lastpt = &outline->items[0];
3749 to_curve = lastpt->corner != POINTTYPE_CORNER && lastpt->corner != POINTTYPE_CURVE_END;
3750 if (lastpt->corner == POINTTYPE_CURVE_START)
3751 lastpt->corner = POINTTYPE_CORNER;
3752 pt = &outline->items[1];
3753 if (attempt_line_merge(outline, 0, &pt->pos, to_curve))
3754 *lastpt = outline->items[outline->count];
3757 lastpt = &outline->items[outline->count - 1];
3758 pt = &outline->items[0];
3759 unit_vec2(&lastdir, &lastpt->pos, &pt->pos);
3760 for (j = 0; j < outline->count; j++)
3762 D3DXVECTOR2 curdir;
3764 lastpt = pt;
3765 pt = &outline->items[(j + 1) % outline->count];
3766 unit_vec2(&curdir, &lastpt->pos, &pt->pos);
3768 switch (lastpt->corner)
3770 case POINTTYPE_CURVE_START:
3771 case POINTTYPE_CURVE_END:
3772 if (!is_direction_similar(&lastdir, &curdir, cos_45))
3773 lastpt->corner = POINTTYPE_CORNER;
3774 break;
3775 case POINTTYPE_CURVE_MIDDLE:
3776 if (!is_direction_similar(&lastdir, &curdir, cos_90))
3777 lastpt->corner = POINTTYPE_CORNER;
3778 else
3779 lastpt->corner = POINTTYPE_CURVE;
3780 break;
3781 default:
3782 break;
3784 lastdir = curdir;
3787 header = (TTPOLYGONHEADER *)((char *)header + header->cb);
3789 return S_OK;
3792 static void free_outline(struct outline *outline)
3794 HeapFree(GetProcessHeap(), 0, outline->items);
3797 static void free_glyphinfo(struct glyphinfo *glyph)
3799 unsigned int i;
3801 for (i = 0; i < glyph->outlines.count; ++i)
3802 free_outline(&glyph->outlines.items[i]);
3803 HeapFree(GetProcessHeap(), 0, glyph->outlines.items);
3806 static void compute_text_mesh(struct mesh *mesh, const char *text,
3807 float deviation, float extrusion, float otmEMSquare, const struct glyphinfo *glyphs)
3809 DWORD nb_vertices, nb_faces;
3810 DWORD nb_corners, nb_outline_points;
3811 int textlen = 0;
3812 int i;
3813 struct vertex *vertex_ptr;
3814 face *face_ptr;
3816 textlen = strlen(text);
3818 /* corner points need an extra vertex for the different side faces normals */
3819 nb_corners = 0;
3820 nb_outline_points = 0;
3821 for (i = 0; i < textlen; i++)
3823 int j;
3824 for (j = 0; j < glyphs[i].outlines.count; j++)
3826 int k;
3827 struct outline *outline = &glyphs[i].outlines.items[j];
3828 nb_outline_points += outline->count;
3829 nb_corners++; /* first outline point always repeated as a corner */
3830 for (k = 1; k < outline->count; k++)
3831 if (outline->items[k].corner)
3832 nb_corners++;
3836 nb_vertices = (nb_outline_points + nb_corners) * 2 + textlen;
3837 nb_faces = nb_outline_points * 2;
3839 ok(new_mesh(mesh, nb_vertices, nb_faces), "Failed to create reference text mesh.\n");
3841 /* convert 2D vertices and faces into 3D mesh */
3842 vertex_ptr = mesh->vertices;
3843 face_ptr = mesh->faces;
3844 for (i = 0; i < textlen; i++)
3846 int j;
3848 /* side vertices and faces */
3849 for (j = 0; j < glyphs[i].outlines.count; j++)
3851 struct vertex *outline_vertices = vertex_ptr;
3852 struct outline *outline = &glyphs[i].outlines.items[j];
3853 int k;
3854 struct point2d *prevpt = &outline->items[outline->count - 1];
3855 struct point2d *pt = &outline->items[0];
3857 for (k = 1; k <= outline->count; k++)
3859 struct vertex vtx;
3860 struct point2d *nextpt = &outline->items[k % outline->count];
3861 WORD vtx_idx = vertex_ptr - mesh->vertices;
3862 D3DXVECTOR2 vec;
3864 if (pt->corner == POINTTYPE_CURVE_START)
3865 D3DXVec2Subtract(&vec, &pt->pos, &prevpt->pos);
3866 else if (pt->corner)
3867 D3DXVec2Subtract(&vec, &nextpt->pos, &pt->pos);
3868 else
3869 D3DXVec2Subtract(&vec, &nextpt->pos, &prevpt->pos);
3870 D3DXVec2Normalize(&vec, &vec);
3871 vtx.normal.x = -vec.y;
3872 vtx.normal.y = vec.x;
3873 vtx.normal.z = 0;
3875 vtx.position.x = pt->pos.x + glyphs[i].offset_x;
3876 vtx.position.y = pt->pos.y;
3877 vtx.position.z = 0;
3878 *vertex_ptr++ = vtx;
3880 vtx.position.z = -extrusion;
3881 *vertex_ptr++ = vtx;
3883 vtx.position.x = nextpt->pos.x + glyphs[i].offset_x;
3884 vtx.position.y = nextpt->pos.y;
3885 if (pt->corner && nextpt->corner && nextpt->corner != POINTTYPE_CURVE_END) {
3886 vtx.position.z = -extrusion;
3887 *vertex_ptr++ = vtx;
3888 vtx.position.z = 0;
3889 *vertex_ptr++ = vtx;
3891 (*face_ptr)[0] = vtx_idx;
3892 (*face_ptr)[1] = vtx_idx + 2;
3893 (*face_ptr)[2] = vtx_idx + 1;
3894 face_ptr++;
3896 (*face_ptr)[0] = vtx_idx;
3897 (*face_ptr)[1] = vtx_idx + 3;
3898 (*face_ptr)[2] = vtx_idx + 2;
3899 face_ptr++;
3900 } else {
3901 if (nextpt->corner) {
3902 if (nextpt->corner == POINTTYPE_CURVE_END) {
3903 struct point2d *nextpt2 = &outline->items[(k + 1) % outline->count];
3904 D3DXVec2Subtract(&vec, &nextpt2->pos, &nextpt->pos);
3905 } else {
3906 D3DXVec2Subtract(&vec, &nextpt->pos, &pt->pos);
3908 D3DXVec2Normalize(&vec, &vec);
3909 vtx.normal.x = -vec.y;
3910 vtx.normal.y = vec.x;
3912 vtx.position.z = 0;
3913 *vertex_ptr++ = vtx;
3914 vtx.position.z = -extrusion;
3915 *vertex_ptr++ = vtx;
3918 (*face_ptr)[0] = vtx_idx;
3919 (*face_ptr)[1] = vtx_idx + 3;
3920 (*face_ptr)[2] = vtx_idx + 1;
3921 face_ptr++;
3923 (*face_ptr)[0] = vtx_idx;
3924 (*face_ptr)[1] = vtx_idx + 2;
3925 (*face_ptr)[2] = vtx_idx + 3;
3926 face_ptr++;
3929 prevpt = pt;
3930 pt = nextpt;
3932 if (!pt->corner) {
3933 *vertex_ptr++ = *outline_vertices++;
3934 *vertex_ptr++ = *outline_vertices++;
3938 /* FIXME: compute expected faces */
3939 /* Add placeholder to separate glyph outlines */
3940 vertex_ptr->position.x = 0;
3941 vertex_ptr->position.y = 0;
3942 vertex_ptr->position.z = 0;
3943 vertex_ptr->normal.x = 0;
3944 vertex_ptr->normal.y = 0;
3945 vertex_ptr->normal.z = 1;
3946 vertex_ptr++;
3950 static void compare_text_outline_mesh(const char *name, ID3DXMesh *d3dxmesh, struct mesh *mesh,
3951 size_t textlen, float extrusion, const struct glyphinfo *glyphs)
3953 HRESULT hr;
3954 DWORD number_of_vertices, number_of_faces;
3955 IDirect3DVertexBuffer9 *vertex_buffer = NULL;
3956 IDirect3DIndexBuffer9 *index_buffer = NULL;
3957 D3DVERTEXBUFFER_DESC vertex_buffer_description;
3958 D3DINDEXBUFFER_DESC index_buffer_description;
3959 struct vertex *vertices = NULL;
3960 face *faces = NULL;
3961 int expected, i;
3962 int vtx_idx1, face_idx1, vtx_idx2, face_idx2;
3964 number_of_vertices = d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh);
3965 number_of_faces = d3dxmesh->lpVtbl->GetNumFaces(d3dxmesh);
3967 hr = d3dxmesh->lpVtbl->GetVertexBuffer(d3dxmesh, &vertex_buffer);
3968 ok(hr == D3D_OK, "Test %s, unexpected hr %#x.\n", name, hr);
3969 hr = IDirect3DVertexBuffer9_GetDesc(vertex_buffer, &vertex_buffer_description);
3970 ok(hr == D3D_OK, "Test %s, unexpected hr %#x.\n", name, hr);
3971 ok(vertex_buffer_description.Format == D3DFMT_VERTEXDATA, "Test %s, unexpected format %u.\n",
3972 name, vertex_buffer_description.Format);
3973 ok(vertex_buffer_description.Type == D3DRTYPE_VERTEXBUFFER, "Test %s, unexpected resource type %u.\n",
3974 name, vertex_buffer_description.Type);
3975 ok(!vertex_buffer_description.Usage, "Test %s, unexpected usage %#x.\n", name, vertex_buffer_description.Usage);
3976 ok(vertex_buffer_description.Pool == D3DPOOL_MANAGED, "Test %s, unexpected pool %u.\n",
3977 name, vertex_buffer_description.Pool);
3978 ok(vertex_buffer_description.FVF == mesh->fvf, "Test %s, unexpected FVF %#x (expected %#x).\n",
3979 name, vertex_buffer_description.FVF, mesh->fvf);
3980 if (!mesh->fvf)
3981 expected = number_of_vertices * mesh->vertex_size;
3982 else
3983 expected = number_of_vertices * D3DXGetFVFVertexSize(mesh->fvf);
3984 ok(vertex_buffer_description.Size == expected, "Test %s, unexpected size %u (expected %u).\n",
3985 name, vertex_buffer_description.Size, expected);
3987 hr = d3dxmesh->lpVtbl->GetIndexBuffer(d3dxmesh, &index_buffer);
3988 ok(hr == D3D_OK, "Test %s, unexpected hr %#x.\n", name, hr);
3989 hr = IDirect3DIndexBuffer9_GetDesc(index_buffer, &index_buffer_description);
3990 ok(hr == D3D_OK, "Test %s, unexpected hr %#x.\n", name, hr);
3991 ok(index_buffer_description.Format == D3DFMT_INDEX16, "Test %s, unexpected format %u.\n",
3992 name, index_buffer_description.Format);
3993 ok(index_buffer_description.Type == D3DRTYPE_INDEXBUFFER, "Test %s, unexpected resource type %u.\n",
3994 name, index_buffer_description.Type);
3995 ok(!index_buffer_description.Usage, "Test %s, unexpected usage %#x.\n",
3996 name, index_buffer_description.Usage);
3997 ok(index_buffer_description.Pool == D3DPOOL_MANAGED, "Test %s, unexpected pool %u.\n",
3998 name, index_buffer_description.Pool);
3999 expected = number_of_faces * sizeof(WORD) * 3;
4000 ok(index_buffer_description.Size == expected, "Test %s, unexpected size %u.\n",
4001 name, index_buffer_description.Size);
4003 hr = IDirect3DVertexBuffer9_Lock(vertex_buffer, 0, number_of_vertices * sizeof(D3DXVECTOR3) * 2,
4004 (void **)&vertices, D3DLOCK_DISCARD);
4005 ok(hr == D3D_OK, "Test %s, unexpected hr %#x.\n", name, hr);
4006 hr = IDirect3DIndexBuffer9_Lock(index_buffer, 0, number_of_faces * sizeof(WORD) * 3,
4007 (void **)&faces, D3DLOCK_DISCARD);
4008 ok(hr == D3D_OK, "Test %s, unexpected hr %#x.\n", name, hr);
4009 face_idx1 = 0;
4010 vtx_idx2 = 0;
4011 face_idx2 = 0;
4012 vtx_idx1 = 0;
4013 for (i = 0; i < textlen; i++)
4015 int nb_outline_vertices1, nb_outline_faces1;
4016 int nb_outline_vertices2, nb_outline_faces2;
4017 int nb_back_vertices, nb_back_faces;
4018 int first_vtx1, first_vtx2;
4019 int first_face1, first_face2;
4020 int j;
4022 first_vtx1 = vtx_idx1;
4023 first_vtx2 = vtx_idx2;
4024 /* Glyphs without outlines do not generate any vertices. */
4025 if (glyphs[i].outlines.count > 0)
4027 for (; vtx_idx1 < number_of_vertices; vtx_idx1++)
4029 if (vertices[vtx_idx1].normal.z != 0)
4030 break;
4033 for (; vtx_idx2 < mesh->number_of_vertices; vtx_idx2++)
4035 if (mesh->vertices[vtx_idx2].normal.z != 0)
4036 break;
4039 nb_outline_vertices1 = vtx_idx1 - first_vtx1;
4040 nb_outline_vertices2 = vtx_idx2 - first_vtx2;
4041 ok(nb_outline_vertices1 == nb_outline_vertices2,
4042 "Test %s, glyph %d, outline vertex count result %d, expected %d\n", name, i,
4043 nb_outline_vertices1, nb_outline_vertices2);
4045 for (j = 0; j < min(nb_outline_vertices1, nb_outline_vertices2); j++)
4047 vtx_idx1 = first_vtx1 + j;
4048 vtx_idx2 = first_vtx2 + j;
4049 ok(compare_vec3(vertices[vtx_idx1].position, mesh->vertices[vtx_idx2].position),
4050 "Test %s, glyph %d, vertex position %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1,
4051 vertices[vtx_idx1].position.x, vertices[vtx_idx1].position.y, vertices[vtx_idx1].position.z,
4052 mesh->vertices[vtx_idx2].position.x, mesh->vertices[vtx_idx2].position.y, mesh->vertices[vtx_idx2].position.z);
4053 ok(compare_vec3(vertices[vtx_idx1].normal, mesh->vertices[first_vtx2 + j].normal),
4054 "Test %s, glyph %d, vertex normal %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1,
4055 vertices[vtx_idx1].normal.x, vertices[vtx_idx1].normal.y, vertices[vtx_idx1].normal.z,
4056 mesh->vertices[vtx_idx2].normal.x, mesh->vertices[vtx_idx2].normal.y, mesh->vertices[vtx_idx2].normal.z);
4058 vtx_idx1 = first_vtx1 + nb_outline_vertices1;
4059 vtx_idx2 = first_vtx2 + nb_outline_vertices2;
4061 first_face1 = face_idx1;
4062 first_face2 = face_idx2;
4063 for (; face_idx1 < number_of_faces; face_idx1++)
4065 if (faces[face_idx1][0] >= vtx_idx1 ||
4066 faces[face_idx1][1] >= vtx_idx1 ||
4067 faces[face_idx1][2] >= vtx_idx1)
4068 break;
4070 for (; face_idx2 < mesh->number_of_faces; face_idx2++)
4072 if (mesh->faces[face_idx2][0] >= vtx_idx2 ||
4073 mesh->faces[face_idx2][1] >= vtx_idx2 ||
4074 mesh->faces[face_idx2][2] >= vtx_idx2)
4075 break;
4077 nb_outline_faces1 = face_idx1 - first_face1;
4078 nb_outline_faces2 = face_idx2 - first_face2;
4079 ok(nb_outline_faces1 == nb_outline_faces2,
4080 "Test %s, glyph %d, outline face count result %d, expected %d\n", name, i,
4081 nb_outline_faces1, nb_outline_faces2);
4083 for (j = 0; j < min(nb_outline_faces1, nb_outline_faces2); j++)
4085 face_idx1 = first_face1 + j;
4086 face_idx2 = first_face2 + j;
4087 ok(faces[face_idx1][0] - first_vtx1 == mesh->faces[face_idx2][0] - first_vtx2 &&
4088 faces[face_idx1][1] - first_vtx1 == mesh->faces[face_idx2][1] - first_vtx2 &&
4089 faces[face_idx1][2] - first_vtx1 == mesh->faces[face_idx2][2] - first_vtx2,
4090 "Test %s, glyph %d, face %d, result (%d, %d, %d), expected (%d, %d, %d)\n", name, i, face_idx1,
4091 faces[face_idx1][0], faces[face_idx1][1], faces[face_idx1][2],
4092 mesh->faces[face_idx2][0] - first_vtx2 + first_vtx1,
4093 mesh->faces[face_idx2][1] - first_vtx2 + first_vtx1,
4094 mesh->faces[face_idx2][2] - first_vtx2 + first_vtx1);
4096 face_idx1 = first_face1 + nb_outline_faces1;
4097 face_idx2 = first_face2 + nb_outline_faces2;
4099 /* partial test on back vertices and faces */
4100 first_vtx1 = vtx_idx1;
4101 for (; vtx_idx1 < number_of_vertices; vtx_idx1++) {
4102 struct vertex vtx;
4104 if (vertices[vtx_idx1].normal.z != 1.0f)
4105 break;
4107 vtx.position.z = 0.0f;
4108 vtx.normal.x = 0.0f;
4109 vtx.normal.y = 0.0f;
4110 vtx.normal.z = 1.0f;
4111 ok(compare(vertices[vtx_idx1].position.z, vtx.position.z),
4112 "Test %s, glyph %d, vertex position.z %d, result %g, expected %g\n", name, i, vtx_idx1,
4113 vertices[vtx_idx1].position.z, vtx.position.z);
4114 ok(compare_vec3(vertices[vtx_idx1].normal, vtx.normal),
4115 "Test %s, glyph %d, vertex normal %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1,
4116 vertices[vtx_idx1].normal.x, vertices[vtx_idx1].normal.y, vertices[vtx_idx1].normal.z,
4117 vtx.normal.x, vtx.normal.y, vtx.normal.z);
4119 nb_back_vertices = vtx_idx1 - first_vtx1;
4120 first_face1 = face_idx1;
4121 for (; face_idx1 < number_of_faces; face_idx1++)
4123 const D3DXVECTOR3 *vtx1, *vtx2, *vtx3;
4124 D3DXVECTOR3 normal;
4125 D3DXVECTOR3 v1 = {0, 0, 0};
4126 D3DXVECTOR3 v2 = {0, 0, 0};
4127 D3DXVECTOR3 forward = {0.0f, 0.0f, 1.0f};
4129 if (faces[face_idx1][0] >= vtx_idx1 ||
4130 faces[face_idx1][1] >= vtx_idx1 ||
4131 faces[face_idx1][2] >= vtx_idx1)
4132 break;
4134 vtx1 = &vertices[faces[face_idx1][0]].position;
4135 vtx2 = &vertices[faces[face_idx1][1]].position;
4136 vtx3 = &vertices[faces[face_idx1][2]].position;
4138 D3DXVec3Subtract(&v1, vtx2, vtx1);
4139 D3DXVec3Subtract(&v2, vtx3, vtx2);
4140 D3DXVec3Cross(&normal, &v1, &v2);
4141 D3DXVec3Normalize(&normal, &normal);
4142 ok(!D3DXVec3Length(&normal) || compare_vec3(normal, forward),
4143 "Test %s, glyph %d, face %d normal, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, face_idx1,
4144 normal.x, normal.y, normal.z, forward.x, forward.y, forward.z);
4146 nb_back_faces = face_idx1 - first_face1;
4148 /* compare front and back faces & vertices */
4149 if (extrusion == 0.0f) {
4150 /* Oddly there are only back faces in this case */
4151 nb_back_vertices /= 2;
4152 nb_back_faces /= 2;
4153 face_idx1 -= nb_back_faces;
4154 vtx_idx1 -= nb_back_vertices;
4156 for (j = 0; j < nb_back_vertices; j++)
4158 struct vertex vtx = vertices[first_vtx1];
4159 vtx.position.z = -extrusion;
4160 vtx.normal.x = 0.0f;
4161 vtx.normal.y = 0.0f;
4162 vtx.normal.z = extrusion == 0.0f ? 1.0f : -1.0f;
4163 ok(compare_vec3(vertices[vtx_idx1].position, vtx.position),
4164 "Test %s, glyph %d, vertex position %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1,
4165 vertices[vtx_idx1].position.x, vertices[vtx_idx1].position.y, vertices[vtx_idx1].position.z,
4166 vtx.position.x, vtx.position.y, vtx.position.z);
4167 ok(compare_vec3(vertices[vtx_idx1].normal, vtx.normal),
4168 "Test %s, glyph %d, vertex normal %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1,
4169 vertices[vtx_idx1].normal.x, vertices[vtx_idx1].normal.y, vertices[vtx_idx1].normal.z,
4170 vtx.normal.x, vtx.normal.y, vtx.normal.z);
4171 vtx_idx1++;
4172 first_vtx1++;
4174 for (j = 0; j < nb_back_faces; j++)
4176 int f1, f2;
4177 if (extrusion == 0.0f) {
4178 f1 = 1;
4179 f2 = 2;
4180 } else {
4181 f1 = 2;
4182 f2 = 1;
4184 ok(faces[face_idx1][0] == faces[first_face1][0] + nb_back_vertices &&
4185 faces[face_idx1][1] == faces[first_face1][f1] + nb_back_vertices &&
4186 faces[face_idx1][2] == faces[first_face1][f2] + nb_back_vertices,
4187 "Test %s, glyph %d, face %d, result (%d, %d, %d), expected (%d, %d, %d)\n", name, i, face_idx1,
4188 faces[face_idx1][0], faces[face_idx1][1], faces[face_idx1][2],
4189 faces[first_face1][0] - nb_back_faces,
4190 faces[first_face1][f1] - nb_back_faces,
4191 faces[first_face1][f2] - nb_back_faces);
4192 first_face1++;
4193 face_idx1++;
4196 /* skip to the outline for the next glyph */
4197 for (; vtx_idx2 < mesh->number_of_vertices; vtx_idx2++) {
4198 if (mesh->vertices[vtx_idx2].normal.z == 0)
4199 break;
4201 for (; face_idx2 < mesh->number_of_faces; face_idx2++)
4203 if (mesh->faces[face_idx2][0] >= vtx_idx2 ||
4204 mesh->faces[face_idx2][1] >= vtx_idx2 ||
4205 mesh->faces[face_idx2][2] >= vtx_idx2) break;
4209 IDirect3DIndexBuffer9_Unlock(index_buffer);
4210 IDirect3DVertexBuffer9_Unlock(vertex_buffer);
4211 IDirect3DIndexBuffer9_Release(index_buffer);
4212 IDirect3DVertexBuffer9_Release(vertex_buffer);
4215 static void test_createtext(IDirect3DDevice9 *device, HDC hdc, const char *text, float deviation, float extrusion)
4217 static const MAT2 identity = {{0, 1}, {0, 0}, {0, 0}, {0, 1}};
4218 HRESULT hr;
4219 ID3DXMesh *d3dxmesh = NULL;
4220 struct mesh mesh = {0};
4221 char name[256];
4222 OUTLINETEXTMETRICA otm;
4223 GLYPHMETRICS gm;
4224 struct glyphinfo *glyphs;
4225 GLYPHMETRICSFLOAT *glyphmetrics_float = HeapAlloc(GetProcessHeap(), 0, sizeof(GLYPHMETRICSFLOAT) * strlen(text));
4226 int i;
4227 LOGFONTA lf;
4228 float offset_x;
4229 size_t textlen;
4230 HFONT font = NULL, oldfont = NULL;
4231 char *raw_outline;
4233 sprintf(name, "text ('%s', %f, %f)", text, deviation, extrusion);
4235 hr = D3DXCreateTextA(device, hdc, text, deviation, extrusion, &d3dxmesh, NULL, glyphmetrics_float);
4236 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
4238 /* must select a modified font having lfHeight = otm.otmEMSquare before
4239 * calling GetGlyphOutline to get the expected values */
4240 ok(GetObjectA(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf), "Failed to get current DC font.\n");
4241 ok(GetOutlineTextMetricsA(hdc, sizeof(otm), &otm), "Failed to get DC font outline.\n");
4242 lf.lfHeight = otm.otmEMSquare;
4243 lf.lfWidth = 0;
4244 ok(!!(font = CreateFontIndirectA(&lf)), "Failed to create font.\n");
4246 textlen = strlen(text);
4247 glyphs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, textlen * sizeof(*glyphs));
4248 oldfont = SelectObject(hdc, font);
4250 for (i = 0; i < textlen; i++)
4252 GetGlyphOutlineA(hdc, text[i], GGO_NATIVE, &gm, 0, NULL, &identity);
4253 compare_float(glyphmetrics_float[i].gmfBlackBoxX, gm.gmBlackBoxX / (float)otm.otmEMSquare);
4254 compare_float(glyphmetrics_float[i].gmfBlackBoxY, gm.gmBlackBoxY / (float)otm.otmEMSquare);
4255 compare_float(glyphmetrics_float[i].gmfptGlyphOrigin.x, gm.gmptGlyphOrigin.x / (float)otm.otmEMSquare);
4256 compare_float(glyphmetrics_float[i].gmfptGlyphOrigin.y, gm.gmptGlyphOrigin.y / (float)otm.otmEMSquare);
4257 compare_float(glyphmetrics_float[i].gmfCellIncX, gm.gmCellIncX / (float)otm.otmEMSquare);
4258 compare_float(glyphmetrics_float[i].gmfCellIncY, gm.gmCellIncY / (float)otm.otmEMSquare);
4261 if (deviation == 0.0f)
4262 deviation = 1.0f / otm.otmEMSquare;
4264 offset_x = 0.0f;
4265 for (i = 0; i < textlen; i++)
4267 DWORD datasize;
4269 glyphs[i].offset_x = offset_x;
4271 datasize = GetGlyphOutlineA(hdc, text[i], GGO_NATIVE, &gm, 0, NULL, &identity);
4272 ok(datasize != GDI_ERROR, "Failed to retrieve GDI glyph outline size.\n");
4273 raw_outline = HeapAlloc(GetProcessHeap(), 0, datasize);
4274 datasize = GetGlyphOutlineA(hdc, text[i], GGO_NATIVE, &gm, datasize, raw_outline, &identity);
4275 ok(datasize != GDI_ERROR, "Failed to retrieve GDI glyph outline.\n");
4276 create_outline(&glyphs[i], raw_outline, datasize, deviation, otm.otmEMSquare);
4277 HeapFree(GetProcessHeap(), 0, raw_outline);
4279 offset_x += gm.gmCellIncX / (float)otm.otmEMSquare;
4282 SelectObject(hdc, oldfont);
4284 compute_text_mesh(&mesh, text, deviation, extrusion, otm.otmEMSquare, glyphs);
4285 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
4287 compare_text_outline_mesh(name, d3dxmesh, &mesh, textlen, extrusion, glyphs);
4289 free_mesh(&mesh);
4290 d3dxmesh->lpVtbl->Release(d3dxmesh);
4291 DeleteObject(font);
4292 HeapFree(GetProcessHeap(), 0, glyphmetrics_float);
4294 for (i = 0; i < textlen; i++)
4295 free_glyphinfo(&glyphs[i]);
4296 HeapFree(GetProcessHeap(), 0, glyphs);
4299 static void D3DXCreateTextTest(void)
4301 HRESULT hr;
4302 HDC hdc;
4303 IDirect3DDevice9* device;
4304 ID3DXMesh* d3dxmesh = NULL;
4305 HFONT hFont;
4306 OUTLINETEXTMETRICA otm;
4307 int number_of_vertices;
4308 int number_of_faces;
4309 struct test_context *test_context;
4311 if (!(test_context = new_test_context()))
4313 skip("Couldn't create test context\n");
4314 return;
4316 device = test_context->device;
4318 hdc = CreateCompatibleDC(NULL);
4320 hFont = CreateFontA(12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
4321 CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, "Arial");
4322 SelectObject(hdc, hFont);
4323 GetOutlineTextMetricsA(hdc, sizeof(otm), &otm);
4325 hr = D3DXCreateTextA(device, hdc, "wine", 0.001f, 0.4f, NULL, NULL, NULL);
4326 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4328 /* D3DXCreateTextA page faults from passing NULL text */
4330 hr = D3DXCreateTextW(device, hdc, NULL, 0.001f, 0.4f, &d3dxmesh, NULL, NULL);
4331 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4333 hr = D3DXCreateTextA(device, hdc, "", 0.001f, 0.4f, &d3dxmesh, NULL, NULL);
4334 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4336 hr = D3DXCreateTextA(device, hdc, " ", 0.001f, 0.4f, &d3dxmesh, NULL, NULL);
4337 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4339 hr = D3DXCreateTextA(NULL, hdc, "wine", 0.001f, 0.4f, &d3dxmesh, NULL, NULL);
4340 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4342 hr = D3DXCreateTextA(device, NULL, "wine", 0.001f, 0.4f, &d3dxmesh, NULL, NULL);
4343 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4345 hr = D3DXCreateTextA(device, hdc, "wine", -FLT_MIN, 0.4f, &d3dxmesh, NULL, NULL);
4346 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4348 hr = D3DXCreateTextA(device, hdc, "wine", 0.001f, -FLT_MIN, &d3dxmesh, NULL, NULL);
4349 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4351 /* deviation = 0.0f treated as if deviation = 1.0f / otm.otmEMSquare */
4352 hr = D3DXCreateTextA(device, hdc, "wine", 1.0f / otm.otmEMSquare, 0.4f, &d3dxmesh, NULL, NULL);
4353 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
4354 number_of_vertices = d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh);
4355 number_of_faces = d3dxmesh->lpVtbl->GetNumFaces(d3dxmesh);
4356 d3dxmesh->lpVtbl->Release(d3dxmesh);
4358 hr = D3DXCreateTextA(device, hdc, "wine", 0.0f, 0.4f, &d3dxmesh, NULL, NULL);
4359 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
4360 ok(number_of_vertices == d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh),
4361 "Got %d vertices, expected %d\n",
4362 d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh), number_of_vertices);
4363 ok(number_of_faces == d3dxmesh->lpVtbl->GetNumFaces(d3dxmesh),
4364 "Got %d faces, expected %d\n",
4365 d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh), number_of_faces);
4366 d3dxmesh->lpVtbl->Release(d3dxmesh);
4368 if (0)
4370 /* too much detail requested, so will appear to hang */
4371 trace("Waiting for D3DXCreateText to finish with deviation = FLT_MIN ...\n");
4372 hr = D3DXCreateTextA(device, hdc, "wine", FLT_MIN, 0.4f, &d3dxmesh, NULL, NULL);
4373 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
4374 if (SUCCEEDED(hr) && d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh);
4375 trace("D3DXCreateText finish with deviation = FLT_MIN\n");
4378 hr = D3DXCreateTextA(device, hdc, "wine", 0.001f, 0.4f, &d3dxmesh, NULL, NULL);
4379 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
4380 if (SUCCEEDED(hr) && d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh);
4382 test_createtext(device, hdc, "wine", FLT_MAX, 0.4f);
4383 test_createtext(device, hdc, "wine", 0.001f, FLT_MIN);
4384 test_createtext(device, hdc, "wine", 0.001f, 0.0f);
4385 test_createtext(device, hdc, "wine", 0.001f, FLT_MAX);
4386 test_createtext(device, hdc, "wine", 0.0f, 1.0f);
4387 test_createtext(device, hdc, " wine", 1.0f, 0.0f);
4388 test_createtext(device, hdc, "wine ", 1.0f, 0.0f);
4389 test_createtext(device, hdc, "wi ne", 1.0f, 0.0f);
4391 DeleteDC(hdc);
4392 DeleteObject(hFont);
4394 free_test_context(test_context);
4397 static void test_get_decl_length(void)
4399 static const D3DVERTEXELEMENT9 declaration1[] =
4401 {0, 0, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4402 {1, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4403 {2, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4404 {3, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4405 {4, 0, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4406 {5, 0, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4407 {6, 0, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4408 {7, 0, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4409 {8, 0, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4410 {9, 0, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4411 {10, 0, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4412 {11, 0, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4413 {12, 0, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4414 {13, 0, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4415 {14, 0, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4416 D3DDECL_END(),
4418 static const D3DVERTEXELEMENT9 declaration2[] =
4420 {0, 8, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4421 {1, 8, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4422 {2, 8, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4423 {3, 8, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4424 {4, 8, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4425 {5, 8, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4426 {6, 8, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4427 {7, 8, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4428 {0, 8, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4429 {1, 8, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4430 {2, 8, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4431 {3, 8, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4432 {4, 8, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4433 {5, 8, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4434 {6, 8, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4435 {7, 8, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4436 D3DDECL_END(),
4438 UINT size;
4440 size = D3DXGetDeclLength(declaration1);
4441 ok(size == 15, "Got size %u, expected 15.\n", size);
4443 size = D3DXGetDeclLength(declaration2);
4444 ok(size == 16, "Got size %u, expected 16.\n", size);
4447 static void test_get_decl_vertex_size(void)
4449 static const D3DVERTEXELEMENT9 declaration1[] =
4451 {0, 0, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4452 {1, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4453 {2, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4454 {3, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4455 {4, 0, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4456 {5, 0, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4457 {6, 0, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4458 {7, 0, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4459 {8, 0, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4460 {9, 0, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4461 {10, 0, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4462 {11, 0, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4463 {12, 0, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4464 {13, 0, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4465 {14, 0, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4466 D3DDECL_END(),
4468 static const D3DVERTEXELEMENT9 declaration2[] =
4470 {0, 8, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4471 {1, 8, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4472 {2, 8, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4473 {3, 8, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4474 {4, 8, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4475 {5, 8, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4476 {6, 8, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4477 {7, 8, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4478 {0, 8, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4479 {1, 8, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4480 {2, 8, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4481 {3, 8, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4482 {4, 8, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4483 {5, 8, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4484 {6, 8, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4485 {7, 8, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4486 D3DDECL_END(),
4488 static const UINT sizes1[] =
4490 4, 8, 12, 16,
4491 4, 4, 4, 8,
4492 4, 4, 8, 4,
4493 4, 4, 8, 0,
4495 static const UINT sizes2[] =
4497 12, 16, 20, 24,
4498 12, 12, 16, 16,
4500 unsigned int i;
4501 UINT size;
4503 size = D3DXGetDeclVertexSize(NULL, 0);
4504 ok(size == 0, "Got size %#x, expected 0.\n", size);
4506 for (i = 0; i < 16; ++i)
4508 size = D3DXGetDeclVertexSize(declaration1, i);
4509 ok(size == sizes1[i], "Got size %u for stream %u, expected %u.\n", size, i, sizes1[i]);
4512 for (i = 0; i < 8; ++i)
4514 size = D3DXGetDeclVertexSize(declaration2, i);
4515 ok(size == sizes2[i], "Got size %u for stream %u, expected %u.\n", size, i, sizes2[i]);
4519 static void D3DXGenerateAdjacencyTest(void)
4521 HRESULT hr;
4522 IDirect3DDevice9 *device;
4523 ID3DXMesh *d3dxmesh = NULL;
4524 D3DXVECTOR3 *vertices = NULL;
4525 WORD *indices = NULL;
4526 int i;
4527 struct {
4528 DWORD num_vertices;
4529 D3DXVECTOR3 vertices[6];
4530 DWORD num_faces;
4531 WORD indices[3 * 3];
4532 FLOAT epsilon;
4533 DWORD adjacency[3 * 3];
4534 } test_data[] = {
4535 { /* for epsilon < 0, indices must match for faces to be adjacent */
4536 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}},
4537 2, {0, 1, 2, 0, 2, 3},
4538 -1.0,
4539 {-1, -1, 1, 0, -1, -1},
4542 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}},
4543 2, {0, 1, 2, 3, 4, 5},
4544 -1.0,
4545 {-1, -1, -1, -1, -1, -1},
4547 { /* for epsilon == 0, indices or vertices must match for faces to be adjacent */
4548 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}},
4549 2, {0, 1, 2, 3, 4, 5},
4550 0.0,
4551 {-1, -1, 1, 0, -1, -1},
4553 { /* for epsilon > 0, vertices must be less than (but NOT equal to) epsilon distance away */
4554 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}},
4555 2, {0, 1, 2, 3, 4, 5},
4556 0.25,
4557 {-1, -1, -1, -1, -1, -1},
4559 { /* for epsilon > 0, vertices must be less than (but NOT equal to) epsilon distance away */
4560 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}},
4561 2, {0, 1, 2, 3, 4, 5},
4562 0.250001,
4563 {-1, -1, 1, 0, -1, -1},
4565 { /* length between vertices are compared to epsilon, not the individual dimension deltas */
4566 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}},
4567 2, {0, 1, 2, 3, 4, 5},
4568 0.353, /* < sqrt(0.25*0.25 + 0.25*0.25) */
4569 {-1, -1, -1, -1, -1, -1},
4572 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}},
4573 2, {0, 1, 2, 3, 4, 5},
4574 0.354, /* > sqrt(0.25*0.25 + 0.25*0.25) */
4575 {-1, -1, 1, 0, -1, -1},
4577 { /* adjacent faces must have opposite winding orders at the shared edge */
4578 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}},
4579 2, {0, 1, 2, 0, 3, 2},
4580 0.0,
4581 {-1, -1, -1, -1, -1, -1},
4584 struct test_context *test_context;
4586 if (!(test_context = new_test_context()))
4588 skip("Couldn't create test context\n");
4589 return;
4591 device = test_context->device;
4593 for (i = 0; i < ARRAY_SIZE(test_data); i++)
4595 DWORD adjacency[ARRAY_SIZE(test_data[0].adjacency)];
4596 int j;
4598 if (d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh);
4599 d3dxmesh = NULL;
4601 hr = D3DXCreateMeshFVF(test_data[i].num_faces, test_data[i].num_vertices, 0, D3DFVF_XYZ, device, &d3dxmesh);
4602 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
4604 hr = d3dxmesh->lpVtbl->LockVertexBuffer(d3dxmesh, D3DLOCK_DISCARD, (void**)&vertices);
4605 ok(hr == D3D_OK, "test %d: Got result %x, expected %x (D3D_OK)\n", i, hr, D3D_OK);
4606 if (FAILED(hr)) continue;
4607 CopyMemory(vertices, test_data[i].vertices, test_data[i].num_vertices * sizeof(test_data[0].vertices[0]));
4608 d3dxmesh->lpVtbl->UnlockVertexBuffer(d3dxmesh);
4610 hr = d3dxmesh->lpVtbl->LockIndexBuffer(d3dxmesh, D3DLOCK_DISCARD, (void**)&indices);
4611 ok(hr == D3D_OK, "test %d: Got result %x, expected %x (D3D_OK)\n", i, hr, D3D_OK);
4612 if (FAILED(hr)) continue;
4613 CopyMemory(indices, test_data[i].indices, test_data[i].num_faces * 3 * sizeof(test_data[0].indices[0]));
4614 d3dxmesh->lpVtbl->UnlockIndexBuffer(d3dxmesh);
4616 if (i == 0) {
4617 hr = d3dxmesh->lpVtbl->GenerateAdjacency(d3dxmesh, 0.0f, NULL);
4618 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4621 hr = d3dxmesh->lpVtbl->GenerateAdjacency(d3dxmesh, test_data[i].epsilon, adjacency);
4622 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
4623 if (FAILED(hr)) continue;
4625 for (j = 0; j < test_data[i].num_faces * 3; j++)
4626 ok(adjacency[j] == test_data[i].adjacency[j],
4627 "Test %d adjacency %d: Got result %u, expected %u\n", i, j,
4628 adjacency[j], test_data[i].adjacency[j]);
4630 if (d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh);
4632 free_test_context(test_context);
4635 static void test_update_semantics(void)
4637 HRESULT hr;
4638 struct test_context *test_context = NULL;
4639 ID3DXMesh *mesh = NULL;
4640 D3DVERTEXELEMENT9 declaration0[] =
4642 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4643 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4644 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4645 D3DDECL_END()
4647 D3DVERTEXELEMENT9 declaration_pos_type_color[] =
4649 {0, 0, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4650 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4651 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4652 D3DDECL_END()
4654 D3DVERTEXELEMENT9 declaration_smaller[] =
4656 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4657 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4658 D3DDECL_END()
4660 D3DVERTEXELEMENT9 declaration_larger[] =
4662 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4663 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4664 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4665 {0, 40, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT, 0},
4666 D3DDECL_END()
4668 D3DVERTEXELEMENT9 declaration_multiple_streams[] =
4670 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4671 {1, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT, 0},
4672 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4673 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4675 D3DDECL_END()
4677 D3DVERTEXELEMENT9 declaration_double_usage[] =
4679 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4680 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4681 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4682 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4683 D3DDECL_END()
4685 D3DVERTEXELEMENT9 declaration_undefined_type[] =
4687 {0, 0, D3DDECLTYPE_UNUSED+1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4688 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4689 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4690 D3DDECL_END()
4692 D3DVERTEXELEMENT9 declaration_not_4_byte_aligned_offset[] =
4694 {0, 3, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4695 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4696 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4697 D3DDECL_END()
4699 static const struct
4701 D3DXVECTOR3 position0;
4702 D3DXVECTOR3 position1;
4703 D3DXVECTOR3 normal;
4704 DWORD color;
4706 vertices[] =
4708 { { 0.0f, 1.0f, 0.f}, { 1.0f, 0.0f, 0.f}, {0.0f, 0.0f, 1.0f}, 0xffff0000 },
4709 { { 1.0f, -1.0f, 0.f}, {-1.0f, -1.0f, 0.f}, {0.0f, 0.0f, 1.0f}, 0xff00ff00 },
4710 { {-1.0f, -1.0f, 0.f}, {-1.0f, 1.0f, 0.f}, {0.0f, 0.0f, 1.0f}, 0xff0000ff },
4712 unsigned int faces[] = {0, 1, 2};
4713 unsigned int attributes[] = {0};
4714 unsigned int num_faces = ARRAY_SIZE(faces) / 3;
4715 unsigned int num_vertices = ARRAY_SIZE(vertices);
4716 int offset = sizeof(D3DXVECTOR3);
4717 DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
4718 void *vertex_buffer;
4719 void *index_buffer;
4720 DWORD *attributes_buffer;
4721 D3DVERTEXELEMENT9 declaration[MAX_FVF_DECL_SIZE];
4722 D3DVERTEXELEMENT9 *decl_ptr;
4723 DWORD exp_vertex_size = sizeof(*vertices);
4724 DWORD vertex_size = 0;
4725 int equal;
4726 int i = 0;
4727 int *decl_mem;
4728 int filler_a = 0xaaaaaaaa;
4729 int filler_b = 0xbbbbbbbb;
4731 test_context = new_test_context();
4732 if (!test_context)
4734 skip("Couldn't create a test_context\n");
4735 goto cleanup;
4738 hr = D3DXCreateMesh(num_faces, num_vertices, options, declaration0,
4739 test_context->device, &mesh);
4740 if (FAILED(hr))
4742 skip("Couldn't create test mesh %#x\n", hr);
4743 goto cleanup;
4746 mesh->lpVtbl->LockVertexBuffer(mesh, 0, &vertex_buffer);
4747 memcpy(vertex_buffer, vertices, sizeof(vertices));
4748 mesh->lpVtbl->UnlockVertexBuffer(mesh);
4750 mesh->lpVtbl->LockIndexBuffer(mesh, 0, &index_buffer);
4751 memcpy(index_buffer, faces, sizeof(faces));
4752 mesh->lpVtbl->UnlockIndexBuffer(mesh);
4754 mesh->lpVtbl->LockAttributeBuffer(mesh, 0, &attributes_buffer);
4755 memcpy(attributes_buffer, attributes, sizeof(attributes));
4756 mesh->lpVtbl->UnlockAttributeBuffer(mesh);
4758 /* Get the declaration and try to change it */
4759 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4760 if (FAILED(hr))
4762 skip("Couldn't get vertex declaration %#x\n", hr);
4763 goto cleanup;
4765 equal = memcmp(declaration, declaration0, sizeof(declaration0));
4766 ok(equal == 0, "Vertex declarations were not equal\n");
4768 for (decl_ptr = declaration; decl_ptr->Stream != 0xFF; decl_ptr++)
4770 if (decl_ptr->Usage == D3DDECLUSAGE_POSITION)
4772 /* Use second vertex position instead of first */
4773 decl_ptr->Offset = offset;
4777 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration);
4778 ok(hr == D3D_OK, "Test UpdateSemantics, got %#x expected %#x\n", hr, D3D_OK);
4780 /* Check that declaration was written by getting it again */
4781 memset(declaration, 0, sizeof(declaration));
4782 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4783 if (FAILED(hr))
4785 skip("Couldn't get vertex declaration %#x\n", hr);
4786 goto cleanup;
4789 for (decl_ptr = declaration; decl_ptr->Stream != 0xFF; decl_ptr++)
4791 if (decl_ptr->Usage == D3DDECLUSAGE_POSITION)
4793 ok(decl_ptr->Offset == offset, "Test UpdateSemantics, got offset %d expected %d\n",
4794 decl_ptr->Offset, offset);
4798 /* Check that GetDeclaration only writes up to the D3DDECL_END() marker and
4799 * not the full MAX_FVF_DECL_SIZE elements.
4801 memset(declaration, filler_a, sizeof(declaration));
4802 memcpy(declaration, declaration0, sizeof(declaration0));
4803 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration);
4804 ok(hr == D3D_OK, "Test UpdateSemantics, "
4805 "got %#x expected D3D_OK\n", hr);
4806 memset(declaration, filler_b, sizeof(declaration));
4807 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4808 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4809 decl_mem = (int*)declaration;
4810 for (i = sizeof(declaration0)/sizeof(*decl_mem); i < sizeof(declaration)/sizeof(*decl_mem); i++)
4812 equal = memcmp(&decl_mem[i], &filler_b, sizeof(filler_b));
4813 ok(equal == 0,
4814 "GetDeclaration wrote past the D3DDECL_END() marker. "
4815 "Got %#x, expected %#x\n", decl_mem[i], filler_b);
4816 if (equal != 0) break;
4819 /* UpdateSemantics does not check for overlapping fields */
4820 memset(declaration, 0, sizeof(declaration));
4821 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4822 if (FAILED(hr))
4824 skip("Couldn't get vertex declaration %#x\n", hr);
4825 goto cleanup;
4828 for (decl_ptr = declaration; decl_ptr->Stream != 0xFF; decl_ptr++)
4830 if (decl_ptr->Type == D3DDECLTYPE_FLOAT3)
4832 decl_ptr->Type = D3DDECLTYPE_FLOAT4;
4836 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration);
4837 ok(hr == D3D_OK, "Test UpdateSemantics for overlapping fields, "
4838 "got %#x expected D3D_OK\n", hr);
4840 /* Set the position type to color instead of float3 */
4841 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_pos_type_color);
4842 ok(hr == D3D_OK, "Test UpdateSemantics position type color, "
4843 "got %#x expected D3D_OK\n", hr);
4845 /* The following test cases show that NULL, smaller or larger declarations,
4846 * and declarations with non-zero Stream values are not accepted.
4847 * UpdateSemantics returns D3DERR_INVALIDCALL and the previously set
4848 * declaration will be used by DrawSubset, GetNumBytesPerVertex, and
4849 * GetDeclaration.
4852 /* Null declaration (invalid declaration) */
4853 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4854 hr = mesh->lpVtbl->UpdateSemantics(mesh, NULL);
4855 ok(hr == D3DERR_INVALIDCALL, "Test UpdateSemantics null pointer declaration, "
4856 "got %#x expected D3DERR_INVALIDCALL\n", hr);
4857 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4858 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4859 vertex_size, exp_vertex_size);
4860 memset(declaration, 0, sizeof(declaration));
4861 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4862 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4863 equal = memcmp(declaration, declaration0, sizeof(declaration0));
4864 ok(equal == 0, "Vertex declarations were not equal\n");
4866 /* Smaller vertex declaration (invalid declaration) */
4867 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4868 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_smaller);
4869 ok(hr == D3DERR_INVALIDCALL, "Test UpdateSemantics for smaller vertex declaration, "
4870 "got %#x expected D3DERR_INVALIDCALL\n", hr);
4871 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4872 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4873 vertex_size, exp_vertex_size);
4874 memset(declaration, 0, sizeof(declaration));
4875 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4876 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4877 equal = memcmp(declaration, declaration0, sizeof(declaration0));
4878 ok(equal == 0, "Vertex declarations were not equal\n");
4880 /* Larger vertex declaration (invalid declaration) */
4881 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4882 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_larger);
4883 ok(hr == D3DERR_INVALIDCALL, "Test UpdateSemantics for larger vertex declaration, "
4884 "got %#x expected D3DERR_INVALIDCALL\n", hr);
4885 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4886 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4887 vertex_size, exp_vertex_size);
4888 memset(declaration, 0, sizeof(declaration));
4889 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4890 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4891 equal = memcmp(declaration, declaration0, sizeof(declaration0));
4892 ok(equal == 0, "Vertex declarations were not equal\n");
4894 /* Use multiple streams and keep the same vertex size (invalid declaration) */
4895 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4896 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_multiple_streams);
4897 ok(hr == D3DERR_INVALIDCALL, "Test UpdateSemantics using multiple streams, "
4898 "got %#x expected D3DERR_INVALIDCALL\n", hr);
4899 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4900 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4901 vertex_size, exp_vertex_size);
4902 memset(declaration, 0, sizeof(declaration));
4903 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4904 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4905 equal = memcmp(declaration, declaration0, sizeof(declaration0));
4906 ok(equal == 0, "Vertex declarations were not equal\n");
4908 /* The next following test cases show that some invalid declarations are
4909 * accepted with a D3D_OK. An access violation is thrown on Windows if
4910 * DrawSubset is called. The methods GetNumBytesPerVertex and GetDeclaration
4911 * are not affected, which indicates that the declaration is cached.
4914 /* Double usage (invalid declaration) */
4915 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4916 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_double_usage);
4917 ok(hr == D3D_OK, "Test UpdateSemantics double usage, "
4918 "got %#x expected D3D_OK\n", hr);
4919 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4920 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4921 vertex_size, exp_vertex_size);
4922 memset(declaration, 0, sizeof(declaration));
4923 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4924 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4925 equal = memcmp(declaration, declaration_double_usage, sizeof(declaration_double_usage));
4926 ok(equal == 0, "Vertex declarations were not equal\n");
4928 /* Set the position to an undefined type (invalid declaration) */
4929 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4930 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_undefined_type);
4931 ok(hr == D3D_OK, "Test UpdateSemantics undefined type, "
4932 "got %#x expected D3D_OK\n", hr);
4933 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4934 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4935 vertex_size, exp_vertex_size);
4936 memset(declaration, 0, sizeof(declaration));
4937 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4938 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4939 equal = memcmp(declaration, declaration_undefined_type, sizeof(declaration_undefined_type));
4940 ok(equal == 0, "Vertex declarations were not equal\n");
4942 /* Use a not 4 byte aligned offset (invalid declaration) */
4943 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4944 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_not_4_byte_aligned_offset);
4945 ok(hr == D3D_OK, "Test UpdateSemantics not 4 byte aligned offset, "
4946 "got %#x expected D3D_OK\n", hr);
4947 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4948 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4949 vertex_size, exp_vertex_size);
4950 memset(declaration, 0, sizeof(declaration));
4951 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4952 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4953 equal = memcmp(declaration, declaration_not_4_byte_aligned_offset,
4954 sizeof(declaration_not_4_byte_aligned_offset));
4955 ok(equal == 0, "Vertex declarations were not equal\n");
4957 cleanup:
4958 if (mesh)
4959 mesh->lpVtbl->Release(mesh);
4961 free_test_context(test_context);
4964 static void test_create_skin_info(void)
4966 HRESULT hr;
4967 ID3DXSkinInfo *skininfo = NULL;
4968 D3DVERTEXELEMENT9 empty_declaration[] = { D3DDECL_END() };
4969 D3DVERTEXELEMENT9 declaration_out[MAX_FVF_DECL_SIZE];
4970 const D3DVERTEXELEMENT9 declaration_with_nonzero_stream[] = {
4971 {1, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
4972 D3DDECL_END()
4975 hr = D3DXCreateSkinInfo(0, empty_declaration, 0, &skininfo);
4976 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4977 if (skininfo) IUnknown_Release(skininfo);
4978 skininfo = NULL;
4980 hr = D3DXCreateSkinInfo(1, NULL, 1, &skininfo);
4981 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4983 hr = D3DXCreateSkinInfo(1, declaration_with_nonzero_stream, 1, &skininfo);
4984 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4986 hr = D3DXCreateSkinInfoFVF(1, 0, 1, &skininfo);
4987 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4988 if (skininfo)
4990 DWORD dword_result;
4991 float flt_result;
4992 const char *string_result;
4993 D3DXMATRIX *transform;
4994 D3DXMATRIX identity_matrix;
4996 /* test initial values */
4997 hr = skininfo->lpVtbl->GetDeclaration(skininfo, declaration_out);
4998 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4999 if (SUCCEEDED(hr))
5000 compare_elements(declaration_out, empty_declaration, __LINE__, 0);
5002 dword_result = skininfo->lpVtbl->GetNumBones(skininfo);
5003 ok(dword_result == 1, "Expected 1, got %u\n", dword_result);
5005 flt_result = skininfo->lpVtbl->GetMinBoneInfluence(skininfo);
5006 ok(flt_result == 0.0f, "Expected 0.0, got %g\n", flt_result);
5008 string_result = skininfo->lpVtbl->GetBoneName(skininfo, 0);
5009 ok(string_result == NULL, "Expected NULL, got %p\n", string_result);
5011 dword_result = skininfo->lpVtbl->GetFVF(skininfo);
5012 ok(dword_result == 0, "Expected 0, got %u\n", dword_result);
5014 dword_result = skininfo->lpVtbl->GetNumBoneInfluences(skininfo, 0);
5015 ok(dword_result == 0, "Expected 0, got %u\n", dword_result);
5017 dword_result = skininfo->lpVtbl->GetNumBoneInfluences(skininfo, 1);
5018 ok(dword_result == 0, "Expected 0, got %u\n", dword_result);
5020 transform = skininfo->lpVtbl->GetBoneOffsetMatrix(skininfo, -1);
5021 ok(transform == NULL, "Expected NULL, got %p\n", transform);
5024 /* test [GS]etBoneOffsetMatrix */
5025 hr = skininfo->lpVtbl->SetBoneOffsetMatrix(skininfo, 1, &identity_matrix);
5026 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5028 hr = skininfo->lpVtbl->SetBoneOffsetMatrix(skininfo, 0, NULL);
5029 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5031 D3DXMatrixIdentity(&identity_matrix);
5032 hr = skininfo->lpVtbl->SetBoneOffsetMatrix(skininfo, 0, &identity_matrix);
5033 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5035 transform = skininfo->lpVtbl->GetBoneOffsetMatrix(skininfo, 0);
5036 check_matrix(transform, &identity_matrix);
5040 /* test [GS]etBoneName */
5041 const char *name_in = "testBoneName";
5042 const char *string_result2;
5044 hr = skininfo->lpVtbl->SetBoneName(skininfo, 1, name_in);
5045 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5047 hr = skininfo->lpVtbl->SetBoneName(skininfo, 0, NULL);
5048 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5050 hr = skininfo->lpVtbl->SetBoneName(skininfo, 0, name_in);
5051 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5053 string_result = skininfo->lpVtbl->GetBoneName(skininfo, 0);
5054 ok(string_result != NULL, "Expected non-NULL string, got %p\n", string_result);
5055 ok(!strcmp(string_result, name_in), "Expected '%s', got '%s'\n", name_in, string_result);
5057 string_result2 = skininfo->lpVtbl->GetBoneName(skininfo, 0);
5058 ok(string_result == string_result2, "Expected %p, got %p\n", string_result, string_result2);
5060 string_result = skininfo->lpVtbl->GetBoneName(skininfo, 1);
5061 ok(string_result == NULL, "Expected NULL, got %p\n", string_result);
5065 /* test [GS]etBoneInfluence */
5066 DWORD vertices[2];
5067 FLOAT weights[2];
5068 int i;
5069 DWORD num_influences;
5070 DWORD exp_vertices[2];
5071 FLOAT exp_weights[2];
5073 /* vertex and weight arrays untouched when num_influences is 0 */
5074 vertices[0] = 0xdeadbeef;
5075 weights[0] = FLT_MAX;
5076 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, vertices, weights);
5077 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5078 ok(vertices[0] == 0xdeadbeef, "expected 0xdeadbeef, got %#x\n", vertices[0]);
5079 ok(weights[0] == FLT_MAX, "expected %g, got %g\n", FLT_MAX, weights[0]);
5081 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 1, vertices, weights);
5082 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5084 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, NULL, NULL);
5085 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5087 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, vertices, NULL);
5088 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5090 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, NULL, weights);
5091 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5094 /* no vertex or weight value checking */
5095 exp_vertices[0] = 0;
5096 exp_vertices[1] = 0x87654321;
5097 exp_weights[0] = 0.5;
5098 exp_weights[1] = NAN;
5099 num_influences = 2;
5101 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 1, num_influences, vertices, weights);
5102 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5104 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, num_influences, NULL, weights);
5105 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5107 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, num_influences, vertices, NULL);
5108 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5110 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, num_influences, NULL, NULL);
5111 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5113 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, num_influences, exp_vertices, exp_weights);
5114 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5116 memset(vertices, 0, sizeof(vertices));
5117 memset(weights, 0, sizeof(weights));
5118 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, vertices, weights);
5119 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5120 for (i = 0; i < num_influences; i++) {
5121 ok(exp_vertices[i] == vertices[i],
5122 "influence[%d]: expected vertex %u, got %u\n", i, exp_vertices[i], vertices[i]);
5123 ok((isnan(exp_weights[i]) && isnan(weights[i])) || exp_weights[i] == weights[i],
5124 "influence[%d]: expected weights %g, got %g\n", i, exp_weights[i], weights[i]);
5127 /* vertices and weights aren't returned after setting num_influences to 0 */
5128 memset(vertices, 0, sizeof(vertices));
5129 memset(weights, 0, sizeof(weights));
5130 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, 0, vertices, weights);
5131 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5133 vertices[0] = 0xdeadbeef;
5134 weights[0] = FLT_MAX;
5135 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, vertices, weights);
5136 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5137 ok(vertices[0] == 0xdeadbeef, "expected vertex 0xdeadbeef, got %u\n", vertices[0]);
5138 ok(weights[0] == FLT_MAX, "expected weight %g, got %g\n", FLT_MAX, weights[0]);
5142 /* test [GS]etFVF and [GS]etDeclaration */
5143 D3DVERTEXELEMENT9 declaration_in[MAX_FVF_DECL_SIZE];
5144 DWORD fvf = D3DFVF_XYZ;
5145 DWORD got_fvf;
5147 hr = skininfo->lpVtbl->SetDeclaration(skininfo, NULL);
5148 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5150 hr = skininfo->lpVtbl->SetDeclaration(skininfo, declaration_with_nonzero_stream);
5151 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5153 hr = skininfo->lpVtbl->SetFVF(skininfo, 0);
5154 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5156 hr = D3DXDeclaratorFromFVF(fvf, declaration_in);
5157 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5158 hr = skininfo->lpVtbl->SetDeclaration(skininfo, declaration_in);
5159 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5160 got_fvf = skininfo->lpVtbl->GetFVF(skininfo);
5161 ok(fvf == got_fvf, "Expected %#x, got %#x\n", fvf, got_fvf);
5162 hr = skininfo->lpVtbl->GetDeclaration(skininfo, declaration_out);
5163 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5164 compare_elements(declaration_out, declaration_in, __LINE__, 0);
5166 hr = skininfo->lpVtbl->SetDeclaration(skininfo, empty_declaration);
5167 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5168 got_fvf = skininfo->lpVtbl->GetFVF(skininfo);
5169 ok(got_fvf == 0, "Expected 0, got %#x\n", got_fvf);
5170 hr = skininfo->lpVtbl->GetDeclaration(skininfo, declaration_out);
5171 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5172 compare_elements(declaration_out, empty_declaration, __LINE__, 0);
5174 hr = skininfo->lpVtbl->SetFVF(skininfo, fvf);
5175 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5176 got_fvf = skininfo->lpVtbl->GetFVF(skininfo);
5177 ok(fvf == got_fvf, "Expected %#x, got %#x\n", fvf, got_fvf);
5178 hr = skininfo->lpVtbl->GetDeclaration(skininfo, declaration_out);
5179 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5180 compare_elements(declaration_out, declaration_in, __LINE__, 0);
5183 if (skininfo) IUnknown_Release(skininfo);
5184 skininfo = NULL;
5186 hr = D3DXCreateSkinInfoFVF(1, D3DFVF_XYZ, 1, NULL);
5187 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5189 hr = D3DXCreateSkinInfo(1, NULL, 1, &skininfo);
5190 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5193 static void test_convert_adjacency_to_point_reps(void)
5195 HRESULT hr;
5196 struct test_context *test_context = NULL;
5197 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
5198 const DWORD options_16bit = D3DXMESH_SYSTEMMEM;
5199 const D3DVERTEXELEMENT9 declaration[] =
5201 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
5202 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
5203 {0, 24, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
5204 D3DDECL_END()
5206 const unsigned int VERTS_PER_FACE = 3;
5207 void *vertex_buffer;
5208 void *index_buffer;
5209 DWORD *attributes_buffer;
5210 int i, j;
5211 enum color { RED = 0xffff0000, GREEN = 0xff00ff00, BLUE = 0xff0000ff};
5212 struct vertex_pnc
5214 D3DXVECTOR3 position;
5215 D3DXVECTOR3 normal;
5216 enum color color; /* In case of manual visual inspection */
5218 D3DXVECTOR3 up = {0.0f, 0.0f, 1.0f};
5219 /* mesh0 (one face)
5221 * 0--1
5222 * | /
5223 * |/
5226 const struct vertex_pnc vertices0[] =
5228 {{ 0.0f, 3.0f, 0.f}, up, RED},
5229 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5230 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5232 const DWORD indices0[] = {0, 1, 2};
5233 const unsigned int num_vertices0 = ARRAY_SIZE(vertices0);
5234 const unsigned int num_faces0 = ARRAY_SIZE(indices0) / VERTS_PER_FACE;
5235 const DWORD adjacency0[] = {-1, -1, -1};
5236 const DWORD exp_point_rep0[] = {0, 1, 2};
5237 /* mesh1 (right)
5239 * 0--1 3
5240 * | / /|
5241 * |/ / |
5242 * 2 5--4
5244 const struct vertex_pnc vertices1[] =
5246 {{ 0.0f, 3.0f, 0.f}, up, RED},
5247 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5248 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5250 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5251 {{ 3.0f, 0.0f, 0.f}, up, RED},
5252 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5254 const DWORD indices1[] = {0, 1, 2, 3, 4, 5};
5255 const unsigned int num_vertices1 = ARRAY_SIZE(vertices1);
5256 const unsigned int num_faces1 = ARRAY_SIZE(indices1) / VERTS_PER_FACE;
5257 const DWORD adjacency1[] = {-1, 1, -1, -1, -1, 0};
5258 const DWORD exp_point_rep1[] = {0, 1, 2, 1, 4, 2};
5259 /* mesh2 (left)
5261 * 3 0--1
5262 * /| | /
5263 * / | |/
5264 * 5--4 2
5266 const struct vertex_pnc vertices2[] =
5268 {{ 0.0f, 3.0f, 0.f}, up, RED},
5269 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5270 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5272 {{-1.0f, 3.0f, 0.f}, up, RED},
5273 {{-1.0f, 0.0f, 0.f}, up, GREEN},
5274 {{-3.0f, 0.0f, 0.f}, up, BLUE},
5276 const DWORD indices2[] = {0, 1, 2, 3, 4, 5};
5277 const unsigned int num_vertices2 = ARRAY_SIZE(vertices2);
5278 const unsigned int num_faces2 = ARRAY_SIZE(indices2) / VERTS_PER_FACE;
5279 const DWORD adjacency2[] = {-1, -1, 1, 0, -1, -1};
5280 const DWORD exp_point_rep2[] = {0, 1, 2, 0, 2, 5};
5281 /* mesh3 (above)
5284 * /|
5285 * / |
5286 * 5--4
5287 * 0--1
5288 * | /
5289 * |/
5292 struct vertex_pnc vertices3[] =
5294 {{ 0.0f, 3.0f, 0.f}, up, RED},
5295 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5296 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5298 {{ 2.0f, 7.0f, 0.f}, up, BLUE},
5299 {{ 2.0f, 4.0f, 0.f}, up, GREEN},
5300 {{ 0.0f, 4.0f, 0.f}, up, RED},
5302 const DWORD indices3[] = {0, 1, 2, 3, 4, 5};
5303 const unsigned int num_vertices3 = ARRAY_SIZE(vertices3);
5304 const unsigned int num_faces3 = ARRAY_SIZE(indices3) / VERTS_PER_FACE;
5305 const DWORD adjacency3[] = {1, -1, -1, -1, 0, -1};
5306 const DWORD exp_point_rep3[] = {0, 1, 2, 3, 1, 0};
5307 /* mesh4 (below, tip against tip)
5309 * 0--1
5310 * | /
5311 * |/
5314 * |\
5315 * | \
5316 * 5--4
5318 struct vertex_pnc vertices4[] =
5320 {{ 0.0f, 3.0f, 0.f}, up, RED},
5321 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5322 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5324 {{ 0.0f, -4.0f, 0.f}, up, BLUE},
5325 {{ 2.0f, -7.0f, 0.f}, up, GREEN},
5326 {{ 0.0f, -7.0f, 0.f}, up, RED},
5328 const DWORD indices4[] = {0, 1, 2, 3, 4, 5};
5329 const unsigned int num_vertices4 = ARRAY_SIZE(vertices4);
5330 const unsigned int num_faces4 = ARRAY_SIZE(indices4) / VERTS_PER_FACE;
5331 const DWORD adjacency4[] = {-1, -1, -1, -1, -1, -1};
5332 const DWORD exp_point_rep4[] = {0, 1, 2, 3, 4, 5};
5333 /* mesh5 (gap in mesh)
5335 * 0 3-----4 15
5336 * / \ \ / / \
5337 * / \ \ / / \
5338 * 2-----1 5 17-----16
5339 * 6-----7 9 12-----13
5340 * \ / / \ \ /
5341 * \ / / \ \ /
5342 * 8 10-----11 14
5345 const struct vertex_pnc vertices5[] =
5347 {{ 0.0f, 1.0f, 0.f}, up, RED},
5348 {{ 1.0f, -1.0f, 0.f}, up, GREEN},
5349 {{-1.0f, -1.0f, 0.f}, up, BLUE},
5351 {{ 0.1f, 1.0f, 0.f}, up, RED},
5352 {{ 2.1f, 1.0f, 0.f}, up, BLUE},
5353 {{ 1.1f, -1.0f, 0.f}, up, GREEN},
5355 {{-1.0f, -1.1f, 0.f}, up, BLUE},
5356 {{ 1.0f, -1.1f, 0.f}, up, GREEN},
5357 {{ 0.0f, -3.1f, 0.f}, up, RED},
5359 {{ 1.1f, -1.1f, 0.f}, up, GREEN},
5360 {{ 2.1f, -3.1f, 0.f}, up, BLUE},
5361 {{ 0.1f, -3.1f, 0.f}, up, RED},
5363 {{ 1.2f, -1.1f, 0.f}, up, GREEN},
5364 {{ 3.2f, -1.1f, 0.f}, up, RED},
5365 {{ 2.2f, -3.1f, 0.f}, up, BLUE},
5367 {{ 2.2f, 1.0f, 0.f}, up, BLUE},
5368 {{ 3.2f, -1.0f, 0.f}, up, RED},
5369 {{ 1.2f, -1.0f, 0.f}, up, GREEN},
5371 const DWORD indices5[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17};
5372 const unsigned int num_vertices5 = ARRAY_SIZE(vertices5);
5373 const unsigned int num_faces5 = ARRAY_SIZE(indices5) / VERTS_PER_FACE;
5374 const DWORD adjacency5[] = {-1, 2, -1, -1, 5, -1, 0, -1, -1, 4, -1, -1, 5, -1, 3, -1, 4, 1};
5375 const DWORD exp_point_rep5[] = {0, 1, 2, 3, 4, 5, 2, 1, 8, 5, 10, 11, 5, 13, 10, 4, 13, 5};
5376 const WORD indices5_16bit[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17};
5377 /* mesh6 (indices re-ordering)
5379 * 0--1 6 3
5380 * | / /| |\
5381 * |/ / | | \
5382 * 2 8--7 5--4
5384 const struct vertex_pnc vertices6[] =
5386 {{ 0.0f, 3.0f, 0.f}, up, RED},
5387 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5388 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5390 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5391 {{ 3.0f, 0.0f, 0.f}, up, RED},
5392 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5394 {{ 4.0f, 3.0f, 0.f}, up, GREEN},
5395 {{ 6.0f, 0.0f, 0.f}, up, BLUE},
5396 {{ 4.0f, 0.0f, 0.f}, up, RED},
5398 const DWORD indices6[] = {0, 1, 2, 6, 7, 8, 3, 4, 5};
5399 const unsigned int num_vertices6 = ARRAY_SIZE(vertices6);
5400 const unsigned int num_faces6 = ARRAY_SIZE(indices6) / VERTS_PER_FACE;
5401 const DWORD adjacency6[] = {-1, 1, -1, 2, -1, 0, -1, -1, 1};
5402 const DWORD exp_point_rep6[] = {0, 1, 2, 1, 4, 5, 1, 5, 2};
5403 /* mesh7 (expands collapsed triangle)
5405 * 0--1 3
5406 * | / /|
5407 * |/ / |
5408 * 2 5--4
5410 const struct vertex_pnc vertices7[] =
5412 {{ 0.0f, 3.0f, 0.f}, up, RED},
5413 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5414 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5416 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5417 {{ 3.0f, 0.0f, 0.f}, up, RED},
5418 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5420 const DWORD indices7[] = {0, 1, 2, 3, 3, 3}; /* Face 1 is collapsed*/
5421 const unsigned int num_vertices7 = ARRAY_SIZE(vertices7);
5422 const unsigned int num_faces7 = ARRAY_SIZE(indices7) / VERTS_PER_FACE;
5423 const DWORD adjacency7[] = {-1, -1, -1, -1, -1, -1};
5424 const DWORD exp_point_rep7[] = {0, 1, 2, 3, 4, 5};
5425 /* mesh8 (indices re-ordering and double replacement)
5427 * 0--1 9 6
5428 * | / /| |\
5429 * |/ / | | \
5430 * 2 11-10 8--7
5431 * 3--4
5432 * | /
5433 * |/
5436 const struct vertex_pnc vertices8[] =
5438 {{ 0.0f, 3.0f, 0.f}, up, RED},
5439 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5440 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5442 {{ 4.0, -4.0, 0.f}, up, RED},
5443 {{ 6.0, -4.0, 0.f}, up, BLUE},
5444 {{ 4.0, -7.0, 0.f}, up, GREEN},
5446 {{ 4.0f, 3.0f, 0.f}, up, GREEN},
5447 {{ 6.0f, 0.0f, 0.f}, up, BLUE},
5448 {{ 4.0f, 0.0f, 0.f}, up, RED},
5450 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5451 {{ 3.0f, 0.0f, 0.f}, up, RED},
5452 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5454 const DWORD indices8[] = {0, 1, 2, 9, 10, 11, 6, 7, 8, 3, 4, 5};
5455 const unsigned int num_vertices8 = ARRAY_SIZE(vertices8);
5456 const unsigned int num_faces8 = ARRAY_SIZE(indices8) / VERTS_PER_FACE;
5457 const DWORD adjacency8[] = {-1, 1, -1, 2, -1, 0, -1, 3, 1, 2, -1, -1};
5458 const DWORD exp_point_rep8[] = {0, 1, 2, 3, 4, 5, 1, 4, 3, 1, 3, 2};
5459 /* mesh9 (right, shared vertices)
5461 * 0--1
5462 * | /|
5463 * |/ |
5464 * 2--3
5466 const struct vertex_pnc vertices9[] =
5468 {{ 0.0f, 3.0f, 0.f}, up, RED},
5469 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5470 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5472 {{ 2.0f, 0.0f, 0.f}, up, RED},
5474 const DWORD indices9[] = {0, 1, 2, 1, 3, 2};
5475 const unsigned int num_vertices9 = ARRAY_SIZE(vertices9);
5476 const unsigned int num_faces9 = ARRAY_SIZE(indices9) / VERTS_PER_FACE;
5477 const DWORD adjacency9[] = {-1, 1, -1, -1, -1, 0};
5478 const DWORD exp_point_rep9[] = {0, 1, 2, 3};
5479 /* All mesh data */
5480 ID3DXMesh *mesh = NULL;
5481 ID3DXMesh *mesh_null_check = NULL;
5482 unsigned int attributes[] = {0};
5483 struct
5485 const struct vertex_pnc *vertices;
5486 const DWORD *indices;
5487 const DWORD num_vertices;
5488 const DWORD num_faces;
5489 const DWORD *adjacency;
5490 const DWORD *exp_point_reps;
5491 const DWORD options;
5493 tc[] =
5496 vertices0,
5497 indices0,
5498 num_vertices0,
5499 num_faces0,
5500 adjacency0,
5501 exp_point_rep0,
5502 options
5505 vertices1,
5506 indices1,
5507 num_vertices1,
5508 num_faces1,
5509 adjacency1,
5510 exp_point_rep1,
5511 options
5514 vertices2,
5515 indices2,
5516 num_vertices2,
5517 num_faces2,
5518 adjacency2,
5519 exp_point_rep2,
5520 options
5523 vertices3,
5524 indices3,
5525 num_vertices3,
5526 num_faces3,
5527 adjacency3,
5528 exp_point_rep3,
5529 options
5532 vertices4,
5533 indices4,
5534 num_vertices4,
5535 num_faces4,
5536 adjacency4,
5537 exp_point_rep4,
5538 options
5541 vertices5,
5542 indices5,
5543 num_vertices5,
5544 num_faces5,
5545 adjacency5,
5546 exp_point_rep5,
5547 options
5550 vertices6,
5551 indices6,
5552 num_vertices6,
5553 num_faces6,
5554 adjacency6,
5555 exp_point_rep6,
5556 options
5559 vertices7,
5560 indices7,
5561 num_vertices7,
5562 num_faces7,
5563 adjacency7,
5564 exp_point_rep7,
5565 options
5568 vertices8,
5569 indices8,
5570 num_vertices8,
5571 num_faces8,
5572 adjacency8,
5573 exp_point_rep8,
5574 options
5577 vertices9,
5578 indices9,
5579 num_vertices9,
5580 num_faces9,
5581 adjacency9,
5582 exp_point_rep9,
5583 options
5586 vertices5,
5587 (DWORD*)indices5_16bit,
5588 num_vertices5,
5589 num_faces5,
5590 adjacency5,
5591 exp_point_rep5,
5592 options_16bit
5595 DWORD *point_reps = NULL;
5597 test_context = new_test_context();
5598 if (!test_context)
5600 skip("Couldn't create test context\n");
5601 goto cleanup;
5604 for (i = 0; i < ARRAY_SIZE(tc); i++)
5606 hr = D3DXCreateMesh(tc[i].num_faces, tc[i].num_vertices, tc[i].options, declaration,
5607 test_context->device, &mesh);
5608 if (FAILED(hr))
5610 skip("Couldn't create mesh %d. Got %x expected D3D_OK\n", i, hr);
5611 goto cleanup;
5614 if (i == 0) /* Save first mesh for later NULL checks */
5615 mesh_null_check = mesh;
5617 point_reps = HeapAlloc(GetProcessHeap(), 0, tc[i].num_vertices * sizeof(*point_reps));
5618 if (!point_reps)
5620 skip("Couldn't allocate point reps array.\n");
5621 goto cleanup;
5624 hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, &vertex_buffer);
5625 if (FAILED(hr))
5627 skip("Couldn't lock vertex buffer.\n");
5628 goto cleanup;
5630 memcpy(vertex_buffer, tc[i].vertices, tc[i].num_vertices * sizeof(*tc[i].vertices));
5631 hr = mesh->lpVtbl->UnlockVertexBuffer(mesh);
5632 if (FAILED(hr))
5634 skip("Couldn't unlock vertex buffer.\n");
5635 goto cleanup;
5638 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, &index_buffer);
5639 if (FAILED(hr))
5641 skip("Couldn't lock index buffer.\n");
5642 goto cleanup;
5644 if (tc[i].options & D3DXMESH_32BIT)
5646 memcpy(index_buffer, tc[i].indices, VERTS_PER_FACE * tc[i].num_faces * sizeof(DWORD));
5648 else
5650 memcpy(index_buffer, tc[i].indices, VERTS_PER_FACE * tc[i].num_faces * sizeof(WORD));
5652 hr = mesh->lpVtbl->UnlockIndexBuffer(mesh);
5653 if (FAILED(hr)) {
5654 skip("Couldn't unlock index buffer.\n");
5655 goto cleanup;
5658 hr = mesh->lpVtbl->LockAttributeBuffer(mesh, 0, &attributes_buffer);
5659 if (FAILED(hr))
5661 skip("Couldn't lock attributes buffer.\n");
5662 goto cleanup;
5664 memcpy(attributes_buffer, attributes, sizeof(attributes));
5665 hr = mesh->lpVtbl->UnlockAttributeBuffer(mesh);
5666 if (FAILED(hr))
5668 skip("Couldn't unlock attributes buffer.\n");
5669 goto cleanup;
5672 /* Convert adjacency to point representation */
5673 for (j = 0; j < tc[i].num_vertices; j++) point_reps[j] = -1;
5674 hr = mesh->lpVtbl->ConvertAdjacencyToPointReps(mesh, tc[i].adjacency, point_reps);
5675 ok(hr == D3D_OK, "ConvertAdjacencyToPointReps failed case %d. "
5676 "Got %x expected D3D_OK\n", i, hr);
5678 /* Check point representation */
5679 for (j = 0; j < tc[i].num_vertices; j++)
5681 ok(point_reps[j] == tc[i].exp_point_reps[j],
5682 "Unexpected point representation at (%d, %d)."
5683 " Got %d expected %d\n",
5684 i, j, point_reps[j], tc[i].exp_point_reps[j]);
5687 HeapFree(GetProcessHeap(), 0, point_reps);
5688 point_reps = NULL;
5690 if (i != 0) /* First mesh will be freed during cleanup */
5691 mesh->lpVtbl->Release(mesh);
5694 /* NULL checks */
5695 hr = mesh_null_check->lpVtbl->ConvertAdjacencyToPointReps(mesh_null_check, tc[0].adjacency, NULL);
5696 ok(hr == D3DERR_INVALIDCALL, "ConvertAdjacencyToPointReps point_reps NULL. "
5697 "Got %x expected D3DERR_INVALIDCALL\n", hr);
5698 hr = mesh_null_check->lpVtbl->ConvertAdjacencyToPointReps(mesh_null_check, NULL, NULL);
5699 ok(hr == D3DERR_INVALIDCALL, "ConvertAdjacencyToPointReps adjacency and point_reps NULL. "
5700 "Got %x expected D3DERR_INVALIDCALL\n", hr);
5702 cleanup:
5703 if (mesh_null_check)
5704 mesh_null_check->lpVtbl->Release(mesh_null_check);
5705 HeapFree(GetProcessHeap(), 0, point_reps);
5706 free_test_context(test_context);
5709 static void test_convert_point_reps_to_adjacency(void)
5711 HRESULT hr;
5712 struct test_context *test_context = NULL;
5713 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
5714 const DWORD options_16bit = D3DXMESH_SYSTEMMEM;
5715 const D3DVERTEXELEMENT9 declaration[] =
5717 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
5718 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
5719 {0, 24, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
5720 D3DDECL_END()
5722 const unsigned int VERTS_PER_FACE = 3;
5723 void *vertex_buffer;
5724 void *index_buffer;
5725 DWORD *attributes_buffer;
5726 int i, j;
5727 enum color { RED = 0xffff0000, GREEN = 0xff00ff00, BLUE = 0xff0000ff};
5728 struct vertex_pnc
5730 D3DXVECTOR3 position;
5731 D3DXVECTOR3 normal;
5732 enum color color; /* In case of manual visual inspection */
5734 D3DXVECTOR3 up = {0.0f, 0.0f, 1.0f};
5735 /* mesh0 (one face)
5737 * 0--1
5738 * | /
5739 * |/
5742 const struct vertex_pnc vertices0[] =
5744 {{ 0.0f, 3.0f, 0.f}, up, RED},
5745 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5746 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5748 const DWORD indices0[] = {0, 1, 2};
5749 const unsigned int num_vertices0 = ARRAY_SIZE(vertices0);
5750 const unsigned int num_faces0 = num_vertices0 / VERTS_PER_FACE;
5751 const DWORD exp_adjacency0[] = {-1, -1, -1};
5752 const DWORD exp_id_adjacency0[] = {-1, -1, -1};
5753 const DWORD point_rep0[] = {0, 1, 2};
5754 /* mesh1 (right)
5756 * 0--1 3
5757 * | / /|
5758 * |/ / |
5759 * 2 5--4
5761 const struct vertex_pnc vertices1[] =
5763 {{ 0.0f, 3.0f, 0.f}, up, RED},
5764 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5765 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5767 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5768 {{ 3.0f, 0.0f, 0.f}, up, RED},
5769 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5771 const DWORD indices1[] = {0, 1, 2, 3, 4, 5};
5772 const unsigned int num_vertices1 = ARRAY_SIZE(vertices1);
5773 const unsigned int num_faces1 = num_vertices1 / VERTS_PER_FACE;
5774 const DWORD exp_adjacency1[] = {-1, 1, -1, -1, -1, 0};
5775 const DWORD exp_id_adjacency1[] = {-1, -1, -1, -1, -1, -1};
5776 const DWORD point_rep1[] = {0, 1, 2, 1, 4, 2};
5777 /* mesh2 (left)
5779 * 3 0--1
5780 * /| | /
5781 * / | |/
5782 * 5--4 2
5784 const struct vertex_pnc vertices2[] =
5786 {{ 0.0f, 3.0f, 0.f}, up, RED},
5787 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5788 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5790 {{-1.0f, 3.0f, 0.f}, up, RED},
5791 {{-1.0f, 0.0f, 0.f}, up, GREEN},
5792 {{-3.0f, 0.0f, 0.f}, up, BLUE},
5794 const DWORD indices2[] = {0, 1, 2, 3, 4, 5};
5795 const unsigned int num_vertices2 = ARRAY_SIZE(vertices2);
5796 const unsigned int num_faces2 = num_vertices2 / VERTS_PER_FACE;
5797 const DWORD exp_adjacency2[] = {-1, -1, 1, 0, -1, -1};
5798 const DWORD exp_id_adjacency2[] = {-1, -1, -1, -1, -1, -1};
5799 const DWORD point_rep2[] = {0, 1, 2, 0, 2, 5};
5800 /* mesh3 (above)
5803 * /|
5804 * / |
5805 * 5--4
5806 * 0--1
5807 * | /
5808 * |/
5811 struct vertex_pnc vertices3[] =
5813 {{ 0.0f, 3.0f, 0.f}, up, RED},
5814 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5815 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5817 {{ 2.0f, 7.0f, 0.f}, up, BLUE},
5818 {{ 2.0f, 4.0f, 0.f}, up, GREEN},
5819 {{ 0.0f, 4.0f, 0.f}, up, RED},
5821 const DWORD indices3[] = {0, 1, 2, 3, 4, 5};
5822 const unsigned int num_vertices3 = ARRAY_SIZE(vertices3);
5823 const unsigned int num_faces3 = num_vertices3 / VERTS_PER_FACE;
5824 const DWORD exp_adjacency3[] = {1, -1, -1, -1, 0, -1};
5825 const DWORD exp_id_adjacency3[] = {-1, -1, -1, -1, -1, -1};
5826 const DWORD point_rep3[] = {0, 1, 2, 3, 1, 0};
5827 /* mesh4 (below, tip against tip)
5829 * 0--1
5830 * | /
5831 * |/
5834 * |\
5835 * | \
5836 * 5--4
5838 struct vertex_pnc vertices4[] =
5840 {{ 0.0f, 3.0f, 0.f}, up, RED},
5841 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5842 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5844 {{ 0.0f, -4.0f, 0.f}, up, BLUE},
5845 {{ 2.0f, -7.0f, 0.f}, up, GREEN},
5846 {{ 0.0f, -7.0f, 0.f}, up, RED},
5848 const DWORD indices4[] = {0, 1, 2, 3, 4, 5};
5849 const unsigned int num_vertices4 = ARRAY_SIZE(vertices4);
5850 const unsigned int num_faces4 = num_vertices4 / VERTS_PER_FACE;
5851 const DWORD exp_adjacency4[] = {-1, -1, -1, -1, -1, -1};
5852 const DWORD exp_id_adjacency4[] = {-1, -1, -1, -1, -1, -1};
5853 const DWORD point_rep4[] = {0, 1, 2, 3, 4, 5};
5854 /* mesh5 (gap in mesh)
5856 * 0 3-----4 15
5857 * / \ \ / / \
5858 * / \ \ / / \
5859 * 2-----1 5 17-----16
5860 * 6-----7 9 12-----13
5861 * \ / / \ \ /
5862 * \ / / \ \ /
5863 * 8 10-----11 14
5866 const struct vertex_pnc vertices5[] =
5868 {{ 0.0f, 1.0f, 0.f}, up, RED},
5869 {{ 1.0f, -1.0f, 0.f}, up, GREEN},
5870 {{-1.0f, -1.0f, 0.f}, up, BLUE},
5872 {{ 0.1f, 1.0f, 0.f}, up, RED},
5873 {{ 2.1f, 1.0f, 0.f}, up, BLUE},
5874 {{ 1.1f, -1.0f, 0.f}, up, GREEN},
5876 {{-1.0f, -1.1f, 0.f}, up, BLUE},
5877 {{ 1.0f, -1.1f, 0.f}, up, GREEN},
5878 {{ 0.0f, -3.1f, 0.f}, up, RED},
5880 {{ 1.1f, -1.1f, 0.f}, up, GREEN},
5881 {{ 2.1f, -3.1f, 0.f}, up, BLUE},
5882 {{ 0.1f, -3.1f, 0.f}, up, RED},
5884 {{ 1.2f, -1.1f, 0.f}, up, GREEN},
5885 {{ 3.2f, -1.1f, 0.f}, up, RED},
5886 {{ 2.2f, -3.1f, 0.f}, up, BLUE},
5888 {{ 2.2f, 1.0f, 0.f}, up, BLUE},
5889 {{ 3.2f, -1.0f, 0.f}, up, RED},
5890 {{ 1.2f, -1.0f, 0.f}, up, GREEN},
5892 const DWORD indices5[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17};
5893 const unsigned int num_vertices5 = ARRAY_SIZE(vertices5);
5894 const unsigned int num_faces5 = num_vertices5 / VERTS_PER_FACE;
5895 const DWORD exp_adjacency5[] = {-1, 2, -1, -1, 5, -1, 0, -1, -1, 4, -1, -1, 5, -1, 3, -1, 4, 1};
5896 const DWORD exp_id_adjacency5[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
5897 const DWORD point_rep5[] = {0, 1, 2, 3, 4, 5, 2, 1, 8, 5, 10, 11, 5, 13, 10, 4, 13, 5};
5898 /* mesh6 (indices re-ordering)
5900 * 0--1 6 3
5901 * | / /| |\
5902 * |/ / | | \
5903 * 2 8--7 5--4
5905 const struct vertex_pnc vertices6[] =
5907 {{ 0.0f, 3.0f, 0.f}, up, RED},
5908 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5909 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5911 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5912 {{ 3.0f, 0.0f, 0.f}, up, RED},
5913 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5915 {{ 4.0f, 3.0f, 0.f}, up, GREEN},
5916 {{ 6.0f, 0.0f, 0.f}, up, BLUE},
5917 {{ 4.0f, 0.0f, 0.f}, up, RED},
5919 const DWORD indices6[] = {0, 1, 2, 6, 7, 8, 3, 4, 5};
5920 const unsigned int num_vertices6 = ARRAY_SIZE(vertices6);
5921 const unsigned int num_faces6 = num_vertices6 / VERTS_PER_FACE;
5922 const DWORD exp_adjacency6[] = {-1, 1, -1, 2, -1, 0, -1, -1, 1};
5923 const DWORD exp_id_adjacency6[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1};
5924 const DWORD point_rep6[] = {0, 1, 2, 1, 4, 5, 1, 5, 2};
5925 /* mesh7 (expands collapsed triangle)
5927 * 0--1 3
5928 * | / /|
5929 * |/ / |
5930 * 2 5--4
5932 const struct vertex_pnc vertices7[] =
5934 {{ 0.0f, 3.0f, 0.f}, up, RED},
5935 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5936 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5938 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5939 {{ 3.0f, 0.0f, 0.f}, up, RED},
5940 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5942 const DWORD indices7[] = {0, 1, 2, 3, 3, 3}; /* Face 1 is collapsed*/
5943 const unsigned int num_vertices7 = ARRAY_SIZE(vertices7);
5944 const unsigned int num_faces7 = num_vertices7 / VERTS_PER_FACE;
5945 const DWORD exp_adjacency7[] = {-1, -1, -1, -1, -1, -1};
5946 const DWORD exp_id_adjacency7[] = {-1, -1, -1, -1, -1, -1};
5947 const DWORD point_rep7[] = {0, 1, 2, 3, 4, 5};
5948 /* mesh8 (indices re-ordering and double replacement)
5950 * 0--1 9 6
5951 * | / /| |\
5952 * |/ / | | \
5953 * 2 11-10 8--7
5954 * 3--4
5955 * | /
5956 * |/
5959 const struct vertex_pnc vertices8[] =
5961 {{ 0.0f, 3.0f, 0.f}, up, RED},
5962 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5963 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5965 {{ 4.0, -4.0, 0.f}, up, RED},
5966 {{ 6.0, -4.0, 0.f}, up, BLUE},
5967 {{ 4.0, -7.0, 0.f}, up, GREEN},
5969 {{ 4.0f, 3.0f, 0.f}, up, GREEN},
5970 {{ 6.0f, 0.0f, 0.f}, up, BLUE},
5971 {{ 4.0f, 0.0f, 0.f}, up, RED},
5973 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5974 {{ 3.0f, 0.0f, 0.f}, up, RED},
5975 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5977 const DWORD indices8[] = {0, 1, 2, 9, 10, 11, 6, 7, 8, 3, 4, 5};
5978 const WORD indices8_16bit[] = {0, 1, 2, 9, 10, 11, 6, 7, 8, 3, 4, 5};
5979 const unsigned int num_vertices8 = ARRAY_SIZE(vertices8);
5980 const unsigned int num_faces8 = num_vertices8 / VERTS_PER_FACE;
5981 const DWORD exp_adjacency8[] = {-1, 1, -1, 2, -1, 0, -1, 3, 1, 2, -1, -1};
5982 const DWORD exp_id_adjacency8[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
5983 const DWORD point_rep8[] = {0, 1, 2, 3, 4, 5, 1, 4, 3, 1, 3, 2};
5984 /* mesh9 (right, shared vertices)
5986 * 0--1
5987 * | /|
5988 * |/ |
5989 * 2--3
5991 const struct vertex_pnc vertices9[] =
5993 {{ 0.0f, 3.0f, 0.f}, up, RED},
5994 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5995 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5997 {{ 2.0f, 0.0f, 0.f}, up, RED},
5999 const DWORD indices9[] = {0, 1, 2, 1, 3, 2};
6000 const unsigned int num_vertices9 = ARRAY_SIZE(vertices9);
6001 const unsigned int num_faces9 = 2;
6002 const DWORD exp_adjacency9[] = {-1, 1, -1, -1, -1, 0};
6003 const DWORD exp_id_adjacency9[] = {-1, 1, -1, -1, -1, 0};
6004 const DWORD point_rep9[] = {0, 1, 2, 3};
6005 /* All mesh data */
6006 ID3DXMesh *mesh = NULL;
6007 ID3DXMesh *mesh_null_check = NULL;
6008 unsigned int attributes[] = {0};
6009 struct
6011 const struct vertex_pnc *vertices;
6012 const DWORD *indices;
6013 const DWORD num_vertices;
6014 const DWORD num_faces;
6015 const DWORD *point_reps;
6016 const DWORD *exp_adjacency;
6017 const DWORD *exp_id_adjacency;
6018 const DWORD options;
6020 tc[] =
6023 vertices0,
6024 indices0,
6025 num_vertices0,
6026 num_faces0,
6027 point_rep0,
6028 exp_adjacency0,
6029 exp_id_adjacency0,
6030 options
6033 vertices1,
6034 indices1,
6035 num_vertices1,
6036 num_faces1,
6037 point_rep1,
6038 exp_adjacency1,
6039 exp_id_adjacency1,
6040 options
6043 vertices2,
6044 indices2,
6045 num_vertices2,
6046 num_faces2,
6047 point_rep2,
6048 exp_adjacency2,
6049 exp_id_adjacency2,
6050 options
6053 vertices3,
6054 indices3,
6055 num_vertices3,
6056 num_faces3,
6057 point_rep3,
6058 exp_adjacency3,
6059 exp_id_adjacency3,
6060 options
6063 vertices4,
6064 indices4,
6065 num_vertices4,
6066 num_faces4,
6067 point_rep4,
6068 exp_adjacency4,
6069 exp_id_adjacency4,
6070 options
6073 vertices5,
6074 indices5,
6075 num_vertices5,
6076 num_faces5,
6077 point_rep5,
6078 exp_adjacency5,
6079 exp_id_adjacency5,
6080 options
6083 vertices6,
6084 indices6,
6085 num_vertices6,
6086 num_faces6,
6087 point_rep6,
6088 exp_adjacency6,
6089 exp_id_adjacency6,
6090 options
6093 vertices7,
6094 indices7,
6095 num_vertices7,
6096 num_faces7,
6097 point_rep7,
6098 exp_adjacency7,
6099 exp_id_adjacency7,
6100 options
6103 vertices8,
6104 indices8,
6105 num_vertices8,
6106 num_faces8,
6107 point_rep8,
6108 exp_adjacency8,
6109 exp_id_adjacency8,
6110 options
6113 vertices9,
6114 indices9,
6115 num_vertices9,
6116 num_faces9,
6117 point_rep9,
6118 exp_adjacency9,
6119 exp_id_adjacency9,
6120 options
6123 vertices8,
6124 (DWORD*)indices8_16bit,
6125 num_vertices8,
6126 num_faces8,
6127 point_rep8,
6128 exp_adjacency8,
6129 exp_id_adjacency8,
6130 options_16bit
6133 DWORD *adjacency = NULL;
6135 test_context = new_test_context();
6136 if (!test_context)
6138 skip("Couldn't create test context\n");
6139 goto cleanup;
6142 for (i = 0; i < ARRAY_SIZE(tc); i++)
6144 hr = D3DXCreateMesh(tc[i].num_faces, tc[i].num_vertices, tc[i].options,
6145 declaration, test_context->device, &mesh);
6146 if (FAILED(hr))
6148 skip("Couldn't create mesh %d. Got %x expected D3D_OK\n", i, hr);
6149 goto cleanup;
6152 if (i == 0) /* Save first mesh for later NULL checks */
6153 mesh_null_check = mesh;
6155 adjacency = HeapAlloc(GetProcessHeap(), 0, VERTS_PER_FACE * tc[i].num_faces * sizeof(*adjacency));
6156 if (!adjacency)
6158 skip("Couldn't allocate adjacency array.\n");
6159 goto cleanup;
6162 hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, &vertex_buffer);
6163 if (FAILED(hr))
6165 skip("Couldn't lock vertex buffer.\n");
6166 goto cleanup;
6168 memcpy(vertex_buffer, tc[i].vertices, tc[i].num_vertices * sizeof(*tc[i].vertices));
6169 hr = mesh->lpVtbl->UnlockVertexBuffer(mesh);
6170 if (FAILED(hr))
6172 skip("Couldn't unlock vertex buffer.\n");
6173 goto cleanup;
6175 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, &index_buffer);
6176 if (FAILED(hr))
6178 skip("Couldn't lock index buffer.\n");
6179 goto cleanup;
6181 if (tc[i].options & D3DXMESH_32BIT)
6183 memcpy(index_buffer, tc[i].indices, VERTS_PER_FACE * tc[i].num_faces * sizeof(DWORD));
6185 else
6187 memcpy(index_buffer, tc[i].indices, VERTS_PER_FACE * tc[i].num_faces * sizeof(WORD));
6189 hr = mesh->lpVtbl->UnlockIndexBuffer(mesh);
6190 if (FAILED(hr)) {
6191 skip("Couldn't unlock index buffer.\n");
6192 goto cleanup;
6195 hr = mesh->lpVtbl->LockAttributeBuffer(mesh, 0, &attributes_buffer);
6196 if (FAILED(hr))
6198 skip("Couldn't lock attributes buffer.\n");
6199 goto cleanup;
6201 memcpy(attributes_buffer, attributes, sizeof(attributes));
6202 hr = mesh->lpVtbl->UnlockAttributeBuffer(mesh);
6203 if (FAILED(hr))
6205 skip("Couldn't unlock attributes buffer.\n");
6206 goto cleanup;
6209 /* Convert point representation to adjacency*/
6210 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++) adjacency[j] = -2;
6212 hr = mesh->lpVtbl->ConvertPointRepsToAdjacency(mesh, tc[i].point_reps, adjacency);
6213 ok(hr == D3D_OK, "ConvertPointRepsToAdjacency failed case %d. "
6214 "Got %x expected D3D_OK\n", i, hr);
6215 /* Check adjacency */
6216 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
6218 ok(adjacency[j] == tc[i].exp_adjacency[j],
6219 "Unexpected adjacency information at (%d, %d)."
6220 " Got %d expected %d\n",
6221 i, j, adjacency[j], tc[i].exp_adjacency[j]);
6224 /* NULL point representation is considered identity. */
6225 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++) adjacency[j] = -2;
6226 hr = mesh_null_check->lpVtbl->ConvertPointRepsToAdjacency(mesh, NULL, adjacency);
6227 ok(hr == D3D_OK, "ConvertPointRepsToAdjacency NULL point_reps. "
6228 "Got %x expected D3D_OK\n", hr);
6229 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
6231 ok(adjacency[j] == tc[i].exp_id_adjacency[j],
6232 "Unexpected adjacency information (id) at (%d, %d)."
6233 " Got %d expected %d\n",
6234 i, j, adjacency[j], tc[i].exp_id_adjacency[j]);
6237 HeapFree(GetProcessHeap(), 0, adjacency);
6238 adjacency = NULL;
6239 if (i != 0) /* First mesh will be freed during cleanup */
6240 mesh->lpVtbl->Release(mesh);
6243 /* NULL checks */
6244 hr = mesh_null_check->lpVtbl->ConvertPointRepsToAdjacency(mesh_null_check, tc[0].point_reps, NULL);
6245 ok(hr == D3DERR_INVALIDCALL, "ConvertPointRepsToAdjacency NULL adjacency. "
6246 "Got %x expected D3DERR_INVALIDCALL\n", hr);
6247 hr = mesh_null_check->lpVtbl->ConvertPointRepsToAdjacency(mesh_null_check, NULL, NULL);
6248 ok(hr == D3DERR_INVALIDCALL, "ConvertPointRepsToAdjacency NULL point_reps and adjacency. "
6249 "Got %x expected D3DERR_INVALIDCALL\n", hr);
6251 cleanup:
6252 if (mesh_null_check)
6253 mesh_null_check->lpVtbl->Release(mesh_null_check);
6254 HeapFree(GetProcessHeap(), 0, adjacency);
6255 free_test_context(test_context);
6258 static HRESULT init_test_mesh(const DWORD num_faces, const DWORD num_vertices,
6259 const DWORD options,
6260 const D3DVERTEXELEMENT9 *declaration,
6261 IDirect3DDevice9 *device, ID3DXMesh **mesh_ptr,
6262 const void *vertices, const DWORD vertex_size,
6263 const DWORD *indices, const DWORD *attributes)
6265 HRESULT hr;
6266 void *vertex_buffer;
6267 void *index_buffer;
6268 DWORD *attributes_buffer;
6269 ID3DXMesh *mesh = NULL;
6271 hr = D3DXCreateMesh(num_faces, num_vertices, options, declaration, device, mesh_ptr);
6272 if (FAILED(hr))
6274 skip("Couldn't create mesh. Got %x expected D3D_OK\n", hr);
6275 goto cleanup;
6277 mesh = *mesh_ptr;
6279 hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, &vertex_buffer);
6280 if (FAILED(hr))
6282 skip("Couldn't lock vertex buffer.\n");
6283 goto cleanup;
6285 memcpy(vertex_buffer, vertices, num_vertices * vertex_size);
6286 hr = mesh->lpVtbl->UnlockVertexBuffer(mesh);
6287 if (FAILED(hr))
6289 skip("Couldn't unlock vertex buffer.\n");
6290 goto cleanup;
6293 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, &index_buffer);
6294 if (FAILED(hr))
6296 skip("Couldn't lock index buffer.\n");
6297 goto cleanup;
6299 if (options & D3DXMESH_32BIT)
6301 if (indices)
6302 memcpy(index_buffer, indices, 3 * num_faces * sizeof(DWORD));
6303 else
6305 /* Fill index buffer with 0, 1, 2, ...*/
6306 DWORD *indices_32bit = (DWORD*)index_buffer;
6307 UINT i;
6308 for (i = 0; i < 3 * num_faces; i++)
6309 indices_32bit[i] = i;
6312 else
6314 if (indices)
6315 memcpy(index_buffer, indices, 3 * num_faces * sizeof(WORD));
6316 else
6318 /* Fill index buffer with 0, 1, 2, ...*/
6319 WORD *indices_16bit = (WORD*)index_buffer;
6320 UINT i;
6321 for (i = 0; i < 3 * num_faces; i++)
6322 indices_16bit[i] = i;
6325 hr = mesh->lpVtbl->UnlockIndexBuffer(mesh);
6326 if (FAILED(hr)) {
6327 skip("Couldn't unlock index buffer.\n");
6328 goto cleanup;
6331 hr = mesh->lpVtbl->LockAttributeBuffer(mesh, 0, &attributes_buffer);
6332 if (FAILED(hr))
6334 skip("Couldn't lock attributes buffer.\n");
6335 goto cleanup;
6338 if (attributes)
6339 memcpy(attributes_buffer, attributes, num_faces * sizeof(*attributes));
6340 else
6341 memset(attributes_buffer, 0, num_faces * sizeof(*attributes));
6343 hr = mesh->lpVtbl->UnlockAttributeBuffer(mesh);
6344 if (FAILED(hr))
6346 skip("Couldn't unlock attributes buffer.\n");
6347 goto cleanup;
6350 hr = D3D_OK;
6351 cleanup:
6352 return hr;
6355 /* Using structs instead of bit-fields in order to avoid compiler issues. */
6356 struct udec3
6358 UINT x;
6359 UINT y;
6360 UINT z;
6361 UINT w;
6364 struct dec3n
6366 INT x;
6367 INT y;
6368 INT z;
6369 INT w;
6372 static DWORD init_udec3_dword(UINT x, UINT y, UINT z, UINT w)
6374 DWORD d = 0;
6376 d |= x & 0x3ff;
6377 d |= (y << 10) & 0xffc00;
6378 d |= (z << 20) & 0x3ff00000;
6379 d |= (w << 30) & 0xc0000000;
6381 return d;
6384 static DWORD init_dec3n_dword(INT x, INT y, INT z, INT w)
6386 DWORD d = 0;
6388 d |= x & 0x3ff;
6389 d |= (y << 10) & 0xffc00;
6390 d |= (z << 20) & 0x3ff00000;
6391 d |= (w << 30) & 0xc0000000;
6393 return d;
6396 static struct udec3 dword_to_udec3(DWORD d)
6398 struct udec3 v;
6400 v.x = d & 0x3ff;
6401 v.y = (d & 0xffc00) >> 10;
6402 v.z = (d & 0x3ff00000) >> 20;
6403 v.w = (d & 0xc0000000) >> 30;
6405 return v;
6408 static struct dec3n dword_to_dec3n(DWORD d)
6410 struct dec3n v;
6412 v.x = d & 0x3ff;
6413 v.y = (d & 0xffc00) >> 10;
6414 v.z = (d & 0x3ff00000) >> 20;
6415 v.w = (d & 0xc0000000) >> 30;
6417 return v;
6420 static void check_vertex_components(int line, int mesh_number, int vertex_number, BYTE *got_ptr, const BYTE *exp_ptr, D3DVERTEXELEMENT9 *declaration)
6422 const char *usage_strings[] =
6424 "position",
6425 "blend weight",
6426 "blend indices",
6427 "normal",
6428 "point size",
6429 "texture coordinates",
6430 "tangent",
6431 "binormal",
6432 "tessellation factor",
6433 "position transformed",
6434 "color",
6435 "fog",
6436 "depth",
6437 "sample"
6439 D3DVERTEXELEMENT9 *decl_ptr;
6440 const float PRECISION = 1e-5f;
6442 for (decl_ptr = declaration; decl_ptr->Stream != 0xFF; decl_ptr++)
6444 switch (decl_ptr->Type)
6446 case D3DDECLTYPE_FLOAT1:
6448 FLOAT *got = (FLOAT*)(got_ptr + decl_ptr->Offset);
6449 FLOAT *exp = (FLOAT*)(exp_ptr + decl_ptr->Offset);
6450 FLOAT diff = fabsf(*got - *exp);
6451 ok_(__FILE__,line)(diff <= PRECISION, "Mesh %d: Got %f for vertex %d %s, expected %f.\n",
6452 mesh_number, *got, vertex_number, usage_strings[decl_ptr->Usage], *exp);
6453 break;
6455 case D3DDECLTYPE_FLOAT2:
6457 D3DXVECTOR2 *got = (D3DXVECTOR2*)(got_ptr + decl_ptr->Offset);
6458 D3DXVECTOR2 *exp = (D3DXVECTOR2*)(exp_ptr + decl_ptr->Offset);
6459 FLOAT diff = max(fabsf(got->x - exp->x), fabsf(got->y - exp->y));
6460 ok_(__FILE__,line)(diff <= PRECISION, "Mesh %d: Got (%f, %f) for vertex %d %s, expected (%f, %f).\n",
6461 mesh_number, got->x, got->y, vertex_number, usage_strings[decl_ptr->Usage], exp->x, exp->y);
6462 break;
6464 case D3DDECLTYPE_FLOAT3:
6466 D3DXVECTOR3 *got = (D3DXVECTOR3*)(got_ptr + decl_ptr->Offset);
6467 D3DXVECTOR3 *exp = (D3DXVECTOR3*)(exp_ptr + decl_ptr->Offset);
6468 FLOAT diff = max(fabsf(got->x - exp->x), fabsf(got->y - exp->y));
6469 diff = max(diff, fabsf(got->z - exp->z));
6470 ok_(__FILE__,line)(diff <= PRECISION, "Mesh %d: Got (%f, %f, %f) for vertex %d %s, expected (%f, %f, %f).\n",
6471 mesh_number, got->x, got->y, got->z, vertex_number, usage_strings[decl_ptr->Usage], exp->x, exp->y, exp->z);
6472 break;
6474 case D3DDECLTYPE_FLOAT4:
6476 D3DXVECTOR4 *got = (D3DXVECTOR4*)(got_ptr + decl_ptr->Offset);
6477 D3DXVECTOR4 *exp = (D3DXVECTOR4*)(exp_ptr + decl_ptr->Offset);
6478 FLOAT diff = max(fabsf(got->x - exp->x), fabsf(got->y - exp->y));
6479 diff = max(diff, fabsf(got->z - exp->z));
6480 diff = max(diff, fabsf(got->w - exp->w));
6481 ok_(__FILE__,line)(diff <= PRECISION, "Mesh %d: Got (%f, %f, %f, %f) for vertex %d %s, expected (%f, %f, %f, %f).\n",
6482 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);
6483 break;
6485 case D3DDECLTYPE_D3DCOLOR:
6487 BYTE *got = got_ptr + decl_ptr->Offset;
6488 const BYTE *exp = exp_ptr + decl_ptr->Offset;
6489 BOOL same_color = got[0] == exp[0] && got[1] == exp[1]
6490 && got[2] == exp[2] && got[3] == exp[3];
6491 const char *color_types[] = {"diffuse", "specular", "undefined color"};
6492 BYTE usage_index = decl_ptr->UsageIndex;
6493 if (usage_index > 1) usage_index = 2;
6494 ok_(__FILE__,line)(same_color, "Mesh %d: Got (%u, %u, %u, %u) for vertex %d %s, expected (%u, %u, %u, %u).\n",
6495 mesh_number, got[0], got[1], got[2], got[3], vertex_number, color_types[usage_index], exp[0], exp[1], exp[2], exp[3]);
6496 break;
6498 case D3DDECLTYPE_UBYTE4:
6499 case D3DDECLTYPE_UBYTE4N:
6501 BYTE *got = got_ptr + decl_ptr->Offset;
6502 const BYTE *exp = exp_ptr + decl_ptr->Offset;
6503 BOOL same = got[0] == exp[0] && got[1] == exp[1]
6504 && got[2] == exp[2] && got[3] == exp[3];
6505 ok_(__FILE__,line)(same, "Mesh %d: Got (%u, %u, %u, %u) for vertex %d %s, expected (%u, %u, %u, %u).\n",
6506 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]);
6507 break;
6509 case D3DDECLTYPE_SHORT2:
6510 case D3DDECLTYPE_SHORT2N:
6512 SHORT *got = (SHORT*)(got_ptr + decl_ptr->Offset);
6513 SHORT *exp = (SHORT*)(exp_ptr + decl_ptr->Offset);
6514 BOOL same = got[0] == exp[0] && got[1] == exp[1];
6515 ok_(__FILE__,line)(same, "Mesh %d: Got (%hd, %hd) for vertex %d %s, expected (%hd, %hd).\n",
6516 mesh_number, got[0], got[1], vertex_number, usage_strings[decl_ptr->Usage], exp[0], exp[1]);
6517 break;
6519 case D3DDECLTYPE_SHORT4:
6520 case D3DDECLTYPE_SHORT4N:
6522 SHORT *got = (SHORT*)(got_ptr + decl_ptr->Offset);
6523 SHORT *exp = (SHORT*)(exp_ptr + decl_ptr->Offset);
6524 BOOL same = got[0] == exp[0] && got[1] == exp[1]
6525 && got[2] == exp[2] && got[3] == exp[3];
6526 ok_(__FILE__,line)(same, "Mesh %d: Got (%hd, %hd, %hd, %hd) for vertex %d %s, expected (%hd, %hd, %hd, %hd).\n",
6527 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]);
6528 break;
6530 case D3DDECLTYPE_USHORT2N:
6532 USHORT *got = (USHORT*)(got_ptr + decl_ptr->Offset);
6533 USHORT *exp = (USHORT*)(exp_ptr + decl_ptr->Offset);
6534 BOOL same = got[0] == exp[0] && got[1] == exp[1];
6535 ok_(__FILE__,line)(same, "Mesh %d: Got (%hu, %hu) for vertex %d %s, expected (%hu, %hu).\n",
6536 mesh_number, got[0], got[1], vertex_number, usage_strings[decl_ptr->Usage], exp[0], exp[1]);
6537 break;
6539 case D3DDECLTYPE_USHORT4N:
6541 USHORT *got = (USHORT*)(got_ptr + decl_ptr->Offset);
6542 USHORT *exp = (USHORT*)(exp_ptr + decl_ptr->Offset);
6543 BOOL same = got[0] == exp[0] && got[1] == exp[1]
6544 && got[2] == exp[2] && got[3] == exp[3];
6545 ok_(__FILE__,line)(same, "Mesh %d: Got (%hu, %hu, %hu, %hu) for vertex %d %s, expected (%hu, %hu, %hu, %hu).\n",
6546 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]);
6547 break;
6549 case D3DDECLTYPE_UDEC3:
6551 DWORD *got = (DWORD*)(got_ptr + decl_ptr->Offset);
6552 DWORD *exp = (DWORD*)(exp_ptr + decl_ptr->Offset);
6553 BOOL same = memcmp(got, exp, sizeof(*got)) == 0;
6554 struct udec3 got_udec3 = dword_to_udec3(*got);
6555 struct udec3 exp_udec3 = dword_to_udec3(*exp);
6556 ok_(__FILE__,line)(same, "Mesh %d: Got (%u, %u, %u, %u) for vertex %d %s, expected (%u, %u, %u, %u).\n",
6557 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);
6559 break;
6561 case D3DDECLTYPE_DEC3N:
6563 DWORD *got = (DWORD*)(got_ptr + decl_ptr->Offset);
6564 DWORD *exp = (DWORD*)(exp_ptr + decl_ptr->Offset);
6565 BOOL same = memcmp(got, exp, sizeof(*got)) == 0;
6566 struct dec3n got_dec3n = dword_to_dec3n(*got);
6567 struct dec3n exp_dec3n = dword_to_dec3n(*exp);
6568 ok_(__FILE__,line)(same, "Mesh %d: Got (%d, %d, %d, %d) for vertex %d %s, expected (%d, %d, %d, %d).\n",
6569 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);
6570 break;
6572 case D3DDECLTYPE_FLOAT16_2:
6574 WORD *got = (WORD*)(got_ptr + decl_ptr->Offset);
6575 WORD *exp = (WORD*)(exp_ptr + decl_ptr->Offset);
6576 BOOL same = got[0] == exp[0] && got[1] == exp[1];
6577 ok_(__FILE__,line)(same, "Mesh %d: Got (%hx, %hx) for vertex %d %s, expected (%hx, %hx).\n",
6578 mesh_number, got[0], got[1], vertex_number, usage_strings[decl_ptr->Usage], exp[0], exp[1]);
6579 break;
6581 case D3DDECLTYPE_FLOAT16_4:
6583 WORD *got = (WORD*)(got_ptr + decl_ptr->Offset);
6584 WORD *exp = (WORD*)(exp_ptr + decl_ptr->Offset);
6585 BOOL same = got[0] == exp[0] && got[1] == exp[1]
6586 && got[2] == exp[2] && got[3] == exp[3];
6587 ok_(__FILE__,line)(same, "Mesh %d: Got (%hx, %hx, %hx, %hx) for vertex %d %s, expected (%hx, %hx, %hx, %hx).\n",
6588 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]);
6589 break;
6591 default:
6592 break;
6597 static void test_weld_vertices(void)
6599 HRESULT hr;
6600 struct test_context *test_context = NULL;
6601 DWORD i;
6602 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
6603 const DWORD options_16bit = D3DXMESH_SYSTEMMEM;
6604 BYTE *vertices = NULL;
6605 DWORD *indices = NULL;
6606 WORD *indices_16bit = NULL;
6607 const UINT VERTS_PER_FACE = 3;
6608 const D3DXVECTOR3 up = {0.0f, 0.0f, 1.0f};
6609 struct vertex_normal
6611 D3DXVECTOR3 position;
6612 D3DXVECTOR3 normal;
6614 struct vertex_blendweight
6616 D3DXVECTOR3 position;
6617 FLOAT blendweight;
6619 struct vertex_texcoord
6621 D3DXVECTOR3 position;
6622 D3DXVECTOR2 texcoord;
6624 struct vertex_color
6626 D3DXVECTOR3 position;
6627 DWORD color;
6629 struct vertex_color_ubyte4
6631 D3DXVECTOR3 position;
6632 BYTE color[4];
6634 struct vertex_texcoord_short2
6636 D3DXVECTOR3 position;
6637 SHORT texcoord[2];
6639 struct vertex_texcoord_ushort2n
6641 D3DXVECTOR3 position;
6642 USHORT texcoord[2];
6644 struct vertex_normal_short4
6646 D3DXVECTOR3 position;
6647 SHORT normal[4];
6649 struct vertex_texcoord_float16_2
6651 D3DXVECTOR3 position;
6652 WORD texcoord[2];
6654 struct vertex_texcoord_float16_4
6656 D3DXVECTOR3 position;
6657 WORD texcoord[4];
6659 struct vertex_normal_udec3
6661 D3DXVECTOR3 position;
6662 DWORD normal;
6664 struct vertex_normal_dec3n
6666 D3DXVECTOR3 position;
6667 DWORD normal;
6669 UINT vertex_size_normal = sizeof(struct vertex_normal);
6670 UINT vertex_size_blendweight = sizeof(struct vertex_blendweight);
6671 UINT vertex_size_texcoord = sizeof(struct vertex_texcoord);
6672 UINT vertex_size_color = sizeof(struct vertex_color);
6673 UINT vertex_size_color_ubyte4 = sizeof(struct vertex_color_ubyte4);
6674 UINT vertex_size_texcoord_short2 = sizeof(struct vertex_texcoord_short2);
6675 UINT vertex_size_normal_short4 = sizeof(struct vertex_normal_short4);
6676 UINT vertex_size_texcoord_float16_2 = sizeof(struct vertex_texcoord_float16_2);
6677 UINT vertex_size_texcoord_float16_4 = sizeof(struct vertex_texcoord_float16_4);
6678 UINT vertex_size_normal_udec3 = sizeof(struct vertex_normal_udec3);
6679 UINT vertex_size_normal_dec3n = sizeof(struct vertex_normal_dec3n);
6680 D3DVERTEXELEMENT9 declaration_normal[] =
6682 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6683 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6684 D3DDECL_END()
6686 D3DVERTEXELEMENT9 declaration_normal3[] =
6688 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 3},
6689 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6690 D3DDECL_END()
6692 D3DVERTEXELEMENT9 declaration_blendweight[] =
6694 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6695 {0, 12, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BLENDWEIGHT, 0},
6696 D3DDECL_END()
6698 D3DVERTEXELEMENT9 declaration_texcoord[] =
6700 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6701 {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6702 D3DDECL_END()
6704 D3DVERTEXELEMENT9 declaration_color[] =
6706 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6707 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
6708 D3DDECL_END()
6710 D3DVERTEXELEMENT9 declaration_color_ubyte4n[] =
6712 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6713 {0, 12, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
6714 D3DDECL_END()
6716 D3DVERTEXELEMENT9 declaration_color_ubyte4[] =
6718 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6719 {0, 12, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
6720 D3DDECL_END()
6722 D3DVERTEXELEMENT9 declaration_texcoord_short2[] =
6724 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6725 {0, 12, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6726 D3DDECL_END()
6728 D3DVERTEXELEMENT9 declaration_texcoord_short2n[] =
6730 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6731 {0, 12, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6732 D3DDECL_END()
6734 D3DVERTEXELEMENT9 declaration_texcoord_ushort2n[] =
6736 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6737 {0, 12, D3DDECLTYPE_USHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6738 D3DDECL_END()
6740 D3DVERTEXELEMENT9 declaration_normal_short4[] =
6742 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6743 {0, 12, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6744 D3DDECL_END()
6746 D3DVERTEXELEMENT9 declaration_normal_short4n[] =
6748 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6749 {0, 12, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6750 D3DDECL_END()
6752 D3DVERTEXELEMENT9 declaration_normal_ushort4n[] =
6754 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6755 {0, 12, D3DDECLTYPE_USHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6756 D3DDECL_END()
6758 D3DVERTEXELEMENT9 declaration_texcoord10[] =
6760 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6761 {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 10},
6762 D3DDECL_END()
6764 D3DVERTEXELEMENT9 declaration_color2[] =
6766 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6767 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 2},
6768 D3DDECL_END()
6770 D3DVERTEXELEMENT9 declaration_color1[] =
6772 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6773 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 1},
6774 D3DDECL_END()
6776 D3DVERTEXELEMENT9 declaration_texcoord_float16_2[] =
6778 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6779 {0, 12, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6780 D3DDECL_END()
6782 D3DVERTEXELEMENT9 declaration_texcoord_float16_4[] =
6784 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6785 {0, 12, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6786 D3DDECL_END()
6788 D3DVERTEXELEMENT9 declaration_normal_udec3[] =
6790 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6791 {0, 12, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6792 D3DDECL_END()
6794 D3DVERTEXELEMENT9 declaration_normal_dec3n[] =
6796 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6797 {0, 12, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6798 D3DDECL_END()
6800 /* Test 0. One face and no welding.
6802 * 0--1
6803 * | /
6804 * |/
6807 const struct vertex vertices0[] =
6809 {{ 0.0f, 3.0f, 0.f}, up},
6810 {{ 2.0f, 3.0f, 0.f}, up},
6811 {{ 0.0f, 0.0f, 0.f}, up},
6813 const DWORD indices0[] = {0, 1, 2};
6814 const DWORD attributes0[] = {0};
6815 const DWORD exp_indices0[] = {0, 1, 2};
6816 const UINT num_vertices0 = ARRAY_SIZE(vertices0);
6817 const UINT num_faces0 = ARRAY_SIZE(indices0) / VERTS_PER_FACE;
6818 const DWORD flags0 = D3DXWELDEPSILONS_WELDALL;
6819 /* epsilons0 is NULL */
6820 const DWORD adjacency0[] = {-1, -1, -1};
6821 const struct vertex exp_vertices0[] =
6823 {{ 0.0f, 3.0f, 0.f}, up},
6824 {{ 2.0f, 3.0f, 0.f}, up},
6825 {{ 0.0f, 0.0f, 0.f}, up},
6827 const DWORD exp_face_remap0[] = {0};
6828 const DWORD exp_vertex_remap0[] = {0, 1, 2};
6829 const DWORD exp_new_num_vertices0 = ARRAY_SIZE(exp_vertices0);
6830 /* Test 1. Two vertices should be removed without regard to epsilon.
6832 * 0--1 3
6833 * | / /|
6834 * |/ / |
6835 * 2 5--4
6837 const struct vertex_normal vertices1[] =
6839 {{ 0.0f, 3.0f, 0.f}, up},
6840 {{ 2.0f, 3.0f, 0.f}, up},
6841 {{ 0.0f, 0.0f, 0.f}, up},
6843 {{ 3.0f, 3.0f, 0.f}, up},
6844 {{ 3.0f, 0.0f, 0.f}, up},
6845 {{ 1.0f, 0.0f, 0.f}, up},
6847 const DWORD indices1[] = {0, 1, 2, 3, 4, 5};
6848 const DWORD attributes1[] = {0, 0};
6849 const UINT num_vertices1 = ARRAY_SIZE(vertices1);
6850 const UINT num_faces1 = ARRAY_SIZE(indices1) / VERTS_PER_FACE;
6851 const DWORD flags1 = D3DXWELDEPSILONS_WELDALL;
6852 /* epsilons1 is NULL */
6853 const DWORD adjacency1[] = {-1, 1, -1, -1, -1, 0};
6854 const struct vertex_normal exp_vertices1[] =
6856 {{ 0.0f, 3.0f, 0.f}, up},
6857 {{ 2.0f, 3.0f, 0.f}, up},
6858 {{ 0.0f, 0.0f, 0.f}, up},
6860 {{ 3.0f, 0.0f, 0.f}, up}
6862 const DWORD exp_indices1[] = {0, 1, 2, 1, 3, 2};
6863 const DWORD exp_face_remap1[] = {0, 1};
6864 const DWORD exp_vertex_remap1[] = {0, 1, 2, 4, -1, -1};
6865 const DWORD exp_new_num_vertices1 = ARRAY_SIZE(exp_vertices1);
6866 /* Test 2. Two faces. No vertices should be removed because of normal
6867 * epsilon, but the positions should be replaced. */
6868 const struct vertex_normal vertices2[] =
6870 {{ 0.0f, 3.0f, 0.f}, up},
6871 {{ 2.0f, 3.0f, 0.f}, up},
6872 {{ 0.0f, 0.0f, 0.f}, up},
6874 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
6875 {{ 3.0f, 0.0f, 0.f}, up},
6876 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6878 const DWORD indices2[] = {0, 1, 2, 3, 4, 5};
6879 const DWORD attributes2[] = {0, 0};
6880 const UINT num_vertices2 = ARRAY_SIZE(vertices2);
6881 const UINT num_faces2 = ARRAY_SIZE(indices2) / VERTS_PER_FACE;
6882 DWORD flags2 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
6883 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};
6884 const DWORD adjacency2[] = {-1, 1, -1, -1, -1, 0};
6885 const struct vertex_normal exp_vertices2[] =
6887 {{ 0.0f, 3.0f, 0.f}, up},
6888 {{ 2.0f, 3.0f, 0.f}, up},
6889 {{ 0.0f, 0.0f, 0.f}, up},
6891 {{ 2.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
6892 {{ 3.0f, 0.0f, 0.f}, up},
6893 {{ 0.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6895 const DWORD exp_indices2[] = {0, 1, 2, 3, 4, 5};
6896 const DWORD exp_face_remap2[] = {0, 1};
6897 const DWORD exp_vertex_remap2[] = {0, 1, 2, 3, 4, 5};
6898 const DWORD exp_new_num_vertices2 = ARRAY_SIZE(exp_vertices2);
6899 /* Test 3. Two faces. One vertex should be removed because of normal epsilon. */
6900 const struct vertex_normal vertices3[] =
6902 {{ 0.0f, 3.0f, 0.f}, up},
6903 {{ 2.0f, 3.0f, 0.f}, up},
6904 {{ 0.0f, 0.0f, 0.f}, up},
6906 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
6907 {{ 3.0f, 0.0f, 0.f}, up},
6908 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6910 const DWORD indices3[] = {0, 1, 2, 3, 4, 5};
6911 const DWORD attributes3[] = {0, 0};
6912 const UINT num_vertices3 = ARRAY_SIZE(vertices3);
6913 const UINT num_faces3 = ARRAY_SIZE(indices3) / VERTS_PER_FACE;
6914 DWORD flags3 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
6915 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};
6916 const DWORD adjacency3[] = {-1, 1, -1, -1, -1, 0};
6917 const struct vertex_normal exp_vertices3[] =
6919 {{ 0.0f, 3.0f, 0.f}, up},
6920 {{ 2.0f, 3.0f, 0.f}, up},
6921 {{ 0.0f, 0.0f, 0.f}, up},
6923 {{ 3.0f, 0.0f, 0.f}, up},
6924 {{ 0.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6926 const DWORD exp_indices3[] = {0, 1, 2, 1, 3, 4};
6927 const DWORD exp_face_remap3[] = {0, 1};
6928 const DWORD exp_vertex_remap3[] = {0, 1, 2, 4, 5, -1};
6929 const DWORD exp_new_num_vertices3 = ARRAY_SIZE(exp_vertices3);
6930 /* Test 4 Two faces. Two vertices should be removed. */
6931 const struct vertex_normal vertices4[] =
6933 {{ 0.0f, 3.0f, 0.f}, up},
6934 {{ 2.0f, 3.0f, 0.f}, up},
6935 {{ 0.0f, 0.0f, 0.f}, up},
6937 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
6938 {{ 3.0f, 0.0f, 0.f}, up},
6939 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6941 const DWORD indices4[] = {0, 1, 2, 3, 4, 5};
6942 const DWORD attributes4[] = {0, 0};
6943 const UINT num_vertices4 = ARRAY_SIZE(vertices4);
6944 const UINT num_faces4 = ARRAY_SIZE(indices4) / VERTS_PER_FACE;
6945 DWORD flags4 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
6946 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};
6947 const DWORD adjacency4[] = {-1, 1, -1, -1, -1, 0};
6948 const struct vertex_normal exp_vertices4[] =
6950 {{ 0.0f, 3.0f, 0.f}, up},
6951 {{ 2.0f, 3.0f, 0.f}, up},
6952 {{ 0.0f, 0.0f, 0.f}, up},
6954 {{ 3.0f, 0.0f, 0.f}, up},
6956 const DWORD exp_indices4[] = {0, 1, 2, 1, 3, 2};
6957 const DWORD exp_face_remap4[] = {0, 1};
6958 const DWORD exp_vertex_remap4[] = {0, 1, 2, 4, -1, -1};
6959 const DWORD exp_new_num_vertices4 = ARRAY_SIZE(exp_vertices4);
6960 /* Test 5. Odd face ordering.
6962 * 0--1 6 3
6963 * | / /| |\
6964 * |/ / | | \
6965 * 2 8--7 5--4
6967 const struct vertex_normal vertices5[] =
6969 {{ 0.0f, 3.0f, 0.f}, up},
6970 {{ 2.0f, 3.0f, 0.f}, up},
6971 {{ 0.0f, 0.0f, 0.f}, up},
6973 {{ 3.0f, 3.0f, 0.f}, up},
6974 {{ 3.0f, 0.0f, 0.f}, up},
6975 {{ 1.0f, 0.0f, 0.f}, up},
6977 {{ 4.0f, 3.0f, 0.f}, up},
6978 {{ 6.0f, 0.0f, 0.f}, up},
6979 {{ 4.0f, 0.0f, 0.f}, up},
6981 const DWORD indices5[] = {0, 1, 2, 6, 7, 8, 3, 4, 5};
6982 const DWORD exp_indices5[] = {0, 1, 2, 1, 4, 2, 1, 3, 4};
6983 const DWORD attributes5[] = {0, 0, 0};
6984 const UINT num_vertices5 = ARRAY_SIZE(vertices5);
6985 const UINT num_faces5 = ARRAY_SIZE(indices5) / VERTS_PER_FACE;
6986 DWORD flags5 = D3DXWELDEPSILONS_WELDALL;
6987 const DWORD adjacency5[] = {-1, 1, -1, 2, -1, 0, -1, -1, 1};
6988 const struct vertex_normal exp_vertices5[] =
6990 {{ 0.0f, 3.0f, 0.f}, up},
6991 {{ 2.0f, 3.0f, 0.f}, up},
6992 {{ 0.0f, 0.0f, 0.f}, up},
6994 {{ 3.0f, 0.0f, 0.f}, up},
6995 {{ 1.0f, 0.0f, 0.f}, up},
6997 const DWORD exp_face_remap5[] = {0, 1, 2};
6998 const DWORD exp_vertex_remap5[] = {0, 1, 2, 4, 5, -1, -1, -1, -1};
6999 const DWORD exp_new_num_vertices5 = ARRAY_SIZE(exp_vertices5);
7000 /* Test 6. Two faces. Do not remove flag is used, so no vertices should be
7001 * removed. */
7002 const struct vertex_normal vertices6[] =
7004 {{ 0.0f, 3.0f, 0.f}, up},
7005 {{ 2.0f, 3.0f, 0.f}, up},
7006 {{ 0.0f, 0.0f, 0.f}, up},
7008 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
7009 {{ 3.0f, 0.0f, 0.f}, up},
7010 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
7012 const DWORD indices6[] = {0, 1, 2, 3, 4, 5};
7013 const DWORD attributes6[] = {0, 0};
7014 const UINT num_vertices6 = ARRAY_SIZE(vertices6);
7015 const UINT num_faces6 = ARRAY_SIZE(indices6) / VERTS_PER_FACE;
7016 DWORD flags6 = D3DXWELDEPSILONS_WELDPARTIALMATCHES | D3DXWELDEPSILONS_DONOTREMOVEVERTICES;
7017 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};
7018 const DWORD adjacency6[] = {-1, 1, -1, -1, -1, 0};
7019 const struct vertex_normal exp_vertices6[] =
7021 {{ 0.0f, 3.0f, 0.f}, up},
7022 {{ 2.0f, 3.0f, 0.f}, up},
7023 {{ 0.0f, 0.0f, 0.f}, up},
7025 {{ 2.0f, 3.0f, 0.f}, up},
7026 {{ 3.0f, 0.0f, 0.f}, up},
7027 {{ 0.0f, 0.0f, 0.f}, up},
7030 const DWORD exp_indices6[] = {0, 1, 2, 3, 4, 5};
7031 const DWORD exp_face_remap6[] = {0, 1};
7032 const DWORD exp_vertex_remap6[] = {0, 1, 2, 3, 4, 5};
7033 const DWORD exp_new_num_vertices6 = ARRAY_SIZE(exp_vertices6);
7034 /* Test 7. Same as test 6 but with 16 bit indices. */
7035 const WORD indices6_16bit[] = {0, 1, 2, 3, 4, 5};
7036 /* Test 8. No flags. Same result as D3DXWELDEPSILONS_WELDPARTIALMATCHES. */
7037 const struct vertex_normal vertices8[] =
7039 {{ 0.0f, 3.0f, 0.f}, up},
7040 {{ 2.0f, 3.0f, 0.f}, up},
7041 {{ 0.0f, 0.0f, 0.f}, up},
7043 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
7044 {{ 3.0f, 0.0f, 0.f}, up},
7045 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
7047 const DWORD indices8[] = {0, 1, 2, 1, 3, 4};
7048 const DWORD attributes8[] = {0, 0};
7049 const UINT num_vertices8 = ARRAY_SIZE(vertices8);
7050 const UINT num_faces8 = ARRAY_SIZE(indices8) / VERTS_PER_FACE;
7051 DWORD flags8 = 0;
7052 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};
7053 const DWORD adjacency8[] = {-1, 1, -1, -1, -1, 0};
7054 const struct vertex_normal exp_vertices8[] =
7056 {{ 0.0f, 3.0f, 0.f}, up},
7057 {{ 2.0f, 3.0f, 0.f}, up},
7058 {{ 0.0f, 0.0f, 0.f}, up},
7060 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
7061 {{ 3.0f, 0.0f, 0.f}, up},
7063 const DWORD exp_indices8[] = {0, 1, 2, 1, 3, 4};
7064 const DWORD exp_face_remap8[] = {0, 1};
7065 const DWORD exp_vertex_remap8[] = {0, 1, 2, 3, 4, -1};
7066 const DWORD exp_new_num_vertices8 = ARRAY_SIZE(exp_vertices8);
7067 /* Test 9. Vertices are removed even though they belong to separate
7068 * attribute groups if D3DXWELDEPSILONS_DONOTSPLIT is set. */
7069 const struct vertex_normal vertices9[] =
7071 {{ 0.0f, 3.0f, 0.f}, up},
7072 {{ 2.0f, 3.0f, 0.f}, up},
7073 {{ 0.0f, 0.0f, 0.f}, up},
7075 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
7076 {{ 3.0f, 0.0f, 0.f}, up},
7077 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
7079 const DWORD indices9[] = {0, 1, 2, 3, 4, 5};
7080 const DWORD attributes9[] = {0, 1};
7081 const UINT num_vertices9 = ARRAY_SIZE(vertices9);
7082 const UINT num_faces9 = ARRAY_SIZE(indices9) / VERTS_PER_FACE;
7083 DWORD flags9 = D3DXWELDEPSILONS_WELDPARTIALMATCHES | D3DXWELDEPSILONS_DONOTSPLIT;
7084 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};
7085 const DWORD adjacency9[] = {-1, 1, -1, -1, -1, 0};
7086 const struct vertex_normal exp_vertices9[] =
7088 {{ 0.0f, 3.0f, 0.f}, up},
7089 {{ 2.0f, 3.0f, 0.f}, up},
7090 {{ 0.0f, 0.0f, 0.f}, up},
7092 {{ 3.0f, 0.0f, 0.f}, up},
7094 const DWORD exp_indices9[] = {0, 1, 2, 1, 3, 2};
7095 const DWORD exp_face_remap9[] = {0, 1};
7096 const DWORD exp_vertex_remap9[] = {0, 1, 2, 4, -1, -1};
7097 const DWORD exp_new_num_vertices9 = ARRAY_SIZE(exp_vertices9);
7098 /* Test 10. Weld blendweight (FLOAT1). */
7099 const struct vertex_blendweight vertices10[] =
7101 {{ 0.0f, 3.0f, 0.f}, 1.0f},
7102 {{ 2.0f, 3.0f, 0.f}, 1.0f},
7103 {{ 0.0f, 0.0f, 0.f}, 1.0f},
7105 {{ 3.0f, 3.0f, 0.f}, 0.9},
7106 {{ 3.0f, 0.0f, 0.f}, 1.0},
7107 {{ 1.0f, 0.0f, 0.f}, 0.4},
7109 const DWORD indices10[] = {0, 1, 2, 3, 4, 5};
7110 const DWORD attributes10[] = {0, 0};
7111 const UINT num_vertices10 = ARRAY_SIZE(vertices10);
7112 const UINT num_faces10 = ARRAY_SIZE(indices10) / VERTS_PER_FACE;
7113 DWORD flags10 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7114 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};
7115 const DWORD adjacency10[] = {-1, 1, -1, -1, -1, 0};
7116 const struct vertex_blendweight exp_vertices10[] =
7118 {{ 0.0f, 3.0f, 0.f}, 1.0f},
7119 {{ 2.0f, 3.0f, 0.f}, 1.0f},
7120 {{ 0.0f, 0.0f, 0.f}, 1.0f},
7122 {{ 3.0f, 0.0f, 0.f}, 1.0},
7123 {{ 0.0f, 0.0f, 0.f}, 0.4},
7125 const DWORD exp_indices10[] = {0, 1, 2, 1, 3, 4};
7126 const DWORD exp_face_remap10[] = {0, 1};
7127 const DWORD exp_vertex_remap10[] = {0, 1, 2, 4, 5, -1};
7128 const DWORD exp_new_num_vertices10 = ARRAY_SIZE(exp_vertices10);
7129 /* Test 11. Weld texture coordinates. */
7130 const struct vertex_texcoord vertices11[] =
7132 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f}},
7133 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.7f}},
7134 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
7136 {{ 3.0f, 3.0f, 0.f}, {0.2f, 0.3f}},
7137 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f}},
7138 {{ 1.0f, 0.0f, 0.f}, {0.1f, 0.2f}}
7140 const DWORD indices11[] = {0, 1, 2, 3, 4, 5};
7141 const DWORD attributes11[] = {0, 0};
7142 const UINT num_vertices11 = ARRAY_SIZE(vertices11);
7143 const UINT num_faces11 = ARRAY_SIZE(indices11) / VERTS_PER_FACE;
7144 DWORD flags11 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7145 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};
7146 const DWORD adjacency11[] = {-1, 1, -1, -1, -1, 0};
7147 const struct vertex_texcoord exp_vertices11[] =
7149 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f}},
7150 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.7f}},
7151 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
7153 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f}},
7154 {{ 0.0f, 0.0f, 0.f}, {0.1f, 0.2f}},
7156 const DWORD exp_indices11[] = {0, 1, 2, 1, 3, 4};
7157 const DWORD exp_face_remap11[] = {0, 1};
7158 const DWORD exp_vertex_remap11[] = {0, 1, 2, 4, 5, -1};
7159 const DWORD exp_new_num_vertices11 = ARRAY_SIZE(exp_vertices11);
7160 /* Test 12. Weld with color. */
7161 const struct vertex_color vertices12[] =
7163 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7164 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7165 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7167 {{ 3.0f, 3.0f, 0.f}, 0x00000000},
7168 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7169 {{ 1.0f, 0.0f, 0.f}, 0x88888888},
7171 const DWORD indices12[] = {0, 1, 2, 3, 4, 5};
7172 const DWORD attributes12[] = {0, 0};
7173 const UINT num_vertices12 = ARRAY_SIZE(vertices12);
7174 const UINT num_faces12 = ARRAY_SIZE(indices12) / VERTS_PER_FACE;
7175 DWORD flags12 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7176 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};
7177 const DWORD adjacency12[] = {-1, 1, -1, -1, -1, 0};
7178 const struct vertex_color exp_vertices12[] =
7180 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7181 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7182 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7184 {{ 2.0f, 3.0f, 0.f}, 0x00000000},
7185 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7187 const DWORD exp_indices12[] = {0, 1, 2, 3, 4, 2};
7188 const DWORD exp_face_remap12[] = {0, 1};
7189 const DWORD exp_vertex_remap12[] = {0, 1, 2, 3, 4, -1};
7190 const DWORD exp_new_num_vertices12 = ARRAY_SIZE(exp_vertices12);
7191 /* Test 13. Two faces. One vertex should be removed because of normal epsilon.
7192 * This is similar to test 3, but the declaration has been changed to NORMAL3.
7194 const struct vertex_normal vertices13[] =
7196 {{ 0.0f, 3.0f, 0.f}, up},
7197 {{ 2.0f, 3.0f, 0.f}, up},
7198 {{ 0.0f, 0.0f, 0.f}, up},
7200 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
7201 {{ 3.0f, 0.0f, 0.f}, up},
7202 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
7204 const DWORD indices13[] = {0, 1, 2, 3, 4, 5};
7205 const DWORD attributes13[] = {0, 0};
7206 const UINT num_vertices13 = ARRAY_SIZE(vertices3);
7207 const UINT num_faces13 = ARRAY_SIZE(indices3) / VERTS_PER_FACE;
7208 DWORD flags13 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7209 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};
7210 const DWORD adjacency13[] = {-1, 1, -1, -1, -1, 0};
7211 const struct vertex_normal exp_vertices13[] =
7213 {{ 0.0f, 3.0f, 0.f}, up},
7214 {{ 2.0f, 3.0f, 0.f}, up},
7215 {{ 0.0f, 0.0f, 0.f}, up},
7217 {{ 3.0f, 0.0f, 0.f}, up},
7218 {{ 0.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
7220 const DWORD exp_indices13[] = {0, 1, 2, 1, 3, 4};
7221 const DWORD exp_face_remap13[] = {0, 1};
7222 const DWORD exp_vertex_remap13[] = {0, 1, 2, 4, 5, -1};
7223 const DWORD exp_new_num_vertices13 = ARRAY_SIZE(exp_vertices13);
7224 /* Test 14. Another test for welding with color. */
7225 const struct vertex_color vertices14[] =
7227 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7228 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7229 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7231 {{ 3.0f, 3.0f, 0.f}, 0x00000000},
7232 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7233 {{ 1.0f, 0.0f, 0.f}, 0x01010101},
7235 const DWORD indices14[] = {0, 1, 2, 3, 4, 5};
7236 const DWORD attributes14[] = {0, 0};
7237 const UINT num_vertices14 = ARRAY_SIZE(vertices14);
7238 const UINT num_faces14 = ARRAY_SIZE(indices14) / VERTS_PER_FACE;
7239 DWORD flags14 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7240 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};
7241 const DWORD adjacency14[] = {-1, 1, -1, -1, -1, 0};
7242 const struct vertex_color exp_vertices14[] =
7244 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7245 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7246 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7248 {{ 2.0f, 3.0f, 0.f}, 0x00000000},
7249 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7251 const DWORD exp_indices14[] = {0, 1, 2, 3, 4, 2};
7252 const DWORD exp_face_remap14[] = {0, 1};
7253 const DWORD exp_vertex_remap14[] = {0, 1, 2, 3, 4, -1};
7254 const DWORD exp_new_num_vertices14 = ARRAY_SIZE(exp_vertices14);
7255 /* Test 15. Weld with color, but as UBYTE4N instead of D3DCOLOR. It shows
7256 * that UBYTE4N and D3DCOLOR are compared the same way.
7258 const struct vertex_color_ubyte4 vertices15[] =
7260 {{ 0.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7261 {{ 2.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7262 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7264 {{ 3.0f, 3.0f, 0.f}, { 0, 0, 0, 0}},
7265 {{ 3.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7266 {{ 1.0f, 0.0f, 0.f}, { 1, 1, 1, 1}},
7268 const DWORD indices15[] = {0, 1, 2, 3, 4, 5};
7269 const DWORD attributes15[] = {0, 0};
7270 const UINT num_vertices15 = ARRAY_SIZE(vertices15);
7271 const UINT num_faces15 = ARRAY_SIZE(indices15) / VERTS_PER_FACE;
7272 DWORD flags15 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7273 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};
7274 const DWORD adjacency15[] = {-1, 1, -1, -1, -1, 0};
7275 const struct vertex_color_ubyte4 exp_vertices15[] =
7277 {{ 0.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7278 {{ 2.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7279 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7281 {{ 2.0f, 3.0f, 0.f}, { 0, 0, 0, 0}},
7282 {{ 3.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7284 const DWORD exp_indices15[] = {0, 1, 2, 3, 4, 2};
7285 const DWORD exp_face_remap15[] = {0, 1};
7286 const DWORD exp_vertex_remap15[] = {0, 1, 2, 3, 4, -1};
7287 const DWORD exp_new_num_vertices15 = ARRAY_SIZE(exp_vertices15);
7288 /* Test 16. Weld with color, but as UBYTE4 instead of D3DCOLOR. It shows
7289 * that UBYTE4 is not normalized and that epsilon is truncated and compared
7290 * directly to each of the four bytes.
7292 const struct vertex_color_ubyte4 vertices16[] =
7294 {{ 0.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7295 {{ 2.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7296 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7298 {{ 3.0f, 3.0f, 0.f}, { 0, 0, 0, 0}},
7299 {{ 3.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7300 {{ 1.0f, 0.0f, 0.f}, { 1, 1, 1, 1}},
7302 const DWORD indices16[] = {0, 1, 2, 3, 4, 5};
7303 const DWORD attributes16[] = {0, 0};
7304 const UINT num_vertices16 = ARRAY_SIZE(vertices16);
7305 const UINT num_faces16 = ARRAY_SIZE(indices16) / VERTS_PER_FACE;
7306 DWORD flags16 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7307 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};
7308 const DWORD adjacency16[] = {-1, 1, -1, -1, -1, 0};
7309 const struct vertex_color_ubyte4 exp_vertices16[] =
7311 {{ 0.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7312 {{ 2.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7313 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7315 {{ 2.0f, 3.0f, 0.f}, { 0, 0, 0, 0}},
7316 {{ 3.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7318 const DWORD exp_indices16[] = {0, 1, 2, 3, 4, 2};
7319 const DWORD exp_face_remap16[] = {0, 1};
7320 const DWORD exp_vertex_remap16[] = {0, 1, 2, 3, 4, -1};
7321 const DWORD exp_new_num_vertices16 = ARRAY_SIZE(exp_vertices16);
7322 /* Test 17. Weld texture coordinates but as SHORT2 instead of D3DXVECTOR2.*/
7323 const struct vertex_texcoord_short2 vertices17[] =
7325 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7326 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7327 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7329 {{ 3.0f, 3.0f, 0.f}, {32767, 32767}},
7330 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7331 {{ 1.0f, 0.0f, 0.f}, {32766, 32766}},
7333 const DWORD indices17[] = {0, 1, 2, 3, 4, 5};
7334 const DWORD attributes17[] = {0, 0};
7335 const UINT num_vertices17 = ARRAY_SIZE(vertices17);
7336 const UINT num_faces17 = ARRAY_SIZE(indices17) / VERTS_PER_FACE;
7337 DWORD flags17 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7338 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};
7339 const DWORD adjacency17[] = {-1, 1, -1, -1, -1, 0};
7340 const struct vertex_texcoord_short2 exp_vertices17[] =
7342 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7343 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7344 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7346 {{ 2.0f, 3.0f, 0.f}, {32767, 32767}},
7347 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7349 const DWORD exp_indices17[] = {0, 1, 2, 3, 4, 2};
7350 const DWORD exp_face_remap17[] = {0, 1};
7351 const DWORD exp_vertex_remap17[] = {0, 1, 2, 3, 4, -1};
7352 const DWORD exp_new_num_vertices17 = ARRAY_SIZE(exp_vertices17);
7353 /* Test 18. Weld texture coordinates but as SHORT2N instead of D3DXVECTOR2. */
7354 const struct vertex_texcoord_short2 vertices18[] =
7356 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7357 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7358 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7360 {{ 3.0f, 3.0f, 0.f}, {32767, 32767}},
7361 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7362 {{ 1.0f, 0.0f, 0.f}, {32766, 32766}},
7364 const DWORD indices18[] = {0, 1, 2, 3, 4, 5};
7365 const DWORD attributes18[] = {0, 0};
7366 const UINT num_vertices18 = ARRAY_SIZE(vertices18);
7367 const UINT num_faces18 = ARRAY_SIZE(indices18) / VERTS_PER_FACE;
7368 DWORD flags18 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7369 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};
7370 const DWORD adjacency18[] = {-1, 1, -1, -1, -1, 0};
7371 const struct vertex_texcoord_short2 exp_vertices18[] =
7373 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7374 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7375 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7377 {{ 2.0f, 3.0f, 0.f}, {32767, 32767}},
7378 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7380 const DWORD exp_indices18[] = {0, 1, 2, 3, 4, 2};
7381 const DWORD exp_face_remap18[] = {0, 1};
7382 const DWORD exp_vertex_remap18[] = {0, 1, 2, 3, 4, -1};
7383 const DWORD exp_new_num_vertices18 = ARRAY_SIZE(exp_vertices18);
7384 /* Test 19. Weld texture coordinates but as USHORT2N instead of D3DXVECTOR2. */
7385 const struct vertex_texcoord_ushort2n vertices19[] =
7387 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7388 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7389 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7391 {{ 3.0f, 3.0f, 0.f}, {65535, 65535}},
7392 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7393 {{ 1.0f, 0.0f, 0.f}, {65534, 65534}},
7395 const DWORD indices19[] = {0, 1, 2, 3, 4, 5};
7396 const DWORD attributes19[] = {0, 0};
7397 const UINT num_vertices19 = ARRAY_SIZE(vertices19);
7398 const UINT num_faces19 = ARRAY_SIZE(indices19) / VERTS_PER_FACE;
7399 DWORD flags19 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7400 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};
7401 const DWORD adjacency19[] = {-1, 1, -1, -1, -1, 0};
7402 const struct vertex_texcoord_ushort2n exp_vertices19[] =
7404 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7405 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7406 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7408 {{ 2.0f, 3.0f, 0.f}, {65535, 65535}},
7409 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7411 const DWORD exp_indices19[] = {0, 1, 2, 3, 4, 2};
7412 const DWORD exp_face_remap19[] = {0, 1};
7413 const DWORD exp_vertex_remap19[] = {0, 1, 2, 3, 4, -1};
7414 const DWORD exp_new_num_vertices19 = ARRAY_SIZE(exp_vertices19);
7415 /* Test 20. Weld normal as SHORT4 instead of D3DXVECTOR3. */
7416 const struct vertex_normal_short4 vertices20[] =
7418 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7419 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7420 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7422 {{ 3.0f, 3.0f, 0.f}, {32767, 32767, 32767, 32767}},
7423 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7424 {{ 1.0f, 0.0f, 0.f}, {32766, 32766, 32766, 32766}},
7426 const DWORD indices20[] = {0, 1, 2, 3, 4, 5};
7427 const DWORD attributes20[] = {0, 0};
7428 const UINT num_vertices20 = ARRAY_SIZE(vertices20);
7429 const UINT num_faces20 = ARRAY_SIZE(indices20) / VERTS_PER_FACE;
7430 DWORD flags20 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7431 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};
7432 const DWORD adjacency20[] = {-1, 1, -1, -1, -1, 0};
7433 const struct vertex_normal_short4 exp_vertices20[] =
7435 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7436 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7437 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7439 {{ 2.0f, 3.0f, 0.f}, {32767, 32767, 32767, 32767}},
7440 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7442 const DWORD exp_indices20[] = {0, 1, 2, 3, 4, 2};
7443 const DWORD exp_face_remap20[] = {0, 1};
7444 const DWORD exp_vertex_remap20[] = {0, 1, 2, 3, 4, -1};
7445 const DWORD exp_new_num_vertices20 = ARRAY_SIZE(exp_vertices20);
7446 /* Test 21. Weld normal as SHORT4N instead of D3DXVECTOR3. */
7447 const struct vertex_normal_short4 vertices21[] =
7449 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7450 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7451 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7453 {{ 3.0f, 3.0f, 0.f}, {32767, 32767, 32767, 32767}},
7454 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7455 {{ 1.0f, 0.0f, 0.f}, {32766, 32766, 32766, 32766}},
7457 const DWORD indices21[] = {0, 1, 2, 3, 4, 5};
7458 const DWORD attributes21[] = {0, 0};
7459 const UINT num_vertices21 = ARRAY_SIZE(vertices21);
7460 const UINT num_faces21 = ARRAY_SIZE(indices21) / VERTS_PER_FACE;
7461 DWORD flags21 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7462 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};
7463 const DWORD adjacency21[] = {-1, 1, -1, -1, -1, 0};
7464 const struct vertex_normal_short4 exp_vertices21[] =
7466 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7467 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7468 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7470 {{ 2.0f, 3.0f, 0.f}, {32767, 32767, 32767, 32767}},
7471 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7473 const DWORD exp_indices21[] = {0, 1, 2, 3, 4, 2};
7474 const DWORD exp_face_remap21[] = {0, 1};
7475 const DWORD exp_vertex_remap21[] = {0, 1, 2, 3, 4, -1};
7476 const DWORD exp_new_num_vertices21 = ARRAY_SIZE(exp_vertices21);
7477 /* Test 22. Weld normal as USHORT4N instead of D3DXVECTOR3. */
7478 const struct vertex_normal_short4 vertices22[] =
7480 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7481 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7482 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7484 {{ 3.0f, 3.0f, 0.f}, {65535, 65535, 65535, 65535}},
7485 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7486 {{ 1.0f, 0.0f, 0.f}, {65534, 65534, 65534, 65534}},
7488 const DWORD indices22[] = {0, 1, 2, 3, 4, 5};
7489 const DWORD attributes22[] = {0, 0};
7490 const UINT num_vertices22 = ARRAY_SIZE(vertices22);
7491 const UINT num_faces22 = ARRAY_SIZE(indices22) / VERTS_PER_FACE;
7492 DWORD flags22 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7493 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};
7494 const DWORD adjacency22[] = {-1, 1, -1, -1, -1, 0};
7495 const struct vertex_normal_short4 exp_vertices22[] =
7497 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7498 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7499 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7501 {{ 2.0f, 3.0f, 0.f}, {65535, 65535, 65535, 65535}},
7502 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7504 const DWORD exp_indices22[] = {0, 1, 2, 3, 4, 2};
7505 const DWORD exp_face_remap22[] = {0, 1};
7506 const DWORD exp_vertex_remap22[] = {0, 1, 2, 3, 4, -1};
7507 const DWORD exp_new_num_vertices22 = ARRAY_SIZE(exp_vertices22);
7508 /* Test 23. Weld texture coordinates as FLOAT16_2. Similar to test 11, but
7509 * with texture coordinates converted to float16 in hex. */
7510 const struct vertex_texcoord_float16_2 vertices23[] =
7512 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
7513 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */
7514 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */
7516 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd}}, /* {0.2f, 0.3f} */
7517 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
7518 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */
7520 const DWORD indices23[] = {0, 1, 2, 3, 4, 5};
7521 const DWORD attributes23[] = {0, 0};
7522 const UINT num_vertices23 = ARRAY_SIZE(vertices23);
7523 const UINT num_faces23 = ARRAY_SIZE(indices23) / VERTS_PER_FACE;
7524 DWORD flags23 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7525 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};
7526 const DWORD adjacency23[] = {-1, 1, -1, -1, -1, 0};
7527 const struct vertex_texcoord_float16_2 exp_vertices23[] =
7529 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
7530 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */
7531 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */
7533 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
7534 {{ 0.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */
7536 const DWORD exp_indices23[] = {0, 1, 2, 1, 3, 4};
7537 const DWORD exp_face_remap23[] = {0, 1};
7538 const DWORD exp_vertex_remap23[] = {0, 1, 2, 4, 5, -1};
7539 const DWORD exp_new_num_vertices23 = ARRAY_SIZE(exp_vertices23);
7540 /* Test 24. Weld texture coordinates as FLOAT16_4. Similar to test 24. */
7541 const struct vertex_texcoord_float16_4 vertices24[] =
7543 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}},
7544 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a, 0x3800, 0x399a}},
7545 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd, 0xb266, 0xb4cd}},
7547 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd, 0x3266, 0x34cd}},
7548 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}},
7549 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266, 0x2e66, 0x3266}},
7551 const DWORD indices24[] = {0, 1, 2, 3, 4, 5};
7552 const DWORD attributes24[] = {0, 0};
7553 const UINT num_vertices24 = ARRAY_SIZE(vertices24);
7554 const UINT num_faces24 = ARRAY_SIZE(indices24) / VERTS_PER_FACE;
7555 DWORD flags24 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7556 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};
7557 const DWORD adjacency24[] = {-1, 1, -1, -1, -1, 0};
7558 const struct vertex_texcoord_float16_4 exp_vertices24[] =
7560 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}},
7561 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a, 0x3800, 0x399a}},
7562 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd, 0xb266, 0xb4cd}},
7564 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}},
7565 {{ 0.0f, 0.0f, 0.f}, {0x2e66, 0x3266, 0x2e66, 0x3266}},
7567 const DWORD exp_indices24[] = {0, 1, 2, 1, 3, 4};
7568 const DWORD exp_face_remap24[] = {0, 1};
7569 const DWORD exp_vertex_remap24[] = {0, 1, 2, 4, 5, -1};
7570 const DWORD exp_new_num_vertices24 = ARRAY_SIZE(exp_vertices24);
7571 /* Test 25. Weld texture coordinates with usage index 10 (TEXCOORD10). The
7572 * usage index is capped at 7, so the epsilon for TEXCOORD7 is used instead.
7574 const struct vertex_texcoord vertices25[] =
7576 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f}},
7577 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.7f}},
7578 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
7580 {{ 3.0f, 3.0f, 0.f}, {0.2f, 0.3f}},
7581 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f}},
7582 {{ 1.0f, 0.0f, 0.f}, {0.1f, 0.2f}}
7584 const DWORD indices25[] = {0, 1, 2, 3, 4, 5};
7585 const DWORD attributes25[] = {0, 0};
7586 const UINT num_vertices25 = ARRAY_SIZE(vertices25);
7587 const UINT num_faces25 = ARRAY_SIZE(indices25) / VERTS_PER_FACE;
7588 DWORD flags25 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7589 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};
7590 const DWORD adjacency25[] = {-1, 1, -1, -1, -1, 0};
7591 const struct vertex_texcoord exp_vertices25[] =
7593 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f}},
7594 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.7f}},
7595 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
7597 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f}},
7598 {{ 0.0f, 0.0f, 0.f}, {0.1f, 0.2f}},
7600 const DWORD exp_indices25[] = {0, 1, 2, 1, 3, 4};
7601 const DWORD exp_face_remap25[] = {0, 1};
7602 const DWORD exp_vertex_remap25[] = {0, 1, 2, 4, 5, -1};
7603 const DWORD exp_new_num_vertices25 = ARRAY_SIZE(exp_vertices25);
7604 /* Test 26. Weld color with usage index larger than 1. Shows that none of
7605 * the epsilon values are used. */
7606 const struct vertex_color vertices26[] =
7608 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7609 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7610 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7612 {{ 3.0f, 3.0f, 0.f}, 0x00000000},
7613 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7614 {{ 1.0f, 0.0f, 0.f}, 0x01010101},
7616 const DWORD indices26[] = {0, 1, 2, 3, 4, 5};
7617 const DWORD attributes26[] = {0, 0};
7618 const UINT num_vertices26 = ARRAY_SIZE(vertices26);
7619 const UINT num_faces26 = ARRAY_SIZE(indices26) / VERTS_PER_FACE;
7620 DWORD flags26 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7621 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};
7622 const DWORD adjacency26[] = {-1, 1, -1, -1, -1, 0};
7623 const struct vertex_color exp_vertices26[] =
7625 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7626 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7627 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7629 {{ 2.0f, 3.0f, 0.f}, 0x00000000},
7630 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7631 {{ 0.0f, 0.0f, 0.f}, 0x01010101},
7633 const DWORD exp_indices26[] = {0, 1, 2, 3, 4, 5};
7634 const DWORD exp_face_remap26[] = {0, 1};
7635 const DWORD exp_vertex_remap26[] = {0, 1, 2, 3, 4, 5};
7636 const DWORD exp_new_num_vertices26 = ARRAY_SIZE(exp_vertices26);
7637 /* Test 27. Weld color with usage index 1 (specular). */
7638 /* Previously this test used float color values and index > 1 but that case
7639 * appears to be effectively unhandled in native so the test gave
7640 * inconsistent results. */
7641 const struct vertex_color vertices27[] =
7643 {{ 0.0f, 3.0f, 0.0f}, 0x00000000},
7644 {{ 2.0f, 3.0f, 0.0f}, 0x10203040},
7645 {{ 0.0f, 0.0f, 0.0f}, 0x50607080},
7647 {{ 3.0f, 3.0f, 0.0f}, 0x11213141},
7648 {{ 3.0f, 0.0f, 0.0f}, 0xffffffff},
7649 {{ 1.0f, 0.0f, 0.0f}, 0x51617181},
7651 const DWORD indices27[] = {0, 1, 2, 3, 4, 5};
7652 const DWORD attributes27[] = {0, 0};
7653 const UINT num_vertices27 = ARRAY_SIZE(vertices27);
7654 const UINT num_faces27 = ARRAY_SIZE(indices27) / VERTS_PER_FACE;
7655 DWORD flags27 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7656 const D3DXWELDEPSILONS epsilons27 =
7658 1.1f, 0.0f, 0.0f, 0.0f, 2.0f / 255.0f, 0.0f,
7659 {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, 0.0f, 0.0f, 0.0f
7661 const DWORD adjacency27[] = {-1, 1, -1, -1, -1, 0};
7662 const struct vertex_color exp_vertices27[] =
7664 {{ 0.0f, 3.0f, 0.0f}, 0x00000000},
7665 {{ 2.0f, 3.0f, 0.0f}, 0x10203040},
7666 {{ 0.0f, 0.0f, 0.0f}, 0x50607080},
7668 {{ 3.0f, 0.0f, 0.0f}, 0xffffffff},
7670 const DWORD exp_indices27[] = {0, 1, 2, 1, 3, 2};
7671 const DWORD exp_face_remap27[] = {0, 1};
7672 const DWORD exp_vertex_remap27[] = {0, 1, 2, 4, -1, -1};
7673 const DWORD exp_new_num_vertices27 = ARRAY_SIZE(exp_vertices27);
7674 /* Test 28. Weld one normal with UDEC3. */
7675 const DWORD dword_udec3_zero = init_udec3_dword(0, 0, 0, 1);
7676 const DWORD dword_udec3_1023 = init_udec3_dword(1023, 1023, 1023, 1);
7677 const DWORD dword_udec3_1022 = init_udec3_dword(1022, 1022, 1022, 1);
7678 const struct vertex_normal_udec3 vertices28[] =
7680 {{ 0.0f, 3.0f, 0.f}, dword_udec3_zero},
7681 {{ 2.0f, 3.0f, 0.f}, dword_udec3_zero},
7682 {{ 0.0f, 0.0f, 0.f}, dword_udec3_zero},
7684 {{ 3.0f, 3.0f, 0.f}, dword_udec3_1023},
7685 {{ 3.0f, 0.0f, 0.f}, dword_udec3_zero},
7686 {{ 1.0f, 0.0f, 0.f}, dword_udec3_1022},
7688 const DWORD indices28[] = {0, 1, 2, 3, 4, 5};
7689 const DWORD attributes28[] = {0, 0};
7690 const UINT num_vertices28 = ARRAY_SIZE(vertices28);
7691 const UINT num_faces28 = ARRAY_SIZE(indices28) / VERTS_PER_FACE;
7692 DWORD flags28 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7693 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};
7694 const DWORD adjacency28[] = {-1, 1, -1, -1, -1, 0};
7695 const struct vertex_normal_udec3 exp_vertices28[] =
7697 {{ 0.0f, 3.0f, 0.f}, dword_udec3_zero},
7698 {{ 2.0f, 3.0f, 0.f}, dword_udec3_zero},
7699 {{ 0.0f, 0.0f, 0.f}, dword_udec3_zero},
7701 {{ 2.0f, 3.0f, 0.f}, dword_udec3_1023},
7702 {{ 3.0f, 0.0f, 0.f}, dword_udec3_zero},
7704 const DWORD exp_indices28[] = {0, 1, 2, 3, 4, 2};
7705 const DWORD exp_face_remap28[] = {0, 1};
7706 const DWORD exp_vertex_remap28[] = {0, 1, 2, 3, 4, -1};
7707 const DWORD exp_new_num_vertices28 = ARRAY_SIZE(exp_vertices28);
7708 /* Test 29. Weld one normal with DEC3N. */
7709 const DWORD dword_dec3n_zero = init_dec3n_dword(0, 0, 0, 1);
7710 const DWORD dword_dec3n_511 = init_dec3n_dword(511, 511, 511, 1);
7711 const DWORD dword_dec3n_510 = init_dec3n_dword(510, 510, 510, 1);
7712 const struct vertex_normal_dec3n vertices29[] =
7714 {{ 0.0f, 3.0f, 0.f}, dword_dec3n_zero},
7715 {{ 2.0f, 3.0f, 0.f}, dword_dec3n_zero},
7716 {{ 0.0f, 0.0f, 0.f}, dword_dec3n_zero},
7718 {{ 3.0f, 3.0f, 0.f}, dword_dec3n_511},
7719 {{ 3.0f, 0.0f, 0.f}, dword_dec3n_zero},
7720 {{ 1.0f, 0.0f, 0.f}, dword_dec3n_510},
7722 const DWORD indices29[] = {0, 1, 2, 3, 4, 5};
7723 const DWORD attributes29[] = {0, 0};
7724 const UINT num_vertices29 = ARRAY_SIZE(vertices29);
7725 const UINT num_faces29 = ARRAY_SIZE(indices29) / VERTS_PER_FACE;
7726 DWORD flags29 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7727 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};
7728 const DWORD adjacency29[] = {-1, 1, -1, -1, -1, 0};
7729 const struct vertex_normal_dec3n exp_vertices29[] =
7731 {{ 0.0f, 3.0f, 0.f}, dword_dec3n_zero},
7732 {{ 2.0f, 3.0f, 0.f}, dword_dec3n_zero},
7733 {{ 0.0f, 0.0f, 0.f}, dword_dec3n_zero},
7735 {{ 2.0f, 3.0f, 0.f}, dword_dec3n_511},
7736 {{ 3.0f, 0.0f, 0.f}, dword_dec3n_zero},
7738 const DWORD exp_indices29[] = {0, 1, 2, 3, 4, 2};
7739 const DWORD exp_face_remap29[] = {0, 1};
7740 const DWORD exp_vertex_remap29[] = {0, 1, 2, 3, 4, -1};
7741 const DWORD exp_new_num_vertices29 = ARRAY_SIZE(exp_vertices29);
7742 /* All mesh data */
7743 DWORD *adjacency_out = NULL;
7744 DWORD *face_remap = NULL;
7745 ID3DXMesh *mesh = NULL;
7746 ID3DXBuffer *vertex_remap = NULL;
7747 struct
7749 const BYTE *vertices;
7750 const DWORD *indices;
7751 const DWORD *attributes;
7752 const DWORD num_vertices;
7753 const DWORD num_faces;
7754 const DWORD options;
7755 D3DVERTEXELEMENT9 *declaration;
7756 const UINT vertex_size;
7757 const DWORD flags;
7758 const D3DXWELDEPSILONS *epsilons;
7759 const DWORD *adjacency;
7760 const BYTE *exp_vertices;
7761 const DWORD *exp_indices;
7762 const DWORD *exp_face_remap;
7763 const DWORD *exp_vertex_remap;
7764 const DWORD exp_new_num_vertices;
7766 tc[] =
7769 (BYTE*)vertices0,
7770 indices0,
7771 attributes0,
7772 num_vertices0,
7773 num_faces0,
7774 options,
7775 declaration_normal,
7776 vertex_size_normal,
7777 flags0,
7778 NULL,
7779 adjacency0,
7780 (BYTE*)exp_vertices0,
7781 exp_indices0,
7782 exp_face_remap0,
7783 exp_vertex_remap0,
7784 exp_new_num_vertices0
7787 (BYTE*)vertices1,
7788 indices1,
7789 attributes1,
7790 num_vertices1,
7791 num_faces1,
7792 options,
7793 declaration_normal,
7794 vertex_size_normal,
7795 flags1,
7796 NULL,
7797 adjacency1,
7798 (BYTE*)exp_vertices1,
7799 exp_indices1,
7800 exp_face_remap1,
7801 exp_vertex_remap1,
7802 exp_new_num_vertices1
7805 (BYTE*)vertices2,
7806 indices2,
7807 attributes2,
7808 num_vertices2,
7809 num_faces2,
7810 options,
7811 declaration_normal,
7812 vertex_size_normal,
7813 flags2,
7814 &epsilons2,
7815 adjacency2,
7816 (BYTE*)exp_vertices2,
7817 exp_indices2,
7818 exp_face_remap2,
7819 exp_vertex_remap2,
7820 exp_new_num_vertices2
7823 (BYTE*)vertices3,
7824 indices3,
7825 attributes3,
7826 num_vertices3,
7827 num_faces3,
7828 options,
7829 declaration_normal,
7830 vertex_size_normal,
7831 flags3,
7832 &epsilons3,
7833 adjacency3,
7834 (BYTE*)exp_vertices3,
7835 exp_indices3,
7836 exp_face_remap3,
7837 exp_vertex_remap3,
7838 exp_new_num_vertices3
7841 (BYTE*)vertices4,
7842 indices4,
7843 attributes4,
7844 num_vertices4,
7845 num_faces4,
7846 options,
7847 declaration_normal,
7848 vertex_size_normal,
7849 flags4,
7850 &epsilons4,
7851 adjacency4,
7852 (BYTE*)exp_vertices4,
7853 exp_indices4,
7854 exp_face_remap4,
7855 exp_vertex_remap4,
7856 exp_new_num_vertices4
7858 /* Unusual ordering. */
7860 (BYTE*)vertices5,
7861 indices5,
7862 attributes5,
7863 num_vertices5,
7864 num_faces5,
7865 options,
7866 declaration_normal,
7867 vertex_size_normal,
7868 flags5,
7869 NULL,
7870 adjacency5,
7871 (BYTE*)exp_vertices5,
7872 exp_indices5,
7873 exp_face_remap5,
7874 exp_vertex_remap5,
7875 exp_new_num_vertices5
7878 (BYTE*)vertices6,
7879 indices6,
7880 attributes6,
7881 num_vertices6,
7882 num_faces6,
7883 options,
7884 declaration_normal,
7885 vertex_size_normal,
7886 flags6,
7887 &epsilons6,
7888 adjacency6,
7889 (BYTE*)exp_vertices6,
7890 exp_indices6,
7891 exp_face_remap6,
7892 exp_vertex_remap6,
7893 exp_new_num_vertices6
7896 (BYTE*)vertices6,
7897 (DWORD*)indices6_16bit,
7898 attributes6,
7899 num_vertices6,
7900 num_faces6,
7901 options_16bit,
7902 declaration_normal,
7903 vertex_size_normal,
7904 flags6,
7905 &epsilons6,
7906 adjacency6,
7907 (BYTE*)exp_vertices6,
7908 exp_indices6,
7909 exp_face_remap6,
7910 exp_vertex_remap6,
7911 exp_new_num_vertices6
7914 (BYTE*)vertices8,
7915 indices8,
7916 attributes8,
7917 num_vertices8,
7918 num_faces8,
7919 options,
7920 declaration_normal,
7921 vertex_size_normal,
7922 flags8,
7923 &epsilons8,
7924 adjacency8,
7925 (BYTE*)exp_vertices8,
7926 exp_indices8,
7927 exp_face_remap8,
7928 exp_vertex_remap8,
7929 exp_new_num_vertices8
7932 (BYTE*)vertices9,
7933 indices9,
7934 attributes9,
7935 num_vertices9,
7936 num_faces9,
7937 options,
7938 declaration_normal,
7939 vertex_size_normal,
7940 flags9,
7941 &epsilons9,
7942 adjacency9,
7943 (BYTE*)exp_vertices9,
7944 exp_indices9,
7945 exp_face_remap9,
7946 exp_vertex_remap9,
7947 exp_new_num_vertices9
7950 (BYTE*)vertices10,
7951 indices10,
7952 attributes10,
7953 num_vertices10,
7954 num_faces10,
7955 options,
7956 declaration_blendweight,
7957 vertex_size_blendweight,
7958 flags10,
7959 &epsilons10,
7960 adjacency10,
7961 (BYTE*)exp_vertices10,
7962 exp_indices10,
7963 exp_face_remap10,
7964 exp_vertex_remap10,
7965 exp_new_num_vertices10
7968 (BYTE*)vertices11,
7969 indices11,
7970 attributes11,
7971 num_vertices11,
7972 num_faces11,
7973 options,
7974 declaration_texcoord,
7975 vertex_size_texcoord,
7976 flags11,
7977 &epsilons11,
7978 adjacency11,
7979 (BYTE*)exp_vertices11,
7980 exp_indices11,
7981 exp_face_remap11,
7982 exp_vertex_remap11,
7983 exp_new_num_vertices11
7986 (BYTE*)vertices12,
7987 indices12,
7988 attributes12,
7989 num_vertices12,
7990 num_faces12,
7991 options,
7992 declaration_color,
7993 vertex_size_color,
7994 flags12,
7995 &epsilons12,
7996 adjacency12,
7997 (BYTE*)exp_vertices12,
7998 exp_indices12,
7999 exp_face_remap12,
8000 exp_vertex_remap12,
8001 exp_new_num_vertices12
8004 (BYTE*)vertices13,
8005 indices13,
8006 attributes13,
8007 num_vertices13,
8008 num_faces13,
8009 options,
8010 declaration_normal3,
8011 vertex_size_normal,
8012 flags13,
8013 &epsilons13,
8014 adjacency13,
8015 (BYTE*)exp_vertices13,
8016 exp_indices13,
8017 exp_face_remap13,
8018 exp_vertex_remap13,
8019 exp_new_num_vertices13
8022 (BYTE*)vertices14,
8023 indices14,
8024 attributes14,
8025 num_vertices14,
8026 num_faces14,
8027 options,
8028 declaration_color,
8029 vertex_size_color,
8030 flags14,
8031 &epsilons14,
8032 adjacency14,
8033 (BYTE*)exp_vertices14,
8034 exp_indices14,
8035 exp_face_remap14,
8036 exp_vertex_remap14,
8037 exp_new_num_vertices14
8040 (BYTE*)vertices15,
8041 indices15,
8042 attributes15,
8043 num_vertices15,
8044 num_faces15,
8045 options,
8046 declaration_color_ubyte4n,
8047 vertex_size_color_ubyte4, /* UBYTE4 same size as UBYTE4N */
8048 flags15,
8049 &epsilons15,
8050 adjacency15,
8051 (BYTE*)exp_vertices15,
8052 exp_indices15,
8053 exp_face_remap15,
8054 exp_vertex_remap15,
8055 exp_new_num_vertices15
8058 (BYTE*)vertices16,
8059 indices16,
8060 attributes16,
8061 num_vertices16,
8062 num_faces16,
8063 options,
8064 declaration_color_ubyte4,
8065 vertex_size_color_ubyte4,
8066 flags16,
8067 &epsilons16,
8068 adjacency16,
8069 (BYTE*)exp_vertices16,
8070 exp_indices16,
8071 exp_face_remap16,
8072 exp_vertex_remap16,
8073 exp_new_num_vertices16
8076 (BYTE*)vertices17,
8077 indices17,
8078 attributes17,
8079 num_vertices17,
8080 num_faces17,
8081 options,
8082 declaration_texcoord_short2,
8083 vertex_size_texcoord_short2,
8084 flags17,
8085 &epsilons17,
8086 adjacency17,
8087 (BYTE*)exp_vertices17,
8088 exp_indices17,
8089 exp_face_remap17,
8090 exp_vertex_remap17,
8091 exp_new_num_vertices17
8094 (BYTE*)vertices18,
8095 indices18,
8096 attributes18,
8097 num_vertices18,
8098 num_faces18,
8099 options,
8100 declaration_texcoord_short2n,
8101 vertex_size_texcoord_short2, /* SHORT2 same size as SHORT2N */
8102 flags18,
8103 &epsilons18,
8104 adjacency18,
8105 (BYTE*)exp_vertices18,
8106 exp_indices18,
8107 exp_face_remap18,
8108 exp_vertex_remap18,
8109 exp_new_num_vertices18
8112 (BYTE*)vertices19,
8113 indices19,
8114 attributes19,
8115 num_vertices19,
8116 num_faces19,
8117 options,
8118 declaration_texcoord_ushort2n,
8119 vertex_size_texcoord_short2, /* SHORT2 same size as USHORT2N */
8120 flags19,
8121 &epsilons19,
8122 adjacency19,
8123 (BYTE*)exp_vertices19,
8124 exp_indices19,
8125 exp_face_remap19,
8126 exp_vertex_remap19,
8127 exp_new_num_vertices19
8130 (BYTE*)vertices20,
8131 indices20,
8132 attributes20,
8133 num_vertices20,
8134 num_faces20,
8135 options,
8136 declaration_normal_short4,
8137 vertex_size_normal_short4,
8138 flags20,
8139 &epsilons20,
8140 adjacency20,
8141 (BYTE*)exp_vertices20,
8142 exp_indices20,
8143 exp_face_remap20,
8144 exp_vertex_remap20,
8145 exp_new_num_vertices20
8148 (BYTE*)vertices21,
8149 indices21,
8150 attributes21,
8151 num_vertices21,
8152 num_faces21,
8153 options,
8154 declaration_normal_short4n,
8155 vertex_size_normal_short4, /* SHORT4 same size as SHORT4N */
8156 flags21,
8157 &epsilons21,
8158 adjacency21,
8159 (BYTE*)exp_vertices21,
8160 exp_indices21,
8161 exp_face_remap21,
8162 exp_vertex_remap21,
8163 exp_new_num_vertices21
8166 (BYTE*)vertices22,
8167 indices22,
8168 attributes22,
8169 num_vertices22,
8170 num_faces22,
8171 options,
8172 declaration_normal_ushort4n,
8173 vertex_size_normal_short4, /* SHORT4 same size as USHORT4N */
8174 flags22,
8175 &epsilons22,
8176 adjacency22,
8177 (BYTE*)exp_vertices22,
8178 exp_indices22,
8179 exp_face_remap22,
8180 exp_vertex_remap22,
8181 exp_new_num_vertices22
8184 (BYTE*)vertices23,
8185 indices23,
8186 attributes23,
8187 num_vertices23,
8188 num_faces23,
8189 options,
8190 declaration_texcoord_float16_2,
8191 vertex_size_texcoord_float16_2,
8192 flags23,
8193 &epsilons23,
8194 adjacency23,
8195 (BYTE*)exp_vertices23,
8196 exp_indices23,
8197 exp_face_remap23,
8198 exp_vertex_remap23,
8199 exp_new_num_vertices23
8202 (BYTE*)vertices24,
8203 indices24,
8204 attributes24,
8205 num_vertices24,
8206 num_faces24,
8207 options,
8208 declaration_texcoord_float16_4,
8209 vertex_size_texcoord_float16_4,
8210 flags24,
8211 &epsilons24,
8212 adjacency24,
8213 (BYTE*)exp_vertices24,
8214 exp_indices24,
8215 exp_face_remap24,
8216 exp_vertex_remap24,
8217 exp_new_num_vertices24
8220 (BYTE*)vertices25,
8221 indices25,
8222 attributes25,
8223 num_vertices25,
8224 num_faces25,
8225 options,
8226 declaration_texcoord10,
8227 vertex_size_texcoord,
8228 flags25,
8229 &epsilons25,
8230 adjacency25,
8231 (BYTE*)exp_vertices25,
8232 exp_indices25,
8233 exp_face_remap25,
8234 exp_vertex_remap25,
8235 exp_new_num_vertices25
8238 (BYTE*)vertices26,
8239 indices26,
8240 attributes26,
8241 num_vertices26,
8242 num_faces26,
8243 options,
8244 declaration_color2,
8245 vertex_size_color,
8246 flags26,
8247 &epsilons26,
8248 adjacency26,
8249 (BYTE*)exp_vertices26,
8250 exp_indices26,
8251 exp_face_remap26,
8252 exp_vertex_remap26,
8253 exp_new_num_vertices26
8256 (BYTE*)vertices27,
8257 indices27,
8258 attributes27,
8259 num_vertices27,
8260 num_faces27,
8261 options,
8262 declaration_color1,
8263 vertex_size_color,
8264 flags27,
8265 &epsilons27,
8266 adjacency27,
8267 (BYTE*)exp_vertices27,
8268 exp_indices27,
8269 exp_face_remap27,
8270 exp_vertex_remap27,
8271 exp_new_num_vertices27
8274 (BYTE*)vertices28,
8275 indices28,
8276 attributes28,
8277 num_vertices28,
8278 num_faces28,
8279 options,
8280 declaration_normal_udec3,
8281 vertex_size_normal_udec3,
8282 flags28,
8283 &epsilons28,
8284 adjacency28,
8285 (BYTE*)exp_vertices28,
8286 exp_indices28,
8287 exp_face_remap28,
8288 exp_vertex_remap28,
8289 exp_new_num_vertices28
8292 (BYTE*)vertices29,
8293 indices29,
8294 attributes29,
8295 num_vertices29,
8296 num_faces29,
8297 options,
8298 declaration_normal_dec3n,
8299 vertex_size_normal_dec3n,
8300 flags29,
8301 &epsilons29,
8302 adjacency29,
8303 (BYTE*)exp_vertices29,
8304 exp_indices29,
8305 exp_face_remap29,
8306 exp_vertex_remap29,
8307 exp_new_num_vertices29
8311 test_context = new_test_context();
8312 if (!test_context)
8314 skip("Couldn't create test context\n");
8315 goto cleanup;
8318 for (i = 0; i < ARRAY_SIZE(tc); i++)
8320 DWORD j;
8321 DWORD *vertex_remap_ptr;
8322 DWORD new_num_vertices;
8324 hr = init_test_mesh(tc[i].num_faces, tc[i].num_vertices, tc[i].options,
8325 tc[i].declaration, test_context->device, &mesh,
8326 tc[i].vertices, tc[i].vertex_size,
8327 tc[i].indices, tc[i].attributes);
8328 if (FAILED(hr))
8330 skip("Couldn't initialize test mesh %d.\n", i);
8331 goto cleanup;
8334 /* Allocate out parameters */
8335 adjacency_out = HeapAlloc(GetProcessHeap(), 0, VERTS_PER_FACE * tc[i].num_faces * sizeof(*adjacency_out));
8336 if (!adjacency_out)
8338 skip("Couldn't allocate adjacency_out array.\n");
8339 goto cleanup;
8341 face_remap = HeapAlloc(GetProcessHeap(), 0, tc[i].num_faces * sizeof(*face_remap));
8342 if (!face_remap)
8344 skip("Couldn't allocate face_remap array.\n");
8345 goto cleanup;
8348 hr = D3DXWeldVertices(mesh, tc[i].flags, tc[i].epsilons, tc[i].adjacency,
8349 adjacency_out, face_remap, &vertex_remap);
8350 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
8351 /* Check number of vertices*/
8352 new_num_vertices = mesh->lpVtbl->GetNumVertices(mesh);
8353 ok(new_num_vertices == tc[i].exp_new_num_vertices,
8354 "Mesh %d: new_num_vertices == %d, expected %d.\n",
8355 i, new_num_vertices, tc[i].exp_new_num_vertices);
8356 /* Check index buffer */
8357 if (tc[i].options & D3DXMESH_32BIT)
8359 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, (void**)&indices);
8360 if (FAILED(hr))
8362 skip("Couldn't lock index buffer.\n");
8363 goto cleanup;
8365 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
8367 ok(indices[j] == tc[i].exp_indices[j],
8368 "Mesh %d: indices[%d] == %d, expected %d\n",
8369 i, j, indices[j], tc[i].exp_indices[j]);
8372 else
8374 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, (void**)&indices_16bit);
8375 if (FAILED(hr))
8377 skip("Couldn't lock index buffer.\n");
8378 goto cleanup;
8380 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
8382 ok(indices_16bit[j] == tc[i].exp_indices[j],
8383 "Mesh %d: indices_16bit[%d] == %d, expected %d\n",
8384 i, j, indices_16bit[j], tc[i].exp_indices[j]);
8387 mesh->lpVtbl->UnlockIndexBuffer(mesh);
8388 indices = NULL;
8389 indices_16bit = NULL;
8390 /* Check adjacency_out */
8391 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
8393 ok(adjacency_out[j] == tc[i].adjacency[j],
8394 "Mesh %d: adjacency_out[%d] == %d, expected %d\n",
8395 i, j, adjacency_out[j], tc[i].adjacency[j]);
8397 /* Check face_remap */
8398 for (j = 0; j < tc[i].num_faces; j++)
8400 ok(face_remap[j] == tc[i].exp_face_remap[j],
8401 "Mesh %d: face_remap[%d] == %d, expected %d\n",
8402 i, j, face_remap[j], tc[i].exp_face_remap[j]);
8404 /* Check vertex_remap */
8405 vertex_remap_ptr = vertex_remap->lpVtbl->GetBufferPointer(vertex_remap);
8406 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
8408 ok(vertex_remap_ptr[j] == tc[i].exp_vertex_remap[j],
8409 "Mesh %d: vertex_remap_ptr[%d] == %d, expected %d\n",
8410 i, j, vertex_remap_ptr[j], tc[i].exp_vertex_remap[j]);
8412 /* Check vertex buffer */
8413 hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, (void*)&vertices);
8414 if (FAILED(hr))
8416 skip("Couldn't lock vertex buffer.\n");
8417 goto cleanup;
8419 /* Check contents of re-ordered vertex buffer */
8420 for (j = 0; j < tc[i].exp_new_num_vertices; j++)
8422 int index = tc[i].vertex_size*j;
8423 check_vertex_components(__LINE__, i, j, &vertices[index], &tc[i].exp_vertices[index], tc[i].declaration);
8425 mesh->lpVtbl->UnlockVertexBuffer(mesh);
8426 vertices = NULL;
8428 /* Free mesh and output data */
8429 HeapFree(GetProcessHeap(), 0, adjacency_out);
8430 adjacency_out = NULL;
8431 HeapFree(GetProcessHeap(), 0, face_remap);
8432 face_remap = NULL;
8433 vertex_remap->lpVtbl->Release(vertex_remap);
8434 vertex_remap = NULL;
8435 mesh->lpVtbl->Release(mesh);
8436 mesh = NULL;
8439 cleanup:
8440 HeapFree(GetProcessHeap(), 0, adjacency_out);
8441 HeapFree(GetProcessHeap(), 0, face_remap);
8442 if (indices) mesh->lpVtbl->UnlockIndexBuffer(mesh);
8443 if (indices_16bit) mesh->lpVtbl->UnlockIndexBuffer(mesh);
8444 if (mesh) mesh->lpVtbl->Release(mesh);
8445 if (vertex_remap) vertex_remap->lpVtbl->Release(vertex_remap);
8446 if (vertices) mesh->lpVtbl->UnlockVertexBuffer(mesh);
8447 free_test_context(test_context);
8450 static void test_clone_mesh(void)
8452 HRESULT hr;
8453 struct test_context *test_context = NULL;
8454 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
8455 D3DVERTEXELEMENT9 declaration_pn[] =
8457 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8458 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
8459 D3DDECL_END()
8461 D3DVERTEXELEMENT9 declaration_pntc[] =
8463 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8464 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
8465 {0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8466 D3DDECL_END()
8468 D3DVERTEXELEMENT9 declaration_ptcn[] =
8470 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8471 {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8472 {0, 20, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
8473 D3DDECL_END()
8475 D3DVERTEXELEMENT9 declaration_ptc[] =
8477 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8478 {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8479 D3DDECL_END()
8481 D3DVERTEXELEMENT9 declaration_ptc_float16_2[] =
8483 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8484 {0, 12, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8485 D3DDECL_END()
8487 D3DVERTEXELEMENT9 declaration_ptc_float16_4[] =
8489 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8490 {0, 12, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8491 D3DDECL_END()
8493 D3DVERTEXELEMENT9 declaration_ptc_float1[] =
8495 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8496 {0, 12, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8497 D3DDECL_END()
8499 D3DVERTEXELEMENT9 declaration_ptc_float3[] =
8501 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8502 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8503 D3DDECL_END()
8505 D3DVERTEXELEMENT9 declaration_ptc_float4[] =
8507 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8508 {0, 12, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8509 D3DDECL_END()
8511 D3DVERTEXELEMENT9 declaration_ptc_d3dcolor[] =
8513 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8514 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8515 D3DDECL_END()
8517 D3DVERTEXELEMENT9 declaration_ptc_ubyte4[] =
8519 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8520 {0, 12, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8521 D3DDECL_END()
8523 D3DVERTEXELEMENT9 declaration_ptc_ubyte4n[] =
8525 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8526 {0, 12, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8527 D3DDECL_END()
8529 D3DVERTEXELEMENT9 declaration_ptc_short2[] =
8531 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8532 {0, 12, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8533 D3DDECL_END()
8535 D3DVERTEXELEMENT9 declaration_ptc_short4[] =
8537 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8538 {0, 12, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8539 D3DDECL_END()
8541 D3DVERTEXELEMENT9 declaration_ptc_short2n[] =
8543 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8544 {0, 12, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8545 D3DDECL_END()
8547 D3DVERTEXELEMENT9 declaration_ptc_short4n[] =
8549 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8550 {0, 12, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8551 D3DDECL_END()
8553 D3DVERTEXELEMENT9 declaration_ptc_ushort2n[] =
8555 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8556 {0, 12, D3DDECLTYPE_USHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8557 D3DDECL_END()
8559 D3DVERTEXELEMENT9 declaration_ptc_ushort4n[] =
8561 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8562 {0, 12, D3DDECLTYPE_USHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8563 D3DDECL_END()
8565 D3DVERTEXELEMENT9 declaration_ptc_float16_2_partialu[] =
8567 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8568 {0, 12, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_PARTIALU, D3DDECLUSAGE_TEXCOORD, 0},
8569 D3DDECL_END()
8571 D3DVERTEXELEMENT9 declaration_pntc1[] =
8573 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8574 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
8575 {0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
8576 D3DDECL_END()
8578 const unsigned int VERTS_PER_FACE = 3;
8579 BYTE *vertices = NULL;
8580 INT i;
8581 struct vertex_pn
8583 D3DXVECTOR3 position;
8584 D3DXVECTOR3 normal;
8586 struct vertex_pntc
8588 D3DXVECTOR3 position;
8589 D3DXVECTOR3 normal;
8590 D3DXVECTOR2 texcoords;
8592 struct vertex_ptcn
8594 D3DXVECTOR3 position;
8595 D3DXVECTOR2 texcoords;
8596 D3DXVECTOR3 normal;
8598 struct vertex_ptc
8600 D3DXVECTOR3 position;
8601 D3DXVECTOR2 texcoords;
8603 struct vertex_ptc_float16_2
8605 D3DXVECTOR3 position;
8606 WORD texcoords[2]; /* float16_2 */
8608 struct vertex_ptc_float16_4
8610 D3DXVECTOR3 position;
8611 WORD texcoords[4]; /* float16_4 */
8613 struct vertex_ptc_float1
8615 D3DXVECTOR3 position;
8616 FLOAT texcoords;
8618 struct vertex_ptc_float3
8620 D3DXVECTOR3 position;
8621 FLOAT texcoords[3];
8623 struct vertex_ptc_float4
8625 D3DXVECTOR3 position;
8626 FLOAT texcoords[4];
8628 struct vertex_ptc_d3dcolor
8630 D3DXVECTOR3 position;
8631 BYTE texcoords[4];
8633 struct vertex_ptc_ubyte4
8635 D3DXVECTOR3 position;
8636 BYTE texcoords[4];
8638 struct vertex_ptc_ubyte4n
8640 D3DXVECTOR3 position;
8641 BYTE texcoords[4];
8643 struct vertex_ptc_short2
8645 D3DXVECTOR3 position;
8646 SHORT texcoords[2];
8648 struct vertex_ptc_short4
8650 D3DXVECTOR3 position;
8651 SHORT texcoords[4];
8653 struct vertex_ptc_ushort2n
8655 D3DXVECTOR3 position;
8656 USHORT texcoords[2];
8658 struct vertex_ptc_ushort4n
8660 D3DXVECTOR3 position;
8661 USHORT texcoords[4];
8663 struct vertex_ptc_udec3
8665 D3DXVECTOR3 position;
8666 DWORD texcoords;
8668 struct vertex_ptc_dec3n
8670 D3DXVECTOR3 position;
8671 DWORD texcoords;
8673 D3DXVECTOR3 up = {0.0f, 0.0f, 1.0f};
8674 D3DXVECTOR2 zero_vec2 = {0.0f, 0.0f};
8675 /* Test 0. Check that a mesh can be cloned if the new declaration is the
8676 * same as the one used to create the mesh.
8678 * 0--1 3
8679 * | / /|
8680 * |/ / |
8681 * 2 5--4
8683 const struct vertex_pn vertices0[] =
8685 {{ 0.0f, 3.0f, 0.f}, up},
8686 {{ 2.0f, 3.0f, 0.f}, up},
8687 {{ 0.0f, 0.0f, 0.f}, up},
8689 {{ 3.0f, 3.0f, 0.f}, up},
8690 {{ 3.0f, 0.0f, 0.f}, up},
8691 {{ 1.0f, 0.0f, 0.f}, up},
8693 const UINT num_vertices0 = ARRAY_SIZE(vertices0);
8694 const UINT num_faces0 = ARRAY_SIZE(vertices0) / VERTS_PER_FACE;
8695 const UINT vertex_size0 = sizeof(*vertices0);
8696 /* Test 1. Check that 16-bit indices are handled. */
8697 const DWORD options_16bit = D3DXMESH_SYSTEMMEM;
8698 /* Test 2. Check that the size of each vertex is increased and the data
8699 * moved if the new declaration adds an element after the original elements.
8701 const struct vertex_pntc exp_vertices2[] =
8703 {{ 0.0f, 3.0f, 0.f}, up, zero_vec2},
8704 {{ 2.0f, 3.0f, 0.f}, up, zero_vec2},
8705 {{ 0.0f, 0.0f, 0.f}, up, zero_vec2},
8707 {{ 3.0f, 3.0f, 0.f}, up, zero_vec2},
8708 {{ 3.0f, 0.0f, 0.f}, up, zero_vec2},
8709 {{ 1.0f, 0.0f, 0.f}, up, zero_vec2},
8711 const UINT exp_vertex_size2 = sizeof(*exp_vertices2);
8712 /* Test 3. Check that the size of each vertex is increased and the data
8713 * moved if the new declaration adds an element between the original
8714 * elements.
8716 const struct vertex_ptcn exp_vertices3[] =
8718 {{ 0.0f, 3.0f, 0.f}, zero_vec2, up},
8719 {{ 2.0f, 3.0f, 0.f}, zero_vec2, up},
8720 {{ 0.0f, 0.0f, 0.f}, zero_vec2, up},
8722 {{ 3.0f, 3.0f, 0.f}, zero_vec2, up},
8723 {{ 3.0f, 0.0f, 0.f}, zero_vec2, up},
8724 {{ 1.0f, 0.0f, 0.f}, zero_vec2, up},
8726 const UINT exp_vertex_size3 = sizeof(*exp_vertices3);
8727 /* Test 4. Test that data types can be converted, e.g. FLOAT2 to FLOAT16_2. */
8728 const struct vertex_ptc vertices4[] =
8730 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8731 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8732 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
8734 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8735 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
8736 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
8738 const UINT num_vertices4 = ARRAY_SIZE(vertices4);
8739 const UINT num_faces4 = ARRAY_SIZE(vertices4) / VERTS_PER_FACE;
8740 const UINT vertex_size4 = sizeof(*vertices4);
8741 const struct vertex_ptc_float16_2 exp_vertices4[] =
8743 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
8744 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */
8745 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */
8747 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd}}, /* {0.2f, 0.3f} */
8748 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
8749 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */
8751 const UINT exp_vertex_size4 = sizeof(*exp_vertices4);
8752 /* Test 5. Convert FLOAT2 to FLOAT16_4. */
8753 const struct vertex_ptc vertices5[] =
8755 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8756 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8757 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
8759 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8760 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
8761 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
8763 const UINT num_vertices5 = ARRAY_SIZE(vertices5);
8764 const UINT num_faces5 = ARRAY_SIZE(vertices5) / VERTS_PER_FACE;
8765 const UINT vertex_size5 = sizeof(*vertices5);
8766 const struct vertex_ptc_float16_4 exp_vertices5[] =
8768 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00, 0, 0x3c00}}, /* {1.0f, 1.0f, 0.0f, 1.0f} */
8769 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a, 0, 0x3c00}}, /* {0.5f, 0.7f, 0.0f, 1.0f} */
8770 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd, 0, 0x3c00}}, /* {-0.2f, -0.3f, 0.0f, 1.0f} */
8772 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd, 0, 0x3c00}}, /* {0.2f, 0.3f, 0.0f, 1.0f} */
8773 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00, 0, 0x3c00}}, /* {1.0f, 1.0f, 0.0f, 1.0f} */
8774 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266, 0, 0x3c00}}, /* {0.1f, 0.2f, 0.0f, 1.0f} */
8776 const UINT exp_vertex_size5 = sizeof(*exp_vertices5);
8777 /* Test 6. Convert FLOAT2 to FLOAT1. */
8778 const struct vertex_ptc vertices6[] =
8780 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8781 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8782 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
8784 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8785 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
8786 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
8788 const UINT num_vertices6 = ARRAY_SIZE(vertices6);
8789 const UINT num_faces6 = ARRAY_SIZE(vertices6) / VERTS_PER_FACE;
8790 const UINT vertex_size6 = sizeof(*vertices6);
8791 const struct vertex_ptc_float1 exp_vertices6[] =
8793 {{ 0.0f, 3.0f, 0.f}, 1.0f},
8794 {{ 2.0f, 3.0f, 0.f}, 0.5f},
8795 {{ 0.0f, 0.0f, 0.f}, -0.2f},
8797 {{ 3.0f, 3.0f, 0.f}, 0.2f},
8798 {{ 3.0f, 0.0f, 0.f}, 1.0f},
8799 {{ 1.0f, 0.0f, 0.f}, 0.1f},
8801 const UINT exp_vertex_size6 = sizeof(*exp_vertices6);
8802 /* Test 7. Convert FLOAT2 to FLOAT3. */
8803 const struct vertex_ptc vertices7[] =
8805 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8806 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8807 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
8809 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8810 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
8811 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
8813 const UINT num_vertices7 = ARRAY_SIZE(vertices7);
8814 const UINT num_faces7 = ARRAY_SIZE(vertices7) / VERTS_PER_FACE;
8815 const UINT vertex_size7 = sizeof(*vertices7);
8816 const struct vertex_ptc_float3 exp_vertices7[] =
8818 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f, 0.0f}},
8819 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f, 0.0f}},
8820 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f, 0.0f}},
8822 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f, 0.0f}},
8823 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f, 0.0f}},
8824 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f, 0.0f}},
8826 const UINT exp_vertex_size7 = sizeof(*exp_vertices7);
8827 /* Test 8. Convert FLOAT2 to FLOAT4. */
8828 const struct vertex_ptc vertices8[] =
8830 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8831 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8832 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
8834 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8835 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
8836 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
8838 const UINT num_vertices8 = ARRAY_SIZE(vertices8);
8839 const UINT num_faces8 = ARRAY_SIZE(vertices8) / VERTS_PER_FACE;
8840 const UINT vertex_size8 = sizeof(*vertices8);
8841 const struct vertex_ptc_float4 exp_vertices8[] =
8843 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f, 0.0f, 1.0f}},
8844 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f, 0.0f, 1.0f}},
8845 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f, 0.0f, 1.0f}},
8847 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f, 0.0f, 1.0f}},
8848 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f, 0.0f, 1.0f}},
8849 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f, 0.0f, 1.0f}},
8851 const UINT exp_vertex_size8 = sizeof(*exp_vertices8);
8852 /* Test 9. Convert FLOAT2 to D3DCOLOR. */
8853 const struct vertex_ptc vertices9[] =
8855 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8856 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8857 {{ 0.0f, 0.0f, 0.f}, {-0.4f, -0.6f}},
8859 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8860 {{ 3.0f, 0.0f, 0.f}, { 2.0f, 256.0f}},
8861 {{ 1.0f, 0.0f, 0.f}, { 0.11f, 0.2f}},
8863 const UINT num_vertices9 = ARRAY_SIZE(vertices9);
8864 const UINT num_faces9 = ARRAY_SIZE(vertices9) / VERTS_PER_FACE;
8865 const UINT vertex_size9 = sizeof(*vertices9);
8866 const struct vertex_ptc_d3dcolor exp_vertices9[] =
8868 {{ 0.0f, 3.0f, 0.f}, {0, 255, 255, 255}},
8869 {{ 2.0f, 3.0f, 0.f}, {0, 179, 128, 255}},
8870 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 255}},
8872 {{ 3.0f, 3.0f, 0.f}, {0, 77, 51, 255}},
8873 {{ 3.0f, 0.0f, 0.f}, {0, 255, 255, 255}},
8874 {{ 1.0f, 0.0f, 0.f}, {0, 51, 28, 255}},
8876 const UINT exp_vertex_size9 = sizeof(*exp_vertices9);
8877 /* Test 10. Convert FLOAT2 to UBYTE4. */
8878 const struct vertex_ptc vertices10[] =
8880 {{ 0.0f, 3.0f, 0.f}, { 0.0f, 1.0f}},
8881 {{ 2.0f, 3.0f, 0.f}, { 2.0f, 3.0f}},
8882 {{ 0.0f, 0.0f, 0.f}, { 254.0f, 255.0f}},
8884 {{ 3.0f, 3.0f, 0.f}, { 256.0f, 257.0f}},
8885 {{ 3.0f, 0.0f, 0.f}, { 1.4f, 1.5f}},
8886 {{ 1.0f, 0.0f, 0.f}, {-4.0f, -5.0f}},
8888 const UINT num_vertices10 = ARRAY_SIZE(vertices10);
8889 const UINT num_faces10 = ARRAY_SIZE(vertices10) / VERTS_PER_FACE;
8890 const UINT vertex_size10 = sizeof(*vertices10);
8891 const struct vertex_ptc_ubyte4 exp_vertices10[] =
8893 {{ 0.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
8894 {{ 2.0f, 3.0f, 0.f}, {2, 3, 0, 1}},
8895 {{ 0.0f, 0.0f, 0.f}, {254, 255, 0, 1}},
8897 {{ 3.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
8898 {{ 3.0f, 0.0f, 0.f}, {1, 2, 0, 1}},
8899 {{ 1.0f, 0.0f, 0.f}, {0, 0, 0, 1}},
8901 const UINT exp_vertex_size10 = sizeof(*exp_vertices10);
8902 /* Test 11. Convert FLOAT2 to SHORT2. */
8903 const struct vertex_ptc vertices11[] =
8905 {{ 0.0f, 3.0f, 0.f}, { 1.0f, -1.0f}},
8906 {{ 2.0f, 3.0f, 0.f}, { 0.4f, 0.5f}},
8907 {{ 0.0f, 0.0f, 0.f}, {-0.5f, -5.0f}},
8909 {{ 3.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MIN}},
8910 {{ 3.0f, 0.0f, 0.f}, {SHRT_MAX + 1.0f, SHRT_MIN - 1.0f}},
8911 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX + 2.0f, SHRT_MIN - 2.0f}},
8913 {{ 4.0f, 3.0f, 0.f}, {2 * SHRT_MAX, 2 * SHRT_MIN}},
8914 {{ 6.0f, 0.0f, 0.f}, {3 * SHRT_MAX, 3 * SHRT_MIN}},
8915 {{ 4.0f, 0.0f, 0.f}, {4 * SHRT_MAX, 4 * SHRT_MIN}},
8917 const UINT num_vertices11 = ARRAY_SIZE(vertices11);
8918 const UINT num_faces11 = ARRAY_SIZE(vertices11) / VERTS_PER_FACE;
8919 const UINT vertex_size11 = sizeof(*vertices11);
8920 const struct vertex_ptc_short2 exp_vertices11[] =
8922 {{ 0.0f, 3.0f, 0.f}, {1, 0}},
8923 {{ 2.0f, 3.0f, 0.f}, {0, 1}},
8924 {{ 0.0f, 0.0f, 0.f}, {0, -4}},
8926 {{ 3.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MIN + 1}},
8927 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MIN}},
8928 {{ 1.0f, 0.0f, 0.f}, {SHRT_MIN + 1, SHRT_MAX}},
8930 {{ 4.0f, 3.0f, 0.f}, {-2, 1}},
8931 {{ 6.0f, 0.0f, 0.f}, {32765, -32767}},
8932 {{ 4.0f, 0.0f, 0.f}, {-4, 1}},
8934 const UINT exp_vertex_size11 = sizeof(*exp_vertices11);
8935 /* Test 12. Convert FLOAT2 to SHORT4. */
8936 const struct vertex_ptc vertices12[] =
8938 {{ 0.0f, 3.0f, 0.f}, { 1.0f, -1.0f}},
8939 {{ 2.0f, 3.0f, 0.f}, { 0.4f, 0.5f}},
8940 {{ 0.0f, 0.0f, 0.f}, {-0.5f, -5.0f}},
8942 {{ 3.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MIN}},
8943 {{ 3.0f, 0.0f, 0.f}, {SHRT_MAX + 1.0f, SHRT_MIN - 1.0f}},
8944 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX + 2.0f, SHRT_MIN - 2.0f}},
8946 {{ 4.0f, 3.0f, 0.f}, {2 * SHRT_MAX, 2 * SHRT_MIN}},
8947 {{ 6.0f, 0.0f, 0.f}, {3 * SHRT_MAX, 3 * SHRT_MIN}},
8948 {{ 4.0f, 0.0f, 0.f}, {4 * SHRT_MAX, 4 * SHRT_MIN}},
8950 const UINT num_vertices12 = ARRAY_SIZE(vertices12);
8951 const UINT num_faces12 = ARRAY_SIZE(vertices12) / VERTS_PER_FACE;
8952 const UINT vertex_size12 = sizeof(*vertices12);
8953 const struct vertex_ptc_short4 exp_vertices12[] =
8955 {{ 0.0f, 3.0f, 0.f}, {1, 0, 0, 1}},
8956 {{ 2.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
8957 {{ 0.0f, 0.0f, 0.f}, {0, -4, 0, 1}},
8959 {{ 3.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MIN + 1, 0, 1}},
8960 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MIN, 0, 1}},
8961 {{ 1.0f, 0.0f, 0.f}, {SHRT_MIN + 1, SHRT_MAX, 0, 1}},
8963 {{ 4.0f, 3.0f, 0.f}, {-2, 1, 0, 1}},
8964 {{ 6.0f, 0.0f, 0.f}, {32765, -32767, 0, 1}},
8965 {{ 4.0f, 0.0f, 0.f}, {-4, 1, 0, 1}},
8967 const UINT exp_vertex_size12 = sizeof(*exp_vertices12);
8968 /* Test 13. Convert FLOAT2 to UBYTE4N. */
8969 const struct vertex_ptc vertices13[] =
8971 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 2.0f}},
8972 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8973 {{ 0.0f, 0.0f, 0.f}, {-0.4f, -0.5f}},
8975 {{ 3.0f, 3.0f, 0.f}, {-0.6f, -1.0f}},
8976 {{ 3.0f, 0.0f, 0.f}, {UCHAR_MAX, UCHAR_MAX + 1}},
8977 {{ 1.0f, 0.0f, 0.f}, {2 * UCHAR_MAX, -UCHAR_MAX}},
8979 const UINT num_vertices13 = ARRAY_SIZE(vertices13);
8980 const UINT num_faces13 = ARRAY_SIZE(vertices13) / VERTS_PER_FACE;
8981 const UINT vertex_size13 = sizeof(*vertices13);
8982 const struct vertex_ptc_ubyte4n exp_vertices13[] =
8984 {{ 0.0f, 3.0f, 0.f}, {255, 255, 0, 255}},
8985 {{ 2.0f, 3.0f, 0.f}, {128, 179, 0, 255}},
8986 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 255}},
8988 {{ 3.0f, 3.0f, 0.f}, {0, 0, 0, 255}},
8989 {{ 3.0f, 0.0f, 0.f}, {255, 255, 0, 255}},
8990 {{ 1.0f, 0.0f, 0.f}, {255, 0, 0, 255}},
8992 const UINT exp_vertex_size13 = sizeof(*exp_vertices13);
8993 /* Test 14. Convert FLOAT2 to SHORT2N. */
8994 const struct vertex_ptc vertices14[] =
8996 {{ 0.0f, 3.0f, 0.f}, {1.0f, 2.0f}},
8997 {{ 2.0f, 3.0f, 0.f}, {0.4f, 0.5f}},
8998 {{ 0.0f, 0.0f, 0.f}, {0.6f, -1.0f}},
9000 {{ 3.0f, 3.0f, 0.f}, {-0.4f, -0.5f}},
9001 {{ 3.0f, 0.0f, 0.f}, {-0.9f, -0.99997}},
9002 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX, SHRT_MIN}},
9004 const UINT num_vertices14 = ARRAY_SIZE(vertices14);
9005 const UINT num_faces14 = ARRAY_SIZE(vertices14) / VERTS_PER_FACE;
9006 const UINT vertex_size14 = sizeof(*vertices14);
9007 const struct vertex_ptc_short2 exp_vertices14[] =
9009 {{ 0.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MAX}},
9010 {{ 2.0f, 3.0f, 0.f}, {13107, 16384}},
9011 {{ 0.0f, 0.0f, 0.f}, {19660, SHRT_MIN + 2}},
9013 {{ 3.0f, 3.0f, 0.f}, {-13106, -16383}},
9014 {{ 3.0f, 0.0f, 0.f}, {-29489, SHRT_MIN + 3}},
9015 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX, SHRT_MIN + 2}},
9017 const UINT exp_vertex_size14 = sizeof(*exp_vertices14);
9018 /* Test 15. Convert FLOAT2 to SHORT4N. */
9019 const struct vertex_ptc vertices15[] =
9021 {{ 0.0f, 3.0f, 0.f}, {1.0f, 2.0f}},
9022 {{ 2.0f, 3.0f, 0.f}, {0.4f, 0.5f}},
9023 {{ 0.0f, 0.0f, 0.f}, {0.6f, -1.0f}},
9025 {{ 3.0f, 3.0f, 0.f}, {-0.4f, -0.5f}},
9026 {{ 3.0f, 0.0f, 0.f}, {-0.9f, -0.99997}},
9027 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX, SHRT_MIN}},
9029 const UINT num_vertices15 = ARRAY_SIZE(vertices15);
9030 const UINT num_faces15 = ARRAY_SIZE(vertices15) / VERTS_PER_FACE;
9031 const UINT vertex_size15 = sizeof(*vertices15);
9032 const struct vertex_ptc_short4 exp_vertices15[] =
9034 {{ 0.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MAX, 0, SHRT_MAX}},
9035 {{ 2.0f, 3.0f, 0.f}, {13107, 16384, 0, SHRT_MAX}},
9036 {{ 0.0f, 0.0f, 0.f}, {19660, SHRT_MIN + 2, 0, SHRT_MAX}},
9038 {{ 3.0f, 3.0f, 0.f}, {-13106, -16383, 0, SHRT_MAX}},
9039 {{ 3.0f, 0.0f, 0.f}, {-29489, SHRT_MIN + 3, 0, SHRT_MAX}},
9040 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX, SHRT_MIN + 2, 0, SHRT_MAX}},
9042 const UINT exp_vertex_size15 = sizeof(*exp_vertices15);
9043 /* Test 16. Convert FLOAT2 to USHORT2N. */
9044 const struct vertex_ptc vertices16[] =
9046 {{ 0.0f, 3.0f, 0.f}, {1.0f, 2.0f}},
9047 {{ 2.0f, 3.0f, 0.f}, {0.4f, 0.5f}},
9048 {{ 0.0f, 0.0f, 0.f}, {0.6f, -1.0f}},
9050 {{ 3.0f, 3.0f, 0.f}, {-0.4f, -0.5f}},
9051 {{ 3.0f, 0.0f, 0.f}, {-0.9f, 0.99998f}},
9052 {{ 1.0f, 0.0f, 0.f}, {USHRT_MAX, 0.0f}},
9054 const UINT num_vertices16 = ARRAY_SIZE(vertices16);
9055 const UINT num_faces16 = ARRAY_SIZE(vertices16) / VERTS_PER_FACE;
9056 const UINT vertex_size16 = sizeof(*vertices16);
9057 const struct vertex_ptc_ushort2n exp_vertices16[] =
9059 {{ 0.0f, 3.0f, 0.f}, {USHRT_MAX, USHRT_MAX}},
9060 {{ 2.0f, 3.0f, 0.f}, {26214, 32768}},
9061 {{ 0.0f, 0.0f, 0.f}, {39321, 0}},
9063 {{ 3.0f, 3.0f, 0.f}, {0, 0}},
9064 {{ 3.0f, 0.0f, 0.f}, {0, USHRT_MAX - 1}},
9065 {{ 1.0f, 0.0f, 0.f}, {USHRT_MAX, 0}},
9067 const UINT exp_vertex_size16 = sizeof(*exp_vertices16);
9068 /* Test 17. Convert FLOAT2 to USHORT4N. */
9069 const struct vertex_ptc vertices17[] =
9071 {{ 0.0f, 3.0f, 0.f}, {1.0f, 2.0f}},
9072 {{ 2.0f, 3.0f, 0.f}, {0.4f, 0.5f}},
9073 {{ 0.0f, 0.0f, 0.f}, {0.6f, -1.0f}},
9075 {{ 3.0f, 3.0f, 0.f}, {-0.4f, -0.5f}},
9076 {{ 3.0f, 0.0f, 0.f}, {-0.9f, 0.99998f}},
9077 {{ 1.0f, 0.0f, 0.f}, {USHRT_MAX, 0.0f}},
9079 const UINT num_vertices17 = ARRAY_SIZE(vertices17);
9080 const UINT num_faces17 = ARRAY_SIZE(vertices17) / VERTS_PER_FACE;
9081 const UINT vertex_size17 = sizeof(*vertices17);
9082 const struct vertex_ptc_ushort4n exp_vertices17[] =
9084 {{ 0.0f, 3.0f, 0.f}, {USHRT_MAX, USHRT_MAX, 0, USHRT_MAX}},
9085 {{ 2.0f, 3.0f, 0.f}, {26214, 32768, 0, USHRT_MAX}},
9086 {{ 0.0f, 0.0f, 0.f}, {39321, 0, 0, USHRT_MAX}},
9088 {{ 3.0f, 3.0f, 0.f}, {0, 0, 0, USHRT_MAX}},
9089 {{ 3.0f, 0.0f, 0.f}, {0, USHRT_MAX - 1, 0, USHRT_MAX}},
9090 {{ 1.0f, 0.0f, 0.f}, {USHRT_MAX, 0, 0, USHRT_MAX}},
9092 const UINT exp_vertex_size17 = sizeof(*exp_vertices17);
9093 /* Test 18. Test that the method field is compared by converting a FLOAT2 to
9094 * FLOAT16_2. where the method field has been change from
9095 * D3DDECLMETHOD_DEFAULT to D3DDECLMETHOD_PARTIALU. */
9096 const struct vertex_ptc vertices18[] =
9098 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
9099 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
9100 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
9102 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
9103 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
9104 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
9106 const UINT num_vertices18 = ARRAY_SIZE(vertices18);
9107 const UINT num_faces18 = ARRAY_SIZE(vertices18) / VERTS_PER_FACE;
9108 const UINT vertex_size18 = sizeof(*vertices18);
9109 const struct vertex_ptc_float16_2 exp_vertices18[] =
9111 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
9112 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */
9113 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */
9115 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd}}, /* {0.2f, 0.3f} */
9116 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
9117 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */
9119 const UINT exp_vertex_size18 = sizeof(*exp_vertices18);
9120 /* Test 19. Test that data is lost if usage index changes, e.g. TEXCOORD0
9121 * TEXCOORD1. */
9122 const struct vertex_pntc vertices19[] =
9124 {{ 0.0f, 3.0f, 0.f}, up, { 1.0f, 1.0f}},
9125 {{ 2.0f, 3.0f, 0.f}, up, { 0.5f, 0.7f}},
9126 {{ 0.0f, 0.0f, 0.f}, up, {-0.2f, -0.3f}},
9128 {{ 3.0f, 3.0f, 0.f}, up, { 0.2f, 0.3f}},
9129 {{ 3.0f, 0.0f, 0.f}, up, { 1.0f, 1.0f}},
9130 {{ 1.0f, 0.0f, 0.f}, up, { 0.1f, 0.2f}},
9132 const UINT num_vertices19 = ARRAY_SIZE(vertices19);
9133 const UINT num_faces19 = ARRAY_SIZE(vertices19) / VERTS_PER_FACE;
9134 const UINT vertex_size19 = sizeof(*vertices19);
9135 const struct vertex_pntc exp_vertices19[] =
9137 {{ 0.0f, 3.0f, 0.f}, up, zero_vec2},
9138 {{ 2.0f, 3.0f, 0.f}, up, zero_vec2},
9139 {{ 0.0f, 0.0f, 0.f}, up, zero_vec2},
9141 {{ 3.0f, 3.0f, 0.f}, up, zero_vec2},
9142 {{ 3.0f, 0.0f, 0.f}, up, zero_vec2},
9143 {{ 1.0f, 0.0f, 0.f}, up, zero_vec2},
9145 const UINT exp_vertex_size19 = sizeof(*exp_vertices19);
9146 /* Test 20. Another test that data is lost if usage index changes, e.g.
9147 * TEXCOORD1 to TEXCOORD0. */
9148 const struct vertex_pntc vertices20[] =
9150 {{ 0.0f, 3.0f, 0.f}, up, { 1.0f, 1.0f}},
9151 {{ 2.0f, 3.0f, 0.f}, up, { 0.5f, 0.7f}},
9152 {{ 0.0f, 0.0f, 0.f}, up, {-0.2f, -0.3f}},
9154 {{ 3.0f, 3.0f, 0.f}, up, { 0.2f, 0.3f}},
9155 {{ 3.0f, 0.0f, 0.f}, up, { 1.0f, 1.0f}},
9156 {{ 1.0f, 0.0f, 0.f}, up, { 0.1f, 0.2f}},
9158 const UINT num_vertices20 = ARRAY_SIZE(vertices20);
9159 const UINT num_faces20 = ARRAY_SIZE(vertices20) / VERTS_PER_FACE;
9160 const UINT vertex_size20 = sizeof(*vertices20);
9161 const struct vertex_pntc exp_vertices20[] =
9163 {{ 0.0f, 3.0f, 0.f}, up, zero_vec2},
9164 {{ 2.0f, 3.0f, 0.f}, up, zero_vec2},
9165 {{ 0.0f, 0.0f, 0.f}, up, zero_vec2},
9167 {{ 3.0f, 3.0f, 0.f}, up, zero_vec2},
9168 {{ 3.0f, 0.0f, 0.f}, up, zero_vec2},
9169 {{ 1.0f, 0.0f, 0.f}, up, zero_vec2},
9171 const UINT exp_vertex_size20 = sizeof(*exp_vertices20);
9172 /* Test 21. Convert FLOAT1 to FLOAT2. */
9173 const struct vertex_ptc_float1 vertices21[] =
9175 {{ 0.0f, 3.0f, 0.f}, 1.0f},
9176 {{ 2.0f, 3.0f, 0.f}, 0.5f},
9177 {{ 0.0f, 0.0f, 0.f}, -0.2f},
9179 {{ 3.0f, 3.0f, 0.f}, 0.2f},
9180 {{ 3.0f, 0.0f, 0.f}, 1.0f},
9181 {{ 1.0f, 0.0f, 0.f}, 0.1f},
9183 const UINT num_vertices21 = ARRAY_SIZE(vertices21);
9184 const UINT num_faces21 = ARRAY_SIZE(vertices21) / VERTS_PER_FACE;
9185 const UINT vertex_size21 = sizeof(*vertices21);
9186 const struct vertex_ptc exp_vertices21[] =
9188 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 0.0f}},
9189 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.0f}},
9190 {{ 0.0f, 0.0f, 0.f}, {-0.2f, 0.0f}},
9192 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.0f}},
9193 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 0.0f}},
9194 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.0f}},
9196 const UINT exp_vertex_size21 = sizeof(*exp_vertices21);
9197 /* Test 22. Convert FLOAT1 to FLOAT3. */
9198 const struct vertex_ptc_float1 vertices22[] =
9200 {{ 0.0f, 3.0f, 0.f}, 1.0f},
9201 {{ 2.0f, 3.0f, 0.f}, 0.5f},
9202 {{ 0.0f, 0.0f, 0.f}, -0.2f},
9204 {{ 3.0f, 3.0f, 0.f}, 0.2f},
9205 {{ 3.0f, 0.0f, 0.f}, 1.0f},
9206 {{ 1.0f, 0.0f, 0.f}, 0.1f},
9208 const UINT num_vertices22 = ARRAY_SIZE(vertices22);
9209 const UINT num_faces22 = ARRAY_SIZE(vertices22) / VERTS_PER_FACE;
9210 const UINT vertex_size22 = sizeof(*vertices22);
9211 const struct vertex_ptc_float3 exp_vertices22[] =
9213 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 0.0f, 0.0f}},
9214 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.0f, 0.0f}},
9215 {{ 0.0f, 0.0f, 0.f}, {-0.2f, 0.0f, 0.0f}},
9217 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.0f, 0.0f}},
9218 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 0.0f, 0.0f}},
9219 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.0f, 0.0f}},
9221 const UINT exp_vertex_size22 = sizeof(*exp_vertices22);
9222 /* Test 23. Convert FLOAT1 to FLOAT4. */
9223 const struct vertex_ptc_float1 vertices23[] =
9225 {{ 0.0f, 3.0f, 0.f}, 1.0f},
9226 {{ 2.0f, 3.0f, 0.f}, 0.5f},
9227 {{ 0.0f, 0.0f, 0.f}, -0.2f},
9229 {{ 3.0f, 3.0f, 0.f}, 0.2f},
9230 {{ 3.0f, 0.0f, 0.f}, 1.0f},
9231 {{ 1.0f, 0.0f, 0.f}, 0.1f},
9233 const UINT num_vertices23 = ARRAY_SIZE(vertices23);
9234 const UINT num_faces23 = ARRAY_SIZE(vertices23) / VERTS_PER_FACE;
9235 const UINT vertex_size23 = sizeof(*vertices23);
9236 const struct vertex_ptc_float4 exp_vertices23[] =
9238 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 0.0f, 0.0f, 1.0f}},
9239 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.0f, 0.0f, 1.0f}},
9240 {{ 0.0f, 0.0f, 0.f}, {-0.2f, 0.0f, 0.0f, 1.0f}},
9242 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.0f, 0.0f, 1.0f}},
9243 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 0.0f, 0.0f, 1.0f}},
9244 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.0f, 0.0f, 1.0f}},
9246 const UINT exp_vertex_size23 = sizeof(*exp_vertices23);
9247 /* Test 24. Convert FLOAT1 to D3DCOLOR. */
9248 const struct vertex_ptc_float1 vertices24[] =
9250 {{ 0.0f, 3.0f, 0.f}, 1.0f},
9251 {{ 2.0f, 3.0f, 0.f}, 0.5f},
9252 {{ 0.0f, 0.0f, 0.f}, -0.2f},
9254 {{ 3.0f, 3.0f, 0.f}, 0.2f},
9255 {{ 3.0f, 0.0f, 0.f}, 1.0f},
9256 {{ 1.0f, 0.0f, 0.f}, 0.11f},
9258 const UINT num_vertices24 = ARRAY_SIZE(vertices24);
9259 const UINT num_faces24 = ARRAY_SIZE(vertices24) / VERTS_PER_FACE;
9260 const UINT vertex_size24 = sizeof(*vertices24);
9261 const struct vertex_ptc_d3dcolor exp_vertices24[] =
9263 {{ 0.0f, 3.0f, 0.f}, {0, 0, 255, 255}},
9264 {{ 2.0f, 3.0f, 0.f}, {0, 0, 128, 255}},
9265 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 255}},
9267 {{ 3.0f, 3.0f, 0.f}, {0, 0, 51, 255}},
9268 {{ 3.0f, 0.0f, 0.f}, {0, 0, 255, 255}},
9269 {{ 1.0f, 0.0f, 0.f}, {0, 0, 28, 255}},
9271 const UINT exp_vertex_size24 = sizeof(*exp_vertices24);
9272 /* Test 25. Convert FLOAT1 to ubyte4. */
9273 const struct vertex_ptc_float1 vertices25[] =
9275 {{ 0.0f, 3.0f, 0.f}, 0.0f},
9276 {{ 2.0f, 3.0f, 0.f}, 1.4f},
9277 {{ 0.0f, 0.0f, 0.f}, 1.5f},
9279 {{ 3.0f, 3.0f, 0.f}, 255.0f},
9280 {{ 3.0f, 0.0f, 0.f}, 256.0f},
9281 {{ 1.0f, 0.0f, 0.f}, -1.0f},
9283 const UINT num_vertices25 = ARRAY_SIZE(vertices25);
9284 const UINT num_faces25 = ARRAY_SIZE(vertices25) / VERTS_PER_FACE;
9285 const UINT vertex_size25 = sizeof(*vertices25);
9286 const struct vertex_ptc_ubyte4 exp_vertices25[] =
9288 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 1}},
9289 {{ 2.0f, 3.0f, 0.f}, {1, 0, 0, 1}},
9290 {{ 0.0f, 0.0f, 0.f}, {2, 0, 0, 1}},
9292 {{ 3.0f, 3.0f, 0.f}, {255, 0, 0, 1}},
9293 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 1}},
9294 {{ 1.0f, 0.0f, 0.f}, {0, 0, 0, 1}},
9296 const UINT exp_vertex_size25 = sizeof(*exp_vertices25);
9297 /* Test 26. Convert FLOAT4 to D3DCOLOR. */
9298 const struct vertex_ptc_float4 vertices26[] =
9300 {{ 0.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.4f, 0.5f}},
9301 {{ 2.0f, 3.0f, 0.f}, {-0.4f, -0.5f, -1.0f, -2.0f}},
9302 {{ 0.0f, 0.0f, 0.f}, {254.0f, 255.0f, 256.0f, 257.0f}},
9304 {{ 3.0f, 3.0f, 0.f}, {0.1f, 0.2f, 0.3f, 0.4f}},
9305 {{ 3.0f, 0.0f, 0.f}, {0.5f, 0.6f, 0.7f, 0.8f}},
9306 {{ 1.0f, 0.0f, 0.f}, {0.9f, 0.99f, 0.995f, 0.999f}},
9308 const UINT num_vertices26 = ARRAY_SIZE(vertices26);
9309 const UINT num_faces26 = ARRAY_SIZE(vertices26) / VERTS_PER_FACE;
9310 const UINT vertex_size26 = sizeof(*vertices26);
9311 const struct vertex_ptc_d3dcolor exp_vertices26[] =
9313 {{ 0.0f, 3.0f, 0.f}, {102, 255, 0, 128}},
9314 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9315 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
9317 {{ 3.0f, 3.0f, 0.f}, {77, 51, 26, 102}},
9318 {{ 3.0f, 0.0f, 0.f}, {179, 153, 128, 204}},
9319 {{ 1.0f, 0.0f, 0.f}, {254, 252, 230, 255}},
9321 const UINT exp_vertex_size26 = sizeof(*exp_vertices26);
9322 /* Test 27. Convert D3DCOLOR to FLOAT4. */
9323 const struct vertex_ptc_d3dcolor vertices27[] =
9325 {{ 0.0f, 3.0f, 0.f}, {102, 255, 0, 128}},
9326 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9327 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
9329 {{ 3.0f, 3.0f, 0.f}, {77, 51, 26, 102}},
9330 {{ 3.0f, 0.0f, 0.f}, {179, 153, 128, 204}},
9331 {{ 1.0f, 0.0f, 0.f}, {254, 252, 230, 255}},
9333 const UINT num_vertices27 = ARRAY_SIZE(vertices27);
9334 const UINT num_faces27 = ARRAY_SIZE(vertices27) / VERTS_PER_FACE;
9335 const UINT vertex_size27 = sizeof(*vertices27);
9336 const struct vertex_ptc_float4 exp_vertices27[] =
9338 {{ 0.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.4f, 0.501961f}},
9339 {{ 2.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9340 {{ 0.0f, 0.0f, 0.f}, {1.0f, 1.0f, 1.0f, 1.0f}},
9342 {{ 3.0f, 3.0f, 0.f}, {0.101961f, 0.2f, 0.301961f, 0.4f}},
9343 {{ 3.0f, 0.0f, 0.f}, {0.501961f, 0.6f, 0.701961f, 0.8f}},
9344 {{ 1.0f, 0.0f, 0.f}, {0.901961f, 0.988235f, 0.996078f, 1.0f}},
9346 const UINT exp_vertex_size27 = sizeof(*exp_vertices27);
9347 /* Test 28. Convert UBYTE4 to FLOAT4. */
9348 const struct vertex_ptc_ubyte4 vertices28[] =
9350 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9351 {{ 2.0f, 3.0f, 0.f}, {1, 1, 1, 1}},
9352 {{ 0.0f, 0.0f, 0.f}, {1, 0, 1, 0}},
9354 {{ 3.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
9355 {{ 3.0f, 0.0f, 0.f}, {10, 20, 30, 40}},
9356 {{ 1.0f, 0.0f, 0.f}, {50, 60, 127, 255}},
9358 const UINT num_vertices28 = ARRAY_SIZE(vertices28);
9359 const UINT num_faces28 = ARRAY_SIZE(vertices28) / VERTS_PER_FACE;
9360 const UINT vertex_size28 = sizeof(*vertices28);
9361 const struct vertex_ptc_float4 exp_vertices28[] =
9363 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9364 {{ 2.0f, 3.0f, 0.f}, {1.0f, 1.0f, 1.0f, 1.0f}},
9365 {{ 0.0f, 0.0f, 0.f}, {1.0f, 0.0f, 1.0f, 0.0f}},
9367 {{ 3.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.0f, 1.0f}},
9368 {{ 3.0f, 0.0f, 0.f}, {10.0f, 20.0f, 30.0f, 40.0f}},
9369 {{ 1.0f, 0.0f, 0.f}, {50.0f, 60.0f, 127.0f, 255.0f}},
9371 const UINT exp_vertex_size28 = sizeof(*exp_vertices28);
9372 /* Test 29. Convert SHORT2 to FLOAT4. */
9373 const struct vertex_ptc_short2 vertices29[] =
9375 {{ 0.0f, 3.0f, 0.f}, {0, 0}},
9376 {{ 2.0f, 3.0f, 0.f}, {0, 1}},
9377 {{ 0.0f, 0.0f, 0.f}, {1, 0}},
9379 {{ 3.0f, 3.0f, 0.f}, {1, 1}},
9380 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MAX}},
9381 {{ 1.0f, 0.0f, 0.f}, {-42, 42}},
9383 const UINT num_vertices29 = ARRAY_SIZE(vertices29);
9384 const UINT num_faces29 = ARRAY_SIZE(vertices29) / VERTS_PER_FACE;
9385 const UINT vertex_size29 = sizeof(*vertices29);
9386 const struct vertex_ptc_float4 exp_vertices29[] =
9388 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 1.0f}},
9389 {{ 2.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.0f, 1.0f }},
9390 {{ 0.0f, 0.0f, 0.f}, {1.0f, 0.0f, 0.0f, 1.0f}},
9392 {{ 3.0f, 3.0f, 0.f}, {1.0f, 1.0f, 0.0f, 1.0f}},
9393 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MAX, 0.0f, 1.0f}},
9394 {{ 1.0f, 0.0f, 0.f}, {-42.0f, 42.0f, 0.0f, 1.0f}},
9396 const UINT exp_vertex_size29 = sizeof(*exp_vertices29);
9397 /* Test 29. Convert SHORT4 to FLOAT4. */
9398 const struct vertex_ptc_short4 vertices30[] =
9400 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9401 {{ 2.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
9402 {{ 0.0f, 0.0f, 0.f}, {1, 0, 1, 0}},
9404 {{ 3.0f, 3.0f, 0.f}, {1, 1, 1, 1}},
9405 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MAX, 1, 0}},
9406 {{ 1.0f, 0.0f, 0.f}, {-42, 42, SHRT_MAX, SHRT_MIN}},
9408 const UINT num_vertices30 = ARRAY_SIZE(vertices30);
9409 const UINT num_faces30 = ARRAY_SIZE(vertices30) / VERTS_PER_FACE;
9410 const UINT vertex_size30 = sizeof(*vertices30);
9411 const struct vertex_ptc_float4 exp_vertices30[] =
9413 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9414 {{ 2.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.0f, 1.0f }},
9415 {{ 0.0f, 0.0f, 0.f}, {1.0f, 0.0f, 1.0f, 0.0f}},
9417 {{ 3.0f, 3.0f, 0.f}, {1.0f, 1.0f, 1.0f, 1.0f}},
9418 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MAX, 1.0f, 0.0f}},
9419 {{ 1.0f, 0.0f, 0.f}, {-42.0f, 42.0f, SHRT_MAX, SHRT_MIN}},
9421 const UINT exp_vertex_size30 = sizeof(*exp_vertices30);
9422 /* Test 31. Convert UBYTE4N to FLOAT4. */
9423 const struct vertex_ptc_ubyte4n vertices31[] =
9425 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9426 {{ 2.0f, 3.0f, 0.f}, {1, 1, 1, 1}},
9427 {{ 0.0f, 0.0f, 0.f}, {1, 0, 1, 0}},
9429 {{ 3.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
9430 {{ 3.0f, 0.0f, 0.f}, {10, 20, 30, 40}},
9431 {{ 1.0f, 0.0f, 0.f}, {50, 60, 70, UCHAR_MAX}},
9433 const UINT num_vertices31 = ARRAY_SIZE(vertices31);
9434 const UINT num_faces31 = ARRAY_SIZE(vertices31) / VERTS_PER_FACE;
9435 const UINT vertex_size31 = sizeof(*vertices31);
9436 const struct vertex_ptc_float4 exp_vertices31[] =
9438 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9439 {{ 2.0f, 3.0f, 0.f}, {(FLOAT)1/UCHAR_MAX, (FLOAT)1/UCHAR_MAX, (FLOAT)1/UCHAR_MAX, (FLOAT)1/UCHAR_MAX}},
9440 {{ 0.0f, 0.0f, 0.f}, {(FLOAT)1/UCHAR_MAX, 0.0f, (FLOAT)1/UCHAR_MAX, 0.0f}},
9442 {{ 3.0f, 3.0f, 0.f}, {0.0f, (FLOAT)1/UCHAR_MAX, 0.0f, (FLOAT)1/UCHAR_MAX}},
9443 {{ 3.0f, 0.0f, 0.f}, {(FLOAT)10/UCHAR_MAX, (FLOAT)20/UCHAR_MAX, (FLOAT)30/UCHAR_MAX, (FLOAT)40/UCHAR_MAX}},
9444 {{ 1.0f, 0.0f, 0.f}, {(FLOAT)50/UCHAR_MAX, (FLOAT)60/UCHAR_MAX, (FLOAT)70/UCHAR_MAX, 1.0f}},
9446 const UINT exp_vertex_size31 = sizeof(*exp_vertices31);
9447 /* Test 32. Convert SHORT2N to FLOAT4. */
9448 const struct vertex_ptc_short2 vertices32[] =
9450 {{ 0.0f, 3.0f, 0.f}, {0, 0}},
9451 {{ 2.0f, 3.0f, 0.f}, {0, 1}},
9452 {{ 0.0f, 0.0f, 0.f}, {1, 0}},
9454 {{ 3.0f, 3.0f, 0.f}, {1, 1}},
9455 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN + 1, SHRT_MAX}},
9456 {{ 1.0f, 0.0f, 0.f}, {-42, 42}},
9458 const UINT num_vertices32 = ARRAY_SIZE(vertices32);
9459 const UINT num_faces32 = ARRAY_SIZE(vertices32) / VERTS_PER_FACE;
9460 const UINT vertex_size32 = sizeof(*vertices32);
9461 const struct vertex_ptc_float4 exp_vertices32[] =
9463 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 1.0f}},
9464 {{ 2.0f, 3.0f, 0.f}, {0.0f, 1.0f/SHRT_MAX, 0.0f, 1.0f}},
9465 {{ 0.0f, 0.0f, 0.f}, {1.0f/SHRT_MAX, 0.0f, 0.0f, 1.0f}},
9467 {{ 3.0f, 3.0f, 0.f}, {1.0f/SHRT_MAX, 1.0f/SHRT_MAX, 0.0f, 1.0f}},
9468 {{ 3.0f, 0.0f, 0.f}, {-1.0f, 1.0f, 0.0f, 1.0f}},
9469 {{ 1.0f, 0.0f, 0.f}, {-42.0f/SHRT_MAX, 42.0f/SHRT_MAX, 0.0f, 1.0f}},
9471 const UINT exp_vertex_size32 = sizeof(*exp_vertices32);
9472 /* Test 33. Convert SHORT4N to FLOAT4. */
9473 const struct vertex_ptc_short4 vertices33[] =
9475 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9476 {{ 2.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
9477 {{ 0.0f, 0.0f, 0.f}, {1, 0, 1, 0}},
9479 {{ 3.0f, 3.0f, 0.f}, {1, 1, 1, 1}},
9480 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN + 1, SHRT_MAX, SHRT_MIN + 1, SHRT_MAX}},
9481 {{ 1.0f, 0.0f, 0.f}, {-42, 42, 1, 1}},
9483 const UINT num_vertices33 = ARRAY_SIZE(vertices33);
9484 const UINT num_faces33 = ARRAY_SIZE(vertices33) / VERTS_PER_FACE;
9485 const UINT vertex_size33 = sizeof(*vertices33);
9486 const struct vertex_ptc_float4 exp_vertices33[] =
9488 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9489 {{ 2.0f, 3.0f, 0.f}, {0.0f, 1.0f/SHRT_MAX, 0.0f, 1.0f/SHRT_MAX}},
9490 {{ 0.0f, 0.0f, 0.f}, {1.0f/SHRT_MAX, 0.0f, 1.0f/SHRT_MAX, 0.0f}},
9492 {{ 3.0f, 3.0f, 0.f}, {1.0f/SHRT_MAX, 1.0f/SHRT_MAX, 1.0f/SHRT_MAX, 1.0f/SHRT_MAX}},
9493 {{ 3.0f, 0.0f, 0.f}, {-1.0f, 1.0f, -1.0f, 1.0f}},
9494 {{ 1.0f, 0.0f, 0.f}, {-42.0f/SHRT_MAX, 42.0f/SHRT_MAX, 1.0f/SHRT_MAX, 1.0f/SHRT_MAX}},
9496 const UINT exp_vertex_size33 = sizeof(*exp_vertices33);
9497 /* Test 34. Convert FLOAT16_2 to FLOAT4. */
9498 const struct vertex_ptc_float16_2 vertices34[] =
9500 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
9501 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */
9502 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */
9504 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd}}, /* {0.2f, 0.3f} */
9505 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
9506 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */
9508 const UINT num_vertices34 = ARRAY_SIZE(vertices34);
9509 const UINT num_faces34 = ARRAY_SIZE(vertices34) / VERTS_PER_FACE;
9510 const UINT vertex_size34 = sizeof(*vertices34);
9511 const struct vertex_ptc_float4 exp_vertices34[] =
9513 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f, 0.0f, 1.0f}},
9514 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.700195f, 0.0f, 1.0f}},
9515 {{ 0.0f, 0.0f, 0.f}, {-0.199951f, -0.300049f, 0.0f, 1.0f}},
9517 {{ 3.0f, 3.0f, 0.f}, {0.199951f, 0.300049f, 0.0f, 1.0f}},
9518 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f, 0.0f, 1.0f}},
9519 {{ 1.0f, 0.0f, 0.f}, {0.099976f, 0.199951f, 0.0f, 1.0f}},
9521 const UINT exp_vertex_size34 = sizeof(*exp_vertices34);
9522 /* Test 35. Convert FLOAT16_4 to FLOAT4. */
9523 const struct vertex_ptc_float16_4 vertices35[] =
9525 {{ 0.0f, 3.0f, 0.f}, {0x0000, 0x0000, 0x0000, 0x0000}},
9526 {{ 2.0f, 3.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}},
9527 {{ 0.0f, 0.0f, 0.f}, {0x3c00, 0x0000, 0x3c00, 0x0000}},
9529 {{ 3.0f, 3.0f, 0.f}, {0x0000, 0x3c00, 0x0000, 0x3c00}},
9530 {{ 3.0f, 0.0f, 0.f}, {0x3800, 0x399a, 0xb266, 0xb4cd}},
9531 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266, 0x2e66, 0x3266}},
9533 const UINT num_vertices35 = ARRAY_SIZE(vertices35);
9534 const UINT num_faces35 = ARRAY_SIZE(vertices35) / VERTS_PER_FACE;
9535 const UINT vertex_size35 = sizeof(*vertices35);
9536 const struct vertex_ptc_float4 exp_vertices35[] =
9538 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9539 {{ 2.0f, 3.0f, 0.f}, {1.0f, 1.0f, 1.0f, 1.0f}},
9540 {{ 0.0f, 0.0f, 0.f}, {1.0f, 0.0f, 1.0f, 0.0f}},
9542 {{ 3.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.0f, 1.0f}},
9543 {{ 3.0f, 0.0f, 0.f}, {0.5f, 0.700195f, -0.199951f, -0.300049f}},
9544 {{ 1.0f, 0.0f, 0.f}, {0.099976f, 0.199951f, 0.099976f, 0.199951f}},
9546 const UINT exp_vertex_size35 = sizeof(*exp_vertices35);
9547 /* Test 36. Check that vertex buffer sharing is ok. */
9548 const struct vertex_pn vertices36[] =
9550 {{ 0.0f, 3.0f, 0.f}, up},
9551 {{ 2.0f, 3.0f, 0.f}, up},
9552 {{ 0.0f, 0.0f, 0.f}, up},
9554 const UINT num_vertices36 = ARRAY_SIZE(vertices36);
9555 const UINT num_faces36 = ARRAY_SIZE(vertices36) / VERTS_PER_FACE;
9556 const UINT vertex_size36 = sizeof(*vertices36);
9557 const DWORD clone_options36 = options | D3DXMESH_VB_SHARE;
9558 /* Common mesh data */
9559 ID3DXMesh *mesh = NULL;
9560 ID3DXMesh *mesh_clone = NULL;
9561 struct
9563 const BYTE *vertices;
9564 const DWORD *indices;
9565 const DWORD *attributes;
9566 const UINT num_vertices;
9567 const UINT num_faces;
9568 const UINT vertex_size;
9569 const DWORD create_options;
9570 const DWORD clone_options;
9571 D3DVERTEXELEMENT9 *declaration;
9572 D3DVERTEXELEMENT9 *new_declaration;
9573 const BYTE *exp_vertices;
9574 const UINT exp_vertex_size;
9576 tc[] =
9579 (BYTE*)vertices0,
9580 NULL,
9581 NULL,
9582 num_vertices0,
9583 num_faces0,
9584 vertex_size0,
9585 options,
9586 options,
9587 declaration_pn,
9588 declaration_pn,
9589 (BYTE*)vertices0,
9590 vertex_size0
9593 (BYTE*)vertices0,
9594 NULL,
9595 NULL,
9596 num_vertices0,
9597 num_faces0,
9598 vertex_size0,
9599 options_16bit,
9600 options_16bit,
9601 declaration_pn,
9602 declaration_pn,
9603 (BYTE*)vertices0,
9604 vertex_size0
9607 (BYTE*)vertices0,
9608 NULL,
9609 NULL,
9610 num_vertices0,
9611 num_faces0,
9612 vertex_size0,
9613 options,
9614 options,
9615 declaration_pn,
9616 declaration_pntc,
9617 (BYTE*)exp_vertices2,
9618 exp_vertex_size2
9621 (BYTE*)vertices0,
9622 NULL,
9623 NULL,
9624 num_vertices0,
9625 num_faces0,
9626 vertex_size0,
9627 options,
9628 options,
9629 declaration_pn,
9630 declaration_ptcn,
9631 (BYTE*)exp_vertices3,
9632 exp_vertex_size3
9635 (BYTE*)vertices4,
9636 NULL,
9637 NULL,
9638 num_vertices4,
9639 num_faces4,
9640 vertex_size4,
9641 options,
9642 options,
9643 declaration_ptc,
9644 declaration_ptc_float16_2,
9645 (BYTE*)exp_vertices4,
9646 exp_vertex_size4
9649 (BYTE*)vertices5,
9650 NULL,
9651 NULL,
9652 num_vertices5,
9653 num_faces5,
9654 vertex_size5,
9655 options,
9656 options,
9657 declaration_ptc,
9658 declaration_ptc_float16_4,
9659 (BYTE*)exp_vertices5,
9660 exp_vertex_size5
9663 (BYTE*)vertices6,
9664 NULL,
9665 NULL,
9666 num_vertices6,
9667 num_faces6,
9668 vertex_size6,
9669 options,
9670 options,
9671 declaration_ptc,
9672 declaration_ptc_float1,
9673 (BYTE*)exp_vertices6,
9674 exp_vertex_size6
9677 (BYTE*)vertices7,
9678 NULL,
9679 NULL,
9680 num_vertices7,
9681 num_faces7,
9682 vertex_size7,
9683 options,
9684 options,
9685 declaration_ptc,
9686 declaration_ptc_float3,
9687 (BYTE*)exp_vertices7,
9688 exp_vertex_size7
9691 (BYTE*)vertices8,
9692 NULL,
9693 NULL,
9694 num_vertices8,
9695 num_faces8,
9696 vertex_size8,
9697 options,
9698 options,
9699 declaration_ptc,
9700 declaration_ptc_float4,
9701 (BYTE*)exp_vertices8,
9702 exp_vertex_size8
9705 (BYTE*)vertices9,
9706 NULL,
9707 NULL,
9708 num_vertices9,
9709 num_faces9,
9710 vertex_size9,
9711 options,
9712 options,
9713 declaration_ptc,
9714 declaration_ptc_d3dcolor,
9715 (BYTE*)exp_vertices9,
9716 exp_vertex_size9
9719 (BYTE*)vertices10,
9720 NULL,
9721 NULL,
9722 num_vertices10,
9723 num_faces10,
9724 vertex_size10,
9725 options,
9726 options,
9727 declaration_ptc,
9728 declaration_ptc_ubyte4,
9729 (BYTE*)exp_vertices10,
9730 exp_vertex_size10
9733 (BYTE*)vertices11,
9734 NULL,
9735 NULL,
9736 num_vertices11,
9737 num_faces11,
9738 vertex_size11,
9739 options,
9740 options,
9741 declaration_ptc,
9742 declaration_ptc_short2,
9743 (BYTE*)exp_vertices11,
9744 exp_vertex_size11
9747 (BYTE*)vertices12,
9748 NULL,
9749 NULL,
9750 num_vertices12,
9751 num_faces12,
9752 vertex_size12,
9753 options,
9754 options,
9755 declaration_ptc,
9756 declaration_ptc_short4,
9757 (BYTE*)exp_vertices12,
9758 exp_vertex_size12
9761 (BYTE*)vertices13,
9762 NULL,
9763 NULL,
9764 num_vertices13,
9765 num_faces13,
9766 vertex_size13,
9767 options,
9768 options,
9769 declaration_ptc,
9770 declaration_ptc_ubyte4n,
9771 (BYTE*)exp_vertices13,
9772 exp_vertex_size13
9775 (BYTE*)vertices14,
9776 NULL,
9777 NULL,
9778 num_vertices14,
9779 num_faces14,
9780 vertex_size14,
9781 options,
9782 options,
9783 declaration_ptc,
9784 declaration_ptc_short2n,
9785 (BYTE*)exp_vertices14,
9786 exp_vertex_size14
9789 (BYTE*)vertices15,
9790 NULL,
9791 NULL,
9792 num_vertices15,
9793 num_faces15,
9794 vertex_size15,
9795 options,
9796 options,
9797 declaration_ptc,
9798 declaration_ptc_short4n,
9799 (BYTE*)exp_vertices15,
9800 exp_vertex_size15
9803 (BYTE*)vertices16,
9804 NULL,
9805 NULL,
9806 num_vertices16,
9807 num_faces16,
9808 vertex_size16,
9809 options,
9810 options,
9811 declaration_ptc,
9812 declaration_ptc_ushort2n,
9813 (BYTE*)exp_vertices16,
9814 exp_vertex_size16
9817 (BYTE*)vertices17,
9818 NULL,
9819 NULL,
9820 num_vertices17,
9821 num_faces17,
9822 vertex_size17,
9823 options,
9824 options,
9825 declaration_ptc,
9826 declaration_ptc_ushort4n,
9827 (BYTE*)exp_vertices17,
9828 exp_vertex_size17
9831 (BYTE*)vertices18,
9832 NULL,
9833 NULL,
9834 num_vertices18,
9835 num_faces18,
9836 vertex_size18,
9837 options,
9838 options,
9839 declaration_ptc,
9840 declaration_ptc_float16_2_partialu,
9841 (BYTE*)exp_vertices18,
9842 exp_vertex_size18
9845 (BYTE*)vertices19,
9846 NULL,
9847 NULL,
9848 num_vertices19,
9849 num_faces19,
9850 vertex_size19,
9851 options,
9852 options,
9853 declaration_pntc,
9854 declaration_pntc1,
9855 (BYTE*)exp_vertices19,
9856 exp_vertex_size19
9859 (BYTE*)vertices20,
9860 NULL,
9861 NULL,
9862 num_vertices20,
9863 num_faces20,
9864 vertex_size20,
9865 options,
9866 options,
9867 declaration_pntc1,
9868 declaration_pntc,
9869 (BYTE*)exp_vertices20,
9870 exp_vertex_size20
9873 (BYTE*)vertices21,
9874 NULL,
9875 NULL,
9876 num_vertices21,
9877 num_faces21,
9878 vertex_size21,
9879 options,
9880 options,
9881 declaration_ptc_float1,
9882 declaration_ptc,
9883 (BYTE*)exp_vertices21,
9884 exp_vertex_size21
9887 (BYTE*)vertices22,
9888 NULL,
9889 NULL,
9890 num_vertices22,
9891 num_faces22,
9892 vertex_size22,
9893 options,
9894 options,
9895 declaration_ptc_float1,
9896 declaration_ptc_float3,
9897 (BYTE*)exp_vertices22,
9898 exp_vertex_size22
9901 (BYTE*)vertices23,
9902 NULL,
9903 NULL,
9904 num_vertices23,
9905 num_faces23,
9906 vertex_size23,
9907 options,
9908 options,
9909 declaration_ptc_float1,
9910 declaration_ptc_float4,
9911 (BYTE*)exp_vertices23,
9912 exp_vertex_size23
9915 (BYTE*)vertices24,
9916 NULL,
9917 NULL,
9918 num_vertices24,
9919 num_faces24,
9920 vertex_size24,
9921 options,
9922 options,
9923 declaration_ptc_float1,
9924 declaration_ptc_d3dcolor,
9925 (BYTE*)exp_vertices24,
9926 exp_vertex_size24
9929 (BYTE*)vertices25,
9930 NULL,
9931 NULL,
9932 num_vertices25,
9933 num_faces25,
9934 vertex_size25,
9935 options,
9936 options,
9937 declaration_ptc_float1,
9938 declaration_ptc_ubyte4,
9939 (BYTE*)exp_vertices25,
9940 exp_vertex_size25
9943 (BYTE*)vertices26,
9944 NULL,
9945 NULL,
9946 num_vertices26,
9947 num_faces26,
9948 vertex_size26,
9949 options,
9950 options,
9951 declaration_ptc_float4,
9952 declaration_ptc_d3dcolor,
9953 (BYTE*)exp_vertices26,
9954 exp_vertex_size26
9957 (BYTE*)vertices27,
9958 NULL,
9959 NULL,
9960 num_vertices27,
9961 num_faces27,
9962 vertex_size27,
9963 options,
9964 options,
9965 declaration_ptc_d3dcolor,
9966 declaration_ptc_float4,
9967 (BYTE*)exp_vertices27,
9968 exp_vertex_size27
9971 (BYTE*)vertices28,
9972 NULL,
9973 NULL,
9974 num_vertices28,
9975 num_faces28,
9976 vertex_size28,
9977 options,
9978 options,
9979 declaration_ptc_ubyte4,
9980 declaration_ptc_float4,
9981 (BYTE*)exp_vertices28,
9982 exp_vertex_size28
9985 (BYTE*)vertices29,
9986 NULL,
9987 NULL,
9988 num_vertices29,
9989 num_faces29,
9990 vertex_size29,
9991 options,
9992 options,
9993 declaration_ptc_short2,
9994 declaration_ptc_float4,
9995 (BYTE*)exp_vertices29,
9996 exp_vertex_size29
9999 (BYTE*)vertices30,
10000 NULL,
10001 NULL,
10002 num_vertices30,
10003 num_faces30,
10004 vertex_size30,
10005 options,
10006 options,
10007 declaration_ptc_short4,
10008 declaration_ptc_float4,
10009 (BYTE*)exp_vertices30,
10010 exp_vertex_size30
10013 (BYTE*)vertices31,
10014 NULL,
10015 NULL,
10016 num_vertices31,
10017 num_faces31,
10018 vertex_size31,
10019 options,
10020 options,
10021 declaration_ptc_ubyte4n,
10022 declaration_ptc_float4,
10023 (BYTE*)exp_vertices31,
10024 exp_vertex_size31
10027 (BYTE*)vertices32,
10028 NULL,
10029 NULL,
10030 num_vertices32,
10031 num_faces32,
10032 vertex_size32,
10033 options,
10034 options,
10035 declaration_ptc_short2n,
10036 declaration_ptc_float4,
10037 (BYTE*)exp_vertices32,
10038 exp_vertex_size32
10041 (BYTE*)vertices33,
10042 NULL,
10043 NULL,
10044 num_vertices33,
10045 num_faces33,
10046 vertex_size33,
10047 options,
10048 options,
10049 declaration_ptc_short4n,
10050 declaration_ptc_float4,
10051 (BYTE*)exp_vertices33,
10052 exp_vertex_size33
10055 (BYTE*)vertices34,
10056 NULL,
10057 NULL,
10058 num_vertices34,
10059 num_faces34,
10060 vertex_size34,
10061 options,
10062 options,
10063 declaration_ptc_float16_2,
10064 declaration_ptc_float4,
10065 (BYTE*)exp_vertices34,
10066 exp_vertex_size34
10069 (BYTE*)vertices35,
10070 NULL,
10071 NULL,
10072 num_vertices35,
10073 num_faces35,
10074 vertex_size35,
10075 options,
10076 options,
10077 declaration_ptc_float16_4,
10078 declaration_ptc_float4,
10079 (BYTE*)exp_vertices35,
10080 exp_vertex_size35
10083 (BYTE*)vertices36,
10084 NULL,
10085 NULL,
10086 num_vertices36,
10087 num_faces36,
10088 vertex_size36,
10089 options,
10090 clone_options36,
10091 declaration_pn,
10092 declaration_pn,
10093 (BYTE*)vertices36,
10094 vertex_size36
10098 test_context = new_test_context();
10099 if (!test_context)
10101 skip("Couldn't create test context\n");
10102 goto cleanup;
10105 for (i = 0; i < ARRAY_SIZE(tc); i++)
10107 UINT j;
10108 D3DVERTEXELEMENT9 new_declaration[MAX_FVF_DECL_SIZE];
10109 UINT exp_new_decl_length, new_decl_length;
10110 UINT exp_new_decl_size, new_decl_size;
10112 hr = init_test_mesh(tc[i].num_faces, tc[i].num_vertices,
10113 tc[i].create_options,
10114 tc[i].declaration,
10115 test_context->device, &mesh,
10116 tc[i].vertices, tc[i].vertex_size,
10117 tc[i].indices, tc[i].attributes);
10118 if (FAILED(hr))
10120 skip("Couldn't initialize test mesh %d. Got %x expected D3D_OK\n", i, hr);
10121 goto cleanup;
10124 hr = mesh->lpVtbl->CloneMesh(mesh, tc[i].clone_options, tc[i].new_declaration,
10125 test_context->device, &mesh_clone);
10126 ok(hr == D3D_OK, "CloneMesh test case %d failed. Got %x\n, expected D3D_OK\n", i, hr);
10128 hr = mesh_clone->lpVtbl->GetDeclaration(mesh_clone, new_declaration);
10129 ok(hr == D3D_OK, "GetDeclaration test case %d failed. Got %x\n, expected D3D_OK\n", i, hr);
10130 /* Check declaration elements */
10131 for (j = 0; tc[i].new_declaration[j].Stream != 0xFF; j++)
10133 ok(memcmp(&tc[i].new_declaration[j], &new_declaration[j], sizeof(*new_declaration)) == 0,
10134 "Test case %d failed. Declaration element %d did not match.\n", i, j);
10137 /* Check declaration length */
10138 exp_new_decl_length = D3DXGetDeclLength(tc[i].new_declaration);
10139 new_decl_length = D3DXGetDeclLength(new_declaration);
10140 ok(new_decl_length == exp_new_decl_length,
10141 "Test case %d failed. Got new declaration length %d, expected %d\n",
10142 i, new_decl_length, exp_new_decl_length);
10144 /* Check declaration size */
10145 exp_new_decl_size = D3DXGetDeclVertexSize(tc[i].new_declaration, 0);
10146 new_decl_size = D3DXGetDeclVertexSize(new_declaration, 0);
10147 ok(new_decl_size == exp_new_decl_size,
10148 "Test case %d failed. Got new declaration size %d, expected %d\n",
10149 i, new_decl_size, exp_new_decl_size);
10151 /* Check vertex data in cloned mesh */
10152 hr = mesh_clone->lpVtbl->LockVertexBuffer(mesh_clone, 0, (void**)&vertices);
10153 if (FAILED(hr))
10155 skip("Couldn't lock cloned vertex buffer.\n");
10156 goto cleanup;
10158 for (j = 0; j < tc[i].num_vertices; j++)
10160 UINT index = tc[i].exp_vertex_size * j;
10161 check_vertex_components(__LINE__, i, j, &vertices[index], &tc[i].exp_vertices[index], tc[i].new_declaration);
10163 hr = mesh_clone->lpVtbl->UnlockVertexBuffer(mesh_clone);
10164 if (FAILED(hr))
10166 skip("Couldn't unlock vertex buffer.\n");
10167 goto cleanup;
10169 vertices = NULL;
10170 mesh->lpVtbl->Release(mesh);
10171 mesh = NULL;
10172 mesh_clone->lpVtbl->Release(mesh_clone);
10173 mesh_clone = NULL;
10176 /* The following test shows that it is not possible to share a vertex buffer
10177 * with D3DXMESH_VB_SHARE and change the vertex declaration at the same
10178 * time. It reuses the test data from test 2.
10180 hr = init_test_mesh(tc[2].num_faces, tc[2].num_vertices,
10181 tc[2].create_options,
10182 tc[2].declaration,
10183 test_context->device, &mesh,
10184 tc[2].vertices, tc[2].vertex_size,
10185 tc[2].indices, tc[2].attributes);
10186 if (FAILED(hr))
10188 skip("Couldn't initialize test mesh for D3DXMESH_VB_SHARE case."
10189 " Got %x expected D3D_OK\n", hr);
10190 goto cleanup;
10193 hr = mesh->lpVtbl->CloneMesh(mesh, tc[2].create_options | D3DXMESH_VB_SHARE,
10194 tc[2].new_declaration, test_context->device,
10195 &mesh_clone);
10196 ok(hr == D3DERR_INVALIDCALL, "CloneMesh D3DXMESH_VB_SHARE with new"
10197 " declaration. Got %x, expected D3DERR_INVALIDCALL\n",
10198 hr);
10199 mesh->lpVtbl->Release(mesh);
10200 mesh = NULL;
10201 mesh_clone = NULL;
10203 cleanup:
10204 if (vertices) mesh->lpVtbl->UnlockVertexBuffer(mesh);
10205 if (mesh) mesh->lpVtbl->Release(mesh);
10206 if (mesh_clone) mesh_clone->lpVtbl->Release(mesh_clone);
10207 free_test_context(test_context);
10210 static void test_valid_mesh(void)
10212 HRESULT hr;
10213 struct test_context *test_context = NULL;
10214 UINT i;
10215 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
10216 const D3DVERTEXELEMENT9 declaration[] =
10218 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
10219 D3DDECL_END()
10221 const unsigned int VERTS_PER_FACE = 3;
10222 /* mesh0 (one face)
10224 * 0--1
10225 * | /
10226 * |/
10229 const D3DXVECTOR3 vertices0[] =
10231 { 0.0f, 3.0f, 0.f},
10232 { 2.0f, 3.0f, 0.f},
10233 { 0.0f, 0.0f, 0.f},
10235 const DWORD indices0[] = {0, 1, 2};
10236 const unsigned int num_vertices0 = ARRAY_SIZE(vertices0);
10237 const unsigned int num_faces0 = ARRAY_SIZE(indices0) / VERTS_PER_FACE;
10238 const DWORD adjacency0[] = {-1, -1, -1};
10239 const HRESULT exp_hr0 = D3D_OK;
10240 /* mesh1 (Simple bow-tie)
10242 * 0--1 1--3
10243 * | / \ |
10244 * |/ \|
10245 * 2 4
10247 const D3DXVECTOR3 vertices1[] =
10249 { 0.0f, 3.0f, 0.f},
10250 { 2.0f, 3.0f, 0.f},
10251 { 0.0f, 0.0f, 0.f},
10253 { 4.0f, 3.0f, 0.f},
10254 { 4.0f, 0.0f, 0.f},
10256 const DWORD indices1[] = {0, 1, 2, 1, 3, 4};
10257 const unsigned int num_vertices1 = ARRAY_SIZE(vertices1);
10258 const unsigned int num_faces1 = ARRAY_SIZE(indices1) / VERTS_PER_FACE;
10259 const DWORD adjacency1[] = {-1, -1, -1, -1, -1, -1};
10260 const HRESULT exp_hr1 = D3DXERR_INVALIDMESH;
10261 /* Common mesh data */
10262 ID3DXMesh *mesh = NULL;
10263 UINT vertex_size = sizeof(D3DXVECTOR3);
10264 ID3DXBuffer *errors_and_warnings = NULL;
10265 struct
10267 const D3DXVECTOR3 *vertices;
10268 const DWORD *indices;
10269 const UINT num_vertices;
10270 const UINT num_faces;
10271 const DWORD *adjacency;
10272 const HRESULT exp_hr;
10274 tc[] =
10277 vertices0,
10278 indices0,
10279 num_vertices0,
10280 num_faces0,
10281 adjacency0,
10282 exp_hr0,
10285 vertices1,
10286 indices1,
10287 num_vertices1,
10288 num_faces1,
10289 adjacency1,
10290 exp_hr1,
10294 test_context = new_test_context();
10295 if (!test_context)
10297 skip("Couldn't create test context\n");
10298 goto cleanup;
10301 for (i = 0; i < ARRAY_SIZE(tc); i++)
10303 hr = init_test_mesh(tc[i].num_faces, tc[i].num_vertices,
10304 options, declaration,
10305 test_context->device, &mesh,
10306 tc[i].vertices, vertex_size,
10307 tc[i].indices, NULL);
10308 if (FAILED(hr))
10310 skip("Couldn't initialize test mesh %d. Got %x expected D3D_OK\n", i, hr);
10311 goto cleanup;
10314 hr = D3DXValidMesh(mesh, tc[i].adjacency, &errors_and_warnings);
10315 todo_wine ok(hr == tc[i].exp_hr, "D3DXValidMesh test case %d failed. "
10316 "Got %x\n, expected %x\n", i, hr, tc[i].exp_hr);
10318 /* Note errors_and_warnings is deliberately not checked because that
10319 * would require copying wast amounts of the text output. */
10320 if (errors_and_warnings)
10322 ID3DXBuffer_Release(errors_and_warnings);
10323 errors_and_warnings = NULL;
10325 mesh->lpVtbl->Release(mesh);
10326 mesh = NULL;
10329 cleanup:
10330 if (mesh) mesh->lpVtbl->Release(mesh);
10331 free_test_context(test_context);
10334 static void test_optimize_faces(void)
10336 HRESULT hr;
10337 UINT i;
10338 DWORD smallest_face_remap;
10339 /* mesh0
10341 * 0--1
10342 * | /
10343 * |/
10346 const DWORD indices0[] = {0, 1, 2};
10347 const UINT num_faces0 = 1;
10348 const UINT num_vertices0 = 3;
10349 const DWORD exp_face_remap0[] = {0};
10350 /* mesh1
10352 * 0--1 3
10353 * | / /|
10354 * |/ / |
10355 * 2 5--4
10357 const DWORD indices1[] = {0, 1, 2, 3, 4, 5};
10358 const UINT num_faces1 = 2;
10359 const UINT num_vertices1 = 6;
10360 const DWORD exp_face_remap1[] = {1, 0};
10361 /* mesh2
10363 * 0--1
10364 * | /|
10365 * |/ |
10366 * 2--3
10368 const DWORD indices2[] = {0, 1, 2, 1, 3, 2};
10369 const UINT num_faces2 = 2;
10370 const UINT num_vertices2 = 4;
10371 const DWORD exp_face_remap2[] = {1, 0};
10372 /* mesh3
10374 * 0--1
10375 * | /|
10376 * |/ |
10377 * 2--3
10378 * | /|
10379 * |/ |
10380 * 4--5
10382 const DWORD indices3[] = {0, 1, 2, 1, 3, 2, 2, 3, 4, 3, 4, 5};
10383 const UINT num_faces3 = 4;
10384 const UINT num_vertices3 = 6;
10385 const DWORD exp_face_remap3[] = {3, 2, 1, 0};
10386 /* mesh4
10388 * 0--1
10389 * | /|
10390 * |/ |
10391 * 2--3
10392 * | /|
10393 * |/ |
10394 * 4--5
10396 const WORD indices4[] = {0, 1, 2, 1, 3, 2, 2, 3, 4, 3, 4, 5};
10397 const UINT num_faces4 = 4;
10398 const UINT num_vertices4 = 6;
10399 const DWORD exp_face_remap4[] = {3, 2, 1, 0};
10400 /* Test cases are stored in the tc array */
10401 struct
10403 const VOID *indices;
10404 const UINT num_faces;
10405 const UINT num_vertices;
10406 const BOOL indices_are_32bit;
10407 const DWORD *exp_face_remap;
10409 tc[] =
10412 indices0,
10413 num_faces0,
10414 num_vertices0,
10415 TRUE,
10416 exp_face_remap0
10419 indices1,
10420 num_faces1,
10421 num_vertices1,
10422 TRUE,
10423 exp_face_remap1
10426 indices2,
10427 num_faces2,
10428 num_vertices2,
10429 TRUE,
10430 exp_face_remap2
10433 indices3,
10434 num_faces3,
10435 num_vertices3,
10436 TRUE,
10437 exp_face_remap3
10440 indices4,
10441 num_faces4,
10442 num_vertices4,
10443 FALSE,
10444 exp_face_remap4
10448 /* Go through all test cases */
10449 for (i = 0; i < ARRAY_SIZE(tc); i++)
10451 DWORD j;
10452 DWORD *face_remap;
10453 face_remap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
10454 tc[i].num_faces*sizeof(*face_remap));
10456 hr = D3DXOptimizeFaces(tc[i].indices, tc[i].num_faces,
10457 tc[i].num_vertices, tc[i].indices_are_32bit,
10458 face_remap);
10459 ok(hr == D3D_OK, "D3DXOptimizeFaces test case %d failed. "
10460 "Got %x\n, expected D3D_OK\n", i, hr);
10462 /* Compare face remap with expected face remap */
10463 for (j = 0; j < tc[i].num_faces; j++)
10465 ok(tc[i].exp_face_remap[j] == face_remap[j],
10466 "Test case %d: Got face %d at %d, expected %d\n", i,
10467 face_remap[j], j, tc[i].exp_face_remap[j]);
10470 HeapFree(GetProcessHeap(), 0, face_remap);
10473 /* face_remap must not be NULL */
10474 hr = D3DXOptimizeFaces(tc[0].indices, tc[0].num_faces,
10475 tc[0].num_vertices, tc[0].indices_are_32bit,
10476 NULL);
10477 ok(hr == D3DERR_INVALIDCALL, "D3DXOptimizeFaces passed NULL face_remap "
10478 "pointer. Got %x\n, expected D3DERR_INVALIDCALL\n", hr);
10480 /* Number of faces must be smaller than 2^15 */
10481 hr = D3DXOptimizeFaces(tc[0].indices, 2 << 15,
10482 tc[0].num_vertices, FALSE,
10483 &smallest_face_remap);
10484 ok(hr == D3DERR_INVALIDCALL, "D3DXOptimizeFaces should not accept 2^15 "
10485 "faces when using 16-bit indices. Got %x\n, expected D3DERR_INVALIDCALL\n", hr);
10488 static HRESULT clear_normals(ID3DXMesh *mesh)
10490 HRESULT hr;
10491 BYTE *vertices;
10492 size_t normal_size;
10493 DWORD i, num_vertices, vertex_stride;
10494 const D3DXVECTOR4 normal = {NAN, NAN, NAN, NAN};
10495 D3DVERTEXELEMENT9 *normal_declaration = NULL;
10496 D3DVERTEXELEMENT9 declaration[MAX_FVF_DECL_SIZE] = {D3DDECL_END()};
10498 if (FAILED(hr = mesh->lpVtbl->GetDeclaration(mesh, declaration)))
10499 return hr;
10501 for (i = 0; declaration[i].Stream != 0xff; i++)
10503 if (declaration[i].Usage == D3DDECLUSAGE_NORMAL && !declaration[i].UsageIndex)
10505 normal_declaration = &declaration[i];
10506 break;
10510 if (!normal_declaration)
10511 return D3DERR_INVALIDCALL;
10513 if (normal_declaration->Type == D3DDECLTYPE_FLOAT3)
10515 normal_size = sizeof(D3DXVECTOR3);
10517 else if (normal_declaration->Type == D3DDECLTYPE_FLOAT4)
10519 normal_size = sizeof(D3DXVECTOR4);
10521 else
10523 trace("Cannot clear normals\n");
10524 return E_NOTIMPL;
10527 num_vertices = mesh->lpVtbl->GetNumVertices(mesh);
10528 vertex_stride = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
10530 if (FAILED(hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, (void **)&vertices)))
10531 return hr;
10533 vertices += normal_declaration->Offset;
10535 for (i = 0; i < num_vertices; i++, vertices += vertex_stride)
10536 memcpy(vertices, &normal, normal_size);
10538 return mesh->lpVtbl->UnlockVertexBuffer(mesh);
10541 static void compare_normals(unsigned int line, const char *test_name,
10542 ID3DXMesh *mesh, const D3DXVECTOR3 *normals, unsigned int num_normals)
10544 unsigned int i;
10545 BYTE *vertices;
10546 DWORD num_vertices, vertex_stride;
10547 D3DVERTEXELEMENT9 *normal_declaration = NULL;
10548 D3DVERTEXELEMENT9 declaration[MAX_FVF_DECL_SIZE] = {D3DDECL_END()};
10550 if (FAILED(mesh->lpVtbl->GetDeclaration(mesh, declaration)))
10552 ok_(__FILE__, line)(0, "%s: Failed to get declaration\n", test_name);
10553 return;
10556 for (i = 0; declaration[i].Stream != 0xff; i++)
10558 if (declaration[i].Usage == D3DDECLUSAGE_NORMAL && !declaration[i].UsageIndex)
10560 normal_declaration = &declaration[i];
10561 break;
10565 if (!normal_declaration)
10567 ok_(__FILE__, line)(0, "%s: Mesh has no normals\n", test_name);
10568 return;
10571 if (normal_declaration->Type != D3DDECLTYPE_FLOAT3 && normal_declaration->Type != D3DDECLTYPE_FLOAT4)
10573 ok_(__FILE__, line)(0, "%s: Mesh has invalid normals type\n", test_name);
10574 return;
10577 num_vertices = mesh->lpVtbl->GetNumVertices(mesh);
10578 vertex_stride = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
10580 ok_(__FILE__, line)(num_vertices == num_normals, "%s: Expected %u vertices, got %u\n", test_name,
10581 num_normals, num_vertices);
10583 if (FAILED(mesh->lpVtbl->LockVertexBuffer(mesh, 0, (void **)&vertices)))
10585 ok_(__FILE__, line)(0, "%s: Failed to compare normals\n", test_name);
10586 return;
10589 vertices += normal_declaration->Offset;
10591 for (i = 0; i < min(num_vertices, num_normals); i++, vertices += vertex_stride)
10593 if (normal_declaration->Type == D3DDECLTYPE_FLOAT3)
10595 const D3DXVECTOR3 *n = (D3DXVECTOR3 *)vertices;
10596 ok_(__FILE__, line)(compare_vec3(*n, normals[i]),
10597 "%s: normal %2u, expected (%f, %f, %f), got (%f, %f, %f)\n",
10598 test_name, i, normals[i].x, normals[i].y, normals[i].z, n->x, n->y, n->z);
10600 else
10602 const D3DXVECTOR4 *n = (D3DXVECTOR4 *)vertices;
10603 const D3DXVECTOR4 normal = {normals[i].x, normals[i].y, normals[i].z, 1.0f};
10604 ok_(__FILE__, line)(compare_vec4(*n, normal),
10605 "%s: normal %2u, expected (%f, %f, %f, %f), got (%f, %f, %f, %f)\n",
10606 test_name, i, normals[i].x, normals[i].y, normals[i].z, 1.0f,
10607 n->x, n->y, n->z, n->w);
10611 mesh->lpVtbl->UnlockVertexBuffer(mesh);
10614 static HRESULT compute_normals_D3DXComputeNormals(ID3DXMesh *mesh, const DWORD *adjacency)
10616 return D3DXComputeNormals((ID3DXBaseMesh *)mesh, adjacency);
10619 static HRESULT compute_normals_D3DXComputeTangentFrameEx(ID3DXMesh *mesh, const DWORD *adjacency)
10621 return D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
10622 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS,
10623 adjacency, -1.01f, -0.01f, -1.01f, NULL, NULL);
10626 static void test_compute_normals(void)
10628 HRESULT hr;
10629 ULONG refcount;
10630 ID3DXMesh *mesh, *cloned_mesh;
10631 ID3DXBuffer *adjacency;
10632 IDirect3DDevice9 *device;
10633 struct test_context *test_context;
10634 unsigned int i;
10636 static const struct compute_normals_func
10638 const char *name;
10639 HRESULT (*apply)(ID3DXMesh *mesh, const DWORD *adjacency);
10641 compute_normals_funcs[] =
10643 {"D3DXComputeNormals", compute_normals_D3DXComputeNormals },
10644 {"D3DXComputeTangentFrameEx", compute_normals_D3DXComputeTangentFrameEx}
10647 static const D3DXVECTOR3 box_normals[24] =
10649 {-1.0f, 0.0f, 0.0f}, {-1.0f, 0.0f, 0.0f}, {-1.0f, 0.0f, 0.0f}, {-1.0f, 0.0f, 0.0f},
10650 { 0.0f, 1.0f, 0.0f}, { 0.0f, 1.0f, 0.0f}, { 0.0f, 1.0f, 0.0f}, { 0.0f, 1.0f, 0.0f},
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 { 0.0f, 0.0f, 1.0f}, { 0.0f, 0.0f, 1.0f}, { 0.0f, 0.0f, 1.0f}, { 0.0f, 0.0f, 1.0f},
10654 { 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 const float box_normal_component = 1.0f / sqrtf(3.0f);
10657 const D3DXVECTOR3 box_normals_adjacency[24] =
10659 {-box_normal_component, -box_normal_component, -box_normal_component},
10660 {-box_normal_component, -box_normal_component, box_normal_component},
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}
10684 static const D3DXVECTOR3 box_normals_adjacency_area[24] =
10686 {-0.666667f, -0.333333f, -0.666667f}, {-0.333333f, -0.666667f, 0.666667f},
10687 {-0.816496f, 0.408248f, 0.408248f}, {-0.408248f, 0.816496f, -0.408248f},
10688 {-0.408248f, 0.816496f, -0.408248f}, {-0.816496f, 0.408248f, 0.408248f},
10689 { 0.333333f, 0.666667f, 0.666667f}, { 0.666667f, 0.333333f, -0.666667f},
10690 { 0.666667f, 0.333333f, -0.666667f}, { 0.333333f, 0.666667f, 0.666667f},
10691 { 0.816496f, -0.408248f, 0.408248f}, { 0.408248f, -0.816496f, -0.408248f},
10692 {-0.333333f, -0.666667f, 0.666667f}, {-0.666667f, -0.333333f, -0.666667f},
10693 { 0.408248f, -0.816496f, -0.408248f}, { 0.816496f, -0.408248f, 0.408248f},
10694 {-0.333333f, -0.666667f, 0.666667f}, { 0.816497f, -0.408248f, 0.408248f},
10695 { 0.333333f, 0.666667f, 0.666667f}, {-0.816497f, 0.408248f, 0.408248f},
10696 {-0.666667f, -0.333333f, -0.666667f}, {-0.408248f, 0.816497f, -0.408248f},
10697 { 0.666667f, 0.333333f, -0.666667f}, { 0.408248f, -0.816496f, -0.408248f}
10699 static const D3DXVECTOR3 box_normals_position1f[24] = {{0}};
10700 static const D3DXVECTOR3 box_normals_position2f[24] =
10702 {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f},
10703 {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, 1.0f},
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}
10712 static const D3DXVECTOR3 sphere_normals[22] =
10714 { 0.000000f, -0.000000f, 1.000000f}, { 0.000000f, 0.582244f, 0.813014f},
10715 { 0.582244f, -0.000000f, 0.813014f}, {-0.000000f, -0.582244f, 0.813014f},
10716 {-0.582244f, 0.000000f, 0.813014f}, {-0.000000f, 0.890608f, 0.454772f},
10717 { 0.890608f, 0.000000f, 0.454772f}, { 0.000000f, -0.890608f, 0.454772f},
10718 {-0.890608f, -0.000000f, 0.454772f}, { 0.000000f, 1.000000f, -0.000000f},
10719 { 1.000000f, -0.000000f, -0.000000f}, {-0.000000f, -1.000000f, -0.000000f},
10720 {-1.000000f, 0.000000f, -0.000000f}, { 0.000000f, 0.890608f, -0.454773f},
10721 { 0.890608f, -0.000000f, -0.454772f}, {-0.000000f, -0.890608f, -0.454773f},
10722 {-0.890608f, 0.000000f, -0.454773f}, { 0.000000f, 0.582244f, -0.813015f},
10723 { 0.582244f, -0.000000f, -0.813015f}, { 0.000000f, -0.582244f, -0.813015f},
10724 {-0.582243f, 0.000000f, -0.813015f}, { 0.000000f, 0.000000f, -1.000000f}
10726 static const D3DXVECTOR3 sphere_normals_area[22] =
10728 { 0.000000f, -0.000000f, 1.000000f}, {-0.215311f, 0.554931f, 0.803550f},
10729 { 0.554931f, 0.215311f, 0.803550f}, { 0.215311f, -0.554931f, 0.803550f},
10730 {-0.554931f, -0.215311f, 0.803550f}, {-0.126638f, 0.872121f, 0.472618f},
10731 { 0.872121f, 0.126638f, 0.472618f}, { 0.126638f, -0.872121f, 0.472618f},
10732 {-0.872121f, -0.126637f, 0.472618f}, { 0.000000f, 1.000000f, -0.000000f},
10733 { 1.000000f, -0.000000f, -0.000000f}, {-0.000000f, -1.000000f, -0.000000f},
10734 {-1.000000f, 0.000000f, -0.000000f}, { 0.126638f, 0.872121f, -0.472618f},
10735 { 0.872121f, -0.126638f, -0.472618f}, {-0.126638f, -0.872121f, -0.472618f},
10736 {-0.872121f, 0.126638f, -0.472618f}, { 0.215311f, 0.554931f, -0.803550f},
10737 { 0.554931f, -0.215311f, -0.803550f}, {-0.215311f, -0.554931f, -0.803550f},
10738 {-0.554931f, 0.215311f, -0.803550f}, { 0.000000f, 0.000000f, -1.000000f}
10740 static const D3DXVECTOR3 sphere_normals_equal[22] =
10742 { 0.000000f, -0.000000f, 1.000000f}, {-0.134974f, 0.522078f, 0.842150f},
10743 { 0.522078f, 0.134974f, 0.842150f}, { 0.134974f, -0.522078f, 0.842150f},
10744 {-0.522078f, -0.134974f, 0.842150f}, {-0.026367f, 0.857121f, 0.514440f},
10745 { 0.857121f, 0.026367f, 0.514440f}, { 0.026367f, -0.857121f, 0.514440f},
10746 {-0.857121f, -0.026367f, 0.514440f}, { 0.000000f, 1.000000f, -0.000000f},
10747 { 1.000000f, -0.000000f, -0.000000f}, {-0.000000f, -1.000000f, -0.000000f},
10748 {-1.000000f, 0.000000f, -0.000000f}, { 0.026367f, 0.857121f, -0.514440f},
10749 { 0.857121f, -0.026367f, -0.514440f}, {-0.026367f, -0.857121f, -0.514440f},
10750 {-0.857121f, 0.026367f, -0.514440f}, { 0.134975f, 0.522078f, -0.842150f},
10751 { 0.522078f, -0.134975f, -0.842150f}, {-0.134974f, -0.522078f, -0.842150f},
10752 {-0.522078f, 0.134974f, -0.842150f}, { 0.000000f, 0.000000f, -1.000000f}
10755 static const D3DVERTEXELEMENT9 position3f_normal1f_declaration[] =
10757 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
10758 {0, sizeof(D3DXVECTOR3), D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
10759 D3DDECL_END()
10761 static const D3DVERTEXELEMENT9 position3f_normal2f_declaration[] =
10763 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
10764 {0, sizeof(D3DXVECTOR3), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
10765 D3DDECL_END()
10767 static const D3DVERTEXELEMENT9 normal4f_position3f_declaration[] =
10769 {0, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
10770 {0, sizeof(D3DXVECTOR4), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
10771 D3DDECL_END()
10773 static const D3DVERTEXELEMENT9 position1f_normal3f_declaration[] =
10775 {0, 0, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
10776 {0, sizeof(float), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
10777 D3DDECL_END()
10779 static const D3DVERTEXELEMENT9 position2f_normal3f_declaration[] =
10781 {0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
10782 {0, sizeof(D3DXVECTOR2), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
10783 D3DDECL_END()
10785 static const D3DVERTEXELEMENT9 position4f_normal3f_declaration[] =
10787 {0, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
10788 {0, sizeof(D3DXVECTOR4), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
10789 D3DDECL_END()
10792 for (i = 0; i < ARRAY_SIZE(compute_normals_funcs); i++)
10794 hr = compute_normals_funcs[i].apply(NULL, NULL);
10795 ok(hr == D3DERR_INVALIDCALL, "%s returned %#x, expected D3DERR_INVALIDCALL\n", compute_normals_funcs[i].name, hr);
10798 if (!(test_context = new_test_context()))
10800 skip("Couldn't create test context\n");
10801 return;
10803 device = test_context->device;
10805 hr = D3DXCreateBox(device, 1.0f, 1.0f, 1.0f, &mesh, &adjacency);
10806 ok(SUCCEEDED(hr), "D3DXCreateBox failed %#x\n", hr);
10808 /* Check wrong input */
10809 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
10810 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE, NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
10811 todo_wine ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr);
10813 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DDECLUSAGE_NORMAL, 0,
10814 D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_BY_AREA | D3DXTANGENT_WEIGHT_EQUAL,
10815 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
10816 ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr);
10818 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
10819 D3DDECLUSAGE_NORMAL, 0, 0, NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
10820 todo_wine ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr);
10822 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
10823 D3DDECLUSAGE_NORMAL, 1, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS,
10824 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
10825 ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr);
10827 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
10828 D3DX_DEFAULT, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS,
10829 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
10830 ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr);
10832 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
10833 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_CALCULATE_NORMALS,
10834 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
10835 todo_wine ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr);
10837 for (i = 0; i < ARRAY_SIZE(compute_normals_funcs); i++)
10839 const struct compute_normals_func *func = &compute_normals_funcs[i];
10841 /* Mesh without normals */
10842 hr = mesh->lpVtbl->CloneMeshFVF(mesh, 0, D3DFVF_XYZ, device, &cloned_mesh);
10843 ok(SUCCEEDED(hr), "CloneMeshFVF failed %#x\n", hr);
10845 hr = func->apply(cloned_mesh, NULL);
10846 ok(hr == D3DERR_INVALIDCALL, "%s returned %#x, expected D3DERR_INVALIDCALL\n", func->name, hr);
10848 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh);
10849 ok(!refcount, "Mesh has %u references left\n", refcount);
10851 /* Mesh without positions */
10852 hr = mesh->lpVtbl->CloneMeshFVF(mesh, 0, D3DFVF_NORMAL, device, &cloned_mesh);
10853 ok(SUCCEEDED(hr), "CloneMeshFVF failed %#x\n", hr);
10855 hr = func->apply(cloned_mesh, NULL);
10856 ok(hr == D3DERR_INVALIDCALL, "%s returned %#x, expected D3DERR_INVALIDCALL\n", func->name, hr);
10858 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh);
10859 ok(!refcount, "Mesh has %u references left\n", refcount);
10861 /* Mesh with D3DDECLTYPE_FLOAT1 normals */
10862 hr = mesh->lpVtbl->CloneMesh(mesh, 0, position3f_normal1f_declaration, device, &cloned_mesh);
10863 ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr);
10865 hr = func->apply(cloned_mesh, NULL);
10866 ok(hr == D3DERR_INVALIDCALL, "%s returned %#x, expected D3DERR_INVALIDCALL\n", func->name, hr);
10868 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh);
10869 ok(!refcount, "Mesh has %u references left\n", refcount);
10871 /* Mesh with D3DDECLTYPE_FLOAT2 normals */
10872 hr = mesh->lpVtbl->CloneMesh(mesh, 0, position3f_normal2f_declaration, device, &cloned_mesh);
10873 ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr);
10875 hr = func->apply(cloned_mesh, NULL);
10876 ok(hr == D3DERR_INVALIDCALL, "%s returned %#x, expected D3DERR_INVALIDCALL\n", func->name, hr);
10878 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh);
10879 ok(!refcount, "Mesh has %u references left\n", refcount);
10881 /* Mesh without adjacency data */
10882 hr = clear_normals(mesh);
10883 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr);
10885 hr = func->apply(mesh, NULL);
10886 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr);
10888 compare_normals(__LINE__, func->name, mesh, box_normals, ARRAY_SIZE(box_normals));
10890 /* Mesh with adjacency data */
10891 hr = clear_normals(mesh);
10892 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr);
10894 hr = func->apply(mesh, ID3DXBuffer_GetBufferPointer(adjacency));
10895 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr);
10897 compare_normals(__LINE__, func->name, mesh, box_normals_adjacency, ARRAY_SIZE(box_normals_adjacency));
10899 /* Mesh with custom vertex format, D3DDECLTYPE_FLOAT4 normals and adjacency */
10900 hr = mesh->lpVtbl->CloneMesh(mesh, 0, normal4f_position3f_declaration, device, &cloned_mesh);
10901 ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr);
10903 hr = clear_normals(cloned_mesh);
10904 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr);
10906 hr = func->apply(cloned_mesh, ID3DXBuffer_GetBufferPointer(adjacency));
10907 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr);
10909 compare_normals(__LINE__, func->name, cloned_mesh, box_normals_adjacency, ARRAY_SIZE(box_normals_adjacency));
10911 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh);
10912 ok(!refcount, "Mesh has %u references left\n", refcount);
10914 /* Mesh with D3DDECLTYPE_FLOAT1 positions and D3DDECLTYPE_FLOAT3 normals */
10915 hr = mesh->lpVtbl->CloneMesh(mesh, 0, position1f_normal3f_declaration, device, &cloned_mesh);
10916 ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr);
10918 hr = clear_normals(cloned_mesh);
10919 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr);
10921 hr = func->apply(cloned_mesh, ID3DXBuffer_GetBufferPointer(adjacency));
10922 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr);
10924 compare_normals(__LINE__, func->name, cloned_mesh, box_normals_position1f, ARRAY_SIZE(box_normals_position1f));
10926 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh);
10927 ok(!refcount, "Mesh has %u references left\n", refcount);
10929 /* Mesh with D3DDECLTYPE_FLOAT2 positions and D3DDECLTYPE_FLOAT3 normals */
10930 hr = mesh->lpVtbl->CloneMesh(mesh, 0, position2f_normal3f_declaration, device, &cloned_mesh);
10931 ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr);
10933 hr = clear_normals(cloned_mesh);
10934 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr);
10936 hr = func->apply(cloned_mesh, ID3DXBuffer_GetBufferPointer(adjacency));
10937 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr);
10939 compare_normals(__LINE__, func->name, cloned_mesh, box_normals_position2f, ARRAY_SIZE(box_normals_position2f));
10941 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh);
10942 ok(!refcount, "Mesh has %u references left\n", refcount);
10944 /* Mesh with D3DDECLTYPE_FLOAT4 positions and D3DDECLTYPE_FLOAT3 normals */
10945 hr = mesh->lpVtbl->CloneMesh(mesh, 0, position4f_normal3f_declaration, device, &cloned_mesh);
10946 ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr);
10948 hr = clear_normals(cloned_mesh);
10949 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr);
10951 hr = func->apply(cloned_mesh, ID3DXBuffer_GetBufferPointer(adjacency));
10952 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr);
10954 compare_normals(__LINE__, func->name, cloned_mesh, box_normals_adjacency, ARRAY_SIZE(box_normals_adjacency));
10956 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh);
10957 ok(!refcount, "Mesh has %u references left\n", refcount);
10960 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
10961 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_BY_AREA,
10962 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
10963 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr);
10965 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, box_normals, ARRAY_SIZE(box_normals));
10967 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
10968 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_BY_AREA,
10969 ID3DXBuffer_GetBufferPointer(adjacency), -1.01f, -0.01f, -1.01f, NULL, NULL);
10970 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr);
10972 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, box_normals_adjacency_area, ARRAY_SIZE(box_normals_adjacency_area));
10974 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
10975 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_EQUAL,
10976 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
10977 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr);
10979 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, box_normals, ARRAY_SIZE(box_normals));
10981 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
10982 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_EQUAL,
10983 ID3DXBuffer_GetBufferPointer(adjacency), -1.01f, -0.01f, -1.01f, NULL, NULL);
10984 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr);
10986 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, box_normals_adjacency_area, ARRAY_SIZE(box_normals_adjacency_area));
10988 refcount = mesh->lpVtbl->Release(mesh);
10989 ok(!refcount, "Mesh has %u references left\n", refcount);
10990 refcount = ID3DXBuffer_Release(adjacency);
10991 ok(!refcount, "Buffer has %u references left\n", refcount);
10993 hr = D3DXCreateSphere(device, 1.0f, 4, 6, &mesh, &adjacency);
10994 ok(SUCCEEDED(hr), "D3DXCreateSphere failed %#x\n", hr);
10996 for (i = 0; i < ARRAY_SIZE(compute_normals_funcs); i++)
10998 const struct compute_normals_func *func = &compute_normals_funcs[i];
11000 /* Sphere without adjacency data */
11001 hr = clear_normals(mesh);
11002 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr);
11004 hr = func->apply(mesh, NULL);
11005 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr);
11007 compare_normals(__LINE__, func->name, mesh, sphere_normals, ARRAY_SIZE(sphere_normals));
11009 /* Sphere with adjacency data */
11010 hr = clear_normals(mesh);
11011 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr);
11013 hr = func->apply(mesh, ID3DXBuffer_GetBufferPointer(adjacency));
11014 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr);
11016 compare_normals(__LINE__, func->name, mesh, sphere_normals, ARRAY_SIZE(sphere_normals));
11019 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
11020 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_BY_AREA,
11021 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
11022 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr);
11024 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, sphere_normals_area, ARRAY_SIZE(sphere_normals_area));
11026 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
11027 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_BY_AREA,
11028 ID3DXBuffer_GetBufferPointer(adjacency), -1.01f, -0.01f, -1.01f, NULL, NULL);
11029 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr);
11031 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, sphere_normals_area, ARRAY_SIZE(sphere_normals_area));
11033 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
11034 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_EQUAL,
11035 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
11036 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr);
11038 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, sphere_normals_equal, ARRAY_SIZE(sphere_normals_equal));
11040 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
11041 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_EQUAL,
11042 ID3DXBuffer_GetBufferPointer(adjacency), -1.01f, -0.01f, -1.01f, NULL, NULL);
11043 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr);
11045 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, sphere_normals_equal, ARRAY_SIZE(sphere_normals_equal));
11047 refcount = mesh->lpVtbl->Release(mesh);
11048 ok(!refcount, "Mesh has %u references left\n", refcount);
11049 refcount = ID3DXBuffer_Release(adjacency);
11050 ok(!refcount, "Buffer has %u references left\n", refcount);
11052 free_test_context(test_context);
11055 static void D3DXCreateAnimationControllerTest(void)
11057 HRESULT hr;
11058 ID3DXAnimationController *animation;
11059 UINT value;
11061 hr = D3DXCreateAnimationController(0, 0, 0, 0, NULL);
11062 ok(hr == D3D_OK, "Got unexpected hr returned %#x.\n", hr);
11064 animation = (void*)0xdeadbeef;
11065 hr = D3DXCreateAnimationController(0, 1, 1, 1, &animation);
11066 ok(hr == D3D_OK, "Got unexpected hr returned %#x.\n", hr);
11067 ok(animation == (void*)0xdeadbeef, "Got unexpected animation %p.\n", animation);
11069 animation = (void*)0xdeadbeef;
11070 hr = D3DXCreateAnimationController(1, 0, 1, 1, &animation);
11071 ok(hr == D3D_OK, "Got unexpected hr returned %#x.\n", hr);
11072 ok(animation == (void*)0xdeadbeef, "Got unexpected animation %p.\n", animation);
11074 animation = (void*)0xdeadbeef;
11075 hr = D3DXCreateAnimationController(1, 1, 0, 1, &animation);
11076 ok(hr == D3D_OK, "Got unexpected hr returned %#x.\n", hr);
11077 ok(animation == (void*)0xdeadbeef, "Got unexpected animation %p.\n", animation);
11079 animation = (void*)0xdeadbeef;
11080 hr = D3DXCreateAnimationController(1, 1, 1, 0, &animation);
11081 ok(hr == D3D_OK, "Got unexpected hr returned %#x.\n", hr);
11082 ok(animation == (void*)0xdeadbeef, "Got unexpected animation %p.\n", animation);
11084 hr = D3DXCreateAnimationController(1, 1, 1, 1, &animation);
11085 ok(hr == D3D_OK, "Got unexpected hr returned %#x.\n", hr);
11087 value = animation->lpVtbl->GetMaxNumAnimationOutputs(animation);
11088 ok(value == 1, "Got unexpected value %u.\n", value);
11090 value = animation->lpVtbl->GetMaxNumAnimationSets(animation);
11091 ok(value == 1, "Got unexpected value %u.\n", value);
11093 value = animation->lpVtbl->GetMaxNumTracks(animation);
11094 ok(value == 1, "Got unexpected value %u.\n", value);
11096 value = animation->lpVtbl->GetMaxNumEvents(animation);
11097 ok(value == 1, "Got unexpected value %u.\n", value);
11099 animation->lpVtbl->Release(animation);
11101 hr = D3DXCreateAnimationController(100, 101, 102, 103, &animation);
11102 ok(hr == D3D_OK, "Got unexpected hr returned %#x.\n", hr);
11104 value = animation->lpVtbl->GetMaxNumAnimationOutputs(animation);
11105 ok(value == 100, "Got unexpected value %u.\n", value);
11107 value = animation->lpVtbl->GetMaxNumAnimationSets(animation);
11108 ok(value == 101, "Got unexpected value %u.\n", value);
11110 value = animation->lpVtbl->GetMaxNumTracks(animation);
11111 ok(value == 102, "Got unexpected value %u.\n", value);
11113 value = animation->lpVtbl->GetMaxNumEvents(animation);
11114 ok(value == 103, "Got unexpected value %u.\n", value);
11116 animation->lpVtbl->Release(animation);
11119 static void test_D3DXFrameFind(void)
11121 static char n1[] = "name1";
11122 static char n2[] = "name2";
11123 static char n3[] = "name3";
11124 static char n4[] = "name4";
11125 static char n5[] = "name5";
11126 static char n6[] = "name6";
11127 static char N1[] = "Name1";
11128 D3DXFRAME root, sibling, sibling2, child, *ret;
11129 D3DXFRAME child2, child3;
11131 ret = D3DXFrameFind(NULL, NULL);
11132 ok(ret == NULL, "Unexpected frame, %p.\n", ret);
11134 ret = D3DXFrameFind(NULL, "test");
11135 ok(ret == NULL, "Unexpected frame, %p.\n", ret);
11137 memset(&root, 0, sizeof(root));
11139 ret = D3DXFrameFind(&root, NULL);
11140 ok(ret == &root, "Unexpected frame, %p.\n", ret);
11142 root.Name = n1;
11143 ret = D3DXFrameFind(&root, NULL);
11144 ok(ret == NULL, "Unexpected frame, %p.\n", ret);
11146 ret = D3DXFrameFind(&root, n1);
11147 ok(ret == &root, "Unexpected frame, %p.\n", ret);
11149 ret = D3DXFrameFind(&root, N1);
11150 ok(ret == NULL, "Unexpected frame, %p.\n", ret);
11152 /* Test siblings order traversal. */
11153 memset(&sibling, 0, sizeof(sibling));
11154 sibling.Name = n2;
11155 root.pFrameSibling = &sibling;
11156 ret = D3DXFrameFind(&root, n2);
11157 ok(ret == &sibling, "Unexpected frame, %p.\n", ret);
11159 memset(&sibling2, 0, sizeof(sibling2));
11160 sibling2.Name = n2;
11161 sibling.pFrameSibling = &sibling2;
11162 ret = D3DXFrameFind(&root, n2);
11163 ok(ret == &sibling, "Unexpected frame, %p.\n", ret);
11165 sibling2.Name = n3;
11166 ret = D3DXFrameFind(&root, n3);
11167 ok(ret == &sibling2, "Unexpected frame, %p.\n", ret);
11169 /* Siblings first. */
11170 memset(&child, 0, sizeof(child));
11171 child.Name = n2;
11172 root.pFrameFirstChild = &child;
11173 ret = D3DXFrameFind(&root, n2);
11174 ok(ret == &sibling, "Unexpected frame, %p.\n", ret);
11176 child.Name = n4;
11177 ret = D3DXFrameFind(&root, n4);
11178 ok(ret == &child, "Unexpected frame, %p.\n", ret);
11180 /* Link a grandchild and another one for sibling. */
11181 memset(&child2, 0, sizeof(child2));
11182 memset(&child3, 0, sizeof(child3));
11183 child2.Name = child3.Name = n5;
11184 sibling.pFrameFirstChild = &child2;
11185 child.pFrameFirstChild = &child3;
11186 ret = D3DXFrameFind(&root, n5);
11187 ok(ret == &child2, "Unexpected frame, %p.\n", ret);
11189 child3.Name = n6;
11190 ret = D3DXFrameFind(&root, n6);
11191 ok(ret == &child3, "Unexpected frame, %p.\n", ret);
11194 START_TEST(mesh)
11196 D3DXBoundProbeTest();
11197 D3DXComputeBoundingBoxTest();
11198 D3DXComputeBoundingSphereTest();
11199 D3DXGetFVFVertexSizeTest();
11200 D3DXIntersectTriTest();
11201 D3DXCreateMeshTest();
11202 D3DXCreateMeshFVFTest();
11203 D3DXLoadMeshTest();
11204 D3DXCreateBoxTest();
11205 D3DXCreatePolygonTest();
11206 D3DXCreateSphereTest();
11207 D3DXCreateCylinderTest();
11208 D3DXCreateTextTest();
11209 D3DXCreateTorusTest();
11210 D3DXCreateAnimationControllerTest();
11211 test_get_decl_length();
11212 test_get_decl_vertex_size();
11213 test_fvf_decl_conversion();
11214 D3DXGenerateAdjacencyTest();
11215 test_update_semantics();
11216 test_create_skin_info();
11217 test_convert_adjacency_to_point_reps();
11218 test_convert_point_reps_to_adjacency();
11219 test_weld_vertices();
11220 test_clone_mesh();
11221 test_valid_mesh();
11222 test_optimize_faces();
11223 test_compute_normals();
11224 test_D3DXFrameFind();