1 /*
2 * Copyright 2008 David Adam
3 * Copyright 2008 Luis Busquets
4 * Copyright 2009 Henri Verbeet for CodeWeavers
5 * Copyright 2011 Michael Mc Donnell
6 *
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.
11 *
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.
16 *
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
20 */
21
22 #define COBJMACROS
23 #include <stdio.h>
24 #include <float.h>
25 #include <limits.h>
26 #include "wine/test.h"
27 #include "d3dx9.h"
28
29 /* Set the WINETEST_DEBUG environment variable to be greater than 1 for verbose
30 * function call traces of ID3DXAllocateHierarchy callbacks. */
31 #define TRACECALLBACK if(winetest_debug > 1) trace
32
33 #define admitted_error 0.0001f
34
35 #define ARRAY_SIZE(array) (sizeof(array)/sizeof(*array))
36
37 #define compare_vertex_sizes(type, exp) \
38 got=D3DXGetFVFVertexSize(type); \
39 ok(got==exp, "Expected: %d, Got: %d\n", exp, got);
40
41 #define compare_float(got, exp) \
42 do { \
43 float _got = (got); \
44 float _exp = (exp); \
45 ok(_got == _exp, "Expected: %g, Got: %g\n", _exp, _got); \
46 } while (0)
47
48 static BOOL compare(FLOAT u, FLOAT v)
49 {
50 return (fabs(u-v) < admitted_error);
51 }
52
53 static BOOL compare_vec3(D3DXVECTOR3 u, D3DXVECTOR3 v)
54 {
55 return ( compare(u.x, v.x) && compare(u.y, v.y) && compare(u.z, v.z) );
56 }
57
58 #define check_floats(got, exp, dim) check_floats_(__LINE__, "", got, exp, dim)
59 static void check_floats_(int line, const char *prefix, const float *got, const float *exp, int dim)
60 {
61 int i;
62 char exp_buffer[256] = "";
63 char got_buffer[256] = "";
64 char *exp_buffer_ptr = exp_buffer;
65 char *got_buffer_ptr = got_buffer;
66 BOOL equal = TRUE;
67
68 for (i = 0; i < dim; i++) {
69 if (i) {
70 exp_buffer_ptr += sprintf(exp_buffer_ptr, ", ");
71 got_buffer_ptr += sprintf(got_buffer_ptr, ", ");
72 }
73 equal = equal && compare(*exp, *got);
74 exp_buffer_ptr += sprintf(exp_buffer_ptr, "%g", *exp);
75 got_buffer_ptr += sprintf(got_buffer_ptr, "%g", *got);
76 exp++, got++;
77 }
78 ok_(__FILE__,line)(equal, "%sExpected (%s), got (%s)", prefix, exp_buffer, got_buffer);
79 }
80
81 struct vertex
82 {
83 D3DXVECTOR3 position;
84 D3DXVECTOR3 normal;
85 };
86
87 typedef WORD face[3];
88
89 static BOOL compare_face(face a, face b)
90 {
91 return (a[0]==b[0] && a[1] == b[1] && a[2] == b[2]);
92 }
93
94 struct test_context
95 {
96 HWND hwnd;
97 IDirect3D9 *d3d;
98 IDirect3DDevice9 *device;
99 };
100
101 /* Initializes a test context struct. Use it to initialize DirectX.
102 *
103 * Returns NULL if an error occurred.
104 */
105 static struct test_context *new_test_context(void)
106 {
107 HRESULT hr;
108 HWND hwnd = NULL;
109 IDirect3D9 *d3d = NULL;
110 IDirect3DDevice9 *device = NULL;
111 D3DPRESENT_PARAMETERS d3dpp = {0};
112 struct test_context *test_context;
113
114 hwnd = CreateWindow("static", "d3dx9_test", 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL);
115 if (!hwnd)
116 {
117 skip("Couldn't create application window\n");
118 goto error;
119 }
120
121 d3d = Direct3DCreate9(D3D_SDK_VERSION);
122 if (!d3d)
123 {
124 skip("Couldn't create IDirect3D9 object\n");
125 goto error;
126 }
127
128 memset(&d3dpp, 0, sizeof(d3dpp));
129 d3dpp.Windowed = TRUE;
130 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
131 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
132 D3DCREATE_MIXED_VERTEXPROCESSING, &d3dpp, &device);
133 if (FAILED(hr))
134 {
135 skip("Couldn't create IDirect3DDevice9 object %#x\n", hr);
136 goto error;
137 }
138
139 test_context = HeapAlloc(GetProcessHeap(), 0, sizeof(*test_context));
140 if (!test_context)
141 {
142 skip("Couldn't allocate memory for test_context\n");
143 goto error;
144 }
145 test_context->hwnd = hwnd;
146 test_context->d3d = d3d;
147 test_context->device = device;
148
149 return test_context;
150
151 error:
152 if (device)
153 IDirect3DDevice9_Release(device);
154
155 if (d3d)
156 IDirect3D9_Release(d3d);
157
158 if (hwnd)
159 DestroyWindow(hwnd);
160
161 return NULL;
162 }
163
164 static void free_test_context(struct test_context *test_context)
165 {
166 if (!test_context)
167 return;
168
169 if (test_context->device)
170 IDirect3DDevice9_Release(test_context->device);
171
172 if (test_context->d3d)
173 IDirect3D9_Release(test_context->d3d);
174
175 if (test_context->hwnd)
176 DestroyWindow(test_context->hwnd);
177
178 HeapFree(GetProcessHeap(), 0, test_context);
179 }
180
181 struct mesh
182 {
183 DWORD number_of_vertices;
184 struct vertex *vertices;
185
186 DWORD number_of_faces;
187 face *faces;
188
189 DWORD fvf;
190 UINT vertex_size;
191 };
192
193 static void free_mesh(struct mesh *mesh)
194 {
195 HeapFree(GetProcessHeap(), 0, mesh->faces);
196 HeapFree(GetProcessHeap(), 0, mesh->vertices);
197 }
198
199 static BOOL new_mesh(struct mesh *mesh, DWORD number_of_vertices, DWORD number_of_faces)
200 {
201 mesh->vertices = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, number_of_vertices * sizeof(*mesh->vertices));
202 if (!mesh->vertices)
203 {
204 return FALSE;
205 }
206 mesh->number_of_vertices = number_of_vertices;
207
208 mesh->faces = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, number_of_faces * sizeof(*mesh->faces));
209 if (!mesh->faces)
210 {
211 HeapFree(GetProcessHeap(), 0, mesh->vertices);
212 return FALSE;
213 }
214 mesh->number_of_faces = number_of_faces;
215
216 return TRUE;
217 }
218
219 static void compare_mesh(const char *name, ID3DXMesh *d3dxmesh, struct mesh *mesh)
220 {
221 HRESULT hr;
222 DWORD number_of_vertices, number_of_faces;
223 IDirect3DVertexBuffer9 *vertex_buffer;
224 IDirect3DIndexBuffer9 *index_buffer;
225 D3DVERTEXBUFFER_DESC vertex_buffer_description;
226 D3DINDEXBUFFER_DESC index_buffer_description;
227 struct vertex *vertices;
228 face *faces;
229 int expected, i;
230
231 number_of_vertices = d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh);
232 ok(number_of_vertices == mesh->number_of_vertices, "Test %s, result %u, expected %d\n",
233 name, number_of_vertices, mesh->number_of_vertices);
234
235 number_of_faces = d3dxmesh->lpVtbl->GetNumFaces(d3dxmesh);
236 ok(number_of_faces == mesh->number_of_faces, "Test %s, result %u, expected %d\n",
237 name, number_of_faces, mesh->number_of_faces);
238
239 /* vertex buffer */
240 hr = d3dxmesh->lpVtbl->GetVertexBuffer(d3dxmesh, &vertex_buffer);
241 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
242
243 if (hr != D3D_OK)
244 {
245 skip("Couldn't get vertex buffer\n");
246 }
247 else
248 {
249 hr = IDirect3DVertexBuffer9_GetDesc(vertex_buffer, &vertex_buffer_description);
250 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
251
252 if (hr != D3D_OK)
253 {
254 skip("Couldn't get vertex buffer description\n");
255 }
256 else
257 {
258 ok(vertex_buffer_description.Format == D3DFMT_VERTEXDATA, "Test %s, result %x, expected %x (D3DFMT_VERTEXDATA)\n",
259 name, vertex_buffer_description.Format, D3DFMT_VERTEXDATA);
260 ok(vertex_buffer_description.Type == D3DRTYPE_VERTEXBUFFER, "Test %s, result %x, expected %x (D3DRTYPE_VERTEXBUFFER)\n",
261 name, vertex_buffer_description.Type, D3DRTYPE_VERTEXBUFFER);
262 ok(vertex_buffer_description.Usage == 0, "Test %s, result %x, expected %x\n", name, vertex_buffer_description.Usage, 0);
263 ok(vertex_buffer_description.Pool == D3DPOOL_MANAGED, "Test %s, result %x, expected %x (D3DPOOL_MANAGED)\n",
264 name, vertex_buffer_description.Pool, D3DPOOL_MANAGED);
265 ok(vertex_buffer_description.FVF == mesh->fvf, "Test %s, result %x, expected %x\n",
266 name, vertex_buffer_description.FVF, mesh->fvf);
267 if (mesh->fvf == 0)
268 {
269 expected = number_of_vertices * mesh->vertex_size;
270 }
271 else
272 {
273 expected = number_of_vertices * D3DXGetFVFVertexSize(mesh->fvf);
274 }
275 ok(vertex_buffer_description.Size == expected, "Test %s, result %x, expected %x\n",
276 name, vertex_buffer_description.Size, expected);
277 }
278
279 /* specify offset and size to avoid potential overruns */
280 hr = IDirect3DVertexBuffer9_Lock(vertex_buffer, 0, number_of_vertices * sizeof(D3DXVECTOR3) * 2,
281 (LPVOID *)&vertices, D3DLOCK_DISCARD);
282 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
283
284 if (hr != D3D_OK)
285 {
286 skip("Couldn't lock vertex buffer\n");
287 }
288 else
289 {
290 for (i = 0; i < number_of_vertices; i++)
291 {
292 ok(compare_vec3(vertices[i].position, mesh->vertices[i].position),
293 "Test %s, vertex position %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i,
294 vertices[i].position.x, vertices[i].position.y, vertices[i].position.z,
295 mesh->vertices[i].position.x, mesh->vertices[i].position.y, mesh->vertices[i].position.z);
296 ok(compare_vec3(vertices[i].normal, mesh->vertices[i].normal),
297 "Test %s, vertex normal %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i,
298 vertices[i].normal.x, vertices[i].normal.y, vertices[i].normal.z,
299 mesh->vertices[i].normal.x, mesh->vertices[i].normal.y, mesh->vertices[i].normal.z);
300 }
301
302 IDirect3DVertexBuffer9_Unlock(vertex_buffer);
303 }
304
305 IDirect3DVertexBuffer9_Release(vertex_buffer);
306 }
307
308 /* index buffer */
309 hr = d3dxmesh->lpVtbl->GetIndexBuffer(d3dxmesh, &index_buffer);
310 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
311
312 if (!index_buffer)
313 {
314 skip("Couldn't get index buffer\n");
315 }
316 else
317 {
318 hr = IDirect3DIndexBuffer9_GetDesc(index_buffer, &index_buffer_description);
319 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
320
321 if (hr != D3D_OK)
322 {
323 skip("Couldn't get index buffer description\n");
324 }
325 else
326 {
327 ok(index_buffer_description.Format == D3DFMT_INDEX16, "Test %s, result %x, expected %x (D3DFMT_INDEX16)\n",
328 name, index_buffer_description.Format, D3DFMT_INDEX16);
329 ok(index_buffer_description.Type == D3DRTYPE_INDEXBUFFER, "Test %s, result %x, expected %x (D3DRTYPE_INDEXBUFFER)\n",
330 name, index_buffer_description.Type, D3DRTYPE_INDEXBUFFER);
331 ok(index_buffer_description.Usage == 0, "Test %s, result %#x, expected %#x.\n",
332 name, index_buffer_description.Usage, 0);
333 ok(index_buffer_description.Pool == D3DPOOL_MANAGED, "Test %s, result %x, expected %x (D3DPOOL_MANAGED)\n",
334 name, index_buffer_description.Pool, D3DPOOL_MANAGED);
335 expected = number_of_faces * sizeof(WORD) * 3;
336 ok(index_buffer_description.Size == expected, "Test %s, result %x, expected %x\n",
337 name, index_buffer_description.Size, expected);
338 }
339
340 /* specify offset and size to avoid potential overruns */
341 hr = IDirect3DIndexBuffer9_Lock(index_buffer, 0, number_of_faces * sizeof(WORD) * 3,
342 (LPVOID *)&faces, D3DLOCK_DISCARD);
343 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
344
345 if (hr != D3D_OK)
346 {
347 skip("Couldn't lock index buffer\n");
348 }
349 else
350 {
351 for (i = 0; i < number_of_faces; i++)
352 {
353 ok(compare_face(faces[i], mesh->faces[i]),
354 "Test %s, face %d, result (%u, %u, %u), expected (%u, %u, %u)\n", name, i,
355 faces[i][0], faces[i][1], faces[i][2],
356 mesh->faces[i][0], mesh->faces[i][1], mesh->faces[i][2]);
357 }
358
359 IDirect3DIndexBuffer9_Unlock(index_buffer);
360 }
361
362 IDirect3DIndexBuffer9_Release(index_buffer);
363 }
364 }
365
366 static void D3DXBoundProbeTest(void)
367 {
368 BOOL result;
369 D3DXVECTOR3 bottom_point, center, top_point, raydirection, rayposition;
370 FLOAT radius;
371
372 /*____________Test the Box case___________________________*/
373 bottom_point.x = -3.0f; bottom_point.y = -2.0f; bottom_point.z = -1.0f;
374 top_point.x = 7.0f; top_point.y = 8.0f; top_point.z = 9.0f;
375
376 raydirection.x = -4.0f; raydirection.y = -5.0f; raydirection.z = -6.0f;
377 rayposition.x = 5.0f; rayposition.y = 5.0f; rayposition.z = 11.0f;
378 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection);
379 ok(result == TRUE, "expected TRUE, received FALSE\n");
380
381 raydirection.x = 4.0f; raydirection.y = 5.0f; raydirection.z = 6.0f;
382 rayposition.x = 5.0f; rayposition.y = 5.0f; rayposition.z = 11.0f;
383 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection);
384 ok(result == FALSE, "expected FALSE, received TRUE\n");
385
386 rayposition.x = -4.0f; rayposition.y = 1.0f; rayposition.z = -2.0f;
387 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection);
388 ok(result == TRUE, "expected TRUE, received FALSE\n");
389
390 bottom_point.x = 1.0f; bottom_point.y = 0.0f; bottom_point.z = 0.0f;
391 top_point.x = 1.0f; top_point.y = 0.0f; top_point.z = 0.0f;
392 rayposition.x = 0.0f; rayposition.y = 1.0f; rayposition.z = 0.0f;
393 raydirection.x = 0.0f; raydirection.y = 3.0f; raydirection.z = 0.0f;
394 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection);
395 ok(result == FALSE, "expected FALSE, received TRUE\n");
396
397 bottom_point.x = 1.0f; bottom_point.y = 2.0f; bottom_point.z = 3.0f;
398 top_point.x = 10.0f; top_point.y = 15.0f; top_point.z = 20.0f;
399
400 raydirection.x = 7.0f; raydirection.y = 8.0f; raydirection.z = 9.0f;
401 rayposition.x = 3.0f; rayposition.y = 7.0f; rayposition.z = -6.0f;
402 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection);
403 ok(result == TRUE, "expected TRUE, received FALSE\n");
404
405 bottom_point.x = 0.0f; bottom_point.y = 0.0f; bottom_point.z = 0.0f;
406 top_point.x = 1.0f; top_point.y = 1.0f; top_point.z = 1.0f;
407
408 raydirection.x = 0.0f; raydirection.y = 1.0f; raydirection.z = .0f;
409 rayposition.x = -3.0f; rayposition.y = 0.0f; rayposition.z = 0.0f;
410 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection);
411 ok(result == FALSE, "expected FALSE, received TRUE\n");
412
413 raydirection.x = 1.0f; raydirection.y = 0.0f; raydirection.z = .0f;
414 rayposition.x = -3.0f; rayposition.y = 0.0f; rayposition.z = 0.0f;
415 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection);
416 ok(result == TRUE, "expected TRUE, received FALSE\n");
417
418 /*____________Test the Sphere case________________________*/
419 radius = sqrt(77.0f);
420 center.x = 1.0f; center.y = 2.0f; center.z = 3.0f;
421 raydirection.x = 2.0f; raydirection.y = -4.0f; raydirection.z = 2.0f;
422
423 rayposition.x = 5.0f; rayposition.y = 5.0f; rayposition.z = 9.0f;
424 result = D3DXSphereBoundProbe(¢er, radius, &rayposition, &raydirection);
425 ok(result == TRUE, "expected TRUE, received FALSE\n");
426
427 rayposition.x = 45.0f; rayposition.y = -75.0f; rayposition.z = 49.0f;
428 result = D3DXSphereBoundProbe(¢er, radius, &rayposition, &raydirection);
429 ok(result == FALSE, "expected FALSE, received TRUE\n");
430
431 rayposition.x = 5.0f; rayposition.y = 11.0f; rayposition.z = 9.0f;
432 result = D3DXSphereBoundProbe(¢er, radius, &rayposition, &raydirection);
433 ok(result == FALSE, "expected FALSE, received TRUE\n");
434 }
435
436 static void D3DXComputeBoundingBoxTest(void)
437 {
438 D3DXVECTOR3 exp_max, exp_min, got_max, got_min, vertex[5];
439 HRESULT hr;
440
441 vertex[0].x = 1.0f; vertex[0].y = 1.0f; vertex[0].z = 1.0f;
442 vertex[1].x = 1.0f; vertex[1].y = 1.0f; vertex[1].z = 1.0f;
443 vertex[2].x = 1.0f; vertex[2].y = 1.0f; vertex[2].z = 1.0f;
444 vertex[3].x = 1.0f; vertex[3].y = 1.0f; vertex[3].z = 1.0f;
445 vertex[4].x = 9.0f; vertex[4].y = 9.0f; vertex[4].z = 9.0f;
446
447 exp_min.x = 1.0f; exp_min.y = 1.0f; exp_min.z = 1.0f;
448 exp_max.x = 9.0f; exp_max.y = 9.0f; exp_max.z = 9.0f;
449
450 hr = D3DXComputeBoundingBox(&vertex[3],2,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_min,&got_max);
451
452 ok( hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
453 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);
454 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);
455
456 /*________________________*/
457
458 vertex[0].x = 2.0f; vertex[0].y = 5.9f; vertex[0].z = -1.2f;
459 vertex[1].x = -1.87f; vertex[1].y = 7.9f; vertex[1].z = 7.4f;
460 vertex[2].x = 7.43f; vertex[2].y = -0.9f; vertex[2].z = 11.9f;
461 vertex[3].x = -6.92f; vertex[3].y = 6.3f; vertex[3].z = -3.8f;
462 vertex[4].x = 11.4f; vertex[4].y = -8.1f; vertex[4].z = 4.5f;
463
464 exp_min.x = -6.92f; exp_min.y = -8.1f; exp_min.z = -3.80f;
465 exp_max.x = 11.4f; exp_max.y = 7.90f; exp_max.z = 11.9f;
466
467 hr = D3DXComputeBoundingBox(&vertex[0],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_min,&got_max);
468
469 ok( hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
470 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);
471 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);
472
473 /*________________________*/
474
475 vertex[0].x = 2.0f; vertex[0].y = 5.9f; vertex[0].z = -1.2f;
476 vertex[1].x = -1.87f; vertex[1].y = 7.9f; vertex[1].z = 7.4f;
477 vertex[2].x = 7.43f; vertex[2].y = -0.9f; vertex[2].z = 11.9f;
478 vertex[3].x = -6.92f; vertex[3].y = 6.3f; vertex[3].z = -3.8f;
479 vertex[4].x = 11.4f; vertex[4].y = -8.1f; vertex[4].z = 4.5f;
480
481 exp_min.x = -6.92f; exp_min.y = -0.9f; exp_min.z = -3.8f;
482 exp_max.x = 7.43f; exp_max.y = 7.90f; exp_max.z = 11.9f;
483
484 hr = D3DXComputeBoundingBox(&vertex[0],4,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_min,&got_max);
485
486 ok( hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
487 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);
488 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);
489
490 /*________________________*/
491 hr = D3DXComputeBoundingBox(NULL,5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_min,&got_max);
492 ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
493
494 /*________________________*/
495 hr = D3DXComputeBoundingBox(&vertex[3],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),NULL,&got_max);
496 ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
497
498 /*________________________*/
499 hr = D3DXComputeBoundingBox(&vertex[3],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_min,NULL);
500 ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
501 }
502
503 static void D3DXComputeBoundingSphereTest(void)
504 {
505 D3DXVECTOR3 exp_cen, got_cen, vertex[5];
506 FLOAT exp_rad, got_rad;
507 HRESULT hr;
508
509 vertex[0].x = 1.0f; vertex[0].y = 1.0f; vertex[0].z = 1.0f;
510 vertex[1].x = 1.0f; vertex[1].y = 1.0f; vertex[1].z = 1.0f;
511 vertex[2].x = 1.0f; vertex[2].y = 1.0f; vertex[2].z = 1.0f;
512 vertex[3].x = 1.0f; vertex[3].y = 1.0f; vertex[3].z = 1.0f;
513 vertex[4].x = 9.0f; vertex[4].y = 9.0f; vertex[4].z = 9.0f;
514
515 exp_rad = 6.928203f;
516 exp_cen.x = 5.0; exp_cen.y = 5.0; exp_cen.z = 5.0;
517
518 hr = D3DXComputeBoundingSphere(&vertex[3],2,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_cen,&got_rad);
519
520 ok( hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
521 ok( compare(exp_rad, got_rad), "Expected radius: %f, got radius: %f\n", exp_rad, got_rad);
522 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);
523
524 /*________________________*/
525
526 vertex[0].x = 2.0f; vertex[0].y = 5.9f; vertex[0].z = -1.2f;
527 vertex[1].x = -1.87f; vertex[1].y = 7.9f; vertex[1].z = 7.4f;
528 vertex[2].x = 7.43f; vertex[2].y = -0.9f; vertex[2].z = 11.9f;
529 vertex[3].x = -6.92f; vertex[3].y = 6.3f; vertex[3].z = -3.8f;
530 vertex[4].x = 11.4f; vertex[4].y = -8.1f; vertex[4].z = 4.5f;
531
532 exp_rad = 13.707883f;
533 exp_cen.x = 2.408f; exp_cen.y = 2.22f; exp_cen.z = 3.76f;
534
535 hr = D3DXComputeBoundingSphere(&vertex[0],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_cen,&got_rad);
536
537 ok( hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
538 ok( compare(exp_rad, got_rad), "Expected radius: %f, got radius: %f\n", exp_rad, got_rad);
539 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);
540
541 /*________________________*/
542 hr = D3DXComputeBoundingSphere(NULL,5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_cen,&got_rad);
543 ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
544
545 /*________________________*/
546 hr = D3DXComputeBoundingSphere(&vertex[3],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),NULL,&got_rad);
547 ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
548
549 /*________________________*/
550 hr = D3DXComputeBoundingSphere(&vertex[3],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_cen,NULL);
551 ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
552 }
553
554 static void print_elements(const D3DVERTEXELEMENT9 *elements)
555 {
556 D3DVERTEXELEMENT9 last = D3DDECL_END();
557 const D3DVERTEXELEMENT9 *ptr = elements;
558 int count = 0;
559
560 while (memcmp(ptr, &last, sizeof(D3DVERTEXELEMENT9)))
561 {
562 trace(
563 "[Element %d] Stream = %d, Offset = %d, Type = %d, Method = %d, Usage = %d, UsageIndex = %d\n",
564 count, ptr->Stream, ptr->Offset, ptr->Type, ptr->Method, ptr->Usage, ptr->UsageIndex);
565 ptr++;
566 count++;
567 }
568 }
569
570 static void compare_elements(const D3DVERTEXELEMENT9 *elements, const D3DVERTEXELEMENT9 *expected_elements,
571 unsigned int line, unsigned int test_id)
572 {
573 D3DVERTEXELEMENT9 last = D3DDECL_END();
574 unsigned int i;
575
576 for (i = 0; i < MAX_FVF_DECL_SIZE; i++)
577 {
578 int end1 = memcmp(&elements[i], &last, sizeof(last));
579 int end2 = memcmp(&expected_elements[i], &last, sizeof(last));
580 int status;
581
582 if (!end1 && !end2) break;
583
584 status = !end1 ^ !end2;
585 ok(!status, "Line %u, test %u: Mismatch in size, test declaration is %s than expected.\n",
586 line, test_id, end1 ? "shorter" : "longer");
587 if (status)
588 {
589 print_elements(elements);
590 break;
591 }
592
593 status = memcmp(&elements[i], &expected_elements[i], sizeof(D3DVERTEXELEMENT9));
594 ok(!status, "Line %u, test %u: Mismatch in element %u.\n", line, test_id, i);
595 if (status)
596 {
597 print_elements(elements);
598 break;
599 }
600 }
601 }
602
603 static void test_fvf_to_decl(DWORD test_fvf, const D3DVERTEXELEMENT9 expected_elements[],
604 HRESULT expected_hr, unsigned int line, unsigned int test_id)
605 {
606 HRESULT hr;
607 D3DVERTEXELEMENT9 decl[MAX_FVF_DECL_SIZE];
608
609 hr = D3DXDeclaratorFromFVF(test_fvf, decl);
610 ok(hr == expected_hr,
611 "Line %u, test %u: D3DXDeclaratorFromFVF returned %#x, expected %#x.\n",
612 line, test_id, hr, expected_hr);
613 if (SUCCEEDED(hr)) compare_elements(decl, expected_elements, line, test_id);
614 }
615
616 static void test_decl_to_fvf(const D3DVERTEXELEMENT9 *decl, DWORD expected_fvf,
617 HRESULT expected_hr, unsigned int line, unsigned int test_id)
618 {
619 HRESULT hr;
620 DWORD result_fvf = 0xdeadbeef;
621
622 hr = D3DXFVFFromDeclarator(decl, &result_fvf);
623 ok(hr == expected_hr,
624 "Line %u, test %u: D3DXFVFFromDeclarator returned %#x, expected %#x.\n",
625 line, test_id, hr, expected_hr);
626 if (SUCCEEDED(hr))
627 {
628 ok(expected_fvf == result_fvf, "Line %u, test %u: Got FVF %#x, expected %#x.\n",
629 line, test_id, result_fvf, expected_fvf);
630 }
631 }
632
633 static void test_fvf_decl_conversion(void)
634 {
635 static const struct
636 {
637 D3DVERTEXELEMENT9 decl[MAXD3DDECLLENGTH + 1];
638 DWORD fvf;
639 }
640 test_data[] =
641 {
642 {{
643 D3DDECL_END(),
644 }, 0},
645 {{
646 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
647 D3DDECL_END(),
648 }, D3DFVF_XYZ},
649 {{
650 {0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITIONT, 0},
651 D3DDECL_END(),
652 }, D3DFVF_XYZRHW},
653 {{
654 {0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITIONT, 0},
655 D3DDECL_END(),
656 }, D3DFVF_XYZRHW},
657 {{
658 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
659 {0, 12, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
660 D3DDECL_END(),
661 }, D3DFVF_XYZB1},
662 {{
663 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
664 {0, 12, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
665 D3DDECL_END(),
666 }, D3DFVF_XYZB1 | D3DFVF_LASTBETA_UBYTE4},
667 {{
668 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
669 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
670 D3DDECL_END(),
671 }, D3DFVF_XYZB1 | D3DFVF_LASTBETA_D3DCOLOR},
672 {{
673 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
674 {0, 12, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
675 D3DDECL_END(),
676 }, D3DFVF_XYZB2},
677 {{
678 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
679 {0, 12, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
680 {0, 16, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
681 D3DDECL_END(),
682 }, D3DFVF_XYZB2 | D3DFVF_LASTBETA_UBYTE4},
683 {{
684 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
685 {0, 12, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
686 {0, 16, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
687 D3DDECL_END(),
688 }, D3DFVF_XYZB2 | D3DFVF_LASTBETA_D3DCOLOR},
689 {{
690 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
691 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
692 D3DDECL_END(),
693 }, D3DFVF_XYZB3},
694 {{
695 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
696 {0, 12, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
697 {0, 20, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
698 D3DDECL_END(),
699 }, D3DFVF_XYZB3 | D3DFVF_LASTBETA_UBYTE4},
700 {{
701 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
702 {0, 12, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
703 {0, 20, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
704 D3DDECL_END(),
705 }, D3DFVF_XYZB3 | D3DFVF_LASTBETA_D3DCOLOR},
706 {{
707 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
708 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
709 D3DDECL_END(),
710 }, D3DFVF_XYZB4},
711 {{
712 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
713 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
714 {0, 24, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
715 D3DDECL_END(),
716 }, D3DFVF_XYZB4 | D3DFVF_LASTBETA_UBYTE4},
717 {{
718 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
719 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
720 {0, 24, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
721 D3DDECL_END(),
722 }, D3DFVF_XYZB4 | D3DFVF_LASTBETA_D3DCOLOR},
723 {{
724 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
725 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
726 {0, 28, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
727 D3DDECL_END(),
728 }, D3DFVF_XYZB5 | D3DFVF_LASTBETA_UBYTE4},
729 {{
730 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
731 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
732 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
733 D3DDECL_END(),
734 }, D3DFVF_XYZB5 | D3DFVF_LASTBETA_D3DCOLOR},
735 {{
736 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
737 D3DDECL_END(),
738 }, D3DFVF_NORMAL},
739 {{
740 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
741 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
742 D3DDECL_END(),
743 }, D3DFVF_NORMAL | D3DFVF_DIFFUSE},
744 {{
745 {0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_PSIZE, 0},
746 D3DDECL_END(),
747 }, D3DFVF_PSIZE},
748 {{
749 {0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
750 D3DDECL_END(),
751 }, D3DFVF_DIFFUSE},
752 {{
753 {0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1},
754 D3DDECL_END(),
755 }, D3DFVF_SPECULAR},
756 /* Make sure textures of different sizes work. */
757 {{
758 {0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
759 D3DDECL_END(),
760 }, D3DFVF_TEXCOORDSIZE1(0) | D3DFVF_TEX1},
761 {{
762 {0, 0, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 0},
763 D3DDECL_END(),
764 }, D3DFVF_TEXCOORDSIZE2(0) | D3DFVF_TEX1},
765 {{
766 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 0},
767 D3DDECL_END(),
768 }, D3DFVF_TEXCOORDSIZE3(0) | D3DFVF_TEX1},
769 {{
770 {0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 0},
771 D3DDECL_END(),
772 }, D3DFVF_TEXCOORDSIZE4(0) | D3DFVF_TEX1},
773 /* Make sure the TEXCOORD index works correctly - try several textures. */
774 {{
775 {0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
776 {0, 4, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 1},
777 {0, 16, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 2},
778 {0, 24, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 3},
779 D3DDECL_END(),
780 }, D3DFVF_TEX4 | D3DFVF_TEXCOORDSIZE1(0) | D3DFVF_TEXCOORDSIZE3(1)
781 | D3DFVF_TEXCOORDSIZE2(2) | D3DFVF_TEXCOORDSIZE4(3)},
782 /* Now try some combination tests. */
783 {{
784 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
785 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
786 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
787 {0, 32, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1},
788 {0, 36, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 0},
789 {0, 44, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 1},
790 D3DDECL_END(),
791 }, D3DFVF_XYZB4 | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_TEX2
792 | D3DFVF_TEXCOORDSIZE2(0) | D3DFVF_TEXCOORDSIZE3(1)},
793 {{
794 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
795 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
796 {0, 24, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_PSIZE, 0},
797 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1},
798 {0, 32, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
799 {0, 36, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 1},
800 D3DDECL_END(),
801 }, D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_PSIZE | D3DFVF_SPECULAR | D3DFVF_TEX2
802 | D3DFVF_TEXCOORDSIZE1(0) | D3DFVF_TEXCOORDSIZE4(1)},
803 };
804 unsigned int i;
805
806 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
807 {
808 test_decl_to_fvf(test_data[i].decl, test_data[i].fvf, D3D_OK, __LINE__, i);
809 test_fvf_to_decl(test_data[i].fvf, test_data[i].decl, D3D_OK, __LINE__, i);
810 }
811
812 /* Usage indices for position and normal are apparently ignored. */
813 {
814 const D3DVERTEXELEMENT9 decl[] =
815 {
816 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 1},
817 D3DDECL_END(),
818 };
819 test_decl_to_fvf(decl, D3DFVF_XYZ, D3D_OK, __LINE__, 0);
820 }
821 {
822 const D3DVERTEXELEMENT9 decl[] =
823 {
824 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 1},
825 D3DDECL_END(),
826 };
827 test_decl_to_fvf(decl, D3DFVF_NORMAL, D3D_OK, __LINE__, 0);
828 }
829 /* D3DFVF_LASTBETA_UBYTE4 and D3DFVF_LASTBETA_D3DCOLOR are ignored if
830 * there are no blend matrices. */
831 {
832 const D3DVERTEXELEMENT9 decl[] =
833 {
834 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
835 D3DDECL_END(),
836 };
837 test_fvf_to_decl(D3DFVF_XYZ | D3DFVF_LASTBETA_UBYTE4, decl, D3D_OK, __LINE__, 0);
838 }
839 {
840 const D3DVERTEXELEMENT9 decl[] =
841 {
842 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
843 D3DDECL_END(),
844 };
845 test_fvf_to_decl(D3DFVF_XYZ | D3DFVF_LASTBETA_D3DCOLOR, decl, D3D_OK, __LINE__, 0);
846 }
847 /* D3DFVF_LASTBETA_UBYTE4 takes precedence over D3DFVF_LASTBETA_D3DCOLOR. */
848 {
849 const D3DVERTEXELEMENT9 decl[] =
850 {
851 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
852 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
853 {0, 28, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
854 D3DDECL_END(),
855 };
856 test_fvf_to_decl(D3DFVF_XYZB5 | D3DFVF_LASTBETA_D3DCOLOR | D3DFVF_LASTBETA_UBYTE4,
857 decl, D3D_OK, __LINE__, 0);
858 }
859 /* These are supposed to fail, both ways. */
860 {
861 const D3DVERTEXELEMENT9 decl[] =
862 {
863 {0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITION, 0},
864 D3DDECL_END(),
865 };
866 test_decl_to_fvf(decl, D3DFVF_XYZW, D3DERR_INVALIDCALL, __LINE__, 0);
867 test_fvf_to_decl(D3DFVF_XYZW, decl, D3DERR_INVALIDCALL, __LINE__, 0);
868 }
869 {
870 const D3DVERTEXELEMENT9 decl[] =
871 {
872 {0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITION, 0},
873 {0, 16, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
874 D3DDECL_END(),
875 };
876 test_decl_to_fvf(decl, D3DFVF_XYZW | D3DFVF_NORMAL, D3DERR_INVALIDCALL, __LINE__, 0);
877 test_fvf_to_decl(D3DFVF_XYZW | D3DFVF_NORMAL, decl, D3DERR_INVALIDCALL, __LINE__, 0);
878 }
879 {
880 const D3DVERTEXELEMENT9 decl[] =
881 {
882 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
883 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
884 {0, 28, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDINDICES, 0},
885 D3DDECL_END(),
886 };
887 test_decl_to_fvf(decl, D3DFVF_XYZB5, D3DERR_INVALIDCALL, __LINE__, 0);
888 test_fvf_to_decl(D3DFVF_XYZB5, decl, D3DERR_INVALIDCALL, __LINE__, 0);
889 }
890 /* Test a declaration that can't be converted to an FVF. */
891 {
892 const D3DVERTEXELEMENT9 decl[] =
893 {
894 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
895 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
896 {0, 24, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_PSIZE, 0},
897 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1},
898 {0, 32, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
899 /* 8 bytes padding */
900 {0, 44, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 1},
901 D3DDECL_END(),
902 };
903 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0);
904 }
905 /* Elements must be ordered by offset. */
906 {
907 const D3DVERTEXELEMENT9 decl[] =
908 {
909 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
910 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
911 D3DDECL_END(),
912 };
913 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0);
914 }
915 /* Basic tests for element order. */
916 {
917 const D3DVERTEXELEMENT9 decl[] =
918 {
919 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
920 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
921 {0, 16, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
922 D3DDECL_END(),
923 };
924 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0);
925 }
926 {
927 const D3DVERTEXELEMENT9 decl[] =
928 {
929 {0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
930 {0, 4, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
931 D3DDECL_END(),
932 };
933 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0);
934 }
935 {
936 const D3DVERTEXELEMENT9 decl[] =
937 {
938 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
939 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
940 D3DDECL_END(),
941 };
942 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0);
943 }
944 /* Textures must be ordered by texcoords. */
945 {
946 const D3DVERTEXELEMENT9 decl[] =
947 {
948 {0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
949 {0, 4, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 2},
950 {0, 16, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 1},
951 {0, 24, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 3},
952 D3DDECL_END(),
953 };
954 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0);
955 }
956 /* Duplicate elements are not allowed. */
957 {
958 const D3DVERTEXELEMENT9 decl[] =
959 {
960 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
961 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
962 {0, 16, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
963 D3DDECL_END(),
964 };
965 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0);
966 }
967 /* Invalid FVFs cannot be converted to a declarator. */
968 test_fvf_to_decl(0xdeadbeef, NULL, D3DERR_INVALIDCALL, __LINE__, 0);
969 }
970
971 static void D3DXGetFVFVertexSizeTest(void)
972 {
973 UINT got;
974
975 compare_vertex_sizes (D3DFVF_XYZ, 12);
976
977 compare_vertex_sizes (D3DFVF_XYZB3, 24);
978
979 compare_vertex_sizes (D3DFVF_XYZB5, 32);
980
981 compare_vertex_sizes (D3DFVF_XYZ | D3DFVF_NORMAL, 24);
982
983 compare_vertex_sizes (D3DFVF_XYZ | D3DFVF_DIFFUSE, 16);
984
985 compare_vertex_sizes (
986 D3DFVF_XYZ |
987 D3DFVF_TEX1 |
988 D3DFVF_TEXCOORDSIZE1(0), 16);
989 compare_vertex_sizes (
990 D3DFVF_XYZ |
991 D3DFVF_TEX2 |
992 D3DFVF_TEXCOORDSIZE1(0) |
993 D3DFVF_TEXCOORDSIZE1(1), 20);
994
995 compare_vertex_sizes (
996 D3DFVF_XYZ |
997 D3DFVF_TEX1 |
998 D3DFVF_TEXCOORDSIZE2(0), 20);
999
1000 compare_vertex_sizes (
1001 D3DFVF_XYZ |
1002 D3DFVF_TEX2 |
1003 D3DFVF_TEXCOORDSIZE2(0) |
1004 D3DFVF_TEXCOORDSIZE2(1), 28);
1005
1006 compare_vertex_sizes (
1007 D3DFVF_XYZ |
1008 D3DFVF_TEX6 |
1009 D3DFVF_TEXCOORDSIZE2(0) |
1010 D3DFVF_TEXCOORDSIZE2(1) |
1011 D3DFVF_TEXCOORDSIZE2(2) |
1012 D3DFVF_TEXCOORDSIZE2(3) |
1013 D3DFVF_TEXCOORDSIZE2(4) |
1014 D3DFVF_TEXCOORDSIZE2(5), 60);
1015
1016 compare_vertex_sizes (
1017 D3DFVF_XYZ |
1018 D3DFVF_TEX8 |
1019 D3DFVF_TEXCOORDSIZE2(0) |
1020 D3DFVF_TEXCOORDSIZE2(1) |
1021 D3DFVF_TEXCOORDSIZE2(2) |
1022 D3DFVF_TEXCOORDSIZE2(3) |
1023 D3DFVF_TEXCOORDSIZE2(4) |
1024 D3DFVF_TEXCOORDSIZE2(5) |
1025 D3DFVF_TEXCOORDSIZE2(6) |
1026 D3DFVF_TEXCOORDSIZE2(7), 76);
1027
1028 compare_vertex_sizes (
1029 D3DFVF_XYZ |
1030 D3DFVF_TEX1 |
1031 D3DFVF_TEXCOORDSIZE3(0), 24);
1032
1033 compare_vertex_sizes (
1034 D3DFVF_XYZ |
1035 D3DFVF_TEX4 |
1036 D3DFVF_TEXCOORDSIZE3(0) |
1037 D3DFVF_TEXCOORDSIZE3(1) |
1038 D3DFVF_TEXCOORDSIZE3(2) |
1039 D3DFVF_TEXCOORDSIZE3(3), 60);
1040
1041 compare_vertex_sizes (
1042 D3DFVF_XYZ |
1043 D3DFVF_TEX1 |
1044 D3DFVF_TEXCOORDSIZE4(0), 28);
1045
1046 compare_vertex_sizes (
1047 D3DFVF_XYZ |
1048 D3DFVF_TEX2 |
1049 D3DFVF_TEXCOORDSIZE4(0) |
1050 D3DFVF_TEXCOORDSIZE4(1), 44);
1051
1052 compare_vertex_sizes (
1053 D3DFVF_XYZ |
1054 D3DFVF_TEX3 |
1055 D3DFVF_TEXCOORDSIZE4(0) |
1056 D3DFVF_TEXCOORDSIZE4(1) |
1057 D3DFVF_TEXCOORDSIZE4(2), 60);
1058
1059 compare_vertex_sizes (
1060 D3DFVF_XYZB5 |
1061 D3DFVF_NORMAL |
1062 D3DFVF_DIFFUSE |
1063 D3DFVF_SPECULAR |
1064 D3DFVF_TEX8 |
1065 D3DFVF_TEXCOORDSIZE4(0) |
1066 D3DFVF_TEXCOORDSIZE4(1) |
1067 D3DFVF_TEXCOORDSIZE4(2) |
1068 D3DFVF_TEXCOORDSIZE4(3) |
1069 D3DFVF_TEXCOORDSIZE4(4) |
1070 D3DFVF_TEXCOORDSIZE4(5) |
1071 D3DFVF_TEXCOORDSIZE4(6) |
1072 D3DFVF_TEXCOORDSIZE4(7), 180);
1073 }
1074
1075 static void D3DXIntersectTriTest(void)
1076 {
1077 BOOL exp_res, got_res;
1078 D3DXVECTOR3 position, ray, vertex[3];
1079 FLOAT exp_dist, got_dist, exp_u, got_u, exp_v, got_v;
1080
1081 vertex[0].x = 1.0f; vertex[0].y = 0.0f; vertex[0].z = 0.0f;
1082 vertex[1].x = 2.0f; vertex[1].y = 0.0f; vertex[1].z = 0.0f;
1083 vertex[2].x = 1.0f; vertex[2].y = 1.0f; vertex[2].z = 0.0f;
1084
1085 position.x = -14.5f; position.y = -23.75f; position.z = -32.0f;
1086
1087 ray.x = 2.0f; ray.y = 3.0f; ray.z = 4.0f;
1088
1089 exp_res = TRUE; exp_u = 0.5f; exp_v = 0.25f; exp_dist = 8.0f;
1090
1091 got_res = D3DXIntersectTri(&vertex[0],&vertex[1],&vertex[2],&position,&ray,&got_u,&got_v,&got_dist);
1092 ok( got_res == exp_res, "Expected result = %d, got %d\n",exp_res,got_res);
1093 ok( compare(exp_u,got_u), "Expected u = %f, got %f\n",exp_u,got_u);
1094 ok( compare(exp_v,got_v), "Expected v = %f, got %f\n",exp_v,got_v);
1095 ok( compare(exp_dist,got_dist), "Expected distance = %f, got %f\n",exp_dist,got_dist);
1096
1097 /*Only positive ray is taken in account*/
1098
1099 vertex[0].x = 1.0f; vertex[0].y = 0.0f; vertex[0].z = 0.0f;
1100 vertex[1].x = 2.0f; vertex[1].y = 0.0f; vertex[1].z = 0.0f;
1101 vertex[2].x = 1.0f; vertex[2].y = 1.0f; vertex[2].z = 0.0f;
1102
1103 position.x = 17.5f; position.y = 24.25f; position.z = 32.0f;
1104
1105 ray.x = 2.0f; ray.y = 3.0f; ray.z = 4.0f;
1106
1107 exp_res = FALSE;
1108
1109 got_res = D3DXIntersectTri(&vertex[0],&vertex[1],&vertex[2],&position,&ray,&got_u,&got_v,&got_dist);
1110 ok( got_res == exp_res, "Expected result = %d, got %d\n",exp_res,got_res);
1111
1112 /*Intersection between ray and triangle in a same plane is considered as empty*/
1113
1114 vertex[0].x = 4.0f; vertex[0].y = 0.0f; vertex[0].z = 0.0f;
1115 vertex[1].x = 6.0f; vertex[1].y = 0.0f; vertex[1].z = 0.0f;
1116 vertex[2].x = 4.0f; vertex[2].y = 2.0f; vertex[2].z = 0.0f;
1117
1118 position.x = 1.0f; position.y = 1.0f; position.z = 0.0f;
1119
1120 ray.x = 1.0f; ray.y = 0.0f; ray.z = 0.0f;
1121
1122 exp_res = FALSE;
1123
1124 got_res = D3DXIntersectTri(&vertex[0],&vertex[1],&vertex[2],&position,&ray,&got_u,&got_v,&got_dist);
1125 ok( got_res == exp_res, "Expected result = %d, got %d\n",exp_res,got_res);
1126 }
1127
1128 static void D3DXCreateMeshTest(void)
1129 {
1130 HRESULT hr;
1131 HWND wnd;
1132 IDirect3D9 *d3d;
1133 IDirect3DDevice9 *device, *test_device;
1134 D3DPRESENT_PARAMETERS d3dpp;
1135 ID3DXMesh *d3dxmesh;
1136 int i, size;
1137 D3DVERTEXELEMENT9 test_decl[MAX_FVF_DECL_SIZE];
1138 DWORD options;
1139 struct mesh mesh;
1140
1141 static const D3DVERTEXELEMENT9 decl1[3] = {
1142 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1143 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
1144 D3DDECL_END(), };
1145
1146 static const D3DVERTEXELEMENT9 decl2[] = {
1147 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1148 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
1149 {0, 24, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_PSIZE, 0},
1150 {0, 28, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 1},
1151 {0, 32, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
1152 /* 8 bytes padding */
1153 {0, 44, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
1154 D3DDECL_END(),
1155 };
1156
1157 static const D3DVERTEXELEMENT9 decl3[] = {
1158 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1159 {1, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
1160 D3DDECL_END(),
1161 };
1162
1163 hr = D3DXCreateMesh(0, 0, 0, NULL, NULL, NULL);
1164 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1165
1166 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl1, NULL, &d3dxmesh);
1167 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1168
1169 wnd = CreateWindow("static", "d3dx9_test", 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL);
1170 if (!wnd)
1171 {
1172 skip("Couldn't create application window\n");
1173 return;
1174 }
1175 d3d = Direct3DCreate9(D3D_SDK_VERSION);
1176 if (!d3d)
1177 {
1178 skip("Couldn't create IDirect3D9 object\n");
1179 DestroyWindow(wnd);
1180 return;
1181 }
1182
1183 ZeroMemory(&d3dpp, sizeof(d3dpp));
1184 d3dpp.Windowed = TRUE;
1185 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1186 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, wnd, D3DCREATE_MIXED_VERTEXPROCESSING, &d3dpp, &device);
1187 if (FAILED(hr))
1188 {
1189 skip("Failed to create IDirect3DDevice9 object %#x\n", hr);
1190 IDirect3D9_Release(d3d);
1191 DestroyWindow(wnd);
1192 return;
1193 }
1194
1195 hr = D3DXCreateMesh(0, 3, D3DXMESH_MANAGED, decl1, device, &d3dxmesh);
1196 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1197
1198 hr = D3DXCreateMesh(1, 0, D3DXMESH_MANAGED, decl1, device, &d3dxmesh);
1199 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1200
1201 hr = D3DXCreateMesh(1, 3, 0, decl1, device, &d3dxmesh);
1202 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
1203
1204 if (hr == D3D_OK)
1205 {
1206 d3dxmesh->lpVtbl->Release(d3dxmesh);
1207 }
1208
1209 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, 0, device, &d3dxmesh);
1210 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1211
1212 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl1, device, NULL);
1213 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1214
1215 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl1, device, &d3dxmesh);
1216 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
1217
1218 if (hr == D3D_OK)
1219 {
1220 /* device */
1221 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, NULL);
1222 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1223
1224 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, &test_device);
1225 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
1226 ok(test_device == device, "Got result %p, expected %p\n", test_device, device);
1227
1228 if (hr == D3D_OK)
1229 {
1230 IDirect3DDevice9_Release(device);
1231 }
1232
1233 /* declaration */
1234 hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, NULL);
1235 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1236
1237 hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, test_decl);
1238 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
1239
1240 if (hr == D3D_OK)
1241 {
1242 size = sizeof(decl1) / sizeof(decl1[0]);
1243 for (i = 0; i < size - 1; i++)
1244 {
1245 ok(test_decl[i].Stream == decl1[i].Stream, "Returned stream %d, expected %d\n", test_decl[i].Stream, decl1[i].Stream);
1246 ok(test_decl[i].Type == decl1[i].Type, "Returned type %d, expected %d\n", test_decl[i].Type, decl1[i].Type);
1247 ok(test_decl[i].Method == decl1[i].Method, "Returned method %d, expected %d\n", test_decl[i].Method, decl1[i].Method);
1248 ok(test_decl[i].Usage == decl1[i].Usage, "Returned usage %d, expected %d\n", test_decl[i].Usage, decl1[i].Usage);
1249 ok(test_decl[i].UsageIndex == decl1[i].UsageIndex, "Returned usage index %d, expected %d\n", test_decl[i].UsageIndex, decl1[i].UsageIndex);
1250 ok(test_decl[i].Offset == decl1[i].Offset, "Returned offset %d, expected %d\n", test_decl[i].Offset, decl1[i].Offset);
1251 }
1252 ok(decl1[size-1].Stream == 0xFF, "Returned too long vertex declaration\n"); /* end element */
1253 }
1254
1255 /* options */
1256 options = d3dxmesh->lpVtbl->GetOptions(d3dxmesh);
1257 ok(options == D3DXMESH_MANAGED, "Got result %x, expected %x (D3DXMESH_MANAGED)\n", options, D3DXMESH_MANAGED);
1258
1259 /* rest */
1260 if (!new_mesh(&mesh, 3, 1))
1261 {
1262 skip("Couldn't create mesh\n");
1263 }
1264 else
1265 {
1266 memset(mesh.vertices, 0, mesh.number_of_vertices * sizeof(*mesh.vertices));
1267 memset(mesh.faces, 0, mesh.number_of_faces * sizeof(*mesh.faces));
1268 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
1269
1270 compare_mesh("createmesh1", d3dxmesh, &mesh);
1271
1272 free_mesh(&mesh);
1273 }
1274
1275 d3dxmesh->lpVtbl->Release(d3dxmesh);
1276 }
1277
1278 /* Test a declaration that can't be converted to an FVF. */
1279 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl2, device, &d3dxmesh);
1280 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
1281
1282 if (hr == D3D_OK)
1283 {
1284 /* device */
1285 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, NULL);
1286 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1287
1288 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, &test_device);
1289 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
1290 ok(test_device == device, "Got result %p, expected %p\n", test_device, device);
1291
1292 if (hr == D3D_OK)
1293 {
1294 IDirect3DDevice9_Release(device);
1295 }
1296
1297 /* declaration */
1298 hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, test_decl);
1299 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
1300
1301 if (hr == D3D_OK)
1302 {
1303 size = sizeof(decl2) / sizeof(decl2[0]);
1304 for (i = 0; i < size - 1; i++)
1305 {
1306 ok(test_decl[i].Stream == decl2[i].Stream, "Returned stream %d, expected %d\n", test_decl[i].Stream, decl2[i].Stream);
1307 ok(test_decl[i].Type == decl2[i].Type, "Returned type %d, expected %d\n", test_decl[i].Type, decl2[i].Type);
1308 ok(test_decl[i].Method == decl2[i].Method, "Returned method %d, expected %d\n", test_decl[i].Method, decl2[i].Method);
1309 ok(test_decl[i].Usage == decl2[i].Usage, "Returned usage %d, expected %d\n", test_decl[i].Usage, decl2[i].Usage);
1310 ok(test_decl[i].UsageIndex == decl2[i].UsageIndex, "Returned usage index %d, expected %d\n", test_decl[i].UsageIndex, decl2[i].UsageIndex);
1311 ok(test_decl[i].Offset == decl2[i].Offset, "Returned offset %d, expected %d\n", test_decl[i].Offset, decl2[i].Offset);
1312 }
1313 ok(decl2[size-1].Stream == 0xFF, "Returned too long vertex declaration\n"); /* end element */
1314 }
1315
1316 /* options */
1317 options = d3dxmesh->lpVtbl->GetOptions(d3dxmesh);
1318 ok(options == D3DXMESH_MANAGED, "Got result %x, expected %x (D3DXMESH_MANAGED)\n", options, D3DXMESH_MANAGED);
1319
1320 /* rest */
1321 if (!new_mesh(&mesh, 3, 1))
1322 {
1323 skip("Couldn't create mesh\n");
1324 }
1325 else
1326 {
1327 memset(mesh.vertices, 0, mesh.number_of_vertices * sizeof(*mesh.vertices));
1328 memset(mesh.faces, 0, mesh.number_of_faces * sizeof(*mesh.faces));
1329 mesh.fvf = 0;
1330 mesh.vertex_size = 60;
1331
1332 compare_mesh("createmesh2", d3dxmesh, &mesh);
1333
1334 free_mesh(&mesh);
1335 }
1336
1337 mesh.vertex_size = d3dxmesh->lpVtbl->GetNumBytesPerVertex(d3dxmesh);
1338 ok(mesh.vertex_size == 60, "Got vertex size %u, expected %u\n", mesh.vertex_size, 60);
1339
1340 d3dxmesh->lpVtbl->Release(d3dxmesh);
1341 }
1342
1343 /* Test a declaration with multiple streams. */
1344 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl3, device, &d3dxmesh);
1345 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1346
1347 IDirect3DDevice9_Release(device);
1348 IDirect3D9_Release(d3d);
1349 DestroyWindow(wnd);
1350 }
1351
1352 static void D3DXCreateMeshFVFTest(void)
1353 {
1354 HRESULT hr;
1355 HWND wnd;
1356 IDirect3D9 *d3d;
1357 IDirect3DDevice9 *device, *test_device;
1358 D3DPRESENT_PARAMETERS d3dpp;
1359 ID3DXMesh *d3dxmesh;
1360 int i, size;
1361 D3DVERTEXELEMENT9 test_decl[MAX_FVF_DECL_SIZE];
1362 DWORD options;
1363 struct mesh mesh;
1364
1365 static const D3DVERTEXELEMENT9 decl[3] = {
1366 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1367 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
1368 D3DDECL_END(), };
1369
1370 hr = D3DXCreateMeshFVF(0, 0, 0, 0, NULL, NULL);
1371 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1372
1373 hr = D3DXCreateMeshFVF(1, 3, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, NULL, &d3dxmesh);
1374 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1375
1376 wnd = CreateWindow("static", "d3dx9_test", 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL);
1377 if (!wnd)
1378 {
1379 skip("Couldn't create application window\n");
1380 return;
1381 }
1382 d3d = Direct3DCreate9(D3D_SDK_VERSION);
1383 if (!d3d)
1384 {
1385 skip("Couldn't create IDirect3D9 object\n");
1386 DestroyWindow(wnd);
1387 return;
1388 }
1389
1390 ZeroMemory(&d3dpp, sizeof(d3dpp));
1391 d3dpp.Windowed = TRUE;
1392 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1393 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, wnd, D3DCREATE_MIXED_VERTEXPROCESSING, &d3dpp, &device);
1394 if (FAILED(hr))
1395 {
1396 skip("Failed to create IDirect3DDevice9 object %#x\n", hr);
1397 IDirect3D9_Release(d3d);
1398 DestroyWindow(wnd);
1399 return;
1400 }
1401
1402 hr = D3DXCreateMeshFVF(0, 3, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, device, &d3dxmesh);
1403 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1404
1405 hr = D3DXCreateMeshFVF(1, 0, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, device, &d3dxmesh);
1406 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1407
1408 hr = D3DXCreateMeshFVF(1, 3, 0, D3DFVF_XYZ | D3DFVF_NORMAL, device, &d3dxmesh);
1409 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
1410
1411 if (hr == D3D_OK)
1412 {
1413 d3dxmesh->lpVtbl->Release(d3dxmesh);
1414 }
1415
1416 hr = D3DXCreateMeshFVF(1, 3, D3DXMESH_MANAGED, 0xdeadbeef, device, &d3dxmesh);
1417 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1418
1419 hr = D3DXCreateMeshFVF(1, 3, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, device, NULL);
1420 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1421
1422 hr = D3DXCreateMeshFVF(1, 3, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, device, &d3dxmesh);
1423 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
1424
1425 if (hr == D3D_OK)
1426 {
1427 /* device */
1428 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, NULL);
1429 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1430
1431 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, &test_device);
1432 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
1433 ok(test_device == device, "Got result %p, expected %p\n", test_device, device);
1434
1435 if (hr == D3D_OK)
1436 {
1437 IDirect3DDevice9_Release(device);
1438 }
1439
1440 /* declaration */
1441 hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, NULL);
1442 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1443
1444 hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, test_decl);
1445 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
1446
1447 if (hr == D3D_OK)
1448 {
1449 size = sizeof(decl) / sizeof(decl[0]);
1450 for (i = 0; i < size - 1; i++)
1451 {
1452 ok(test_decl[i].Stream == decl[i].Stream, "Returned stream %d, expected %d\n", test_decl[i].Stream, decl[i].Stream);
1453 ok(test_decl[i].Type == decl[i].Type, "Returned type %d, expected %d\n", test_decl[i].Type, decl[i].Type);
1454 ok(test_decl[i].Method == decl[i].Method, "Returned method %d, expected %d\n", test_decl[i].Method, decl[i].Method);
1455 ok(test_decl[i].Usage == decl[i].Usage, "Returned usage %d, expected %d\n", test_decl[i].Usage, decl[i].Usage);
1456 ok(test_decl[i].UsageIndex == decl[i].UsageIndex, "Returned usage index %d, expected %d\n",
1457 test_decl[i].UsageIndex, decl[i].UsageIndex);
1458 ok(test_decl[i].Offset == decl[i].Offset, "Returned offset %d, expected %d\n", test_decl[i].Offset, decl[i].Offset);
1459 }
1460 ok(decl[size-1].Stream == 0xFF, "Returned too long vertex declaration\n"); /* end element */
1461 }
1462
1463 /* options */
1464 options = d3dxmesh->lpVtbl->GetOptions(d3dxmesh);
1465 ok(options == D3DXMESH_MANAGED, "Got result %x, expected %x (D3DXMESH_MANAGED)\n", options, D3DXMESH_MANAGED);
1466
1467 /* rest */
1468 if (!new_mesh(&mesh, 3, 1))
1469 {
1470 skip("Couldn't create mesh\n");
1471 }
1472 else
1473 {
1474 memset(mesh.vertices, 0, mesh.number_of_vertices * sizeof(*mesh.vertices));
1475 memset(mesh.faces, 0, mesh.number_of_faces * sizeof(*mesh.faces));
1476 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
1477
1478 compare_mesh("createmeshfvf", d3dxmesh, &mesh);
1479
1480 free_mesh(&mesh);
1481 }
1482
1483 d3dxmesh->lpVtbl->Release(d3dxmesh);
1484 }
1485
1486 IDirect3DDevice9_Release(device);
1487 IDirect3D9_Release(d3d);
1488 DestroyWindow(wnd);
1489 }
1490
1491 #define check_vertex_buffer(mesh, vertices, num_vertices, fvf) \
1492 check_vertex_buffer_(__LINE__, mesh, vertices, num_vertices, fvf)
1493 static void check_vertex_buffer_(int line, ID3DXMesh *mesh, const void *vertices, DWORD num_vertices, DWORD fvf)
1494 {
1495 DWORD mesh_num_vertices = mesh->lpVtbl->GetNumVertices(mesh);
1496 DWORD mesh_fvf = mesh->lpVtbl->GetFVF(mesh);
1497 const void *mesh_vertices;
1498 HRESULT hr;
1499
1500 ok_(__FILE__,line)(fvf == mesh_fvf, "expected FVF %x, got %x\n", fvf, mesh_fvf);
1501 ok_(__FILE__,line)(num_vertices == mesh_num_vertices,
1502 "Expected %u vertices, got %u\n", num_vertices, mesh_num_vertices);
1503
1504 hr = mesh->lpVtbl->LockVertexBuffer(mesh, D3DLOCK_READONLY, (void**)&mesh_vertices);
1505 ok_(__FILE__,line)(hr == D3D_OK, "LockVertexBuffer returned %x, expected %x (D3D_OK)\n", hr, D3D_OK);
1506 if (FAILED(hr))
1507 return;
1508
1509 if (mesh_fvf == fvf) {
1510 DWORD vertex_size = D3DXGetFVFVertexSize(fvf);
1511 int i;
1512 for (i = 0; i < min(num_vertices, mesh_num_vertices); i++)
1513 {
1514 const FLOAT *exp_float = vertices;
1515 const FLOAT *got_float = mesh_vertices;
1516 DWORD texcount;
1517 DWORD pos_dim = 0;
1518 int j;
1519 BOOL last_beta_dword = FALSE;
1520 char prefix[128];
1521
1522 switch (fvf & D3DFVF_POSITION_MASK) {
1523 case D3DFVF_XYZ: pos_dim = 3; break;
1524 case D3DFVF_XYZRHW: pos_dim = 4; break;
1525 case D3DFVF_XYZB1:
1526 case D3DFVF_XYZB2:
1527 case D3DFVF_XYZB3:
1528 case D3DFVF_XYZB4:
1529 case D3DFVF_XYZB5:
1530 pos_dim = (fvf & D3DFVF_POSITION_MASK) - D3DFVF_XYZB1 + 1;
1531 if (fvf & (D3DFVF_LASTBETA_UBYTE4 | D3DFVF_LASTBETA_D3DCOLOR))
1532 {
1533 pos_dim--;
1534 last_beta_dword = TRUE;
1535 }
1536 break;
1537 case D3DFVF_XYZW: pos_dim = 4; break;
1538 }
1539 sprintf(prefix, "vertex[%u] position, ", i);
1540 check_floats_(line, prefix, got_float, exp_float, pos_dim);
1541 exp_float += pos_dim;
1542 got_float += pos_dim;
1543
1544 if (last_beta_dword) {
1545 ok_(__FILE__,line)(*(DWORD*)exp_float == *(DWORD*)got_float,
1546 "Vertex[%u]: Expected last beta %08x, got %08x\n", i, *(DWORD*)exp_float, *(DWORD*)got_float);
1547 exp_float++;
1548 got_float++;
1549 }
1550
1551 if (fvf & D3DFVF_NORMAL) {
1552 sprintf(prefix, "vertex[%u] normal, ", i);
1553 check_floats_(line, prefix, got_float, exp_float, 3);
1554 exp_float += 3;
1555 got_float += 3;
1556 }
1557 if (fvf & D3DFVF_PSIZE) {
1558 ok_(__FILE__,line)(compare(*exp_float, *got_float),
1559 "Vertex[%u]: Expected psize %g, got %g\n", i, *exp_float, *got_float);
1560 exp_float++;
1561 got_float++;
1562 }
1563 if (fvf & D3DFVF_DIFFUSE) {
1564 ok_(__FILE__,line)(*(DWORD*)exp_float == *(DWORD*)got_float,
1565 "Vertex[%u]: Expected diffuse %08x, got %08x\n", i, *(DWORD*)exp_float, *(DWORD*)got_float);
1566 exp_float++;
1567 got_float++;
1568 }
1569 if (fvf & D3DFVF_SPECULAR) {
1570 ok_(__FILE__,line)(*(DWORD*)exp_float == *(DWORD*)got_float,
1571 "Vertex[%u]: Expected specular %08x, got %08x\n", i, *(DWORD*)exp_float, *(DWORD*)got_float);
1572 exp_float++;
1573 got_float++;
1574 }
1575
1576 texcount = (fvf & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
1577 for (j = 0; j < texcount; j++) {
1578 DWORD dim = (((fvf >> (16 + 2 * j)) + 1) & 0x03) + 1;
1579 sprintf(prefix, "vertex[%u] texture, ", i);
1580 check_floats_(line, prefix, got_float, exp_float, dim);
1581 exp_float += dim;
1582 got_float += dim;
1583 }
1584
1585 vertices = (BYTE*)vertices + vertex_size;
1586 mesh_vertices = (BYTE*)mesh_vertices + vertex_size;
1587 }
1588 }
1589
1590 mesh->lpVtbl->UnlockVertexBuffer(mesh);
1591 }
1592
1593 #define check_index_buffer(mesh, indices, num_indices, index_size) \
1594 check_index_buffer_(__LINE__, mesh, indices, num_indices, index_size)
1595 static void check_index_buffer_(int line, ID3DXMesh *mesh, const void *indices, DWORD num_indices, DWORD index_size)
1596 {
1597 DWORD mesh_index_size = (mesh->lpVtbl->GetOptions(mesh) & D3DXMESH_32BIT) ? 4 : 2;
1598 DWORD mesh_num_indices = mesh->lpVtbl->GetNumFaces(mesh) * 3;
1599 const void *mesh_indices;
1600 HRESULT hr;
1601 DWORD i;
1602
1603 ok_(__FILE__,line)(index_size == mesh_index_size,
1604 "Expected index size %u, got %u\n", index_size, mesh_index_size);
1605 ok_(__FILE__,line)(num_indices == mesh_num_indices,
1606 "Expected %u indices, got %u\n", num_indices, mesh_num_indices);
1607
1608 hr = mesh->lpVtbl->LockIndexBuffer(mesh, D3DLOCK_READONLY, (void**)&mesh_indices);
1609 ok_(__FILE__,line)(hr == D3D_OK, "LockIndexBuffer returned %x, expected %x (D3D_OK)\n", hr, D3D_OK);
1610 if (FAILED(hr))
1611 return;
1612
1613 if (mesh_index_size == index_size) {
1614 for (i = 0; i < min(num_indices, mesh_num_indices); i++)
1615 {
1616 if (index_size == 4)
1617 ok_(__FILE__,line)(*(DWORD*)indices == *(DWORD*)mesh_indices,
1618 "Index[%u]: expected %u, got %u\n", i, *(DWORD*)indices, *(DWORD*)mesh_indices);
1619 else
1620 ok_(__FILE__,line)(*(WORD*)indices == *(WORD*)mesh_indices,
1621 "Index[%u]: expected %u, got %u\n", i, *(WORD*)indices, *(WORD*)mesh_indices);
1622 indices = (BYTE*)indices + index_size;
1623 mesh_indices = (BYTE*)mesh_indices + index_size;
1624 }
1625 }
1626 mesh->lpVtbl->UnlockIndexBuffer(mesh);
1627 }
1628
1629 #define check_matrix(got, expected) check_matrix_(__LINE__, got, expected)
1630 static void check_matrix_(int line, const D3DXMATRIX *got, const D3DXMATRIX *expected)
1631 {
1632 int i, j;
1633 for (i = 0; i < 4; i++) {
1634 for (j = 0; j < 4; j++) {
1635 ok_(__FILE__,line)(compare(U(*expected).m[i][j], U(*got).m[i][j]),
1636 "matrix[%u][%u]: expected %g, got %g\n",
1637 i, j, U(*expected).m[i][j], U(*got).m[i][j]);
1638 }
1639 }
1640 }
1641
1642 static void check_colorvalue_(int line, const char *prefix, const D3DCOLORVALUE got, const D3DCOLORVALUE expected)
1643 {
1644 ok_(__FILE__,line)(expected.r == got.r && expected.g == got.g && expected.b == got.b && expected.a == got.a,
1645 "%sExpected (%g, %g, %g, %g), got (%g, %g, %g, %g)\n", prefix,
1646 expected.r, expected.g, expected.b, expected.a, got.r, got.g, got.b, got.a);
1647 }
1648
1649 #define check_materials(got, got_count, expected, expected_count) \
1650 check_materials_(__LINE__, got, got_count, expected, expected_count)
1651 static void check_materials_(int line, const D3DXMATERIAL *got, DWORD got_count, const D3DXMATERIAL *expected, DWORD expected_count)
1652 {
1653 int i;
1654 ok_(__FILE__,line)(expected_count == got_count, "Expected %u materials, got %u\n", expected_count, got_count);
1655 if (!expected) {
1656 ok_(__FILE__,line)(got == NULL, "Expected NULL material ptr, got %p\n", got);
1657 return;
1658 }
1659 for (i = 0; i < min(expected_count, got_count); i++)
1660 {
1661 if (!expected[i].pTextureFilename)
1662 ok_(__FILE__,line)(got[i].pTextureFilename == NULL,
1663 "Expected NULL pTextureFilename, got %p\n", got[i].pTextureFilename);
1664 else
1665 ok_(__FILE__,line)(!strcmp(expected[i].pTextureFilename, got[i].pTextureFilename),
1666 "Expected '%s' for pTextureFilename, got '%s'\n", expected[i].pTextureFilename, got[i].pTextureFilename);
1667 check_colorvalue_(line, "Diffuse: ", got[i].MatD3D.Diffuse, expected[i].MatD3D.Diffuse);
1668 check_colorvalue_(line, "Ambient: ", got[i].MatD3D.Ambient, expected[i].MatD3D.Ambient);
1669 check_colorvalue_(line, "Specular: ", got[i].MatD3D.Specular, expected[i].MatD3D.Specular);
1670 check_colorvalue_(line, "Emissive: ", got[i].MatD3D.Emissive, expected[i].MatD3D.Emissive);
1671 ok_(__FILE__,line)(expected[i].MatD3D.Power == got[i].MatD3D.Power,
1672 "Power: Expected %g, got %g\n", expected[i].MatD3D.Power, got[i].MatD3D.Power);
1673 }
1674 }
1675
1676 #define check_generated_adjacency(mesh, got, epsilon) check_generated_adjacency_(__LINE__, mesh, got, epsilon)
1677 static void check_generated_adjacency_(int line, ID3DXMesh *mesh, const DWORD *got, FLOAT epsilon)
1678 {
1679 DWORD *expected;
1680 DWORD num_faces = mesh->lpVtbl->GetNumFaces(mesh);
1681 HRESULT hr;
1682
1683 expected = HeapAlloc(GetProcessHeap(), 0, num_faces * sizeof(DWORD) * 3);
1684 if (!expected) {
1685 skip_(__FILE__, line)("Out of memory\n");
1686 return;
1687 }
1688 hr = mesh->lpVtbl->GenerateAdjacency(mesh, epsilon, expected);
1689 ok_(__FILE__, line)(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
1690 if (SUCCEEDED(hr))
1691 {
1692 int i;
1693 for (i = 0; i < num_faces; i++)
1694 {
1695 ok_(__FILE__, line)(expected[i * 3] == got[i * 3] &&
1696 expected[i * 3 + 1] == got[i * 3 + 1] &&
1697 expected[i * 3 + 2] == got[i * 3 + 2],
1698 "Face %u adjacencies: Expected (%u, %u, %u), got (%u, %u, %u)\n", i,
1699 expected[i * 3], expected[i * 3 + 1], expected[i * 3 + 2],
1700 got[i * 3], got[i * 3 + 1], got[i * 3 + 2]);
1701 }
1702 }
1703 HeapFree(GetProcessHeap(), 0, expected);
1704 }
1705
1706 #define check_generated_effects(materials, num_materials, effects) \
1707 check_generated_effects_(__LINE__, materials, num_materials, effects)
1708 static void check_generated_effects_(int line, const D3DXMATERIAL *materials, DWORD num_materials, const D3DXEFFECTINSTANCE *effects)
1709 {
1710 int i;
1711 static const struct {
1712 const char *name;
1713 DWORD name_size;
1714 DWORD num_bytes;
1715 DWORD value_offset;
1716 } params[] = {
1717 #define EFFECT_TABLE_ENTRY(str, field) \
1718 {str, sizeof(str), sizeof(materials->MatD3D.field), offsetof(D3DXMATERIAL, MatD3D.field)}
1719 EFFECT_TABLE_ENTRY("Diffuse", Diffuse),
1720 EFFECT_TABLE_ENTRY("Power", Power),
1721 EFFECT_TABLE_ENTRY("Specular", Specular),
1722 EFFECT_TABLE_ENTRY("Emissive", Emissive),
1723 EFFECT_TABLE_ENTRY("Ambient", Ambient),
1724 #undef EFFECT_TABLE_ENTRY
1725 };
1726
1727 if (!num_materials) {
1728 ok_(__FILE__, line)(effects == NULL, "Expected NULL effects, got %p\n", effects);
1729 return;
1730 }
1731 for (i = 0; i < num_materials; i++)
1732 {
1733 int j;
1734 DWORD expected_num_defaults = ARRAY_SIZE(params) + (materials[i].pTextureFilename ? 1 : 0);
1735
1736 ok_(__FILE__,line)(expected_num_defaults == effects[i].NumDefaults,
1737 "effect[%u] NumDefaults: Expected %u, got %u\n", i,
1738 expected_num_defaults, effects[i].NumDefaults);
1739 for (j = 0; j < min(ARRAY_SIZE(params), effects[i].NumDefaults); j++)
1740 {
1741 int k;
1742 D3DXEFFECTDEFAULT *got_param = &effects[i].pDefaults[j];
1743 ok_(__FILE__,line)(!strcmp(params[j].name, got_param->pParamName),
1744 "effect[%u].pDefaults[%u].pParamName: Expected '%s', got '%s'\n", i, j,
1745 params[j].name, got_param->pParamName);
1746 ok_(__FILE__,line)(D3DXEDT_FLOATS == got_param->Type,
1747 "effect[%u].pDefaults[%u].Type: Expected %u, got %u\n", i, j,
1748 D3DXEDT_FLOATS, got_param->Type);
1749 ok_(__FILE__,line)(params[j].num_bytes == got_param->NumBytes,
1750 "effect[%u].pDefaults[%u].NumBytes: Expected %u, got %u\n", i, j,
1751 params[j].num_bytes, got_param->NumBytes);
1752 for (k = 0; k < min(params[j].num_bytes, got_param->NumBytes) / 4; k++)
1753 {
1754 FLOAT expected = ((FLOAT*)((BYTE*)&materials[i] + params[j].value_offset))[k];
1755 FLOAT got = ((FLOAT*)got_param->pValue)[k];
1756 ok_(__FILE__,line)(compare(expected, got),
1757 "effect[%u].pDefaults[%u] float value %u: Expected %g, got %g\n", i, j, k, expected, got);
1758 }
1759 }
1760 if (effects[i].NumDefaults > ARRAY_SIZE(params)) {
1761 D3DXEFFECTDEFAULT *got_param = &effects[i].pDefaults[j];
1762 static const char *expected_name = "Texture0@Name";
1763
1764 ok_(__FILE__,line)(!strcmp(expected_name, got_param->pParamName),
1765 "effect[%u].pDefaults[%u].pParamName: Expected '%s', got '%s'\n", i, j,
1766 expected_name, got_param->pParamName);
1767 ok_(__FILE__,line)(D3DXEDT_STRING == got_param->Type,
1768 "effect[%u].pDefaults[%u].Type: Expected %u, got %u\n", i, j,
1769 D3DXEDT_STRING, got_param->Type);
1770 if (materials[i].pTextureFilename) {
1771 ok_(__FILE__,line)(strlen(materials[i].pTextureFilename) + 1 == got_param->NumBytes,
1772 "effect[%u] texture filename length: Expected %u, got %u\n", i,
1773 (DWORD)strlen(materials[i].pTextureFilename) + 1, got_param->NumBytes);
1774 ok_(__FILE__,line)(!strcmp(materials[i].pTextureFilename, got_param->pValue),
1775 "effect[%u] texture filename: Expected '%s', got '%s'\n", i,
1776 materials[i].pTextureFilename, (char*)got_param->pValue);
1777 }
1778 }
1779 }
1780 }
1781
1782 static LPSTR strdupA(LPCSTR p)
1783 {
1784 LPSTR ret;
1785 if (!p) return NULL;
1786 ret = HeapAlloc(GetProcessHeap(), 0, strlen(p) + 1);
1787 if (ret) strcpy(ret, p);
1788 return ret;
1789 }
1790
1791 static CALLBACK HRESULT ID3DXAllocateHierarchyImpl_DestroyFrame(ID3DXAllocateHierarchy *iface, LPD3DXFRAME frame)
1792 {
1793 TRACECALLBACK("ID3DXAllocateHierarchyImpl_DestroyFrame(%p, %p)\n", iface, frame);
1794 if (frame) {
1795 HeapFree(GetProcessHeap(), 0, frame->Name);
1796 HeapFree(GetProcessHeap(), 0, frame);
1797 }
1798 return D3D_OK;
1799 }
1800
1801 static CALLBACK HRESULT ID3DXAllocateHierarchyImpl_CreateFrame(ID3DXAllocateHierarchy *iface, LPCSTR name, LPD3DXFRAME *new_frame)
1802 {
1803 LPD3DXFRAME frame;
1804
1805 TRACECALLBACK("ID3DXAllocateHierarchyImpl_CreateFrame(%p, '%s', %p)\n", iface, name, new_frame);
1806 frame = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*frame));
1807 if (!frame)
1808 return E_OUTOFMEMORY;
1809 if (name) {
1810 frame->Name = strdupA(name);
1811 if (!frame->Name) {
1812 HeapFree(GetProcessHeap(), 0, frame);
1813 return E_OUTOFMEMORY;
1814 }
1815 }
1816 *new_frame = frame;
1817 return D3D_OK;
1818 }
1819
1820 static HRESULT destroy_mesh_container(LPD3DXMESHCONTAINER mesh_container)
1821 {
1822 int i;
1823
1824 if (!mesh_container)
1825 return D3D_OK;
1826 HeapFree(GetProcessHeap(), 0, mesh_container->Name);
1827 if (U(mesh_container->MeshData).pMesh)
1828 IUnknown_Release(U(mesh_container->MeshData).pMesh);
1829 if (mesh_container->pMaterials) {
1830 for (i = 0; i < mesh_container->NumMaterials; i++)
1831 HeapFree(GetProcessHeap(), 0, mesh_container->pMaterials[i].pTextureFilename);
1832 HeapFree(GetProcessHeap(), 0, mesh_container->pMaterials);
1833 }
1834 if (mesh_container->pEffects) {
1835 for (i = 0; i < mesh_container->NumMaterials; i++) {
1836 HeapFree(GetProcessHeap(), 0, mesh_container->pEffects[i].pEffectFilename);
1837 if (mesh_container->pEffects[i].pDefaults) {
1838 int j;
1839 for (j = 0; j < mesh_container->pEffects[i].NumDefaults; j++) {
1840 HeapFree(GetProcessHeap(), 0, mesh_container->pEffects[i].pDefaults[j].pParamName);
1841 HeapFree(GetProcessHeap(), 0, mesh_container->pEffects[i].pDefaults[j].pValue);
1842 }
1843 HeapFree(GetProcessHeap(), 0, mesh_container->pEffects[i].pDefaults);
1844 }
1845 }
1846 HeapFree(GetProcessHeap(), 0, mesh_container->pEffects);
1847 }
1848 HeapFree(GetProcessHeap(), 0, mesh_container->pAdjacency);
1849 if (mesh_container->pSkinInfo)
1850 IUnknown_Release(mesh_container->pSkinInfo);
1851 HeapFree(GetProcessHeap(), 0, mesh_container);
1852 return D3D_OK;
1853 }
1854
1855 static CALLBACK HRESULT ID3DXAllocateHierarchyImpl_DestroyMeshContainer(ID3DXAllocateHierarchy *iface, LPD3DXMESHCONTAINER mesh_container)
1856 {
1857 TRACECALLBACK("ID3DXAllocateHierarchyImpl_DestroyMeshContainer(%p, %p)\n", iface, mesh_container);
1858 return destroy_mesh_container(mesh_container);
1859 }
1860
1861 static CALLBACK HRESULT ID3DXAllocateHierarchyImpl_CreateMeshContainer(ID3DXAllocateHierarchy *iface,
1862 LPCSTR name, CONST D3DXMESHDATA *mesh_data, CONST D3DXMATERIAL *materials,
1863 CONST D3DXEFFECTINSTANCE *effects, DWORD num_materials, CONST DWORD *adjacency,
1864 LPD3DXSKININFO skin_info, LPD3DXMESHCONTAINER *new_mesh_container)
1865 {
1866 LPD3DXMESHCONTAINER mesh_container = NULL;
1867 int i;
1868
1869 TRACECALLBACK("ID3DXAllocateHierarchyImpl_CreateMeshContainer(%p, '%s', %u, %p, %p, %p, %d, %p, %p, %p)\n",
1870 iface, name, mesh_data->Type, U(*mesh_data).pMesh, materials, effects,
1871 num_materials, adjacency, skin_info, *new_mesh_container);
1872
1873 mesh_container = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*mesh_container));
1874 if (!mesh_container)
1875 return E_OUTOFMEMORY;
1876
1877 if (name) {
1878 mesh_container->Name = strdupA(name);
1879 if (!mesh_container->Name)
1880 goto error;
1881 }
1882
1883 mesh_container->NumMaterials = num_materials;
1884 if (num_materials) {
1885 mesh_container->pMaterials = HeapAlloc(GetProcessHeap(), 0, num_materials * sizeof(*materials));
1886 if (!mesh_container->pMaterials)
1887 goto error;
1888
1889 memcpy(mesh_container->pMaterials, materials, num_materials * sizeof(*materials));
1890 for (i = 0; i < num_materials; i++)
1891 mesh_container->pMaterials[i].pTextureFilename = NULL;
1892 for (i = 0; i < num_materials; i++) {
1893 if (materials[i].pTextureFilename) {
1894 mesh_container->pMaterials[i].pTextureFilename = strdupA(materials[i].pTextureFilename);
1895 if (!mesh_container->pMaterials[i].pTextureFilename)
1896 goto error;
1897 }
1898 }
1899
1900 mesh_container->pEffects = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, num_materials * sizeof(*effects));
1901 if (!mesh_container->pEffects)
1902 goto error;
1903 for (i = 0; i < num_materials; i++) {
1904 int j;
1905 const D3DXEFFECTINSTANCE *effect_src = &effects[i];
1906 D3DXEFFECTINSTANCE *effect_dest = &mesh_container->pEffects[i];
1907
1908 if (effect_src->pEffectFilename) {
1909 effect_dest->pEffectFilename = strdupA(effect_src->pEffectFilename);
1910 if (!effect_dest->pEffectFilename)
1911 goto error;
1912 }
1913 effect_dest->pDefaults = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1914 effect_src->NumDefaults * sizeof(*effect_src->pDefaults));
1915 if (!effect_dest->pDefaults)
1916 goto error;
1917 effect_dest->NumDefaults = effect_src->NumDefaults;
1918 for (j = 0; j < effect_src->NumDefaults; j++) {
1919 const D3DXEFFECTDEFAULT *default_src = &effect_src->pDefaults[j];
1920 D3DXEFFECTDEFAULT *default_dest = &effect_dest->pDefaults[j];
1921
1922 if (default_src->pParamName) {
1923 default_dest->pParamName = strdupA(default_src->pParamName);
1924 if (!default_dest->pParamName)
1925 goto error;
1926 }
1927 default_dest->NumBytes = default_src->NumBytes;
1928 default_dest->Type = default_src->Type;
1929 default_dest->pValue = HeapAlloc(GetProcessHeap(), 0, default_src->NumBytes);
1930 memcpy(default_dest->pValue, default_src->pValue, default_src->NumBytes);
1931 }
1932 }
1933 }
1934
1935 ok(adjacency != NULL, "Expected non-NULL adjacency, got NULL\n");
1936 if (adjacency) {
1937 if (mesh_data->Type == D3DXMESHTYPE_MESH || mesh_data->Type == D3DXMESHTYPE_PMESH) {
1938 ID3DXBaseMesh *basemesh = (ID3DXBaseMesh*)U(*mesh_data).pMesh;
1939 DWORD num_faces = basemesh->lpVtbl->GetNumFaces(basemesh);
1940 size_t size = num_faces * sizeof(DWORD) * 3;
1941 mesh_container->pAdjacency = HeapAlloc(GetProcessHeap(), 0, size);
1942 if (!mesh_container->pAdjacency)
1943 goto error;
1944 memcpy(mesh_container->pAdjacency, adjacency, size);
1945 } else {
1946 ok(mesh_data->Type == D3DXMESHTYPE_PATCHMESH, "Unknown mesh type %u\n", mesh_data->Type);
1947 if (mesh_data->Type == D3DXMESHTYPE_PATCHMESH)
1948 trace("FIXME: copying adjacency data for patch mesh not implemented\n");
1949 }
1950 }
1951
1952 memcpy(&mesh_container->MeshData, mesh_data, sizeof(*mesh_data));
1953 if (U(*mesh_data).pMesh)
1954 IUnknown_AddRef(U(*mesh_data).pMesh);
1955 if (skin_info) {
1956 mesh_container->pSkinInfo = skin_info;
1957 skin_info->lpVtbl->AddRef(skin_info);
1958 }
1959 *new_mesh_container = mesh_container;
1960
1961 return S_OK;
1962 error:
1963 destroy_mesh_container(mesh_container);
1964 return E_OUTOFMEMORY;
1965 }
1966
1967 static ID3DXAllocateHierarchyVtbl ID3DXAllocateHierarchyImpl_Vtbl = {
1968 ID3DXAllocateHierarchyImpl_CreateFrame,
1969 ID3DXAllocateHierarchyImpl_CreateMeshContainer,
1970 ID3DXAllocateHierarchyImpl_DestroyFrame,
1971 ID3DXAllocateHierarchyImpl_DestroyMeshContainer,
1972 };
1973 static ID3DXAllocateHierarchy alloc_hier = { &ID3DXAllocateHierarchyImpl_Vtbl };
1974
1975 #define test_LoadMeshFromX(device, xfile_str, vertex_array, fvf, index_array, materials_array, check_adjacency) \
1976 test_LoadMeshFromX_(__LINE__, device, xfile_str, sizeof(xfile_str) - 1, vertex_array, ARRAY_SIZE(vertex_array), fvf, \
1977 index_array, ARRAY_SIZE(index_array), sizeof(*index_array), materials_array, ARRAY_SIZE(materials_array), \
1978 check_adjacency);
1979 static void test_LoadMeshFromX_(int line, IDirect3DDevice9 *device, const char *xfile_str, size_t xfile_strlen,
1980 const void *vertices, DWORD num_vertices, DWORD fvf, const void *indices, DWORD num_indices, size_t index_size,
1981 const D3DXMATERIAL *expected_materials, DWORD expected_num_materials, BOOL check_adjacency)
1982 {
1983 HRESULT hr;
1984 ID3DXBuffer *materials = NULL;
1985 ID3DXBuffer *effects = NULL;
1986 ID3DXBuffer *adjacency = NULL;
1987 ID3DXMesh *mesh = NULL;
1988 DWORD num_materials = 0;
1989
1990 /* Adjacency is not checked when the X file contains multiple meshes,
1991 * since calling GenerateAdjacency on the merged mesh is not equivalent
1992 * to calling GenerateAdjacency on the individual meshes and then merging
1993 * the adjacency data. */
1994 hr = D3DXLoadMeshFromXInMemory(xfile_str, xfile_strlen, D3DXMESH_MANAGED, device,
1995 check_adjacency ? &adjacency : NULL, &materials, &effects, &num_materials, &mesh);
1996 ok_(__FILE__,line)(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
1997 if (SUCCEEDED(hr)) {
1998 D3DXMATERIAL *materials_ptr = materials ? ID3DXBuffer_GetBufferPointer(materials) : NULL;
1999 D3DXEFFECTINSTANCE *effects_ptr = effects ? ID3DXBuffer_GetBufferPointer(effects) : NULL;
2000 DWORD *adjacency_ptr = check_adjacency ? ID3DXBuffer_GetBufferPointer(adjacency) : NULL;
2001
2002 check_vertex_buffer_(line, mesh, vertices, num_vertices, fvf);
2003 check_index_buffer_(line, mesh, indices, num_indices, index_size);
2004 check_materials_(line, materials_ptr, num_materials, expected_materials, expected_num_materials);
2005 check_generated_effects_(line, materials_ptr, num_materials, effects_ptr);
2006 if (check_adjacency)
2007 check_generated_adjacency_(line, mesh, adjacency_ptr, 0.0f);
2008
2009 if (materials) ID3DXBuffer_Release(materials);
2010 if (effects) ID3DXBuffer_Release(effects);
2011 if (adjacency) ID3DXBuffer_Release(adjacency);
2012 IUnknown_Release(mesh);
2013 }
2014 }
2015
2016 static void D3DXLoadMeshTest(void)
2017 {
2018 static const char empty_xfile[] = "xof 0303txt 0032";
2019 /*________________________*/
2020 static const char simple_xfile[] =
2021 "xof 0303txt 0032"
2022 "Mesh {"
2023 "3;"
2024 "0.0; 0.0; 0.0;,"
2025 "0.0; 1.0; 0.0;,"
2026 "1.0; 1.0; 0.0;;"
2027 "1;"
2028 "3; 0, 1, 2;;"
2029 "}";
2030 static const WORD simple_index_buffer[] = {0, 1, 2};
2031 static const D3DXVECTOR3 simple_vertex_buffer[] = {
2032 {0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {1.0, 1.0, 0.0}
2033 };
2034 const DWORD simple_fvf = D3DFVF_XYZ;
2035 static const char framed_xfile[] =
2036 "xof 0303txt 0032"
2037 "Frame {"
2038 "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;; }"
2039 "FrameTransformMatrix {" /* translation (0.0, 0.0, 2.0) */
2040 "1.0, 0.0, 0.0, 0.0,"
2041 "0.0, 1.0, 0.0, 0.0,"
2042 "0.0, 0.0, 1.0, 0.0,"
2043 "0.0, 0.0, 2.0, 1.0;;"
2044 "}"
2045 "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;; }"
2046 "FrameTransformMatrix {" /* translation (0.0, 0.0, 3.0) */
2047 "1.0, 0.0, 0.0, 0.0,"
2048 "0.0, 1.0, 0.0, 0.0,"
2049 "0.0, 0.0, 1.0, 0.0,"
2050 "0.0, 0.0, 3.0, 1.0;;"
2051 "}"
2052 "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;; }"
2053 "}";
2054 static const WORD framed_index_buffer[] = { 0, 1, 2 };
2055 static const D3DXVECTOR3 framed_vertex_buffers[3][3] = {
2056 {{0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {1.0, 1.0, 0.0}},
2057 {{0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {2.0, 1.0, 0.0}},
2058 {{0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {3.0, 1.0, 0.0}},
2059 };
2060 static const WORD merged_index_buffer[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
2061 /* frame transforms accumulates for D3DXLoadMeshFromX */
2062 static const D3DXVECTOR3 merged_vertex_buffer[] = {
2063 {0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {1.0, 1.0, 0.0},
2064 {0.0, 0.0, 2.0}, {0.0, 1.0, 2.0}, {2.0, 1.0, 2.0},
2065 {0.0, 0.0, 5.0}, {0.0, 1.0, 5.0}, {3.0, 1.0, 5.0},
2066 };
2067 const DWORD framed_fvf = D3DFVF_XYZ;
2068 /*________________________*/
2069 static const char box_xfile[] =
2070 "xof 0303txt 0032"
2071 "Mesh {"
2072 "8;" /* DWORD nVertices; */
2073 /* array Vector vertices[nVertices]; */
2074 "0.0; 0.0; 0.0;,"
2075 "0.0; 0.0; 1.0;,"
2076 "0.0; 1.0; 0.0;,"
2077 "0.0; 1.0; 1.0;,"
2078 "1.0; 0.0; 0.0;,"
2079 "1.0; 0.0; 1.0;,"
2080 "1.0; 1.0; 0.0;,"
2081 "1.0; 1.0; 1.0;;"
2082 "6;" /* DWORD nFaces; */
2083 /* array MeshFace faces[nFaces]; */
2084 "4; 0, 1, 3, 2;," /* (left side) */
2085 "4; 2, 3, 7, 6;," /* (top side) */
2086 "4; 6, 7, 5, 4;," /* (right side) */
2087 "4; 1, 0, 4, 5;," /* (bottom side) */
2088 "4; 1, 5, 7, 3;," /* (back side) */
2089 "4; 0, 2, 6, 4;;" /* (front side) */
2090 "MeshNormals {"
2091 "6;" /* DWORD nNormals; */
2092 /* array Vector normals[nNormals]; */
2093 "-1.0; 0.0; 0.0;,"
2094 "0.0; 1.0; 0.0;,"
2095 "1.0; 0.0; 0.0;,"
2096 "0.0; -1.0; 0.0;,"
2097 "0.0; 0.0; 1.0;,"
2098 "0.0; 0.0; -1.0;;"
2099 "6;" /* DWORD nFaceNormals; */
2100 /* array MeshFace faceNormals[nFaceNormals]; */
2101 "4; 0, 0, 0, 0;,"
2102 "4; 1, 1, 1, 1;,"
2103 "4; 2, 2, 2, 2;,"
2104 "4; 3, 3, 3, 3;,"
2105 "4; 4, 4, 4, 4;,"
2106 "4; 5, 5, 5, 5;;"
2107 "}"
2108 "MeshMaterialList materials {"
2109 "2;" /* DWORD nMaterials; */
2110 "6;" /* DWORD nFaceIndexes; */
2111 /* array DWORD faceIndexes[nFaceIndexes]; */
2112 "0, 0, 0, 1, 1, 1;;"
2113 "Material {"
2114 /* ColorRGBA faceColor; */
2115 "0.0; 0.0; 1.0; 1.0;;"
2116 /* FLOAT power; */
2117 "0.5;"
2118 /* ColorRGB specularColor; */
2119 "1.0; 1.0; 1.0;;"
2120 /* ColorRGB emissiveColor; */
2121 "0.0; 0.0; 0.0;;"
2122 "}"
2123 "Material {"
2124 /* ColorRGBA faceColor; */
2125 "1.0; 1.0; 1.0; 1.0;;"
2126 /* FLOAT power; */
2127 "1.0;"
2128 /* ColorRGB specularColor; */
2129 "1.0; 1.0; 1.0;;"
2130 /* ColorRGB emissiveColor; */
2131 "0.0; 0.0; 0.0;;"
2132 "TextureFilename { \"texture.jpg\"; }"
2133 "}"
2134 "}"
2135 "MeshVertexColors {"
2136 "8;" /* DWORD nVertexColors; */
2137 /* array IndexedColor vertexColors[nVertexColors]; */
2138 "0; 0.0; 0.0; 0.0; 0.0;;"
2139 "1; 0.0; 0.0; 1.0; 0.1;;"
2140 "2; 0.0; 1.0; 0.0; 0.2;;"
2141 "3; 0.0; 1.0; 1.0; 0.3;;"
2142 "4; 1.0; 0.0; 0.0; 0.4;;"
2143 "5; 1.0; 0.0; 1.0; 0.5;;"
2144 "6; 1.0; 1.0; 0.0; 0.6;;"
2145 "7; 1.0; 1.0; 1.0; 0.7;;"
2146 "}"
2147 "MeshTextureCoords {"
2148 "8;" /* DWORD nTextureCoords; */
2149 /* array Coords2d textureCoords[nTextureCoords]; */
2150 "0.0; 1.0;,"
2151 "1.0; 1.0;,"
2152 "0.0; 0.0;,"
2153 "1.0; 0.0;,"
2154 "1.0; 1.0;,"
2155 "0.0; 1.0;,"
2156 "1.0; 0.0;,"
2157 "0.0; 0.0;;"
2158 "}"
2159 "}";
2160 static const WORD box_index_buffer[] = {
2161 0, 1, 3,
2162 0, 3, 2,
2163 8, 9, 7,
2164 8, 7, 6,
2165 10, 11, 5,
2166 10, 5, 4,
2167 12, 13, 14,
2168 12, 14, 15,
2169 16, 17, 18,
2170 16, 18, 19,
2171 20, 21, 22,
2172 20, 22, 23,
2173 };
2174 static const struct {
2175 D3DXVECTOR3 position;
2176 D3DXVECTOR3 normal;
2177 D3DCOLOR diffuse;
2178 D3DXVECTOR2 tex_coords;
2179 } box_vertex_buffer[] = {
2180 {{0.0, 0.0, 0.0}, {-1.0, 0.0, 0.0}, 0x00000000, {0.0, 1.0}},
2181 {{0.0, 0.0, 1.0}, {-1.0, 0.0, 0.0}, 0x1a0000ff, {1.0, 1.0}},
2182 {{0.0, 1.0, 0.0}, {-1.0, 0.0, 0.0}, 0x3300ff00, {0.0, 0.0}},
2183 {{0.0, 1.0, 1.0}, {-1.0, 0.0, 0.0}, 0x4d00ffff, {1.0, 0.0}},
2184 {{1.0, 0.0, 0.0}, {1.0, 0.0, 0.0}, 0x66ff0000, {1.0, 1.0}},
2185 {{1.0, 0.0, 1.0}, {1.0, 0.0, 0.0}, 0x80ff00ff, {0.0, 1.0}},
2186 {{1.0, 1.0, 0.0}, {0.0, 1.0, 0.0}, 0x99ffff00, {1.0, 0.0}},
2187 {{1.0, 1.0, 1.0}, {0.0, 1.0, 0.0}, 0xb3ffffff, {0.0, 0.0}},
2188 {{0.0, 1.0, 0.0}, {0.0, 1.0, 0.0}, 0x3300ff00, {0.0, 0.0}},
2189 {{0.0, 1.0, 1.0}, {0.0, 1.0, 0.0}, 0x4d00ffff, {1.0, 0.0}},
2190 {{1.0, 1.0, 0.0}, {1.0, 0.0, 0.0}, 0x99ffff00, {1.0, 0.0}},
2191 {{1.0, 1.0, 1.0}, {1.0, 0.0, 0.0}, 0xb3ffffff, {0.0, 0.0}},
2192 {{0.0, 0.0, 1.0}, {0.0, -1.0, 0.0}, 0x1a0000ff, {1.0, 1.0}},
2193 {{0.0, 0.0, 0.0}, {0.0, -1.0, 0.0}, 0x00000000, {0.0, 1.0}},
2194 {{1.0, 0.0, 0.0}, {0.0, -1.0, 0.0}, 0x66ff0000, {1.0, 1.0}},
2195 {{1.0, 0.0, 1.0}, {0.0, -1.0, 0.0}, 0x80ff00ff, {0.0, 1.0}},
2196 {{0.0, 0.0, 1.0}, {0.0, 0.0, 1.0}, 0x1a0000ff, {1.0, 1.0}},
2197 {{1.0, 0.0, 1.0}, {0.0, 0.0, 1.0}, 0x80ff00ff, {0.0, 1.0}},
2198 {{1.0, 1.0, 1.0}, {0.0, 0.0, 1.0}, 0xb3ffffff, {0.0, 0.0}},
2199 {{0.0, 1.0, 1.0}, {0.0, 0.0, 1.0}, 0x4d00ffff, {1.0, 0.0}},
2200 {{0.0, 0.0, 0.0}, {0.0, 0.0, -1.0}, 0x00000000, {0.0, 1.0}},
2201 {{0.0, 1.0, 0.0}, {0.0, 0.0, -1.0}, 0x3300ff00, {0.0, 0.0}},
2202 {{1.0, 1.0, 0.0}, {0.0, 0.0, -1.0}, 0x99ffff00, {1.0, 0.0}},
2203 {{1.0, 0.0, 0.0}, {0.0, 0.0, -1.0}, 0x66ff0000, {1.0, 1.0}},
2204 };
2205 static const D3DXMATERIAL box_materials[] = {
2206 {
2207 {
2208 {0.0, 0.0, 1.0, 1.0}, /* Diffuse */
2209 {0.0, 0.0, 0.0, 1.0}, /* Ambient */
2210 {1.0, 1.0, 1.0, 1.0}, /* Specular */
2211 {0.0, 0.0, 0.0, 1.0}, /* Emissive */
2212 0.5, /* Power */
2213 },
2214 NULL, /* pTextureFilename */
2215 },
2216 {
2217 {
2218 {1.0, 1.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 1.0, /* Power */
2223 },
2224 (char *)"texture.jpg", /* pTextureFilename */
2225 },
2226 };
2227 const DWORD box_fvf = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_TEX1;
2228 /*________________________*/
2229 static const D3DXMATERIAL default_materials[] = {
2230 {
2231 {
2232 {0.5, 0.5, 0.5, 0.0}, /* Diffuse */
2233 {0.0, 0.0, 0.0, 0.0}, /* Ambient */
2234 {0.5, 0.5, 0.5, 0.0}, /* Specular */
2235 {0.0, 0.0, 0.0, 0.0}, /* Emissive */
2236 0.0, /* Power */
2237 },
2238 NULL, /* pTextureFilename */
2239 }
2240 };
2241 HRESULT hr;
2242 HWND wnd = NULL;
2243 IDirect3D9 *d3d = NULL;
2244 IDirect3DDevice9 *device = NULL;
2245 D3DPRESENT_PARAMETERS d3dpp;
2246 ID3DXMesh *mesh = NULL;
2247 D3DXFRAME *frame_hier = NULL;
2248 D3DXMATRIX transform;
2249
2250 wnd = CreateWindow("static", "d3dx9_test", WS_POPUP, 0, 0, 1000, 1000, NULL, NULL, NULL, NULL);
2251 if (!wnd)
2252 {
2253 skip("Couldn't create application window\n");
2254 return;
2255 }
2256 d3d = Direct3DCreate9(D3D_SDK_VERSION);
2257 if (!d3d)
2258 {
2259 skip("Couldn't create IDirect3D9 object\n");
2260 goto cleanup;
2261 }
2262
2263 ZeroMemory(&d3dpp, sizeof(d3dpp));
2264 d3dpp.Windowed = TRUE;
2265 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2266 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, wnd, D3DCREATE_MIXED_VERTEXPROCESSING, &d3dpp, &device);
2267 if (FAILED(hr))
2268 {
2269 skip("Failed to create IDirect3DDevice9 object %#x\n", hr);
2270 goto cleanup;
2271 }
2272
2273 hr = D3DXLoadMeshHierarchyFromXInMemory(NULL, sizeof(simple_xfile) - 1,
2274 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
2275 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2276
2277 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, 0,
2278 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
2279 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2280
2281 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1,
2282 D3DXMESH_MANAGED, NULL, &alloc_hier, NULL, &frame_hier, NULL);
2283 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2284
2285 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1,
2286 D3DXMESH_MANAGED, device, NULL, NULL, &frame_hier, NULL);
2287 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2288
2289 hr = D3DXLoadMeshHierarchyFromXInMemory(empty_xfile, sizeof(empty_xfile) - 1,
2290 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
2291 ok(hr == E_FAIL, "Expected E_FAIL, got %#x\n", hr);
2292
2293 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1,
2294 D3DXMESH_MANAGED, device, &alloc_hier, NULL, NULL, NULL);
2295 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2296
2297 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1,
2298 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
2299 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2300 if (SUCCEEDED(hr)) {
2301 D3DXMESHCONTAINER *container = frame_hier->pMeshContainer;
2302
2303 ok(frame_hier->Name == NULL, "Expected NULL, got '%s'\n", frame_hier->Name);
2304 D3DXMatrixIdentity(&transform);
2305 check_matrix(&frame_hier->TransformationMatrix, &transform);
2306
2307 ok(!strcmp(container->Name, ""), "Expected '', got '%s'\n", container->Name);
2308 ok(container->MeshData.Type == D3DXMESHTYPE_MESH, "Expected %d, got %d\n",
2309 D3DXMESHTYPE_MESH, container->MeshData.Type);
2310 mesh = U(container->MeshData).pMesh;
2311 check_vertex_buffer(mesh, simple_vertex_buffer, ARRAY_SIZE(simple_vertex_buffer), simple_fvf);
2312 check_index_buffer(mesh, simple_index_buffer, ARRAY_SIZE(simple_index_buffer), sizeof(*simple_index_buffer));
2313 check_materials(container->pMaterials, container->NumMaterials, NULL, 0);
2314 check_generated_effects(container->pMaterials, container->NumMaterials, container->pEffects);
2315 check_generated_adjacency(mesh, container->pAdjacency, 0.0f);
2316 hr = D3DXFrameDestroy(frame_hier, &alloc_hier);
2317 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2318 frame_hier = NULL;
2319 }
2320
2321 hr = D3DXLoadMeshHierarchyFromXInMemory(box_xfile, sizeof(box_xfile) - 1,
2322 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
2323 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2324 if (SUCCEEDED(hr)) {
2325 D3DXMESHCONTAINER *container = frame_hier->pMeshContainer;
2326
2327 ok(frame_hier->Name == NULL, "Expected NULL, got '%s'\n", frame_hier->Name);
2328 D3DXMatrixIdentity(&transform);
2329 check_matrix(&frame_hier->TransformationMatrix, &transform);
2330
2331 ok(!strcmp(container->Name, ""), "Expected '', got '%s'\n", container->Name);
2332 ok(container->MeshData.Type == D3DXMESHTYPE_MESH, "Expected %d, got %d\n",
2333 D3DXMESHTYPE_MESH, container->MeshData.Type);
2334 mesh = U(container->MeshData).pMesh;
2335 check_vertex_buffer(mesh, box_vertex_buffer, ARRAY_SIZE(box_vertex_buffer), box_fvf);
2336 check_index_buffer(mesh, box_index_buffer, ARRAY_SIZE(box_index_buffer), sizeof(*box_index_buffer));
2337 check_materials(container->pMaterials, container->NumMaterials, box_materials, ARRAY_SIZE(box_materials));
2338 check_generated_effects(container->pMaterials, container->NumMaterials, container->pEffects);
2339 check_generated_adjacency(mesh, container->pAdjacency, 0.0f);
2340 hr = D3DXFrameDestroy(frame_hier, &alloc_hier);
2341 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2342 frame_hier = NULL;
2343 }
2344
2345 hr = D3DXLoadMeshHierarchyFromXInMemory(framed_xfile, sizeof(framed_xfile) - 1,
2346 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
2347 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2348 if (SUCCEEDED(hr)) {
2349 D3DXMESHCONTAINER *container = frame_hier->pMeshContainer;
2350 int i;
2351
2352 ok(!strcmp(frame_hier->Name, ""), "Expected '', got '%s'\n", frame_hier->Name);
2353 /* last frame transform replaces the first */
2354 D3DXMatrixIdentity(&transform);
2355 U(transform).m[3][2] = 3.0;
2356 check_matrix(&frame_hier->TransformationMatrix, &transform);
2357
2358 for (i = 0; i < 3; i++) {
2359 ok(!strcmp(container->Name, ""), "Expected '', got '%s'\n", container->Name);
2360 ok(container->MeshData.Type == D3DXMESHTYPE_MESH, "Expected %d, got %d\n",
2361 D3DXMESHTYPE_MESH, container->MeshData.Type);
2362 mesh = U(container->MeshData).pMesh;
2363 check_vertex_buffer(mesh, framed_vertex_buffers[i], ARRAY_SIZE(framed_vertex_buffers[0]), framed_fvf);
2364 check_index_buffer(mesh, framed_index_buffer, ARRAY_SIZE(framed_index_buffer), sizeof(*framed_index_buffer));
2365 check_materials(container->pMaterials, container->NumMaterials, NULL, 0);
2366 check_generated_effects(container->pMaterials, container->NumMaterials, container->pEffects);
2367 check_generated_adjacency(mesh, container->pAdjacency, 0.0f);
2368 container = container->pNextMeshContainer;
2369 }
2370 ok(container == NULL, "Expected NULL, got %p\n", container);
2371 hr = D3DXFrameDestroy(frame_hier, &alloc_hier);
2372 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2373 frame_hier = NULL;
2374 }
2375
2376
2377 hr = D3DXLoadMeshFromXInMemory(NULL, 0, D3DXMESH_MANAGED,
2378 device, NULL, NULL, NULL, NULL, &mesh);
2379 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2380
2381 hr = D3DXLoadMeshFromXInMemory(NULL, sizeof(simple_xfile) - 1, D3DXMESH_MANAGED,
2382 device, NULL, NULL, NULL, NULL, &mesh);
2383 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2384
2385 hr = D3DXLoadMeshFromXInMemory(simple_xfile, 0, D3DXMESH_MANAGED,
2386 device, NULL, NULL, NULL, NULL, &mesh);
2387 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2388
2389 hr = D3DXLoadMeshFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1, D3DXMESH_MANAGED,
2390 device, NULL, NULL, NULL, NULL, NULL);
2391 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2392
2393 hr = D3DXLoadMeshFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1, D3DXMESH_MANAGED,
2394 NULL, NULL, NULL, NULL, NULL, &mesh);
2395 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2396
2397 hr = D3DXLoadMeshFromXInMemory(empty_xfile, sizeof(empty_xfile) - 1, D3DXMESH_MANAGED,
2398 device, NULL, NULL, NULL, NULL, &mesh);
2399 ok(hr == E_FAIL, "Expected E_FAIL, got %#x\n", hr);
2400
2401 hr = D3DXLoadMeshFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1, D3DXMESH_MANAGED,
2402 device, NULL, NULL, NULL, NULL, &mesh);
2403 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2404 if (SUCCEEDED(hr))
2405 IUnknown_Release(mesh);
2406
2407 test_LoadMeshFromX(device, simple_xfile, simple_vertex_buffer, simple_fvf, simple_index_buffer, default_materials, TRUE);
2408 test_LoadMeshFromX(device, box_xfile, box_vertex_buffer, box_fvf, box_index_buffer, box_materials, TRUE);
2409 test_LoadMeshFromX(device, framed_xfile, merged_vertex_buffer, framed_fvf, merged_index_buffer, default_materials, FALSE);
2410
2411 cleanup:
2412 if (device) IDirect3DDevice9_Release(device);
2413 if (d3d) IDirect3D9_Release(d3d);
2414 if (wnd) DestroyWindow(wnd);
2415 }
2416
2417 static void D3DXCreateBoxTest(void)
2418 {
2419 HRESULT hr;
2420 HWND wnd;
2421 WNDCLASS wc={0};
2422 IDirect3D9* d3d;
2423 IDirect3DDevice9* device;
2424 D3DPRESENT_PARAMETERS d3dpp;
2425 ID3DXMesh* box;
2426 ID3DXBuffer* ppBuffer;
2427 DWORD *buffer;
2428 static const DWORD adjacency[36]=
2429 {6, 9, 1, 2, 10, 0,
2430 1, 9, 3, 4, 10, 2,
2431 3, 8, 5, 7, 11, 4,
2432 0, 11, 7, 5, 8, 6,
2433 7, 4, 9, 2, 0, 8,
2434 1, 3, 11, 5, 6, 10};
2435 unsigned int i;
2436
2437 wc.lpfnWndProc = DefWindowProcA;
2438 wc.lpszClassName = "d3dx9_test_wc";
2439 if (!RegisterClass(&wc))
2440 {
2441 skip("RegisterClass failed\n");
2442 return;
2443 }
2444
2445 wnd = CreateWindow("d3dx9_test_wc", "d3dx9_test",
2446 WS_SYSMENU | WS_POPUP , 0, 0, 640, 480, 0, 0, 0, 0);
2447 ok(wnd != NULL, "Expected to have a window, received NULL\n");
2448 if (!wnd)
2449 {
2450 skip("Couldn't create application window\n");
2451 return;
2452 }
2453
2454 d3d = Direct3DCreate9(D3D_SDK_VERSION);
2455 if (!d3d)
2456 {
2457 skip("Couldn't create IDirect3D9 object\n");
2458 DestroyWindow(wnd);
2459 return;
2460 }
2461
2462 memset(&d3dpp, 0, sizeof(d3dpp));
2463 d3dpp.Windowed = TRUE;
2464 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2465 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, wnd, D3DCREATE_MIXED_VERTEXPROCESSING, &d3dpp, &device);
2466 if (FAILED(hr))
2467 {
2468 skip("Failed to create IDirect3DDevice9 object %#x\n", hr);
2469 IDirect3D9_Release(d3d);
2470 DestroyWindow(wnd);
2471 return;
2472 }
2473
2474 hr = D3DXCreateBox(device,2.0f,20.0f,4.9f,NULL, &ppBuffer);
2475 todo_wine ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2476
2477 hr = D3DXCreateBox(NULL,22.0f,20.0f,4.9f,&box, &ppBuffer);
2478 todo_wine ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2479
2480 hr = D3DXCreateBox(device,-2.0f,20.0f,4.9f,&box, &ppBuffer);
2481 todo_wine ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2482
2483 hr = D3DXCreateBox(device,22.0f,-20.0f,4.9f,&box, &ppBuffer);
2484 todo_wine ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2485
2486 hr = D3DXCreateBox(device,22.0f,20.0f,-4.9f,&box, &ppBuffer);
2487 todo_wine ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2488
2489 ppBuffer = NULL;
2490 hr = D3DXCreateBox(device,10.9f,20.0f,4.9f,&box, &ppBuffer);
2491 todo_wine ok(hr==D3D_OK, "Expected D3D_OK, received %#x\n", hr);
2492
2493 if (FAILED(hr))
2494 {
2495 skip("D3DXCreateBox failed\n");
2496 goto end;
2497 }
2498
2499 buffer = ID3DXBuffer_GetBufferPointer(ppBuffer);
2500 for(i=0; i<36; i++)
2501 todo_wine ok(adjacency[i]==buffer[i], "expected adjacency %d: %#x, received %#x\n",i,adjacency[i], buffer[i]);
2502
2503 box->lpVtbl->Release(box);
2504
2505 end:
2506 IDirect3DDevice9_Release(device);
2507 IDirect3D9_Release(d3d);
2508 if (ppBuffer) ID3DXBuffer_Release(ppBuffer);
2509 DestroyWindow(wnd);
2510 }
2511
2512 struct sincos_table
2513 {
2514 float *sin;
2515 float *cos;
2516 };
2517
2518 static void free_sincos_table(struct sincos_table *sincos_table)
2519 {
2520 HeapFree(GetProcessHeap(), 0, sincos_table->cos);
2521 HeapFree(GetProcessHeap(), 0, sincos_table->sin);
2522 }
2523
2524 /* pre compute sine and cosine tables; caller must free */
2525 static BOOL compute_sincos_table(struct sincos_table *sincos_table, float angle_start, float angle_step, int n)
2526 {
2527 float angle;
2528 int i;
2529
2530 sincos_table->sin = HeapAlloc(GetProcessHeap(), 0, n * sizeof(*sincos_table->sin));
2531 if (!sincos_table->sin)
2532 {
2533 return FALSE;
2534 }
2535 sincos_table->cos = HeapAlloc(GetProcessHeap(), 0, n * sizeof(*sincos_table->cos));
2536 if (!sincos_table->cos)
2537 {
2538 HeapFree(GetProcessHeap(), 0, sincos_table->sin);
2539 return FALSE;
2540 }
2541
2542 angle = angle_start;
2543 for (i = 0; i < n; i++)
2544 {
2545 sincos_table->sin[i] = sin(angle);
2546 sincos_table->cos[i] = cos(angle);
2547 angle += angle_step;
2548 }
2549
2550 return TRUE;
2551 }
2552
2553 static WORD vertex_index(UINT slices, int slice, int stack)
2554 {
2555 return stack*slices+slice+1;
2556 }
2557
2558 /* slices = subdivisions along xy plane, stacks = subdivisions along z axis */
2559 static BOOL compute_sphere(struct mesh *mesh, FLOAT radius, UINT slices, UINT stacks)
2560 {
2561 float theta_step, theta_start;
2562 struct sincos_table theta;
2563 float phi_step, phi_start;
2564 struct sincos_table phi;
2565 DWORD number_of_vertices, number_of_faces;
2566 DWORD vertex, face;
2567 int slice, stack;
2568
2569 /* theta = angle on xy plane wrt x axis */
2570 theta_step = M_PI / stacks;
2571 theta_start = theta_step;
2572
2573 /* phi = angle on xz plane wrt z axis */
2574 phi_step = -2 * M_PI / slices;
2575 phi_start = M_PI / 2;
2576
2577 if (!compute_sincos_table(&theta, theta_start, theta_step, stacks))
2578 {
2579 return FALSE;
2580 }
2581 if (!compute_sincos_table(&phi, phi_start, phi_step, slices))
2582 {
2583 free_sincos_table(&theta);
2584 return FALSE;
2585 }
2586
2587 number_of_vertices = 2 + slices * (stacks-1);
2588 number_of_faces = 2 * slices + (stacks - 2) * (2 * slices);
2589
2590 if (!new_mesh(mesh, number_of_vertices, number_of_faces))
2591 {
2592 free_sincos_table(&phi);
2593 free_sincos_table(&theta);
2594 return FALSE;
2595 }
2596
2597 vertex = 0;
2598 face = 0;
2599
2600 mesh->vertices[vertex].normal.x = 0.0f;
2601 mesh->vertices[vertex].normal.y = 0.0f;
2602 mesh->vertices[vertex].normal.z = 1.0f;
2603 mesh->vertices[vertex].position.x = 0.0f;
2604 mesh->vertices[vertex].position.y = 0.0f;
2605 mesh->vertices[vertex].position.z = radius;
2606 vertex++;
2607
2608 for (stack = 0; stack < stacks - 1; stack++)
2609 {
2610 for (slice = 0; slice < slices; slice++)
2611 {
2612 mesh->vertices[vertex].normal.x = theta.sin[stack] * phi.cos[slice];
2613 mesh->vertices[vertex].normal.y = theta.sin[stack] * phi.sin[slice];
2614 mesh->vertices[vertex].normal.z = theta.cos[stack];
2615 mesh->vertices[vertex].position.x = radius * theta.sin[stack] * phi.cos[slice];
2616 mesh->vertices[vertex].position.y = radius * theta.sin[stack] * phi.sin[slice];
2617 mesh->vertices[vertex].position.z = radius * theta.cos[stack];
2618 vertex++;
2619
2620 if (slice > 0)
2621 {
2622 if (stack == 0)
2623 {
2624 /* top stack is triangle fan */
2625 mesh->faces[face][0] = 0;
2626 mesh->faces[face][1] = slice + 1;
2627 mesh->faces[face][2] = slice;
2628 face++;
2629 }
2630 else
2631 {
2632 /* stacks in between top and bottom are quad strips */
2633 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
2634 mesh->faces[face][1] = vertex_index(slices, slice, stack-1);
2635 mesh->faces[face][2] = vertex_index(slices, slice-1, stack);
2636 face++;
2637
2638 mesh->faces[face][0] = vertex_index(slices, slice, stack-1);
2639 mesh->faces[face][1] = vertex_index(slices, slice, stack);
2640 mesh->faces[face][2] = vertex_index(slices, slice-1, stack);
2641 face++;
2642 }
2643 }
2644 }
2645
2646 if (stack == 0)
2647 {
2648 mesh->faces[face][0] = 0;
2649 mesh->faces[face][1] = 1;
2650 mesh->faces[face][2] = slice;
2651 face++;
2652 }
2653 else
2654 {
2655 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
2656 mesh->faces[face][1] = vertex_index(slices, 0, stack-1);
2657 mesh->faces[face][2] = vertex_index(slices, slice-1, stack);
2658 face++;
2659
2660 mesh->faces[face][0] = vertex_index(slices, 0, stack-1);
2661 mesh->faces[face][1] = vertex_index(slices, 0, stack);
2662 mesh->faces[face][2] = vertex_index(slices, slice-1, stack);
2663 face++;
2664 }
2665 }
2666
2667 mesh->vertices[vertex].position.x = 0.0f;
2668 mesh->vertices[vertex].position.y = 0.0f;
2669 mesh->vertices[vertex].position.z = -radius;
2670 mesh->vertices[vertex].normal.x = 0.0f;
2671 mesh->vertices[vertex].normal.y = 0.0f;
2672 mesh->vertices[vertex].normal.z = -1.0f;
2673
2674 /* bottom stack is triangle fan */
2675 for (slice = 1; slice < slices; slice++)
2676 {
2677 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
2678 mesh->faces[face][1] = vertex_index(slices, slice, stack-1);
2679 mesh->faces[face][2] = vertex;
2680 face++;
2681 }
2682
2683 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
2684 mesh->faces[face][1] = vertex_index(slices, 0, stack-1);
2685 mesh->faces[face][2] = vertex;
2686
2687 free_sincos_table(&phi);
2688 free_sincos_table(&theta);
2689
2690 return TRUE;
2691 }
2692
2693 static void test_sphere(IDirect3DDevice9 *device, FLOAT radius, UINT slices, UINT stacks)
2694 {
2695 HRESULT hr;
2696 ID3DXMesh *sphere;
2697 struct mesh mesh;
2698 char name[256];
2699
2700 hr = D3DXCreateSphere(device, radius, slices, stacks, &sphere, NULL);
2701 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
2702 if (hr != D3D_OK)
2703 {
2704 skip("Couldn't create sphere\n");
2705 return;
2706 }
2707
2708 if (!compute_sphere(&mesh, radius, slices, stacks))
2709 {
2710 skip("Couldn't create mesh\n");
2711 sphere->lpVtbl->Release(sphere);
2712 return;
2713 }
2714
2715 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
2716
2717 sprintf(name, "sphere (%g, %u, %u)", radius, slices, stacks);
2718 compare_mesh(name, sphere, &mesh);
2719
2720 free_mesh(&mesh);
2721
2722 sphere->lpVtbl->Release(sphere);
2723 }
2724
2725 static void D3DXCreateSphereTest(void)
2726 {
2727 HRESULT hr;
2728 HWND wnd;
2729 IDirect3D9* d3d;
2730 IDirect3DDevice9* device;
2731 D3DPRESENT_PARAMETERS d3dpp;
2732 ID3DXMesh* sphere = NULL;
2733
2734 hr = D3DXCreateSphere(NULL, 0.0f, 0, 0, NULL, NULL);
2735 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
2736
2737 hr = D3DXCreateSphere(NULL, 0.1f, 0, 0, NULL, NULL);
2738 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
2739
2740 hr = D3DXCreateSphere(NULL, 0.0f, 1, 0, NULL, NULL);
2741 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
2742
2743 hr = D3DXCreateSphere(NULL, 0.0f, 0, 1, NULL, NULL);
2744 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
2745
2746 wnd = CreateWindow("static", "d3dx9_test", 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL);
2747 d3d = Direct3DCreate9(D3D_SDK_VERSION);
2748 if (!wnd)
2749 {
2750 skip("Couldn't create application window\n");
2751 return;
2752 }
2753 if (!d3d)
2754 {
2755 skip("Couldn't create IDirect3D9 object\n");
2756 DestroyWindow(wnd);
2757 return;
2758 }
2759
2760 ZeroMemory(&d3dpp, sizeof(d3dpp));
2761 d3dpp.Windowed = TRUE;
2762 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2763 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, wnd, D3DCREATE_MIXED_VERTEXPROCESSING, &d3dpp, &device);
2764 if (FAILED(hr))
2765 {
2766 skip("Failed to create IDirect3DDevice9 object %#x\n", hr);
2767 IDirect3D9_Release(d3d);
2768 DestroyWindow(wnd);
2769 return;
2770 }
2771
2772 hr = D3DXCreateSphere(device, 1.0f, 1, 1, &sphere, NULL);
2773 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
2774
2775 hr = D3DXCreateSphere(device, 1.0f, 2, 1, &sphere, NULL);
2776 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
2777
2778 hr = D3DXCreateSphere(device, 1.0f, 1, 2, &sphere, NULL);
2779 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
2780
2781 hr = D3DXCreateSphere(device, -0.1f, 1, 2, &sphere, NULL);
2782 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
2783
2784 test_sphere(device, 0.0f, 2, 2);
2785 test_sphere(device, 1.0f, 2, 2);
2786 test_sphere(device, 1.0f, 3, 2);
2787 test_sphere(device, 1.0f, 4, 4);
2788 test_sphere(device, 1.0f, 3, 4);
2789 test_sphere(device, 5.0f, 6, 7);
2790 test_sphere(device, 10.0f, 11, 12);
2791
2792 IDirect3DDevice9_Release(device);
2793 IDirect3D9_Release(d3d);
2794 DestroyWindow(wnd);
2795 }
2796
2797 static BOOL compute_cylinder(struct mesh *mesh, FLOAT radius1, FLOAT radius2, FLOAT length, UINT slices, UINT stacks)
2798 {
2799 float theta_step, theta_start;
2800 struct sincos_table theta;
2801 FLOAT delta_radius, radius, radius_step;
2802 FLOAT z, z_step, z_normal;
2803 DWORD number_of_vertices, number_of_faces;
2804 DWORD vertex, face;
2805 int slice, stack;
2806
2807 /* theta = angle on xy plane wrt x axis */
2808 theta_step = -2 * M_PI / slices;
2809 theta_start = M_PI / 2;
2810
2811 if (!compute_sincos_table(&theta, theta_start, theta_step, slices))
2812 {
2813 return FALSE;
2814 }
2815
2816 number_of_vertices = 2 + (slices * (3 + stacks));
2817 number_of_faces = 2 * slices + stacks * (2 * slices);
2818
2819 if (!new_mesh(mesh, number_of_vertices, number_of_faces))
2820 {
2821 free_sincos_table(&theta);
2822 return FALSE;
2823 }
2824
2825 vertex = 0;
2826 face = 0;
2827
2828 delta_radius = radius1 - radius2;
2829 radius = radius1;
2830 radius_step = delta_radius / stacks;
2831
2832 z = -length / 2;
2833 z_step = length / stacks;
2834 z_normal = delta_radius / length;
2835 if (isnan(z_normal))
2836 {
2837 z_normal = 0.0f;
2838 }
2839
2840 mesh->vertices[vertex].normal.x = 0.0f;
2841 mesh->vertices[vertex].normal.y = 0.0f;
2842 mesh->vertices[vertex].normal.z = -1.0f;
2843 mesh->vertices[vertex].position.x = 0.0f;
2844 mesh->vertices[vertex].position.y = 0.0f;
2845 mesh->vertices[vertex++].position.z = z;
2846
2847 for (slice = 0; slice < slices; slice++, vertex++)
2848 {
2849 mesh->vertices[vertex].normal.x = 0.0f;
2850 mesh->vertices[vertex].normal.y = 0.0f;
2851 mesh->vertices[vertex].normal.z = -1.0f;
2852 mesh->vertices[vertex].position.x = radius * theta.cos[slice];
2853 mesh->vertices[vertex].position.y = radius * theta.sin[slice];
2854 mesh->vertices[vertex].position.z = z;
2855
2856 if (slice > 0)
2857 {
2858 mesh->faces[face][0] = 0;
2859 mesh->faces[face][1] = slice;
2860 mesh->faces[face++][2] = slice + 1;
2861 }
2862 }
2863
2864 mesh->faces[face][0] = 0;
2865 mesh->faces[face][1] = slice;
2866 mesh->faces[face++][2] = 1;
2867
2868 for (stack = 1; stack <= stacks+1; stack++)
2869 {
2870 for (slice = 0; slice < slices; slice++, vertex++)
2871 {
2872 mesh->vertices[vertex].normal.x = theta.cos[slice];
2873 mesh->vertices[vertex].normal.y = theta.sin[slice];
2874 mesh->vertices[vertex].normal.z = z_normal;
2875 D3DXVec3Normalize(&mesh->vertices[vertex].normal, &mesh->vertices[vertex].normal);
2876 mesh->vertices[vertex].position.x = radius * theta.cos[slice];
2877 mesh->vertices[vertex].position.y = radius * theta.sin[slice];
2878 mesh->vertices[vertex].position.z = z;
2879
2880 if (stack > 1 && slice > 0)
2881 {
2882 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
2883 mesh->faces[face][1] = vertex_index(slices, slice-1, stack);
2884 mesh->faces[face++][2] = vertex_index(slices, slice, stack-1);
2885
2886 mesh->faces[face][0] = vertex_index(slices, slice, stack-1);
2887 mesh->faces[face][1] = vertex_index(slices, slice-1, stack);
2888 mesh->faces[face++][2] = vertex_index(slices, slice, stack);
2889 }
2890 }
2891
2892 if (stack > 1)
2893 {
2894 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
2895 mesh->faces[face][1] = vertex_index(slices, slice-1, stack);
2896 mesh->faces[face++][2] = vertex_index(slices, 0, stack-1);
2897
2898 mesh->faces[face][0] = vertex_index(slices, 0, stack-1);
2899 mesh->faces[face][1] = vertex_index(slices, slice-1, stack);
2900 mesh->faces[face++][2] = vertex_index(slices, 0, stack);
2901 }
2902
2903 if (stack < stacks + 1)
2904 {
2905 z += z_step;
2906 radius -= radius_step;
2907 }
2908 }
2909
2910 for (slice = 0; slice < slices; slice++, vertex++)
2911 {
2912 mesh->vertices[vertex].normal.x = 0.0f;
2913 mesh->vertices[vertex].normal.y = 0.0f;
2914 mesh->vertices[vertex].normal.z = 1.0f;
2915 mesh->vertices[vertex].position.x = radius * theta.cos[slice];
2916 mesh->vertices[vertex].position.y = radius * theta.sin[slice];
2917 mesh->vertices[vertex].position.z = z;
2918
2919 if (slice > 0)
2920 {
2921 mesh->faces[face][0] = vertex_index(slices, slice-1, stack);
2922 mesh->faces[face][1] = number_of_vertices - 1;
2923 mesh->faces[face++][2] = vertex_index(slices, slice, stack);
2924 }
2925 }
2926
2927 mesh->vertices[vertex].position.x = 0.0f;
2928 mesh->vertices[vertex].position.y = 0.0f;
2929 mesh->vertices[vertex].position.z = z;
2930 mesh->vertices[vertex].normal.x = 0.0f;
2931 mesh->vertices[vertex].normal.y = 0.0f;
2932 mesh->vertices[vertex].normal.z = 1.0f;
2933
2934 mesh->faces[face][0] = vertex_index(slices, slice-1, stack);
2935 mesh->faces[face][1] = number_of_vertices - 1;
2936 mesh->faces[face][2] = vertex_index(slices, 0, stack);
2937
2938 free_sincos_table(&theta);
2939
2940 return TRUE;
2941 }
2942
2943 static void test_cylinder(IDirect3DDevice9 *device, FLOAT radius1, FLOAT radius2, FLOAT length, UINT slices, UINT stacks)
2944 {
2945 HRESULT hr;
2946 ID3DXMesh *cylinder;
2947 struct mesh mesh;
2948 char name[256];
2949
2950 hr = D3DXCreateCylinder(device, radius1, radius2, length, slices, stacks, &cylinder, NULL);
2951 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
2952 if (hr != D3D_OK)
2953 {
2954 skip("Couldn't create cylinder\n");
2955 return;
2956 }
2957
2958 if (!compute_cylinder(&mesh, radius1, radius2, length, slices, stacks))
2959 {
2960 skip("Couldn't create mesh\n");
2961 cylinder->lpVtbl->Release(cylinder);
2962 return;
2963 }
2964
2965 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
2966
2967 sprintf(name, "cylinder (%g, %g, %g, %u, %u)", radius1, radius2, length, slices, stacks);
2968 compare_mesh(name, cylinder, &mesh);
2969
2970 free_mesh(&mesh);
2971
2972 cylinder->lpVtbl->Release(cylinder);
2973 }
2974
2975 static void D3DXCreateCylinderTest(void)
2976 {
2977 HRESULT hr;
2978 HWND wnd;
2979 IDirect3D9* d3d;
2980 IDirect3DDevice9* device;
2981 D3DPRESENT_PARAMETERS d3dpp;
2982 ID3DXMesh* cylinder = NULL;
2983
2984 hr = D3DXCreateCylinder(NULL, 0.0f, 0.0f, 0.0f, 0, 0, NULL, NULL);
2985 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
2986
2987 hr = D3DXCreateCylinder(NULL, 1.0f, 1.0f, 1.0f, 2, 1, &cylinder, NULL);
2988 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
2989
2990 wnd = CreateWindow("static", "d3dx9_test", 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL);
2991 d3d = Direct3DCreate9(D3D_SDK_VERSION);
2992 if (!wnd)
2993 {
2994 skip("Couldn't create application window\n");
2995 return;
2996 }
2997 if (!d3d)
2998 {
2999 skip("Couldn't create IDirect3D9 object\n");
3000 DestroyWindow(wnd);
3001 return;
3002 }
3003
3004 ZeroMemory(&d3dpp, sizeof(d3dpp));
3005 d3dpp.Windowed = TRUE;
3006 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
3007 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, wnd, D3DCREATE_MIXED_VERTEXPROCESSING, &d3dpp, &device);
3008 if (FAILED(hr))
3009 {
3010 skip("Failed to create IDirect3DDevice9 object %#x\n", hr);
3011 IDirect3D9_Release(d3d);
3012 DestroyWindow(wnd);
3013 return;
3014 }
3015
3016 hr = D3DXCreateCylinder(device, -0.1f, 1.0f, 1.0f, 2, 1, &cylinder, NULL);
3017 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3018
3019 hr = D3DXCreateCylinder(device, 0.0f, 1.0f, 1.0f, 2, 1, &cylinder, NULL);
3020 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n",hr);
3021
3022 if (SUCCEEDED(hr) && cylinder)
3023 {
3024 cylinder->lpVtbl->Release(cylinder);
3025 }
3026
3027 hr = D3DXCreateCylinder(device, 1.0f, -0.1f, 1.0f, 2, 1, &cylinder, NULL);
3028 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3029
3030 hr = D3DXCreateCylinder(device, 1.0f, 0.0f, 1.0f, 2, 1, &cylinder, NULL);
3031 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n",hr);
3032
3033 if (SUCCEEDED(hr) && cylinder)
3034 {
3035 cylinder->lpVtbl->Release(cylinder);
3036 }
3037
3038 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, -0.1f, 2, 1, &cylinder, NULL);
3039 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3040
3041 /* Test with length == 0.0f succeeds */
3042 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, 0.0f, 2, 1, &cylinder, NULL);
3043 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n",hr);
3044
3045 if (SUCCEEDED(hr) && cylinder)
3046 {
3047 cylinder->lpVtbl->Release(cylinder);
3048 }
3049
3050 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, 1.0f, 1, 1, &cylinder, NULL);
3051 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3052
3053 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, 1.0f, 2, 0, &cylinder, NULL);
3054 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3055
3056 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, 1.0f, 2, 1, NULL, NULL);
3057 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3058
3059 test_cylinder(device, 0.0f, 0.0f, 0.0f, 2, 1);
3060 test_cylinder(device, 1.0f, 1.0f, 1.0f, 2, 1);
3061 test_cylinder(device, 1.0f, 1.0f, 2.0f, 3, 4);
3062 test_cylinder(device, 3.0f, 2.0f, 4.0f, 3, 4);
3063 test_cylinder(device, 2.0f, 3.0f, 4.0f, 3, 4);
3064 test_cylinder(device, 3.0f, 4.0f, 5.0f, 11, 20);
3065
3066 IDirect3DDevice9_Release(device);
3067 IDirect3D9_Release(d3d);
3068 DestroyWindow(wnd);
3069 }
3070
3071 struct dynamic_array
3072 {
3073 int count, capacity;
3074 void *items;
3075 };
3076
3077 enum pointtype {
3078 POINTTYPE_CURVE = 0,
3079 POINTTYPE_CORNER,
3080 POINTTYPE_CURVE_START,
3081 POINTTYPE_CURVE_END,
3082 POINTTYPE_CURVE_MIDDLE,
3083 };
3084
3085 struct point2d
3086 {
3087 D3DXVECTOR2 pos;
3088 enum pointtype corner;
3089 };
3090
3091 /* is a dynamic_array */
3092 struct outline
3093 {
3094 int count, capacity;
3095 struct point2d *items;
3096 };
3097
3098 /* is a dynamic_array */
3099 struct outline_array
3100 {
3101 int count, capacity;
3102 struct outline *items;
3103 };
3104
3105 struct glyphinfo
3106 {
3107 struct outline_array outlines;
3108 float offset_x;
3109 };
3110
3111 static BOOL reserve(struct dynamic_array *array, int count, int itemsize)
3112 {
3113 if (count > array->capacity) {
3114 void *new_buffer;
3115 int new_capacity;
3116 if (array->items && array->capacity) {
3117 new_capacity = max(array->capacity * 2, count);
3118 new_buffer = HeapReAlloc(GetProcessHeap(), 0, array->items, new_capacity * itemsize);
3119 } else {
3120 new_capacity = max(16, count);
3121 new_buffer = HeapAlloc(GetProcessHeap(), 0, new_capacity * itemsize);
3122 }
3123 if (!new_buffer)
3124 return FALSE;
3125 array->items = new_buffer;
3126 array->capacity = new_capacity;
3127 }
3128 return TRUE;
3129 }
3130
3131 static struct point2d *add_point(struct outline *array)
3132 {
3133 struct point2d *item;
3134
3135 if (!reserve((struct dynamic_array *)array, array->count + 1, sizeof(array->items[0])))
3136 return NULL;
3137
3138 item = &array->items[array->count++];
3139 ZeroMemory(item, sizeof(*item));
3140 return item;
3141 }
3142
3143 static struct outline *add_outline(struct outline_array *array)
3144 {
3145 struct outline *item;
3146
3147 if (!reserve((struct dynamic_array *)array, array->count + 1, sizeof(array->items[0])))
3148 return NULL;
3149
3150 item = &array->items[array->count++];
3151 ZeroMemory(item, sizeof(*item));
3152 return item;
3153 }
3154
3155 static inline D3DXVECTOR2 *convert_fixed_to_float(POINTFX *pt, int count, float emsquare)
3156 {
3157 D3DXVECTOR2 *ret = (D3DXVECTOR2*)pt;
3158 while (count--) {
3159 D3DXVECTOR2 *pt_flt = (D3DXVECTOR2*)pt;
3160 pt_flt->x = (pt->x.value + pt->x.fract / (float)0x10000) / emsquare;
3161 pt_flt->y = (pt->y.value + pt->y.fract / (float)0x10000) / emsquare;
3162 pt++;
3163 }
3164 return ret;
3165 }
3166
3167 static HRESULT add_bezier_points(struct outline *outline, const D3DXVECTOR2 *p1,
3168 const D3DXVECTOR2 *p2, const D3DXVECTOR2 *p3,
3169 float max_deviation)
3170 {
3171 D3DXVECTOR2 split1 = {0, 0}, split2 = {0, 0}, middle, vec;
3172 float deviation;
3173
3174 D3DXVec2Scale(&split1, D3DXVec2Add(&split1, p1, p2), 0.5f);
3175 D3DXVec2Scale(&split2, D3DXVec2Add(&split2, p2, p3), 0.5f);
3176 D3DXVec2Scale(&middle, D3DXVec2Add(&middle, &split1, &split2), 0.5f);
3177
3178 deviation = D3DXVec2Length(D3DXVec2Subtract(&vec, &middle, p2));
3179 if (deviation < max_deviation) {
3180 struct point2d *pt = add_point(outline);
3181 if (!pt) return E_OUTOFMEMORY;
3182 pt->pos = *p2;
3183 pt->corner = POINTTYPE_CURVE;
3184 /* the end point is omitted because the end line merges into the next segment of
3185 * the split bezier curve, and the end of the split bezier curve is added outside
3186 * this recursive function. */
3187 } else {
3188 HRESULT hr = add_bezier_points(outline, p1, &split1, &middle, max_deviation);
3189 if (hr != S_OK) return hr;
3190 hr = add_bezier_points(outline, &middle, &split2, p3, max_deviation);
3191 if (hr != S_OK) return hr;
3192 }
3193
3194 return S_OK;
3195 }
3196
3197 static inline BOOL is_direction_similar(D3DXVECTOR2 *dir1, D3DXVECTOR2 *dir2, float cos_theta)
3198 {
3199 /* dot product = cos(theta) */
3200 return D3DXVec2Dot(dir1, dir2) > cos_theta;
3201 }
3202
3203 static inline D3DXVECTOR2 *unit_vec2(D3DXVECTOR2 *dir, const D3DXVECTOR2 *pt1, const D3DXVECTOR2 *pt2)
3204 {
3205 return D3DXVec2Normalize(D3DXVec2Subtract(dir, pt2, pt1), dir);
3206 }
3207
3208 static BOOL attempt_line_merge(struct outline *outline,
3209 int pt_index,
3210 const D3DXVECTOR2 *nextpt,
3211 BOOL to_curve)
3212 {
3213 D3DXVECTOR2 curdir, lastdir;
3214 struct point2d *prevpt, *pt;
3215 BOOL ret = FALSE;
3216 const float cos_half = cos(D3DXToRadian(0.5f));
3217
3218 pt = &outline->items[pt_index];
3219 pt_index = (pt_index - 1 + outline->count) % outline->count;
3220 prevpt = &outline->items[pt_index];
3221
3222 if (to_curve)
3223 pt->corner = pt->corner != POINTTYPE_CORNER ? POINTTYPE_CURVE_MIDDLE : POINTTYPE_CURVE_START;
3224
3225 if (outline->count < 2)
3226 return FALSE;
3227
3228 /* remove last point if the next line continues the last line */
3229 unit_vec2(&lastdir, &prevpt->pos, &pt->pos);
3230 unit_vec2(&curdir, &pt->pos, nextpt);
3231 if (is_direction_similar(&lastdir, &curdir, cos_half))
3232 {
3233 outline->count--;
3234 if (pt->corner == POINTTYPE_CURVE_END)
3235 prevpt->corner = pt->corner;
3236 if (prevpt->corner == POINTTYPE_CURVE_END && to_curve)
3237 prevpt->corner = POINTTYPE_CURVE_MIDDLE;
3238 pt = prevpt;
3239
3240 ret = TRUE;
3241 if (outline->count < 2)
3242 return ret;
3243
3244 pt_index = (pt_index - 1 + outline->count) % outline->count;
3245 prevpt = &outline->items[pt_index];
3246 unit_vec2(&lastdir, &prevpt->pos, &pt->pos);
3247 unit_vec2(&curdir, &pt->pos, nextpt);
3248 }
3249 return ret;
3250 }
3251
3252 static HRESULT create_outline(struct glyphinfo *glyph, void *raw_outline, int datasize,
3253 float max_deviation, float emsquare)
3254 {
3255 const float cos_45 = cos(D3DXToRadian(45.0f));
3256 const float cos_90 = cos(D3DXToRadian(90.0f));
3257 TTPOLYGONHEADER *header = (TTPOLYGONHEADER *)raw_outline;
3258
3259 while ((char *)header < (char *)raw_outline + datasize)
3260 {
3261 TTPOLYCURVE *curve = (TTPOLYCURVE *)(header + 1);
3262 struct point2d *lastpt, *pt;
3263 D3DXVECTOR2 lastdir;
3264 D3DXVECTOR2 *pt_flt;
3265 int j;
3266 struct outline *outline = add_outline(&glyph->outlines);
3267
3268 if (!outline)
3269 return E_OUTOFMEMORY;
3270
3271 pt = add_point(outline);
3272 if (!pt)
3273 return E_OUTOFMEMORY;
3274 pt_flt = convert_fixed_to_float(&header->pfxStart, 1, emsquare);
3275 pt->pos = *pt_flt;
3276 pt->corner = POINTTYPE_CORNER;
3277
3278 if (header->dwType != TT_POLYGON_TYPE)
3279 trace("Unknown header type %d\n", header->dwType);
3280
3281 while ((char *)curve < (char *)header + header->cb)
3282 {
3283 D3DXVECTOR2 bezier_start = outline->items[outline->count - 1].pos;
3284 BOOL to_curve = curve->wType != TT_PRIM_LINE && curve->cpfx > 1;
3285
3286 if (!curve->cpfx) {
3287 curve = (TTPOLYCURVE *)&curve->apfx[curve->cpfx];
3288 continue;
3289 }
3290
3291 pt_flt = convert_fixed_to_float(curve->apfx, curve->cpfx, emsquare);
3292
3293 attempt_line_merge(outline, outline->count - 1, &pt_flt[0], to_curve);
3294
3295 if (to_curve)
3296 {
3297 HRESULT hr;
3298 int count = curve->cpfx;
3299 j = 0;
3300
3301 while (count > 2)
3302 {
3303 D3DXVECTOR2 bezier_end;
3304
3305 D3DXVec2Scale(&bezier_end, D3DXVec2Add(&bezier_end, &pt_flt[j], &pt_flt[j+1]), 0.5f);
3306 hr = add_bezier_points(outline, &bezier_start, &pt_flt[j], &bezier_end, max_deviation);
3307 if (hr != S_OK)
3308 return hr;
3309 bezier_start = bezier_end;
3310 count--;
3311 j++;
3312 }
3313 hr = add_bezier_points(outline, &bezier_start, &pt_flt[j], &pt_flt[j+1], max_deviation);
3314 if (hr != S_OK)
3315 return hr;
3316
3317 pt = add_point(outline);
3318 if (!pt)
3319 return E_OUTOFMEMORY;
3320 j++;
3321 pt->pos = pt_flt[j];
3322 pt->corner = POINTTYPE_CURVE_END;
3323 } else {
3324 for (j = 0; j < curve->cpfx; j++)
3325 {
3326 pt = add_point(outline);
3327 if (!pt)
3328 return E_OUTOFMEMORY;
3329 pt->pos = pt_flt[j];
3330 pt->corner = POINTTYPE_CORNER;
3331 }
3332 }
3333
3334 curve = (TTPOLYCURVE *)&curve->apfx[curve->cpfx];
3335 }
3336
3337 /* remove last point if the next line continues the last line */
3338 if (outline->count >= 3) {
3339 BOOL to_curve;
3340
3341 lastpt = &outline->items[outline->count - 1];
3342 pt = &outline->items[0];
3343 if (pt->pos.x == lastpt->pos.x && pt->pos.y == lastpt->pos.y) {
3344 if (lastpt->corner == POINTTYPE_CURVE_END)
3345 {
3346 if (pt->corner == POINTTYPE_CURVE_START)
3347 pt->corner = POINTTYPE_CURVE_MIDDLE;
3348 else
3349 pt->corner = POINTTYPE_CURVE_END;
3350 }
3351 outline->count--;
3352 lastpt = &outline->items[outline->count - 1];
3353 } else {
3354 /* outline closed with a line from end to start point */
3355 attempt_line_merge(outline, outline->count - 1, &pt->pos, FALSE);
3356 }
3357 lastpt = &outline->items[0];
3358 to_curve = lastpt->corner != POINTTYPE_CORNER && lastpt->corner != POINTTYPE_CURVE_END;
3359 if (lastpt->corner == POINTTYPE_CURVE_START)
3360 lastpt->corner = POINTTYPE_CORNER;
3361 pt = &outline->items[1];
3362 if (attempt_line_merge(outline, 0, &pt->pos, to_curve))
3363 *lastpt = outline->items[outline->count];
3364 }
3365
3366 lastpt = &outline->items[outline->count - 1];
3367 pt = &outline->items[0];
3368 unit_vec2(&lastdir, &lastpt->pos, &pt->pos);
3369 for (j = 0; j < outline->count; j++)
3370 {
3371 D3DXVECTOR2 curdir;
3372
3373 lastpt = pt;
3374 pt = &outline->items[(j + 1) % outline->count];
3375 unit_vec2(&curdir, &lastpt->pos, &pt->pos);
3376
3377 switch (lastpt->corner)
3378 {
3379 case POINTTYPE_CURVE_START:
3380 case POINTTYPE_CURVE_END:
3381 if (!is_direction_similar(&lastdir, &curdir, cos_45))
3382 lastpt->corner = POINTTYPE_CORNER;
3383 break;
3384 case POINTTYPE_CURVE_MIDDLE:
3385 if (!is_direction_similar(&lastdir, &curdir, cos_90))
3386 lastpt->corner = POINTTYPE_CORNER;
3387 else
3388 lastpt->corner = POINTTYPE_CURVE;
3389 break;
3390 default:
3391 break;
3392 }
3393 lastdir = curdir;
3394 }
3395
3396 header = (TTPOLYGONHEADER *)((char *)header + header->cb);
3397 }
3398 return S_OK;
3399 }
3400
3401 static BOOL compute_text_mesh(struct mesh *mesh, HDC hdc, LPCSTR text, FLOAT deviation, FLOAT extrusion, FLOAT otmEMSquare)
3402 {
3403 HRESULT hr = E_FAIL;
3404 DWORD nb_vertices, nb_faces;
3405 DWORD nb_corners, nb_outline_points;
3406 int textlen = 0;
3407 float offset_x;
3408 char *raw_outline = NULL;
3409 struct glyphinfo *glyphs = NULL;
3410 GLYPHMETRICS gm;
3411 int i;
3412 struct vertex *vertex_ptr;
3413 face *face_ptr;
3414
3415 if (deviation == 0.0f)
3416 deviation = 1.0f / otmEMSquare;
3417
3418 textlen = strlen(text);
3419 glyphs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, textlen * sizeof(*glyphs));
3420 if (!glyphs) {
3421 hr = E_OUTOFMEMORY;
3422 goto error;
3423 }
3424
3425 offset_x = 0.0f;
3426 for (i = 0; i < textlen; i++)
3427 {
3428 /* get outline points from data returned from GetGlyphOutline */
3429 const MAT2 identity = {{0, 1}, {0, 0}, {0, 0}, {0, 1}};
3430 int datasize;
3431
3432 glyphs[i].offset_x = offset_x;
3433
3434 datasize = GetGlyphOutline(hdc, text[i], GGO_NATIVE, &gm, 0, NULL, &identity);
3435 if (datasize < 0) {
3436 hr = E_FAIL;
3437 goto error;
3438 }
3439 HeapFree(GetProcessHeap(), 0, raw_outline);
3440 raw_outline = HeapAlloc(GetProcessHeap(), 0, datasize);
3441 if (!glyphs) {
3442 hr = E_OUTOFMEMORY;
3443 goto error;
3444 }
3445 datasize = GetGlyphOutline(hdc, text[i], GGO_NATIVE, &gm, datasize, raw_outline, &identity);
3446
3447 create_outline(&glyphs[i], raw_outline, datasize, deviation, otmEMSquare);
3448
3449 offset_x += gm.gmCellIncX / (float)otmEMSquare;
3450 }
3451
3452 /* corner points need an extra vertex for the different side faces normals */
3453 nb_corners = 0;
3454 nb_outline_points = 0;
3455 for (i = 0; i < textlen; i++)
3456 {
3457 int j;
3458 for (j = 0; j < glyphs[i].outlines.count; j++)
3459 {
3460 int k;
3461 struct outline *outline = &glyphs[i].outlines.items[j];
3462 nb_outline_points += outline->count;
3463 nb_corners++; /* first outline point always repeated as a corner */
3464 for (k = 1; k < outline->count; k++)
3465 if (outline->items[k].corner)
3466 nb_corners++;
3467 }
3468 }
3469
3470 nb_vertices = (nb_outline_points + nb_corners) * 2 + textlen;
3471 nb_faces = nb_outline_points * 2;
3472
3473 if (!new_mesh(mesh, nb_vertices, nb_faces))
3474 goto error;
3475
3476 /* convert 2D vertices and faces into 3D mesh */
3477 vertex_ptr = mesh->vertices;
3478 face_ptr = mesh->faces;
3479 for (i = 0; i < textlen; i++)
3480 {
3481 int j;
3482
3483 /* side vertices and faces */
3484 for (j = 0; j < glyphs[i].outlines.count; j++)
3485 {
3486 struct vertex *outline_vertices = vertex_ptr;
3487 struct outline *outline = &glyphs[i].outlines.items[j];
3488 int k;
3489 struct point2d *prevpt = &outline->items[outline->count - 1];
3490 struct point2d *pt = &outline->items[0];
3491
3492 for (k = 1; k <= outline->count; k++)
3493 {
3494 struct vertex vtx;
3495 struct point2d *nextpt = &outline->items[k % outline->count];
3496 WORD vtx_idx = vertex_ptr - mesh->vertices;
3497 D3DXVECTOR2 vec;
3498
3499 if (pt->corner == POINTTYPE_CURVE_START)
3500 D3DXVec2Subtract(&vec, &pt->pos, &prevpt->pos);
3501 else if (pt->corner)
3502 D3DXVec2Subtract(&vec, &nextpt->pos, &pt->pos);
3503 else
3504 D3DXVec2Subtract(&vec, &nextpt->pos, &prevpt->pos);
3505 D3DXVec2Normalize(&vec, &vec);
3506 vtx.normal.x = -vec.y;
3507 vtx.normal.y = vec.x;
3508 vtx.normal.z = 0;
3509
3510 vtx.position.x = pt->pos.x + glyphs[i].offset_x;
3511 vtx.position.y = pt->pos.y;
3512 vtx.position.z = 0;
3513 *vertex_ptr++ = vtx;
3514
3515 vtx.position.z = -extrusion;
3516 *vertex_ptr++ = vtx;
3517
3518 vtx.position.x = nextpt->pos.x + glyphs[i].offset_x;
3519 vtx.position.y = nextpt->pos.y;
3520 if (pt->corner && nextpt->corner && nextpt->corner != POINTTYPE_CURVE_END) {
3521 vtx.position.z = -extrusion;
3522 *vertex_ptr++ = vtx;
3523 vtx.position.z = 0;
3524 *vertex_ptr++ = vtx;
3525
3526 (*face_ptr)[0] = vtx_idx;
3527 (*face_ptr)[1] = vtx_idx + 2;
3528 (*face_ptr)[2] = vtx_idx + 1;
3529 face_ptr++;
3530
3531 (*face_ptr)[0] = vtx_idx;
3532 (*face_ptr)[1] = vtx_idx + 3;
3533 (*face_ptr)[2] = vtx_idx + 2;
3534 face_ptr++;
3535 } else {
3536 if (nextpt->corner) {
3537 if (nextpt->corner == POINTTYPE_CURVE_END) {
3538 struct point2d *nextpt2 = &outline->items[(k + 1) % outline->count];
3539 D3DXVec2Subtract(&vec, &nextpt2->pos, &nextpt->pos);
3540 } else {
3541 D3DXVec2Subtract(&vec, &nextpt->pos, &pt->pos);
3542 }
3543 D3DXVec2Normalize(&vec, &vec);
3544 vtx.normal.x = -vec.y;
3545 vtx.normal.y = vec.x;
3546
3547 vtx.position.z = 0;
3548 *vertex_ptr++ = vtx;
3549 vtx.position.z = -extrusion;
3550 *vertex_ptr++ = vtx;
3551 }
3552
3553 (*face_ptr)[0] = vtx_idx;
3554 (*face_ptr)[1] = vtx_idx + 3;
3555 (*face_ptr)[2] = vtx_idx + 1;
3556 face_ptr++;
3557
3558 (*face_ptr)[0] = vtx_idx;
3559 (*face_ptr)[1] = vtx_idx + 2;
3560 (*face_ptr)[2] = vtx_idx + 3;
3561 face_ptr++;
3562 }
3563
3564 prevpt = pt;
3565 pt = nextpt;
3566 }
3567 if (!pt->corner) {
3568 *vertex_ptr++ = *outline_vertices++;
3569 *vertex_ptr++ = *outline_vertices++;
3570 }
3571 }
3572
3573 /* FIXME: compute expected faces */
3574 /* Add placeholder to separate glyph outlines */
3575 vertex_ptr->position.x = 0;
3576 vertex_ptr->position.y = 0;
3577 vertex_ptr->position.z = 0;
3578 vertex_ptr->normal.x = 0;
3579 vertex_ptr->normal.y = 0;
3580 vertex_ptr->normal.z = 1;
3581 vertex_ptr++;
3582 }
3583
3584 hr = D3D_OK;
3585 error:
3586 if (glyphs) {
3587 for (i = 0; i < textlen; i++)
3588 {
3589 int j;
3590 for (j = 0; j < glyphs[i].outlines.count; j++)
3591 HeapFree(GetProcessHeap(), 0, glyphs[i].outlines.items[j].items);
3592 HeapFree(GetProcessHeap(), 0, glyphs[i].outlines.items);
3593 }
3594 HeapFree(GetProcessHeap(), 0, glyphs);
3595 }
3596 HeapFree(GetProcessHeap(), 0, raw_outline);
3597
3598 return hr == D3D_OK;
3599 }
3600
3601 static void compare_text_outline_mesh(const char *name, ID3DXMesh *d3dxmesh, struct mesh *mesh, int textlen, float extrusion)
3602 {
3603 HRESULT hr;
3604 DWORD number_of_vertices, number_of_faces;
3605 IDirect3DVertexBuffer9 *vertex_buffer = NULL;
3606 IDirect3DIndexBuffer9 *index_buffer = NULL;
3607 D3DVERTEXBUFFER_DESC vertex_buffer_description;
3608 D3DINDEXBUFFER_DESC index_buffer_description;
3609 struct vertex *vertices = NULL;
3610 face *faces = NULL;
3611 int expected, i;
3612 int vtx_idx1, face_idx1, vtx_idx2, face_idx2;
3613
3614 number_of_vertices = d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh);
3615 number_of_faces = d3dxmesh->lpVtbl->GetNumFaces(d3dxmesh);
3616
3617 /* vertex buffer */
3618 hr = d3dxmesh->lpVtbl->GetVertexBuffer(d3dxmesh, &vertex_buffer);
3619 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
3620 if (hr != D3D_OK)
3621 {
3622 skip("Couldn't get vertex buffers\n");
3623 goto error;
3624 }
3625
3626 hr = IDirect3DVertexBuffer9_GetDesc(vertex_buffer, &vertex_buffer_description);
3627 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
3628
3629 if (hr != D3D_OK)
3630 {
3631 skip("Couldn't get vertex buffer description\n");
3632 }
3633 else
3634 {
3635 ok(vertex_buffer_description.Format == D3DFMT_VERTEXDATA, "Test %s, result %x, expected %x (D3DFMT_VERTEXDATA)\n",
3636 name, vertex_buffer_description.Format, D3DFMT_VERTEXDATA);
3637 ok(vertex_buffer_description.Type == D3DRTYPE_VERTEXBUFFER, "Test %s, result %x, expected %x (D3DRTYPE_VERTEXBUFFER)\n",
3638 name, vertex_buffer_description.Type, D3DRTYPE_VERTEXBUFFER);
3639 ok(vertex_buffer_description.Usage == 0, "Test %s, result %x, expected %x\n", name, vertex_buffer_description.Usage, 0);
3640 ok(vertex_buffer_description.Pool == D3DPOOL_MANAGED, "Test %s, result %x, expected %x (D3DPOOL_MANAGED)\n",
3641 name, vertex_buffer_description.Pool, D3DPOOL_MANAGED);
3642 ok(vertex_buffer_description.FVF == mesh->fvf, "Test %s, result %x, expected %x\n",
3643 name, vertex_buffer_description.FVF, mesh->fvf);
3644 if (mesh->fvf == 0)
3645 {
3646 expected = number_of_vertices * mesh->vertex_size;
3647 }
3648 else
3649 {
3650 expected = number_of_vertices * D3DXGetFVFVertexSize(mesh->fvf);
3651 }
3652 ok(vertex_buffer_description.Size == expected, "Test %s, result %x, expected %x\n",
3653 name, vertex_buffer_description.Size, expected);
3654 }
3655
3656 hr = d3dxmesh->lpVtbl->GetIndexBuffer(d3dxmesh, &index_buffer);
3657 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
3658 if (hr != D3D_OK)
3659 {
3660 skip("Couldn't get index buffer\n");
3661 goto error;
3662 }
3663
3664 hr = IDirect3DIndexBuffer9_GetDesc(index_buffer, &index_buffer_description);
3665 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
3666
3667 if (hr != D3D_OK)
3668 {
3669 skip("Couldn't get index buffer description\n");
3670 }
3671 else
3672 {
3673 ok(index_buffer_description.Format == D3DFMT_INDEX16, "Test %s, result %x, expected %x (D3DFMT_INDEX16)\n",
3674 name, index_buffer_description.Format, D3DFMT_INDEX16);
3675 ok(index_buffer_description.Type == D3DRTYPE_INDEXBUFFER, "Test %s, result %x, expected %x (D3DRTYPE_INDEXBUFFER)\n",
3676 name, index_buffer_description.Type, D3DRTYPE_INDEXBUFFER);
3677 ok(index_buffer_description.Usage == 0, "Test %s, result %#x, expected %#x.\n",
3678 name, index_buffer_description.Usage, 0);
3679 ok(index_buffer_description.Pool == D3DPOOL_MANAGED, "Test %s, result %x, expected %x (D3DPOOL_MANAGED)\n",
3680 name, index_buffer_description.Pool, D3DPOOL_MANAGED);
3681 expected = number_of_faces * sizeof(WORD) * 3;
3682 ok(index_buffer_description.Size == expected, "Test %s, result %x, expected %x\n",
3683 name, index_buffer_description.Size, expected);
3684 }
3685
3686 /* specify offset and size to avoid potential overruns */
3687 hr = IDirect3DVertexBuffer9_Lock(vertex_buffer, 0, number_of_vertices * sizeof(D3DXVECTOR3) * 2,
3688 (LPVOID *)&vertices, D3DLOCK_DISCARD);
3689 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
3690 if (hr != D3D_OK)
3691 {
3692 skip("Couldn't lock vertex buffer\n");
3693 goto error;
3694 }
3695 hr = IDirect3DIndexBuffer9_Lock(index_buffer, 0, number_of_faces * sizeof(WORD) * 3,
3696 (LPVOID *)&faces, D3DLOCK_DISCARD);
3697 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
3698 if (hr != D3D_OK)
3699 {
3700 skip("Couldn't lock index buffer\n");
3701 goto error;
3702 }
3703
3704 face_idx1 = 0;
3705 vtx_idx2 = 0;
3706 face_idx2 = 0;
3707 vtx_idx1 = 0;
3708 for (i = 0; i < textlen; i++)
3709 {
3710 int nb_outline_vertices1, nb_outline_faces1;
3711 int nb_outline_vertices2, nb_outline_faces2;
3712 int nb_back_vertices, nb_back_faces;
3713 int first_vtx1, first_vtx2;
3714 int first_face1, first_face2;
3715 int j;
3716
3717 first_vtx1 = vtx_idx1;
3718 first_vtx2 = vtx_idx2;
3719 for (; vtx_idx1 < number_of_vertices; vtx_idx1++) {
3720 if (vertices[vtx_idx1].normal.z != 0)
3721 break;
3722 }
3723 for (; vtx_idx2 < mesh->number_of_vertices; vtx_idx2++) {
3724 if (mesh->vertices[vtx_idx2].normal.z != 0)
3725 break;
3726 }
3727 nb_outline_vertices1 = vtx_idx1 - first_vtx1;
3728 nb_outline_vertices2 = vtx_idx2 - first_vtx2;
3729 ok(nb_outline_vertices1 == nb_outline_vertices2,
3730 "Test %s, glyph %d, outline vertex count result %d, expected %d\n", name, i,
3731 nb_outline_vertices1, nb_outline_vertices2);
3732
3733 for (j = 0; j < min(nb_outline_vertices1, nb_outline_vertices2); j++)
3734 {
3735 vtx_idx1 = first_vtx1 + j;
3736 vtx_idx2 = first_vtx2 + j;
3737 ok(compare_vec3(vertices[vtx_idx1].position, mesh->vertices[vtx_idx2].position),
3738 "Test %s, glyph %d, vertex position %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1,
3739 vertices[vtx_idx1].position.x, vertices[vtx_idx1].position.y, vertices[vtx_idx1].position.z,
3740 mesh->vertices[vtx_idx2].position.x, mesh->vertices[vtx_idx2].position.y, mesh->vertices[vtx_idx2].position.z);
3741 ok(compare_vec3(vertices[vtx_idx1].normal, mesh->vertices[first_vtx2 + j].normal),
3742 "Test %s, glyph %d, vertex normal %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1,
3743 vertices[vtx_idx1].normal.x, vertices[vtx_idx1].normal.y, vertices[vtx_idx1].normal.z,
3744 mesh->vertices[vtx_idx2].normal.x, mesh->vertices[vtx_idx2].normal.y, mesh->vertices[vtx_idx2].normal.z);
3745 }
3746 vtx_idx1 = first_vtx1 + nb_outline_vertices1;
3747 vtx_idx2 = first_vtx2 + nb_outline_vertices2;
3748
3749 first_face1 = face_idx1;
3750 first_face2 = face_idx2;
3751 for (; face_idx1 < number_of_faces; face_idx1++)
3752 {
3753 if (faces[face_idx1][0] >= vtx_idx1 ||
3754 faces[face_idx1][1] >= vtx_idx1 ||
3755 faces[face_idx1][2] >= vtx_idx1)
3756 break;
3757 }
3758 for (; face_idx2 < mesh->number_of_faces; face_idx2++)
3759 {
3760 if (mesh->faces[face_idx2][0] >= vtx_idx2 ||
3761 mesh->faces[face_idx2][1] >= vtx_idx2 ||
3762 mesh->faces[face_idx2][2] >= vtx_idx2)
3763 break;
3764 }
3765 nb_outline_faces1 = face_idx1 - first_face1;
3766 nb_outline_faces2 = face_idx2 - first_face2;
3767 ok(nb_outline_faces1 == nb_outline_faces2,
3768 "Test %s, glyph %d, outline face count result %d, expected %d\n", name, i,
3769 nb_outline_faces1, nb_outline_faces2);
3770
3771 for (j = 0; j < min(nb_outline_faces1, nb_outline_faces2); j++)
3772 {
3773 face_idx1 = first_face1 + j;
3774 face_idx2 = first_face2 + j;
3775 ok(faces[face_idx1][0] - first_vtx1 == mesh->faces[face_idx2][0] - first_vtx2 &&
3776 faces[face_idx1][1] - first_vtx1 == mesh->faces[face_idx2][1] - first_vtx2 &&
3777 faces[face_idx1][2] - first_vtx1 == mesh->faces[face_idx2][2] - first_vtx2,
3778 "Test %s, glyph %d, face %d, result (%d, %d, %d), expected (%d, %d, %d)\n", name, i, face_idx1,
3779 faces[face_idx1][0], faces[face_idx1][1], faces[face_idx1][2],
3780 mesh->faces[face_idx2][0] - first_vtx2 + first_vtx1,
3781 mesh->faces[face_idx2][1] - first_vtx2 + first_vtx1,
3782 mesh->faces[face_idx2][2] - first_vtx2 + first_vtx1);
3783 }
3784 face_idx1 = first_face1 + nb_outline_faces1;
3785 face_idx2 = first_face2 + nb_outline_faces2;
3786
3787 /* partial test on back vertices and faces */
3788 first_vtx1 = vtx_idx1;
3789 for (; vtx_idx1 < number_of_vertices; vtx_idx1++) {
3790 struct vertex vtx;
3791
3792 if (vertices[vtx_idx1].normal.z != 1.0f)
3793 break;
3794
3795 vtx.position.z = 0.0f;
3796 vtx.normal.x = 0.0f;
3797 vtx.normal.y = 0.0f;
3798 vtx.normal.z = 1.0f;
3799 ok(compare(vertices[vtx_idx1].position.z, vtx.position.z),
3800 "Test %s, glyph %d, vertex position.z %d, result %g, expected %g\n", name, i, vtx_idx1,
3801 vertices[vtx_idx1].position.z, vtx.position.z);
3802 ok(compare_vec3(vertices[vtx_idx1].normal, vtx.normal),
3803 "Test %s, glyph %d, vertex normal %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1,
3804 vertices[vtx_idx1].normal.x, vertices[vtx_idx1].normal.y, vertices[vtx_idx1].normal.z,
3805 vtx.normal.x, vtx.normal.y, vtx.normal.z);
3806 }
3807 nb_back_vertices = vtx_idx1 - first_vtx1;
3808 first_face1 = face_idx1;
3809 for (; face_idx1 < number_of_faces; face_idx1++)
3810 {
3811 const D3DXVECTOR3 *vtx1, *vtx2, *vtx3;
3812 D3DXVECTOR3 normal;
3813 D3DXVECTOR3 v1 = {0, 0, 0};
3814 D3DXVECTOR3 v2 = {0, 0, 0};
3815 D3DXVECTOR3 forward = {0.0f, 0.0f, 1.0f};
3816
3817 if (faces[face_idx1][0] >= vtx_idx1 ||
3818 faces[face_idx1][1] >= vtx_idx1 ||
3819 faces[face_idx1][2] >= vtx_idx1)
3820 break;
3821
3822 vtx1 = &vertices[faces[face_idx1][0]].position;
3823 vtx2 = &vertices[faces[face_idx1][1]].position;
3824 vtx3 = &vertices[faces[face_idx1][2]].position;
3825
3826 D3DXVec3Subtract(&v1, vtx2, vtx1);
3827 D3DXVec3Subtract(&v2, vtx3, vtx2);
3828 D3DXVec3Cross(&normal, &v1, &v2);
3829 D3DXVec3Normalize(&normal, &normal);
3830 ok(!D3DXVec3Length(&normal) || compare_vec3(normal, forward),
3831 "Test %s, glyph %d, face %d normal, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, face_idx1,
3832 normal.x, normal.y, normal.z, forward.x, forward.y, forward.z);
3833 }
3834 nb_back_faces = face_idx1 - first_face1;
3835
3836 /* compare front and back faces & vertices */
3837 if (extrusion == 0.0f) {
3838 /* Oddly there are only back faces in this case */
3839 nb_back_vertices /= 2;
3840 nb_back_faces /= 2;
3841 face_idx1 -= nb_back_faces;
3842 vtx_idx1 -= nb_back_vertices;
3843 }
3844 for (j = 0; j < nb_back_vertices; j++)
3845 {
3846 struct vertex vtx = vertices[first_vtx1];
3847 vtx.position.z = -extrusion;
3848 vtx.normal.x = 0.0f;
3849 vtx.normal.y = 0.0f;
3850 vtx.normal.z = extrusion == 0.0f ? 1.0f : -1.0f;
3851 ok(compare_vec3(vertices[vtx_idx1].position, vtx.position),
3852 "Test %s, glyph %d, vertex position %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1,
3853 vertices[vtx_idx1].position.x, vertices[vtx_idx1].position.y, vertices[vtx_idx1].position.z,
3854 vtx.position.x, vtx.position.y, vtx.position.z);
3855 ok(compare_vec3(vertices[vtx_idx1].normal, vtx.normal),
3856 "Test %s, glyph %d, vertex normal %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1,
3857 vertices[vtx_idx1].normal.x, vertices[vtx_idx1].normal.y, vertices[vtx_idx1].normal.z,
3858 vtx.normal.x, vtx.normal.y, vtx.normal.z);
3859 vtx_idx1++;
3860 first_vtx1++;
3861 }
3862 for (j = 0; j < nb_back_faces; j++)
3863 {
3864 int f1, f2;
3865 if (extrusion == 0.0f) {
3866 f1 = 1;
3867 f2 = 2;
3868 } else {
3869 f1 = 2;
3870 f2 = 1;
3871 }
3872 ok(faces[face_idx1][0] == faces[first_face1][0] + nb_back_vertices &&
3873 faces[face_idx1][1] == faces[first_face1][f1] + nb_back_vertices &&
3874 faces[face_idx1][2] == faces[first_face1][f2] + nb_back_vertices,
3875 "Test %s, glyph %d, face %d, result (%d, %d, %d), expected (%d, %d, %d)\n", name, i, face_idx1,
3876 faces[face_idx1][0], faces[face_idx1][1], faces[face_idx1][2],
3877 faces[first_face1][0] - nb_back_faces,
3878 faces[first_face1][f1] - nb_back_faces,
3879 faces[first_face1][f2] - nb_back_faces);
3880 first_face1++;
3881 face_idx1++;
3882 }
3883
3884 /* skip to the outline for the next glyph */
3885 for (; vtx_idx2 < mesh->number_of_vertices; vtx_idx2++) {
3886 if (mesh->vertices[vtx_idx2].normal.z == 0)
3887 break;
3888 }
3889 for (; face_idx2 < mesh->number_of_faces; face_idx2++)
3890 {
3891 if (mesh->faces[face_idx2][0] >= vtx_idx2 ||
3892 mesh->faces[face_idx2][1] >= vtx_idx2 ||
3893 mesh->faces[face_idx2][2] >= vtx_idx2) break;
3894 }
3895 }
3896
3897 error:
3898 if (vertices) IDirect3DVertexBuffer9_Unlock(vertex_buffer);
3899 if (faces) IDirect3DIndexBuffer9_Unlock(index_buffer);
3900 if (index_buffer) IDirect3DIndexBuffer9_Release(index_buffer);
3901 if (vertex_buffer) IDirect3DVertexBuffer9_Release(vertex_buffer);
3902 }
3903
3904 static void test_createtext(IDirect3DDevice9 *device, HDC hdc, LPCSTR text, FLOAT deviation, FLOAT extrusion)
3905 {
3906 HRESULT hr;
3907 ID3DXMesh *d3dxmesh;
3908 struct mesh mesh;
3909 char name[256];
3910 OUTLINETEXTMETRIC otm;
3911 GLYPHMETRICS gm;
3912 GLYPHMETRICSFLOAT *glyphmetrics_float = HeapAlloc(GetProcessHeap(), 0, sizeof(GLYPHMETRICSFLOAT) * strlen(text));
3913 int i;
3914 LOGFONT lf;
3915 HFONT font = NULL, oldfont = NULL;
3916
3917 sprintf(name, "text ('%s', %f, %f)", text, deviation, extrusion);
3918
3919 hr = D3DXCreateText(device, hdc, text, deviation, extrusion, &d3dxmesh, NULL, glyphmetrics_float);
3920 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
3921 if (hr != D3D_OK)
3922 {
3923 skip("Couldn't create text with D3DXCreateText\n");
3924 return;
3925 }
3926
3927 /* must select a modified font having lfHeight = otm.otmEMSquare before
3928 * calling GetGlyphOutline to get the expected values */
3929 if (!GetObject(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf) ||
3930 !GetOutlineTextMetrics(hdc, sizeof(otm), &otm))
3931 {
3932 d3dxmesh->lpVtbl->Release(d3dxmesh);
3933 skip("Couldn't get text outline\n");
3934 return;
3935 }
3936 lf.lfHeight = otm.otmEMSquare;
3937 lf.lfWidth = 0;
3938 font = CreateFontIndirect(&lf);
3939 if (!font) {
3940 d3dxmesh->lpVtbl->Release(d3dxmesh);
3941 skip("Couldn't create the modified font\n");
3942 return;
3943 }
3944 oldfont = SelectObject(hdc, font);
3945
3946 for (i = 0; i < strlen(text); i++)
3947 {
3948 const MAT2 identity = {{0, 1}, {0, 0}, {0, 0}, {0, 1}};
3949 GetGlyphOutlineA(hdc, text[i], GGO_NATIVE, &gm, 0, NULL, &identity);
3950 compare_float(glyphmetrics_float[i].gmfBlackBoxX, gm.gmBlackBoxX / (float)otm.otmEMSquare);
3951 compare_float(glyphmetrics_float[i].gmfBlackBoxY, gm.gmBlackBoxY / (float)otm.otmEMSquare);
3952 compare_float(glyphmetrics_float[i].gmfptGlyphOrigin.x, gm.gmptGlyphOrigin.x / (float)otm.otmEMSquare);
3953 compare_float(glyphmetrics_float[i].gmfptGlyphOrigin.y, gm.gmptGlyphOrigin.y / (float)otm.otmEMSquare);
3954 compare_float(glyphmetrics_float[i].gmfCellIncX, gm.gmCellIncX / (float)otm.otmEMSquare);
3955 compare_float(glyphmetrics_float[i].gmfCellIncY, gm.gmCellIncY / (float)otm.otmEMSquare);
3956 }
3957
3958 ZeroMemory(&mesh, sizeof(mesh));
3959 if (!compute_text_mesh(&mesh, hdc, text, deviation, extrusion, otm.otmEMSquare))
3960 {
3961 skip("Couldn't create mesh\n");
3962 d3dxmesh->lpVtbl->Release(d3dxmesh);
3963 return;
3964 }
3965 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
3966
3967 compare_text_outline_mesh(name, d3dxmesh, &mesh, strlen(text), extrusion);
3968
3969 free_mesh(&mesh);
3970
3971 d3dxmesh->lpVtbl->Release(d3dxmesh);
3972 SelectObject(hdc, oldfont);
3973 HeapFree(GetProcessHeap(), 0, glyphmetrics_float);
3974 }
3975
3976 static void D3DXCreateTextTest(void)
3977 {
3978 HRESULT hr;
3979 HWND wnd;
3980 HDC hdc;
3981 IDirect3D9* d3d;
3982 IDirect3DDevice9* device;
3983 D3DPRESENT_PARAMETERS d3dpp;
3984 ID3DXMesh* d3dxmesh = NULL;
3985 HFONT hFont;
3986 OUTLINETEXTMETRIC otm;
3987 int number_of_vertices;
3988 int number_of_faces;
3989
3990 wnd = CreateWindow("static", "d3dx9_test", WS_POPUP, 0, 0, 1000, 1000, NULL, NULL, NULL, NULL);
3991 d3d = Direct3DCreate9(D3D_SDK_VERSION);
3992 if (!wnd)
3993 {
3994 skip("Couldn't create application window\n");
3995 return;
3996 }
3997 if (!d3d)
3998 {
3999 skip("Couldn't create IDirect3D9 object\n");
4000 DestroyWindow(wnd);
4001 return;
4002 }
4003
4004 ZeroMemory(&d3dpp, sizeof(d3dpp));
4005 d3dpp.Windowed = TRUE;
4006 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
4007 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, wnd, D3DCREATE_MIXED_VERTEXPROCESSING, &d3dpp, &device);
4008 if (FAILED(hr))
4009 {
4010 skip("Failed to create IDirect3DDevice9 object %#x\n", hr);
4011 IDirect3D9_Release(d3d);
4012 DestroyWindow(wnd);
4013 return;
4014 }
4015
4016 hdc = CreateCompatibleDC(NULL);
4017
4018 hFont = CreateFont(12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET,
4019 OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE,
4020 "Arial");
4021 SelectObject(hdc, hFont);
4022 GetOutlineTextMetrics(hdc, sizeof(otm), &otm);
4023
4024 hr = D3DXCreateText(device, hdc, "wine", 0.001f, 0.4f, NULL, NULL, NULL);
4025 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4026
4027 /* D3DXCreateTextA page faults from passing NULL text */
4028
4029 hr = D3DXCreateTextW(device, hdc, NULL, 0.001f, 0.4f, &d3dxmesh, NULL, NULL);
4030 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4031
4032 hr = D3DXCreateText(device, hdc, "", 0.001f, 0.4f, &d3dxmesh, NULL, NULL);
4033 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4034
4035 hr = D3DXCreateText(device, hdc, " ", 0.001f, 0.4f, &d3dxmesh, NULL, NULL);
4036 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4037
4038 hr = D3DXCreateText(NULL, hdc, "wine", 0.001f, 0.4f, &d3dxmesh, NULL, NULL);
4039 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4040
4041 hr = D3DXCreateText(device, NULL, "wine", 0.001f, 0.4f, &d3dxmesh, NULL, NULL);
4042 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4043
4044 hr = D3DXCreateText(device, hdc, "wine", -FLT_MIN, 0.4f, &d3dxmesh, NULL, NULL);
4045 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4046
4047 hr = D3DXCreateText(device, hdc, "wine", 0.001f, -FLT_MIN, &d3dxmesh, NULL, NULL);
4048 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4049
4050 /* deviation = 0.0f treated as if deviation = 1.0f / otm.otmEMSquare */
4051 hr = D3DXCreateText(device, hdc, "wine", 1.0f / otm.otmEMSquare, 0.4f, &d3dxmesh, NULL, NULL);
4052 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
4053 number_of_vertices = d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh);
4054 number_of_faces = d3dxmesh->lpVtbl->GetNumFaces(d3dxmesh);
4055 if (SUCCEEDED(hr) && d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh);
4056
4057 hr = D3DXCreateText(device, hdc, "wine", 0.0f, 0.4f, &d3dxmesh, NULL, NULL);
4058 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
4059 ok(number_of_vertices == d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh),
4060 "Got %d vertices, expected %d\n",
4061 d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh), number_of_vertices);
4062 ok(number_of_faces == d3dxmesh->lpVtbl->GetNumFaces(d3dxmesh),
4063 "Got %d faces, expected %d\n",
4064 d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh), number_of_faces);
4065 if (SUCCEEDED(hr) && d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh);
4066
4067 #if 0
4068 /* too much detail requested, so will appear to hang */
4069 trace("Waiting for D3DXCreateText to finish with deviation = FLT_MIN ...\n");
4070 hr = D3DXCreateText(device, hdc, "wine", FLT_MIN, 0.4f, &d3dxmesh, NULL, NULL);
4071 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
4072 if (SUCCEEDED(hr) && d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh);
4073 trace("D3DXCreateText finish with deviation = FLT_MIN\n");
4074 #endif
4075
4076 hr = D3DXCreateText(device, hdc, "wine", 0.001f, 0.4f, &d3dxmesh, NULL, NULL);
4077 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
4078 if (SUCCEEDED(hr) && d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh);
4079
4080 test_createtext(device, hdc, "wine", FLT_MAX, 0.4f);
4081 test_createtext(device, hdc, "wine", 0.001f, FLT_MIN);
4082 test_createtext(device, hdc, "wine", 0.001f, 0.0f);
4083 test_createtext(device, hdc, "wine", 0.001f, FLT_MAX);
4084 test_createtext(device, hdc, "wine", 0.0f, 1.0f);
4085
4086 DeleteDC(hdc);
4087
4088 IDirect3DDevice9_Release(device);
4089 IDirect3D9_Release(d3d);
4090 DestroyWindow(wnd);
4091 }
4092
4093 static void test_get_decl_length(void)
4094 {
4095 static const D3DVERTEXELEMENT9 declaration1[] =
4096 {
4097 {0, 0, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4098 {1, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4099 {2, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4100 {3, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4101 {4, 0, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4102 {5, 0, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4103 {6, 0, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4104 {7, 0, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4105 {8, 0, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4106 {9, 0, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4107 {10, 0, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4108 {11, 0, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4109 {12, 0, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4110 {13, 0, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4111 {14, 0, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4112 D3DDECL_END(),
4113 };
4114 static const D3DVERTEXELEMENT9 declaration2[] =
4115 {
4116 {0, 8, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4117 {1, 8, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4118 {2, 8, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4119 {3, 8, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4120 {4, 8, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4121 {5, 8, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4122 {6, 8, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4123 {7, 8, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4124 {0, 8, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4125 {1, 8, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4126 {2, 8, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4127 {3, 8, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4128 {4, 8, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4129 {5, 8, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4130 {6, 8, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4131 {7, 8, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4132 D3DDECL_END(),
4133 };
4134 UINT size;
4135
4136 size = D3DXGetDeclLength(declaration1);
4137 ok(size == 15, "Got size %u, expected 15.\n", size);
4138
4139 size = D3DXGetDeclLength(declaration2);
4140 ok(size == 16, "Got size %u, expected 16.\n", size);
4141 }
4142
4143 static void test_get_decl_vertex_size(void)
4144 {
4145 static const D3DVERTEXELEMENT9 declaration1[] =
4146 {
4147 {0, 0, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4148 {1, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4149 {2, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4150 {3, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4151 {4, 0, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4152 {5, 0, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4153 {6, 0, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4154 {7, 0, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4155 {8, 0, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4156 {9, 0, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4157 {10, 0, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4158 {11, 0, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4159 {12, 0, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4160 {13, 0, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4161 {14, 0, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4162 D3DDECL_END(),
4163 };
4164 static const D3DVERTEXELEMENT9 declaration2[] =
4165 {
4166 {0, 8, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4167 {1, 8, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4168 {2, 8, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4169 {3, 8, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4170 {4, 8, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4171 {5, 8, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4172 {6, 8, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4173 {7, 8, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4174 {0, 8, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4175 {1, 8, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4176 {2, 8, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4177 {3, 8, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4178 {4, 8, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4179 {5, 8, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4180 {6, 8, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4181 {7, 8, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4182 D3DDECL_END(),
4183 };
4184 static const UINT sizes1[] =
4185 {
4186 4, 8, 12, 16,
4187 4, 4, 4, 8,
4188 4, 4, 8, 4,
4189 4, 4, 8, 0,
4190 };
4191 static const UINT sizes2[] =
4192 {
4193 12, 16, 20, 24,
4194 12, 12, 16, 16,
4195 };
4196 unsigned int i;
4197 UINT size;
4198
4199 size = D3DXGetDeclVertexSize(NULL, 0);
4200 ok(size == 0, "Got size %#x, expected 0.\n", size);
4201
4202 for (i = 0; i < 16; ++i)
4203 {
4204 size = D3DXGetDeclVertexSize(declaration1, i);
4205 ok(size == sizes1[i], "Got size %u for stream %u, expected %u.\n", size, i, sizes1[i]);
4206 }
4207
4208 for (i = 0; i < 8; ++i)
4209 {
4210 size = D3DXGetDeclVertexSize(declaration2, i);
4211 ok(size == sizes2[i], "Got size %u for stream %u, expected %u.\n", size, i, sizes2[i]);
4212 }
4213 }
4214
4215 static void D3DXGenerateAdjacencyTest(void)
4216 {
4217 HRESULT hr;
4218 HWND wnd;
4219 IDirect3D9 *d3d;
4220 IDirect3DDevice9 *device;
4221 D3DPRESENT_PARAMETERS d3dpp;
4222 ID3DXMesh *d3dxmesh = NULL;
4223 D3DXVECTOR3 *vertices = NULL;
4224 WORD *indices = NULL;
4225 int i;
4226 struct {
4227 DWORD num_vertices;
4228 D3DXVECTOR3 vertices[6];
4229 DWORD num_faces;
4230 WORD indices[3 * 3];
4231 FLOAT epsilon;
4232 DWORD adjacency[3 * 3];
4233 } test_data[] = {
4234 { /* for epsilon < 0, indices must match for faces to be adjacent */
4235 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}},
4236 2, {0, 1, 2, 0, 2, 3},
4237 -1.0,
4238 {-1, -1, 1, 0, -1, -1},
4239 },
4240 {
4241 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}},
4242 2, {0, 1, 2, 3, 4, 5},
4243 -1.0,
4244 {-1, -1, -1, -1, -1, -1},
4245 },
4246 { /* for epsilon == 0, indices or vertices must match for faces to be adjacent */
4247 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}},
4248 2, {0, 1, 2, 3, 4, 5},
4249 0.0,
4250 {-1, -1, 1, 0, -1, -1},
4251 },
4252 { /* for epsilon > 0, vertices must be less than (but NOT equal to) epsilon distance away */
4253 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}},
4254 2, {0, 1, 2, 3, 4, 5},
4255 0.25,
4256 {-1, -1, -1, -1, -1, -1},
4257 },
4258 { /* for epsilon > 0, vertices must be less than (but NOT equal to) epsilon distance away */
4259 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}},
4260 2, {0, 1, 2, 3, 4, 5},
4261 0.250001,
4262 {-1, -1, 1, 0, -1, -1},
4263 },
4264 { /* length between vertices are compared to epsilon, not the individual dimension deltas */
4265 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}},
4266 2, {0, 1, 2, 3, 4, 5},
4267 0.353, /* < sqrt(0.25*0.25 + 0.25*0.25) */
4268 {-1, -1, -1, -1, -1, -1},
4269 },
4270 {
4271 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}},
4272 2, {0, 1, 2, 3, 4, 5},
4273 0.354, /* > sqrt(0.25*0.25 + 0.25*0.25) */
4274 {-1, -1, 1, 0, -1, -1},
4275 },
4276 { /* adjacent faces must have opposite winding orders at the shared edge */
4277 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}},
4278 2, {0, 1, 2, 0, 3, 2},
4279 0.0,
4280 {-1, -1, -1, -1, -1, -1},
4281 },
4282 };
4283
4284 wnd = CreateWindow("static", "d3dx9_test", 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL);
4285 if (!wnd)
4286 {
4287 skip("Couldn't create application window\n");
4288 return;
4289 }
4290 d3d = Direct3DCreate9(D3D_SDK_VERSION);
4291 if (!d3d)
4292 {
4293 skip("Couldn't create IDirect3D9 object\n");
4294 DestroyWindow(wnd);
4295 return;
4296 }
4297
4298 ZeroMemory(&d3dpp, sizeof(d3dpp));
4299 d3dpp.Windowed = TRUE;
4300 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
4301 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, wnd, D3DCREATE_MIXED_VERTEXPROCESSING, &d3dpp, &device);
4302 if (FAILED(hr))
4303 {
4304 skip("Failed to create IDirect3DDevice9 object %#x\n", hr);
4305 IDirect3D9_Release(d3d);
4306 DestroyWindow(wnd);
4307 return;
4308 }
4309
4310 for (i = 0; i < ARRAY_SIZE(test_data); i++)
4311 {
4312 DWORD adjacency[ARRAY_SIZE(test_data[0].adjacency)];
4313 int j;
4314
4315 if (d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh);
4316 d3dxmesh = NULL;
4317
4318 hr = D3DXCreateMeshFVF(test_data[i].num_faces, test_data[i].num_vertices, 0, D3DFVF_XYZ, device, &d3dxmesh);
4319 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
4320
4321 hr = d3dxmesh->lpVtbl->LockVertexBuffer(d3dxmesh, D3DLOCK_DISCARD, (void**)&vertices);
4322 ok(hr == D3D_OK, "test %d: Got result %x, expected %x (D3D_OK)\n", i, hr, D3D_OK);
4323 if (FAILED(hr)) continue;
4324 CopyMemory(vertices, test_data[i].vertices, test_data[i].num_vertices * sizeof(test_data[0].vertices[0]));
4325 d3dxmesh->lpVtbl->UnlockVertexBuffer(d3dxmesh);
4326
4327 hr = d3dxmesh->lpVtbl->LockIndexBuffer(d3dxmesh, D3DLOCK_DISCARD, (void**)&indices);
4328 ok(hr == D3D_OK, "test %d: Got result %x, expected %x (D3D_OK)\n", i, hr, D3D_OK);
4329 if (FAILED(hr)) continue;
4330 CopyMemory(indices, test_data[i].indices, test_data[i].num_faces * 3 * sizeof(test_data[0].indices[0]));
4331 d3dxmesh->lpVtbl->UnlockIndexBuffer(d3dxmesh);
4332
4333 if (i == 0) {
4334 hr = d3dxmesh->lpVtbl->GenerateAdjacency(d3dxmesh, 0.0f, NULL);
4335 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4336 }
4337
4338 hr = d3dxmesh->lpVtbl->GenerateAdjacency(d3dxmesh, test_data[i].epsilon, adjacency);
4339 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
4340 if (FAILED(hr)) continue;
4341
4342 for (j = 0; j < test_data[i].num_faces * 3; j++)
4343 ok(adjacency[j] == test_data[i].adjacency[j],
4344 "Test %d adjacency %d: Got result %u, expected %u\n", i, j,
4345 adjacency[j], test_data[i].adjacency[j]);
4346 }
4347 if (d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh);
4348 }
4349
4350 static void test_update_semantics(void)
4351 {
4352 HRESULT hr;
4353 struct test_context *test_context = NULL;
4354 ID3DXMesh *mesh = NULL;
4355 D3DVERTEXELEMENT9 declaration0[] =
4356 {
4357 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4358 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4359 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4360 D3DDECL_END()
4361 };
4362 D3DVERTEXELEMENT9 declaration_pos_type_color[] =
4363 {
4364 {0, 0, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4365 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4366 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4367 D3DDECL_END()
4368 };
4369 D3DVERTEXELEMENT9 declaration_smaller[] =
4370 {
4371 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4372 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4373 D3DDECL_END()
4374 };
4375 D3DVERTEXELEMENT9 declaration_larger[] =
4376 {
4377 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4378 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4379 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4380 {0, 40, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT, 0},
4381 D3DDECL_END()
4382 };
4383 D3DVERTEXELEMENT9 declaration_multiple_streams[] =
4384 {
4385 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4386 {1, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT, 0},
4387 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4388 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4389
4390 D3DDECL_END()
4391 };
4392 D3DVERTEXELEMENT9 declaration_double_usage[] =
4393 {
4394 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4395 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4396 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4397 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4398 D3DDECL_END()
4399 };
4400 D3DVERTEXELEMENT9 declaration_undefined_type[] =
4401 {
4402 {0, 0, D3DDECLTYPE_UNUSED+1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4403 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4404 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4405 D3DDECL_END()
4406 };
4407 D3DVERTEXELEMENT9 declaration_not_4_byte_aligned_offset[] =
4408 {
4409 {0, 3, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4410 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4411 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4412 D3DDECL_END()
4413 };
4414 static const struct
4415 {
4416 D3DXVECTOR3 position0;
4417 D3DXVECTOR3 position1;
4418 D3DXVECTOR3 normal;
4419 DWORD color;
4420 }
4421 vertices[] =
4422 {
4423 { { 0.0f, 1.0f, 0.f}, { 1.0f, 0.0f, 0.f}, {0.0f, 0.0f, 1.0f}, 0xffff0000 },
4424 { { 1.0f, -1.0f, 0.f}, {-1.0f, -1.0f, 0.f}, {0.0f, 0.0f, 1.0f}, 0xff00ff00 },
4425 { {-1.0f, -1.0f, 0.f}, {-1.0f, 1.0f, 0.f}, {0.0f, 0.0f, 1.0f}, 0xff0000ff },
4426 };
4427 unsigned int faces[] = {0, 1, 2};
4428 unsigned int attributes[] = {0};
4429 unsigned int num_faces = ARRAY_SIZE(faces) / 3;
4430 unsigned int num_vertices = ARRAY_SIZE(vertices);
4431 int offset = sizeof(D3DXVECTOR3);
4432 DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
4433 void *vertex_buffer;
4434 void *index_buffer;
4435 DWORD *attributes_buffer;
4436 D3DVERTEXELEMENT9 declaration[MAX_FVF_DECL_SIZE];
4437 D3DVERTEXELEMENT9 *decl_ptr;
4438 DWORD exp_vertex_size = sizeof(*vertices);
4439 DWORD vertex_size = 0;
4440 int equal;
4441 int i = 0;
4442 int *decl_mem;
4443 int filler_a = 0xaaaaaaaa;
4444 int filler_b = 0xbbbbbbbb;
4445
4446 test_context = new_test_context();
4447 if (!test_context)
4448 {
4449 skip("Couldn't create a test_context\n");
4450 goto cleanup;
4451 }
4452
4453 hr = D3DXCreateMesh(num_faces, num_vertices, options, declaration0,
4454 test_context->device, &mesh);
4455 if (FAILED(hr))
4456 {
4457 skip("Couldn't create test mesh %#x\n", hr);
4458 goto cleanup;
4459 }
4460
4461 mesh->lpVtbl->LockVertexBuffer(mesh, 0, &vertex_buffer);
4462 memcpy(vertex_buffer, vertices, sizeof(vertices));
4463 mesh->lpVtbl->UnlockVertexBuffer(mesh);
4464
4465 mesh->lpVtbl->LockIndexBuffer(mesh, 0, &index_buffer);
4466 memcpy(index_buffer, faces, sizeof(faces));
4467 mesh->lpVtbl->UnlockIndexBuffer(mesh);
4468
4469 mesh->lpVtbl->LockAttributeBuffer(mesh, 0, &attributes_buffer);
4470 memcpy(attributes_buffer, attributes, sizeof(attributes));
4471 mesh->lpVtbl->UnlockAttributeBuffer(mesh);
4472
4473 /* Get the declaration and try to change it */
4474 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4475 if (FAILED(hr))
4476 {
4477 skip("Couldn't get vertex declaration %#x\n", hr);
4478 goto cleanup;
4479 }
4480 equal = memcmp(declaration, declaration0, sizeof(declaration0));
4481 ok(equal == 0, "Vertex declarations were not equal\n");
4482
4483 for (decl_ptr = declaration; decl_ptr->Stream != 0xFF; decl_ptr++)
4484 {
4485 if (decl_ptr->Usage == D3DDECLUSAGE_POSITION)
4486 {
4487 /* Use second vertex position instead of first */
4488 decl_ptr->Offset = offset;
4489 }
4490 }
4491
4492 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration);
4493 ok(hr == D3D_OK, "Test UpdateSematics, got %#x expected %#x\n", hr, D3D_OK);
4494
4495 /* Check that declaration was written by getting it again */
4496 memset(declaration, 0, sizeof(declaration));
4497 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4498 if (FAILED(hr))
4499 {
4500 skip("Couldn't get vertex declaration %#x\n", hr);
4501 goto cleanup;
4502 }
4503
4504 for (decl_ptr = declaration; decl_ptr->Stream != 0xFF; decl_ptr++)
4505 {
4506 if (decl_ptr->Usage == D3DDECLUSAGE_POSITION)
4507 {
4508 ok(decl_ptr->Offset == offset, "Test UpdateSematics, got offset %d expected %d\n",
4509 decl_ptr->Offset, offset);
4510 }
4511 }
4512
4513 /* Check that GetDeclaration only writes up to the D3DDECL_END() marker and
4514 * not the full MAX_FVF_DECL_SIZE elements.
4515 */
4516 memset(declaration, filler_a, sizeof(declaration));
4517 memcpy(declaration, declaration0, sizeof(declaration0));
4518 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration);
4519 ok(hr == D3D_OK, "Test UpdateSematics, "
4520 "got %#x expected D3D_OK\n", hr);
4521 memset(declaration, filler_b, sizeof(declaration));
4522 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4523 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4524 decl_mem = (int*)declaration;
4525 for (i = sizeof(declaration0)/sizeof(*decl_mem); i < sizeof(declaration)/sizeof(*decl_mem); i++)
4526 {
4527 equal = memcmp(&decl_mem[i], &filler_b, sizeof(filler_b));
4528 ok(equal == 0,
4529 "GetDeclaration wrote past the D3DDECL_END() marker. "
4530 "Got %#x, expected %#x\n", decl_mem[i], filler_b);
4531 if (equal != 0) break;
4532 }
4533
4534 /* UpdateSemantics does not check for overlapping fields */
4535 memset(declaration, 0, sizeof(declaration));
4536 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4537 if (FAILED(hr))
4538 {
4539 skip("Couldn't get vertex declaration %#x\n", hr);
4540 goto cleanup;
4541 }
4542
4543 for (decl_ptr = declaration; decl_ptr->Stream != 0xFF; decl_ptr++)
4544 {
4545 if (decl_ptr->Type == D3DDECLTYPE_FLOAT3)
4546 {
4547 decl_ptr->Type = D3DDECLTYPE_FLOAT4;
4548 }
4549 }
4550
4551 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration);
4552 ok(hr == D3D_OK, "Test UpdateSematics for overlapping fields, "
4553 "got %#x expected D3D_OK\n", hr);
4554
4555 /* Set the position type to color instead of float3 */
4556 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_pos_type_color);
4557 ok(hr == D3D_OK, "Test UpdateSematics position type color, "
4558 "got %#x expected D3D_OK\n", hr);
4559
4560 /* The following test cases show that NULL, smaller or larger declarations,
4561 * and declarations with non-zero Stream values are not accepted.
4562 * UpdateSemantics returns D3DERR_INVALIDCALL and the previously set
4563 * declaration will be used by DrawSubset, GetNumBytesPerVertex, and
4564 * GetDeclaration.
4565 */
4566
4567 /* Null declaration (invalid declaration) */
4568 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4569 hr = mesh->lpVtbl->UpdateSemantics(mesh, NULL);
4570 ok(hr == D3DERR_INVALIDCALL, "Test UpdateSematics null pointer declaration, "
4571 "got %#x expected D3DERR_INVALIDCALL\n", hr);
4572 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4573 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4574 vertex_size, exp_vertex_size);
4575 memset(declaration, 0, sizeof(declaration));
4576 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4577 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4578 equal = memcmp(declaration, declaration0, sizeof(declaration0));
4579 ok(equal == 0, "Vertex declarations were not equal\n");
4580
4581 /* Smaller vertex declaration (invalid declaration) */
4582 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4583 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_smaller);
4584 ok(hr == D3DERR_INVALIDCALL, "Test UpdateSematics for smaller vertex declaration, "
4585 "got %#x expected D3DERR_INVALIDCALL\n", hr);
4586 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4587 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4588 vertex_size, exp_vertex_size);
4589 memset(declaration, 0, sizeof(declaration));
4590 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4591 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4592 equal = memcmp(declaration, declaration0, sizeof(declaration0));
4593 ok(equal == 0, "Vertex declarations were not equal\n");
4594
4595 /* Larger vertex declaration (invalid declaration) */
4596 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4597 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_larger);
4598 ok(hr == D3DERR_INVALIDCALL, "Test UpdateSematics for larger vertex declaration, "
4599 "got %#x expected D3DERR_INVALIDCALL\n", hr);
4600 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4601 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4602 vertex_size, exp_vertex_size);
4603 memset(declaration, 0, sizeof(declaration));
4604 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4605 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4606 equal = memcmp(declaration, declaration0, sizeof(declaration0));
4607 ok(equal == 0, "Vertex declarations were not equal\n");
4608
4609 /* Use multiple streams and keep the same vertex size (invalid declaration) */
4610 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4611 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_multiple_streams);
4612 ok(hr == D3DERR_INVALIDCALL, "Test UpdateSematics using multiple streams, "
4613 "got %#x expected D3DERR_INVALIDCALL\n", hr);
4614 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4615 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4616 vertex_size, exp_vertex_size);
4617 memset(declaration, 0, sizeof(declaration));
4618 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4619 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4620 equal = memcmp(declaration, declaration0, sizeof(declaration0));
4621 ok(equal == 0, "Vertex declarations were not equal\n");
4622
4623 /* The next following test cases show that some invalid declarations are
4624 * accepted with a D3D_OK. An access violation is thrown on Windows if
4625 * DrawSubset is called. The methods GetNumBytesPerVertex and GetDeclaration
4626 * are not affected, which indicates that the declaration is cached.
4627 */
4628
4629 /* Double usage (invalid declaration) */
4630 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4631 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_double_usage);
4632 ok(hr == D3D_OK, "Test UpdateSematics double usage, "
4633 "got %#x expected D3D_OK\n", hr);
4634 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4635 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4636 vertex_size, exp_vertex_size);
4637 memset(declaration, 0, sizeof(declaration));
4638 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4639 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4640 equal = memcmp(declaration, declaration_double_usage, sizeof(declaration_double_usage));
4641 ok(equal == 0, "Vertex declarations were not equal\n");
4642
4643 /* Set the position to an undefined type (invalid declaration) */
4644 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4645 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_undefined_type);
4646 ok(hr == D3D_OK, "Test UpdateSematics undefined type, "
4647 "got %#x expected D3D_OK\n", hr);
4648 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4649 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4650 vertex_size, exp_vertex_size);
4651 memset(declaration, 0, sizeof(declaration));
4652 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4653 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4654 equal = memcmp(declaration, declaration_undefined_type, sizeof(declaration_undefined_type));
4655 ok(equal == 0, "Vertex declarations were not equal\n");
4656
4657 /* Use a not 4 byte aligned offset (invalid declaration) */
4658 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4659 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_not_4_byte_aligned_offset);
4660 ok(hr == D3D_OK, "Test UpdateSematics not 4 byte aligned offset, "
4661 "got %#x expected D3D_OK\n", hr);
4662 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4663 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4664 vertex_size, exp_vertex_size);
4665 memset(declaration, 0, sizeof(declaration));
4666 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4667 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4668 equal = memcmp(declaration, declaration_not_4_byte_aligned_offset,
4669 sizeof(declaration_not_4_byte_aligned_offset));
4670 ok(equal == 0, "Vertex declarations were not equal\n");
4671
4672 cleanup:
4673 if (mesh)
4674 mesh->lpVtbl->Release(mesh);
4675
4676 free_test_context(test_context);
4677 }
4678
4679 static void test_create_skin_info(void)
4680 {
4681 HRESULT hr;
4682 ID3DXSkinInfo *skininfo = NULL;
4683 D3DVERTEXELEMENT9 empty_declaration[] = { D3DDECL_END() };
4684 D3DVERTEXELEMENT9 declaration_out[MAX_FVF_DECL_SIZE];
4685 const D3DVERTEXELEMENT9 declaration_with_nonzero_stream[] = {
4686 {1, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
4687 D3DDECL_END()
4688 };
4689
4690 hr = D3DXCreateSkinInfo(0, empty_declaration, 0, &skininfo);
4691 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4692 if (skininfo) IUnknown_Release(skininfo);
4693 skininfo = NULL;
4694
4695 hr = D3DXCreateSkinInfo(1, NULL, 1, &skininfo);
4696 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4697
4698 hr = D3DXCreateSkinInfo(1, declaration_with_nonzero_stream, 1, &skininfo);
4699 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4700
4701 hr = D3DXCreateSkinInfoFVF(1, 0, 1, &skininfo);
4702 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4703 if (skininfo) {
4704 DWORD dword_result;
4705 FLOAT flt_result;
4706 LPCSTR string_result;
4707 D3DXMATRIX *transform;
4708 D3DXMATRIX identity_matrix;
4709
4710 /* test initial values */
4711 hr = skininfo->lpVtbl->GetDeclaration(skininfo, declaration_out);
4712 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4713 if (SUCCEEDED(hr))
4714 compare_elements(declaration_out, empty_declaration, __LINE__, 0);
4715
4716 dword_result = skininfo->lpVtbl->GetNumBones(skininfo);
4717 ok(dword_result == 1, "Expected 1, got %u\n", dword_result);
4718
4719 flt_result = skininfo->lpVtbl->GetMinBoneInfluence(skininfo);
4720 ok(flt_result == 0.0f, "Expected 0.0, got %g\n", flt_result);
4721
4722 string_result = skininfo->lpVtbl->GetBoneName(skininfo, 0);
4723 ok(string_result == NULL, "Expected NULL, got %p\n", string_result);
4724
4725 dword_result = skininfo->lpVtbl->GetFVF(skininfo);
4726 ok(dword_result == 0, "Expected 0, got %u\n", dword_result);
4727
4728 dword_result = skininfo->lpVtbl->GetNumBoneInfluences(skininfo, 0);
4729 ok(dword_result == 0, "Expected 0, got %u\n", dword_result);
4730
4731 dword_result = skininfo->lpVtbl->GetNumBoneInfluences(skininfo, 1);
4732 ok(dword_result == 0, "Expected 0, got %u\n", dword_result);
4733
4734 transform = skininfo->lpVtbl->GetBoneOffsetMatrix(skininfo, -1);
4735 ok(transform == NULL, "Expected NULL, got %p\n", transform);
4736
4737 {
4738 /* test [GS]etBoneOffsetMatrix */
4739 hr = skininfo->lpVtbl->SetBoneOffsetMatrix(skininfo, 1, &identity_matrix);
4740 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4741
4742 hr = skininfo->lpVtbl->SetBoneOffsetMatrix(skininfo, 0, NULL);
4743 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4744
4745 D3DXMatrixIdentity(&identity_matrix);
4746 hr = skininfo->lpVtbl->SetBoneOffsetMatrix(skininfo, 0, &identity_matrix);
4747 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4748
4749 transform = skininfo->lpVtbl->GetBoneOffsetMatrix(skininfo, 0);
4750 check_matrix(transform, &identity_matrix);
4751 }
4752
4753 {
4754 /* test [GS]etBoneName */
4755 const char *name_in = "testBoneName";
4756 const char *string_result2;
4757
4758 hr = skininfo->lpVtbl->SetBoneName(skininfo, 1, name_in);
4759 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4760
4761 hr = skininfo->lpVtbl->SetBoneName(skininfo, 0, NULL);
4762 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4763
4764 hr = skininfo->lpVtbl->SetBoneName(skininfo, 0, name_in);
4765 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4766
4767 string_result = skininfo->lpVtbl->GetBoneName(skininfo, 0);
4768 ok(string_result != NULL, "Expected non-NULL string, got %p\n", string_result);
4769 ok(!strcmp(string_result, name_in), "Expected '%s', got '%s'\n", name_in, string_result);
4770
4771 string_result2 = skininfo->lpVtbl->GetBoneName(skininfo, 0);
4772 ok(string_result == string_result2, "Expected %p, got %p\n", string_result, string_result2);
4773
4774 string_result = skininfo->lpVtbl->GetBoneName(skininfo, 1);
4775 ok(string_result == NULL, "Expected NULL, got %p\n", string_result);
4776 }
4777
4778 {
4779 /* test [GS]etBoneInfluence */
4780 DWORD vertices[2];
4781 FLOAT weights[2];
4782 int i;
4783 DWORD num_influences;
4784 DWORD exp_vertices[2];
4785 FLOAT exp_weights[2];
4786
4787 /* vertex and weight arrays untouched when num_influences is 0 */
4788 vertices[0] = 0xdeadbeef;
4789 weights[0] = FLT_MAX;
4790 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, vertices, weights);
4791 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4792 ok(vertices[0] == 0xdeadbeef, "expected 0xdeadbeef, got %#x\n", vertices[0]);
4793 ok(weights[0] == FLT_MAX, "expected %g, got %g\n", FLT_MAX, weights[0]);
4794
4795 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 1, vertices, weights);
4796 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4797
4798 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, NULL, NULL);
4799 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4800
4801 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, vertices, NULL);
4802 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4803
4804 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, NULL, weights);
4805 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4806
4807
4808 /* no vertex or weight value checking */
4809 exp_vertices[0] = 0;
4810 exp_vertices[1] = 0x87654321;
4811 exp_weights[0] = 0.5;
4812 exp_weights[1] = 0.0f / 0.0f; /* NAN */
4813 num_influences = 2;
4814
4815 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 1, num_influences, vertices, weights);
4816 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4817
4818 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, num_influences, NULL, weights);
4819 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4820
4821 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, num_influences, vertices, NULL);
4822 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4823
4824 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, num_influences, NULL, NULL);
4825 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4826
4827 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, num_influences, exp_vertices, exp_weights);
4828 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4829
4830 memset(vertices, 0, sizeof(vertices));
4831 memset(weights, 0, sizeof(weights));
4832 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, vertices, weights);
4833 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4834 for (i = 0; i < num_influences; i++) {
4835 ok(exp_vertices[i] == vertices[i],
4836 "influence[%d]: expected vertex %u, got %u\n", i, exp_vertices[i], vertices[i]);
4837 ok((isnan(exp_weights[i]) && isnan(weights[i])) || exp_weights[i] == weights[i],
4838 "influence[%d]: expected weights %g, got %g\n", i, exp_weights[i], weights[i]);
4839 }
4840
4841 /* vertices and weights aren't returned after setting num_influences to 0 */
4842 memset(vertices, 0, sizeof(vertices));
4843 memset(weights, 0, sizeof(weights));
4844 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, 0, vertices, weights);
4845 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4846
4847 vertices[0] = 0xdeadbeef;
4848 weights[0] = FLT_MAX;
4849 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, vertices, weights);
4850 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4851 ok(vertices[0] == 0xdeadbeef, "expected vertex 0xdeadbeef, got %u\n", vertices[0]);
4852 ok(weights[0] == FLT_MAX, "expected weight %g, got %g\n", FLT_MAX, weights[0]);
4853 }
4854
4855 {
4856 /* test [GS]etFVF and [GS]etDeclaration */
4857 D3DVERTEXELEMENT9 declaration_in[MAX_FVF_DECL_SIZE];
4858 DWORD fvf = D3DFVF_XYZ;
4859 DWORD got_fvf;
4860
4861 hr = skininfo->lpVtbl->SetDeclaration(skininfo, NULL);
4862 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4863
4864 hr = skininfo->lpVtbl->SetDeclaration(skininfo, declaration_with_nonzero_stream);
4865 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4866
4867 hr = skininfo->lpVtbl->SetFVF(skininfo, 0);
4868 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4869
4870 hr = D3DXDeclaratorFromFVF(fvf, declaration_in);
4871 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4872 hr = skininfo->lpVtbl->SetDeclaration(skininfo, declaration_in);
4873 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4874 got_fvf = skininfo->lpVtbl->GetFVF(skininfo);
4875 ok(fvf == got_fvf, "Expected %#x, got %#x\n", fvf, got_fvf);
4876 hr = skininfo->lpVtbl->GetDeclaration(skininfo, declaration_out);
4877 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4878 compare_elements(declaration_out, declaration_in, __LINE__, 0);
4879
4880 hr = skininfo->lpVtbl->SetDeclaration(skininfo, empty_declaration);
4881 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4882 got_fvf = skininfo->lpVtbl->GetFVF(skininfo);
4883 ok(got_fvf == 0, "Expected 0, got %#x\n", got_fvf);
4884 hr = skininfo->lpVtbl->GetDeclaration(skininfo, declaration_out);
4885 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4886 compare_elements(declaration_out, empty_declaration, __LINE__, 0);
4887
4888 hr = skininfo->lpVtbl->SetFVF(skininfo, fvf);
4889 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4890 got_fvf = skininfo->lpVtbl->GetFVF(skininfo);
4891 ok(fvf == got_fvf, "Expected %#x, got %#x\n", fvf, got_fvf);
4892 hr = skininfo->lpVtbl->GetDeclaration(skininfo, declaration_out);
4893 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
4894 compare_elements(declaration_out, declaration_in, __LINE__, 0);
4895 }
4896 }
4897 if (skininfo) IUnknown_Release(skininfo);
4898 skininfo = NULL;
4899
4900 hr = D3DXCreateSkinInfoFVF(1, D3DFVF_XYZ, 1, NULL);
4901 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4902
4903 hr = D3DXCreateSkinInfo(1, NULL, 1, &skininfo);
4904 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
4905 }
4906
4907 static void test_convert_adjacency_to_point_reps(void)
4908 {
4909 HRESULT hr;
4910 struct test_context *test_context = NULL;
4911 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
4912 const DWORD options_16bit = D3DXMESH_SYSTEMMEM;
4913 const D3DVERTEXELEMENT9 declaration[] =
4914 {
4915 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4916 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4917 {0, 24, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4918 D3DDECL_END()
4919 };
4920 const unsigned int VERTS_PER_FACE = 3;
4921 void *vertex_buffer;
4922 void *index_buffer;
4923 DWORD *attributes_buffer;
4924 int i, j;
4925 enum color { RED = 0xffff0000, GREEN = 0xff00ff00, BLUE = 0xff0000ff};
4926 struct vertex_pnc
4927 {
4928 D3DXVECTOR3 position;
4929 D3DXVECTOR3 normal;
4930 enum color color; /* In case of manual visual inspection */
4931 };
4932 D3DXVECTOR3 up = {0.0f, 0.0f, 1.0f};
4933 /* mesh0 (one face)
4934 *
4935 * 0--1
4936 * | /
4937 * |/
4938 * 2
4939 */
4940 const struct vertex_pnc vertices0[] =
4941 {
4942 {{ 0.0f, 3.0f, 0.f}, up, RED},
4943 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
4944 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
4945 };
4946 const DWORD indices0[] = {0, 1, 2};
4947 const unsigned int num_vertices0 = ARRAY_SIZE(vertices0);
4948 const unsigned int num_faces0 = ARRAY_SIZE(indices0) / VERTS_PER_FACE;
4949 const DWORD adjacency0[] = {-1, -1, -1};
4950 const DWORD exp_point_rep0[] = {0, 1, 2};
4951 /* mesh1 (right)
4952 *
4953 * 0--1 3
4954 * | / /|
4955 * |/ / |
4956 * 2 5--4
4957 */
4958 const struct vertex_pnc vertices1[] =
4959 {
4960 {{ 0.0f, 3.0f, 0.f}, up, RED},
4961 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
4962 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
4963
4964 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
4965 {{ 3.0f, 0.0f, 0.f}, up, RED},
4966 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
4967 };
4968 const DWORD indices1[] = {0, 1, 2, 3, 4, 5};
4969 const unsigned int num_vertices1 = ARRAY_SIZE(vertices1);
4970 const unsigned int num_faces1 = ARRAY_SIZE(indices1) / VERTS_PER_FACE;
4971 const DWORD adjacency1[] = {-1, 1, -1, -1, -1, 0};
4972 const DWORD exp_point_rep1[] = {0, 1, 2, 1, 4, 2};
4973 /* mesh2 (left)
4974 *
4975 * 3 0--1
4976 * /| | /
4977 * / | |/
4978 * 5--4 2
4979 */
4980 const struct vertex_pnc vertices2[] =
4981 {
4982 {{ 0.0f, 3.0f, 0.f}, up, RED},
4983 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
4984 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
4985
4986 {{-1.0f, 3.0f, 0.f}, up, RED},
4987 {{-1.0f, 0.0f, 0.f}, up, GREEN},
4988 {{-3.0f, 0.0f, 0.f}, up, BLUE},
4989 };
4990 const DWORD indices2[] = {0, 1, 2, 3, 4, 5};
4991 const unsigned int num_vertices2 = ARRAY_SIZE(vertices2);
4992 const unsigned int num_faces2 = ARRAY_SIZE(indices2) / VERTS_PER_FACE;
4993 const DWORD adjacency2[] = {-1, -1, 1, 0, -1, -1};
4994 const DWORD exp_point_rep2[] = {0, 1, 2, 0, 2, 5};
4995 /* mesh3 (above)
4996 *
4997 * 3
4998 * /|
4999 * / |
5000 * 5--4
5001 * 0--1
5002 * | /
5003 * |/
5004 * 2
5005 */
5006 struct vertex_pnc vertices3[] =
5007 {
5008 {{ 0.0f, 3.0f, 0.f}, up, RED},
5009 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5010 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5011
5012 {{ 2.0f, 7.0f, 0.f}, up, BLUE},
5013 {{ 2.0f, 4.0f, 0.f}, up, GREEN},
5014 {{ 0.0f, 4.0f, 0.f}, up, RED},
5015 };
5016 const DWORD indices3[] = {0, 1, 2, 3, 4, 5};
5017 const unsigned int num_vertices3 = ARRAY_SIZE(vertices3);
5018 const unsigned int num_faces3 = ARRAY_SIZE(indices3) / VERTS_PER_FACE;
5019 const DWORD adjacency3[] = {1, -1, -1, -1, 0, -1};
5020 const DWORD exp_point_rep3[] = {0, 1, 2, 3, 1, 0};
5021 /* mesh4 (below, tip against tip)
5022 *
5023 * 0--1
5024 * | /
5025 * |/
5026 * 2
5027 * 3
5028 * |\
5029 * | \
5030 * 5--4
5031 */
5032 struct vertex_pnc vertices4[] =
5033 {
5034 {{ 0.0f, 3.0f, 0.f}, up, RED},
5035 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5036 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5037
5038 {{ 0.0f, -4.0f, 0.f}, up, BLUE},
5039 {{ 2.0f, -7.0f, 0.f}, up, GREEN},
5040 {{ 0.0f, -7.0f, 0.f}, up, RED},
5041 };
5042 const DWORD indices4[] = {0, 1, 2, 3, 4, 5};
5043 const unsigned int num_vertices4 = ARRAY_SIZE(vertices4);
5044 const unsigned int num_faces4 = ARRAY_SIZE(indices4) / VERTS_PER_FACE;
5045 const DWORD adjacency4[] = {-1, -1, -1, -1, -1, -1};
5046 const DWORD exp_point_rep4[] = {0, 1, 2, 3, 4, 5};
5047 /* mesh5 (gap in mesh)
5048 *
5049 * 0 3-----4 15
5050 * / \ \ / / \
5051 * / \ \ / / \
5052 * 2-----1 5 17-----16
5053 * 6-----7 9 12-----13
5054 * \ / / \ \ /
5055 * \ / / \ \ /
5056 * 8 10-----11 14
5057 *
5058 */
5059 const struct vertex_pnc vertices5[] =
5060 {
5061 {{ 0.0f, 1.0f, 0.f}, up, RED},
5062 {{ 1.0f, -1.0f, 0.f}, up, GREEN},
5063 {{-1.0f, -1.0f, 0.f}, up, BLUE},
5064
5065 {{ 0.1f, 1.0f, 0.f}, up, RED},
5066 {{ 2.1f, 1.0f, 0.f}, up, BLUE},
5067 {{ 1.1f, -1.0f, 0.f}, up, GREEN},
5068
5069 {{-1.0f, -1.1f, 0.f}, up, BLUE},
5070 {{ 1.0f, -1.1f, 0.f}, up, GREEN},
5071 {{ 0.0f, -3.1f, 0.f}, up, RED},
5072
5073 {{ 1.1f, -1.1f, 0.f}, up, GREEN},
5074 {{ 2.1f, -3.1f, 0.f}, up, BLUE},
5075 {{ 0.1f, -3.1f, 0.f}, up, RED},
5076
5077 {{ 1.2f, -1.1f, 0.f}, up, GREEN},
5078 {{ 3.2f, -1.1f, 0.f}, up, RED},
5079 {{ 2.2f, -3.1f, 0.f}, up, BLUE},
5080
5081 {{ 2.2f, 1.0f, 0.f}, up, BLUE},
5082 {{ 3.2f, -1.0f, 0.f}, up, RED},
5083 {{ 1.2f, -1.0f, 0.f}, up, GREEN},
5084 };
5085 const DWORD indices5[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17};
5086 const unsigned int num_vertices5 = ARRAY_SIZE(vertices5);
5087 const unsigned int num_faces5 = ARRAY_SIZE(indices5) / VERTS_PER_FACE;
5088 const DWORD adjacency5[] = {-1, 2, -1, -1, 5, -1, 0, -1, -1, 4, -1, -1, 5, -1, 3, -1, 4, 1};
5089 const DWORD exp_point_rep5[] = {0, 1, 2, 3, 4, 5, 2, 1, 8, 5, 10, 11, 5, 13, 10, 4, 13, 5};
5090 const WORD indices5_16bit[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17};
5091 /* mesh6 (indices re-ordering)
5092 *
5093 * 0--1 6 3
5094 * | / /| |\
5095 * |/ / | | \
5096 * 2 8--7 5--4
5097 */
5098 const struct vertex_pnc vertices6[] =
5099 {
5100 {{ 0.0f, 3.0f, 0.f}, up, RED},
5101 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5102 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5103
5104 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5105 {{ 3.0f, 0.0f, 0.f}, up, RED},
5106 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5107
5108 {{ 4.0f, 3.0f, 0.f}, up, GREEN},
5109 {{ 6.0f, 0.0f, 0.f}, up, BLUE},
5110 {{ 4.0f, 0.0f, 0.f}, up, RED},
5111 };
5112 const DWORD indices6[] = {0, 1, 2, 6, 7, 8, 3, 4, 5};
5113 const unsigned int num_vertices6 = ARRAY_SIZE(vertices6);
5114 const unsigned int num_faces6 = ARRAY_SIZE(indices6) / VERTS_PER_FACE;
5115 const DWORD adjacency6[] = {-1, 1, -1, 2, -1, 0, -1, -1, 1};
5116 const DWORD exp_point_rep6[] = {0, 1, 2, 1, 4, 5, 1, 5, 2};
5117 /* mesh7 (expands collapsed triangle)
5118 *
5119 * 0--1 3
5120 * | / /|
5121 * |/ / |
5122 * 2 5--4
5123 */
5124 const struct vertex_pnc vertices7[] =
5125 {
5126 {{ 0.0f, 3.0f, 0.f}, up, RED},
5127 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5128 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5129
5130 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5131 {{ 3.0f, 0.0f, 0.f}, up, RED},
5132 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5133 };
5134 const DWORD indices7[] = {0, 1, 2, 3, 3, 3}; /* Face 1 is collapsed*/
5135 const unsigned int num_vertices7 = ARRAY_SIZE(vertices7);
5136 const unsigned int num_faces7 = ARRAY_SIZE(indices7) / VERTS_PER_FACE;
5137 const DWORD adjacency7[] = {-1, -1, -1, -1, -1, -1};
5138 const DWORD exp_point_rep7[] = {0, 1, 2, 3, 4, 5};
5139 /* mesh8 (indices re-ordering and double replacement)
5140 *
5141 * 0--1 9 6
5142 * | / /| |\
5143 * |/ / | | \
5144 * 2 11-10 8--7
5145 * 3--4
5146 * | /
5147 * |/
5148 * 5
5149 */
5150 const struct vertex_pnc vertices8[] =
5151 {
5152 {{ 0.0f, 3.0f, 0.f}, up, RED},
5153 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5154 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5155
5156 {{ 4.0, -4.0, 0.f}, up, RED},
5157 {{ 6.0, -4.0, 0.f}, up, BLUE},
5158 {{ 4.0, -7.0, 0.f}, up, GREEN},
5159
5160 {{ 4.0f, 3.0f, 0.f}, up, GREEN},
5161 {{ 6.0f, 0.0f, 0.f}, up, BLUE},
5162 {{ 4.0f, 0.0f, 0.f}, up, RED},
5163
5164 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5165 {{ 3.0f, 0.0f, 0.f}, up, RED},
5166 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5167 };
5168 const DWORD indices8[] = {0, 1, 2, 9, 10, 11, 6, 7, 8, 3, 4, 5};
5169 const unsigned int num_vertices8 = ARRAY_SIZE(vertices8);
5170 const unsigned int num_faces8 = ARRAY_SIZE(indices8) / VERTS_PER_FACE;
5171 const DWORD adjacency8[] = {-1, 1, -1, 2, -1, 0, -1, 3, 1, 2, -1, -1};
5172 const DWORD exp_point_rep8[] = {0, 1, 2, 3, 4, 5, 1, 4, 3, 1, 3, 2};
5173 /* mesh9 (right, shared vertices)
5174 *
5175 * 0--1
5176 * | /|
5177 * |/ |
5178 * 2--3
5179 */
5180 const struct vertex_pnc vertices9[] =
5181 {
5182 {{ 0.0f, 3.0f, 0.f}, up, RED},
5183 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5184 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5185
5186 {{ 2.0f, 0.0f, 0.f}, up, RED},
5187 };
5188 const DWORD indices9[] = {0, 1, 2, 1, 3, 2};
5189 const unsigned int num_vertices9 = ARRAY_SIZE(vertices9);
5190 const unsigned int num_faces9 = ARRAY_SIZE(indices9) / VERTS_PER_FACE;
5191 const DWORD adjacency9[] = {-1, 1, -1, -1, -1, 0};
5192 const DWORD exp_point_rep9[] = {0, 1, 2, 3};
5193 /* All mesh data */
5194 ID3DXMesh *mesh = NULL;
5195 ID3DXMesh *mesh_null_check = NULL;
5196 unsigned int attributes[] = {0};
5197 struct
5198 {
5199 const struct vertex_pnc *vertices;
5200 const DWORD *indices;
5201 const DWORD num_vertices;
5202 const DWORD num_faces;
5203 const DWORD *adjacency;
5204 const DWORD *exp_point_reps;
5205 const DWORD options;
5206 }
5207 tc[] =
5208 {
5209 {
5210 vertices0,
5211 indices0,
5212 num_vertices0,
5213 num_faces0,
5214 adjacency0,
5215 exp_point_rep0,
5216 options
5217 },
5218 {
5219 vertices1,
5220 indices1,
5221 num_vertices1,
5222 num_faces1,
5223 adjacency1,
5224 exp_point_rep1,
5225 options
5226 },
5227 {
5228 vertices2,
5229 indices2,
5230 num_vertices2,
5231 num_faces2,
5232 adjacency2,
5233 exp_point_rep2,
5234 options
5235 },
5236 {
5237 vertices3,
5238 indices3,
5239 num_vertices3,
5240 num_faces3,
5241 adjacency3,
5242 exp_point_rep3,
5243 options
5244 },
5245 {
5246 vertices4,
5247 indices4,
5248 num_vertices4,
5249 num_faces4,
5250 adjacency4,
5251 exp_point_rep4,
5252 options
5253 },
5254 {
5255 vertices5,
5256 indices5,
5257 num_vertices5,
5258 num_faces5,
5259 adjacency5,
5260 exp_point_rep5,
5261 options
5262 },
5263 {
5264 vertices6,
5265 indices6,
5266 num_vertices6,
5267 num_faces6,
5268 adjacency6,
5269 exp_point_rep6,
5270 options
5271 },
5272 {
5273 vertices7,
5274 indices7,
5275 num_vertices7,
5276 num_faces7,
5277 adjacency7,
5278 exp_point_rep7,
5279 options
5280 },
5281 {
5282 vertices8,
5283 indices8,
5284 num_vertices8,
5285 num_faces8,
5286 adjacency8,
5287 exp_point_rep8,
5288 options
5289 },
5290 {
5291 vertices9,
5292 indices9,
5293 num_vertices9,
5294 num_faces9,
5295 adjacency9,
5296 exp_point_rep9,
5297 options
5298 },
5299 {
5300 vertices5,
5301 (DWORD*)indices5_16bit,
5302 num_vertices5,
5303 num_faces5,
5304 adjacency5,
5305 exp_point_rep5,
5306 options_16bit
5307 },
5308 };
5309 DWORD *point_reps = NULL;
5310
5311 test_context = new_test_context();
5312 if (!test_context)
5313 {
5314 skip("Couldn't create test context\n");
5315 goto cleanup;
5316 }
5317
5318 for (i = 0; i < ARRAY_SIZE(tc); i++)
5319 {
5320 hr = D3DXCreateMesh(tc[i].num_faces, tc[i].num_vertices, tc[i].options, declaration,
5321 test_context->device, &mesh);
5322 if (FAILED(hr))
5323 {
5324 skip("Couldn't create mesh %d. Got %x expected D3D_OK\n", i, hr);
5325 goto cleanup;
5326 }
5327
5328 if (i == 0) /* Save first mesh for later NULL checks */
5329 mesh_null_check = mesh;
5330
5331 point_reps = HeapAlloc(GetProcessHeap(), 0, tc[i].num_vertices * sizeof(*point_reps));
5332 if (!point_reps)
5333 {
5334 skip("Couldn't allocate point reps array.\n");
5335 goto cleanup;
5336 }
5337
5338 hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, &vertex_buffer);
5339 if (FAILED(hr))
5340 {
5341 skip("Couldn't lock vertex buffer.\n");
5342 goto cleanup;
5343 }
5344 memcpy(vertex_buffer, tc[i].vertices, tc[i].num_vertices * sizeof(*tc[i].vertices));
5345 hr = mesh->lpVtbl->UnlockVertexBuffer(mesh);
5346 if (FAILED(hr))
5347 {
5348 skip("Couldn't unlock vertex buffer.\n");
5349 goto cleanup;
5350 }
5351
5352 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, &index_buffer);
5353 if (FAILED(hr))
5354 {
5355 skip("Couldn't lock index buffer.\n");
5356 goto cleanup;
5357 }
5358 if (tc[i].options & D3DXMESH_32BIT)
5359 {
5360 memcpy(index_buffer, tc[i].indices, VERTS_PER_FACE * tc[i].num_faces * sizeof(DWORD));
5361 }
5362 else
5363 {
5364 memcpy(index_buffer, tc[i].indices, VERTS_PER_FACE * tc[i].num_faces * sizeof(WORD));
5365 }
5366 hr = mesh->lpVtbl->UnlockIndexBuffer(mesh);
5367 if (FAILED(hr)) {
5368 skip("Couldn't unlock index buffer.\n");
5369 goto cleanup;
5370 }
5371
5372 hr = mesh->lpVtbl->LockAttributeBuffer(mesh, 0, &attributes_buffer);
5373 if (FAILED(hr))
5374 {
5375 skip("Couldn't lock attributes buffer.\n");
5376 goto cleanup;
5377 }
5378 memcpy(attributes_buffer, attributes, sizeof(attributes));
5379 hr = mesh->lpVtbl->UnlockAttributeBuffer(mesh);
5380 if (FAILED(hr))
5381 {
5382 skip("Couldn't unlock attributes buffer.\n");
5383 goto cleanup;
5384 }
5385
5386 /* Convert adjacency to point representation */
5387 for (j = 0; j < tc[i].num_vertices; j++) point_reps[j] = -1;
5388 hr = mesh->lpVtbl->ConvertAdjacencyToPointReps(mesh, tc[i].adjacency, point_reps);
5389 ok(hr == D3D_OK, "ConvertAdjacencyToPointReps failed case %d. "
5390 "Got %x expected D3D_OK\n", i, hr);
5391
5392 /* Check point representation */
5393 for (j = 0; j < tc[i].num_vertices; j++)
5394 {
5395 ok(point_reps[j] == tc[i].exp_point_reps[j],
5396 "Unexpected point representation at (%d, %d)."
5397 " Got %d expected %d\n",
5398 i, j, point_reps[j], tc[i].exp_point_reps[j]);
5399 }
5400
5401 HeapFree(GetProcessHeap(), 0, point_reps);
5402 point_reps = NULL;
5403
5404 if (i != 0) /* First mesh will be freed during cleanup */
5405 mesh->lpVtbl->Release(mesh);
5406 }
5407
5408 /* NULL checks */
5409 hr = mesh_null_check->lpVtbl->ConvertAdjacencyToPointReps(mesh_null_check, tc[0].adjacency, NULL);
5410 ok(hr == D3DERR_INVALIDCALL, "ConvertAdjacencyToPointReps point_reps NULL. "
5411 "Got %x expected D3DERR_INVALIDCALL\n", hr);
5412 hr = mesh_null_check->lpVtbl->ConvertAdjacencyToPointReps(mesh_null_check, NULL, NULL);
5413 ok(hr == D3DERR_INVALIDCALL, "ConvertAdjacencyToPointReps adjacency and point_reps NULL. "
5414 "Got %x expected D3DERR_INVALIDCALL\n", hr);
5415
5416 cleanup:
5417 if (mesh_null_check)
5418 mesh_null_check->lpVtbl->Release(mesh_null_check);
5419 HeapFree(GetProcessHeap(), 0, point_reps);
5420 free_test_context(test_context);
5421 }
5422
5423 static void test_convert_point_reps_to_adjacency(void)
5424 {
5425 HRESULT hr;
5426 struct test_context *test_context = NULL;
5427 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
5428 const DWORD options_16bit = D3DXMESH_SYSTEMMEM;
5429 const D3DVERTEXELEMENT9 declaration[] =
5430 {
5431 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
5432 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
5433 {0, 24, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
5434 D3DDECL_END()
5435 };
5436 const unsigned int VERTS_PER_FACE = 3;
5437 void *vertex_buffer;
5438 void *index_buffer;
5439 DWORD *attributes_buffer;
5440 int i, j;
5441 enum color { RED = 0xffff0000, GREEN = 0xff00ff00, BLUE = 0xff0000ff};
5442 struct vertex_pnc
5443 {
5444 D3DXVECTOR3 position;
5445 D3DXVECTOR3 normal;
5446 enum color color; /* In case of manual visual inspection */
5447 };
5448 D3DXVECTOR3 up = {0.0f, 0.0f, 1.0f};
5449 /* mesh0 (one face)
5450 *
5451 * 0--1
5452 * | /
5453 * |/
5454 * 2
5455 */
5456 const struct vertex_pnc vertices0[] =
5457 {
5458 {{ 0.0f, 3.0f, 0.f}, up, RED},
5459 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5460 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5461 };
5462 const DWORD indices0[] = {0, 1, 2};
5463 const unsigned int num_vertices0 = ARRAY_SIZE(vertices0);
5464 const unsigned int num_faces0 = num_vertices0 / VERTS_PER_FACE;
5465 const DWORD exp_adjacency0[] = {-1, -1, -1};
5466 const DWORD exp_id_adjacency0[] = {-1, -1, -1};
5467 const DWORD point_rep0[] = {0, 1, 2};
5468 /* mesh1 (right)
5469 *
5470 * 0--1 3
5471 * | / /|
5472 * |/ / |
5473 * 2 5--4
5474 */
5475 const struct vertex_pnc vertices1[] =
5476 {
5477 {{ 0.0f, 3.0f, 0.f}, up, RED},
5478 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5479 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5480
5481 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5482 {{ 3.0f, 0.0f, 0.f}, up, RED},
5483 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5484 };
5485 const DWORD indices1[] = {0, 1, 2, 3, 4, 5};
5486 const unsigned int num_vertices1 = ARRAY_SIZE(vertices1);
5487 const unsigned int num_faces1 = num_vertices1 / VERTS_PER_FACE;
5488 const DWORD exp_adjacency1[] = {-1, 1, -1, -1, -1, 0};
5489 const DWORD exp_id_adjacency1[] = {-1, -1, -1, -1, -1, -1};
5490 const DWORD point_rep1[] = {0, 1, 2, 1, 4, 2};
5491 /* mesh2 (left)
5492 *
5493 * 3 0--1
5494 * /| | /
5495 * / | |/
5496 * 5--4 2
5497 */
5498 const struct vertex_pnc vertices2[] =
5499 {
5500 {{ 0.0f, 3.0f, 0.f}, up, RED},
5501 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5502 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5503
5504 {{-1.0f, 3.0f, 0.f}, up, RED},
5505 {{-1.0f, 0.0f, 0.f}, up, GREEN},
5506 {{-3.0f, 0.0f, 0.f}, up, BLUE},
5507 };
5508 const DWORD indices2[] = {0, 1, 2, 3, 4, 5};
5509 const unsigned int num_vertices2 = ARRAY_SIZE(vertices2);
5510 const unsigned int num_faces2 = num_vertices2 / VERTS_PER_FACE;
5511 const DWORD exp_adjacency2[] = {-1, -1, 1, 0, -1, -1};
5512 const DWORD exp_id_adjacency2[] = {-1, -1, -1, -1, -1, -1};
5513 const DWORD point_rep2[] = {0, 1, 2, 0, 2, 5};
5514 /* mesh3 (above)
5515 *
5516 * 3
5517 * /|
5518 * / |
5519 * 5--4
5520 * 0--1
5521 * | /
5522 * |/
5523 * 2
5524 */
5525 struct vertex_pnc vertices3[] =
5526 {
5527 {{ 0.0f, 3.0f, 0.f}, up, RED},
5528 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5529 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5530
5531 {{ 2.0f, 7.0f, 0.f}, up, BLUE},
5532 {{ 2.0f, 4.0f, 0.f}, up, GREEN},
5533 {{ 0.0f, 4.0f, 0.f}, up, RED},
5534 };
5535 const DWORD indices3[] = {0, 1, 2, 3, 4, 5};
5536 const unsigned int num_vertices3 = ARRAY_SIZE(vertices3);
5537 const unsigned int num_faces3 = num_vertices3 / VERTS_PER_FACE;
5538 const DWORD exp_adjacency3[] = {1, -1, -1, -1, 0, -1};
5539 const DWORD exp_id_adjacency3[] = {-1, -1, -1, -1, -1, -1};
5540 const DWORD point_rep3[] = {0, 1, 2, 3, 1, 0};
5541 /* mesh4 (below, tip against tip)
5542 *
5543 * 0--1
5544 * | /
5545 * |/
5546 * 2
5547 * 3
5548 * |\
5549 * | \
5550 * 5--4
5551 */
5552 struct vertex_pnc vertices4[] =
5553 {
5554 {{ 0.0f, 3.0f, 0.f}, up, RED},
5555 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5556 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5557
5558 {{ 0.0f, -4.0f, 0.f}, up, BLUE},
5559 {{ 2.0f, -7.0f, 0.f}, up, GREEN},
5560 {{ 0.0f, -7.0f, 0.f}, up, RED},
5561 };
5562 const DWORD indices4[] = {0, 1, 2, 3, 4, 5};
5563 const unsigned int num_vertices4 = ARRAY_SIZE(vertices4);
5564 const unsigned int num_faces4 = num_vertices4 / VERTS_PER_FACE;
5565 const DWORD exp_adjacency4[] = {-1, -1, -1, -1, -1, -1};
5566 const DWORD exp_id_adjacency4[] = {-1, -1, -1, -1, -1, -1};
5567 const DWORD point_rep4[] = {0, 1, 2, 3, 4, 5};
5568 /* mesh5 (gap in mesh)
5569 *
5570 * 0 3-----4 15
5571 * / \ \ / / \
5572 * / \ \ / / \
5573 * 2-----1 5 17-----16
5574 * 6-----7 9 12-----13
5575 * \ / / \ \ /
5576 * \ / / \ \ /
5577 * 8 10-----11 14
5578 *
5579 */
5580 const struct vertex_pnc vertices5[] =
5581 {
5582 {{ 0.0f, 1.0f, 0.f}, up, RED},
5583 {{ 1.0f, -1.0f, 0.f}, up, GREEN},
5584 {{-1.0f, -1.0f, 0.f}, up, BLUE},
5585
5586 {{ 0.1f, 1.0f, 0.f}, up, RED},
5587 {{ 2.1f, 1.0f, 0.f}, up, BLUE},
5588 {{ 1.1f, -1.0f, 0.f}, up, GREEN},
5589
5590 {{-1.0f, -1.1f, 0.f}, up, BLUE},
5591 {{ 1.0f, -1.1f, 0.f}, up, GREEN},
5592 {{ 0.0f, -3.1f, 0.f}, up, RED},
5593
5594 {{ 1.1f, -1.1f, 0.f}, up, GREEN},
5595 {{ 2.1f, -3.1f, 0.f}, up, BLUE},
5596 {{ 0.1f, -3.1f, 0.f}, up, RED},
5597
5598 {{ 1.2f, -1.1f, 0.f}, up, GREEN},
5599 {{ 3.2f, -1.1f, 0.f}, up, RED},
5600 {{ 2.2f, -3.1f, 0.f}, up, BLUE},
5601
5602 {{ 2.2f, 1.0f, 0.f}, up, BLUE},
5603 {{ 3.2f, -1.0f, 0.f}, up, RED},
5604 {{ 1.2f, -1.0f, 0.f}, up, GREEN},
5605 };
5606 const DWORD indices5[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17};
5607 const unsigned int num_vertices5 = ARRAY_SIZE(vertices5);
5608 const unsigned int num_faces5 = num_vertices5 / VERTS_PER_FACE;
5609 const DWORD exp_adjacency5[] = {-1, 2, -1, -1, 5, -1, 0, -1, -1, 4, -1, -1, 5, -1, 3, -1, 4, 1};
5610 const DWORD exp_id_adjacency5[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
5611 const DWORD point_rep5[] = {0, 1, 2, 3, 4, 5, 2, 1, 8, 5, 10, 11, 5, 13, 10, 4, 13, 5};
5612 /* mesh6 (indices re-ordering)
5613 *
5614 * 0--1 6 3
5615 * | / /| |\
5616 * |/ / | | \
5617 * 2 8--7 5--4
5618 */
5619 const struct vertex_pnc vertices6[] =
5620 {
5621 {{ 0.0f, 3.0f, 0.f}, up, RED},
5622 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5623 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5624
5625 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5626 {{ 3.0f, 0.0f, 0.f}, up, RED},
5627 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5628
5629 {{ 4.0f, 3.0f, 0.f}, up, GREEN},
5630 {{ 6.0f, 0.0f, 0.f}, up, BLUE},
5631 {{ 4.0f, 0.0f, 0.f}, up, RED},
5632 };
5633 const DWORD indices6[] = {0, 1, 2, 6, 7, 8, 3, 4, 5};
5634 const unsigned int num_vertices6 = ARRAY_SIZE(vertices6);
5635 const unsigned int num_faces6 = num_vertices6 / VERTS_PER_FACE;
5636 const DWORD exp_adjacency6[] = {-1, 1, -1, 2, -1, 0, -1, -1, 1};
5637 const DWORD exp_id_adjacency6[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1};
5638 const DWORD point_rep6[] = {0, 1, 2, 1, 4, 5, 1, 5, 2};
5639 /* mesh7 (expands collapsed triangle)
5640 *
5641 * 0--1 3
5642 * | / /|
5643 * |/ / |
5644 * 2 5--4
5645 */
5646 const struct vertex_pnc vertices7[] =
5647 {
5648 {{ 0.0f, 3.0f, 0.f}, up, RED},
5649 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5650 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5651
5652 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5653 {{ 3.0f, 0.0f, 0.f}, up, RED},
5654 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5655 };
5656 const DWORD indices7[] = {0, 1, 2, 3, 3, 3}; /* Face 1 is collapsed*/
5657 const unsigned int num_vertices7 = ARRAY_SIZE(vertices7);
5658 const unsigned int num_faces7 = num_vertices7 / VERTS_PER_FACE;
5659 const DWORD exp_adjacency7[] = {-1, -1, -1, -1, -1, -1};
5660 const DWORD exp_id_adjacency7[] = {-1, -1, -1, -1, -1, -1};
5661 const DWORD point_rep7[] = {0, 1, 2, 3, 4, 5};
5662 /* mesh8 (indices re-ordering and double replacement)
5663 *
5664 * 0--1 9 6
5665 * | / /| |\
5666 * |/ / | | \
5667 * 2 11-10 8--7
5668 * 3--4
5669 * | /
5670 * |/
5671 * 5
5672 */
5673 const struct vertex_pnc vertices8[] =
5674 {
5675 {{ 0.0f, 3.0f, 0.f}, up, RED},
5676 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5677 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5678
5679 {{ 4.0, -4.0, 0.f}, up, RED},
5680 {{ 6.0, -4.0, 0.f}, up, BLUE},
5681 {{ 4.0, -7.0, 0.f}, up, GREEN},
5682
5683 {{ 4.0f, 3.0f, 0.f}, up, GREEN},
5684 {{ 6.0f, 0.0f, 0.f}, up, BLUE},
5685 {{ 4.0f, 0.0f, 0.f}, up, RED},
5686
5687 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5688 {{ 3.0f, 0.0f, 0.f}, up, RED},
5689 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5690 };
5691 const DWORD indices8[] = {0, 1, 2, 9, 10, 11, 6, 7, 8, 3, 4, 5};
5692 const WORD indices8_16bit[] = {0, 1, 2, 9, 10, 11, 6, 7, 8, 3, 4, 5};
5693 const unsigned int num_vertices8 = ARRAY_SIZE(vertices8);
5694 const unsigned int num_faces8 = num_vertices8 / VERTS_PER_FACE;
5695 const DWORD exp_adjacency8[] = {-1, 1, -1, 2, -1, 0, -1, 3, 1, 2, -1, -1};
5696 const DWORD exp_id_adjacency8[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
5697 const DWORD point_rep8[] = {0, 1, 2, 3, 4, 5, 1, 4, 3, 1, 3, 2};
5698 /* mesh9 (right, shared vertices)
5699 *
5700 * 0--1
5701 * | /|
5702 * |/ |
5703 * 2--3
5704 */
5705 const struct vertex_pnc vertices9[] =
5706 {
5707 {{ 0.0f, 3.0f, 0.f}, up, RED},
5708 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5709 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5710
5711 {{ 2.0f, 0.0f, 0.f}, up, RED},
5712 };
5713 const DWORD indices9[] = {0, 1, 2, 1, 3, 2};
5714 const unsigned int num_vertices9 = ARRAY_SIZE(vertices9);
5715 const unsigned int num_faces9 = 2;
5716 const DWORD exp_adjacency9[] = {-1, 1, -1, -1, -1, 0};
5717 const DWORD exp_id_adjacency9[] = {-1, 1, -1, -1, -1, 0};
5718 const DWORD point_rep9[] = {0, 1, 2, 3};
5719 /* All mesh data */
5720 ID3DXMesh *mesh = NULL;
5721 ID3DXMesh *mesh_null_check = NULL;
5722 unsigned int attributes[] = {0};
5723 struct
5724 {
5725 const struct vertex_pnc *vertices;
5726 const DWORD *indices;
5727 const DWORD num_vertices;
5728 const DWORD num_faces;
5729 const DWORD *point_reps;
5730 const DWORD *exp_adjacency;
5731 const DWORD *exp_id_adjacency;
5732 const DWORD options;
5733 }
5734 tc[] =
5735 {
5736 {
5737 vertices0,
5738 indices0,
5739 num_vertices0,
5740 num_faces0,
5741 point_rep0,
5742 exp_adjacency0,
5743 exp_id_adjacency0,
5744 options
5745 },
5746 {
5747 vertices1,
5748 indices1,
5749 num_vertices1,
5750 num_faces1,
5751 point_rep1,
5752 exp_adjacency1,
5753 exp_id_adjacency1,
5754 options
5755 },
5756 {
5757 vertices2,
5758 indices2,
5759 num_vertices2,
5760 num_faces2,
5761 point_rep2,
5762 exp_adjacency2,
5763 exp_id_adjacency2,
5764 options
5765 },
5766 {
5767 vertices3,
5768 indices3,
5769 num_vertices3,
5770 num_faces3,
5771 point_rep3,
5772 exp_adjacency3,
5773 exp_id_adjacency3,
5774 options
5775 },
5776 {
5777 vertices4,
5778 indices4,
5779 num_vertices4,
5780 num_faces4,
5781 point_rep4,
5782 exp_adjacency4,
5783 exp_id_adjacency4,
5784 options
5785 },
5786 {
5787 vertices5,
5788 indices5,
5789 num_vertices5,
5790 num_faces5,
5791 point_rep5,
5792 exp_adjacency5,
5793 exp_id_adjacency5,
5794 options
5795 },
5796 {
5797 vertices6,
5798 indices6,
5799 num_vertices6,
5800 num_faces6,
5801 point_rep6,
5802 exp_adjacency6,
5803 exp_id_adjacency6,
5804 options
5805 },
5806 {
5807 vertices7,
5808 indices7,
5809 num_vertices7,
5810 num_faces7,
5811 point_rep7,
5812 exp_adjacency7,
5813 exp_id_adjacency7,
5814 options
5815 },
5816 {
5817 vertices8,
5818 indices8,
5819 num_vertices8,
5820 num_faces8,
5821 point_rep8,
5822 exp_adjacency8,
5823 exp_id_adjacency8,
5824 options
5825 },
5826 {
5827 vertices9,
5828 indices9,
5829 num_vertices9,
5830 num_faces9,
5831 point_rep9,
5832 exp_adjacency9,
5833 exp_id_adjacency9,
5834 options
5835 },
5836 {
5837 vertices8,
5838 (DWORD*)indices8_16bit,
5839 num_vertices8,
5840 num_faces8,
5841 point_rep8,
5842 exp_adjacency8,
5843 exp_id_adjacency8,
5844 options_16bit
5845 },
5846 };
5847 DWORD *adjacency = NULL;
5848
5849 test_context = new_test_context();
5850 if (!test_context)
5851 {
5852 skip("Couldn't create test context\n");
5853 goto cleanup;
5854 }
5855
5856 for (i = 0; i < ARRAY_SIZE(tc); i++)
5857 {
5858 hr = D3DXCreateMesh(tc[i].num_faces, tc[i].num_vertices, tc[i].options,
5859 declaration, test_context->device, &mesh);
5860 if (FAILED(hr))
5861 {
5862 skip("Couldn't create mesh %d. Got %x expected D3D_OK\n", i, hr);
5863 goto cleanup;
5864 }
5865
5866 if (i == 0) /* Save first mesh for later NULL checks */
5867 mesh_null_check = mesh;
5868
5869 adjacency = HeapAlloc(GetProcessHeap(), 0, VERTS_PER_FACE * tc[i].num_faces * sizeof(*adjacency));
5870 if (!adjacency)
5871 {
5872 skip("Couldn't allocate adjacency array.\n");
5873 goto cleanup;
5874 }
5875
5876 hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, &vertex_buffer);
5877 if (FAILED(hr))
5878 {
5879 skip("Couldn't lock vertex buffer.\n");
5880 goto cleanup;
5881 }
5882 memcpy(vertex_buffer, tc[i].vertices, tc[i].num_vertices * sizeof(*tc[i].vertices));
5883 hr = mesh->lpVtbl->UnlockVertexBuffer(mesh);
5884 if (FAILED(hr))
5885 {
5886 skip("Couldn't unlock vertex buffer.\n");
5887 goto cleanup;
5888 }
5889 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, &index_buffer);
5890 if (FAILED(hr))
5891 {
5892 skip("Couldn't lock index buffer.\n");
5893 goto cleanup;
5894 }
5895 if (tc[i].options & D3DXMESH_32BIT)
5896 {
5897 memcpy(index_buffer, tc[i].indices, VERTS_PER_FACE * tc[i].num_faces * sizeof(DWORD));
5898 }
5899 else
5900 {
5901 memcpy(index_buffer, tc[i].indices, VERTS_PER_FACE * tc[i].num_faces * sizeof(WORD));
5902 }
5903 hr = mesh->lpVtbl->UnlockIndexBuffer(mesh);
5904 if (FAILED(hr)) {
5905 skip("Couldn't unlock index buffer.\n");
5906 goto cleanup;
5907 }
5908
5909 hr = mesh->lpVtbl->LockAttributeBuffer(mesh, 0, &attributes_buffer);
5910 if (FAILED(hr))
5911 {
5912 skip("Couldn't lock attributes buffer.\n");
5913 goto cleanup;
5914 }
5915 memcpy(attributes_buffer, attributes, sizeof(attributes));
5916 hr = mesh->lpVtbl->UnlockAttributeBuffer(mesh);
5917 if (FAILED(hr))
5918 {
5919 skip("Couldn't unlock attributes buffer.\n");
5920 goto cleanup;
5921 }
5922
5923 /* Convert point representation to adjacency*/
5924 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++) adjacency[j] = -2;
5925
5926 hr = mesh->lpVtbl->ConvertPointRepsToAdjacency(mesh, tc[i].point_reps, adjacency);
5927 ok(hr == D3D_OK, "ConvertPointRepsToAdjacency failed case %d. "
5928 "Got %x expected D3D_OK\n", i, hr);
5929 /* Check adjacency */
5930 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
5931 {
5932 ok(adjacency[j] == tc[i].exp_adjacency[j],
5933 "Unexpected adjacency information at (%d, %d)."
5934 " Got %d expected %d\n",
5935 i, j, adjacency[j], tc[i].exp_adjacency[j]);
5936 }
5937
5938 /* NULL point representation is considered identity. */
5939 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++) adjacency[j] = -2;
5940 hr = mesh_null_check->lpVtbl->ConvertPointRepsToAdjacency(mesh, NULL, adjacency);
5941 ok(hr == D3D_OK, "ConvertPointRepsToAdjacency NULL point_reps. "
5942 "Got %x expected D3D_OK\n", hr);
5943 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
5944 {
5945 ok(adjacency[j] == tc[i].exp_id_adjacency[j],
5946 "Unexpected adjacency information (id) at (%d, %d)."
5947 " Got %d expected %d\n",
5948 i, j, adjacency[j], tc[i].exp_id_adjacency[j]);
5949 }
5950
5951 HeapFree(GetProcessHeap(), 0, adjacency);
5952 adjacency = NULL;
5953 if (i != 0) /* First mesh will be freed during cleanup */
5954 mesh->lpVtbl->Release(mesh);
5955 }
5956
5957 /* NULL checks */
5958 hr = mesh_null_check->lpVtbl->ConvertPointRepsToAdjacency(mesh_null_check, tc[0].point_reps, NULL);
5959 ok(hr == D3DERR_INVALIDCALL, "ConvertPointRepsToAdjacency NULL adjacency. "
5960 "Got %x expected D3DERR_INVALIDCALL\n", hr);
5961 hr = mesh_null_check->lpVtbl->ConvertPointRepsToAdjacency(mesh_null_check, NULL, NULL);
5962 ok(hr == D3DERR_INVALIDCALL, "ConvertPointRepsToAdjacency NULL point_reps and adjacency. "
5963 "Got %x expected D3DERR_INVALIDCALL\n", hr);
5964
5965 cleanup:
5966 if (mesh_null_check)
5967 mesh_null_check->lpVtbl->Release(mesh_null_check);
5968 HeapFree(GetProcessHeap(), 0, adjacency);
5969 free_test_context(test_context);
5970 }
5971
5972 static HRESULT init_test_mesh(const DWORD num_faces, const DWORD num_vertices,
5973 const DWORD options,
5974 const D3DVERTEXELEMENT9 *declaration,
5975 IDirect3DDevice9 *device, ID3DXMesh **mesh_ptr,
5976 const void *vertices, const DWORD vertex_size,
5977 const DWORD *indices, const DWORD *attributes)
5978 {
5979 HRESULT hr;
5980 void *vertex_buffer;
5981 void *index_buffer;
5982 DWORD *attributes_buffer;
5983 ID3DXMesh *mesh = NULL;
5984
5985 hr = D3DXCreateMesh(num_faces, num_vertices, options, declaration, device, mesh_ptr);
5986 if (FAILED(hr))
5987 {
5988 skip("Couldn't create mesh. Got %x expected D3D_OK\n", hr);
5989 goto cleanup;
5990 }
5991 mesh = *mesh_ptr;
5992
5993 hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, &vertex_buffer);
5994 if (FAILED(hr))
5995 {
5996 skip("Couldn't lock vertex buffer.\n");
5997 goto cleanup;
5998 }
5999 memcpy(vertex_buffer, vertices, num_vertices * vertex_size);
6000 hr = mesh->lpVtbl->UnlockVertexBuffer(mesh);
6001 if (FAILED(hr))
6002 {
6003 skip("Couldn't unlock vertex buffer.\n");
6004 goto cleanup;
6005 }
6006
6007 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, &index_buffer);
6008 if (FAILED(hr))
6009 {
6010 skip("Couldn't lock index buffer.\n");
6011 goto cleanup;
6012 }
6013 if (options & D3DXMESH_32BIT)
6014 {
6015 if (indices)
6016 memcpy(index_buffer, indices, 3 * num_faces * sizeof(DWORD));
6017 else
6018 {
6019 /* Fill index buffer with 0, 1, 2, ...*/
6020 DWORD *indices_32bit = (DWORD*)index_buffer;
6021 UINT i;
6022 for (i = 0; i < 3 * num_faces; i++)
6023 indices_32bit[i] = i;
6024 }
6025 }
6026 else
6027 {
6028 if (indices)
6029 memcpy(index_buffer, indices, 3 * num_faces * sizeof(WORD));
6030 else
6031 {
6032 /* Fill index buffer with 0, 1, 2, ...*/
6033 WORD *indices_16bit = (WORD*)index_buffer;
6034 UINT i;
6035 for (i = 0; i < 3 * num_faces; i++)
6036 indices_16bit[i] = i;
6037 }
6038 }
6039 hr = mesh->lpVtbl->UnlockIndexBuffer(mesh);
6040 if (FAILED(hr)) {
6041 skip("Couldn't unlock index buffer.\n");
6042 goto cleanup;
6043 }
6044
6045 hr = mesh->lpVtbl->LockAttributeBuffer(mesh, 0, &attributes_buffer);
6046 if (FAILED(hr))
6047 {
6048 skip("Couldn't lock attributes buffer.\n");
6049 goto cleanup;
6050 }
6051
6052 if (attributes)
6053 memcpy(attributes_buffer, attributes, num_faces * sizeof(*attributes));
6054 else
6055 memset(attributes_buffer, 0, num_faces * sizeof(*attributes));
6056
6057 hr = mesh->lpVtbl->UnlockAttributeBuffer(mesh);
6058 if (FAILED(hr))
6059 {
6060 skip("Couldn't unlock attributes buffer.\n");
6061 goto cleanup;
6062 }
6063
6064 hr = D3D_OK;
6065 cleanup:
6066 return hr;
6067 }
6068
6069 /* Using structs instead of bit-fields in order to avoid compiler issues. */
6070 struct udec3
6071 {
6072 UINT x;
6073 UINT y;
6074 UINT z;
6075 UINT w;
6076 };
6077
6078 struct dec3n
6079 {
6080 INT x;
6081 INT y;
6082 INT z;
6083 INT w;
6084 };
6085
6086 static DWORD init_udec3_dword(UINT x, UINT y, UINT z, UINT w)
6087 {
6088 DWORD d = 0;
6089
6090 d |= x & 0x3ff;
6091 d |= (y << 10) & 0xffc00;
6092 d |= (z << 20) & 0x3ff00000;
6093 d |= (w << 30) & 0xc0000000;
6094
6095 return d;
6096 }
6097
6098 static DWORD init_dec3n_dword(INT x, INT y, INT z, INT w)
6099 {
6100 DWORD d = 0;
6101
6102 d |= x & 0x3ff;
6103 d |= (y << 10) & 0xffc00;
6104 d |= (z << 20) & 0x3ff00000;
6105 d |= (w << 30) & 0xc0000000;
6106
6107 return d;
6108 }
6109
6110 static struct udec3 dword_to_udec3(DWORD d)
6111 {
6112 struct udec3 v;
6113
6114 v.x = d & 0x3ff;
6115 v.y = (d & 0xffc00) >> 10;
6116 v.z = (d & 0x3ff00000) >> 20;
6117 v.w = (d & 0xc0000000) >> 30;
6118
6119 return v;
6120 }
6121
6122 static struct dec3n dword_to_dec3n(DWORD d)
6123 {
6124 struct dec3n v;
6125
6126 v.x = d & 0x3ff;
6127 v.y = (d & 0xffc00) >> 10;
6128 v.z = (d & 0x3ff00000) >> 20;
6129 v.w = (d & 0xc0000000) >> 30;
6130
6131 return v;
6132 }
6133
6134 static void check_vertex_components(int line, int mesh_number, int vertex_number, BYTE *got_ptr, const BYTE *exp_ptr, D3DVERTEXELEMENT9 *declaration)
6135 {
6136 const char *usage_strings[] =
6137 {
6138 "position",
6139 "blend weight",
6140 "blend indices",
6141 "normal",
6142 "point size",
6143 "texture coordinates",
6144 "tangent",
6145 "binormal",
6146 "tessellation factor",
6147 "position transformed",
6148 "color",
6149 "fog",
6150 "depth",
6151 "sample"
6152 };
6153 D3DVERTEXELEMENT9 *decl_ptr;
6154 const float PRECISION = 1e-5f;
6155
6156 for (decl_ptr = declaration; decl_ptr->Stream != 0xFF; decl_ptr++)
6157 {
6158 switch (decl_ptr->Type)
6159 {
6160 case D3DDECLTYPE_FLOAT1:
6161 {
6162 FLOAT *got = (FLOAT*)(got_ptr + decl_ptr->Offset);
6163 FLOAT *exp = (FLOAT*)(exp_ptr + decl_ptr->Offset);
6164 FLOAT diff = fabsf(*got - *exp);
6165 ok_(__FILE__,line)(diff <= PRECISION, "Mesh %d: Got %f for vertex %d %s, expected %f.\n",
6166 mesh_number, *got, vertex_number, usage_strings[decl_ptr->Usage], *exp);
6167 break;
6168 }
6169 case D3DDECLTYPE_FLOAT2:
6170 {
6171 D3DXVECTOR2 *got = (D3DXVECTOR2*)(got_ptr + decl_ptr->Offset);
6172 D3DXVECTOR2 *exp = (D3DXVECTOR2*)(exp_ptr + decl_ptr->Offset);
6173 FLOAT diff = max(fabsf(got->x - exp->x), fabsf(got->y - exp->y));
6174 ok_(__FILE__,line)(diff <= PRECISION, "Mesh %d: Got (%f, %f) for vertex %d %s, expected (%f, %f).\n",
6175 mesh_number, got->x, got->y, vertex_number, usage_strings[decl_ptr->Usage], exp->x, exp->y);
6176 break;
6177 }
6178 case D3DDECLTYPE_FLOAT3:
6179 {
6180 D3DXVECTOR3 *got = (D3DXVECTOR3*)(got_ptr + decl_ptr->Offset);
6181 D3DXVECTOR3 *exp = (D3DXVECTOR3*)(exp_ptr + decl_ptr->Offset);
6182 FLOAT diff = max(fabsf(got->x - exp->x), fabsf(got->y - exp->y));
6183 diff = max(diff, fabsf(got->z - exp->z));
6184 ok_(__FILE__,line)(diff <= PRECISION, "Mesh %d: Got (%f, %f, %f) for vertex %d %s, expected (%f, %f, %f).\n",
6185 mesh_number, got->x, got->y, got->z, vertex_number, usage_strings[decl_ptr->Usage], exp->x, exp->y, exp->z);
6186 break;
6187 }
6188 case D3DDECLTYPE_FLOAT4:
6189 {
6190 D3DXVECTOR4 *got = (D3DXVECTOR4*)(got_ptr + decl_ptr->Offset);
6191 D3DXVECTOR4 *exp = (D3DXVECTOR4*)(exp_ptr + decl_ptr->Offset);
6192 FLOAT diff = max(fabsf(got->x - exp->x), fabsf(got->y - exp->y));
6193 diff = max(diff, fabsf(got->z - exp->z));
6194 diff = max(diff, fabsf(got->w - exp->w));
6195 ok_(__FILE__,line)(diff <= PRECISION, "Mesh %d: Got (%f, %f, %f, %f) for vertex %d %s, expected (%f, %f, %f, %f).\n",
6196 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);
6197 break;
6198 }
6199 case D3DDECLTYPE_D3DCOLOR:
6200 {
6201 BYTE *got = got_ptr + decl_ptr->Offset;
6202 const BYTE *exp = exp_ptr + decl_ptr->Offset;
6203 BOOL same_color = got[0] == exp[0] && got[1] == exp[1]
6204 && got[2] == exp[2] && got[3] == exp[3];
6205 const char *color_types[] = {"diffuse", "specular", "undefined color"};
6206 BYTE usage_index = decl_ptr->UsageIndex;
6207 if (usage_index > 1) usage_index = 2;
6208 ok_(__FILE__,line)(same_color, "Mesh %d: Got (%u, %u, %u, %u) for vertex %d %s, expected (%u, %u, %u, %u).\n",
6209 mesh_number, got[0], got[1], got[2], got[3], vertex_number, color_types[usage_index], exp[0], exp[1], exp[2], exp[3]);
6210 break;
6211 }
6212 case D3DDECLTYPE_UBYTE4:
6213 case D3DDECLTYPE_UBYTE4N:
6214 {
6215 BYTE *got = got_ptr + decl_ptr->Offset;
6216 const BYTE *exp = exp_ptr + decl_ptr->Offset;
6217 BOOL same = got[0] == exp[0] && got[1] == exp[1]
6218 && got[2] == exp[2] && got[3] == exp[3];
6219 ok_(__FILE__,line)(same, "Mesh %d: Got (%u, %u, %u, %u) for vertex %d %s, expected (%u, %u, %u, %u).\n",
6220 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]);
6221 break;
6222 }
6223 case D3DDECLTYPE_SHORT2:
6224 case D3DDECLTYPE_SHORT2N:
6225 {
6226 SHORT *got = (SHORT*)(got_ptr + decl_ptr->Offset);
6227 SHORT *exp = (SHORT*)(exp_ptr + decl_ptr->Offset);
6228 BOOL same = got[0] == exp[0] && got[1] == exp[1];
6229 ok_(__FILE__,line)(same, "Mesh %d: Got (%hd, %hd) for vertex %d %s, expected (%hd, %hd).\n",
6230 mesh_number, got[0], got[1], vertex_number, usage_strings[decl_ptr->Usage], exp[0], exp[1]);
6231 break;
6232 }
6233 case D3DDECLTYPE_SHORT4:
6234 case D3DDECLTYPE_SHORT4N:
6235 {
6236 SHORT *got = (SHORT*)(got_ptr + decl_ptr->Offset);
6237 SHORT *exp = (SHORT*)(exp_ptr + decl_ptr->Offset);
6238 BOOL same = got[0] == exp[0] && got[1] == exp[1]
6239 && got[2] == exp[2] && got[3] == exp[3];
6240 ok_(__FILE__,line)(same, "Mesh %d: Got (%hd, %hd, %hd, %hd) for vertex %d %s, expected (%hd, %hd, %hd, %hd).\n",
6241 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]);
6242 break;
6243 }
6244 case D3DDECLTYPE_USHORT2N:
6245 {
6246 USHORT *got = (USHORT*)(got_ptr + decl_ptr->Offset);
6247 USHORT *exp = (USHORT*)(exp_ptr + decl_ptr->Offset);
6248 BOOL same = got[0] == exp[0] && got[1] == exp[1];
6249 ok_(__FILE__,line)(same, "Mesh %d: Got (%hu, %hu) for vertex %d %s, expected (%hu, %hu).\n",
6250 mesh_number, got[0], got[1], vertex_number, usage_strings[decl_ptr->Usage], exp[0], exp[1]);
6251 break;
6252 }
6253 case D3DDECLTYPE_USHORT4N:
6254 {
6255 USHORT *got = (USHORT*)(got_ptr + decl_ptr->Offset);
6256 USHORT *exp = (USHORT*)(exp_ptr + decl_ptr->Offset);
6257 BOOL same = got[0] == exp[0] && got[1] == exp[1]
6258 && got[2] == exp[2] && got[3] == exp[3];
6259 ok_(__FILE__,line)(same, "Mesh %d: Got (%hu, %hu, %hu, %hu) for vertex %d %s, expected (%hu, %hu, %hu, %hu).\n",
6260 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]);
6261 break;
6262 }
6263 case D3DDECLTYPE_UDEC3:
6264 {
6265 DWORD *got = (DWORD*)(got_ptr + decl_ptr->Offset);
6266 DWORD *exp = (DWORD*)(exp_ptr + decl_ptr->Offset);
6267 BOOL same = memcmp(got, exp, sizeof(*got)) == 0;
6268 struct udec3 got_udec3 = dword_to_udec3(*got);
6269 struct udec3 exp_udec3 = dword_to_udec3(*exp);
6270 ok_(__FILE__,line)(same, "Mesh %d: Got (%u, %u, %u, %u) for vertex %d %s, expected (%u, %u, %u, %u).\n",
6271 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);
6272
6273 break;
6274 }
6275 case D3DDECLTYPE_DEC3N:
6276 {
6277 DWORD *got = (DWORD*)(got_ptr + decl_ptr->Offset);
6278 DWORD *exp = (DWORD*)(exp_ptr + decl_ptr->Offset);
6279 BOOL same = memcmp(got, exp, sizeof(*got)) == 0;
6280 struct dec3n got_dec3n = dword_to_dec3n(*got);
6281 struct dec3n exp_dec3n = dword_to_dec3n(*exp);
6282 ok_(__FILE__,line)(same, "Mesh %d: Got (%d, %d, %d, %d) for vertex %d %s, expected (%d, %d, %d, %d).\n",
6283 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);
6284 break;
6285 }
6286 case D3DDECLTYPE_FLOAT16_2:
6287 {
6288 WORD *got = (WORD*)(got_ptr + decl_ptr->Offset);
6289 WORD *exp = (WORD*)(exp_ptr + decl_ptr->Offset);
6290 BOOL same = got[0] == exp[0] && got[1] == exp[1];
6291 ok_(__FILE__,line)(same, "Mesh %d: Got (%hx, %hx) for vertex %d %s, expected (%hx, %hx).\n",
6292 mesh_number, got[0], got[1], vertex_number, usage_strings[decl_ptr->Usage], exp[0], exp[1]);
6293 break;
6294 }
6295 case D3DDECLTYPE_FLOAT16_4:
6296 {
6297 WORD *got = (WORD*)(got_ptr + decl_ptr->Offset);
6298 WORD *exp = (WORD*)(exp_ptr + decl_ptr->Offset);
6299 BOOL same = got[0] == exp[0] && got[1] == exp[1]
6300 && got[2] == exp[2] && got[3] == exp[3];
6301 ok_(__FILE__,line)(same, "Mesh %d: Got (%hx, %hx, %hx, %hx) for vertex %d %s, expected (%hx, %hx, %hx, %hx).\n",
6302 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]);
6303 break;
6304 }
6305 default:
6306 break;
6307 }
6308 }
6309 }
6310
6311 static void test_weld_vertices(void)
6312 {
6313 HRESULT hr;
6314 struct test_context *test_context = NULL;
6315 DWORD i;
6316 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
6317 const DWORD options_16bit = D3DXMESH_SYSTEMMEM;
6318 BYTE *vertices = NULL;
6319 DWORD *indices = NULL;
6320 WORD *indices_16bit = NULL;
6321 const UINT VERTS_PER_FACE = 3;
6322 const D3DXVECTOR3 up = {0.0f, 0.0f, 1.0f};
6323 struct vertex_normal
6324 {
6325 D3DXVECTOR3 position;
6326 D3DXVECTOR3 normal;
6327 };
6328 struct vertex_blendweight
6329 {
6330 D3DXVECTOR3 position;
6331 FLOAT blendweight;
6332 };
6333 struct vertex_texcoord
6334 {
6335 D3DXVECTOR3 position;
6336 D3DXVECTOR2 texcoord;
6337 };
6338 struct vertex_color
6339 {
6340 D3DXVECTOR3 position;
6341 DWORD color;
6342 };
6343 struct vertex_color_ubyte4
6344 {
6345 D3DXVECTOR3 position;
6346 BYTE color[4];
6347 };
6348 struct vertex_texcoord_short2
6349 {
6350 D3DXVECTOR3 position;
6351 SHORT texcoord[2];
6352 };
6353 struct vertex_texcoord_ushort2n
6354 {
6355 D3DXVECTOR3 position;
6356 USHORT texcoord[2];
6357 };
6358 struct vertex_normal_short4
6359 {
6360 D3DXVECTOR3 position;
6361 SHORT normal[4];
6362 };
6363 struct vertex_color_float4
6364 {
6365 D3DXVECTOR3 position;
6366 D3DXVECTOR4 color;
6367 };
6368 struct vertex_texcoord_float16_2
6369 {
6370 D3DXVECTOR3 position;
6371 WORD texcoord[2];
6372 };
6373 struct vertex_texcoord_float16_4
6374 {
6375 D3DXVECTOR3 position;
6376 WORD texcoord[4];
6377 };
6378 struct vertex_normal_udec3
6379 {
6380 D3DXVECTOR3 position;
6381 DWORD normal;
6382 };
6383 struct vertex_normal_dec3n
6384 {
6385 D3DXVECTOR3 position;
6386 DWORD normal;
6387 };
6388 UINT vertex_size_normal = sizeof(struct vertex_normal);
6389 UINT vertex_size_blendweight = sizeof(struct vertex_blendweight);
6390 UINT vertex_size_texcoord = sizeof(struct vertex_texcoord);
6391 UINT vertex_size_color = sizeof(struct vertex_color);
6392 UINT vertex_size_color_ubyte4 = sizeof(struct vertex_color_ubyte4);
6393 UINT vertex_size_texcoord_short2 = sizeof(struct vertex_texcoord_short2);
6394 UINT vertex_size_normal_short4 = sizeof(struct vertex_normal_short4);
6395 UINT vertex_size_color_float4 = sizeof(struct vertex_color_float4);
6396 UINT vertex_size_texcoord_float16_2 = sizeof(struct vertex_texcoord_float16_2);
6397 UINT vertex_size_texcoord_float16_4 = sizeof(struct vertex_texcoord_float16_4);
6398 UINT vertex_size_normal_udec3 = sizeof(struct vertex_normal_udec3);
6399 UINT vertex_size_normal_dec3n = sizeof(struct vertex_normal_dec3n);
6400 D3DVERTEXELEMENT9 declaration_normal[] =
6401 {
6402 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6403 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6404 D3DDECL_END()
6405 };
6406 D3DVERTEXELEMENT9 declaration_normal3[] =
6407 {
6408 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 3},
6409 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6410 D3DDECL_END()
6411 };
6412 D3DVERTEXELEMENT9 declaration_blendweight[] =
6413 {
6414 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6415 {0, 12, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BLENDWEIGHT, 0},
6416 D3DDECL_END()
6417 };
6418 D3DVERTEXELEMENT9 declaration_texcoord[] =
6419 {
6420 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6421 {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6422 D3DDECL_END()
6423 };
6424 D3DVERTEXELEMENT9 declaration_color[] =
6425 {
6426 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6427 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
6428 D3DDECL_END()
6429 };
6430 D3DVERTEXELEMENT9 declaration_color_ubyte4n[] =
6431 {
6432 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6433 {0, 12, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
6434 D3DDECL_END()
6435 };
6436 D3DVERTEXELEMENT9 declaration_color_ubyte4[] =
6437 {
6438 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6439 {0, 12, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
6440 D3DDECL_END()
6441 };
6442 D3DVERTEXELEMENT9 declaration_texcoord_short2[] =
6443 {
6444 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6445 {0, 12, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6446 D3DDECL_END()
6447 };
6448 D3DVERTEXELEMENT9 declaration_texcoord_short2n[] =
6449 {
6450 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6451 {0, 12, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6452 D3DDECL_END()
6453 };
6454 D3DVERTEXELEMENT9 declaration_texcoord_ushort2n[] =
6455 {
6456 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6457 {0, 12, D3DDECLTYPE_USHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6458 D3DDECL_END()
6459 };
6460 D3DVERTEXELEMENT9 declaration_normal_short4[] =
6461 {
6462 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6463 {0, 12, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6464 D3DDECL_END()
6465 };
6466 D3DVERTEXELEMENT9 declaration_normal_short4n[] =
6467 {
6468 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6469 {0, 12, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6470 D3DDECL_END()
6471 };
6472 D3DVERTEXELEMENT9 declaration_normal_ushort4n[] =
6473 {
6474 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6475 {0, 12, D3DDECLTYPE_USHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6476 D3DDECL_END()
6477 };
6478 D3DVERTEXELEMENT9 declaration_texcoord10[] =
6479 {
6480 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6481 {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 10},
6482 D3DDECL_END()
6483 };
6484 D3DVERTEXELEMENT9 declaration_color2[] =
6485 {
6486 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6487 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 2},
6488 D3DDECL_END()
6489 };
6490 D3DVERTEXELEMENT9 declaration_color2_float4[] =
6491 {
6492 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6493 {0, 12, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 2},
6494 D3DDECL_END()
6495 };
6496 D3DVERTEXELEMENT9 declaration_texcoord_float16_2[] =
6497 {
6498 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6499 {0, 12, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6500 D3DDECL_END()
6501 };
6502 D3DVERTEXELEMENT9 declaration_texcoord_float16_4[] =
6503 {
6504 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6505 {0, 12, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6506 D3DDECL_END()
6507 };
6508 D3DVERTEXELEMENT9 declaration_normal_udec3[] =
6509 {
6510 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6511 {0, 12, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6512 D3DDECL_END()
6513 };
6514 D3DVERTEXELEMENT9 declaration_normal_dec3n[] =
6515 {
6516 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6517 {0, 12, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6518 D3DDECL_END()
6519 };
6520 /* Test 0. One face and no welding.
6521 *
6522 * 0--1
6523 * | /
6524 * |/
6525 * 2
6526 */
6527 const struct vertex vertices0[] =
6528 {
6529 {{ 0.0f, 3.0f, 0.f}, up},
6530 {{ 2.0f, 3.0f, 0.f}, up},
6531 {{ 0.0f, 0.0f, 0.f}, up},
6532 };
6533 const DWORD indices0[] = {0, 1, 2};
6534 const DWORD attributes0[] = {0};
6535 const DWORD exp_indices0[] = {0, 1, 2};
6536 const UINT num_vertices0 = ARRAY_SIZE(vertices0);
6537 const UINT num_faces0 = ARRAY_SIZE(indices0) / VERTS_PER_FACE;
6538 const DWORD flags0 = D3DXWELDEPSILONS_WELDALL;
6539 /* epsilons0 is NULL */
6540 const DWORD adjacency0[] = {-1, -1, -1};
6541 const struct vertex exp_vertices0[] =
6542 {
6543 {{ 0.0f, 3.0f, 0.f}, up},
6544 {{ 2.0f, 3.0f, 0.f}, up},
6545 {{ 0.0f, 0.0f, 0.f}, up},
6546 };
6547 const DWORD exp_face_remap0[] = {0};
6548 const DWORD exp_vertex_remap0[] = {0, 1, 2};
6549 const DWORD exp_new_num_vertices0 = ARRAY_SIZE(exp_vertices0);
6550 /* Test 1. Two vertices should be removed without regard to epsilon.
6551 *
6552 * 0--1 3
6553 * | / /|
6554 * |/ / |
6555 * 2 5--4
6556 */
6557 const struct vertex_normal vertices1[] =
6558 {
6559 {{ 0.0f, 3.0f, 0.f}, up},
6560 {{ 2.0f, 3.0f, 0.f}, up},
6561 {{ 0.0f, 0.0f, 0.f}, up},
6562
6563 {{ 3.0f, 3.0f, 0.f}, up},
6564 {{ 3.0f, 0.0f, 0.f}, up},
6565 {{ 1.0f, 0.0f, 0.f}, up},
6566 };
6567 const DWORD indices1[] = {0, 1, 2, 3, 4, 5};
6568 const DWORD attributes1[] = {0, 0};
6569 const UINT num_vertices1 = ARRAY_SIZE(vertices1);
6570 const UINT num_faces1 = ARRAY_SIZE(indices1) / VERTS_PER_FACE;
6571 const DWORD flags1 = D3DXWELDEPSILONS_WELDALL;
6572 /* epsilons1 is NULL */
6573 const DWORD adjacency1[] = {-1, 1, -1, -1, -1, 0};
6574 const struct vertex_normal exp_vertices1[] =
6575 {
6576 {{ 0.0f, 3.0f, 0.f}, up},
6577 {{ 2.0f, 3.0f, 0.f}, up},
6578 {{ 0.0f, 0.0f, 0.f}, up},
6579
6580 {{ 3.0f, 0.0f, 0.f}, up}
6581 };
6582 const DWORD exp_indices1[] = {0, 1, 2, 1, 3, 2};
6583 const DWORD exp_face_remap1[] = {0, 1};
6584 const DWORD exp_vertex_remap1[] = {0, 1, 2, 4, -1, -1};
6585 const DWORD exp_new_num_vertices1 = ARRAY_SIZE(exp_vertices1);
6586 /* Test 2. Two faces. No vertices should be removed because of normal
6587 * epsilon, but the positions should be replaced. */
6588 const struct vertex_normal vertices2[] =
6589 {
6590 {{ 0.0f, 3.0f, 0.f}, up},
6591 {{ 2.0f, 3.0f, 0.f}, up},
6592 {{ 0.0f, 0.0f, 0.f}, up},
6593
6594 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
6595 {{ 3.0f, 0.0f, 0.f}, up},
6596 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6597 };
6598 const DWORD indices2[] = {0, 1, 2, 3, 4, 5};
6599 const DWORD attributes2[] = {0, 0};
6600 const UINT num_vertices2 = ARRAY_SIZE(vertices2);
6601 const UINT num_faces2 = ARRAY_SIZE(indices2) / VERTS_PER_FACE;
6602 DWORD flags2 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
6603 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};
6604 const DWORD adjacency2[] = {-1, 1, -1, -1, -1, 0};
6605 const struct vertex_normal exp_vertices2[] =
6606 {
6607 {{ 0.0f, 3.0f, 0.f}, up},
6608 {{ 2.0f, 3.0f, 0.f}, up},
6609 {{ 0.0f, 0.0f, 0.f}, up},
6610
6611 {{ 2.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
6612 {{ 3.0f, 0.0f, 0.f}, up},
6613 {{ 0.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6614 };
6615 const DWORD exp_indices2[] = {0, 1, 2, 3, 4, 5};
6616 const DWORD exp_face_remap2[] = {0, 1};
6617 const DWORD exp_vertex_remap2[] = {0, 1, 2, 3, 4, 5};
6618 const DWORD exp_new_num_vertices2 = ARRAY_SIZE(exp_vertices2);
6619 /* Test 3. Two faces. One vertex should be removed because of normal epsilon. */
6620 const struct vertex_normal vertices3[] =
6621 {
6622 {{ 0.0f, 3.0f, 0.f}, up},
6623 {{ 2.0f, 3.0f, 0.f}, up},
6624 {{ 0.0f, 0.0f, 0.f}, up},
6625
6626 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
6627 {{ 3.0f, 0.0f, 0.f}, up},
6628 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6629 };
6630 const DWORD indices3[] = {0, 1, 2, 3, 4, 5};
6631 const DWORD attributes3[] = {0, 0};
6632 const UINT num_vertices3 = ARRAY_SIZE(vertices3);
6633 const UINT num_faces3 = ARRAY_SIZE(indices3) / VERTS_PER_FACE;
6634 DWORD flags3 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
6635 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};
6636 const DWORD adjacency3[] = {-1, 1, -1, -1, -1, 0};
6637 const struct vertex_normal exp_vertices3[] =
6638 {
6639 {{ 0.0f, 3.0f, 0.f}, up},
6640 {{ 2.0f, 3.0f, 0.f}, up},
6641 {{ 0.0f, 0.0f, 0.f}, up},
6642
6643 {{ 3.0f, 0.0f, 0.f}, up},
6644 {{ 0.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6645 };
6646 const DWORD exp_indices3[] = {0, 1, 2, 1, 3, 4};
6647 const DWORD exp_face_remap3[] = {0, 1};
6648 const DWORD exp_vertex_remap3[] = {0, 1, 2, 4, 5, -1};
6649 const DWORD exp_new_num_vertices3 = ARRAY_SIZE(exp_vertices3);
6650 /* Test 4 Two faces. Two vertices should be removed. */
6651 const struct vertex_normal vertices4[] =
6652 {
6653 {{ 0.0f, 3.0f, 0.f}, up},
6654 {{ 2.0f, 3.0f, 0.f}, up},
6655 {{ 0.0f, 0.0f, 0.f}, up},
6656
6657 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
6658 {{ 3.0f, 0.0f, 0.f}, up},
6659 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6660 };
6661 const DWORD indices4[] = {0, 1, 2, 3, 4, 5};
6662 const DWORD attributes4[] = {0, 0};
6663 const UINT num_vertices4 = ARRAY_SIZE(vertices4);
6664 const UINT num_faces4 = ARRAY_SIZE(indices4) / VERTS_PER_FACE;
6665 DWORD flags4 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
6666 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};
6667 const DWORD adjacency4[] = {-1, 1, -1, -1, -1, 0};
6668 const struct vertex_normal exp_vertices4[] =
6669 {
6670 {{ 0.0f, 3.0f, 0.f}, up},
6671 {{ 2.0f, 3.0f, 0.f}, up},
6672 {{ 0.0f, 0.0f, 0.f}, up},
6673
6674 {{ 3.0f, 0.0f, 0.f}, up},
6675 };
6676 const DWORD exp_indices4[] = {0, 1, 2, 1, 3, 2};
6677 const DWORD exp_face_remap4[] = {0, 1};
6678 const DWORD exp_vertex_remap4[] = {0, 1, 2, 4, -1, -1};
6679 const DWORD exp_new_num_vertices4 = ARRAY_SIZE(exp_vertices4);
6680 /* Test 5. Odd face ordering.
6681 *
6682 * 0--1 6 3
6683 * | / /| |\
6684 * |/ / | | \
6685 * 2 8--7 5--4
6686 */
6687 const struct vertex_normal vertices5[] =
6688 {
6689 {{ 0.0f, 3.0f, 0.f}, up},
6690 {{ 2.0f, 3.0f, 0.f}, up},
6691 {{ 0.0f, 0.0f, 0.f}, up},
6692
6693 {{ 3.0f, 3.0f, 0.f}, up},
6694 {{ 3.0f, 0.0f, 0.f}, up},
6695 {{ 1.0f, 0.0f, 0.f}, up},
6696
6697 {{ 4.0f, 3.0f, 0.f}, up},
6698 {{ 6.0f, 0.0f, 0.f}, up},
6699 {{ 4.0f, 0.0f, 0.f}, up},
6700 };
6701 const DWORD indices5[] = {0, 1, 2, 6, 7, 8, 3, 4, 5};
6702 const DWORD exp_indices5[] = {0, 1, 2, 1, 4, 2, 1, 3, 4};
6703 const DWORD attributes5[] = {0, 0, 0};
6704 const UINT num_vertices5 = ARRAY_SIZE(vertices5);
6705 const UINT num_faces5 = ARRAY_SIZE(indices5) / VERTS_PER_FACE;
6706 DWORD flags5 = D3DXWELDEPSILONS_WELDALL;
6707 const DWORD adjacency5[] = {-1, 1, -1, 2, -1, 0, -1, -1, 1};
6708 const struct vertex_normal exp_vertices5[] =
6709 {
6710 {{ 0.0f, 3.0f, 0.f}, up},
6711 {{ 2.0f, 3.0f, 0.f}, up},
6712 {{ 0.0f, 0.0f, 0.f}, up},
6713
6714 {{ 3.0f, 0.0f, 0.f}, up},
6715 {{ 1.0f, 0.0f, 0.f}, up},
6716 };
6717 const DWORD exp_face_remap5[] = {0, 1, 2};
6718 const DWORD exp_vertex_remap5[] = {0, 1, 2, 4, 5, -1, -1, -1, -1};
6719 const DWORD exp_new_num_vertices5 = ARRAY_SIZE(exp_vertices5);
6720 /* Test 6. Two faces. Do not remove flag is used, so no vertices should be
6721 * removed. */
6722 const struct vertex_normal vertices6[] =
6723 {
6724 {{ 0.0f, 3.0f, 0.f}, up},
6725 {{ 2.0f, 3.0f, 0.f}, up},
6726 {{ 0.0f, 0.0f, 0.f}, up},
6727
6728 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
6729 {{ 3.0f, 0.0f, 0.f}, up},
6730 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6731 };
6732 const DWORD indices6[] = {0, 1, 2, 3, 4, 5};
6733 const DWORD attributes6[] = {0, 0};
6734 const UINT num_vertices6 = ARRAY_SIZE(vertices6);
6735 const UINT num_faces6 = ARRAY_SIZE(indices6) / VERTS_PER_FACE;
6736 DWORD flags6 = D3DXWELDEPSILONS_WELDPARTIALMATCHES | D3DXWELDEPSILONS_DONOTREMOVEVERTICES;
6737 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};
6738 const DWORD adjacency6[] = {-1, 1, -1, -1, -1, 0};
6739 const struct vertex_normal exp_vertices6[] =
6740 {
6741 {{ 0.0f, 3.0f, 0.f}, up},
6742 {{ 2.0f, 3.0f, 0.f}, up},
6743 {{ 0.0f, 0.0f, 0.f}, up},
6744
6745 {{ 2.0f, 3.0f, 0.f}, up},
6746 {{ 3.0f, 0.0f, 0.f}, up},
6747 {{ 0.0f, 0.0f, 0.f}, up},
6748
6749 };
6750 const DWORD exp_indices6[] = {0, 1, 2, 3, 4, 5};
6751 const DWORD exp_face_remap6[] = {0, 1};
6752 const DWORD exp_vertex_remap6[] = {0, 1, 2, 3, 4, 5};
6753 const DWORD exp_new_num_vertices6 = ARRAY_SIZE(exp_vertices6);
6754 /* Test 7. Same as test 6 but with 16 bit indices. */
6755 const WORD indices6_16bit[] = {0, 1, 2, 3, 4, 5};
6756 /* Test 8. No flags. Same result as D3DXWELDEPSILONS_WELDPARTIALMATCHES. */
6757 const struct vertex_normal vertices8[] =
6758 {
6759 {{ 0.0f, 3.0f, 0.f}, up},
6760 {{ 2.0f, 3.0f, 0.f}, up},
6761 {{ 0.0f, 0.0f, 0.f}, up},
6762
6763 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
6764 {{ 3.0f, 0.0f, 0.f}, up},
6765 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6766 };
6767 const DWORD indices8[] = {0, 1, 2, 1, 3, 4};
6768 const DWORD attributes8[] = {0, 0};
6769 const UINT num_vertices8 = ARRAY_SIZE(vertices8);
6770 const UINT num_faces8 = ARRAY_SIZE(indices8) / VERTS_PER_FACE;
6771 DWORD flags8 = 0;
6772 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};
6773 const DWORD adjacency8[] = {-1, 1, -1, -1, -1, 0};
6774 const struct vertex_normal exp_vertices8[] =
6775 {
6776 {{ 0.0f, 3.0f, 0.f}, up},
6777 {{ 2.0f, 3.0f, 0.f}, up},
6778 {{ 0.0f, 0.0f, 0.f}, up},
6779
6780 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
6781 {{ 3.0f, 0.0f, 0.f}, up},
6782 };
6783 const DWORD exp_indices8[] = {0, 1, 2, 1, 3, 4};
6784 const DWORD exp_face_remap8[] = {0, 1};
6785 const DWORD exp_vertex_remap8[] = {0, 1, 2, 3, 4, -1};
6786 const DWORD exp_new_num_vertices8 = ARRAY_SIZE(exp_vertices8);
6787 /* Test 9. Vertices are removed even though they belong to separate
6788 * attribute groups if D3DXWELDEPSILONS_DONOTSPLIT is set. */
6789 const struct vertex_normal vertices9[] =
6790 {
6791 {{ 0.0f, 3.0f, 0.f}, up},
6792 {{ 2.0f, 3.0f, 0.f}, up},
6793 {{ 0.0f, 0.0f, 0.f}, up},
6794
6795 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
6796 {{ 3.0f, 0.0f, 0.f}, up},
6797 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6798 };
6799 const DWORD indices9[] = {0, 1, 2, 3, 4, 5};
6800 const DWORD attributes9[] = {0, 1};
6801 const UINT num_vertices9 = ARRAY_SIZE(vertices9);
6802 const UINT num_faces9 = ARRAY_SIZE(indices9) / VERTS_PER_FACE;
6803 DWORD flags9 = D3DXWELDEPSILONS_WELDPARTIALMATCHES | D3DXWELDEPSILONS_DONOTSPLIT;
6804 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};
6805 const DWORD adjacency9[] = {-1, 1, -1, -1, -1, 0};
6806 const struct vertex_normal exp_vertices9[] =
6807 {
6808 {{ 0.0f, 3.0f, 0.f}, up},
6809 {{ 2.0f, 3.0f, 0.f}, up},
6810 {{ 0.0f, 0.0f, 0.f}, up},
6811
6812 {{ 3.0f, 0.0f, 0.f}, up},
6813 };
6814 const DWORD exp_indices9[] = {0, 1, 2, 1, 3, 2};
6815 const DWORD exp_face_remap9[] = {0, 1};
6816 const DWORD exp_vertex_remap9[] = {0, 1, 2, 4, -1, -1};
6817 const DWORD exp_new_num_vertices9 = ARRAY_SIZE(exp_vertices9);
6818 /* Test 10. Weld blendweight (FLOAT1). */
6819 const struct vertex_blendweight vertices10[] =
6820 {
6821 {{ 0.0f, 3.0f, 0.f}, 1.0f},
6822 {{ 2.0f, 3.0f, 0.f}, 1.0f},
6823 {{ 0.0f, 0.0f, 0.f}, 1.0f},
6824
6825 {{ 3.0f, 3.0f, 0.f}, 0.9},
6826 {{ 3.0f, 0.0f, 0.f}, 1.0},
6827 {{ 1.0f, 0.0f, 0.f}, 0.4},
6828 };
6829 const DWORD indices10[] = {0, 1, 2, 3, 4, 5};
6830 const DWORD attributes10[] = {0, 0};
6831 const UINT num_vertices10 = ARRAY_SIZE(vertices10);
6832 const UINT num_faces10 = ARRAY_SIZE(indices10) / VERTS_PER_FACE;
6833 DWORD flags10 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
6834 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};
6835 const DWORD adjacency10[] = {-1, 1, -1, -1, -1, 0};
6836 const struct vertex_blendweight exp_vertices10[] =
6837 {
6838 {{ 0.0f, 3.0f, 0.f}, 1.0f},
6839 {{ 2.0f, 3.0f, 0.f}, 1.0f},
6840 {{ 0.0f, 0.0f, 0.f}, 1.0f},
6841
6842 {{ 3.0f, 0.0f, 0.f}, 1.0},
6843 {{ 0.0f, 0.0f, 0.f}, 0.4},
6844 };
6845 const DWORD exp_indices10[] = {0, 1, 2, 1, 3, 4};
6846 const DWORD exp_face_remap10[] = {0, 1};
6847 const DWORD exp_vertex_remap10[] = {0, 1, 2, 4, 5, -1};
6848 const DWORD exp_new_num_vertices10 = ARRAY_SIZE(exp_vertices10);
6849 /* Test 11. Weld texture coordinates. */
6850 const struct vertex_texcoord vertices11[] =
6851 {
6852 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f}},
6853 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.7f}},
6854 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
6855
6856 {{ 3.0f, 3.0f, 0.f}, {0.2f, 0.3f}},
6857 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f}},
6858 {{ 1.0f, 0.0f, 0.f}, {0.1f, 0.2f}}
6859 };
6860 const DWORD indices11[] = {0, 1, 2, 3, 4, 5};
6861 const DWORD attributes11[] = {0, 0};
6862 const UINT num_vertices11 = ARRAY_SIZE(vertices11);
6863 const UINT num_faces11 = ARRAY_SIZE(indices11) / VERTS_PER_FACE;
6864 DWORD flags11 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
6865 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};
6866 const DWORD adjacency11[] = {-1, 1, -1, -1, -1, 0};
6867 const struct vertex_texcoord exp_vertices11[] =
6868 {
6869 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f}},
6870 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.7f}},
6871 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
6872
6873 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f}},
6874 {{ 0.0f, 0.0f, 0.f}, {0.1f, 0.2f}},
6875 };
6876 const DWORD exp_indices11[] = {0, 1, 2, 1, 3, 4};
6877 const DWORD exp_face_remap11[] = {0, 1};
6878 const DWORD exp_vertex_remap11[] = {0, 1, 2, 4, 5, -1};
6879 const DWORD exp_new_num_vertices11 = ARRAY_SIZE(exp_vertices11);
6880 /* Test 12. Weld with color. */
6881 const struct vertex_color vertices12[] =
6882 {
6883 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
6884 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
6885 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
6886
6887 {{ 3.0f, 3.0f, 0.f}, 0x00000000},
6888 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
6889 {{ 1.0f, 0.0f, 0.f}, 0x88888888},
6890 };
6891 const DWORD indices12[] = {0, 1, 2, 3, 4, 5};
6892 const DWORD attributes12[] = {0, 0};
6893 const UINT num_vertices12 = ARRAY_SIZE(vertices12);
6894 const UINT num_faces12 = ARRAY_SIZE(indices12) / VERTS_PER_FACE;
6895 DWORD flags12 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
6896 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};
6897 const DWORD adjacency12[] = {-1, 1, -1, -1, -1, 0};
6898 const struct vertex_color exp_vertices12[] =
6899 {
6900 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
6901 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
6902 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
6903
6904 {{ 2.0f, 3.0f, 0.f}, 0x00000000},
6905 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
6906 };
6907 const DWORD exp_indices12[] = {0, 1, 2, 3, 4, 2};
6908 const DWORD exp_face_remap12[] = {0, 1};
6909 const DWORD exp_vertex_remap12[] = {0, 1, 2, 3, 4, -1};
6910 const DWORD exp_new_num_vertices12 = ARRAY_SIZE(exp_vertices12);
6911 /* Test 13. Two faces. One vertex should be removed because of normal epsilon.
6912 * This is similar to test 3, but the declaration has been changed to NORMAL3.
6913 */
6914 const struct vertex_normal vertices13[] =
6915 {
6916 {{ 0.0f, 3.0f, 0.f}, up},
6917 {{ 2.0f, 3.0f, 0.f}, up},
6918 {{ 0.0f, 0.0f, 0.f}, up},
6919
6920 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
6921 {{ 3.0f, 0.0f, 0.f}, up},
6922 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6923 };
6924 const DWORD indices13[] = {0, 1, 2, 3, 4, 5};
6925 const DWORD attributes13[] = {0, 0};
6926 const UINT num_vertices13 = ARRAY_SIZE(vertices3);
6927 const UINT num_faces13 = ARRAY_SIZE(indices3) / VERTS_PER_FACE;
6928 DWORD flags13 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
6929 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};
6930 const DWORD adjacency13[] = {-1, 1, -1, -1, -1, 0};
6931 const struct vertex_normal exp_vertices13[] =
6932 {
6933 {{ 0.0f, 3.0f, 0.f}, up},
6934 {{ 2.0f, 3.0f, 0.f}, up},
6935 {{ 0.0f, 0.0f, 0.f}, up},
6936
6937 {{ 3.0f, 0.0f, 0.f}, up},
6938 {{ 0.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
6939 };
6940 const DWORD exp_indices13[] = {0, 1, 2, 1, 3, 4};
6941 const DWORD exp_face_remap13[] = {0, 1};
6942 const DWORD exp_vertex_remap13[] = {0, 1, 2, 4, 5, -1};
6943 const DWORD exp_new_num_vertices13 = ARRAY_SIZE(exp_vertices13);
6944 /* Test 14. Another test for welding with color. */
6945 const struct vertex_color vertices14[] =
6946 {
6947 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
6948 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
6949 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
6950
6951 {{ 3.0f, 3.0f, 0.f}, 0x00000000},
6952 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
6953 {{ 1.0f, 0.0f, 0.f}, 0x01010101},
6954 };
6955 const DWORD indices14[] = {0, 1, 2, 3, 4, 5};
6956 const DWORD attributes14[] = {0, 0};
6957 const UINT num_vertices14 = ARRAY_SIZE(vertices14);
6958 const UINT num_faces14 = ARRAY_SIZE(indices14) / VERTS_PER_FACE;
6959 DWORD flags14 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
6960 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};
6961 const DWORD adjacency14[] = {-1, 1, -1, -1, -1, 0};
6962 const struct vertex_color exp_vertices14[] =
6963 {
6964 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
6965 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
6966 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
6967
6968 {{ 2.0f, 3.0f, 0.f}, 0x00000000},
6969 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
6970 };
6971 const DWORD exp_indices14[] = {0, 1, 2, 3, 4, 2};
6972 const DWORD exp_face_remap14[] = {0, 1};
6973 const DWORD exp_vertex_remap14[] = {0, 1, 2, 3, 4, -1};
6974 const DWORD exp_new_num_vertices14 = ARRAY_SIZE(exp_vertices14);
6975 /* Test 15. Weld with color, but as UBYTE4N instead of D3DCOLOR. It shows
6976 * that UBYTE4N and D3DCOLOR are compared the same way.
6977 */
6978 const struct vertex_color_ubyte4 vertices15[] =
6979 {
6980 {{ 0.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
6981 {{ 2.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
6982 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
6983
6984 {{ 3.0f, 3.0f, 0.f}, { 0, 0, 0, 0}},
6985 {{ 3.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
6986 {{ 1.0f, 0.0f, 0.f}, { 1, 1, 1, 1}},
6987 };
6988 const DWORD indices15[] = {0, 1, 2, 3, 4, 5};
6989 const DWORD attributes15[] = {0, 0};
6990 const UINT num_vertices15 = ARRAY_SIZE(vertices15);
6991 const UINT num_faces15 = ARRAY_SIZE(indices15) / VERTS_PER_FACE;
6992 DWORD flags15 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
6993 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};
6994 const DWORD adjacency15[] = {-1, 1, -1, -1, -1, 0};
6995 const struct vertex_color_ubyte4 exp_vertices15[] =
6996 {
6997 {{ 0.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
6998 {{ 2.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
6999 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7000
7001 {{ 2.0f, 3.0f, 0.f}, { 0, 0, 0, 0}},
7002 {{ 3.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7003 };
7004 const DWORD exp_indices15[] = {0, 1, 2, 3, 4, 2};
7005 const DWORD exp_face_remap15[] = {0, 1};
7006 const DWORD exp_vertex_remap15[] = {0, 1, 2, 3, 4, -1};
7007 const DWORD exp_new_num_vertices15 = ARRAY_SIZE(exp_vertices15);
7008 /* Test 16. Weld with color, but as UBYTE4 instead of D3DCOLOR. It shows
7009 * that UBYTE4 is not normalized and that epsilon is truncated and compared
7010 * directly to each of the four bytes.
7011 */
7012 const struct vertex_color_ubyte4 vertices16[] =
7013 {
7014 {{ 0.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7015 {{ 2.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7016 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7017
7018 {{ 3.0f, 3.0f, 0.f}, { 0, 0, 0, 0}},
7019 {{ 3.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7020 {{ 1.0f, 0.0f, 0.f}, { 1, 1, 1, 1}},
7021 };
7022 const DWORD indices16[] = {0, 1, 2, 3, 4, 5};
7023 const DWORD attributes16[] = {0, 0};
7024 const UINT num_vertices16 = ARRAY_SIZE(vertices16);
7025 const UINT num_faces16 = ARRAY_SIZE(indices16) / VERTS_PER_FACE;
7026 DWORD flags16 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7027 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};
7028 const DWORD adjacency16[] = {-1, 1, -1, -1, -1, 0};
7029 const struct vertex_color_ubyte4 exp_vertices16[] =
7030 {
7031 {{ 0.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7032 {{ 2.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7033 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7034
7035 {{ 2.0f, 3.0f, 0.f}, { 0, 0, 0, 0}},
7036 {{ 3.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7037 };
7038 const DWORD exp_indices16[] = {0, 1, 2, 3, 4, 2};
7039 const DWORD exp_face_remap16[] = {0, 1};
7040 const DWORD exp_vertex_remap16[] = {0, 1, 2, 3, 4, -1};
7041 const DWORD exp_new_num_vertices16 = ARRAY_SIZE(exp_vertices16);
7042 /* Test 17. Weld texture coordinates but as SHORT2 instead of D3DXVECTOR2.*/
7043 const struct vertex_texcoord_short2 vertices17[] =
7044 {
7045 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7046 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7047 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7048
7049 {{ 3.0f, 3.0f, 0.f}, {32767, 32767}},
7050 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7051 {{ 1.0f, 0.0f, 0.f}, {32766, 32766}},
7052 };
7053 const DWORD indices17[] = {0, 1, 2, 3, 4, 5};
7054 const DWORD attributes17[] = {0, 0};
7055 const UINT num_vertices17 = ARRAY_SIZE(vertices17);
7056 const UINT num_faces17 = ARRAY_SIZE(indices17) / VERTS_PER_FACE;
7057 DWORD flags17 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7058 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};
7059 const DWORD adjacency17[] = {-1, 1, -1, -1, -1, 0};
7060 const struct vertex_texcoord_short2 exp_vertices17[] =
7061 {
7062 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7063 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7064 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7065
7066 {{ 2.0f, 3.0f, 0.f}, {32767, 32767}},
7067 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7068 };
7069 const DWORD exp_indices17[] = {0, 1, 2, 3, 4, 2};
7070 const DWORD exp_face_remap17[] = {0, 1};
7071 const DWORD exp_vertex_remap17[] = {0, 1, 2, 3, 4, -1};
7072 const DWORD exp_new_num_vertices17 = ARRAY_SIZE(exp_vertices17);
7073 /* Test 18. Weld texture coordinates but as SHORT2N instead of D3DXVECTOR2. */
7074 const struct vertex_texcoord_short2 vertices18[] =
7075 {
7076 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7077 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7078 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7079
7080 {{ 3.0f, 3.0f, 0.f}, {32767, 32767}},
7081 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7082 {{ 1.0f, 0.0f, 0.f}, {32766, 32766}},
7083 };
7084 const DWORD indices18[] = {0, 1, 2, 3, 4, 5};
7085 const DWORD attributes18[] = {0, 0};
7086 const UINT num_vertices18 = ARRAY_SIZE(vertices18);
7087 const UINT num_faces18 = ARRAY_SIZE(indices18) / VERTS_PER_FACE;
7088 DWORD flags18 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7089 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};
7090 const DWORD adjacency18[] = {-1, 1, -1, -1, -1, 0};
7091 const struct vertex_texcoord_short2 exp_vertices18[] =
7092 {
7093 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7094 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7095 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7096
7097 {{ 2.0f, 3.0f, 0.f}, {32767, 32767}},
7098 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7099 };
7100 const DWORD exp_indices18[] = {0, 1, 2, 3, 4, 2};
7101 const DWORD exp_face_remap18[] = {0, 1};
7102 const DWORD exp_vertex_remap18[] = {0, 1, 2, 3, 4, -1};
7103 const DWORD exp_new_num_vertices18 = ARRAY_SIZE(exp_vertices18);
7104 /* Test 19. Weld texture coordinates but as USHORT2N instead of D3DXVECTOR2. */
7105 const struct vertex_texcoord_ushort2n vertices19[] =
7106 {
7107 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7108 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7109 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7110
7111 {{ 3.0f, 3.0f, 0.f}, {65535, 65535}},
7112 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7113 {{ 1.0f, 0.0f, 0.f}, {65534, 65534}},
7114 };
7115 const DWORD indices19[] = {0, 1, 2, 3, 4, 5};
7116 const DWORD attributes19[] = {0, 0};
7117 const UINT num_vertices19 = ARRAY_SIZE(vertices19);
7118 const UINT num_faces19 = ARRAY_SIZE(indices19) / VERTS_PER_FACE;
7119 DWORD flags19 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7120 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};
7121 const DWORD adjacency19[] = {-1, 1, -1, -1, -1, 0};
7122 const struct vertex_texcoord_ushort2n exp_vertices19[] =
7123 {
7124 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7125 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7126 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7127
7128 {{ 2.0f, 3.0f, 0.f}, {65535, 65535}},
7129 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7130 };
7131 const DWORD exp_indices19[] = {0, 1, 2, 3, 4, 2};
7132 const DWORD exp_face_remap19[] = {0, 1};
7133 const DWORD exp_vertex_remap19[] = {0, 1, 2, 3, 4, -1};
7134 const DWORD exp_new_num_vertices19 = ARRAY_SIZE(exp_vertices19);
7135 /* Test 20. Weld normal as SHORT4 instead of D3DXVECTOR3. */
7136 const struct vertex_normal_short4 vertices20[] =
7137 {
7138 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7139 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7140 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7141
7142 {{ 3.0f, 3.0f, 0.f}, {32767, 32767, 32767, 32767}},
7143 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7144 {{ 1.0f, 0.0f, 0.f}, {32766, 32766, 32766, 32766}},
7145 };
7146 const DWORD indices20[] = {0, 1, 2, 3, 4, 5};
7147 const DWORD attributes20[] = {0, 0};
7148 const UINT num_vertices20 = ARRAY_SIZE(vertices20);
7149 const UINT num_faces20 = ARRAY_SIZE(indices20) / VERTS_PER_FACE;
7150 DWORD flags20 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7151 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};
7152 const DWORD adjacency20[] = {-1, 1, -1, -1, -1, 0};
7153 const struct vertex_normal_short4 exp_vertices20[] =
7154 {
7155 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7156 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7157 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7158
7159 {{ 2.0f, 3.0f, 0.f}, {32767, 32767, 32767, 32767}},
7160 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7161 };
7162 const DWORD exp_indices20[] = {0, 1, 2, 3, 4, 2};
7163 const DWORD exp_face_remap20[] = {0, 1};
7164 const DWORD exp_vertex_remap20[] = {0, 1, 2, 3, 4, -1};
7165 const DWORD exp_new_num_vertices20 = ARRAY_SIZE(exp_vertices20);
7166 /* Test 21. Weld normal as SHORT4N instead of D3DXVECTOR3. */
7167 const struct vertex_normal_short4 vertices21[] =
7168 {
7169 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7170 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7171 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7172
7173 {{ 3.0f, 3.0f, 0.f}, {32767, 32767, 32767, 32767}},
7174 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7175 {{ 1.0f, 0.0f, 0.f}, {32766, 32766, 32766, 32766}},
7176 };
7177 const DWORD indices21[] = {0, 1, 2, 3, 4, 5};
7178 const DWORD attributes21[] = {0, 0};
7179 const UINT num_vertices21 = ARRAY_SIZE(vertices21);
7180 const UINT num_faces21 = ARRAY_SIZE(indices21) / VERTS_PER_FACE;
7181 DWORD flags21 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7182 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};
7183 const DWORD adjacency21[] = {-1, 1, -1, -1, -1, 0};
7184 const struct vertex_normal_short4 exp_vertices21[] =
7185 {
7186 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7187 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7188 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7189
7190 {{ 2.0f, 3.0f, 0.f}, {32767, 32767, 32767, 32767}},
7191 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7192 };
7193 const DWORD exp_indices21[] = {0, 1, 2, 3, 4, 2};
7194 const DWORD exp_face_remap21[] = {0, 1};
7195 const DWORD exp_vertex_remap21[] = {0, 1, 2, 3, 4, -1};
7196 const DWORD exp_new_num_vertices21 = ARRAY_SIZE(exp_vertices21);
7197 /* Test 22. Weld normal as USHORT4N instead of D3DXVECTOR3. */
7198 const struct vertex_normal_short4 vertices22[] =
7199 {
7200 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7201 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7202 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7203
7204 {{ 3.0f, 3.0f, 0.f}, {65535, 65535, 65535, 65535}},
7205 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7206 {{ 1.0f, 0.0f, 0.f}, {65534, 65534, 65534, 65534}},
7207 };
7208 const DWORD indices22[] = {0, 1, 2, 3, 4, 5};
7209 const DWORD attributes22[] = {0, 0};
7210 const UINT num_vertices22 = ARRAY_SIZE(vertices22);
7211 const UINT num_faces22 = ARRAY_SIZE(indices22) / VERTS_PER_FACE;
7212 DWORD flags22 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7213 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};
7214 const DWORD adjacency22[] = {-1, 1, -1, -1, -1, 0};
7215 const struct vertex_normal_short4 exp_vertices22[] =
7216 {
7217 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7218 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7219 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7220
7221 {{ 2.0f, 3.0f, 0.f}, {65535, 65535, 65535, 65535}},
7222 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7223 };
7224 const DWORD exp_indices22[] = {0, 1, 2, 3, 4, 2};
7225 const DWORD exp_face_remap22[] = {0, 1};
7226 const DWORD exp_vertex_remap22[] = {0, 1, 2, 3, 4, -1};
7227 const DWORD exp_new_num_vertices22 = ARRAY_SIZE(exp_vertices22);
7228 /* Test 23. Weld texture coordinates as FLOAT16_2. Similar to test 11, but
7229 * with texture coordinates converted to float16 in hex. */
7230 const struct vertex_texcoord_float16_2 vertices23[] =
7231 {
7232 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
7233 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */
7234 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */
7235
7236 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd}}, /* {0.2f, 0.3f} */
7237 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
7238 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */
7239 };
7240 const DWORD indices23[] = {0, 1, 2, 3, 4, 5};
7241 const DWORD attributes23[] = {0, 0};
7242 const UINT num_vertices23 = ARRAY_SIZE(vertices23);
7243 const UINT num_faces23 = ARRAY_SIZE(indices23) / VERTS_PER_FACE;
7244 DWORD flags23 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7245 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};
7246 const DWORD adjacency23[] = {-1, 1, -1, -1, -1, 0};
7247 const struct vertex_texcoord_float16_2 exp_vertices23[] =
7248 {
7249 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
7250 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */
7251 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */
7252
7253 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
7254 {{ 0.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */
7255 };
7256 const DWORD exp_indices23[] = {0, 1, 2, 1, 3, 4};
7257 const DWORD exp_face_remap23[] = {0, 1};
7258 const DWORD exp_vertex_remap23[] = {0, 1, 2, 4, 5, -1};
7259 const DWORD exp_new_num_vertices23 = ARRAY_SIZE(exp_vertices23);
7260 /* Test 24. Weld texture coordinates as FLOAT16_4. Similar to test 24. */
7261 const struct vertex_texcoord_float16_4 vertices24[] =
7262 {
7263 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}},
7264 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a, 0x3800, 0x399a}},
7265 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd, 0xb266, 0xb4cd}},
7266
7267 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd, 0x3266, 0x34cd}},
7268 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}},
7269 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266, 0x2e66, 0x3266}},
7270 };
7271 const DWORD indices24[] = {0, 1, 2, 3, 4, 5};
7272 const DWORD attributes24[] = {0, 0};
7273 const UINT num_vertices24 = ARRAY_SIZE(vertices24);
7274 const UINT num_faces24 = ARRAY_SIZE(indices24) / VERTS_PER_FACE;
7275 DWORD flags24 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7276 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};
7277 const DWORD adjacency24[] = {-1, 1, -1, -1, -1, 0};
7278 const struct vertex_texcoord_float16_4 exp_vertices24[] =
7279 {
7280 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}},
7281 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a, 0x3800, 0x399a}},
7282 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd, 0xb266, 0xb4cd}},
7283
7284 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}},
7285 {{ 0.0f, 0.0f, 0.f}, {0x2e66, 0x3266, 0x2e66, 0x3266}},
7286 };
7287 const DWORD exp_indices24[] = {0, 1, 2, 1, 3, 4};
7288 const DWORD exp_face_remap24[] = {0, 1};
7289 const DWORD exp_vertex_remap24[] = {0, 1, 2, 4, 5, -1};
7290 const DWORD exp_new_num_vertices24 = ARRAY_SIZE(exp_vertices24);
7291 /* Test 25. Weld texture coordinates with usage index 10 (TEXCOORD10). The
7292 * usage index is capped at 7, so the epsilon for TEXCOORD7 is used instead.
7293 */
7294 const struct vertex_texcoord vertices25[] =
7295 {
7296 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f}},
7297 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.7f}},
7298 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
7299
7300 {{ 3.0f, 3.0f, 0.f}, {0.2f, 0.3f}},
7301 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f}},
7302 {{ 1.0f, 0.0f, 0.f}, {0.1f, 0.2f}}
7303 };
7304 const DWORD indices25[] = {0, 1, 2, 3, 4, 5};
7305 const DWORD attributes25[] = {0, 0};
7306 const UINT num_vertices25 = ARRAY_SIZE(vertices25);
7307 const UINT num_faces25 = ARRAY_SIZE(indices25) / VERTS_PER_FACE;
7308 DWORD flags25 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7309 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};
7310 const DWORD adjacency25[] = {-1, 1, -1, -1, -1, 0};
7311 const struct vertex_texcoord exp_vertices25[] =
7312 {
7313 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f}},
7314 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.7f}},
7315 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
7316
7317 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f}},
7318 {{ 0.0f, 0.0f, 0.f}, {0.1f, 0.2f}},
7319 };
7320 const DWORD exp_indices25[] = {0, 1, 2, 1, 3, 4};
7321 const DWORD exp_face_remap25[] = {0, 1};
7322 const DWORD exp_vertex_remap25[] = {0, 1, 2, 4, 5, -1};
7323 const DWORD exp_new_num_vertices25 = ARRAY_SIZE(exp_vertices25);
7324 /* Test 26. Weld color with usage index larger than 1. Shows that none of
7325 * the epsilon values are used. */
7326 const struct vertex_color vertices26[] =
7327 {
7328 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7329 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7330 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7331
7332 {{ 3.0f, 3.0f, 0.f}, 0x00000000},
7333 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7334 {{ 1.0f, 0.0f, 0.f}, 0x01010101},
7335 };
7336 const DWORD indices26[] = {0, 1, 2, 3, 4, 5};
7337 const DWORD attributes26[] = {0, 0};
7338 const UINT num_vertices26 = ARRAY_SIZE(vertices26);
7339 const UINT num_faces26 = ARRAY_SIZE(indices26) / VERTS_PER_FACE;
7340 DWORD flags26 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7341 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};
7342 const DWORD adjacency26[] = {-1, 1, -1, -1, -1, 0};
7343 const struct vertex_color exp_vertices26[] =
7344 {
7345 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7346 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7347 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7348
7349 {{ 2.0f, 3.0f, 0.f}, 0x00000000},
7350 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7351 {{ 0.0f, 0.0f, 0.f}, 0x01010101},
7352 };
7353 const DWORD exp_indices26[] = {0, 1, 2, 3, 4, 5};
7354 const DWORD exp_face_remap26[] = {0, 1};
7355 const DWORD exp_vertex_remap26[] = {0, 1, 2, 3, 4, 5};
7356 const DWORD exp_new_num_vertices26 = ARRAY_SIZE(exp_vertices26);
7357 /* Test 27. Weld color with usage index larger than 1. Check that the
7358 * default epsilon of 1e-6f is used. */
7359 D3DXVECTOR4 zero_float4 = {0.0f, 0.0f, 0.0f, 0.0f};
7360 D3DXVECTOR4 almost_zero_float4 = {0.0f + FLT_EPSILON, 0.0f + FLT_EPSILON, 0.0f + FLT_EPSILON, 0.0f + FLT_EPSILON};
7361 const struct vertex_color_float4 vertices27[] =
7362 {
7363 {{ 0.0f, 3.0f, 0.f}, zero_float4},
7364 {{ 2.0f, 3.0f, 0.f}, zero_float4},
7365 {{ 0.0f, 0.0f, 0.f}, zero_float4},
7366
7367 {{ 3.0f, 3.0f, 0.f}, almost_zero_float4},
7368 {{ 3.0f, 0.0f, 0.f}, zero_float4},
7369 {{ 1.0f, 0.0f, 0.f}, almost_zero_float4},
7370 };
7371 const DWORD indices27[] = {0, 1, 2, 3, 4, 5};
7372 const DWORD attributes27[] = {0, 0};
7373 const UINT num_vertices27 = ARRAY_SIZE(vertices27);
7374 const UINT num_faces27 = ARRAY_SIZE(indices27) / VERTS_PER_FACE;
7375 DWORD flags27 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7376 const D3DXWELDEPSILONS epsilons27 = {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.0f}, 0.0f, 0.0f, 0.0f};
7377 const DWORD adjacency27[] = {-1, 1, -1, -1, -1, 0};
7378 const struct vertex_color_float4 exp_vertices27[] =
7379 {
7380 {{ 0.0f, 3.0f, 0.f}, zero_float4},
7381 {{ 2.0f, 3.0f, 0.f}, zero_float4},
7382 {{ 0.0f, 0.0f, 0.f}, zero_float4},
7383
7384 {{ 3.0f, 0.0f, 0.f}, zero_float4},
7385 };
7386 const DWORD exp_indices27[] = {0, 1, 2, 1, 3, 2};
7387 const DWORD exp_face_remap27[] = {0, 1};
7388 const DWORD exp_vertex_remap27[] = {0, 1, 2, 4, -1, -1};
7389 const DWORD exp_new_num_vertices27 = ARRAY_SIZE(exp_vertices27);
7390 /* Test 28. Weld one normal with UDEC3. */
7391 const DWORD dword_udec3_zero = init_udec3_dword(0, 0, 0, 1);
7392 const DWORD dword_udec3_1023 = init_udec3_dword(1023, 1023, 1023, 1);
7393 const DWORD dword_udec3_1022 = init_udec3_dword(1022, 1022, 1022, 1);
7394 const struct vertex_normal_udec3 vertices28[] =
7395 {
7396 {{ 0.0f, 3.0f, 0.f}, dword_udec3_zero},
7397 {{ 2.0f, 3.0f, 0.f}, dword_udec3_zero},
7398 {{ 0.0f, 0.0f, 0.f}, dword_udec3_zero},
7399
7400 {{ 3.0f, 3.0f, 0.f}, dword_udec3_1023},
7401 {{ 3.0f, 0.0f, 0.f}, dword_udec3_zero},
7402 {{ 1.0f, 0.0f, 0.f}, dword_udec3_1022},
7403 };
7404 const DWORD indices28[] = {0, 1, 2, 3, 4, 5};
7405 const DWORD attributes28[] = {0, 0};
7406 const UINT num_vertices28 = ARRAY_SIZE(vertices28);
7407 const UINT num_faces28 = ARRAY_SIZE(indices28) / VERTS_PER_FACE;
7408 DWORD flags28 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7409 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};
7410 const DWORD adjacency28[] = {-1, 1, -1, -1, -1, 0};
7411 const struct vertex_normal_udec3 exp_vertices28[] =
7412 {
7413 {{ 0.0f, 3.0f, 0.f}, dword_udec3_zero},
7414 {{ 2.0f, 3.0f, 0.f}, dword_udec3_zero},
7415 {{ 0.0f, 0.0f, 0.f}, dword_udec3_zero},
7416
7417 {{ 2.0f, 3.0f, 0.f}, dword_udec3_1023},
7418 {{ 3.0f, 0.0f, 0.f}, dword_udec3_zero},
7419 };
7420 const DWORD exp_indices28[] = {0, 1, 2, 3, 4, 2};
7421 const DWORD exp_face_remap28[] = {0, 1};
7422 const DWORD exp_vertex_remap28[] = {0, 1, 2, 3, 4, -1};
7423 const DWORD exp_new_num_vertices28 = ARRAY_SIZE(exp_vertices28);
7424 /* Test 29. Weld one normal with DEC3N. */
7425 const DWORD dword_dec3n_zero = init_dec3n_dword(0, 0, 0, 1);
7426 const DWORD dword_dec3n_511 = init_dec3n_dword(511, 511, 511, 1);
7427 const DWORD dword_dec3n_510 = init_dec3n_dword(510, 510, 510, 1);
7428 const struct vertex_normal_dec3n vertices29[] =
7429 {
7430 {{ 0.0f, 3.0f, 0.f}, dword_dec3n_zero},
7431 {{ 2.0f, 3.0f, 0.f}, dword_dec3n_zero},
7432 {{ 0.0f, 0.0f, 0.f}, dword_dec3n_zero},
7433
7434 {{ 3.0f, 3.0f, 0.f}, dword_dec3n_511},
7435 {{ 3.0f, 0.0f, 0.f}, dword_dec3n_zero},
7436 {{ 1.0f, 0.0f, 0.f}, dword_dec3n_510},
7437 };
7438 const DWORD indices29[] = {0, 1, 2, 3, 4, 5};
7439 const DWORD attributes29[] = {0, 0};
7440 const UINT num_vertices29 = ARRAY_SIZE(vertices29);
7441 const UINT num_faces29 = ARRAY_SIZE(indices29) / VERTS_PER_FACE;
7442 DWORD flags29 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7443 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};
7444 const DWORD adjacency29[] = {-1, 1, -1, -1, -1, 0};
7445 const struct vertex_normal_dec3n exp_vertices29[] =
7446 {
7447 {{ 0.0f, 3.0f, 0.f}, dword_dec3n_zero},
7448 {{ 2.0f, 3.0f, 0.f}, dword_dec3n_zero},
7449 {{ 0.0f, 0.0f, 0.f}, dword_dec3n_zero},
7450
7451 {{ 2.0f, 3.0f, 0.f}, dword_dec3n_511},
7452 {{ 3.0f, 0.0f, 0.f}, dword_dec3n_zero},
7453 };
7454 const DWORD exp_indices29[] = {0, 1, 2, 3, 4, 2};
7455 const DWORD exp_face_remap29[] = {0, 1};
7456 const DWORD exp_vertex_remap29[] = {0, 1, 2, 3, 4, -1};
7457 const DWORD exp_new_num_vertices29 = ARRAY_SIZE(exp_vertices29);
7458 /* All mesh data */
7459 DWORD *adjacency_out = NULL;
7460 DWORD *face_remap = NULL;
7461 ID3DXMesh *mesh = NULL;
7462 ID3DXBuffer *vertex_remap = NULL;
7463 struct
7464 {
7465 const BYTE *vertices;
7466 const DWORD *indices;
7467 const DWORD *attributes;
7468 const DWORD num_vertices;
7469 const DWORD num_faces;
7470 const DWORD options;
7471 D3DVERTEXELEMENT9 *declaration;
7472 const UINT vertex_size;
7473 const DWORD flags;
7474 const D3DXWELDEPSILONS *epsilons;
7475 const DWORD *adjacency;
7476 const BYTE *exp_vertices;
7477 const DWORD *exp_indices;
7478 const DWORD *exp_face_remap;
7479 const DWORD *exp_vertex_remap;
7480 const DWORD exp_new_num_vertices;
7481 }
7482 tc[] =
7483 {
7484 {
7485 (BYTE*)vertices0,
7486 indices0,
7487 attributes0,
7488 num_vertices0,
7489 num_faces0,
7490 options,
7491 declaration_normal,
7492 vertex_size_normal,
7493 flags0,
7494 NULL,
7495 adjacency0,
7496 (BYTE*)exp_vertices0,
7497 exp_indices0,
7498 exp_face_remap0,
7499 exp_vertex_remap0,
7500 exp_new_num_vertices0
7501 },
7502 {
7503 (BYTE*)vertices1,
7504 indices1,
7505 attributes1,
7506 num_vertices1,
7507 num_faces1,
7508 options,
7509 declaration_normal,
7510 vertex_size_normal,
7511 flags1,
7512 NULL,
7513 adjacency1,
7514 (BYTE*)exp_vertices1,
7515 exp_indices1,
7516 exp_face_remap1,
7517 exp_vertex_remap1,
7518 exp_new_num_vertices1
7519 },
7520 {
7521 (BYTE*)vertices2,
7522 indices2,
7523 attributes2,
7524 num_vertices2,
7525 num_faces2,
7526 options,
7527 declaration_normal,
7528 vertex_size_normal,
7529 flags2,
7530 &epsilons2,
7531 adjacency2,
7532 (BYTE*)exp_vertices2,
7533 exp_indices2,
7534 exp_face_remap2,
7535 exp_vertex_remap2,
7536 exp_new_num_vertices2
7537 },
7538 {
7539 (BYTE*)vertices3,
7540 indices3,
7541 attributes3,
7542 num_vertices3,
7543 num_faces3,
7544 options,
7545 declaration_normal,
7546 vertex_size_normal,
7547 flags3,
7548 &epsilons3,
7549 adjacency3,
7550 (BYTE*)exp_vertices3,
7551 exp_indices3,
7552 exp_face_remap3,
7553 exp_vertex_remap3,
7554 exp_new_num_vertices3
7555 },
7556 {
7557 (BYTE*)vertices4,
7558 indices4,
7559 attributes4,
7560 num_vertices4,
7561 num_faces4,
7562 options,
7563 declaration_normal,
7564 vertex_size_normal,
7565 flags4,
7566 &epsilons4,
7567 adjacency4,
7568 (BYTE*)exp_vertices4,
7569 exp_indices4,
7570 exp_face_remap4,
7571 exp_vertex_remap4,
7572 exp_new_num_vertices4
7573 },
7574 /* Unusual ordering. */
7575 {
7576 (BYTE*)vertices5,
7577 indices5,
7578 attributes5,
7579 num_vertices5,
7580 num_faces5,
7581 options,
7582 declaration_normal,
7583 vertex_size_normal,
7584 flags5,
7585 NULL,
7586 adjacency5,
7587 (BYTE*)exp_vertices5,
7588 exp_indices5,
7589 exp_face_remap5,
7590 exp_vertex_remap5,
7591 exp_new_num_vertices5
7592 },
7593 {
7594 (BYTE*)vertices6,
7595 indices6,
7596 attributes6,
7597 num_vertices6,
7598 num_faces6,
7599 options,
7600 declaration_normal,
7601 vertex_size_normal,
7602 flags6,
7603 &epsilons6,
7604 adjacency6,
7605 (BYTE*)exp_vertices6,
7606 exp_indices6,
7607 exp_face_remap6,
7608 exp_vertex_remap6,
7609 exp_new_num_vertices6
7610 },
7611 {
7612 (BYTE*)vertices6,
7613 (DWORD*)indices6_16bit,
7614 attributes6,
7615 num_vertices6,
7616 num_faces6,
7617 options_16bit,
7618 declaration_normal,
7619 vertex_size_normal,
7620 flags6,
7621 &epsilons6,
7622 adjacency6,
7623 (BYTE*)exp_vertices6,
7624 exp_indices6,
7625 exp_face_remap6,
7626 exp_vertex_remap6,
7627 exp_new_num_vertices6
7628 },
7629 {
7630 (BYTE*)vertices8,
7631 indices8,
7632 attributes8,
7633 num_vertices8,
7634 num_faces8,
7635 options,
7636 declaration_normal,
7637 vertex_size_normal,
7638 flags8,
7639 &epsilons8,
7640 adjacency8,
7641 (BYTE*)exp_vertices8,
7642 exp_indices8,
7643 exp_face_remap8,
7644 exp_vertex_remap8,
7645 exp_new_num_vertices8
7646 },
7647 {
7648 (BYTE*)vertices9,
7649 indices9,
7650 attributes9,
7651 num_vertices9,
7652 num_faces9,
7653 options,
7654 declaration_normal,
7655 vertex_size_normal,
7656 flags9,
7657 &epsilons9,
7658 adjacency9,
7659 (BYTE*)exp_vertices9,
7660 exp_indices9,
7661 exp_face_remap9,
7662 exp_vertex_remap9,
7663 exp_new_num_vertices9
7664 },
7665 {
7666 (BYTE*)vertices10,
7667 indices10,
7668 attributes10,
7669 num_vertices10,
7670 num_faces10,
7671 options,
7672 declaration_blendweight,
7673 vertex_size_blendweight,
7674 flags10,
7675 &epsilons10,
7676 adjacency10,
7677 (BYTE*)exp_vertices10,
7678 exp_indices10,
7679 exp_face_remap10,
7680 exp_vertex_remap10,
7681 exp_new_num_vertices10
7682 },
7683 {
7684 (BYTE*)vertices11,
7685 indices11,
7686 attributes11,
7687 num_vertices11,
7688 num_faces11,
7689 options,
7690 declaration_texcoord,
7691 vertex_size_texcoord,
7692 flags11,
7693 &epsilons11,
7694 adjacency11,
7695 (BYTE*)exp_vertices11,
7696 exp_indices11,
7697 exp_face_remap11,
7698 exp_vertex_remap11,
7699 exp_new_num_vertices11
7700 },
7701 {
7702 (BYTE*)vertices12,
7703 indices12,
7704 attributes12,
7705 num_vertices12,
7706 num_faces12,
7707 options,
7708 declaration_color,
7709 vertex_size_color,
7710 flags12,
7711 &epsilons12,
7712 adjacency12,
7713 (BYTE*)exp_vertices12,
7714 exp_indices12,
7715 exp_face_remap12,
7716 exp_vertex_remap12,
7717 exp_new_num_vertices12
7718 },
7719 {
7720 (BYTE*)vertices13,
7721 indices13,
7722 attributes13,
7723 num_vertices13,
7724 num_faces13,
7725 options,
7726 declaration_normal3,
7727 vertex_size_normal,
7728 flags13,
7729 &epsilons13,
7730 adjacency13,
7731 (BYTE*)exp_vertices13,
7732 exp_indices13,
7733 exp_face_remap13,
7734 exp_vertex_remap13,
7735 exp_new_num_vertices13
7736 },
7737 {
7738 (BYTE*)vertices14,
7739 indices14,
7740 attributes14,
7741 num_vertices14,
7742 num_faces14,
7743 options,
7744 declaration_color,
7745 vertex_size_color,
7746 flags14,
7747 &epsilons14,
7748 adjacency14,
7749 (BYTE*)exp_vertices14,
7750 exp_indices14,
7751 exp_face_remap14,
7752 exp_vertex_remap14,
7753 exp_new_num_vertices14
7754 },
7755 {
7756 (BYTE*)vertices15,
7757 indices15,
7758 attributes15,
7759 num_vertices15,
7760 num_faces15,
7761 options,
7762 declaration_color_ubyte4n,
7763 vertex_size_color_ubyte4, /* UBYTE4 same size as UBYTE4N */
7764 flags15,
7765 &epsilons15,
7766 adjacency15,
7767 (BYTE*)exp_vertices15,
7768 exp_indices15,
7769 exp_face_remap15,
7770 exp_vertex_remap15,
7771 exp_new_num_vertices15
7772 },
7773 {
7774 (BYTE*)vertices16,
7775 indices16,
7776 attributes16,
7777 num_vertices16,
7778 num_faces16,
7779 options,
7780 declaration_color_ubyte4,
7781 vertex_size_color_ubyte4,
7782 flags16,
7783 &epsilons16,
7784 adjacency16,
7785 (BYTE*)exp_vertices16,
7786 exp_indices16,
7787 exp_face_remap16,
7788 exp_vertex_remap16,
7789 exp_new_num_vertices16
7790 },
7791 {
7792 (BYTE*)vertices17,
7793 indices17,
7794 attributes17,
7795 num_vertices17,
7796 num_faces17,
7797 options,
7798 declaration_texcoord_short2,
7799 vertex_size_texcoord_short2,
7800 flags17,
7801 &epsilons17,
7802 adjacency17,
7803 (BYTE*)exp_vertices17,
7804 exp_indices17,
7805 exp_face_remap17,
7806 exp_vertex_remap17,
7807 exp_new_num_vertices17
7808 },
7809 {
7810 (BYTE*)vertices18,
7811 indices18,
7812 attributes18,
7813 num_vertices18,
7814 num_faces18,
7815 options,
7816 declaration_texcoord_short2n,
7817 vertex_size_texcoord_short2, /* SHORT2 same size as SHORT2N */
7818 flags18,
7819 &epsilons18,
7820 adjacency18,
7821 (BYTE*)exp_vertices18,
7822 exp_indices18,
7823 exp_face_remap18,
7824 exp_vertex_remap18,
7825 exp_new_num_vertices18
7826 },
7827 {
7828 (BYTE*)vertices19,
7829 indices19,
7830 attributes19,
7831 num_vertices19,
7832 num_faces19,
7833 options,
7834 declaration_texcoord_ushort2n,
7835 vertex_size_texcoord_short2, /* SHORT2 same size as USHORT2N */
7836 flags19,
7837 &epsilons19,
7838 adjacency19,
7839 (BYTE*)exp_vertices19,
7840 exp_indices19,
7841 exp_face_remap19,
7842 exp_vertex_remap19,
7843 exp_new_num_vertices19
7844 },
7845 {
7846 (BYTE*)vertices20,
7847 indices20,
7848 attributes20,
7849 num_vertices20,
7850 num_faces20,
7851 options,
7852 declaration_normal_short4,
7853 vertex_size_normal_short4,
7854 flags20,
7855 &epsilons20,
7856 adjacency20,
7857 (BYTE*)exp_vertices20,
7858 exp_indices20,
7859 exp_face_remap20,
7860 exp_vertex_remap20,
7861 exp_new_num_vertices20
7862 },
7863 {
7864 (BYTE*)vertices21,
7865 indices21,
7866 attributes21,
7867 num_vertices21,
7868 num_faces21,
7869 options,
7870 declaration_normal_short4n,
7871 vertex_size_normal_short4, /* SHORT4 same size as SHORT4N */
7872 flags21,
7873 &epsilons21,
7874 adjacency21,
7875 (BYTE*)exp_vertices21,
7876 exp_indices21,
7877 exp_face_remap21,
7878 exp_vertex_remap21,
7879 exp_new_num_vertices21
7880 },
7881 {
7882 (BYTE*)vertices22,
7883 indices22,
7884 attributes22,
7885 num_vertices22,
7886 num_faces22,
7887 options,
7888 declaration_normal_ushort4n,
7889 vertex_size_normal_short4, /* SHORT4 same size as USHORT4N */
7890 flags22,
7891 &epsilons22,
7892 adjacency22,
7893 (BYTE*)exp_vertices22,
7894 exp_indices22,
7895 exp_face_remap22,
7896 exp_vertex_remap22,
7897 exp_new_num_vertices22
7898 },
7899 {
7900 (BYTE*)vertices23,
7901 indices23,
7902 attributes23,
7903 num_vertices23,
7904 num_faces23,
7905 options,
7906 declaration_texcoord_float16_2,
7907 vertex_size_texcoord_float16_2,
7908 flags23,
7909 &epsilons23,
7910 adjacency23,
7911 (BYTE*)exp_vertices23,
7912 exp_indices23,
7913 exp_face_remap23,
7914 exp_vertex_remap23,
7915 exp_new_num_vertices23
7916 },
7917 {
7918 (BYTE*)vertices24,
7919 indices24,
7920 attributes24,
7921 num_vertices24,
7922 num_faces24,
7923 options,
7924 declaration_texcoord_float16_4,
7925 vertex_size_texcoord_float16_4,
7926 flags24,
7927 &epsilons24,
7928 adjacency24,
7929 (BYTE*)exp_vertices24,
7930 exp_indices24,
7931 exp_face_remap24,
7932 exp_vertex_remap24,
7933 exp_new_num_vertices24
7934 },
7935 {
7936 (BYTE*)vertices25,
7937 indices25,
7938 attributes25,
7939 num_vertices25,
7940 num_faces25,
7941 options,
7942 declaration_texcoord10,
7943 vertex_size_texcoord,
7944 flags25,
7945 &epsilons25,
7946 adjacency25,
7947 (BYTE*)exp_vertices25,
7948 exp_indices25,
7949 exp_face_remap25,
7950 exp_vertex_remap25,
7951 exp_new_num_vertices25
7952 },
7953 {
7954 (BYTE*)vertices26,
7955 indices26,
7956 attributes26,
7957 num_vertices26,
7958 num_faces26,
7959 options,
7960 declaration_color2,
7961 vertex_size_color,
7962 flags26,
7963 &epsilons26,
7964 adjacency26,
7965 (BYTE*)exp_vertices26,
7966 exp_indices26,
7967 exp_face_remap26,
7968 exp_vertex_remap26,
7969 exp_new_num_vertices26
7970 },
7971 {
7972 (BYTE*)vertices27,
7973 indices27,
7974 attributes27,
7975 num_vertices27,
7976 num_faces27,
7977 options,
7978 declaration_color2_float4,
7979 vertex_size_color_float4,
7980 flags27,
7981 &epsilons27,
7982 adjacency27,
7983 (BYTE*)exp_vertices27,
7984 exp_indices27,
7985 exp_face_remap27,
7986 exp_vertex_remap27,
7987 exp_new_num_vertices27
7988 },
7989 {
7990 (BYTE*)vertices28,
7991 indices28,
7992 attributes28,
7993 num_vertices28,
7994 num_faces28,
7995 options,
7996 declaration_normal_udec3,
7997 vertex_size_normal_udec3,
7998 flags28,
7999 &epsilons28,
8000 adjacency28,
8001 (BYTE*)exp_vertices28,
8002 exp_indices28,
8003 exp_face_remap28,
8004 exp_vertex_remap28,
8005 exp_new_num_vertices28
8006 },
8007 {
8008 (BYTE*)vertices29,
8009 indices29,
8010 attributes29,
8011 num_vertices29,
8012 num_faces29,
8013 options,
8014 declaration_normal_dec3n,
8015 vertex_size_normal_dec3n,
8016 flags29,
8017 &epsilons29,
8018 adjacency29,
8019 (BYTE*)exp_vertices29,
8020 exp_indices29,
8021 exp_face_remap29,
8022 exp_vertex_remap29,
8023 exp_new_num_vertices29
8024 }
8025 };
8026
8027 test_context = new_test_context();
8028 if (!test_context)
8029 {
8030 skip("Couldn't create test context\n");
8031 goto cleanup;
8032 }
8033
8034 for (i = 0; i < ARRAY_SIZE(tc); i++)
8035 {
8036 DWORD j;
8037 DWORD *vertex_remap_ptr;
8038 DWORD new_num_vertices;
8039
8040 hr = init_test_mesh(tc[i].num_faces, tc[i].num_vertices, tc[i].options,
8041 tc[i].declaration, test_context->device, &mesh,
8042 tc[i].vertices, tc[i].vertex_size,
8043 tc[i].indices, tc[i].attributes);
8044 if (FAILED(hr))
8045 {
8046 skip("Couldn't initialize test mesh %d.\n", i);
8047 goto cleanup;
8048 }
8049
8050 /* Allocate out parameters */
8051 adjacency_out = HeapAlloc(GetProcessHeap(), 0, VERTS_PER_FACE * tc[i].num_faces * sizeof(*adjacency_out));
8052 if (!adjacency_out)
8053 {
8054 skip("Couldn't allocate adjacency_out array.\n");
8055 goto cleanup;
8056 }
8057 face_remap = HeapAlloc(GetProcessHeap(), 0, tc[i].num_faces * sizeof(*face_remap));
8058 if (!adjacency_out)
8059 {
8060 skip("Couldn't allocate face_remap array.\n");
8061 goto cleanup;
8062 }
8063
8064 hr = D3DXWeldVertices(mesh, tc[i].flags, tc[i].epsilons, tc[i].adjacency,
8065 adjacency_out, face_remap, &vertex_remap);
8066 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
8067 /* Check number of vertices*/
8068 new_num_vertices = mesh->lpVtbl->GetNumVertices(mesh);
8069 ok(new_num_vertices == tc[i].exp_new_num_vertices,
8070 "Mesh %d: new_num_vertices == %d, expected %d.\n",
8071 i, new_num_vertices, tc[i].exp_new_num_vertices);
8072 /* Check index buffer */
8073 if (tc[i].options & D3DXMESH_32BIT)
8074 {
8075 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, (void**)&indices);
8076 if (FAILED(hr))
8077 {
8078 skip("Couldn't lock index buffer.\n");
8079 goto cleanup;
8080 }
8081 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
8082 {
8083 ok(indices[j] == tc[i].exp_indices[j],
8084 "Mesh %d: indices[%d] == %d, expected %d\n",
8085 i, j, indices[j], tc[i].exp_indices[j]);
8086 }
8087 }
8088 else
8089 {
8090 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, (void**)&indices_16bit);
8091 if (FAILED(hr))
8092 {
8093 skip("Couldn't lock index buffer.\n");
8094 goto cleanup;
8095 }
8096 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
8097 {
8098 ok(indices_16bit[j] == tc[i].exp_indices[j],
8099 "Mesh %d: indices_16bit[%d] == %d, expected %d\n",
8100 i, j, indices_16bit[j], tc[i].exp_indices[j]);
8101 }
8102 }
8103 mesh->lpVtbl->UnlockIndexBuffer(mesh);
8104 indices = NULL;
8105 indices_16bit = NULL;
8106 /* Check adjacency_out */
8107 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
8108 {
8109 ok(adjacency_out[j] == tc[i].adjacency[j],
8110 "Mesh %d: adjacency_out[%d] == %d, expected %d\n",
8111 i, j, adjacency_out[j], tc[i].adjacency[j]);
8112 }
8113 /* Check face_remap */
8114 for (j = 0; j < tc[i].num_faces; j++)
8115 {
8116 ok(face_remap[j] == tc[i].exp_face_remap[j],
8117 "Mesh %d: face_remap[%d] == %d, expected %d\n",
8118 i, j, face_remap[j], tc[i].exp_face_remap[j]);
8119 }
8120 /* Check vertex_remap */
8121 vertex_remap_ptr = vertex_remap->lpVtbl->GetBufferPointer(vertex_remap);
8122 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
8123 {
8124 ok(vertex_remap_ptr[j] == tc[i].exp_vertex_remap[j],
8125 "Mesh %d: vertex_remap_ptr[%d] == %d, expected %d\n",
8126 i, j, vertex_remap_ptr[j], tc[i].exp_vertex_remap[j]);
8127 }
8128 /* Check vertex buffer */
8129 hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, (void*)&vertices);
8130 if (FAILED(hr))
8131 {
8132 skip("Couldn't lock vertex buffer.\n");
8133 goto cleanup;
8134 }
8135 /* Check contents of re-ordered vertex buffer */
8136 for (j = 0; j < tc[i].exp_new_num_vertices; j++)
8137 {
8138 int index = tc[i].vertex_size*j;
8139 check_vertex_components(__LINE__, i, j, &vertices[index], &tc[i].exp_vertices[index], tc[i].declaration);
8140 }
8141 mesh->lpVtbl->UnlockVertexBuffer(mesh);
8142 vertices = NULL;
8143
8144 /* Free mesh and output data */
8145 HeapFree(GetProcessHeap(), 0, adjacency_out);
8146 adjacency_out = NULL;
8147 HeapFree(GetProcessHeap(), 0, face_remap);
8148 face_remap = NULL;
8149 vertex_remap->lpVtbl->Release(vertex_remap);
8150 vertex_remap = NULL;
8151 mesh->lpVtbl->Release(mesh);
8152 mesh = NULL;
8153 }
8154
8155 cleanup:
8156 HeapFree(GetProcessHeap(), 0, adjacency_out);
8157 HeapFree(GetProcessHeap(), 0, face_remap);
8158 if (indices) mesh->lpVtbl->UnlockIndexBuffer(mesh);
8159 if (indices_16bit) mesh->lpVtbl->UnlockIndexBuffer(mesh);
8160 if (mesh) mesh->lpVtbl->Release(mesh);
8161 if (vertex_remap) vertex_remap->lpVtbl->Release(vertex_remap);
8162 if (vertices) mesh->lpVtbl->UnlockVertexBuffer(mesh);
8163 free_test_context(test_context);
8164 }
8165
8166 static void test_clone_mesh(void)
8167 {
8168 HRESULT hr;
8169 struct test_context *test_context = NULL;
8170 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
8171 D3DVERTEXELEMENT9 declaration_pn[] =
8172 {
8173 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8174 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
8175 D3DDECL_END()
8176 };
8177 D3DVERTEXELEMENT9 declaration_pntc[] =
8178 {
8179 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8180 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
8181 {0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8182 D3DDECL_END()
8183 };
8184 D3DVERTEXELEMENT9 declaration_ptcn[] =
8185 {
8186 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8187 {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8188 {0, 20, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
8189 D3DDECL_END()
8190 };
8191 D3DVERTEXELEMENT9 declaration_ptc[] =
8192 {
8193 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8194 {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8195 D3DDECL_END()
8196 };
8197 D3DVERTEXELEMENT9 declaration_ptc_float16_2[] =
8198 {
8199 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8200 {0, 12, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8201 D3DDECL_END()
8202 };
8203 D3DVERTEXELEMENT9 declaration_ptc_float16_4[] =
8204 {
8205 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8206 {0, 12, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8207 D3DDECL_END()
8208 };
8209 D3DVERTEXELEMENT9 declaration_ptc_float1[] =
8210 {
8211 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8212 {0, 12, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8213 D3DDECL_END()
8214 };
8215 D3DVERTEXELEMENT9 declaration_ptc_float3[] =
8216 {
8217 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8218 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8219 D3DDECL_END()
8220 };
8221 D3DVERTEXELEMENT9 declaration_ptc_float4[] =
8222 {
8223 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8224 {0, 12, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8225 D3DDECL_END()
8226 };
8227 D3DVERTEXELEMENT9 declaration_ptc_d3dcolor[] =
8228 {
8229 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8230 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8231 D3DDECL_END()
8232 };
8233 D3DVERTEXELEMENT9 declaration_ptc_ubyte4[] =
8234 {
8235 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8236 {0, 12, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8237 D3DDECL_END()
8238 };
8239 D3DVERTEXELEMENT9 declaration_ptc_ubyte4n[] =
8240 {
8241 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8242 {0, 12, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8243 D3DDECL_END()
8244 };
8245 D3DVERTEXELEMENT9 declaration_ptc_short2[] =
8246 {
8247 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8248 {0, 12, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8249 D3DDECL_END()
8250 };
8251 D3DVERTEXELEMENT9 declaration_ptc_short4[] =
8252 {
8253 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8254 {0, 12, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8255 D3DDECL_END()
8256 };
8257 D3DVERTEXELEMENT9 declaration_ptc_short2n[] =
8258 {
8259 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8260 {0, 12, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8261 D3DDECL_END()
8262 };
8263 D3DVERTEXELEMENT9 declaration_ptc_short4n[] =
8264 {
8265 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8266 {0, 12, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8267 D3DDECL_END()
8268 };
8269 D3DVERTEXELEMENT9 declaration_ptc_ushort2n[] =
8270 {
8271 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8272 {0, 12, D3DDECLTYPE_USHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8273 D3DDECL_END()
8274 };
8275 D3DVERTEXELEMENT9 declaration_ptc_ushort4n[] =
8276 {
8277 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8278 {0, 12, D3DDECLTYPE_USHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8279 D3DDECL_END()
8280 };
8281 D3DVERTEXELEMENT9 declaration_ptc_float16_2_partialu[] =
8282 {
8283 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8284 {0, 12, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_PARTIALU, D3DDECLUSAGE_TEXCOORD, 0},
8285 D3DDECL_END()
8286 };
8287 D3DVERTEXELEMENT9 declaration_pntc1[] =
8288 {
8289 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8290 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
8291 {0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
8292 D3DDECL_END()
8293 };
8294 const unsigned int VERTS_PER_FACE = 3;
8295 BYTE *vertices = NULL;
8296 INT i;
8297 struct vertex_pn
8298 {
8299 D3DXVECTOR3 position;
8300 D3DXVECTOR3 normal;
8301 };
8302 struct vertex_pntc
8303 {
8304 D3DXVECTOR3 position;
8305 D3DXVECTOR3 normal;
8306 D3DXVECTOR2 texcoords;
8307 };
8308 struct vertex_ptcn
8309 {
8310 D3DXVECTOR3 position;
8311 D3DXVECTOR2 texcoords;
8312 D3DXVECTOR3 normal;
8313 };
8314 struct vertex_ptc
8315 {
8316 D3DXVECTOR3 position;
8317 D3DXVECTOR2 texcoords;
8318 };
8319 struct vertex_ptc_float16_2
8320 {
8321 D3DXVECTOR3 position;
8322 WORD texcoords[2]; /* float16_2 */
8323 };
8324 struct vertex_ptc_float16_4
8325 {
8326 D3DXVECTOR3 position;
8327 WORD texcoords[4]; /* float16_4 */
8328 };
8329 struct vertex_ptc_float1
8330 {
8331 D3DXVECTOR3 position;
8332 FLOAT texcoords;
8333 };
8334 struct vertex_ptc_float3
8335 {
8336 D3DXVECTOR3 position;
8337 FLOAT texcoords[3];
8338 };
8339 struct vertex_ptc_float4
8340 {
8341 D3DXVECTOR3 position;
8342 FLOAT texcoords[4];
8343 };
8344 struct vertex_ptc_d3dcolor
8345 {
8346 D3DXVECTOR3 position;
8347 BYTE texcoords[4];
8348 };
8349 struct vertex_ptc_ubyte4
8350 {
8351 D3DXVECTOR3 position;
8352 BYTE texcoords[4];
8353 };
8354 struct vertex_ptc_ubyte4n
8355 {
8356 D3DXVECTOR3 position;
8357 BYTE texcoords[4];
8358 };
8359 struct vertex_ptc_short2
8360 {
8361 D3DXVECTOR3 position;
8362 SHORT texcoords[2];
8363 };
8364 struct vertex_ptc_short4
8365 {
8366 D3DXVECTOR3 position;
8367 SHORT texcoords[4];
8368 };
8369 struct vertex_ptc_ushort2n
8370 {
8371 D3DXVECTOR3 position;
8372 USHORT texcoords[2];
8373 };
8374 struct vertex_ptc_ushort4n
8375 {
8376 D3DXVECTOR3 position;
8377 USHORT texcoords[4];
8378 };
8379 struct vertex_ptc_udec3
8380 {
8381 D3DXVECTOR3 position;
8382 DWORD texcoords;
8383 };
8384 struct vertex_ptc_dec3n
8385 {
8386 D3DXVECTOR3 position;
8387 DWORD texcoords;
8388 };
8389 D3DXVECTOR3 up = {0.0f, 0.0f, 1.0f};
8390 D3DXVECTOR2 zero_vec2 = {0.0f, 0.0f};
8391 /* Test 0. Check that a mesh can be cloned if the new declaration is the
8392 * same as the one used to create the mesh.
8393 *
8394 * 0--1 3
8395 * | / /|
8396 * |/ / |
8397 * 2 5--4
8398 */
8399 const struct vertex_pn vertices0[] =
8400 {
8401 {{ 0.0f, 3.0f, 0.f}, up},
8402 {{ 2.0f, 3.0f, 0.f}, up},
8403 {{ 0.0f, 0.0f, 0.f}, up},
8404
8405 {{ 3.0f, 3.0f, 0.f}, up},
8406 {{ 3.0f, 0.0f, 0.f}, up},
8407 {{ 1.0f, 0.0f, 0.f}, up},
8408 };
8409 const UINT num_vertices0 = ARRAY_SIZE(vertices0);
8410 const UINT num_faces0 = ARRAY_SIZE(vertices0) / VERTS_PER_FACE;
8411 const UINT vertex_size0 = sizeof(*vertices0);
8412 /* Test 1. Check that 16-bit indices are handled. */
8413 const DWORD options_16bit = D3DXMESH_SYSTEMMEM;
8414 /* Test 2. Check that the size of each vertex is increased and the data
8415 * moved if the new declaration adds an element after the original elements.
8416 */
8417 const struct vertex_pntc exp_vertices2[] =
8418 {
8419 {{ 0.0f, 3.0f, 0.f}, up, zero_vec2},
8420 {{ 2.0f, 3.0f, 0.f}, up, zero_vec2},
8421 {{ 0.0f, 0.0f, 0.f}, up, zero_vec2},
8422
8423 {{ 3.0f, 3.0f, 0.f}, up, zero_vec2},
8424 {{ 3.0f, 0.0f, 0.f}, up, zero_vec2},
8425 {{ 1.0f, 0.0f, 0.f}, up, zero_vec2},
8426 };
8427 const UINT exp_vertex_size2 = sizeof(*exp_vertices2);
8428 /* Test 3. Check that the size of each vertex is increased and the data
8429 * moved if the new declaration adds an element between the original
8430 * elements.
8431 */
8432 const struct vertex_ptcn exp_vertices3[] =
8433 {
8434 {{ 0.0f, 3.0f, 0.f}, zero_vec2, up},
8435 {{ 2.0f, 3.0f, 0.f}, zero_vec2, up},
8436 {{ 0.0f, 0.0f, 0.f}, zero_vec2, up},
8437
8438 {{ 3.0f, 3.0f, 0.f}, zero_vec2, up},
8439 {{ 3.0f, 0.0f, 0.f}, zero_vec2, up},
8440 {{ 1.0f, 0.0f, 0.f}, zero_vec2, up},
8441 };
8442 const UINT exp_vertex_size3 = sizeof(*exp_vertices3);
8443 /* Test 4. Test that data types can be converted, e.g. FLOAT2 to FLOAT16_2. */
8444 const struct vertex_ptc vertices4[] =
8445 {
8446 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8447 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8448 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
8449
8450 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8451 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
8452 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
8453 };
8454 const UINT num_vertices4 = ARRAY_SIZE(vertices4);
8455 const UINT num_faces4 = ARRAY_SIZE(vertices4) / VERTS_PER_FACE;
8456 const UINT vertex_size4 = sizeof(*vertices4);
8457 const struct vertex_ptc_float16_2 exp_vertices4[] =
8458 {
8459 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
8460 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */
8461 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */
8462
8463 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd}}, /* {0.2f, 0.3f} */
8464 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
8465 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */
8466 };
8467 const UINT exp_vertex_size4 = sizeof(*exp_vertices4);
8468 /* Test 5. Convert FLOAT2 to FLOAT16_4. */
8469 const struct vertex_ptc vertices5[] =
8470 {
8471 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8472 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8473 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
8474
8475 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8476 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
8477 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
8478 };
8479 const UINT num_vertices5 = ARRAY_SIZE(vertices5);
8480 const UINT num_faces5 = ARRAY_SIZE(vertices5) / VERTS_PER_FACE;
8481 const UINT vertex_size5 = sizeof(*vertices5);
8482 const struct vertex_ptc_float16_4 exp_vertices5[] =
8483 {
8484 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00, 0, 0x3c00}}, /* {1.0f, 1.0f, 0.0f, 1.0f} */
8485 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a, 0, 0x3c00}}, /* {0.5f, 0.7f, 0.0f, 1.0f} */
8486 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd, 0, 0x3c00}}, /* {-0.2f, -0.3f, 0.0f, 1.0f} */
8487
8488 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd, 0, 0x3c00}}, /* {0.2f, 0.3f, 0.0f, 1.0f} */
8489 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00, 0, 0x3c00}}, /* {1.0f, 1.0f, 0.0f, 1.0f} */
8490 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266, 0, 0x3c00}}, /* {0.1f, 0.2f, 0.0f, 1.0f} */
8491 };
8492 const UINT exp_vertex_size5 = sizeof(*exp_vertices5);
8493 /* Test 6. Convert FLOAT2 to FLOAT1. */
8494 const struct vertex_ptc vertices6[] =
8495 {
8496 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8497 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8498 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
8499
8500 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8501 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
8502 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
8503 };
8504 const UINT num_vertices6 = ARRAY_SIZE(vertices6);
8505 const UINT num_faces6 = ARRAY_SIZE(vertices6) / VERTS_PER_FACE;
8506 const UINT vertex_size6 = sizeof(*vertices6);
8507 const struct vertex_ptc_float1 exp_vertices6[] =
8508 {
8509 {{ 0.0f, 3.0f, 0.f}, 1.0f},
8510 {{ 2.0f, 3.0f, 0.f}, 0.5f},
8511 {{ 0.0f, 0.0f, 0.f}, -0.2f},
8512
8513 {{ 3.0f, 3.0f, 0.f}, 0.2f},
8514 {{ 3.0f, 0.0f, 0.f}, 1.0f},
8515 {{ 1.0f, 0.0f, 0.f}, 0.1f},
8516 };
8517 const UINT exp_vertex_size6 = sizeof(*exp_vertices6);
8518 /* Test 7. Convert FLOAT2 to FLOAT3. */
8519 const struct vertex_ptc vertices7[] =
8520 {
8521 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8522 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8523 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
8524
8525 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8526 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
8527 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
8528 };
8529 const UINT num_vertices7 = ARRAY_SIZE(vertices7);
8530 const UINT num_faces7 = ARRAY_SIZE(vertices7) / VERTS_PER_FACE;
8531 const UINT vertex_size7 = sizeof(*vertices7);
8532 const struct vertex_ptc_float3 exp_vertices7[] =
8533 {
8534 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f, 0.0f}},
8535 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f, 0.0f}},
8536 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f, 0.0f}},
8537
8538 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f, 0.0f}},
8539 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f, 0.0f}},
8540 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f, 0.0f}},
8541 };
8542 const UINT exp_vertex_size7 = sizeof(*exp_vertices7);
8543 /* Test 8. Convert FLOAT2 to FLOAT4. */
8544 const struct vertex_ptc vertices8[] =
8545 {
8546 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8547 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8548 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
8549
8550 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8551 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
8552 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
8553 };
8554 const UINT num_vertices8 = ARRAY_SIZE(vertices8);
8555 const UINT num_faces8 = ARRAY_SIZE(vertices8) / VERTS_PER_FACE;
8556 const UINT vertex_size8 = sizeof(*vertices8);
8557 const struct vertex_ptc_float4 exp_vertices8[] =
8558 {
8559 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f, 0.0f, 1.0f}},
8560 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f, 0.0f, 1.0f}},
8561 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f, 0.0f, 1.0f}},
8562
8563 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f, 0.0f, 1.0f}},
8564 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f, 0.0f, 1.0f}},
8565 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f, 0.0f, 1.0f}},
8566 };
8567 const UINT exp_vertex_size8 = sizeof(*exp_vertices8);
8568 /* Test 9. Convert FLOAT2 to D3DCOLOR. */
8569 const struct vertex_ptc vertices9[] =
8570 {
8571 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8572 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8573 {{ 0.0f, 0.0f, 0.f}, {-0.4f, -0.6f}},
8574
8575 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8576 {{ 3.0f, 0.0f, 0.f}, { 2.0f, 256.0f}},
8577 {{ 1.0f, 0.0f, 0.f}, { 0.11f, 0.2f}},
8578 };
8579 const UINT num_vertices9 = ARRAY_SIZE(vertices9);
8580 const UINT num_faces9 = ARRAY_SIZE(vertices9) / VERTS_PER_FACE;
8581 const UINT vertex_size9 = sizeof(*vertices9);
8582 const struct vertex_ptc_d3dcolor exp_vertices9[] =
8583 {
8584 {{ 0.0f, 3.0f, 0.f}, {0, 255, 255, 255}},
8585 {{ 2.0f, 3.0f, 0.f}, {0, 179, 128, 255}},
8586 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 255}},
8587
8588 {{ 3.0f, 3.0f, 0.f}, {0, 77, 51, 255}},
8589 {{ 3.0f, 0.0f, 0.f}, {0, 255, 255, 255}},
8590 {{ 1.0f, 0.0f, 0.f}, {0, 51, 28, 255}},
8591 };
8592 const UINT exp_vertex_size9 = sizeof(*exp_vertices9);
8593 /* Test 10. Convert FLOAT2 to UBYTE4. */
8594 const struct vertex_ptc vertices10[] =
8595 {
8596 {{ 0.0f, 3.0f, 0.f}, { 0.0f, 1.0f}},
8597 {{ 2.0f, 3.0f, 0.f}, { 2.0f, 3.0f}},
8598 {{ 0.0f, 0.0f, 0.f}, { 254.0f, 255.0f}},
8599
8600 {{ 3.0f, 3.0f, 0.f}, { 256.0f, 257.0f}},
8601 {{ 3.0f, 0.0f, 0.f}, { 1.4f, 1.5f}},
8602 {{ 1.0f, 0.0f, 0.f}, {-4.0f, -5.0f}},
8603 };
8604 const UINT num_vertices10 = ARRAY_SIZE(vertices10);
8605 const UINT num_faces10 = ARRAY_SIZE(vertices10) / VERTS_PER_FACE;
8606 const UINT vertex_size10 = sizeof(*vertices10);
8607 const struct vertex_ptc_ubyte4 exp_vertices10[] =
8608 {
8609 {{ 0.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
8610 {{ 2.0f, 3.0f, 0.f}, {2, 3, 0, 1}},
8611 {{ 0.0f, 0.0f, 0.f}, {254, 255, 0, 1}},
8612
8613 {{ 3.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
8614 {{ 3.0f, 0.0f, 0.f}, {1, 2, 0, 1}},
8615 {{ 1.0f, 0.0f, 0.f}, {0, 0, 0, 1}},
8616 };
8617 const UINT exp_vertex_size10 = sizeof(*exp_vertices10);
8618 /* Test 11. Convert FLOAT2 to SHORT2. */
8619 const struct vertex_ptc vertices11[] =
8620 {
8621 {{ 0.0f, 3.0f, 0.f}, { 1.0f, -1.0f}},
8622 {{ 2.0f, 3.0f, 0.f}, { 0.4f, 0.5f}},
8623 {{ 0.0f, 0.0f, 0.f}, {-0.5f, -5.0f}},
8624
8625 {{ 3.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MIN}},
8626 {{ 3.0f, 0.0f, 0.f}, {SHRT_MAX + 1.0f, SHRT_MIN - 1.0f}},
8627 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX + 2.0f, SHRT_MIN - 2.0f}},
8628
8629 {{ 4.0f, 3.0f, 0.f}, {2 * SHRT_MAX, 2 * SHRT_MIN}},
8630 {{ 6.0f, 0.0f, 0.f}, {3 * SHRT_MAX, 3 * SHRT_MIN}},
8631 {{ 4.0f, 0.0f, 0.f}, {4 * SHRT_MAX, 4 * SHRT_MIN}},
8632 };
8633 const UINT num_vertices11 = ARRAY_SIZE(vertices11);
8634 const UINT num_faces11 = ARRAY_SIZE(vertices11) / VERTS_PER_FACE;
8635 const UINT vertex_size11 = sizeof(*vertices11);
8636 const struct vertex_ptc_short2 exp_vertices11[] =
8637 {
8638 {{ 0.0f, 3.0f, 0.f}, {1, 0}},
8639 {{ 2.0f, 3.0f, 0.f}, {0, 1}},
8640 {{ 0.0f, 0.0f, 0.f}, {0, -4}},
8641
8642 {{ 3.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MIN + 1}},
8643 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MIN}},
8644 {{ 1.0f, 0.0f, 0.f}, {SHRT_MIN + 1, SHRT_MAX}},
8645
8646 {{ 4.0f, 3.0f, 0.f}, {-2, 1}},
8647 {{ 6.0f, 0.0f, 0.f}, {32765, -32767}},
8648 {{ 4.0f, 0.0f, 0.f}, {-4, 1}},
8649 };
8650 const UINT exp_vertex_size11 = sizeof(*exp_vertices11);
8651 /* Test 12. Convert FLOAT2 to SHORT4. */
8652 const struct vertex_ptc vertices12[] =
8653 {
8654 {{ 0.0f, 3.0f, 0.f}, { 1.0f, -1.0f}},
8655 {{ 2.0f, 3.0f, 0.f}, { 0.4f, 0.5f}},
8656 {{ 0.0f, 0.0f, 0.f}, {-0.5f, -5.0f}},
8657
8658 {{ 3.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MIN}},
8659 {{ 3.0f, 0.0f, 0.f}, {SHRT_MAX + 1.0f, SHRT_MIN - 1.0f}},
8660 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX + 2.0f, SHRT_MIN - 2.0f}},
8661
8662 {{ 4.0f, 3.0f, 0.f}, {2 * SHRT_MAX, 2 * SHRT_MIN}},
8663 {{ 6.0f, 0.0f, 0.f}, {3 * SHRT_MAX, 3 * SHRT_MIN}},
8664 {{ 4.0f, 0.0f, 0.f}, {4 * SHRT_MAX, 4 * SHRT_MIN}},
8665 };
8666 const UINT num_vertices12 = ARRAY_SIZE(vertices12);
8667 const UINT num_faces12 = ARRAY_SIZE(vertices12) / VERTS_PER_FACE;
8668 const UINT vertex_size12 = sizeof(*vertices12);
8669 const struct vertex_ptc_short4 exp_vertices12[] =
8670 {
8671 {{ 0.0f, 3.0f, 0.f}, {1, 0, 0, 1}},
8672 {{ 2.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
8673 {{ 0.0f, 0.0f, 0.f}, {0, -4, 0, 1}},
8674
8675 {{ 3.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MIN + 1, 0, 1}},
8676 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MIN, 0, 1}},
8677 {{ 1.0f, 0.0f, 0.f}, {SHRT_MIN + 1, SHRT_MAX, 0, 1}},
8678
8679 {{ 4.0f, 3.0f, 0.f}, {-2, 1, 0, 1}},
8680 {{ 6.0f, 0.0f, 0.f}, {32765, -32767, 0, 1}},
8681 {{ 4.0f, 0.0f, 0.f}, {-4, 1, 0, 1}},
8682 };
8683 const UINT exp_vertex_size12 = sizeof(*exp_vertices12);
8684 /* Test 13. Convert FLOAT2 to UBYTE4N. */
8685 const struct vertex_ptc vertices13[] =
8686 {
8687 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 2.0f}},
8688 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8689 {{ 0.0f, 0.0f, 0.f}, {-0.4f, -0.5f}},
8690
8691 {{ 3.0f, 3.0f, 0.f}, {-0.6f, -1.0f}},
8692 {{ 3.0f, 0.0f, 0.f}, {UCHAR_MAX, UCHAR_MAX + 1}},
8693 {{ 1.0f, 0.0f, 0.f}, {2 * UCHAR_MAX, -UCHAR_MAX}},
8694 };
8695 const UINT num_vertices13 = ARRAY_SIZE(vertices13);
8696 const UINT num_faces13 = ARRAY_SIZE(vertices13) / VERTS_PER_FACE;
8697 const UINT vertex_size13 = sizeof(*vertices13);
8698 const struct vertex_ptc_ubyte4n exp_vertices13[] =
8699 {
8700 {{ 0.0f, 3.0f, 0.f}, {255, 255, 0, 255}},
8701 {{ 2.0f, 3.0f, 0.f}, {128, 179, 0, 255}},
8702 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 255}},
8703
8704 {{ 3.0f, 3.0f, 0.f}, {0, 0, 0, 255}},
8705 {{ 3.0f, 0.0f, 0.f}, {255, 255, 0, 255}},
8706 {{ 1.0f, 0.0f, 0.f}, {255, 0, 0, 255}},
8707 };
8708 const UINT exp_vertex_size13 = sizeof(*exp_vertices13);
8709 /* Test 14. Convert FLOAT2 to SHORT2N. */
8710 const struct vertex_ptc vertices14[] =
8711 {
8712 {{ 0.0f, 3.0f, 0.f}, {1.0f, 2.0f}},
8713 {{ 2.0f, 3.0f, 0.f}, {0.4f, 0.5f}},
8714 {{ 0.0f, 0.0f, 0.f}, {0.6f, -1.0f}},
8715
8716 {{ 3.0f, 3.0f, 0.f}, {-0.4f, -0.5f}},
8717 {{ 3.0f, 0.0f, 0.f}, {-0.9f, -0.99997}},
8718 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX, SHRT_MIN}},
8719 };
8720 const UINT num_vertices14 = ARRAY_SIZE(vertices14);
8721 const UINT num_faces14 = ARRAY_SIZE(vertices14) / VERTS_PER_FACE;
8722 const UINT vertex_size14 = sizeof(*vertices14);
8723 const struct vertex_ptc_short2 exp_vertices14[] =
8724 {
8725 {{ 0.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MAX}},
8726 {{ 2.0f, 3.0f, 0.f}, {13107, 16384}},
8727 {{ 0.0f, 0.0f, 0.f}, {19660, SHRT_MIN + 2}},
8728
8729 {{ 3.0f, 3.0f, 0.f}, {-13106, -16383}},
8730 {{ 3.0f, 0.0f, 0.f}, {-29489, SHRT_MIN + 3}},
8731 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX, SHRT_MIN + 2}},
8732 };
8733 const UINT exp_vertex_size14 = sizeof(*exp_vertices14);
8734 /* Test 15. Convert FLOAT2 to SHORT4N. */
8735 const struct vertex_ptc vertices15[] =
8736 {
8737 {{ 0.0f, 3.0f, 0.f}, {1.0f, 2.0f}},
8738 {{ 2.0f, 3.0f, 0.f}, {0.4f, 0.5f}},
8739 {{ 0.0f, 0.0f, 0.f}, {0.6f, -1.0f}},
8740
8741 {{ 3.0f, 3.0f, 0.f}, {-0.4f, -0.5f}},
8742 {{ 3.0f, 0.0f, 0.f}, {-0.9f, -0.99997}},
8743 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX, SHRT_MIN}},
8744 };
8745 const UINT num_vertices15 = ARRAY_SIZE(vertices15);
8746 const UINT num_faces15 = ARRAY_SIZE(vertices15) / VERTS_PER_FACE;
8747 const UINT vertex_size15 = sizeof(*vertices15);
8748 const struct vertex_ptc_short4 exp_vertices15[] =
8749 {
8750 {{ 0.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MAX, 0, SHRT_MAX}},
8751 {{ 2.0f, 3.0f, 0.f}, {13107, 16384, 0, SHRT_MAX}},
8752 {{ 0.0f, 0.0f, 0.f}, {19660, SHRT_MIN + 2, 0, SHRT_MAX}},
8753
8754 {{ 3.0f, 3.0f, 0.f}, {-13106, -16383, 0, SHRT_MAX}},
8755 {{ 3.0f, 0.0f, 0.f}, {-29489, SHRT_MIN + 3, 0, SHRT_MAX}},
8756 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX, SHRT_MIN + 2, 0, SHRT_MAX}},
8757 };
8758 const UINT exp_vertex_size15 = sizeof(*exp_vertices15);
8759 /* Test 16. Convert FLOAT2 to USHORT2N. */
8760 const struct vertex_ptc vertices16[] =
8761 {
8762 {{ 0.0f, 3.0f, 0.f}, {1.0f, 2.0f}},
8763 {{ 2.0f, 3.0f, 0.f}, {0.4f, 0.5f}},
8764 {{ 0.0f, 0.0f, 0.f}, {0.6f, -1.0f}},
8765
8766 {{ 3.0f, 3.0f, 0.f}, {-0.4f, -0.5f}},
8767 {{ 3.0f, 0.0f, 0.f}, {-0.9f, 0.99998f}},
8768 {{ 1.0f, 0.0f, 0.f}, {USHRT_MAX, 0.0f}},
8769 };
8770 const UINT num_vertices16 = ARRAY_SIZE(vertices16);
8771 const UINT num_faces16 = ARRAY_SIZE(vertices16) / VERTS_PER_FACE;
8772 const UINT vertex_size16 = sizeof(*vertices16);
8773 const struct vertex_ptc_ushort2n exp_vertices16[] =
8774 {
8775 {{ 0.0f, 3.0f, 0.f}, {USHRT_MAX, USHRT_MAX}},
8776 {{ 2.0f, 3.0f, 0.f}, {26214, 32768}},
8777 {{ 0.0f, 0.0f, 0.f}, {39321, 0}},
8778
8779 {{ 3.0f, 3.0f, 0.f}, {0, 0}},
8780 {{ 3.0f, 0.0f, 0.f}, {0, USHRT_MAX - 1}},
8781 {{ 1.0f, 0.0f, 0.f}, {USHRT_MAX, 0}},
8782 };
8783 const UINT exp_vertex_size16 = sizeof(*exp_vertices16);
8784 /* Test 17. Convert FLOAT2 to USHORT4N. */
8785 const struct vertex_ptc vertices17[] =
8786 {
8787 {{ 0.0f, 3.0f, 0.f}, {1.0f, 2.0f}},
8788 {{ 2.0f, 3.0f, 0.f}, {0.4f, 0.5f}},
8789 {{ 0.0f, 0.0f, 0.f}, {0.6f, -1.0f}},
8790
8791 {{ 3.0f, 3.0f, 0.f}, {-0.4f, -0.5f}},
8792 {{ 3.0f, 0.0f, 0.f}, {-0.9f, 0.99998f}},
8793 {{ 1.0f, 0.0f, 0.f}, {USHRT_MAX, 0.0f}},
8794 };
8795 const UINT num_vertices17 = ARRAY_SIZE(vertices17);
8796 const UINT num_faces17 = ARRAY_SIZE(vertices17) / VERTS_PER_FACE;
8797 const UINT vertex_size17 = sizeof(*vertices17);
8798 const struct vertex_ptc_ushort4n exp_vertices17[] =
8799 {
8800 {{ 0.0f, 3.0f, 0.f}, {USHRT_MAX, USHRT_MAX, 0, USHRT_MAX}},
8801 {{ 2.0f, 3.0f, 0.f}, {26214, 32768, 0, USHRT_MAX}},
8802 {{ 0.0f, 0.0f, 0.f}, {39321, 0, 0, USHRT_MAX}},
8803
8804 {{ 3.0f, 3.0f, 0.f}, {0, 0, 0, USHRT_MAX}},
8805 {{ 3.0f, 0.0f, 0.f}, {0, USHRT_MAX - 1, 0, USHRT_MAX}},
8806 {{ 1.0f, 0.0f, 0.f}, {USHRT_MAX, 0, 0, USHRT_MAX}},
8807 };
8808 const UINT exp_vertex_size17 = sizeof(*exp_vertices17);
8809 /* Test 18. Test that the method field is compared by converting a FLOAT2 to
8810 * FLOAT16_2. where the method field has been change from
8811 * D3DDECLMETHOD_DEFAULT to D3DDECLMETHOD_PARTIALU. */
8812 const struct vertex_ptc vertices18[] =
8813 {
8814 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8815 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8816 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
8817
8818 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8819 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
8820 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
8821 };
8822 const UINT num_vertices18 = ARRAY_SIZE(vertices18);
8823 const UINT num_faces18 = ARRAY_SIZE(vertices18) / VERTS_PER_FACE;
8824 const UINT vertex_size18 = sizeof(*vertices18);
8825 const struct vertex_ptc_float16_2 exp_vertices18[] =
8826 {
8827 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
8828 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */
8829 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */
8830
8831 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd}}, /* {0.2f, 0.3f} */
8832 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
8833 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */
8834 };
8835 const UINT exp_vertex_size18 = sizeof(*exp_vertices18);
8836 /* Test 19. Test that data is lost if usage index changes, e.g. TEXCOORD0
8837 * TEXCOORD1. */
8838 const struct vertex_pntc vertices19[] =
8839 {
8840 {{ 0.0f, 3.0f, 0.f}, up, { 1.0f, 1.0f}},
8841 {{ 2.0f, 3.0f, 0.f}, up, { 0.5f, 0.7f}},
8842 {{ 0.0f, 0.0f, 0.f}, up, {-0.2f, -0.3f}},
8843
8844 {{ 3.0f, 3.0f, 0.f}, up, { 0.2f, 0.3f}},
8845 {{ 3.0f, 0.0f, 0.f}, up, { 1.0f, 1.0f}},
8846 {{ 1.0f, 0.0f, 0.f}, up, { 0.1f, 0.2f}},
8847 };
8848 const UINT num_vertices19 = ARRAY_SIZE(vertices19);
8849 const UINT num_faces19 = ARRAY_SIZE(vertices19) / VERTS_PER_FACE;
8850 const UINT vertex_size19 = sizeof(*vertices19);
8851 const struct vertex_pntc exp_vertices19[] =
8852 {
8853 {{ 0.0f, 3.0f, 0.f}, up, zero_vec2},
8854 {{ 2.0f, 3.0f, 0.f}, up, zero_vec2},
8855 {{ 0.0f, 0.0f, 0.f}, up, zero_vec2},
8856
8857 {{ 3.0f, 3.0f, 0.f}, up, zero_vec2},
8858 {{ 3.0f, 0.0f, 0.f}, up, zero_vec2},
8859 {{ 1.0f, 0.0f, 0.f}, up, zero_vec2},
8860 };
8861 const UINT exp_vertex_size19 = sizeof(*exp_vertices19);
8862 /* Test 20. Another test that data is lost if usage index changes, e.g.
8863 * TEXCOORD1 to TEXCOORD0. */
8864 const struct vertex_pntc vertices20[] =
8865 {
8866 {{ 0.0f, 3.0f, 0.f}, up, { 1.0f, 1.0f}},
8867 {{ 2.0f, 3.0f, 0.f}, up, { 0.5f, 0.7f}},
8868 {{ 0.0f, 0.0f, 0.f}, up, {-0.2f, -0.3f}},
8869
8870 {{ 3.0f, 3.0f, 0.f}, up, { 0.2f, 0.3f}},
8871 {{ 3.0f, 0.0f, 0.f}, up, { 1.0f, 1.0f}},
8872 {{ 1.0f, 0.0f, 0.f}, up, { 0.1f, 0.2f}},
8873 };
8874 const UINT num_vertices20 = ARRAY_SIZE(vertices20);
8875 const UINT num_faces20 = ARRAY_SIZE(vertices20) / VERTS_PER_FACE;
8876 const UINT vertex_size20 = sizeof(*vertices20);
8877 const struct vertex_pntc exp_vertices20[] =
8878 {
8879 {{ 0.0f, 3.0f, 0.f}, up, zero_vec2},
8880 {{ 2.0f, 3.0f, 0.f}, up, zero_vec2},
8881 {{ 0.0f, 0.0f, 0.f}, up, zero_vec2},
8882
8883 {{ 3.0f, 3.0f, 0.f}, up, zero_vec2},
8884 {{ 3.0f, 0.0f, 0.f}, up, zero_vec2},
8885 {{ 1.0f, 0.0f, 0.f}, up, zero_vec2},
8886 };
8887 const UINT exp_vertex_size20 = sizeof(*exp_vertices20);
8888 /* Test 21. Convert FLOAT1 to FLOAT2. */
8889 const struct vertex_ptc_float1 vertices21[] =
8890 {
8891 {{ 0.0f, 3.0f, 0.f}, 1.0f},
8892 {{ 2.0f, 3.0f, 0.f}, 0.5f},
8893 {{ 0.0f, 0.0f, 0.f}, -0.2f},
8894
8895 {{ 3.0f, 3.0f, 0.f}, 0.2f},
8896 {{ 3.0f, 0.0f, 0.f}, 1.0f},
8897 {{ 1.0f, 0.0f, 0.f}, 0.1f},
8898 };
8899 const UINT num_vertices21 = ARRAY_SIZE(vertices21);
8900 const UINT num_faces21 = ARRAY_SIZE(vertices21) / VERTS_PER_FACE;
8901 const UINT vertex_size21 = sizeof(*vertices21);
8902 const struct vertex_ptc exp_vertices21[] =
8903 {
8904 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 0.0f}},
8905 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.0f}},
8906 {{ 0.0f, 0.0f, 0.f}, {-0.2f, 0.0f}},
8907
8908 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.0f}},
8909 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 0.0f}},
8910 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.0f}},
8911 };
8912 const UINT exp_vertex_size21 = sizeof(*exp_vertices21);
8913 /* Test 22. Convert FLOAT1 to FLOAT3. */
8914 const struct vertex_ptc_float1 vertices22[] =
8915 {
8916 {{ 0.0f, 3.0f, 0.f}, 1.0f},
8917 {{ 2.0f, 3.0f, 0.f}, 0.5f},
8918 {{ 0.0f, 0.0f, 0.f}, -0.2f},
8919
8920 {{ 3.0f, 3.0f, 0.f}, 0.2f},
8921 {{ 3.0f, 0.0f, 0.f}, 1.0f},
8922 {{ 1.0f, 0.0f, 0.f}, 0.1f},
8923 };
8924 const UINT num_vertices22 = ARRAY_SIZE(vertices22);
8925 const UINT num_faces22 = ARRAY_SIZE(vertices22) / VERTS_PER_FACE;
8926 const UINT vertex_size22 = sizeof(*vertices22);
8927 const struct vertex_ptc_float3 exp_vertices22[] =
8928 {
8929 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 0.0f, 0.0f}},
8930 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.0f, 0.0f}},
8931 {{ 0.0f, 0.0f, 0.f}, {-0.2f, 0.0f, 0.0f}},
8932
8933 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.0f, 0.0f}},
8934 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 0.0f, 0.0f}},
8935 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.0f, 0.0f}},
8936 };
8937 const UINT exp_vertex_size22 = sizeof(*exp_vertices22);
8938 /* Test 23. Convert FLOAT1 to FLOAT4. */
8939 const struct vertex_ptc_float1 vertices23[] =
8940 {
8941 {{ 0.0f, 3.0f, 0.f}, 1.0f},
8942 {{ 2.0f, 3.0f, 0.f}, 0.5f},
8943 {{ 0.0f, 0.0f, 0.f}, -0.2f},
8944
8945 {{ 3.0f, 3.0f, 0.f}, 0.2f},
8946 {{ 3.0f, 0.0f, 0.f}, 1.0f},
8947 {{ 1.0f, 0.0f, 0.f}, 0.1f},
8948 };
8949 const UINT num_vertices23 = ARRAY_SIZE(vertices23);
8950 const UINT num_faces23 = ARRAY_SIZE(vertices23) / VERTS_PER_FACE;
8951 const UINT vertex_size23 = sizeof(*vertices23);
8952 const struct vertex_ptc_float4 exp_vertices23[] =
8953 {
8954 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 0.0f, 0.0f, 1.0f}},
8955 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.0f, 0.0f, 1.0f}},
8956 {{ 0.0f, 0.0f, 0.f}, {-0.2f, 0.0f, 0.0f, 1.0f}},
8957
8958 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.0f, 0.0f, 1.0f}},
8959 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 0.0f, 0.0f, 1.0f}},
8960 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.0f, 0.0f, 1.0f}},
8961 };
8962 const UINT exp_vertex_size23 = sizeof(*exp_vertices23);
8963 /* Test 24. Convert FLOAT1 to D3DCOLOR. */
8964 const struct vertex_ptc_float1 vertices24[] =
8965 {
8966 {{ 0.0f, 3.0f, 0.f}, 1.0f},
8967 {{ 2.0f, 3.0f, 0.f}, 0.5f},
8968 {{ 0.0f, 0.0f, 0.f}, -0.2f},
8969
8970 {{ 3.0f, 3.0f, 0.f}, 0.2f},
8971 {{ 3.0f, 0.0f, 0.f}, 1.0f},
8972 {{ 1.0f, 0.0f, 0.f}, 0.11f},
8973 };
8974 const UINT num_vertices24 = ARRAY_SIZE(vertices24);
8975 const UINT num_faces24 = ARRAY_SIZE(vertices24) / VERTS_PER_FACE;
8976 const UINT vertex_size24 = sizeof(*vertices24);
8977 const struct vertex_ptc_d3dcolor exp_vertices24[] =
8978 {
8979 {{ 0.0f, 3.0f, 0.f}, {0, 0, 255, 255}},
8980 {{ 2.0f, 3.0f, 0.f}, {0, 0, 128, 255}},
8981 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 255}},
8982
8983 {{ 3.0f, 3.0f, 0.f}, {0, 0, 51, 255}},
8984 {{ 3.0f, 0.0f, 0.f}, {0, 0, 255, 255}},
8985 {{ 1.0f, 0.0f, 0.f}, {0, 0, 28, 255}},
8986 };
8987 const UINT exp_vertex_size24 = sizeof(*exp_vertices24);
8988 /* Test 25. Convert FLOAT1 to ubyte4. */
8989 const struct vertex_ptc_float1 vertices25[] =
8990 {
8991 {{ 0.0f, 3.0f, 0.f}, 0.0f},
8992 {{ 2.0f, 3.0f, 0.f}, 1.4f},
8993 {{ 0.0f, 0.0f, 0.f}, 1.5f},
8994
8995 {{ 3.0f, 3.0f, 0.f}, 255.0f},
8996 {{ 3.0f, 0.0f, 0.f}, 256.0f},
8997 {{ 1.0f, 0.0f, 0.f}, -1.0f},
8998 };
8999 const UINT num_vertices25 = ARRAY_SIZE(vertices25);
9000 const UINT num_faces25 = ARRAY_SIZE(vertices25) / VERTS_PER_FACE;
9001 const UINT vertex_size25 = sizeof(*vertices25);
9002 const struct vertex_ptc_ubyte4 exp_vertices25[] =
9003 {
9004 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 1}},
9005 {{ 2.0f, 3.0f, 0.f}, {1, 0, 0, 1}},
9006 {{ 0.0f, 0.0f, 0.f}, {2, 0, 0, 1}},
9007
9008 {{ 3.0f, 3.0f, 0.f}, {255, 0, 0, 1}},
9009 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 1}},
9010 {{ 1.0f, 0.0f, 0.f}, {0, 0, 0, 1}},
9011 };
9012 const UINT exp_vertex_size25 = sizeof(*exp_vertices25);
9013 /* Test 26. Convert FLOAT4 to D3DCOLOR. */
9014 const struct vertex_ptc_float4 vertices26[] =
9015 {
9016 {{ 0.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.4f, 0.5f}},
9017 {{ 2.0f, 3.0f, 0.f}, {-0.4f, -0.5f, -1.0f, -2.0f}},
9018 {{ 0.0f, 0.0f, 0.f}, {254.0f, 255.0f, 256.0f, 257.0f}},
9019
9020 {{ 3.0f, 3.0f, 0.f}, {0.1f, 0.2f, 0.3f, 0.4f}},
9021 {{ 3.0f, 0.0f, 0.f}, {0.5f, 0.6f, 0.7f, 0.8f}},
9022 {{ 1.0f, 0.0f, 0.f}, {0.9f, 0.99f, 0.995f, 0.999f}},
9023 };
9024 const UINT num_vertices26 = ARRAY_SIZE(vertices26);
9025 const UINT num_faces26 = ARRAY_SIZE(vertices26) / VERTS_PER_FACE;
9026 const UINT vertex_size26 = sizeof(*vertices26);
9027 const struct vertex_ptc_d3dcolor exp_vertices26[] =
9028 {
9029 {{ 0.0f, 3.0f, 0.f}, {102, 255, 0, 128}},
9030 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9031 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
9032
9033 {{ 3.0f, 3.0f, 0.f}, {77, 51, 26, 102}},
9034 {{ 3.0f, 0.0f, 0.f}, {179, 153, 128, 204}},
9035 {{ 1.0f, 0.0f, 0.f}, {254, 252, 230, 255}},
9036 };
9037 const UINT exp_vertex_size26 = sizeof(*exp_vertices26);
9038 /* Test 27. Convert D3DCOLOR to FLOAT4. */
9039 const struct vertex_ptc_d3dcolor vertices27[] =
9040 {
9041 {{ 0.0f, 3.0f, 0.f}, {102, 255, 0, 128}},
9042 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9043 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
9044
9045 {{ 3.0f, 3.0f, 0.f}, {77, 51, 26, 102}},
9046 {{ 3.0f, 0.0f, 0.f}, {179, 153, 128, 204}},
9047 {{ 1.0f, 0.0f, 0.f}, {254, 252, 230, 255}},
9048 };
9049 const UINT num_vertices27 = ARRAY_SIZE(vertices27);
9050 const UINT num_faces27 = ARRAY_SIZE(vertices27) / VERTS_PER_FACE;
9051 const UINT vertex_size27 = sizeof(*vertices27);
9052 const struct vertex_ptc_float4 exp_vertices27[] =
9053 {
9054 {{ 0.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.4f, 0.501961f}},
9055 {{ 2.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9056 {{ 0.0f, 0.0f, 0.f}, {1.0f, 1.0f, 1.0f, 1.0f}},
9057
9058 {{ 3.0f, 3.0f, 0.f}, {0.101961f, 0.2f, 0.301961f, 0.4f}},
9059 {{ 3.0f, 0.0f, 0.f}, {0.501961f, 0.6f, 0.701961f, 0.8f}},
9060 {{ 1.0f, 0.0f, 0.f}, {0.901961f, 0.988235f, 0.996078f, 1.0f}},
9061 };
9062 const UINT exp_vertex_size27 = sizeof(*exp_vertices27);
9063 /* Test 28. Convert UBYTE4 to FLOAT4. */
9064 const struct vertex_ptc_ubyte4 vertices28[] =
9065 {
9066 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9067 {{ 2.0f, 3.0f, 0.f}, {1, 1, 1, 1}},
9068 {{ 0.0f, 0.0f, 0.f}, {1, 0, 1, 0}},
9069
9070 {{ 3.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
9071 {{ 3.0f, 0.0f, 0.f}, {10, 20, 30, 40}},
9072 {{ 1.0f, 0.0f, 0.f}, {50, 60, 127, 255}},
9073 };
9074 const UINT num_vertices28 = ARRAY_SIZE(vertices28);
9075 const UINT num_faces28 = ARRAY_SIZE(vertices28) / VERTS_PER_FACE;
9076 const UINT vertex_size28 = sizeof(*vertices28);
9077 const struct vertex_ptc_float4 exp_vertices28[] =
9078 {
9079 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9080 {{ 2.0f, 3.0f, 0.f}, {1.0f, 1.0f, 1.0f, 1.0f}},
9081 {{ 0.0f, 0.0f, 0.f}, {1.0f, 0.0f, 1.0f, 0.0f}},
9082
9083 {{ 3.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.0f, 1.0f}},
9084 {{ 3.0f, 0.0f, 0.f}, {10.0f, 20.0f, 30.0f, 40.0f}},
9085 {{ 1.0f, 0.0f, 0.f}, {50.0f, 60.0f, 127.0f, 255.0f}},
9086 };
9087 const UINT exp_vertex_size28 = sizeof(*exp_vertices28);
9088 /* Test 29. Convert SHORT2 to FLOAT4. */
9089 const struct vertex_ptc_short2 vertices29[] =
9090 {
9091 {{ 0.0f, 3.0f, 0.f}, {0, 0}},
9092 {{ 2.0f, 3.0f, 0.f}, {0, 1}},
9093 {{ 0.0f, 0.0f, 0.f}, {1, 0}},
9094
9095 {{ 3.0f, 3.0f, 0.f}, {1, 1}},
9096 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MAX}},
9097 {{ 1.0f, 0.0f, 0.f}, {-42, 42}},
9098 };
9099 const UINT num_vertices29 = ARRAY_SIZE(vertices29);
9100 const UINT num_faces29 = ARRAY_SIZE(vertices29) / VERTS_PER_FACE;
9101 const UINT vertex_size29 = sizeof(*vertices29);
9102 const struct vertex_ptc_float4 exp_vertices29[] =
9103 {
9104 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 1.0f}},
9105 {{ 2.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.0f, 1.0f }},
9106 {{ 0.0f, 0.0f, 0.f}, {1.0f, 0.0f, 0.0f, 1.0f}},
9107
9108 {{ 3.0f, 3.0f, 0.f}, {1.0f, 1.0f, 0.0f, 1.0f}},
9109 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MAX, 0.0f, 1.0f}},
9110 {{ 1.0f, 0.0f, 0.f}, {-42.0f, 42.0f, 0.0f, 1.0f}},
9111 };
9112 const UINT exp_vertex_size29 = sizeof(*exp_vertices29);
9113 /* Test 29. Convert SHORT4 to FLOAT4. */
9114 const struct vertex_ptc_short4 vertices30[] =
9115 {
9116 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9117 {{ 2.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
9118 {{ 0.0f, 0.0f, 0.f}, {1, 0, 1, 0}},
9119
9120 {{ 3.0f, 3.0f, 0.f}, {1, 1, 1, 1}},
9121 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MAX, 1, 0}},
9122 {{ 1.0f, 0.0f, 0.f}, {-42, 42, SHRT_MAX, SHRT_MIN}},
9123 };
9124 const UINT num_vertices30 = ARRAY_SIZE(vertices30);
9125 const UINT num_faces30 = ARRAY_SIZE(vertices30) / VERTS_PER_FACE;
9126 const UINT vertex_size30 = sizeof(*vertices30);
9127 const struct vertex_ptc_float4 exp_vertices30[] =
9128 {
9129 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9130 {{ 2.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.0f, 1.0f }},
9131 {{ 0.0f, 0.0f, 0.f}, {1.0f, 0.0f, 1.0f, 0.0f}},
9132
9133 {{ 3.0f, 3.0f, 0.f}, {1.0f, 1.0f, 1.0f, 1.0f}},
9134 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MAX, 1.0f, 0.0f}},
9135 {{ 1.0f, 0.0f, 0.f}, {-42.0f, 42.0f, SHRT_MAX, SHRT_MIN}},
9136 };
9137 const UINT exp_vertex_size30 = sizeof(*exp_vertices30);
9138 /* Test 31. Convert UBYTE4N to FLOAT4. */
9139 const struct vertex_ptc_ubyte4n vertices31[] =
9140 {
9141 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9142 {{ 2.0f, 3.0f, 0.f}, {1, 1, 1, 1}},
9143 {{ 0.0f, 0.0f, 0.f}, {1, 0, 1, 0}},
9144
9145 {{ 3.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
9146 {{ 3.0f, 0.0f, 0.f}, {10, 20, 30, 40}},
9147 {{ 1.0f, 0.0f, 0.f}, {50, 60, 70, UCHAR_MAX}},
9148 };
9149 const UINT num_vertices31 = ARRAY_SIZE(vertices31);
9150 const UINT num_faces31 = ARRAY_SIZE(vertices31) / VERTS_PER_FACE;
9151 const UINT vertex_size31 = sizeof(*vertices31);
9152 const struct vertex_ptc_float4 exp_vertices31[] =
9153 {
9154 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9155 {{ 2.0f, 3.0f, 0.f}, {(FLOAT)1/UCHAR_MAX, (FLOAT)1/UCHAR_MAX, (FLOAT)1/UCHAR_MAX, (FLOAT)1/UCHAR_MAX}},
9156 {{ 0.0f, 0.0f, 0.f}, {(FLOAT)1/UCHAR_MAX, 0.0f, (FLOAT)1/UCHAR_MAX, 0.0f}},
9157
9158 {{ 3.0f, 3.0f, 0.f}, {0.0f, (FLOAT)1/UCHAR_MAX, 0.0f, (FLOAT)1/UCHAR_MAX}},
9159 {{ 3.0f, 0.0f, 0.f}, {(FLOAT)10/UCHAR_MAX, (FLOAT)20/UCHAR_MAX, (FLOAT)30/UCHAR_MAX, (FLOAT)40/UCHAR_MAX}},
9160 {{ 1.0f, 0.0f, 0.f}, {(FLOAT)50/UCHAR_MAX, (FLOAT)60/UCHAR_MAX, (FLOAT)70/UCHAR_MAX, 1.0f}},
9161 };
9162 const UINT exp_vertex_size31 = sizeof(*exp_vertices31);
9163 /* Test 32. Convert SHORT2N to FLOAT4. */
9164 const struct vertex_ptc_short2 vertices32[] =
9165 {
9166 {{ 0.0f, 3.0f, 0.f}, {0, 0}},
9167 {{ 2.0f, 3.0f, 0.f}, {0, 1}},
9168 {{ 0.0f, 0.0f, 0.f}, {1, 0}},
9169
9170 {{ 3.0f, 3.0f, 0.f}, {1, 1}},
9171 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN + 1, SHRT_MAX}},
9172 {{ 1.0f, 0.0f, 0.f}, {-42, 42}},
9173 };
9174 const UINT num_vertices32 = ARRAY_SIZE(vertices32);
9175 const UINT num_faces32 = ARRAY_SIZE(vertices32) / VERTS_PER_FACE;
9176 const UINT vertex_size32 = sizeof(*vertices32);
9177 const struct vertex_ptc_float4 exp_vertices32[] =
9178 {
9179 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 1.0f}},
9180 {{ 2.0f, 3.0f, 0.f}, {0.0f, 1.0f/SHRT_MAX, 0.0f, 1.0f}},
9181 {{ 0.0f, 0.0f, 0.f}, {1.0f/SHRT_MAX, 0.0f, 0.0f, 1.0f}},
9182
9183 {{ 3.0f, 3.0f, 0.f}, {1.0f/SHRT_MAX, 1.0f/SHRT_MAX, 0.0f, 1.0f}},
9184 {{ 3.0f, 0.0f, 0.f}, {-1.0f, 1.0f, 0.0f, 1.0f}},
9185 {{ 1.0f, 0.0f, 0.f}, {-42.0f/SHRT_MAX, 42.0f/SHRT_MAX, 0.0f, 1.0f}},
9186 };
9187 const UINT exp_vertex_size32 = sizeof(*exp_vertices32);
9188 /* Test 33. Convert SHORT4N to FLOAT4. */
9189 const struct vertex_ptc_short4 vertices33[] =
9190 {
9191 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9192 {{ 2.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
9193 {{ 0.0f, 0.0f, 0.f}, {1, 0, 1, 0}},
9194
9195 {{ 3.0f, 3.0f, 0.f}, {1, 1, 1, 1}},
9196 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN + 1, SHRT_MAX, SHRT_MIN + 1, SHRT_MAX}},
9197 {{ 1.0f, 0.0f, 0.f}, {-42, 42, 1, 1}},
9198 };
9199 const UINT num_vertices33 = ARRAY_SIZE(vertices33);
9200 const UINT num_faces33 = ARRAY_SIZE(vertices33) / VERTS_PER_FACE;
9201 const UINT vertex_size33 = sizeof(*vertices33);
9202 const struct vertex_ptc_float4 exp_vertices33[] =
9203 {
9204 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9205 {{ 2.0f, 3.0f, 0.f}, {0.0f, 1.0f/SHRT_MAX, 0.0f, 1.0f/SHRT_MAX}},
9206 {{ 0.0f, 0.0f, 0.f}, {1.0f/SHRT_MAX, 0.0f, 1.0f/SHRT_MAX, 0.0f}},
9207
9208 {{ 3.0f, 3.0f, 0.f}, {1.0f/SHRT_MAX, 1.0f/SHRT_MAX, 1.0f/SHRT_MAX, 1.0f/SHRT_MAX}},
9209 {{ 3.0f, 0.0f, 0.f}, {-1.0f, 1.0f, -1.0f, 1.0f}},
9210 {{ 1.0f, 0.0f, 0.f}, {-42.0f/SHRT_MAX, 42.0f/SHRT_MAX, 1.0f/SHRT_MAX, 1.0f/SHRT_MAX}},
9211 };
9212 const UINT exp_vertex_size33 = sizeof(*exp_vertices33);
9213 /* Test 34. Convert FLOAT16_2 to FLOAT4. */
9214 const struct vertex_ptc_float16_2 vertices34[] =
9215 {
9216 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
9217 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */
9218 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */
9219
9220 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd}}, /* {0.2f, 0.3f} */
9221 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
9222 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */
9223 };
9224 const UINT num_vertices34 = ARRAY_SIZE(vertices34);
9225 const UINT num_faces34 = ARRAY_SIZE(vertices34) / VERTS_PER_FACE;
9226 const UINT vertex_size34 = sizeof(*vertices34);
9227 const struct vertex_ptc_float4 exp_vertices34[] =
9228 {
9229 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f, 0.0f, 1.0f}},
9230 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.700195f, 0.0f, 1.0f}},
9231 {{ 0.0f, 0.0f, 0.f}, {-0.199951f, -0.300049f, 0.0f, 1.0f}},
9232
9233 {{ 3.0f, 3.0f, 0.f}, {0.199951f, 0.300049f, 0.0f, 1.0f}},
9234 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f, 0.0f, 1.0f}},
9235 {{ 1.0f, 0.0f, 0.f}, {0.099976f, 0.199951f, 0.0f, 1.0f}},
9236 };
9237 const UINT exp_vertex_size34 = sizeof(*exp_vertices34);
9238 /* Test 35. Convert FLOAT16_4 to FLOAT4. */
9239 const struct vertex_ptc_float16_4 vertices35[] =
9240 {
9241 {{ 0.0f, 3.0f, 0.f}, {0x0000, 0x0000, 0x0000, 0x0000}},
9242 {{ 2.0f, 3.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}},
9243 {{ 0.0f, 0.0f, 0.f}, {0x3c00, 0x0000, 0x3c00, 0x0000}},
9244
9245 {{ 3.0f, 3.0f, 0.f}, {0x0000, 0x3c00, 0x0000, 0x3c00}},
9246 {{ 3.0f, 0.0f, 0.f}, {0x3800, 0x399a, 0xb266, 0xb4cd}},
9247 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266, 0x2e66, 0x3266}},
9248 };
9249 const UINT num_vertices35 = ARRAY_SIZE(vertices35);
9250 const UINT num_faces35 = ARRAY_SIZE(vertices35) / VERTS_PER_FACE;
9251 const UINT vertex_size35 = sizeof(*vertices35);
9252 const struct vertex_ptc_float4 exp_vertices35[] =
9253 {
9254 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9255 {{ 2.0f, 3.0f, 0.f}, {1.0f, 1.0f, 1.0f, 1.0f}},
9256 {{ 0.0f, 0.0f, 0.f}, {1.0f, 0.0f, 1.0f, 0.0f}},
9257
9258 {{ 3.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.0f, 1.0f}},
9259 {{ 3.0f, 0.0f, 0.f}, {0.5f, 0.700195f, -0.199951f, -0.300049f}},
9260 {{ 1.0f, 0.0f, 0.f}, {0.099976f, 0.199951f, 0.099976f, 0.199951f}},
9261 };
9262 const UINT exp_vertex_size35 = sizeof(*exp_vertices35);
9263 /* Test 36. Check that vertex buffer sharing is ok. */
9264 const struct vertex_pn vertices36[] =
9265 {
9266 {{ 0.0f, 3.0f, 0.f}, up},
9267 {{ 2.0f, 3.0f, 0.f}, up},
9268 {{ 0.0f, 0.0f, 0.f}, up},
9269 };
9270 const UINT num_vertices36 = ARRAY_SIZE(vertices36);
9271 const UINT num_faces36 = ARRAY_SIZE(vertices36) / VERTS_PER_FACE;
9272 const UINT vertex_size36 = sizeof(*vertices36);
9273 const DWORD clone_options36 = options | D3DXMESH_VB_SHARE;
9274 /* Common mesh data */
9275 ID3DXMesh *mesh = NULL;
9276 ID3DXMesh *mesh_clone = NULL;
9277 struct
9278 {
9279 const BYTE *vertices;
9280 const DWORD *indices;
9281 const DWORD *attributes;
9282 const UINT num_vertices;
9283 const UINT num_faces;
9284 const UINT vertex_size;
9285 const DWORD create_options;
9286 const DWORD clone_options;
9287 D3DVERTEXELEMENT9 *declaration;
9288 D3DVERTEXELEMENT9 *new_declaration;
9289 const BYTE *exp_vertices;
9290 const UINT exp_vertex_size;
9291 }
9292 tc[] =
9293 {
9294 {
9295 (BYTE*)vertices0,
9296 NULL,
9297 NULL,
9298 num_vertices0,
9299 num_faces0,
9300 vertex_size0,
9301 options,
9302 options,
9303 declaration_pn,
9304 declaration_pn,
9305 (BYTE*)vertices0,
9306 vertex_size0
9307 },
9308 {
9309 (BYTE*)vertices0,
9310 NULL,
9311 NULL,
9312 num_vertices0,
9313 num_faces0,
9314 vertex_size0,
9315 options_16bit,
9316 options_16bit,
9317 declaration_pn,
9318 declaration_pn,
9319 (BYTE*)vertices0,
9320 vertex_size0
9321 },
9322 {
9323 (BYTE*)vertices0,
9324 NULL,
9325 NULL,
9326 num_vertices0,
9327 num_faces0,
9328 vertex_size0,
9329 options,
9330 options,
9331 declaration_pn,
9332 declaration_pntc,
9333 (BYTE*)exp_vertices2,
9334 exp_vertex_size2
9335 },
9336 {
9337 (BYTE*)vertices0,
9338 NULL,
9339 NULL,
9340 num_vertices0,
9341 num_faces0,
9342 vertex_size0,
9343 options,
9344 options,
9345 declaration_pn,
9346 declaration_ptcn,
9347 (BYTE*)exp_vertices3,
9348 exp_vertex_size3
9349 },
9350 {
9351 (BYTE*)vertices4,
9352 NULL,
9353 NULL,
9354 num_vertices4,
9355 num_faces4,
9356 vertex_size4,
9357 options,
9358 options,
9359 declaration_ptc,
9360 declaration_ptc_float16_2,
9361 (BYTE*)exp_vertices4,
9362 exp_vertex_size4
9363 },
9364 {
9365 (BYTE*)vertices5,
9366 NULL,
9367 NULL,
9368 num_vertices5,
9369 num_faces5,
9370 vertex_size5,
9371 options,
9372 options,
9373 declaration_ptc,
9374 declaration_ptc_float16_4,
9375 (BYTE*)exp_vertices5,
9376 exp_vertex_size5
9377 },
9378 {
9379 (BYTE*)vertices6,
9380 NULL,
9381 NULL,
9382 num_vertices6,
9383 num_faces6,
9384 vertex_size6,
9385 options,
9386 options,
9387 declaration_ptc,
9388 declaration_ptc_float1,
9389 (BYTE*)exp_vertices6,
9390 exp_vertex_size6
9391 },
9392 {
9393 (BYTE*)vertices7,
9394 NULL,
9395 NULL,
9396 num_vertices7,
9397 num_faces7,
9398 vertex_size7,
9399 options,
9400 options,
9401 declaration_ptc,
9402 declaration_ptc_float3,
9403 (BYTE*)exp_vertices7,
9404 exp_vertex_size7
9405 },
9406 {
9407 (BYTE*)vertices8,
9408 NULL,
9409 NULL,
9410 num_vertices8,
9411 num_faces8,
9412 vertex_size8,
9413 options,
9414 options,
9415 declaration_ptc,
9416 declaration_ptc_float4,
9417 (BYTE*)exp_vertices8,
9418 exp_vertex_size8
9419 },
9420 {
9421 (BYTE*)vertices9,
9422 NULL,
9423 NULL,
9424 num_vertices9,
9425 num_faces9,
9426 vertex_size9,
9427 options,
9428 options,
9429 declaration_ptc,
9430 declaration_ptc_d3dcolor,
9431 (BYTE*)exp_vertices9,
9432 exp_vertex_size9
9433 },
9434 {
9435 (BYTE*)vertices10,
9436 NULL,
9437 NULL,
9438 num_vertices10,
9439 num_faces10,
9440 vertex_size10,
9441 options,
9442 options,
9443 declaration_ptc,
9444 declaration_ptc_ubyte4,
9445 (BYTE*)exp_vertices10,
9446 exp_vertex_size10
9447 },
9448 {
9449 (BYTE*)vertices11,
9450 NULL,
9451 NULL,
9452 num_vertices11,
9453 num_faces11,
9454 vertex_size11,
9455 options,
9456 options,
9457 declaration_ptc,
9458 declaration_ptc_short2,
9459 (BYTE*)exp_vertices11,
9460 exp_vertex_size11
9461 },
9462 {
9463 (BYTE*)vertices12,
9464 NULL,
9465 NULL,
9466 num_vertices12,
9467 num_faces12,
9468 vertex_size12,
9469 options,
9470 options,
9471 declaration_ptc,
9472 declaration_ptc_short4,
9473 (BYTE*)exp_vertices12,
9474 exp_vertex_size12
9475 },
9476 {
9477 (BYTE*)vertices13,
9478 NULL,
9479 NULL,
9480 num_vertices13,
9481 num_faces13,
9482 vertex_size13,
9483 options,
9484 options,
9485 declaration_ptc,
9486 declaration_ptc_ubyte4n,
9487 (BYTE*)exp_vertices13,
9488 exp_vertex_size13
9489 },
9490 {
9491 (BYTE*)vertices14,
9492 NULL,
9493 NULL,
9494 num_vertices14,
9495 num_faces14,
9496 vertex_size14,
9497 options,
9498 options,
9499 declaration_ptc,
9500 declaration_ptc_short2n,
9501 (BYTE*)exp_vertices14,
9502 exp_vertex_size14
9503 },
9504 {
9505 (BYTE*)vertices15,
9506 NULL,
9507 NULL,
9508 num_vertices15,
9509 num_faces15,
9510 vertex_size15,
9511 options,
9512 options,
9513 declaration_ptc,
9514 declaration_ptc_short4n,
9515 (BYTE*)exp_vertices15,
9516 exp_vertex_size15
9517 },
9518 {
9519 (BYTE*)vertices16,
9520 NULL,
9521 NULL,
9522 num_vertices16,
9523 num_faces16,
9524 vertex_size16,
9525 options,
9526 options,
9527 declaration_ptc,
9528 declaration_ptc_ushort2n,
9529 (BYTE*)exp_vertices16,
9530 exp_vertex_size16
9531 },
9532 {
9533 (BYTE*)vertices17,
9534 NULL,
9535 NULL,
9536 num_vertices17,
9537 num_faces17,
9538 vertex_size17,
9539 options,
9540 options,
9541 declaration_ptc,
9542 declaration_ptc_ushort4n,
9543 (BYTE*)exp_vertices17,
9544 exp_vertex_size17
9545 },
9546 {
9547 (BYTE*)vertices18,
9548 NULL,
9549 NULL,
9550 num_vertices18,
9551 num_faces18,
9552 vertex_size18,
9553 options,
9554 options,
9555 declaration_ptc,
9556 declaration_ptc_float16_2_partialu,
9557 (BYTE*)exp_vertices18,
9558 exp_vertex_size18
9559 },
9560 {
9561 (BYTE*)vertices19,
9562 NULL,
9563 NULL,
9564 num_vertices19,
9565 num_faces19,
9566 vertex_size19,
9567 options,
9568 options,
9569 declaration_pntc,
9570 declaration_pntc1,
9571 (BYTE*)exp_vertices19,
9572 exp_vertex_size19
9573 },
9574 {
9575 (BYTE*)vertices20,
9576 NULL,
9577 NULL,
9578 num_vertices20,
9579 num_faces20,
9580 vertex_size20,
9581 options,
9582 options,
9583 declaration_pntc1,
9584 declaration_pntc,
9585 (BYTE*)exp_vertices20,
9586 exp_vertex_size20
9587 },
9588 {
9589 (BYTE*)vertices21,
9590 NULL,
9591 NULL,
9592 num_vertices21,
9593 num_faces21,
9594 vertex_size21,
9595 options,
9596 options,
9597 declaration_ptc_float1,
9598 declaration_ptc,
9599 (BYTE*)exp_vertices21,
9600 exp_vertex_size21
9601 },
9602 {
9603 (BYTE*)vertices22,
9604 NULL,
9605 NULL,
9606 num_vertices22,
9607 num_faces22,
9608 vertex_size22,
9609 options,
9610 options,
9611 declaration_ptc_float1,
9612 declaration_ptc_float3,
9613 (BYTE*)exp_vertices22,
9614 exp_vertex_size22
9615 },
9616 {
9617 (BYTE*)vertices23,
9618 NULL,
9619 NULL,
9620 num_vertices23,
9621 num_faces23,
9622 vertex_size23,
9623 options,
9624 options,
9625 declaration_ptc_float1,
9626 declaration_ptc_float4,
9627 (BYTE*)exp_vertices23,
9628 exp_vertex_size23
9629 },
9630 {
9631 (BYTE*)vertices24,
9632 NULL,
9633 NULL,
9634 num_vertices24,
9635 num_faces24,
9636 vertex_size24,
9637 options,
9638 options,
9639 declaration_ptc_float1,
9640 declaration_ptc_d3dcolor,
9641 (BYTE*)exp_vertices24,
9642 exp_vertex_size24
9643 },
9644 {
9645 (BYTE*)vertices25,
9646 NULL,
9647 NULL,
9648 num_vertices25,
9649 num_faces25,
9650 vertex_size25,
9651 options,
9652 options,
9653 declaration_ptc_float1,
9654 declaration_ptc_ubyte4,
9655 (BYTE*)exp_vertices25,
9656 exp_vertex_size25
9657 },
9658 {
9659 (BYTE*)vertices26,
9660 NULL,
9661 NULL,
9662 num_vertices26,
9663 num_faces26,
9664 vertex_size26,
9665 options,
9666 options,
9667 declaration_ptc_float4,
9668 declaration_ptc_d3dcolor,
9669 (BYTE*)exp_vertices26,
9670 exp_vertex_size26
9671 },
9672 {
9673 (BYTE*)vertices27,
9674 NULL,
9675 NULL,
9676 num_vertices27,
9677 num_faces27,
9678 vertex_size27,
9679 options,
9680 options,
9681 declaration_ptc_d3dcolor,
9682 declaration_ptc_float4,
9683 (BYTE*)exp_vertices27,
9684 exp_vertex_size27
9685 },
9686 {
9687 (BYTE*)vertices28,
9688 NULL,
9689 NULL,
9690 num_vertices28,
9691 num_faces28,
9692 vertex_size28,
9693 options,
9694 options,
9695 declaration_ptc_ubyte4,
9696 declaration_ptc_float4,
9697 (BYTE*)exp_vertices28,
9698 exp_vertex_size28
9699 },
9700 {
9701 (BYTE*)vertices29,
9702 NULL,
9703 NULL,
9704 num_vertices29,
9705 num_faces29,
9706 vertex_size29,
9707 options,
9708 options,
9709 declaration_ptc_short2,
9710 declaration_ptc_float4,
9711 (BYTE*)exp_vertices29,
9712 exp_vertex_size29
9713 },
9714 {
9715 (BYTE*)vertices30,
9716 NULL,
9717 NULL,
9718 num_vertices30,
9719 num_faces30,
9720 vertex_size30,
9721 options,
9722 options,
9723 declaration_ptc_short4,
9724 declaration_ptc_float4,
9725 (BYTE*)exp_vertices30,
9726 exp_vertex_size30
9727 },
9728 {
9729 (BYTE*)vertices31,
9730 NULL,
9731 NULL,
9732 num_vertices31,
9733 num_faces31,
9734 vertex_size31,
9735 options,
9736 options,
9737 declaration_ptc_ubyte4n,
9738 declaration_ptc_float4,
9739 (BYTE*)exp_vertices31,
9740 exp_vertex_size31
9741 },
9742 {
9743 (BYTE*)vertices32,
9744 NULL,
9745 NULL,
9746 num_vertices32,
9747 num_faces32,
9748 vertex_size32,
9749 options,
9750 options,
9751 declaration_ptc_short2n,
9752 declaration_ptc_float4,
9753 (BYTE*)exp_vertices32,
9754 exp_vertex_size32
9755 },
9756 {
9757 (BYTE*)vertices33,
9758 NULL,
9759 NULL,
9760 num_vertices33,
9761 num_faces33,
9762 vertex_size33,
9763 options,
9764 options,
9765 declaration_ptc_short4n,
9766 declaration_ptc_float4,
9767 (BYTE*)exp_vertices33,
9768 exp_vertex_size33
9769 },
9770 {
9771 (BYTE*)vertices34,
9772 NULL,
9773 NULL,
9774 num_vertices34,
9775 num_faces34,
9776 vertex_size34,
9777 options,
9778 options,
9779 declaration_ptc_float16_2,
9780 declaration_ptc_float4,
9781 (BYTE*)exp_vertices34,
9782 exp_vertex_size34
9783 },
9784 {
9785 (BYTE*)vertices35,
9786 NULL,
9787 NULL,
9788 num_vertices35,
9789 num_faces35,
9790 vertex_size35,
9791 options,
9792 options,
9793 declaration_ptc_float16_4,
9794 declaration_ptc_float4,
9795 (BYTE*)exp_vertices35,
9796 exp_vertex_size35
9797 },
9798 {
9799 (BYTE*)vertices36,
9800 NULL,
9801 NULL,
9802 num_vertices36,
9803 num_faces36,
9804 vertex_size36,
9805 options,
9806 clone_options36,
9807 declaration_pn,
9808 declaration_pn,
9809 (BYTE*)vertices36,
9810 vertex_size36
9811 },
9812 };
9813
9814 test_context = new_test_context();
9815 if (!test_context)
9816 {
9817 skip("Couldn't create test context\n");
9818 goto cleanup;
9819 }
9820
9821 for (i = 0; i < ARRAY_SIZE(tc); i++)
9822 {
9823 UINT j;
9824 D3DVERTEXELEMENT9 new_declaration[MAX_FVF_DECL_SIZE];
9825 UINT exp_new_decl_length, new_decl_length;
9826 UINT exp_new_decl_size, new_decl_size;
9827
9828 hr = init_test_mesh(tc[i].num_faces, tc[i].num_vertices,
9829 tc[i].create_options,
9830 tc[i].declaration,
9831 test_context->device, &mesh,
9832 tc[i].vertices, tc[i].vertex_size,
9833 tc[i].indices, tc[i].attributes);
9834 if (FAILED(hr))
9835 {
9836 skip("Couldn't initialize test mesh %d. Got %x expected D3D_OK\n", i, hr);
9837 goto cleanup;
9838 }
9839
9840 hr = mesh->lpVtbl->CloneMesh(mesh, tc[i].clone_options, tc[i].new_declaration,
9841 test_context->device, &mesh_clone);
9842 ok(hr == D3D_OK, "CloneMesh test case %d failed. Got %x\n, expected D3D_OK\n", i, hr);
9843
9844 hr = mesh_clone->lpVtbl->GetDeclaration(mesh_clone, new_declaration);
9845 ok(hr == D3D_OK, "GetDeclaration test case %d failed. Got %x\n, expected D3D_OK\n", i, hr);
9846 /* Check declaration elements */
9847 for (j = 0; tc[i].new_declaration[j].Stream != 0xFF; j++)
9848 {
9849 ok(memcmp(&tc[i].new_declaration[j], &new_declaration[j], sizeof(*new_declaration)) == 0,
9850 "Test case %d failed. Declaration element %d did not match.\n", i, j);
9851 }
9852
9853 /* Check declaration length */
9854 exp_new_decl_length = D3DXGetDeclLength(tc[i].new_declaration);
9855 new_decl_length = D3DXGetDeclLength(new_declaration);
9856 ok(new_decl_length == exp_new_decl_length,
9857 "Test case %d failed. Got new declaration length %d, expected %d\n",
9858 i, new_decl_length, exp_new_decl_length);
9859
9860 /* Check declaration size */
9861 exp_new_decl_size = D3DXGetDeclVertexSize(tc[i].new_declaration, 0);
9862 new_decl_size = D3DXGetDeclVertexSize(new_declaration, 0);
9863 ok(new_decl_size == exp_new_decl_size,
9864 "Test case %d failed. Got new declaration size %d, expected %d\n",
9865 i, new_decl_size, exp_new_decl_size);
9866
9867 /* Check vertex data in cloned mesh */
9868 hr = mesh_clone->lpVtbl->LockVertexBuffer(mesh_clone, 0, (void**)&vertices);
9869 if (FAILED(hr))
9870 {
9871 skip("Couldn't lock cloned vertex buffer.\n");
9872 goto cleanup;
9873 }
9874 for (j = 0; j < tc[i].num_vertices; j++)
9875 {
9876 UINT index = tc[i].exp_vertex_size * j;
9877 check_vertex_components(__LINE__, i, j, &vertices[index], &tc[i].exp_vertices[index], tc[i].new_declaration);
9878 }
9879 hr = mesh_clone->lpVtbl->UnlockVertexBuffer(mesh_clone);
9880 if (FAILED(hr))
9881 {
9882 skip("Couldn't unlock vertex buffer.\n");
9883 goto cleanup;
9884 }
9885 vertices = NULL;
9886 mesh->lpVtbl->Release(mesh);
9887 mesh = NULL;
9888 mesh_clone->lpVtbl->Release(mesh_clone);
9889 mesh_clone = NULL;
9890 }
9891
9892 /* The following test shows that it is not possible to share a vertex buffer
9893 * with D3DXMESH_VB_SHARE and change the vertex declaration at the same
9894 * time. It reuses the test data from test 2.
9895 */
9896 hr = init_test_mesh(tc[2].num_faces, tc[2].num_vertices,
9897 tc[2].create_options,
9898 tc[2].declaration,
9899 test_context->device, &mesh,
9900 tc[2].vertices, tc[2].vertex_size,
9901 tc[2].indices, tc[2].attributes);
9902 if (FAILED(hr))
9903 {
9904 skip("Couldn't initialize test mesh for D3DXMESH_VB_SHARE case."
9905 " Got %x expected D3D_OK\n", hr);
9906 goto cleanup;
9907 }
9908
9909 hr = mesh->lpVtbl->CloneMesh(mesh, tc[2].create_options | D3DXMESH_VB_SHARE,
9910 tc[2].new_declaration, test_context->device,
9911 &mesh_clone);
9912 ok(hr == D3DERR_INVALIDCALL, "CloneMesh D3DXMESH_VB_SHARE with new"
9913 " declaration. Got %x, expected D3DERR_INVALIDCALL\n",
9914 hr);
9915 mesh->lpVtbl->Release(mesh);
9916 mesh = NULL;
9917 mesh_clone = NULL;
9918
9919 cleanup:
9920 if (vertices) mesh->lpVtbl->UnlockVertexBuffer(mesh);
9921 if (mesh) mesh->lpVtbl->Release(mesh);
9922 if (mesh_clone) mesh_clone->lpVtbl->Release(mesh_clone);
9923 free_test_context(test_context);
9924 }
9925
9926 static void test_valid_mesh(void)
9927 {
9928 HRESULT hr;
9929 struct test_context *test_context = NULL;
9930 UINT i;
9931 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
9932 const D3DVERTEXELEMENT9 declaration[] =
9933 {
9934 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
9935 D3DDECL_END()
9936 };
9937 const unsigned int VERTS_PER_FACE = 3;
9938 /* mesh0 (one face)
9939 *
9940 * 0--1
9941 * | /
9942 * |/
9943 * 2
9944 */
9945 const D3DXVECTOR3 vertices0[] =
9946 {
9947 { 0.0f, 3.0f, 0.f},
9948 { 2.0f, 3.0f, 0.f},
9949 { 0.0f, 0.0f, 0.f},
9950 };
9951 const DWORD indices0[] = {0, 1, 2};
9952 const unsigned int num_vertices0 = ARRAY_SIZE(vertices0);
9953 const unsigned int num_faces0 = ARRAY_SIZE(indices0) / VERTS_PER_FACE;
9954 const DWORD adjacency0[] = {-1, -1, -1};
9955 const HRESULT exp_hr0 = D3D_OK;
9956 /* mesh1 (Simple bow-tie)
9957 *
9958 * 0--1 1--3
9959 * | / \ |
9960 * |/ \|
9961 * 2 4
9962 */
9963 const D3DXVECTOR3 vertices1[] =
9964 {
9965 { 0.0f, 3.0f, 0.f},
9966 { 2.0f, 3.0f, 0.f},
9967 { 0.0f, 0.0f, 0.f},
9968
9969 { 4.0f, 3.0f, 0.f},
9970 { 4.0f, 0.0f, 0.f},
9971 };
9972 const DWORD indices1[] = {0, 1, 2, 1, 3, 4};
9973 const unsigned int num_vertices1 = ARRAY_SIZE(vertices1);
9974 const unsigned int num_faces1 = ARRAY_SIZE(indices1) / VERTS_PER_FACE;
9975 const DWORD adjacency1[] = {-1, -1, -1, -1, -1, -1};
9976 const HRESULT exp_hr1 = D3DXERR_INVALIDMESH;
9977 /* Common mesh data */
9978 ID3DXMesh *mesh = NULL;
9979 UINT vertex_size = sizeof(D3DXVECTOR3);
9980 ID3DXBuffer *errors_and_warnings = NULL;
9981 struct
9982 {
9983 const D3DXVECTOR3 *vertices;
9984 const DWORD *indices;
9985 const UINT num_vertices;
9986 const UINT num_faces;
9987 const DWORD *adjacency;
9988 const HRESULT exp_hr;
9989 }
9990 tc[] =
9991 {
9992 {
9993 vertices0,
9994 indices0,
9995 num_vertices0,
9996 num_faces0,
9997 adjacency0,
9998 exp_hr0,
9999 },
10000 {
10001 vertices1,
10002 indices1,
10003 num_vertices1,
10004 num_faces1,
10005 adjacency1,
10006 exp_hr1,
10007 },
10008 };
10009
10010 test_context = new_test_context();
10011 if (!test_context)
10012 {
10013 skip("Couldn't create test context\n");
10014 goto cleanup;
10015 }
10016
10017 for (i = 0; i < ARRAY_SIZE(tc); i++)
10018 {
10019 hr = init_test_mesh(tc[i].num_faces, tc[i].num_vertices,
10020 options, declaration,
10021 test_context->device, &mesh,
10022 tc[i].vertices, vertex_size,
10023 tc[i].indices, NULL);
10024 if (FAILED(hr))
10025 {
10026 skip("Couldn't initialize test mesh %d. Got %x expected D3D_OK\n", i, hr);
10027 goto cleanup;
10028 }
10029
10030 hr = D3DXValidMesh(mesh, tc[i].adjacency, &errors_and_warnings);
10031 todo_wine ok(hr == tc[i].exp_hr, "D3DXValidMesh test case %d failed. "
10032 "Got %x\n, expected %x\n", i, hr, tc[i].exp_hr);
10033
10034 /* Note errors_and_warnings is deliberately not checked because that
10035 * would require copying wast amounts of the text output. */
10036 if (errors_and_warnings)
10037 {
10038 ID3DXBuffer_Release(errors_and_warnings);
10039 errors_and_warnings = NULL;
10040 }
10041 mesh->lpVtbl->Release(mesh);
10042 mesh = NULL;
10043 }
10044
10045 cleanup:
10046 if (mesh) mesh->lpVtbl->Release(mesh);
10047 free_test_context(test_context);
10048 }
10049
10050 static void test_optimize_faces(void)
10051 {
10052 HRESULT hr;
10053 UINT i;
10054 DWORD smallest_face_remap;
10055 /* mesh0
10056 *
10057 * 0--1
10058 * | /
10059 * |/
10060 * 2
10061 */
10062 const DWORD indices0[] = {0, 1, 2};
10063 const UINT num_faces0 = 1;
10064 const UINT num_vertices0 = 3;
10065 const DWORD exp_face_remap0[] = {0};
10066 /* mesh1
10067 *
10068 * 0--1 3
10069 * | / /|
10070 * |/ / |
10071 * 2 5--4
10072 */
10073 const DWORD indices1[] = {0, 1, 2, 3, 4, 5};
10074 const UINT num_faces1 = 2;
10075 const UINT num_vertices1 = 6;
10076 const DWORD exp_face_remap1[] = {1, 0};
10077 /* mesh2
10078 *
10079 * 0--1
10080 * | /|
10081 * |/ |
10082 * 2--3
10083 */
10084 const DWORD indices2[] = {0, 1, 2, 1, 3, 2};
10085 const UINT num_faces2 = 2;
10086 const UINT num_vertices2 = 4;
10087 const DWORD exp_face_remap2[] = {1, 0};
10088 /* mesh3
10089 *
10090 * 0--1
10091 * | /|
10092 * |/ |
10093 * 2--3
10094 * | /|
10095 * |/ |
10096 * 4--5
10097 */
10098 const DWORD indices3[] = {0, 1, 2, 1, 3, 2, 2, 3, 4, 3, 4, 5};
10099 const UINT num_faces3 = 4;
10100 const UINT num_vertices3 = 6;
10101 const DWORD exp_face_remap3[] = {3, 2, 1, 0};
10102 /* mesh4
10103 *
10104 * 0--1
10105 * | /|
10106 * |/ |
10107 * 2--3
10108 * | /|
10109 * |/ |
10110 * 4--5
10111 */
10112 const WORD indices4[] = {0, 1, 2, 1, 3, 2, 2, 3, 4, 3, 4, 5};
10113 const UINT num_faces4 = 4;
10114 const UINT num_vertices4 = 6;
10115 const DWORD exp_face_remap4[] = {3, 2, 1, 0};
10116 /* Test cases are stored in the tc array */
10117 struct
10118 {
10119 const VOID *indices;
10120 const UINT num_faces;
10121 const UINT num_vertices;
10122 const BOOL indices_are_32bit;
10123 const DWORD *exp_face_remap;
10124 }
10125 tc[] =
10126 {
10127 {
10128 indices0,
10129 num_faces0,
10130 num_vertices0,
10131 TRUE,
10132 exp_face_remap0
10133 },
10134 {
10135 indices1,
10136 num_faces1,
10137 num_vertices1,
10138 TRUE,
10139 exp_face_remap1
10140 },
10141 {
10142 indices2,
10143 num_faces2,
10144 num_vertices2,
10145 TRUE,
10146 exp_face_remap2
10147 },
10148 {
10149 indices3,
10150 num_faces3,
10151 num_vertices3,
10152 TRUE,
10153 exp_face_remap3
10154 },
10155 {
10156 indices4,
10157 num_faces4,
10158 num_vertices4,
10159 FALSE,
10160 exp_face_remap4
10161 },
10162 };
10163
10164 /* Go through all test cases */
10165 for (i = 0; i < ARRAY_SIZE(tc); i++)
10166 {
10167 DWORD j;
10168 DWORD *face_remap;
10169 face_remap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
10170 tc[i].num_faces*sizeof(face_remap));
10171
10172 hr = D3DXOptimizeFaces(tc[i].indices, tc[i].num_faces,
10173 tc[i].num_vertices, tc[i].indices_are_32bit,
10174 face_remap);
10175 ok(hr == D3D_OK, "D3DXOptimizeFaces test case %d failed. "
10176 "Got %x\n, expected D3D_OK\n", i, hr);
10177
10178 /* Compare face remap with expected face remap */
10179 for (j = 0; j < tc[i].num_faces; j++)
10180 {
10181 ok(tc[i].exp_face_remap[j] == face_remap[j],
10182 "Test case %d: Got face %d at %d, expected %d\n", i,
10183 face_remap[j], j, tc[i].exp_face_remap[j]);
10184 }
10185
10186 HeapFree(GetProcessHeap(), 0, face_remap);
10187 }
10188
10189 /* face_remap must not be NULL */
10190 hr = D3DXOptimizeFaces(tc[0].indices, tc[0].num_faces,
10191 tc[0].num_vertices, tc[0].indices_are_32bit,
10192 NULL);
10193 ok(hr == D3DERR_INVALIDCALL, "D3DXOptimizeFaces passed NULL face_remap "
10194 "pointer. Got %x\n, expected D3DERR_INVALIDCALL\n", hr);
10195
10196 /* Number of faces must be smaller than 2^15 */
10197 hr = D3DXOptimizeFaces(tc[0].indices, 2 << 15,
10198 tc[0].num_vertices, FALSE,
10199 &smallest_face_remap);
10200 ok(hr == D3DERR_INVALIDCALL, "D3DXOptimizeFaces should not accept 2^15 "
10201 "faces when using 16-bit indices. Got %x\n, expected D3DERR_INVALIDCALL\n", hr);
10202 }
10203
10204 START_TEST(mesh)
10205 {
10206 D3DXBoundProbeTest();
10207 D3DXComputeBoundingBoxTest();
10208 D3DXComputeBoundingSphereTest();
10209 D3DXGetFVFVertexSizeTest();
10210 D3DXIntersectTriTest();
10211 D3DXCreateMeshTest();
10212 D3DXCreateMeshFVFTest();
10213 D3DXLoadMeshTest();
10214 D3DXCreateBoxTest();
10215 D3DXCreateSphereTest();
10216 D3DXCreateCylinderTest();
10217 D3DXCreateTextTest();
10218 test_get_decl_length();
10219 test_get_decl_vertex_size();
10220 test_fvf_decl_conversion();
10221 D3DXGenerateAdjacencyTest();
10222 test_update_semantics();
10223 test_create_skin_info();
10224 test_convert_adjacency_to_point_reps();
10225 test_convert_point_reps_to_adjacency();
10226 test_weld_vertices();
10227 test_clone_mesh();
10228 test_valid_mesh();
10229 test_optimize_faces();
10230 }
10231
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.