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 #include "initguid.h"
29 #include "rmxftmpl.h"
30 #include "rmxfguid.h"
31
32 #ifndef NAN
33 /* From wine/port.h */
__port_nan(void)34 static inline float __port_nan(void)
35 {
36 static const unsigned __nan_bytes = 0x7fc00000;
37 return *(const float *)&__nan_bytes;
38 }
39 #define NAN __port_nan()
40 #endif
41
42 /* Set the WINETEST_DEBUG environment variable to be greater than 1 for verbose
43 * function call traces of ID3DXAllocateHierarchy callbacks. */
44 #define TRACECALLBACK if(winetest_debug > 1) trace
45
46 #define admitted_error 0.0001f
47
48 #define compare_vertex_sizes(type, exp) \
49 got=D3DXGetFVFVertexSize(type); \
50 ok(got==exp, "Expected: %d, Got: %d\n", exp, got);
51
52 #define compare_float(got, exp) \
53 do { \
54 float _got = (got); \
55 float _exp = (exp); \
56 ok(_got == _exp, "Expected: %g, Got: %g\n", _exp, _got); \
57 } while (0)
58
compare(FLOAT u,FLOAT v)59 static BOOL compare(FLOAT u, FLOAT v)
60 {
61 return (fabs(u-v) < admitted_error);
62 }
63
compare_vec3(D3DXVECTOR3 u,D3DXVECTOR3 v)64 static BOOL compare_vec3(D3DXVECTOR3 u, D3DXVECTOR3 v)
65 {
66 return ( compare(u.x, v.x) && compare(u.y, v.y) && compare(u.z, v.z) );
67 }
68
compare_vec4(D3DXVECTOR4 u,D3DXVECTOR4 v)69 static BOOL compare_vec4(D3DXVECTOR4 u, D3DXVECTOR4 v)
70 {
71 return compare(u.x, v.x) && compare(u.y, v.y) && compare(u.z, v.z) && compare(u.w, v.w);
72 }
73
74 #define check_floats(got, exp, dim) check_floats_(__LINE__, "", got, exp, dim)
check_floats_(int line,const char * prefix,const float * got,const float * exp,int dim)75 static void check_floats_(int line, const char *prefix, const float *got, const float *exp, int dim)
76 {
77 int i;
78 char exp_buffer[256] = "";
79 char got_buffer[256] = "";
80 char *exp_buffer_ptr = exp_buffer;
81 char *got_buffer_ptr = got_buffer;
82 BOOL equal = TRUE;
83
84 for (i = 0; i < dim; i++) {
85 if (i) {
86 exp_buffer_ptr += sprintf(exp_buffer_ptr, ", ");
87 got_buffer_ptr += sprintf(got_buffer_ptr, ", ");
88 }
89 equal = equal && compare(*exp, *got);
90 exp_buffer_ptr += sprintf(exp_buffer_ptr, "%g", *exp);
91 got_buffer_ptr += sprintf(got_buffer_ptr, "%g", *got);
92 exp++; got++;
93 }
94 ok_(__FILE__,line)(equal, "%sExpected (%s), got (%s)", prefix, exp_buffer, got_buffer);
95 }
96
97 struct vertex
98 {
99 D3DXVECTOR3 position;
100 D3DXVECTOR3 normal;
101 };
102
103 typedef WORD face[3];
104
compare_face(face a,face b)105 static BOOL compare_face(face a, face b)
106 {
107 return (a[0]==b[0] && a[1] == b[1] && a[2] == b[2]);
108 }
109
110 struct test_context
111 {
112 HWND hwnd;
113 IDirect3D9 *d3d;
114 IDirect3DDevice9 *device;
115 };
116
117 /* Initializes a test context struct. Use it to initialize DirectX.
118 *
119 * Returns NULL if an error occurred.
120 */
new_test_context(void)121 static struct test_context *new_test_context(void)
122 {
123 HRESULT hr;
124 HWND hwnd = NULL;
125 IDirect3D9 *d3d = NULL;
126 IDirect3DDevice9 *device = NULL;
127 D3DPRESENT_PARAMETERS d3dpp = {0};
128 struct test_context *test_context;
129
130 if (!(hwnd = CreateWindowA("static", "d3dx9_test", WS_OVERLAPPEDWINDOW, 0, 0,
131 640, 480, NULL, NULL, NULL, NULL)))
132 {
133 skip("Couldn't create application window\n");
134 goto error;
135 }
136
137 d3d = Direct3DCreate9(D3D_SDK_VERSION);
138 if (!d3d)
139 {
140 skip("Couldn't create IDirect3D9 object\n");
141 goto error;
142 }
143
144 memset(&d3dpp, 0, sizeof(d3dpp));
145 d3dpp.Windowed = TRUE;
146 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
147 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
148 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device);
149 if (FAILED(hr))
150 {
151 skip("Couldn't create IDirect3DDevice9 object %#x\n", hr);
152 goto error;
153 }
154
155 test_context = HeapAlloc(GetProcessHeap(), 0, sizeof(*test_context));
156 if (!test_context)
157 {
158 skip("Couldn't allocate memory for test_context\n");
159 goto error;
160 }
161 test_context->hwnd = hwnd;
162 test_context->d3d = d3d;
163 test_context->device = device;
164
165 return test_context;
166
167 error:
168 if (device)
169 IDirect3DDevice9_Release(device);
170
171 if (d3d)
172 IDirect3D9_Release(d3d);
173
174 if (hwnd)
175 DestroyWindow(hwnd);
176
177 return NULL;
178 }
179
free_test_context(struct test_context * test_context)180 static void free_test_context(struct test_context *test_context)
181 {
182 if (!test_context)
183 return;
184
185 if (test_context->device)
186 IDirect3DDevice9_Release(test_context->device);
187
188 if (test_context->d3d)
189 IDirect3D9_Release(test_context->d3d);
190
191 if (test_context->hwnd)
192 DestroyWindow(test_context->hwnd);
193
194 HeapFree(GetProcessHeap(), 0, test_context);
195 }
196
197 struct mesh
198 {
199 DWORD number_of_vertices;
200 struct vertex *vertices;
201
202 DWORD number_of_faces;
203 face *faces;
204
205 DWORD fvf;
206 UINT vertex_size;
207 };
208
free_mesh(struct mesh * mesh)209 static void free_mesh(struct mesh *mesh)
210 {
211 HeapFree(GetProcessHeap(), 0, mesh->faces);
212 HeapFree(GetProcessHeap(), 0, mesh->vertices);
213 }
214
new_mesh(struct mesh * mesh,DWORD number_of_vertices,DWORD number_of_faces)215 static BOOL new_mesh(struct mesh *mesh, DWORD number_of_vertices, DWORD number_of_faces)
216 {
217 mesh->vertices = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, number_of_vertices * sizeof(*mesh->vertices));
218 if (!mesh->vertices)
219 {
220 return FALSE;
221 }
222 mesh->number_of_vertices = number_of_vertices;
223
224 mesh->faces = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, number_of_faces * sizeof(*mesh->faces));
225 if (!mesh->faces)
226 {
227 HeapFree(GetProcessHeap(), 0, mesh->vertices);
228 return FALSE;
229 }
230 mesh->number_of_faces = number_of_faces;
231
232 return TRUE;
233 }
234
compare_mesh(const char * name,ID3DXMesh * d3dxmesh,struct mesh * mesh)235 static void compare_mesh(const char *name, ID3DXMesh *d3dxmesh, struct mesh *mesh)
236 {
237 HRESULT hr;
238 DWORD number_of_vertices, number_of_faces;
239 IDirect3DVertexBuffer9 *vertex_buffer;
240 IDirect3DIndexBuffer9 *index_buffer;
241 D3DVERTEXBUFFER_DESC vertex_buffer_description;
242 D3DINDEXBUFFER_DESC index_buffer_description;
243 struct vertex *vertices;
244 face *faces;
245 int expected, i;
246
247 number_of_vertices = d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh);
248 ok(number_of_vertices == mesh->number_of_vertices, "Test %s, result %u, expected %d\n",
249 name, number_of_vertices, mesh->number_of_vertices);
250
251 number_of_faces = d3dxmesh->lpVtbl->GetNumFaces(d3dxmesh);
252 ok(number_of_faces == mesh->number_of_faces, "Test %s, result %u, expected %d\n",
253 name, number_of_faces, mesh->number_of_faces);
254
255 /* vertex buffer */
256 hr = d3dxmesh->lpVtbl->GetVertexBuffer(d3dxmesh, &vertex_buffer);
257 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
258
259 if (hr != D3D_OK)
260 {
261 skip("Couldn't get vertex buffer\n");
262 }
263 else
264 {
265 hr = IDirect3DVertexBuffer9_GetDesc(vertex_buffer, &vertex_buffer_description);
266 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
267
268 if (hr != D3D_OK)
269 {
270 skip("Couldn't get vertex buffer description\n");
271 }
272 else
273 {
274 ok(vertex_buffer_description.Format == D3DFMT_VERTEXDATA, "Test %s, result %x, expected %x (D3DFMT_VERTEXDATA)\n",
275 name, vertex_buffer_description.Format, D3DFMT_VERTEXDATA);
276 ok(vertex_buffer_description.Type == D3DRTYPE_VERTEXBUFFER, "Test %s, result %x, expected %x (D3DRTYPE_VERTEXBUFFER)\n",
277 name, vertex_buffer_description.Type, D3DRTYPE_VERTEXBUFFER);
278 ok(vertex_buffer_description.Usage == 0, "Test %s, result %x, expected %x\n", name, vertex_buffer_description.Usage, 0);
279 ok(vertex_buffer_description.Pool == D3DPOOL_MANAGED, "Test %s, result %x, expected %x (D3DPOOL_MANAGED)\n",
280 name, vertex_buffer_description.Pool, D3DPOOL_MANAGED);
281 ok(vertex_buffer_description.FVF == mesh->fvf, "Test %s, result %x, expected %x\n",
282 name, vertex_buffer_description.FVF, mesh->fvf);
283 if (mesh->fvf == 0)
284 {
285 expected = number_of_vertices * mesh->vertex_size;
286 }
287 else
288 {
289 expected = number_of_vertices * D3DXGetFVFVertexSize(mesh->fvf);
290 }
291 ok(vertex_buffer_description.Size == expected, "Test %s, result %x, expected %x\n",
292 name, vertex_buffer_description.Size, expected);
293 }
294
295 /* specify offset and size to avoid potential overruns */
296 hr = IDirect3DVertexBuffer9_Lock(vertex_buffer, 0, number_of_vertices * sizeof(D3DXVECTOR3) * 2,
297 (void **)&vertices, D3DLOCK_DISCARD);
298 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
299
300 if (hr != D3D_OK)
301 {
302 skip("Couldn't lock vertex buffer\n");
303 }
304 else
305 {
306 for (i = 0; i < number_of_vertices; i++)
307 {
308 ok(compare_vec3(vertices[i].position, mesh->vertices[i].position),
309 "Test %s, vertex position %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i,
310 vertices[i].position.x, vertices[i].position.y, vertices[i].position.z,
311 mesh->vertices[i].position.x, mesh->vertices[i].position.y, mesh->vertices[i].position.z);
312 ok(compare_vec3(vertices[i].normal, mesh->vertices[i].normal),
313 "Test %s, vertex normal %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i,
314 vertices[i].normal.x, vertices[i].normal.y, vertices[i].normal.z,
315 mesh->vertices[i].normal.x, mesh->vertices[i].normal.y, mesh->vertices[i].normal.z);
316 }
317
318 IDirect3DVertexBuffer9_Unlock(vertex_buffer);
319 }
320
321 IDirect3DVertexBuffer9_Release(vertex_buffer);
322 }
323
324 /* index buffer */
325 hr = d3dxmesh->lpVtbl->GetIndexBuffer(d3dxmesh, &index_buffer);
326 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
327
328 if (!index_buffer)
329 {
330 skip("Couldn't get index buffer\n");
331 }
332 else
333 {
334 hr = IDirect3DIndexBuffer9_GetDesc(index_buffer, &index_buffer_description);
335 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
336
337 if (hr != D3D_OK)
338 {
339 skip("Couldn't get index buffer description\n");
340 }
341 else
342 {
343 ok(index_buffer_description.Format == D3DFMT_INDEX16, "Test %s, result %x, expected %x (D3DFMT_INDEX16)\n",
344 name, index_buffer_description.Format, D3DFMT_INDEX16);
345 ok(index_buffer_description.Type == D3DRTYPE_INDEXBUFFER, "Test %s, result %x, expected %x (D3DRTYPE_INDEXBUFFER)\n",
346 name, index_buffer_description.Type, D3DRTYPE_INDEXBUFFER);
347 ok(index_buffer_description.Usage == 0, "Test %s, result %#x, expected %#x.\n",
348 name, index_buffer_description.Usage, 0);
349 ok(index_buffer_description.Pool == D3DPOOL_MANAGED, "Test %s, result %x, expected %x (D3DPOOL_MANAGED)\n",
350 name, index_buffer_description.Pool, D3DPOOL_MANAGED);
351 expected = number_of_faces * sizeof(WORD) * 3;
352 ok(index_buffer_description.Size == expected, "Test %s, result %x, expected %x\n",
353 name, index_buffer_description.Size, expected);
354 }
355
356 /* specify offset and size to avoid potential overruns */
357 hr = IDirect3DIndexBuffer9_Lock(index_buffer, 0, number_of_faces * sizeof(WORD) * 3,
358 (void **)&faces, D3DLOCK_DISCARD);
359 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr);
360
361 if (hr != D3D_OK)
362 {
363 skip("Couldn't lock index buffer\n");
364 }
365 else
366 {
367 for (i = 0; i < number_of_faces; i++)
368 {
369 ok(compare_face(faces[i], mesh->faces[i]),
370 "Test %s, face %d, result (%u, %u, %u), expected (%u, %u, %u)\n", name, i,
371 faces[i][0], faces[i][1], faces[i][2],
372 mesh->faces[i][0], mesh->faces[i][1], mesh->faces[i][2]);
373 }
374
375 IDirect3DIndexBuffer9_Unlock(index_buffer);
376 }
377
378 IDirect3DIndexBuffer9_Release(index_buffer);
379 }
380 }
381
D3DXBoundProbeTest(void)382 static void D3DXBoundProbeTest(void)
383 {
384 BOOL result;
385 D3DXVECTOR3 bottom_point, center, top_point, raydirection, rayposition;
386 FLOAT radius;
387
388 /*____________Test the Box case___________________________*/
389 bottom_point.x = -3.0f; bottom_point.y = -2.0f; bottom_point.z = -1.0f;
390 top_point.x = 7.0f; top_point.y = 8.0f; top_point.z = 9.0f;
391
392 raydirection.x = -4.0f; raydirection.y = -5.0f; raydirection.z = -6.0f;
393 rayposition.x = 5.0f; rayposition.y = 5.0f; rayposition.z = 11.0f;
394 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection);
395 ok(result == TRUE, "expected TRUE, received FALSE\n");
396
397 raydirection.x = 4.0f; raydirection.y = 5.0f; raydirection.z = 6.0f;
398 rayposition.x = 5.0f; rayposition.y = 5.0f; rayposition.z = 11.0f;
399 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection);
400 ok(result == FALSE, "expected FALSE, received TRUE\n");
401
402 rayposition.x = -4.0f; rayposition.y = 1.0f; rayposition.z = -2.0f;
403 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection);
404 ok(result == TRUE, "expected TRUE, received FALSE\n");
405
406 bottom_point.x = 1.0f; bottom_point.y = 0.0f; bottom_point.z = 0.0f;
407 top_point.x = 1.0f; top_point.y = 0.0f; top_point.z = 0.0f;
408 rayposition.x = 0.0f; rayposition.y = 1.0f; rayposition.z = 0.0f;
409 raydirection.x = 0.0f; raydirection.y = 3.0f; raydirection.z = 0.0f;
410 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection);
411 ok(result == FALSE, "expected FALSE, received TRUE\n");
412
413 bottom_point.x = 1.0f; bottom_point.y = 2.0f; bottom_point.z = 3.0f;
414 top_point.x = 10.0f; top_point.y = 15.0f; top_point.z = 20.0f;
415
416 raydirection.x = 7.0f; raydirection.y = 8.0f; raydirection.z = 9.0f;
417 rayposition.x = 3.0f; rayposition.y = 7.0f; rayposition.z = -6.0f;
418 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection);
419 ok(result == TRUE, "expected TRUE, received FALSE\n");
420
421 bottom_point.x = 0.0f; bottom_point.y = 0.0f; bottom_point.z = 0.0f;
422 top_point.x = 1.0f; top_point.y = 1.0f; top_point.z = 1.0f;
423
424 raydirection.x = 0.0f; raydirection.y = 1.0f; raydirection.z = .0f;
425 rayposition.x = -3.0f; rayposition.y = 0.0f; rayposition.z = 0.0f;
426 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection);
427 ok(result == FALSE, "expected FALSE, received TRUE\n");
428
429 raydirection.x = 1.0f; raydirection.y = 0.0f; raydirection.z = .0f;
430 rayposition.x = -3.0f; rayposition.y = 0.0f; rayposition.z = 0.0f;
431 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection);
432 ok(result == TRUE, "expected TRUE, received FALSE\n");
433
434 /*____________Test the Sphere case________________________*/
435 radius = sqrt(77.0f);
436 center.x = 1.0f; center.y = 2.0f; center.z = 3.0f;
437 raydirection.x = 2.0f; raydirection.y = -4.0f; raydirection.z = 2.0f;
438 rayposition.x = 5.0f; rayposition.y = 5.0f; rayposition.z = 9.0f;
439 result = D3DXSphereBoundProbe(¢er, radius, &rayposition, &raydirection);
440 ok(result == TRUE, "Got unexpected result %#x.\n", result);
441
442 rayposition.x = 45.0f; rayposition.y = -75.0f; rayposition.z = 49.0f;
443 result = D3DXSphereBoundProbe(¢er, radius, &rayposition, &raydirection);
444 ok(result == FALSE, "Got unexpected result %#x.\n", result);
445
446 raydirection.x = -2.0f; raydirection.y = 4.0f; raydirection.z = -2.0f;
447 result = D3DXSphereBoundProbe(¢er, radius, &rayposition, &raydirection);
448 ok(result == TRUE, "Got unexpected result %#x.\n", result);
449
450 rayposition.x = 5.0f; rayposition.y = 11.0f; rayposition.z = 9.0f;
451 result = D3DXSphereBoundProbe(¢er, radius, &rayposition, &raydirection);
452 ok(result == FALSE, "Got unexpected result %#x.\n", result);
453
454 raydirection.x = 2.0f; raydirection.y = -4.0f; raydirection.z = 2.0f;
455 result = D3DXSphereBoundProbe(¢er, radius, &rayposition, &raydirection);
456 ok(result == FALSE, "Got unexpected result %#x.\n", result);
457
458 radius = 1.0f;
459 rayposition.x = 2.0f; rayposition.y = 2.0f; rayposition.z = 3.0f;
460 result = D3DXSphereBoundProbe(¢er, radius, &rayposition, &raydirection);
461 ok(result == FALSE, "Got unexpected result %#x.\n", result);
462
463 raydirection.x = 0.0f; raydirection.y = 0.0f; raydirection.z = 1.0f;
464 result = D3DXSphereBoundProbe(¢er, radius, &rayposition, &raydirection);
465 ok(result == TRUE, "Got unexpected result %#x.\n", result);
466
467 if (0)
468 {
469 /* All these crash on native. */
470 D3DXSphereBoundProbe(¢er, radius, &rayposition, NULL);
471 D3DXSphereBoundProbe(¢er, radius, NULL, &raydirection);
472 D3DXSphereBoundProbe(NULL, radius, &rayposition, &raydirection);
473 }
474 }
475
D3DXComputeBoundingBoxTest(void)476 static void D3DXComputeBoundingBoxTest(void)
477 {
478 D3DXVECTOR3 exp_max, exp_min, got_max, got_min, vertex[5];
479 HRESULT hr;
480
481 vertex[0].x = 1.0f; vertex[0].y = 1.0f; vertex[0].z = 1.0f;
482 vertex[1].x = 1.0f; vertex[1].y = 1.0f; vertex[1].z = 1.0f;
483 vertex[2].x = 1.0f; vertex[2].y = 1.0f; vertex[2].z = 1.0f;
484 vertex[3].x = 1.0f; vertex[3].y = 1.0f; vertex[3].z = 1.0f;
485 vertex[4].x = 9.0f; vertex[4].y = 9.0f; vertex[4].z = 9.0f;
486
487 exp_min.x = 1.0f; exp_min.y = 1.0f; exp_min.z = 1.0f;
488 exp_max.x = 9.0f; exp_max.y = 9.0f; exp_max.z = 9.0f;
489
490 hr = D3DXComputeBoundingBox(&vertex[3],2,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_min,&got_max);
491
492 ok( hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
493 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);
494 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);
495
496 /*________________________*/
497
498 vertex[0].x = 2.0f; vertex[0].y = 5.9f; vertex[0].z = -1.2f;
499 vertex[1].x = -1.87f; vertex[1].y = 7.9f; vertex[1].z = 7.4f;
500 vertex[2].x = 7.43f; vertex[2].y = -0.9f; vertex[2].z = 11.9f;
501 vertex[3].x = -6.92f; vertex[3].y = 6.3f; vertex[3].z = -3.8f;
502 vertex[4].x = 11.4f; vertex[4].y = -8.1f; vertex[4].z = 4.5f;
503
504 exp_min.x = -6.92f; exp_min.y = -8.1f; exp_min.z = -3.80f;
505 exp_max.x = 11.4f; exp_max.y = 7.90f; exp_max.z = 11.9f;
506
507 hr = D3DXComputeBoundingBox(&vertex[0],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_min,&got_max);
508
509 ok( hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
510 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);
511 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);
512
513 /*________________________*/
514
515 vertex[0].x = 2.0f; vertex[0].y = 5.9f; vertex[0].z = -1.2f;
516 vertex[1].x = -1.87f; vertex[1].y = 7.9f; vertex[1].z = 7.4f;
517 vertex[2].x = 7.43f; vertex[2].y = -0.9f; vertex[2].z = 11.9f;
518 vertex[3].x = -6.92f; vertex[3].y = 6.3f; vertex[3].z = -3.8f;
519 vertex[4].x = 11.4f; vertex[4].y = -8.1f; vertex[4].z = 4.5f;
520
521 exp_min.x = -6.92f; exp_min.y = -0.9f; exp_min.z = -3.8f;
522 exp_max.x = 7.43f; exp_max.y = 7.90f; exp_max.z = 11.9f;
523
524 hr = D3DXComputeBoundingBox(&vertex[0],4,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_min,&got_max);
525
526 ok( hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
527 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);
528 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);
529
530 /*________________________*/
531 hr = D3DXComputeBoundingBox(NULL,5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_min,&got_max);
532 ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
533
534 /*________________________*/
535 hr = D3DXComputeBoundingBox(&vertex[3],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),NULL,&got_max);
536 ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
537
538 /*________________________*/
539 hr = D3DXComputeBoundingBox(&vertex[3],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_min,NULL);
540 ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
541 }
542
D3DXComputeBoundingSphereTest(void)543 static void D3DXComputeBoundingSphereTest(void)
544 {
545 D3DXVECTOR3 exp_cen, got_cen, vertex[5];
546 FLOAT exp_rad, got_rad;
547 HRESULT hr;
548
549 vertex[0].x = 1.0f; vertex[0].y = 1.0f; vertex[0].z = 1.0f;
550 vertex[1].x = 1.0f; vertex[1].y = 1.0f; vertex[1].z = 1.0f;
551 vertex[2].x = 1.0f; vertex[2].y = 1.0f; vertex[2].z = 1.0f;
552 vertex[3].x = 1.0f; vertex[3].y = 1.0f; vertex[3].z = 1.0f;
553 vertex[4].x = 9.0f; vertex[4].y = 9.0f; vertex[4].z = 9.0f;
554
555 exp_rad = 6.928203f;
556 exp_cen.x = 5.0; exp_cen.y = 5.0; exp_cen.z = 5.0;
557
558 hr = D3DXComputeBoundingSphere(&vertex[3],2,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_cen,&got_rad);
559
560 ok( hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
561 ok( compare(exp_rad, got_rad), "Expected radius: %f, got radius: %f\n", exp_rad, got_rad);
562 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);
563
564 /*________________________*/
565
566 vertex[0].x = 2.0f; vertex[0].y = 5.9f; vertex[0].z = -1.2f;
567 vertex[1].x = -1.87f; vertex[1].y = 7.9f; vertex[1].z = 7.4f;
568 vertex[2].x = 7.43f; vertex[2].y = -0.9f; vertex[2].z = 11.9f;
569 vertex[3].x = -6.92f; vertex[3].y = 6.3f; vertex[3].z = -3.8f;
570 vertex[4].x = 11.4f; vertex[4].y = -8.1f; vertex[4].z = 4.5f;
571
572 exp_rad = 13.707883f;
573 exp_cen.x = 2.408f; exp_cen.y = 2.22f; exp_cen.z = 3.76f;
574
575 hr = D3DXComputeBoundingSphere(&vertex[0],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_cen,&got_rad);
576
577 ok( hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
578 ok( compare(exp_rad, got_rad), "Expected radius: %f, got radius: %f\n", exp_rad, got_rad);
579 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);
580
581 /*________________________*/
582 hr = D3DXComputeBoundingSphere(NULL,5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_cen,&got_rad);
583 ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
584
585 /*________________________*/
586 hr = D3DXComputeBoundingSphere(&vertex[3],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),NULL,&got_rad);
587 ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
588
589 /*________________________*/
590 hr = D3DXComputeBoundingSphere(&vertex[3],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_cen,NULL);
591 ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
592 }
593
print_elements(const D3DVERTEXELEMENT9 * elements)594 static void print_elements(const D3DVERTEXELEMENT9 *elements)
595 {
596 D3DVERTEXELEMENT9 last = D3DDECL_END();
597 const D3DVERTEXELEMENT9 *ptr = elements;
598 int count = 0;
599
600 while (memcmp(ptr, &last, sizeof(D3DVERTEXELEMENT9)))
601 {
602 trace(
603 "[Element %d] Stream = %d, Offset = %d, Type = %d, Method = %d, Usage = %d, UsageIndex = %d\n",
604 count, ptr->Stream, ptr->Offset, ptr->Type, ptr->Method, ptr->Usage, ptr->UsageIndex);
605 ptr++;
606 count++;
607 }
608 }
609
compare_elements(const D3DVERTEXELEMENT9 * elements,const D3DVERTEXELEMENT9 * expected_elements,unsigned int line,unsigned int test_id)610 static void compare_elements(const D3DVERTEXELEMENT9 *elements, const D3DVERTEXELEMENT9 *expected_elements,
611 unsigned int line, unsigned int test_id)
612 {
613 D3DVERTEXELEMENT9 last = D3DDECL_END();
614 unsigned int i;
615
616 for (i = 0; i < MAX_FVF_DECL_SIZE; i++)
617 {
618 int end1 = memcmp(&elements[i], &last, sizeof(last));
619 int end2 = memcmp(&expected_elements[i], &last, sizeof(last));
620 int status;
621
622 if (!end1 && !end2) break;
623
624 status = !end1 ^ !end2;
625 ok(!status, "Line %u, test %u: Mismatch in size, test declaration is %s than expected.\n",
626 line, test_id, end1 ? "shorter" : "longer");
627 if (status)
628 {
629 print_elements(elements);
630 break;
631 }
632
633 status = memcmp(&elements[i], &expected_elements[i], sizeof(D3DVERTEXELEMENT9));
634 ok(!status, "Line %u, test %u: Mismatch in element %u.\n", line, test_id, i);
635 if (status)
636 {
637 print_elements(elements);
638 break;
639 }
640 }
641 }
642
test_fvf_to_decl(DWORD test_fvf,const D3DVERTEXELEMENT9 expected_elements[],HRESULT expected_hr,unsigned int line,unsigned int test_id)643 static void test_fvf_to_decl(DWORD test_fvf, const D3DVERTEXELEMENT9 expected_elements[],
644 HRESULT expected_hr, unsigned int line, unsigned int test_id)
645 {
646 HRESULT hr;
647 D3DVERTEXELEMENT9 decl[MAX_FVF_DECL_SIZE];
648
649 hr = D3DXDeclaratorFromFVF(test_fvf, decl);
650 ok(hr == expected_hr,
651 "Line %u, test %u: D3DXDeclaratorFromFVF returned %#x, expected %#x.\n",
652 line, test_id, hr, expected_hr);
653 if (SUCCEEDED(hr)) compare_elements(decl, expected_elements, line, test_id);
654 }
655
test_decl_to_fvf(const D3DVERTEXELEMENT9 * decl,DWORD expected_fvf,HRESULT expected_hr,unsigned int line,unsigned int test_id)656 static void test_decl_to_fvf(const D3DVERTEXELEMENT9 *decl, DWORD expected_fvf,
657 HRESULT expected_hr, unsigned int line, unsigned int test_id)
658 {
659 HRESULT hr;
660 DWORD result_fvf = 0xdeadbeef;
661
662 hr = D3DXFVFFromDeclarator(decl, &result_fvf);
663 ok(hr == expected_hr,
664 "Line %u, test %u: D3DXFVFFromDeclarator returned %#x, expected %#x.\n",
665 line, test_id, hr, expected_hr);
666 if (SUCCEEDED(hr))
667 {
668 ok(expected_fvf == result_fvf, "Line %u, test %u: Got FVF %#x, expected %#x.\n",
669 line, test_id, result_fvf, expected_fvf);
670 }
671 }
672
test_fvf_decl_conversion(void)673 static void test_fvf_decl_conversion(void)
674 {
675 static const struct
676 {
677 D3DVERTEXELEMENT9 decl[MAXD3DDECLLENGTH + 1];
678 DWORD fvf;
679 }
680 test_data[] =
681 {
682 {{
683 D3DDECL_END(),
684 }, 0},
685 {{
686 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
687 D3DDECL_END(),
688 }, D3DFVF_XYZ},
689 {{
690 {0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITIONT, 0},
691 D3DDECL_END(),
692 }, D3DFVF_XYZRHW},
693 {{
694 {0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITIONT, 0},
695 D3DDECL_END(),
696 }, D3DFVF_XYZRHW},
697 {{
698 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
699 {0, 12, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
700 D3DDECL_END(),
701 }, D3DFVF_XYZB1},
702 {{
703 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
704 {0, 12, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
705 D3DDECL_END(),
706 }, D3DFVF_XYZB1 | D3DFVF_LASTBETA_UBYTE4},
707 {{
708 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
709 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
710 D3DDECL_END(),
711 }, D3DFVF_XYZB1 | D3DFVF_LASTBETA_D3DCOLOR},
712 {{
713 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
714 {0, 12, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
715 D3DDECL_END(),
716 }, D3DFVF_XYZB2},
717 {{
718 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
719 {0, 12, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
720 {0, 16, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
721 D3DDECL_END(),
722 }, D3DFVF_XYZB2 | D3DFVF_LASTBETA_UBYTE4},
723 {{
724 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
725 {0, 12, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
726 {0, 16, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
727 D3DDECL_END(),
728 }, D3DFVF_XYZB2 | D3DFVF_LASTBETA_D3DCOLOR},
729 {{
730 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
731 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
732 D3DDECL_END(),
733 }, D3DFVF_XYZB3},
734 {{
735 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
736 {0, 12, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
737 {0, 20, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
738 D3DDECL_END(),
739 }, D3DFVF_XYZB3 | D3DFVF_LASTBETA_UBYTE4},
740 {{
741 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
742 {0, 12, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
743 {0, 20, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
744 D3DDECL_END(),
745 }, D3DFVF_XYZB3 | D3DFVF_LASTBETA_D3DCOLOR},
746 {{
747 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
748 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
749 D3DDECL_END(),
750 }, D3DFVF_XYZB4},
751 {{
752 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
753 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
754 {0, 24, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
755 D3DDECL_END(),
756 }, D3DFVF_XYZB4 | D3DFVF_LASTBETA_UBYTE4},
757 {{
758 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
759 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
760 {0, 24, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
761 D3DDECL_END(),
762 }, D3DFVF_XYZB4 | D3DFVF_LASTBETA_D3DCOLOR},
763 {{
764 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
765 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
766 {0, 28, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
767 D3DDECL_END(),
768 }, D3DFVF_XYZB5 | D3DFVF_LASTBETA_UBYTE4},
769 {{
770 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
771 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
772 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
773 D3DDECL_END(),
774 }, D3DFVF_XYZB5 | D3DFVF_LASTBETA_D3DCOLOR},
775 {{
776 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
777 D3DDECL_END(),
778 }, D3DFVF_NORMAL},
779 {{
780 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
781 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
782 D3DDECL_END(),
783 }, D3DFVF_NORMAL | D3DFVF_DIFFUSE},
784 {{
785 {0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_PSIZE, 0},
786 D3DDECL_END(),
787 }, D3DFVF_PSIZE},
788 {{
789 {0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
790 D3DDECL_END(),
791 }, D3DFVF_DIFFUSE},
792 {{
793 {0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1},
794 D3DDECL_END(),
795 }, D3DFVF_SPECULAR},
796 /* Make sure textures of different sizes work. */
797 {{
798 {0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
799 D3DDECL_END(),
800 }, D3DFVF_TEXCOORDSIZE1(0) | D3DFVF_TEX1},
801 {{
802 {0, 0, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 0},
803 D3DDECL_END(),
804 }, D3DFVF_TEXCOORDSIZE2(0) | D3DFVF_TEX1},
805 {{
806 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 0},
807 D3DDECL_END(),
808 }, D3DFVF_TEXCOORDSIZE3(0) | D3DFVF_TEX1},
809 {{
810 {0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 0},
811 D3DDECL_END(),
812 }, D3DFVF_TEXCOORDSIZE4(0) | D3DFVF_TEX1},
813 /* Make sure the TEXCOORD index works correctly - try several textures. */
814 {{
815 {0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
816 {0, 4, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 1},
817 {0, 16, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 2},
818 {0, 24, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 3},
819 D3DDECL_END(),
820 }, D3DFVF_TEX4 | D3DFVF_TEXCOORDSIZE1(0) | D3DFVF_TEXCOORDSIZE3(1)
821 | D3DFVF_TEXCOORDSIZE2(2) | D3DFVF_TEXCOORDSIZE4(3)},
822 /* Now try some combination tests. */
823 {{
824 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
825 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
826 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
827 {0, 32, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1},
828 {0, 36, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 0},
829 {0, 44, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 1},
830 D3DDECL_END(),
831 }, D3DFVF_XYZB4 | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_TEX2
832 | D3DFVF_TEXCOORDSIZE2(0) | D3DFVF_TEXCOORDSIZE3(1)},
833 {{
834 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
835 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
836 {0, 24, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_PSIZE, 0},
837 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1},
838 {0, 32, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
839 {0, 36, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 1},
840 D3DDECL_END(),
841 }, D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_PSIZE | D3DFVF_SPECULAR | D3DFVF_TEX2
842 | D3DFVF_TEXCOORDSIZE1(0) | D3DFVF_TEXCOORDSIZE4(1)},
843 };
844 unsigned int i;
845
846 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
847 {
848 test_decl_to_fvf(test_data[i].decl, test_data[i].fvf, D3D_OK, __LINE__, i);
849 test_fvf_to_decl(test_data[i].fvf, test_data[i].decl, D3D_OK, __LINE__, i);
850 }
851
852 /* Usage indices for position and normal are apparently ignored. */
853 {
854 const D3DVERTEXELEMENT9 decl[] =
855 {
856 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 1},
857 D3DDECL_END(),
858 };
859 test_decl_to_fvf(decl, D3DFVF_XYZ, D3D_OK, __LINE__, 0);
860 }
861 {
862 const D3DVERTEXELEMENT9 decl[] =
863 {
864 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 1},
865 D3DDECL_END(),
866 };
867 test_decl_to_fvf(decl, D3DFVF_NORMAL, D3D_OK, __LINE__, 0);
868 }
869 /* D3DFVF_LASTBETA_UBYTE4 and D3DFVF_LASTBETA_D3DCOLOR are ignored if
870 * there are no blend matrices. */
871 {
872 const D3DVERTEXELEMENT9 decl[] =
873 {
874 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
875 D3DDECL_END(),
876 };
877 test_fvf_to_decl(D3DFVF_XYZ | D3DFVF_LASTBETA_UBYTE4, decl, D3D_OK, __LINE__, 0);
878 }
879 {
880 const D3DVERTEXELEMENT9 decl[] =
881 {
882 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
883 D3DDECL_END(),
884 };
885 test_fvf_to_decl(D3DFVF_XYZ | D3DFVF_LASTBETA_D3DCOLOR, decl, D3D_OK, __LINE__, 0);
886 }
887 /* D3DFVF_LASTBETA_UBYTE4 takes precedence over D3DFVF_LASTBETA_D3DCOLOR. */
888 {
889 const D3DVERTEXELEMENT9 decl[] =
890 {
891 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
892 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
893 {0, 28, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
894 D3DDECL_END(),
895 };
896 test_fvf_to_decl(D3DFVF_XYZB5 | D3DFVF_LASTBETA_D3DCOLOR | D3DFVF_LASTBETA_UBYTE4,
897 decl, D3D_OK, __LINE__, 0);
898 }
899 /* These are supposed to fail, both ways. */
900 {
901 const D3DVERTEXELEMENT9 decl[] =
902 {
903 {0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITION, 0},
904 D3DDECL_END(),
905 };
906 test_decl_to_fvf(decl, D3DFVF_XYZW, D3DERR_INVALIDCALL, __LINE__, 0);
907 test_fvf_to_decl(D3DFVF_XYZW, decl, D3DERR_INVALIDCALL, __LINE__, 0);
908 }
909 {
910 const D3DVERTEXELEMENT9 decl[] =
911 {
912 {0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITION, 0},
913 {0, 16, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
914 D3DDECL_END(),
915 };
916 test_decl_to_fvf(decl, D3DFVF_XYZW | D3DFVF_NORMAL, D3DERR_INVALIDCALL, __LINE__, 0);
917 test_fvf_to_decl(D3DFVF_XYZW | D3DFVF_NORMAL, decl, D3DERR_INVALIDCALL, __LINE__, 0);
918 }
919 {
920 const D3DVERTEXELEMENT9 decl[] =
921 {
922 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
923 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
924 {0, 28, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDINDICES, 0},
925 D3DDECL_END(),
926 };
927 test_decl_to_fvf(decl, D3DFVF_XYZB5, D3DERR_INVALIDCALL, __LINE__, 0);
928 test_fvf_to_decl(D3DFVF_XYZB5, decl, D3DERR_INVALIDCALL, __LINE__, 0);
929 }
930 /* Test a declaration that can't be converted to an FVF. */
931 {
932 const D3DVERTEXELEMENT9 decl[] =
933 {
934 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
935 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
936 {0, 24, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_PSIZE, 0},
937 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1},
938 {0, 32, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
939 /* 8 bytes padding */
940 {0, 44, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 1},
941 D3DDECL_END(),
942 };
943 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0);
944 }
945 /* Elements must be ordered by offset. */
946 {
947 const D3DVERTEXELEMENT9 decl[] =
948 {
949 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
950 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
951 D3DDECL_END(),
952 };
953 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0);
954 }
955 /* Basic tests for element order. */
956 {
957 const D3DVERTEXELEMENT9 decl[] =
958 {
959 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
960 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
961 {0, 16, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
962 D3DDECL_END(),
963 };
964 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0);
965 }
966 {
967 const D3DVERTEXELEMENT9 decl[] =
968 {
969 {0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
970 {0, 4, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
971 D3DDECL_END(),
972 };
973 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0);
974 }
975 {
976 const D3DVERTEXELEMENT9 decl[] =
977 {
978 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
979 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
980 D3DDECL_END(),
981 };
982 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0);
983 }
984 /* Textures must be ordered by texcoords. */
985 {
986 const D3DVERTEXELEMENT9 decl[] =
987 {
988 {0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
989 {0, 4, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 2},
990 {0, 16, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 1},
991 {0, 24, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 3},
992 D3DDECL_END(),
993 };
994 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0);
995 }
996 /* Duplicate elements are not allowed. */
997 {
998 const D3DVERTEXELEMENT9 decl[] =
999 {
1000 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
1001 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
1002 {0, 16, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
1003 D3DDECL_END(),
1004 };
1005 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0);
1006 }
1007 /* Invalid FVFs cannot be converted to a declarator. */
1008 test_fvf_to_decl(0xdeadbeef, NULL, D3DERR_INVALIDCALL, __LINE__, 0);
1009 }
1010
D3DXGetFVFVertexSizeTest(void)1011 static void D3DXGetFVFVertexSizeTest(void)
1012 {
1013 UINT got;
1014
1015 compare_vertex_sizes (D3DFVF_XYZ, 12);
1016
1017 compare_vertex_sizes (D3DFVF_XYZB3, 24);
1018
1019 compare_vertex_sizes (D3DFVF_XYZB5, 32);
1020
1021 compare_vertex_sizes (D3DFVF_XYZ | D3DFVF_NORMAL, 24);
1022
1023 compare_vertex_sizes (D3DFVF_XYZ | D3DFVF_DIFFUSE, 16);
1024
1025 compare_vertex_sizes (
1026 D3DFVF_XYZ |
1027 D3DFVF_TEX1 |
1028 D3DFVF_TEXCOORDSIZE1(0), 16);
1029 compare_vertex_sizes (
1030 D3DFVF_XYZ |
1031 D3DFVF_TEX2 |
1032 D3DFVF_TEXCOORDSIZE1(0) |
1033 D3DFVF_TEXCOORDSIZE1(1), 20);
1034
1035 compare_vertex_sizes (
1036 D3DFVF_XYZ |
1037 D3DFVF_TEX1 |
1038 D3DFVF_TEXCOORDSIZE2(0), 20);
1039
1040 compare_vertex_sizes (
1041 D3DFVF_XYZ |
1042 D3DFVF_TEX2 |
1043 D3DFVF_TEXCOORDSIZE2(0) |
1044 D3DFVF_TEXCOORDSIZE2(1), 28);
1045
1046 compare_vertex_sizes (
1047 D3DFVF_XYZ |
1048 D3DFVF_TEX6 |
1049 D3DFVF_TEXCOORDSIZE2(0) |
1050 D3DFVF_TEXCOORDSIZE2(1) |
1051 D3DFVF_TEXCOORDSIZE2(2) |
1052 D3DFVF_TEXCOORDSIZE2(3) |
1053 D3DFVF_TEXCOORDSIZE2(4) |
1054 D3DFVF_TEXCOORDSIZE2(5), 60);
1055
1056 compare_vertex_sizes (
1057 D3DFVF_XYZ |
1058 D3DFVF_TEX8 |
1059 D3DFVF_TEXCOORDSIZE2(0) |
1060 D3DFVF_TEXCOORDSIZE2(1) |
1061 D3DFVF_TEXCOORDSIZE2(2) |
1062 D3DFVF_TEXCOORDSIZE2(3) |
1063 D3DFVF_TEXCOORDSIZE2(4) |
1064 D3DFVF_TEXCOORDSIZE2(5) |
1065 D3DFVF_TEXCOORDSIZE2(6) |
1066 D3DFVF_TEXCOORDSIZE2(7), 76);
1067
1068 compare_vertex_sizes (
1069 D3DFVF_XYZ |
1070 D3DFVF_TEX1 |
1071 D3DFVF_TEXCOORDSIZE3(0), 24);
1072
1073 compare_vertex_sizes (
1074 D3DFVF_XYZ |
1075 D3DFVF_TEX4 |
1076 D3DFVF_TEXCOORDSIZE3(0) |
1077 D3DFVF_TEXCOORDSIZE3(1) |
1078 D3DFVF_TEXCOORDSIZE3(2) |
1079 D3DFVF_TEXCOORDSIZE3(3), 60);
1080
1081 compare_vertex_sizes (
1082 D3DFVF_XYZ |
1083 D3DFVF_TEX1 |
1084 D3DFVF_TEXCOORDSIZE4(0), 28);
1085
1086 compare_vertex_sizes (
1087 D3DFVF_XYZ |
1088 D3DFVF_TEX2 |
1089 D3DFVF_TEXCOORDSIZE4(0) |
1090 D3DFVF_TEXCOORDSIZE4(1), 44);
1091
1092 compare_vertex_sizes (
1093 D3DFVF_XYZ |
1094 D3DFVF_TEX3 |
1095 D3DFVF_TEXCOORDSIZE4(0) |
1096 D3DFVF_TEXCOORDSIZE4(1) |
1097 D3DFVF_TEXCOORDSIZE4(2), 60);
1098
1099 compare_vertex_sizes (
1100 D3DFVF_XYZB5 |
1101 D3DFVF_NORMAL |
1102 D3DFVF_DIFFUSE |
1103 D3DFVF_SPECULAR |
1104 D3DFVF_TEX8 |
1105 D3DFVF_TEXCOORDSIZE4(0) |
1106 D3DFVF_TEXCOORDSIZE4(1) |
1107 D3DFVF_TEXCOORDSIZE4(2) |
1108 D3DFVF_TEXCOORDSIZE4(3) |
1109 D3DFVF_TEXCOORDSIZE4(4) |
1110 D3DFVF_TEXCOORDSIZE4(5) |
1111 D3DFVF_TEXCOORDSIZE4(6) |
1112 D3DFVF_TEXCOORDSIZE4(7), 180);
1113 }
1114
D3DXIntersectTriTest(void)1115 static void D3DXIntersectTriTest(void)
1116 {
1117 BOOL exp_res, got_res;
1118 D3DXVECTOR3 position, ray, vertex[3];
1119 FLOAT exp_dist, got_dist, exp_u, got_u, exp_v, got_v;
1120
1121 vertex[0].x = 1.0f; vertex[0].y = 0.0f; vertex[0].z = 0.0f;
1122 vertex[1].x = 2.0f; vertex[1].y = 0.0f; vertex[1].z = 0.0f;
1123 vertex[2].x = 1.0f; vertex[2].y = 1.0f; vertex[2].z = 0.0f;
1124
1125 position.x = -14.5f; position.y = -23.75f; position.z = -32.0f;
1126
1127 ray.x = 2.0f; ray.y = 3.0f; ray.z = 4.0f;
1128
1129 exp_res = TRUE; exp_u = 0.5f; exp_v = 0.25f; exp_dist = 8.0f;
1130
1131 got_res = D3DXIntersectTri(&vertex[0], &vertex[1], &vertex[2], &position, &ray, &got_u, &got_v, &got_dist);
1132 ok(got_res == exp_res, "Expected result %d, got %d.\n", exp_res, got_res);
1133 ok(compare(exp_u, got_u), "Expected u %f, got %f.\n", exp_u, got_u);
1134 ok(compare(exp_v, got_v), "Expected v %f, got %f.\n", exp_v, got_v);
1135 ok(compare(exp_dist, got_dist), "Expected distance %f, got %f.\n", exp_dist, got_dist);
1136
1137 got_res = D3DXIntersectTri(&vertex[0], &vertex[1], &vertex[2], &position, &ray, NULL, NULL, NULL);
1138 ok(got_res == exp_res, "Expected result %d, got %d.\n", exp_res, got_res);
1139
1140 vertex[2].x = 1.0f; vertex[2].y = 0.0f; vertex[2].z = 0.0f;
1141 vertex[1].x = 2.0f; vertex[1].y = 0.0f; vertex[1].z = 0.0f;
1142 vertex[0].x = 1.0f; vertex[0].y = 1.0f; vertex[0].z = 0.0f;
1143
1144 got_u = got_v = got_dist = 0.0f;
1145 got_res = D3DXIntersectTri(&vertex[0], &vertex[1], &vertex[2], &position, &ray, &got_u, &got_v, &got_dist);
1146 ok(got_res == exp_res, "Expected result %d, got %d.\n", exp_res, got_res);
1147 ok(compare(exp_u, got_u), "Expected u %f, got %f.\n", exp_u, got_u);
1148 ok(compare(exp_v, got_v), "Expected v %f, got %f.\n", exp_v, got_v);
1149 ok(compare(exp_dist, got_dist), "Expected distance %f, got %f.\n", exp_dist, got_dist);
1150
1151 vertex[2].x = 1.0f; vertex[2].y = 0.0f; vertex[2].z = 0.0f;
1152 vertex[1].x = 2.0f; vertex[1].y = 0.0f; vertex[1].z = -0.5f;
1153 vertex[0].x = 1.0f; vertex[0].y = 1.0f; vertex[0].z = -1.0f;
1154 exp_u = 0.375f;
1155 exp_v = 0.5625f;
1156 exp_dist = 7.9375f;
1157 got_u = got_v = got_dist = 0.0f;
1158 got_res = D3DXIntersectTri(&vertex[0], &vertex[1], &vertex[2], &position, &ray, &got_u, &got_v, &got_dist);
1159 ok(got_res == exp_res, "Expected result %d, got %d.\n", exp_res, got_res);
1160 ok(compare(exp_u, got_u), "Expected u %f, got %f.\n", exp_u, got_u);
1161 ok(compare(exp_v, got_v), "Expected v %f, got %f.\n", exp_v, got_v);
1162 ok(compare(exp_dist, got_dist), "Expected distance %f, got %f.\n", exp_dist, got_dist);
1163
1164
1165 /*Only positive ray is taken in account*/
1166
1167 vertex[0].x = 1.0f; vertex[0].y = 0.0f; vertex[0].z = 0.0f;
1168 vertex[1].x = 2.0f; vertex[1].y = 0.0f; vertex[1].z = 0.0f;
1169 vertex[2].x = 1.0f; vertex[2].y = 1.0f; vertex[2].z = 0.0f;
1170
1171 position.x = 17.5f; position.y = 24.25f; position.z = 32.0f;
1172
1173 ray.x = 2.0f; ray.y = 3.0f; ray.z = 4.0f;
1174
1175 exp_res = FALSE;
1176
1177 got_res = D3DXIntersectTri(&vertex[0],&vertex[1],&vertex[2],&position,&ray,&got_u,&got_v,&got_dist);
1178 ok( got_res == exp_res, "Expected result = %d, got %d\n",exp_res,got_res);
1179
1180 got_res = D3DXIntersectTri(&vertex[0], &vertex[1], &vertex[2], &position, &ray, NULL, NULL, NULL);
1181 ok(got_res == exp_res, "Expected result = %d, got %d\n", exp_res, got_res);
1182
1183 /*Intersection between ray and triangle in a same plane is considered as empty*/
1184
1185 vertex[0].x = 4.0f; vertex[0].y = 0.0f; vertex[0].z = 0.0f;
1186 vertex[1].x = 6.0f; vertex[1].y = 0.0f; vertex[1].z = 0.0f;
1187 vertex[2].x = 4.0f; vertex[2].y = 2.0f; vertex[2].z = 0.0f;
1188
1189 position.x = 1.0f; position.y = 1.0f; position.z = 0.0f;
1190
1191 ray.x = 1.0f; ray.y = 0.0f; ray.z = 0.0f;
1192
1193 exp_res = FALSE;
1194
1195 got_res = D3DXIntersectTri(&vertex[0],&vertex[1],&vertex[2],&position,&ray,&got_u,&got_v,&got_dist);
1196 ok( got_res == exp_res, "Expected result = %d, got %d\n",exp_res,got_res);
1197
1198 got_res = D3DXIntersectTri(&vertex[0], &vertex[1], &vertex[2], &position, &ray, NULL, NULL, NULL);
1199 ok(got_res == exp_res, "Expected result = %d, got %d\n", exp_res, got_res);
1200 }
1201
D3DXCreateMeshTest(void)1202 static void D3DXCreateMeshTest(void)
1203 {
1204 HRESULT hr;
1205 IDirect3DDevice9 *device, *test_device;
1206 ID3DXMesh *d3dxmesh;
1207 int i, size;
1208 D3DVERTEXELEMENT9 test_decl[MAX_FVF_DECL_SIZE];
1209 DWORD options;
1210 struct mesh mesh;
1211 struct test_context *test_context;
1212
1213 static const D3DVERTEXELEMENT9 decl1[] =
1214 {
1215 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1216 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
1217 D3DDECL_END(),
1218 };
1219
1220 static const D3DVERTEXELEMENT9 decl2[] =
1221 {
1222 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1223 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
1224 {0, 24, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_PSIZE, 0},
1225 {0, 28, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 1},
1226 {0, 32, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
1227 /* 8 bytes padding */
1228 {0, 44, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
1229 D3DDECL_END(),
1230 };
1231
1232 static const D3DVERTEXELEMENT9 decl3[] =
1233 {
1234 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1235 {1, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
1236 D3DDECL_END(),
1237 };
1238
1239 hr = D3DXCreateMesh(0, 0, 0, NULL, NULL, NULL);
1240 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1241
1242 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl1, NULL, &d3dxmesh);
1243 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1244
1245 test_context = new_test_context();
1246 if (!test_context)
1247 {
1248 skip("Couldn't create test context\n");
1249 return;
1250 }
1251 device = test_context->device;
1252
1253 hr = D3DXCreateMesh(0, 3, D3DXMESH_MANAGED, decl1, device, &d3dxmesh);
1254 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1255
1256 hr = D3DXCreateMesh(1, 0, D3DXMESH_MANAGED, decl1, device, &d3dxmesh);
1257 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1258
1259 hr = D3DXCreateMesh(1, 3, 0, decl1, device, &d3dxmesh);
1260 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
1261
1262 if (hr == D3D_OK)
1263 {
1264 d3dxmesh->lpVtbl->Release(d3dxmesh);
1265 }
1266
1267 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, 0, device, &d3dxmesh);
1268 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1269
1270 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl1, device, NULL);
1271 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1272
1273 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl1, device, &d3dxmesh);
1274 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
1275
1276 if (hr == D3D_OK)
1277 {
1278 /* device */
1279 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, NULL);
1280 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1281
1282 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, &test_device);
1283 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
1284 ok(test_device == device, "Got result %p, expected %p\n", test_device, device);
1285
1286 if (hr == D3D_OK)
1287 {
1288 IDirect3DDevice9_Release(device);
1289 }
1290
1291 /* declaration */
1292 hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, NULL);
1293 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1294
1295 hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, test_decl);
1296 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
1297
1298 if (hr == D3D_OK)
1299 {
1300 size = ARRAY_SIZE(decl1);
1301 for (i = 0; i < size - 1; i++)
1302 {
1303 ok(test_decl[i].Stream == decl1[i].Stream, "Returned stream %d, expected %d\n", test_decl[i].Stream, decl1[i].Stream);
1304 ok(test_decl[i].Type == decl1[i].Type, "Returned type %d, expected %d\n", test_decl[i].Type, decl1[i].Type);
1305 ok(test_decl[i].Method == decl1[i].Method, "Returned method %d, expected %d\n", test_decl[i].Method, decl1[i].Method);
1306 ok(test_decl[i].Usage == decl1[i].Usage, "Returned usage %d, expected %d\n", test_decl[i].Usage, decl1[i].Usage);
1307 ok(test_decl[i].UsageIndex == decl1[i].UsageIndex, "Returned usage index %d, expected %d\n", test_decl[i].UsageIndex, decl1[i].UsageIndex);
1308 ok(test_decl[i].Offset == decl1[i].Offset, "Returned offset %d, expected %d\n", test_decl[i].Offset, decl1[i].Offset);
1309 }
1310 ok(decl1[size-1].Stream == 0xFF, "Returned too long vertex declaration\n"); /* end element */
1311 }
1312
1313 /* options */
1314 options = d3dxmesh->lpVtbl->GetOptions(d3dxmesh);
1315 ok(options == D3DXMESH_MANAGED, "Got result %x, expected %x (D3DXMESH_MANAGED)\n", options, D3DXMESH_MANAGED);
1316
1317 /* rest */
1318 if (!new_mesh(&mesh, 3, 1))
1319 {
1320 skip("Couldn't create mesh\n");
1321 }
1322 else
1323 {
1324 memset(mesh.vertices, 0, mesh.number_of_vertices * sizeof(*mesh.vertices));
1325 memset(mesh.faces, 0, mesh.number_of_faces * sizeof(*mesh.faces));
1326 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
1327
1328 compare_mesh("createmesh1", d3dxmesh, &mesh);
1329
1330 free_mesh(&mesh);
1331 }
1332
1333 d3dxmesh->lpVtbl->Release(d3dxmesh);
1334 }
1335
1336 /* Test a declaration that can't be converted to an FVF. */
1337 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl2, device, &d3dxmesh);
1338 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
1339
1340 if (hr == D3D_OK)
1341 {
1342 /* device */
1343 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, NULL);
1344 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1345
1346 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, &test_device);
1347 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
1348 ok(test_device == device, "Got result %p, expected %p\n", test_device, device);
1349
1350 if (hr == D3D_OK)
1351 {
1352 IDirect3DDevice9_Release(device);
1353 }
1354
1355 /* declaration */
1356 hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, test_decl);
1357 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
1358
1359 if (hr == D3D_OK)
1360 {
1361 size = ARRAY_SIZE(decl2);
1362 for (i = 0; i < size - 1; i++)
1363 {
1364 ok(test_decl[i].Stream == decl2[i].Stream, "Returned stream %d, expected %d\n", test_decl[i].Stream, decl2[i].Stream);
1365 ok(test_decl[i].Type == decl2[i].Type, "Returned type %d, expected %d\n", test_decl[i].Type, decl2[i].Type);
1366 ok(test_decl[i].Method == decl2[i].Method, "Returned method %d, expected %d\n", test_decl[i].Method, decl2[i].Method);
1367 ok(test_decl[i].Usage == decl2[i].Usage, "Returned usage %d, expected %d\n", test_decl[i].Usage, decl2[i].Usage);
1368 ok(test_decl[i].UsageIndex == decl2[i].UsageIndex, "Returned usage index %d, expected %d\n", test_decl[i].UsageIndex, decl2[i].UsageIndex);
1369 ok(test_decl[i].Offset == decl2[i].Offset, "Returned offset %d, expected %d\n", test_decl[i].Offset, decl2[i].Offset);
1370 }
1371 ok(decl2[size-1].Stream == 0xFF, "Returned too long vertex declaration\n"); /* end element */
1372 }
1373
1374 /* options */
1375 options = d3dxmesh->lpVtbl->GetOptions(d3dxmesh);
1376 ok(options == D3DXMESH_MANAGED, "Got result %x, expected %x (D3DXMESH_MANAGED)\n", options, D3DXMESH_MANAGED);
1377
1378 /* rest */
1379 if (!new_mesh(&mesh, 3, 1))
1380 {
1381 skip("Couldn't create mesh\n");
1382 }
1383 else
1384 {
1385 memset(mesh.vertices, 0, mesh.number_of_vertices * sizeof(*mesh.vertices));
1386 memset(mesh.faces, 0, mesh.number_of_faces * sizeof(*mesh.faces));
1387 mesh.fvf = 0;
1388 mesh.vertex_size = 60;
1389
1390 compare_mesh("createmesh2", d3dxmesh, &mesh);
1391
1392 free_mesh(&mesh);
1393 }
1394
1395 mesh.vertex_size = d3dxmesh->lpVtbl->GetNumBytesPerVertex(d3dxmesh);
1396 ok(mesh.vertex_size == 60, "Got vertex size %u, expected %u\n", mesh.vertex_size, 60);
1397
1398 d3dxmesh->lpVtbl->Release(d3dxmesh);
1399 }
1400
1401 /* Test a declaration with multiple streams. */
1402 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl3, device, &d3dxmesh);
1403 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1404
1405 free_test_context(test_context);
1406 }
1407
D3DXCreateMeshFVFTest(void)1408 static void D3DXCreateMeshFVFTest(void)
1409 {
1410 HRESULT hr;
1411 IDirect3DDevice9 *device, *test_device;
1412 ID3DXMesh *d3dxmesh;
1413 int i, size;
1414 D3DVERTEXELEMENT9 test_decl[MAX_FVF_DECL_SIZE];
1415 DWORD options;
1416 struct mesh mesh;
1417 struct test_context *test_context;
1418
1419 static const D3DVERTEXELEMENT9 decl[] =
1420 {
1421 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1422 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
1423 D3DDECL_END(),
1424 };
1425
1426 hr = D3DXCreateMeshFVF(0, 0, 0, 0, NULL, NULL);
1427 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1428
1429 hr = D3DXCreateMeshFVF(1, 3, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, NULL, &d3dxmesh);
1430 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1431
1432 test_context = new_test_context();
1433 if (!test_context)
1434 {
1435 skip("Couldn't create test context\n");
1436 return;
1437 }
1438 device = test_context->device;
1439
1440 hr = D3DXCreateMeshFVF(0, 3, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, device, &d3dxmesh);
1441 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1442
1443 hr = D3DXCreateMeshFVF(1, 0, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, device, &d3dxmesh);
1444 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1445
1446 hr = D3DXCreateMeshFVF(1, 3, 0, D3DFVF_XYZ | D3DFVF_NORMAL, device, &d3dxmesh);
1447 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
1448
1449 if (hr == D3D_OK)
1450 {
1451 d3dxmesh->lpVtbl->Release(d3dxmesh);
1452 }
1453
1454 hr = D3DXCreateMeshFVF(1, 3, D3DXMESH_MANAGED, 0xdeadbeef, device, &d3dxmesh);
1455 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1456
1457 hr = D3DXCreateMeshFVF(1, 3, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, device, NULL);
1458 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1459
1460 hr = D3DXCreateMeshFVF(1, 3, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, device, &d3dxmesh);
1461 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
1462
1463 if (hr == D3D_OK)
1464 {
1465 /* device */
1466 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, NULL);
1467 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1468
1469 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, &test_device);
1470 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
1471 ok(test_device == device, "Got result %p, expected %p\n", test_device, device);
1472
1473 if (hr == D3D_OK)
1474 {
1475 IDirect3DDevice9_Release(device);
1476 }
1477
1478 /* declaration */
1479 hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, NULL);
1480 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
1481
1482 hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, test_decl);
1483 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
1484
1485 if (hr == D3D_OK)
1486 {
1487 size = ARRAY_SIZE(decl);
1488 for (i = 0; i < size - 1; i++)
1489 {
1490 ok(test_decl[i].Stream == decl[i].Stream, "Returned stream %d, expected %d\n", test_decl[i].Stream, decl[i].Stream);
1491 ok(test_decl[i].Type == decl[i].Type, "Returned type %d, expected %d\n", test_decl[i].Type, decl[i].Type);
1492 ok(test_decl[i].Method == decl[i].Method, "Returned method %d, expected %d\n", test_decl[i].Method, decl[i].Method);
1493 ok(test_decl[i].Usage == decl[i].Usage, "Returned usage %d, expected %d\n", test_decl[i].Usage, decl[i].Usage);
1494 ok(test_decl[i].UsageIndex == decl[i].UsageIndex, "Returned usage index %d, expected %d\n",
1495 test_decl[i].UsageIndex, decl[i].UsageIndex);
1496 ok(test_decl[i].Offset == decl[i].Offset, "Returned offset %d, expected %d\n", test_decl[i].Offset, decl[i].Offset);
1497 }
1498 ok(decl[size-1].Stream == 0xFF, "Returned too long vertex declaration\n"); /* end element */
1499 }
1500
1501 /* options */
1502 options = d3dxmesh->lpVtbl->GetOptions(d3dxmesh);
1503 ok(options == D3DXMESH_MANAGED, "Got result %x, expected %x (D3DXMESH_MANAGED)\n", options, D3DXMESH_MANAGED);
1504
1505 /* rest */
1506 if (!new_mesh(&mesh, 3, 1))
1507 {
1508 skip("Couldn't create mesh\n");
1509 }
1510 else
1511 {
1512 memset(mesh.vertices, 0, mesh.number_of_vertices * sizeof(*mesh.vertices));
1513 memset(mesh.faces, 0, mesh.number_of_faces * sizeof(*mesh.faces));
1514 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
1515
1516 compare_mesh("createmeshfvf", d3dxmesh, &mesh);
1517
1518 free_mesh(&mesh);
1519 }
1520
1521 d3dxmesh->lpVtbl->Release(d3dxmesh);
1522 }
1523
1524 free_test_context(test_context);
1525 }
1526
1527 #define check_vertex_buffer(mesh, vertices, num_vertices, fvf) \
1528 check_vertex_buffer_(__LINE__, mesh, vertices, num_vertices, fvf)
check_vertex_buffer_(int line,ID3DXMesh * mesh,const void * vertices,DWORD num_vertices,DWORD fvf)1529 static void check_vertex_buffer_(int line, ID3DXMesh *mesh, const void *vertices, DWORD num_vertices, DWORD fvf)
1530 {
1531 DWORD mesh_num_vertices = mesh->lpVtbl->GetNumVertices(mesh);
1532 DWORD mesh_fvf = mesh->lpVtbl->GetFVF(mesh);
1533 const void *mesh_vertices;
1534 HRESULT hr;
1535
1536 ok_(__FILE__,line)(fvf == mesh_fvf, "expected FVF %x, got %x\n", fvf, mesh_fvf);
1537 ok_(__FILE__,line)(num_vertices == mesh_num_vertices,
1538 "Expected %u vertices, got %u\n", num_vertices, mesh_num_vertices);
1539
1540 hr = mesh->lpVtbl->LockVertexBuffer(mesh, D3DLOCK_READONLY, (void**)&mesh_vertices);
1541 ok_(__FILE__,line)(hr == D3D_OK, "LockVertexBuffer returned %x, expected %x (D3D_OK)\n", hr, D3D_OK);
1542 if (FAILED(hr))
1543 return;
1544
1545 if (mesh_fvf == fvf) {
1546 DWORD vertex_size = D3DXGetFVFVertexSize(fvf), i;
1547
1548 for (i = 0; i < min(num_vertices, mesh_num_vertices); i++)
1549 {
1550 const FLOAT *exp_float = vertices;
1551 const FLOAT *got_float = mesh_vertices;
1552 DWORD texcount;
1553 DWORD pos_dim = 0;
1554 int j;
1555 BOOL last_beta_dword = FALSE;
1556 char prefix[128];
1557
1558 switch (fvf & D3DFVF_POSITION_MASK) {
1559 case D3DFVF_XYZ: pos_dim = 3; break;
1560 case D3DFVF_XYZRHW: pos_dim = 4; break;
1561 case D3DFVF_XYZB1:
1562 case D3DFVF_XYZB2:
1563 case D3DFVF_XYZB3:
1564 case D3DFVF_XYZB4:
1565 case D3DFVF_XYZB5:
1566 pos_dim = (fvf & D3DFVF_POSITION_MASK) - D3DFVF_XYZB1 + 1;
1567 if (fvf & (D3DFVF_LASTBETA_UBYTE4 | D3DFVF_LASTBETA_D3DCOLOR))
1568 {
1569 pos_dim--;
1570 last_beta_dword = TRUE;
1571 }
1572 break;
1573 case D3DFVF_XYZW: pos_dim = 4; break;
1574 }
1575 sprintf(prefix, "vertex[%u] position, ", i);
1576 check_floats_(line, prefix, got_float, exp_float, pos_dim);
1577 exp_float += pos_dim;
1578 got_float += pos_dim;
1579
1580 if (last_beta_dword) {
1581 ok_(__FILE__,line)(*(DWORD*)exp_float == *(DWORD*)got_float,
1582 "Vertex[%u]: Expected last beta %08x, got %08x\n", i, *(DWORD*)exp_float, *(DWORD*)got_float);
1583 exp_float++;
1584 got_float++;
1585 }
1586
1587 if (fvf & D3DFVF_NORMAL) {
1588 sprintf(prefix, "vertex[%u] normal, ", i);
1589 check_floats_(line, prefix, got_float, exp_float, 3);
1590 exp_float += 3;
1591 got_float += 3;
1592 }
1593 if (fvf & D3DFVF_PSIZE) {
1594 ok_(__FILE__,line)(compare(*exp_float, *got_float),
1595 "Vertex[%u]: Expected psize %g, got %g\n", i, *exp_float, *got_float);
1596 exp_float++;
1597 got_float++;
1598 }
1599 if (fvf & D3DFVF_DIFFUSE) {
1600 ok_(__FILE__,line)(*(DWORD*)exp_float == *(DWORD*)got_float,
1601 "Vertex[%u]: Expected diffuse %08x, got %08x\n", i, *(DWORD*)exp_float, *(DWORD*)got_float);
1602 exp_float++;
1603 got_float++;
1604 }
1605 if (fvf & D3DFVF_SPECULAR) {
1606 ok_(__FILE__,line)(*(DWORD*)exp_float == *(DWORD*)got_float,
1607 "Vertex[%u]: Expected specular %08x, got %08x\n", i, *(DWORD*)exp_float, *(DWORD*)got_float);
1608 exp_float++;
1609 got_float++;
1610 }
1611
1612 texcount = (fvf & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
1613 for (j = 0; j < texcount; j++) {
1614 DWORD dim = (((fvf >> (16 + 2 * j)) + 1) & 0x03) + 1;
1615 sprintf(prefix, "vertex[%u] texture, ", i);
1616 check_floats_(line, prefix, got_float, exp_float, dim);
1617 exp_float += dim;
1618 got_float += dim;
1619 }
1620
1621 vertices = (BYTE*)vertices + vertex_size;
1622 mesh_vertices = (BYTE*)mesh_vertices + vertex_size;
1623 }
1624 }
1625
1626 mesh->lpVtbl->UnlockVertexBuffer(mesh);
1627 }
1628
1629 #define check_index_buffer(mesh, indices, num_indices, index_size) \
1630 check_index_buffer_(__LINE__, mesh, indices, num_indices, index_size)
check_index_buffer_(int line,ID3DXMesh * mesh,const void * indices,DWORD num_indices,DWORD index_size)1631 static void check_index_buffer_(int line, ID3DXMesh *mesh, const void *indices, DWORD num_indices, DWORD index_size)
1632 {
1633 DWORD mesh_index_size = (mesh->lpVtbl->GetOptions(mesh) & D3DXMESH_32BIT) ? 4 : 2;
1634 DWORD mesh_num_indices = mesh->lpVtbl->GetNumFaces(mesh) * 3;
1635 const void *mesh_indices;
1636 HRESULT hr;
1637 DWORD i;
1638
1639 ok_(__FILE__,line)(index_size == mesh_index_size,
1640 "Expected index size %u, got %u\n", index_size, mesh_index_size);
1641 ok_(__FILE__,line)(num_indices == mesh_num_indices,
1642 "Expected %u indices, got %u\n", num_indices, mesh_num_indices);
1643
1644 hr = mesh->lpVtbl->LockIndexBuffer(mesh, D3DLOCK_READONLY, (void**)&mesh_indices);
1645 ok_(__FILE__,line)(hr == D3D_OK, "LockIndexBuffer returned %x, expected %x (D3D_OK)\n", hr, D3D_OK);
1646 if (FAILED(hr))
1647 return;
1648
1649 if (mesh_index_size == index_size) {
1650 for (i = 0; i < min(num_indices, mesh_num_indices); i++)
1651 {
1652 if (index_size == 4)
1653 ok_(__FILE__,line)(*(DWORD*)indices == *(DWORD*)mesh_indices,
1654 "Index[%u]: expected %u, got %u\n", i, *(DWORD*)indices, *(DWORD*)mesh_indices);
1655 else
1656 ok_(__FILE__,line)(*(WORD*)indices == *(WORD*)mesh_indices,
1657 "Index[%u]: expected %u, got %u\n", i, *(WORD*)indices, *(WORD*)mesh_indices);
1658 indices = (BYTE*)indices + index_size;
1659 mesh_indices = (BYTE*)mesh_indices + index_size;
1660 }
1661 }
1662 mesh->lpVtbl->UnlockIndexBuffer(mesh);
1663 }
1664
1665 #define check_matrix(got, expected) check_matrix_(__LINE__, got, expected)
check_matrix_(int line,const D3DXMATRIX * got,const D3DXMATRIX * expected)1666 static void check_matrix_(int line, const D3DXMATRIX *got, const D3DXMATRIX *expected)
1667 {
1668 int i, j;
1669 for (i = 0; i < 4; i++) {
1670 for (j = 0; j < 4; j++) {
1671 ok_(__FILE__,line)(compare(U(*expected).m[i][j], U(*got).m[i][j]),
1672 "matrix[%u][%u]: expected %g, got %g\n",
1673 i, j, U(*expected).m[i][j], U(*got).m[i][j]);
1674 }
1675 }
1676 }
1677
check_colorvalue_(int line,const char * prefix,const D3DCOLORVALUE got,const D3DCOLORVALUE expected)1678 static void check_colorvalue_(int line, const char *prefix, const D3DCOLORVALUE got, const D3DCOLORVALUE expected)
1679 {
1680 ok_(__FILE__,line)(expected.r == got.r && expected.g == got.g && expected.b == got.b && expected.a == got.a,
1681 "%sExpected (%g, %g, %g, %g), got (%g, %g, %g, %g)\n", prefix,
1682 expected.r, expected.g, expected.b, expected.a, got.r, got.g, got.b, got.a);
1683 }
1684
1685 #define check_materials(got, got_count, expected, expected_count) \
1686 check_materials_(__LINE__, got, got_count, expected, expected_count)
check_materials_(int line,const D3DXMATERIAL * got,DWORD got_count,const D3DXMATERIAL * expected,DWORD expected_count)1687 static void check_materials_(int line, const D3DXMATERIAL *got, DWORD got_count, const D3DXMATERIAL *expected, DWORD expected_count)
1688 {
1689 int i;
1690 ok_(__FILE__,line)(expected_count == got_count, "Expected %u materials, got %u\n", expected_count, got_count);
1691 if (!expected) {
1692 ok_(__FILE__,line)(got == NULL, "Expected NULL material ptr, got %p\n", got);
1693 return;
1694 }
1695 for (i = 0; i < min(expected_count, got_count); i++)
1696 {
1697 if (!expected[i].pTextureFilename)
1698 ok_(__FILE__,line)(got[i].pTextureFilename == NULL,
1699 "Expected NULL pTextureFilename, got %p\n", got[i].pTextureFilename);
1700 else
1701 ok_(__FILE__,line)(!strcmp(expected[i].pTextureFilename, got[i].pTextureFilename),
1702 "Expected '%s' for pTextureFilename, got '%s'\n", expected[i].pTextureFilename, got[i].pTextureFilename);
1703 check_colorvalue_(line, "Diffuse: ", got[i].MatD3D.Diffuse, expected[i].MatD3D.Diffuse);
1704 check_colorvalue_(line, "Ambient: ", got[i].MatD3D.Ambient, expected[i].MatD3D.Ambient);
1705 check_colorvalue_(line, "Specular: ", got[i].MatD3D.Specular, expected[i].MatD3D.Specular);
1706 check_colorvalue_(line, "Emissive: ", got[i].MatD3D.Emissive, expected[i].MatD3D.Emissive);
1707 ok_(__FILE__,line)(expected[i].MatD3D.Power == got[i].MatD3D.Power,
1708 "Power: Expected %g, got %g\n", expected[i].MatD3D.Power, got[i].MatD3D.Power);
1709 }
1710 }
1711
1712 #define check_generated_adjacency(mesh, got, epsilon) check_generated_adjacency_(__LINE__, mesh, got, epsilon)
check_generated_adjacency_(int line,ID3DXMesh * mesh,const DWORD * got,FLOAT epsilon)1713 static void check_generated_adjacency_(int line, ID3DXMesh *mesh, const DWORD *got, FLOAT epsilon)
1714 {
1715 DWORD *expected;
1716 DWORD num_faces = mesh->lpVtbl->GetNumFaces(mesh);
1717 HRESULT hr;
1718
1719 expected = HeapAlloc(GetProcessHeap(), 0, num_faces * sizeof(DWORD) * 3);
1720 if (!expected) {
1721 skip_(__FILE__, line)("Out of memory\n");
1722 return;
1723 }
1724 hr = mesh->lpVtbl->GenerateAdjacency(mesh, epsilon, expected);
1725 ok_(__FILE__, line)(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
1726 if (SUCCEEDED(hr))
1727 {
1728 int i;
1729 for (i = 0; i < num_faces; i++)
1730 {
1731 ok_(__FILE__, line)(expected[i * 3] == got[i * 3] &&
1732 expected[i * 3 + 1] == got[i * 3 + 1] &&
1733 expected[i * 3 + 2] == got[i * 3 + 2],
1734 "Face %u adjacencies: Expected (%u, %u, %u), got (%u, %u, %u)\n", i,
1735 expected[i * 3], expected[i * 3 + 1], expected[i * 3 + 2],
1736 got[i * 3], got[i * 3 + 1], got[i * 3 + 2]);
1737 }
1738 }
1739 HeapFree(GetProcessHeap(), 0, expected);
1740 }
1741
1742 #define check_generated_effects(materials, num_materials, effects) \
1743 check_generated_effects_(__LINE__, materials, num_materials, effects)
check_generated_effects_(int line,const D3DXMATERIAL * materials,DWORD num_materials,const D3DXEFFECTINSTANCE * effects)1744 static void check_generated_effects_(int line, const D3DXMATERIAL *materials, DWORD num_materials, const D3DXEFFECTINSTANCE *effects)
1745 {
1746 int i;
1747 static const struct {
1748 const char *name;
1749 DWORD name_size;
1750 DWORD num_bytes;
1751 DWORD value_offset;
1752 } params[] = {
1753 #define EFFECT_TABLE_ENTRY(str, field) \
1754 {str, sizeof(str), sizeof(materials->MatD3D.field), offsetof(D3DXMATERIAL, MatD3D.field)}
1755 EFFECT_TABLE_ENTRY("Diffuse", Diffuse),
1756 EFFECT_TABLE_ENTRY("Power", Power),
1757 EFFECT_TABLE_ENTRY("Specular", Specular),
1758 EFFECT_TABLE_ENTRY("Emissive", Emissive),
1759 EFFECT_TABLE_ENTRY("Ambient", Ambient),
1760 #undef EFFECT_TABLE_ENTRY
1761 };
1762
1763 if (!num_materials) {
1764 ok_(__FILE__, line)(effects == NULL, "Expected NULL effects, got %p\n", effects);
1765 return;
1766 }
1767 for (i = 0; i < num_materials; i++)
1768 {
1769 int j;
1770 DWORD expected_num_defaults = ARRAY_SIZE(params) + (materials[i].pTextureFilename ? 1 : 0);
1771
1772 ok_(__FILE__,line)(expected_num_defaults == effects[i].NumDefaults,
1773 "effect[%u] NumDefaults: Expected %u, got %u\n", i,
1774 expected_num_defaults, effects[i].NumDefaults);
1775 for (j = 0; j < min(ARRAY_SIZE(params), effects[i].NumDefaults); j++)
1776 {
1777 int k;
1778 D3DXEFFECTDEFAULT *got_param = &effects[i].pDefaults[j];
1779 ok_(__FILE__,line)(!strcmp(params[j].name, got_param->pParamName),
1780 "effect[%u].pDefaults[%u].pParamName: Expected '%s', got '%s'\n", i, j,
1781 params[j].name, got_param->pParamName);
1782 ok_(__FILE__,line)(D3DXEDT_FLOATS == got_param->Type,
1783 "effect[%u].pDefaults[%u].Type: Expected %u, got %u\n", i, j,
1784 D3DXEDT_FLOATS, got_param->Type);
1785 ok_(__FILE__,line)(params[j].num_bytes == got_param->NumBytes,
1786 "effect[%u].pDefaults[%u].NumBytes: Expected %u, got %u\n", i, j,
1787 params[j].num_bytes, got_param->NumBytes);
1788 for (k = 0; k < min(params[j].num_bytes, got_param->NumBytes) / 4; k++)
1789 {
1790 FLOAT expected = ((FLOAT*)((BYTE*)&materials[i] + params[j].value_offset))[k];
1791 FLOAT got = ((FLOAT*)got_param->pValue)[k];
1792 ok_(__FILE__,line)(compare(expected, got),
1793 "effect[%u].pDefaults[%u] float value %u: Expected %g, got %g\n", i, j, k, expected, got);
1794 }
1795 }
1796 if (effects[i].NumDefaults > ARRAY_SIZE(params)) {
1797 D3DXEFFECTDEFAULT *got_param = &effects[i].pDefaults[j];
1798 static const char *expected_name = "Texture0@Name";
1799
1800 ok_(__FILE__,line)(!strcmp(expected_name, got_param->pParamName),
1801 "effect[%u].pDefaults[%u].pParamName: Expected '%s', got '%s'\n", i, j,
1802 expected_name, got_param->pParamName);
1803 ok_(__FILE__,line)(D3DXEDT_STRING == got_param->Type,
1804 "effect[%u].pDefaults[%u].Type: Expected %u, got %u\n", i, j,
1805 D3DXEDT_STRING, got_param->Type);
1806 if (materials[i].pTextureFilename) {
1807 ok_(__FILE__,line)(strlen(materials[i].pTextureFilename) + 1 == got_param->NumBytes,
1808 "effect[%u] texture filename length: Expected %u, got %u\n", i,
1809 (DWORD)strlen(materials[i].pTextureFilename) + 1, got_param->NumBytes);
1810 ok_(__FILE__,line)(!strcmp(materials[i].pTextureFilename, got_param->pValue),
1811 "effect[%u] texture filename: Expected '%s', got '%s'\n", i,
1812 materials[i].pTextureFilename, (char*)got_param->pValue);
1813 }
1814 }
1815 }
1816 }
1817
strdupA(const char * p)1818 static char *strdupA(const char *p)
1819 {
1820 char *ret;
1821 if (!p) return NULL;
1822 ret = HeapAlloc(GetProcessHeap(), 0, strlen(p) + 1);
1823 if (ret) strcpy(ret, p);
1824 return ret;
1825 }
1826
ID3DXAllocateHierarchyImpl_DestroyFrame(ID3DXAllocateHierarchy * iface,LPD3DXFRAME frame)1827 static HRESULT CALLBACK ID3DXAllocateHierarchyImpl_DestroyFrame(ID3DXAllocateHierarchy *iface, LPD3DXFRAME frame)
1828 {
1829 TRACECALLBACK("ID3DXAllocateHierarchyImpl_DestroyFrame(%p, %p)\n", iface, frame);
1830 if (frame) {
1831 HeapFree(GetProcessHeap(), 0, frame->Name);
1832 HeapFree(GetProcessHeap(), 0, frame);
1833 }
1834 return D3D_OK;
1835 }
1836
ID3DXAllocateHierarchyImpl_CreateFrame(ID3DXAllocateHierarchy * iface,const char * name,D3DXFRAME ** new_frame)1837 static HRESULT CALLBACK ID3DXAllocateHierarchyImpl_CreateFrame(ID3DXAllocateHierarchy *iface,
1838 const char *name, D3DXFRAME **new_frame)
1839 {
1840 D3DXFRAME *frame;
1841
1842 TRACECALLBACK("ID3DXAllocateHierarchyImpl_CreateFrame(%p, '%s', %p)\n", iface, name, new_frame);
1843 frame = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*frame));
1844 if (!frame)
1845 return E_OUTOFMEMORY;
1846 if (name) {
1847 frame->Name = strdupA(name);
1848 if (!frame->Name) {
1849 HeapFree(GetProcessHeap(), 0, frame);
1850 return E_OUTOFMEMORY;
1851 }
1852 }
1853 *new_frame = frame;
1854 return D3D_OK;
1855 }
1856
destroy_mesh_container(LPD3DXMESHCONTAINER mesh_container)1857 static HRESULT destroy_mesh_container(LPD3DXMESHCONTAINER mesh_container)
1858 {
1859 int i;
1860
1861 if (!mesh_container)
1862 return D3D_OK;
1863 HeapFree(GetProcessHeap(), 0, mesh_container->Name);
1864 if (U(mesh_container->MeshData).pMesh)
1865 IUnknown_Release(U(mesh_container->MeshData).pMesh);
1866 if (mesh_container->pMaterials) {
1867 for (i = 0; i < mesh_container->NumMaterials; i++)
1868 HeapFree(GetProcessHeap(), 0, mesh_container->pMaterials[i].pTextureFilename);
1869 HeapFree(GetProcessHeap(), 0, mesh_container->pMaterials);
1870 }
1871 if (mesh_container->pEffects) {
1872 for (i = 0; i < mesh_container->NumMaterials; i++) {
1873 HeapFree(GetProcessHeap(), 0, mesh_container->pEffects[i].pEffectFilename);
1874 if (mesh_container->pEffects[i].pDefaults) {
1875 int j;
1876 for (j = 0; j < mesh_container->pEffects[i].NumDefaults; j++) {
1877 HeapFree(GetProcessHeap(), 0, mesh_container->pEffects[i].pDefaults[j].pParamName);
1878 HeapFree(GetProcessHeap(), 0, mesh_container->pEffects[i].pDefaults[j].pValue);
1879 }
1880 HeapFree(GetProcessHeap(), 0, mesh_container->pEffects[i].pDefaults);
1881 }
1882 }
1883 HeapFree(GetProcessHeap(), 0, mesh_container->pEffects);
1884 }
1885 HeapFree(GetProcessHeap(), 0, mesh_container->pAdjacency);
1886 if (mesh_container->pSkinInfo)
1887 IUnknown_Release(mesh_container->pSkinInfo);
1888 HeapFree(GetProcessHeap(), 0, mesh_container);
1889 return D3D_OK;
1890 }
1891
ID3DXAllocateHierarchyImpl_DestroyMeshContainer(ID3DXAllocateHierarchy * iface,LPD3DXMESHCONTAINER mesh_container)1892 static HRESULT CALLBACK ID3DXAllocateHierarchyImpl_DestroyMeshContainer(ID3DXAllocateHierarchy *iface, LPD3DXMESHCONTAINER mesh_container)
1893 {
1894 TRACECALLBACK("ID3DXAllocateHierarchyImpl_DestroyMeshContainer(%p, %p)\n", iface, mesh_container);
1895 return destroy_mesh_container(mesh_container);
1896 }
1897
ID3DXAllocateHierarchyImpl_CreateMeshContainer(ID3DXAllocateHierarchy * iface,const char * name,const D3DXMESHDATA * mesh_data,const D3DXMATERIAL * materials,const D3DXEFFECTINSTANCE * effects,DWORD num_materials,const DWORD * adjacency,ID3DXSkinInfo * skin_info,D3DXMESHCONTAINER ** new_mesh_container)1898 static HRESULT CALLBACK ID3DXAllocateHierarchyImpl_CreateMeshContainer(ID3DXAllocateHierarchy *iface,
1899 const char *name, const D3DXMESHDATA *mesh_data, const D3DXMATERIAL *materials,
1900 const D3DXEFFECTINSTANCE *effects, DWORD num_materials, const DWORD *adjacency,
1901 ID3DXSkinInfo *skin_info, D3DXMESHCONTAINER **new_mesh_container)
1902 {
1903 LPD3DXMESHCONTAINER mesh_container = NULL;
1904 int i;
1905
1906 TRACECALLBACK("ID3DXAllocateHierarchyImpl_CreateMeshContainer(%p, '%s', %u, %p, %p, %p, %d, %p, %p, %p)\n",
1907 iface, name, mesh_data->Type, U(*mesh_data).pMesh, materials, effects,
1908 num_materials, adjacency, skin_info, *new_mesh_container);
1909
1910 mesh_container = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*mesh_container));
1911 if (!mesh_container)
1912 return E_OUTOFMEMORY;
1913
1914 if (name) {
1915 mesh_container->Name = strdupA(name);
1916 if (!mesh_container->Name)
1917 goto error;
1918 }
1919
1920 mesh_container->NumMaterials = num_materials;
1921 if (num_materials) {
1922 mesh_container->pMaterials = HeapAlloc(GetProcessHeap(), 0, num_materials * sizeof(*materials));
1923 if (!mesh_container->pMaterials)
1924 goto error;
1925
1926 memcpy(mesh_container->pMaterials, materials, num_materials * sizeof(*materials));
1927 for (i = 0; i < num_materials; i++)
1928 mesh_container->pMaterials[i].pTextureFilename = NULL;
1929 for (i = 0; i < num_materials; i++) {
1930 if (materials[i].pTextureFilename) {
1931 mesh_container->pMaterials[i].pTextureFilename = strdupA(materials[i].pTextureFilename);
1932 if (!mesh_container->pMaterials[i].pTextureFilename)
1933 goto error;
1934 }
1935 }
1936
1937 mesh_container->pEffects = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, num_materials * sizeof(*effects));
1938 if (!mesh_container->pEffects)
1939 goto error;
1940 for (i = 0; i < num_materials; i++) {
1941 int j;
1942 const D3DXEFFECTINSTANCE *effect_src = &effects[i];
1943 D3DXEFFECTINSTANCE *effect_dest = &mesh_container->pEffects[i];
1944
1945 if (effect_src->pEffectFilename) {
1946 effect_dest->pEffectFilename = strdupA(effect_src->pEffectFilename);
1947 if (!effect_dest->pEffectFilename)
1948 goto error;
1949 }
1950 effect_dest->pDefaults = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1951 effect_src->NumDefaults * sizeof(*effect_src->pDefaults));
1952 if (!effect_dest->pDefaults)
1953 goto error;
1954 effect_dest->NumDefaults = effect_src->NumDefaults;
1955 for (j = 0; j < effect_src->NumDefaults; j++) {
1956 const D3DXEFFECTDEFAULT *default_src = &effect_src->pDefaults[j];
1957 D3DXEFFECTDEFAULT *default_dest = &effect_dest->pDefaults[j];
1958
1959 if (default_src->pParamName) {
1960 default_dest->pParamName = strdupA(default_src->pParamName);
1961 if (!default_dest->pParamName)
1962 goto error;
1963 }
1964 default_dest->NumBytes = default_src->NumBytes;
1965 default_dest->Type = default_src->Type;
1966 default_dest->pValue = HeapAlloc(GetProcessHeap(), 0, default_src->NumBytes);
1967 memcpy(default_dest->pValue, default_src->pValue, default_src->NumBytes);
1968 }
1969 }
1970 }
1971
1972 ok(adjacency != NULL, "Expected non-NULL adjacency, got NULL\n");
1973 if (adjacency) {
1974 if (mesh_data->Type == D3DXMESHTYPE_MESH || mesh_data->Type == D3DXMESHTYPE_PMESH) {
1975 ID3DXBaseMesh *basemesh = (ID3DXBaseMesh*)U(*mesh_data).pMesh;
1976 DWORD num_faces = basemesh->lpVtbl->GetNumFaces(basemesh);
1977 size_t size = num_faces * sizeof(DWORD) * 3;
1978 mesh_container->pAdjacency = HeapAlloc(GetProcessHeap(), 0, size);
1979 if (!mesh_container->pAdjacency)
1980 goto error;
1981 memcpy(mesh_container->pAdjacency, adjacency, size);
1982 } else {
1983 ok(mesh_data->Type == D3DXMESHTYPE_PATCHMESH, "Unknown mesh type %u\n", mesh_data->Type);
1984 if (mesh_data->Type == D3DXMESHTYPE_PATCHMESH)
1985 trace("FIXME: copying adjacency data for patch mesh not implemented\n");
1986 }
1987 }
1988
1989 memcpy(&mesh_container->MeshData, mesh_data, sizeof(*mesh_data));
1990 if (U(*mesh_data).pMesh)
1991 IUnknown_AddRef(U(*mesh_data).pMesh);
1992 if (skin_info) {
1993 mesh_container->pSkinInfo = skin_info;
1994 skin_info->lpVtbl->AddRef(skin_info);
1995 }
1996 *new_mesh_container = mesh_container;
1997
1998 return S_OK;
1999 error:
2000 destroy_mesh_container(mesh_container);
2001 return E_OUTOFMEMORY;
2002 }
2003
2004 static ID3DXAllocateHierarchyVtbl ID3DXAllocateHierarchyImpl_Vtbl = {
2005 ID3DXAllocateHierarchyImpl_CreateFrame,
2006 ID3DXAllocateHierarchyImpl_CreateMeshContainer,
2007 ID3DXAllocateHierarchyImpl_DestroyFrame,
2008 ID3DXAllocateHierarchyImpl_DestroyMeshContainer,
2009 };
2010 static ID3DXAllocateHierarchy alloc_hier = { &ID3DXAllocateHierarchyImpl_Vtbl };
2011
2012 #define test_LoadMeshFromX(device, xfile_str, vertex_array, fvf, index_array, materials_array, check_adjacency) \
2013 test_LoadMeshFromX_(__LINE__, device, xfile_str, sizeof(xfile_str) - 1, vertex_array, ARRAY_SIZE(vertex_array), fvf, \
2014 index_array, ARRAY_SIZE(index_array), sizeof(*index_array), materials_array, ARRAY_SIZE(materials_array), \
2015 check_adjacency);
test_LoadMeshFromX_(int line,IDirect3DDevice9 * device,const char * xfile_str,size_t xfile_strlen,const void * vertices,DWORD num_vertices,DWORD fvf,const void * indices,DWORD num_indices,size_t index_size,const D3DXMATERIAL * expected_materials,DWORD expected_num_materials,BOOL check_adjacency)2016 static void test_LoadMeshFromX_(int line, IDirect3DDevice9 *device, const char *xfile_str, size_t xfile_strlen,
2017 const void *vertices, DWORD num_vertices, DWORD fvf, const void *indices, DWORD num_indices, size_t index_size,
2018 const D3DXMATERIAL *expected_materials, DWORD expected_num_materials, BOOL check_adjacency)
2019 {
2020 HRESULT hr;
2021 ID3DXBuffer *materials = NULL;
2022 ID3DXBuffer *effects = NULL;
2023 ID3DXBuffer *adjacency = NULL;
2024 ID3DXMesh *mesh = NULL;
2025 DWORD num_materials = 0;
2026
2027 /* Adjacency is not checked when the X file contains multiple meshes,
2028 * since calling GenerateAdjacency on the merged mesh is not equivalent
2029 * to calling GenerateAdjacency on the individual meshes and then merging
2030 * the adjacency data. */
2031 hr = D3DXLoadMeshFromXInMemory(xfile_str, xfile_strlen, D3DXMESH_MANAGED, device,
2032 check_adjacency ? &adjacency : NULL, &materials, &effects, &num_materials, &mesh);
2033 ok_(__FILE__,line)(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2034 if (SUCCEEDED(hr)) {
2035 D3DXMATERIAL *materials_ptr = materials ? ID3DXBuffer_GetBufferPointer(materials) : NULL;
2036 D3DXEFFECTINSTANCE *effects_ptr = effects ? ID3DXBuffer_GetBufferPointer(effects) : NULL;
2037 DWORD *adjacency_ptr = check_adjacency ? ID3DXBuffer_GetBufferPointer(adjacency) : NULL;
2038
2039 check_vertex_buffer_(line, mesh, vertices, num_vertices, fvf);
2040 check_index_buffer_(line, mesh, indices, num_indices, index_size);
2041 check_materials_(line, materials_ptr, num_materials, expected_materials, expected_num_materials);
2042 check_generated_effects_(line, materials_ptr, num_materials, effects_ptr);
2043 if (check_adjacency)
2044 check_generated_adjacency_(line, mesh, adjacency_ptr, 0.0f);
2045
2046 if (materials) ID3DXBuffer_Release(materials);
2047 if (effects) ID3DXBuffer_Release(effects);
2048 if (adjacency) ID3DXBuffer_Release(adjacency);
2049 IUnknown_Release(mesh);
2050 }
2051 }
2052
D3DXLoadMeshTest(void)2053 static void D3DXLoadMeshTest(void)
2054 {
2055 static const char empty_xfile[] = "xof 0303txt 0032";
2056 /*________________________*/
2057 static const char simple_xfile[] =
2058 "xof 0303txt 0032"
2059 "Mesh {"
2060 "3;"
2061 "0.0; 0.0; 0.0;,"
2062 "0.0; 1.0; 0.0;,"
2063 "1.0; 1.0; 0.0;;"
2064 "1;"
2065 "3; 0, 1, 2;;"
2066 "}";
2067 static const WORD simple_index_buffer[] = {0, 1, 2};
2068 static const D3DXVECTOR3 simple_vertex_buffer[] = {
2069 {0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {1.0, 1.0, 0.0}
2070 };
2071 const DWORD simple_fvf = D3DFVF_XYZ;
2072 static const char framed_xfile[] =
2073 "xof 0303txt 0032"
2074 "Frame {"
2075 "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;; }"
2076 "FrameTransformMatrix {" /* translation (0.0, 0.0, 2.0) */
2077 "1.0, 0.0, 0.0, 0.0,"
2078 "0.0, 1.0, 0.0, 0.0,"
2079 "0.0, 0.0, 1.0, 0.0,"
2080 "0.0, 0.0, 2.0, 1.0;;"
2081 "}"
2082 "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;; }"
2083 "FrameTransformMatrix {" /* translation (0.0, 0.0, 3.0) */
2084 "1.0, 0.0, 0.0, 0.0,"
2085 "0.0, 1.0, 0.0, 0.0,"
2086 "0.0, 0.0, 1.0, 0.0,"
2087 "0.0, 0.0, 3.0, 1.0;;"
2088 "}"
2089 "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;; }"
2090 "}";
2091 static const WORD framed_index_buffer[] = { 0, 1, 2 };
2092 static const D3DXVECTOR3 framed_vertex_buffers[3][3] = {
2093 {{0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {1.0, 1.0, 0.0}},
2094 {{0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {2.0, 1.0, 0.0}},
2095 {{0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {3.0, 1.0, 0.0}},
2096 };
2097 static const WORD merged_index_buffer[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
2098 /* frame transforms accumulates for D3DXLoadMeshFromX */
2099 static const D3DXVECTOR3 merged_vertex_buffer[] = {
2100 {0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {1.0, 1.0, 0.0},
2101 {0.0, 0.0, 2.0}, {0.0, 1.0, 2.0}, {2.0, 1.0, 2.0},
2102 {0.0, 0.0, 5.0}, {0.0, 1.0, 5.0}, {3.0, 1.0, 5.0},
2103 };
2104 const DWORD framed_fvf = D3DFVF_XYZ;
2105 /*________________________*/
2106 static const char box_xfile[] =
2107 "xof 0303txt 0032"
2108 "Mesh {"
2109 "8;" /* DWORD nVertices; */
2110 /* array Vector vertices[nVertices]; */
2111 "0.0; 0.0; 0.0;,"
2112 "0.0; 0.0; 1.0;,"
2113 "0.0; 1.0; 0.0;,"
2114 "0.0; 1.0; 1.0;,"
2115 "1.0; 0.0; 0.0;,"
2116 "1.0; 0.0; 1.0;,"
2117 "1.0; 1.0; 0.0;,"
2118 "1.0; 1.0; 1.0;;"
2119 "6;" /* DWORD nFaces; */
2120 /* array MeshFace faces[nFaces]; */
2121 "4; 0, 1, 3, 2;," /* (left side) */
2122 "4; 2, 3, 7, 6;," /* (top side) */
2123 "4; 6, 7, 5, 4;," /* (right side) */
2124 "4; 1, 0, 4, 5;," /* (bottom side) */
2125 "4; 1, 5, 7, 3;," /* (back side) */
2126 "4; 0, 2, 6, 4;;" /* (front side) */
2127 "MeshNormals {"
2128 "6;" /* DWORD nNormals; */
2129 /* array Vector normals[nNormals]; */
2130 "-1.0; 0.0; 0.0;,"
2131 "0.0; 1.0; 0.0;,"
2132 "1.0; 0.0; 0.0;,"
2133 "0.0; -1.0; 0.0;,"
2134 "0.0; 0.0; 1.0;,"
2135 "0.0; 0.0; -1.0;;"
2136 "6;" /* DWORD nFaceNormals; */
2137 /* array MeshFace faceNormals[nFaceNormals]; */
2138 "4; 0, 0, 0, 0;,"
2139 "4; 1, 1, 1, 1;,"
2140 "4; 2, 2, 2, 2;,"
2141 "4; 3, 3, 3, 3;,"
2142 "4; 4, 4, 4, 4;,"
2143 "4; 5, 5, 5, 5;;"
2144 "}"
2145 "MeshMaterialList materials {"
2146 "2;" /* DWORD nMaterials; */
2147 "6;" /* DWORD nFaceIndexes; */
2148 /* array DWORD faceIndexes[nFaceIndexes]; */
2149 "0, 0, 0, 1, 1, 1;;"
2150 "Material {"
2151 /* ColorRGBA faceColor; */
2152 "0.0; 0.0; 1.0; 1.0;;"
2153 /* FLOAT power; */
2154 "0.5;"
2155 /* ColorRGB specularColor; */
2156 "1.0; 1.0; 1.0;;"
2157 /* ColorRGB emissiveColor; */
2158 "0.0; 0.0; 0.0;;"
2159 "}"
2160 "Material {"
2161 /* ColorRGBA faceColor; */
2162 "1.0; 1.0; 1.0; 1.0;;"
2163 /* FLOAT power; */
2164 "1.0;"
2165 /* ColorRGB specularColor; */
2166 "1.0; 1.0; 1.0;;"
2167 /* ColorRGB emissiveColor; */
2168 "0.0; 0.0; 0.0;;"
2169 "TextureFilename { \"texture.jpg\"; }"
2170 "}"
2171 "}"
2172 "MeshVertexColors {"
2173 "8;" /* DWORD nVertexColors; */
2174 /* array IndexedColor vertexColors[nVertexColors]; */
2175 "0; 0.0; 0.0; 0.0; 0.0;;"
2176 "1; 0.0; 0.0; 1.0; 0.1;;"
2177 "2; 0.0; 1.0; 0.0; 0.2;;"
2178 "3; 0.0; 1.0; 1.0; 0.3;;"
2179 "4; 1.0; 0.0; 0.0; 0.4;;"
2180 "5; 1.0; 0.0; 1.0; 0.5;;"
2181 "6; 1.0; 1.0; 0.0; 0.6;;"
2182 "7; 1.0; 1.0; 1.0; 0.7;;"
2183 "}"
2184 "MeshTextureCoords {"
2185 "8;" /* DWORD nTextureCoords; */
2186 /* array Coords2d textureCoords[nTextureCoords]; */
2187 "0.0; 1.0;,"
2188 "1.0; 1.0;,"
2189 "0.0; 0.0;,"
2190 "1.0; 0.0;,"
2191 "1.0; 1.0;,"
2192 "0.0; 1.0;,"
2193 "1.0; 0.0;,"
2194 "0.0; 0.0;;"
2195 "}"
2196 "}";
2197 static const WORD box_index_buffer[] = {
2198 0, 1, 3,
2199 0, 3, 2,
2200 8, 9, 7,
2201 8, 7, 6,
2202 10, 11, 5,
2203 10, 5, 4,
2204 12, 13, 14,
2205 12, 14, 15,
2206 16, 17, 18,
2207 16, 18, 19,
2208 20, 21, 22,
2209 20, 22, 23,
2210 };
2211 static const struct {
2212 D3DXVECTOR3 position;
2213 D3DXVECTOR3 normal;
2214 D3DCOLOR diffuse;
2215 D3DXVECTOR2 tex_coords;
2216 } box_vertex_buffer[] = {
2217 {{0.0, 0.0, 0.0}, {-1.0, 0.0, 0.0}, 0x00000000, {0.0, 1.0}},
2218 {{0.0, 0.0, 1.0}, {-1.0, 0.0, 0.0}, 0x1a0000ff, {1.0, 1.0}},
2219 {{0.0, 1.0, 0.0}, {-1.0, 0.0, 0.0}, 0x3300ff00, {0.0, 0.0}},
2220 {{0.0, 1.0, 1.0}, {-1.0, 0.0, 0.0}, 0x4d00ffff, {1.0, 0.0}},
2221 {{1.0, 0.0, 0.0}, {1.0, 0.0, 0.0}, 0x66ff0000, {1.0, 1.0}},
2222 {{1.0, 0.0, 1.0}, {1.0, 0.0, 0.0}, 0x80ff00ff, {0.0, 1.0}},
2223 {{1.0, 1.0, 0.0}, {0.0, 1.0, 0.0}, 0x99ffff00, {1.0, 0.0}},
2224 {{1.0, 1.0, 1.0}, {0.0, 1.0, 0.0}, 0xb3ffffff, {0.0, 0.0}},
2225 {{0.0, 1.0, 0.0}, {0.0, 1.0, 0.0}, 0x3300ff00, {0.0, 0.0}},
2226 {{0.0, 1.0, 1.0}, {0.0, 1.0, 0.0}, 0x4d00ffff, {1.0, 0.0}},
2227 {{1.0, 1.0, 0.0}, {1.0, 0.0, 0.0}, 0x99ffff00, {1.0, 0.0}},
2228 {{1.0, 1.0, 1.0}, {1.0, 0.0, 0.0}, 0xb3ffffff, {0.0, 0.0}},
2229 {{0.0, 0.0, 1.0}, {0.0, -1.0, 0.0}, 0x1a0000ff, {1.0, 1.0}},
2230 {{0.0, 0.0, 0.0}, {0.0, -1.0, 0.0}, 0x00000000, {0.0, 1.0}},
2231 {{1.0, 0.0, 0.0}, {0.0, -1.0, 0.0}, 0x66ff0000, {1.0, 1.0}},
2232 {{1.0, 0.0, 1.0}, {0.0, -1.0, 0.0}, 0x80ff00ff, {0.0, 1.0}},
2233 {{0.0, 0.0, 1.0}, {0.0, 0.0, 1.0}, 0x1a0000ff, {1.0, 1.0}},
2234 {{1.0, 0.0, 1.0}, {0.0, 0.0, 1.0}, 0x80ff00ff, {0.0, 1.0}},
2235 {{1.0, 1.0, 1.0}, {0.0, 0.0, 1.0}, 0xb3ffffff, {0.0, 0.0}},
2236 {{0.0, 1.0, 1.0}, {0.0, 0.0, 1.0}, 0x4d00ffff, {1.0, 0.0}},
2237 {{0.0, 0.0, 0.0}, {0.0, 0.0, -1.0}, 0x00000000, {0.0, 1.0}},
2238 {{0.0, 1.0, 0.0}, {0.0, 0.0, -1.0}, 0x3300ff00, {0.0, 0.0}},
2239 {{1.0, 1.0, 0.0}, {0.0, 0.0, -1.0}, 0x99ffff00, {1.0, 0.0}},
2240 {{1.0, 0.0, 0.0}, {0.0, 0.0, -1.0}, 0x66ff0000, {1.0, 1.0}},
2241 };
2242 static const D3DXMATERIAL box_materials[] = {
2243 {
2244 {
2245 {0.0, 0.0, 1.0, 1.0}, /* Diffuse */
2246 {0.0, 0.0, 0.0, 1.0}, /* Ambient */
2247 {1.0, 1.0, 1.0, 1.0}, /* Specular */
2248 {0.0, 0.0, 0.0, 1.0}, /* Emissive */
2249 0.5, /* Power */
2250 },
2251 NULL, /* pTextureFilename */
2252 },
2253 {
2254 {
2255 {1.0, 1.0, 1.0, 1.0}, /* Diffuse */
2256 {0.0, 0.0, 0.0, 1.0}, /* Ambient */
2257 {1.0, 1.0, 1.0, 1.0}, /* Specular */
2258 {0.0, 0.0, 0.0, 1.0}, /* Emissive */
2259 1.0, /* Power */
2260 },
2261 (char *)"texture.jpg", /* pTextureFilename */
2262 },
2263 };
2264 static const char box_anim_xfile[] =
2265 "xof 0303txt 0032"
2266 "Mesh CubeMesh {"
2267 "8;" /* DWORD nVertices; */
2268 /* array Vector vertices[nVertices]; */
2269 "0.0; 0.0; 0.0;,"
2270 "0.0; 0.0; 1.0;,"
2271 "0.0; 1.0; 0.0;,"
2272 "0.0; 1.0; 1.0;,"
2273 "1.0; 0.0; 0.0;,"
2274 "1.0; 0.0; 1.0;,"
2275 "1.0; 1.0; 0.0;,"
2276 "1.0; 1.0; 1.0;;"
2277 "6;" /* DWORD nFaces; */
2278 /* array MeshFace faces[nFaces]; */
2279 "4; 0, 1, 3, 2;," /* left side */
2280 "4; 2, 3, 7, 6;," /* top side */
2281 "4; 6, 7, 5, 4;," /* right side */
2282 "4; 1, 0, 4, 5;," /* bottom side */
2283 "4; 1, 5, 7, 3;," /* back side */
2284 "4; 0, 2, 6, 4;;" /* front side */
2285 "MeshNormals {"
2286 "6;" /* DWORD nNormals; */
2287 /* array Vector normals[nNormals]; */
2288 "-1.0; 0.0; 0.0;,"
2289 "0.0; 1.0; 0.0;,"
2290 "1.0; 0.0; 0.0;,"
2291 "0.0; -1.0; 0.0;,"
2292 "0.0; 0.0; 1.0;,"
2293 "0.0; 0.0; -1.0;;"
2294 "6;" /* DWORD nFaceNormals; */
2295 /* array MeshFace faceNormals[nFaceNormals]; */
2296 "4; 0, 0, 0, 0;,"
2297 "4; 1, 1, 1, 1;,"
2298 "4; 2, 2, 2, 2;,"
2299 "4; 3, 3, 3, 3;,"
2300 "4; 4, 4, 4, 4;,"
2301 "4; 5, 5, 5, 5;;"
2302 "}"
2303 "MeshMaterialList materials {"
2304 "2;" /* DWORD nMaterials; */
2305 "6;" /* DWORD nFaceIndexes; */
2306 /* array DWORD faceIndexes[nFaceIndexes]; */
2307 "0, 0, 0, 1, 1, 1;;"
2308 "Material {"
2309 /* ColorRGBA faceColor; */
2310 "0.0; 0.0; 1.0; 1.0;;"
2311 /* FLOAT power; */
2312 "0.5;"
2313 /* ColorRGB specularColor; */
2314 "1.0; 1.0; 1.0;;"
2315 /* ColorRGB emissiveColor; */
2316 "0.0; 0.0; 0.0;;"
2317 "}"
2318 "Material {"
2319 /* ColorRGBA faceColor; */
2320 "1.0; 1.0; 1.0; 1.0;;"
2321 /* FLOAT power; */
2322 "1.0;"
2323 /* ColorRGB specularColor; */
2324 "1.0; 1.0; 1.0;;"
2325 /* ColorRGB emissiveColor; */
2326 "0.0; 0.0; 0.0;;"
2327 "TextureFilename { \"texture.jpg\"; }"
2328 "}"
2329 "}"
2330 "MeshVertexColors {"
2331 "8;" /* DWORD nVertexColors; */
2332 /* array IndexedColor vertexColors[nVertexColors]; */
2333 "0; 0.0; 0.0; 0.0; 0.0;;"
2334 "1; 0.0; 0.0; 1.0; 0.1;;"
2335 "2; 0.0; 1.0; 0.0; 0.2;;"
2336 "3; 0.0; 1.0; 1.0; 0.3;;"
2337 "4; 1.0; 0.0; 0.0; 0.4;;"
2338 "5; 1.0; 0.0; 1.0; 0.5;;"
2339 "6; 1.0; 1.0; 0.0; 0.6;;"
2340 "7; 1.0; 1.0; 1.0; 0.7;;"
2341 "}"
2342 "MeshTextureCoords {"
2343 "8;" /* DWORD nTextureCoords; */
2344 /* array Coords2d textureCoords[nTextureCoords]; */
2345 "0.0; 1.0;,"
2346 "1.0; 1.0;,"
2347 "0.0; 0.0;,"
2348 "1.0; 0.0;,"
2349 "1.0; 1.0;,"
2350 "0.0; 1.0;,"
2351 "1.0; 0.0;,"
2352 "0.0; 0.0;;"
2353 "}"
2354 "}"
2355 "Frame CubeFrame {"
2356 "FrameTransformMatrix {"
2357 /* Matrix4x4 frameMatrix; */
2358 "1.0, 0.0, 0.0, 0.0,"
2359 "0.0, 1.0, 0.0, 0.0,"
2360 "0.0, 0.0, 1.0, 0.0,"
2361 "0.0, 0.0, 0.0, 1.0;;"
2362 "}"
2363 "{CubeMesh}"
2364 "}"
2365 "AnimationSet AnimationSet0 {"
2366 "Animation Animation0 {"
2367 "{CubeFrame}"
2368 "AnimationKey {"
2369 "2;" /* DWORD keyType; */
2370 "9;" /* DWORD nKeys; */
2371 /* array TimedFloatKeys keys[nKeys]; */
2372 "10; 3; -100.0, 0.0, 0.0;;,"
2373 "20; 3; -75.0, 0.0, 0.0;;,"
2374 "30; 3; -50.0, 0.0, 0.0;;,"
2375 "40; 3; -25.5, 0.0, 0.0;;,"
2376 "50; 3; 0.0, 0.0, 0.0;;,"
2377 "60; 3; 25.5, 0.0, 0.0;;,"
2378 "70; 3; 50.0, 0.0, 0.0;;,"
2379 "80; 3; 75.5, 0.0, 0.0;;,"
2380 "90; 3; 100.0, 0.0, 0.0;;;"
2381 "}"
2382 "}"
2383 "}";
2384
2385 const DWORD box_fvf = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_TEX1;
2386 /*________________________*/
2387 static const D3DXMATERIAL default_materials[] = {
2388 {
2389 {
2390 {0.5, 0.5, 0.5, 0.0}, /* Diffuse */
2391 {0.0, 0.0, 0.0, 0.0}, /* Ambient */
2392 {0.5, 0.5, 0.5, 0.0}, /* Specular */
2393 {0.0, 0.0, 0.0, 0.0}, /* Emissive */
2394 0.0, /* Power */
2395 },
2396 NULL, /* pTextureFilename */
2397 }
2398 };
2399 HRESULT hr;
2400 IDirect3DDevice9 *device = NULL;
2401 ID3DXMesh *mesh = NULL;
2402 D3DXFRAME *frame_hier = NULL;
2403 D3DXMATRIX transform;
2404 struct test_context *test_context;
2405 ID3DXAnimationController *controller;
2406
2407 if (!(test_context = new_test_context()))
2408 {
2409 skip("Couldn't create test context\n");
2410 return;
2411 }
2412 device = test_context->device;
2413
2414 hr = D3DXLoadMeshHierarchyFromXInMemory(NULL, sizeof(simple_xfile) - 1,
2415 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
2416 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2417
2418 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, 0,
2419 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
2420 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2421
2422 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1,
2423 D3DXMESH_MANAGED, NULL, &alloc_hier, NULL, &frame_hier, NULL);
2424 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2425
2426 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1,
2427 D3DXMESH_MANAGED, device, NULL, NULL, &frame_hier, NULL);
2428 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2429
2430 hr = D3DXLoadMeshHierarchyFromXInMemory(empty_xfile, sizeof(empty_xfile) - 1,
2431 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
2432 ok(hr == E_FAIL, "Expected E_FAIL, got %#x\n", hr);
2433
2434 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1,
2435 D3DXMESH_MANAGED, device, &alloc_hier, NULL, NULL, NULL);
2436 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2437
2438 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1,
2439 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
2440 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2441 if (SUCCEEDED(hr)) {
2442 D3DXMESHCONTAINER *container = frame_hier->pMeshContainer;
2443
2444 ok(frame_hier->Name == NULL, "Expected NULL, got '%s'\n", frame_hier->Name);
2445 D3DXMatrixIdentity(&transform);
2446 check_matrix(&frame_hier->TransformationMatrix, &transform);
2447
2448 ok(!strcmp(container->Name, ""), "Expected '', got '%s'\n", container->Name);
2449 ok(container->MeshData.Type == D3DXMESHTYPE_MESH, "Expected %d, got %d\n",
2450 D3DXMESHTYPE_MESH, container->MeshData.Type);
2451 mesh = U(container->MeshData).pMesh;
2452 check_vertex_buffer(mesh, simple_vertex_buffer, ARRAY_SIZE(simple_vertex_buffer), simple_fvf);
2453 check_index_buffer(mesh, simple_index_buffer, ARRAY_SIZE(simple_index_buffer), sizeof(*simple_index_buffer));
2454 check_materials(container->pMaterials, container->NumMaterials, NULL, 0);
2455 check_generated_effects(container->pMaterials, container->NumMaterials, container->pEffects);
2456 check_generated_adjacency(mesh, container->pAdjacency, 0.0f);
2457 hr = D3DXFrameDestroy(frame_hier, &alloc_hier);
2458 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2459 frame_hier = NULL;
2460 }
2461
2462 controller = (ID3DXAnimationController *)0xdeadbeef;
2463 hr = D3DXLoadMeshHierarchyFromXInMemory(box_anim_xfile, sizeof(box_anim_xfile) - 1,
2464 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, &controller);
2465 todo_wine ok(hr == D3D_OK, "Expected D3D_OK, got %#x.\n", hr);
2466 if (SUCCEEDED(hr))
2467 {
2468 ok(controller != NULL, "Animation Controller NULL.\n");
2469
2470 hr = D3DXFrameDestroy(frame_hier, &alloc_hier);
2471 ok(hr == D3D_OK, "Expected D3D_OK, got %#x.\n", hr);
2472 if (controller)
2473 controller->lpVtbl->Release(controller);
2474
2475 frame_hier = NULL;
2476 }
2477
2478 controller = (ID3DXAnimationController *)0xdeadbeef;
2479 hr = D3DXLoadMeshHierarchyFromXInMemory(box_xfile, sizeof(box_xfile) - 1,
2480 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, &controller);
2481 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2482 if (SUCCEEDED(hr))
2483 {
2484 D3DXMESHCONTAINER *container = frame_hier->pMeshContainer;
2485
2486 ok(!controller, "Animation Controller returned.\n");
2487 ok(frame_hier->Name == NULL, "Expected NULL, got '%s'\n", frame_hier->Name);
2488 D3DXMatrixIdentity(&transform);
2489 check_matrix(&frame_hier->TransformationMatrix, &transform);
2490
2491 ok(!strcmp(container->Name, ""), "Expected '', got '%s'\n", container->Name);
2492 ok(container->MeshData.Type == D3DXMESHTYPE_MESH, "Expected %d, got %d\n",
2493 D3DXMESHTYPE_MESH, container->MeshData.Type);
2494 mesh = U(container->MeshData).pMesh;
2495 check_vertex_buffer(mesh, box_vertex_buffer, ARRAY_SIZE(box_vertex_buffer), box_fvf);
2496 check_index_buffer(mesh, box_index_buffer, ARRAY_SIZE(box_index_buffer), sizeof(*box_index_buffer));
2497 check_materials(container->pMaterials, container->NumMaterials, box_materials, ARRAY_SIZE(box_materials));
2498 check_generated_effects(container->pMaterials, container->NumMaterials, container->pEffects);
2499 check_generated_adjacency(mesh, container->pAdjacency, 0.0f);
2500 hr = D3DXFrameDestroy(frame_hier, &alloc_hier);
2501 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2502 frame_hier = NULL;
2503 }
2504
2505 hr = D3DXLoadMeshHierarchyFromXInMemory(framed_xfile, sizeof(framed_xfile) - 1,
2506 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
2507 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2508 if (SUCCEEDED(hr)) {
2509 D3DXMESHCONTAINER *container = frame_hier->pMeshContainer;
2510 int i;
2511
2512 ok(!strcmp(frame_hier->Name, ""), "Expected '', got '%s'\n", frame_hier->Name);
2513 /* last frame transform replaces the first */
2514 D3DXMatrixIdentity(&transform);
2515 U(transform).m[3][2] = 3.0;
2516 check_matrix(&frame_hier->TransformationMatrix, &transform);
2517
2518 for (i = 0; i < 3; i++) {
2519 ok(!strcmp(container->Name, ""), "Expected '', got '%s'\n", container->Name);
2520 ok(container->MeshData.Type == D3DXMESHTYPE_MESH, "Expected %d, got %d\n",
2521 D3DXMESHTYPE_MESH, container->MeshData.Type);
2522 mesh = U(container->MeshData).pMesh;
2523 check_vertex_buffer(mesh, framed_vertex_buffers[i], ARRAY_SIZE(framed_vertex_buffers[0]), framed_fvf);
2524 check_index_buffer(mesh, framed_index_buffer, ARRAY_SIZE(framed_index_buffer), sizeof(*framed_index_buffer));
2525 check_materials(container->pMaterials, container->NumMaterials, NULL, 0);
2526 check_generated_effects(container->pMaterials, container->NumMaterials, container->pEffects);
2527 check_generated_adjacency(mesh, container->pAdjacency, 0.0f);
2528 container = container->pNextMeshContainer;
2529 }
2530 ok(container == NULL, "Expected NULL, got %p\n", container);
2531 hr = D3DXFrameDestroy(frame_hier, &alloc_hier);
2532 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2533 frame_hier = NULL;
2534 }
2535
2536
2537 hr = D3DXLoadMeshFromXInMemory(NULL, 0, D3DXMESH_MANAGED,
2538 device, NULL, NULL, NULL, NULL, &mesh);
2539 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2540
2541 hr = D3DXLoadMeshFromXInMemory(NULL, sizeof(simple_xfile) - 1, D3DXMESH_MANAGED,
2542 device, NULL, NULL, NULL, NULL, &mesh);
2543 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2544
2545 hr = D3DXLoadMeshFromXInMemory(simple_xfile, 0, D3DXMESH_MANAGED,
2546 device, NULL, NULL, NULL, NULL, &mesh);
2547 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2548
2549 hr = D3DXLoadMeshFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1, D3DXMESH_MANAGED,
2550 device, NULL, NULL, NULL, NULL, NULL);
2551 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2552
2553 hr = D3DXLoadMeshFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1, D3DXMESH_MANAGED,
2554 NULL, NULL, NULL, NULL, NULL, &mesh);
2555 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
2556
2557 hr = D3DXLoadMeshFromXInMemory(empty_xfile, sizeof(empty_xfile) - 1, D3DXMESH_MANAGED,
2558 device, NULL, NULL, NULL, NULL, &mesh);
2559 ok(hr == E_FAIL, "Expected E_FAIL, got %#x\n", hr);
2560
2561 hr = D3DXLoadMeshFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1, D3DXMESH_MANAGED,
2562 device, NULL, NULL, NULL, NULL, &mesh);
2563 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
2564 if (SUCCEEDED(hr))
2565 IUnknown_Release(mesh);
2566
2567 test_LoadMeshFromX(device, simple_xfile, simple_vertex_buffer, simple_fvf, simple_index_buffer, default_materials, TRUE);
2568 test_LoadMeshFromX(device, box_xfile, box_vertex_buffer, box_fvf, box_index_buffer, box_materials, TRUE);
2569 test_LoadMeshFromX(device, framed_xfile, merged_vertex_buffer, framed_fvf, merged_index_buffer, default_materials, FALSE);
2570
2571 free_test_context(test_context);
2572 }
2573
compute_box(struct mesh * mesh,float width,float height,float depth)2574 static BOOL compute_box(struct mesh *mesh, float width, float height, float depth)
2575 {
2576 unsigned int i, face;
2577 static const D3DXVECTOR3 unit_box[] =
2578 {
2579 {-1.0f, -1.0f, -1.0f}, {-1.0f, -1.0f, 1.0f}, {-1.0f, 1.0f, 1.0f}, {-1.0f, 1.0f, -1.0f},
2580 {-1.0f, 1.0f, -1.0f}, {-1.0f, 1.0f, 1.0f}, { 1.0f, 1.0f, 1.0f}, { 1.0f, 1.0f, -1.0f},
2581 { 1.0f, 1.0f, -1.0f}, { 1.0f, 1.0f, 1.0f}, { 1.0f, -1.0f, 1.0f}, { 1.0f, -1.0f, -1.0f},
2582 {-1.0f, -1.0f, 1.0f}, {-1.0f, -1.0f, -1.0f}, { 1.0f, -1.0f, -1.0f}, { 1.0f, -1.0f, 1.0f},
2583 {-1.0f, -1.0f, 1.0f}, { 1.0f, -1.0f, 1.0f}, { 1.0f, 1.0f, 1.0f}, {-1.0f, 1.0f, 1.0f},
2584 {-1.0f, -1.0f, -1.0f}, {-1.0f, 1.0f, -1.0f}, { 1.0f, 1.0f, -1.0f}, { 1.0f, -1.0f, -1.0f}
2585 };
2586 static const D3DXVECTOR3 normals[] =
2587 {
2588 {-1.0f, 0.0f, 0.0f}, { 0.0f, 1.0f, 0.0f}, { 1.0f, 0.0f, 0.0f},
2589 { 0.0f, -1.0f, 0.0f}, { 0.0f, 0.0f, 1.0f}, { 0.0f, 0.0f, -1.0f}
2590 };
2591
2592 if (!new_mesh(mesh, 24, 12))
2593 {
2594 return FALSE;
2595 }
2596
2597 width /= 2.0f;
2598 height /= 2.0f;
2599 depth /= 2.0f;
2600
2601 for (i = 0; i < 24; i++)
2602 {
2603 mesh->vertices[i].position.x = width * unit_box[i].x;
2604 mesh->vertices[i].position.y = height * unit_box[i].y;
2605 mesh->vertices[i].position.z = depth * unit_box[i].z;
2606 mesh->vertices[i].normal.x = normals[i / 4].x;
2607 mesh->vertices[i].normal.y = normals[i / 4].y;
2608 mesh->vertices[i].normal.z = normals[i / 4].z;
2609 }
2610
2611 face = 0;
2612 for (i = 0; i < 12; i++)
2613 {
2614 mesh->faces[i][0] = face++;
2615 mesh->faces[i][1] = face++;
2616 mesh->faces[i][2] = (i % 2) ? face - 4 : face;
2617 }
2618
2619 return TRUE;
2620 }
2621
test_box(IDirect3DDevice9 * device,float width,float height,float depth)2622 static void test_box(IDirect3DDevice9 *device, float width, float height, float depth)
2623 {
2624 HRESULT hr;
2625 ID3DXMesh *box;
2626 struct mesh mesh;
2627 char name[256];
2628
2629 hr = D3DXCreateBox(device, width, height, depth, &box, NULL);
2630 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
2631 if (hr != D3D_OK)
2632 {
2633 skip("Couldn't create box\n");
2634 return;
2635 }
2636
2637 if (!compute_box(&mesh, width, height, depth))
2638 {
2639 skip("Couldn't create mesh\n");
2640 box->lpVtbl->Release(box);
2641 return;
2642 }
2643
2644 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
2645
2646 sprintf(name, "box (%g, %g, %g)", width, height, depth);
2647 compare_mesh(name, box, &mesh);
2648
2649 free_mesh(&mesh);
2650
2651 box->lpVtbl->Release(box);
2652 }
D3DXCreateBoxTest(void)2653 static void D3DXCreateBoxTest(void)
2654 {
2655 HRESULT hr;
2656 IDirect3DDevice9* device;
2657 ID3DXMesh* box;
2658 ID3DXBuffer* ppBuffer;
2659 DWORD *buffer;
2660 static const DWORD adjacency[36]=
2661 {6, 9, 1, 2, 10, 0,
2662 1, 9, 3, 4, 10, 2,
2663 3, 8, 5, 7, 11, 4,
2664 0, 11, 7, 5, 8, 6,
2665 7, 4, 9, 2, 0, 8,
2666 1, 3, 11, 5, 6, 10};
2667 unsigned int i;
2668 struct test_context *test_context;
2669
2670 if (!(test_context = new_test_context()))
2671 {
2672 skip("Couldn't create test context\n");
2673 return;
2674 }
2675 device = test_context->device;
2676
2677 hr = D3DXCreateBox(device,2.0f,20.0f,4.9f,NULL, &ppBuffer);
2678 ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2679
2680 hr = D3DXCreateBox(NULL,22.0f,20.0f,4.9f,&box, &ppBuffer);
2681 ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2682
2683 hr = D3DXCreateBox(device,-2.0f,20.0f,4.9f,&box, &ppBuffer);
2684 ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2685
2686 hr = D3DXCreateBox(device,22.0f,-20.0f,4.9f,&box, &ppBuffer);
2687 ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2688
2689 hr = D3DXCreateBox(device,22.0f,20.0f,-4.9f,&box, &ppBuffer);
2690 ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2691
2692 ppBuffer = NULL;
2693 hr = D3DXCreateBox(device,10.9f,20.0f,4.9f,&box, &ppBuffer);
2694 ok(hr==D3D_OK, "Expected D3D_OK, received %#x\n", hr);
2695
2696 buffer = ID3DXBuffer_GetBufferPointer(ppBuffer);
2697 for(i=0; i<36; i++)
2698 ok(adjacency[i]==buffer[i], "expected adjacency %d: %#x, received %#x\n",i,adjacency[i], buffer[i]);
2699
2700 box->lpVtbl->Release(box);
2701 ID3DXBuffer_Release(ppBuffer);
2702
2703 test_box(device, 10.9f, 20.0f, 4.9f);
2704
2705 free_test_context(test_context);
2706 }
2707
compute_polygon(struct mesh * mesh,float length,unsigned int sides)2708 static BOOL compute_polygon(struct mesh *mesh, float length, unsigned int sides)
2709 {
2710 unsigned int i;
2711 float angle, scale;
2712
2713 if (!new_mesh(mesh, sides + 1, sides))
2714 return FALSE;
2715
2716 angle = D3DX_PI / sides;
2717 scale = 0.5f * length / sinf(angle);
2718 angle *= 2.0f;
2719
2720 mesh->vertices[0].position.x = 0.0f;
2721 mesh->vertices[0].position.y = 0.0f;
2722 mesh->vertices[0].position.z = 0.0f;
2723 mesh->vertices[0].normal.x = 0.0f;
2724 mesh->vertices[0].normal.y = 0.0f;
2725 mesh->vertices[0].normal.z = 1.0f;
2726
2727 for (i = 0; i < sides; ++i)
2728 {
2729 mesh->vertices[i + 1].position.x = cosf(angle * i) * scale;
2730 mesh->vertices[i + 1].position.y = sinf(angle * i) * scale;
2731 mesh->vertices[i + 1].position.z = 0.0f;
2732 mesh->vertices[i + 1].normal.x = 0.0f;
2733 mesh->vertices[i + 1].normal.y = 0.0f;
2734 mesh->vertices[i + 1].normal.z = 1.0f;
2735
2736 mesh->faces[i][0] = 0;
2737 mesh->faces[i][1] = i + 1;
2738 mesh->faces[i][2] = i + 2;
2739 }
2740
2741 mesh->faces[sides - 1][2] = 1;
2742
2743 return TRUE;
2744 }
2745
test_polygon(IDirect3DDevice9 * device,float length,unsigned int sides)2746 static void test_polygon(IDirect3DDevice9 *device, float length, unsigned int sides)
2747 {
2748 HRESULT hr;
2749 ID3DXMesh *polygon;
2750 struct mesh mesh;
2751 char name[64];
2752
2753 hr = D3DXCreatePolygon(device, length, sides, &polygon, NULL);
2754 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
2755 if (hr != D3D_OK)
2756 {
2757 skip("Couldn't create polygon\n");
2758 return;
2759 }
2760
2761 if (!compute_polygon(&mesh, length, sides))
2762 {
2763 skip("Couldn't create mesh\n");
2764 polygon->lpVtbl->Release(polygon);
2765 return;
2766 }
2767
2768 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
2769
2770 sprintf(name, "polygon (%g, %u)", length, sides);
2771 compare_mesh(name, polygon, &mesh);
2772
2773 free_mesh(&mesh);
2774
2775 polygon->lpVtbl->Release(polygon);
2776 }
2777
D3DXCreatePolygonTest(void)2778 static void D3DXCreatePolygonTest(void)
2779 {
2780 HRESULT hr;
2781 IDirect3DDevice9 *device;
2782 ID3DXMesh *polygon;
2783 ID3DXBuffer *adjacency;
2784 DWORD (*buffer)[3], buffer_size;
2785 unsigned int i;
2786 struct test_context *test_context;
2787
2788 if (!(test_context = new_test_context()))
2789 {
2790 skip("Couldn't create test context\n");
2791 return;
2792 }
2793 device = test_context->device;
2794
2795 hr = D3DXCreatePolygon(device, 2.0f, 11, NULL, &adjacency);
2796 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2797
2798 hr = D3DXCreatePolygon(NULL, 2.0f, 11, &polygon, &adjacency);
2799 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2800
2801 hr = D3DXCreatePolygon(device, -2.0f, 11, &polygon, &adjacency);
2802 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2803
2804 polygon = (void *)0xdeadbeef;
2805 adjacency = (void *)0xdeadbeef;
2806 hr = D3DXCreatePolygon(device, 2.0f, 0, &polygon, &adjacency);
2807 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2808 ok(polygon == (void *)0xdeadbeef, "Polygon was changed to %p\n", polygon);
2809 ok(adjacency == (void *)0xdeadbeef, "Adjacency was changed to %p\n", adjacency);
2810
2811 hr = D3DXCreatePolygon(device, 2.0f, 2, &polygon, &adjacency);
2812 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr);
2813
2814 adjacency = NULL;
2815 hr = D3DXCreatePolygon(device, 3.0f, 11, &polygon, &adjacency);
2816 ok(hr == D3D_OK, "Expected D3D_OK, received %#x\n", hr);
2817
2818 buffer_size = ID3DXBuffer_GetBufferSize(adjacency);
2819 ok(buffer_size == 33 * sizeof(DWORD), "Wrong adjacency buffer size %u\n", buffer_size);
2820
2821 buffer = ID3DXBuffer_GetBufferPointer(adjacency);
2822 for (i = 0; i < 11; ++i)
2823 {
2824 ok(buffer[i][0] == (i + 10) % 11, "Wrong adjacency[%d][0] = %u\n", i, buffer[i][0]);
2825 ok(buffer[i][1] == ~0U, "Wrong adjacency[%d][1] = %u\n", i, buffer[i][1]);
2826 ok(buffer[i][2] == (i + 1) % 11, "Wrong adjacency[%d][2] = %u\n", i, buffer[i][2]);
2827 }
2828
2829 polygon->lpVtbl->Release(polygon);
2830 ID3DXBuffer_Release(adjacency);
2831
2832 test_polygon(device, 2.0f, 3);
2833 test_polygon(device, 10.0f, 3);
2834 test_polygon(device, 10.0f, 5);
2835 test_polygon(device, 10.0f, 10);
2836 test_polygon(device, 20.0f, 10);
2837 test_polygon(device, 20.0f, 32000);
2838
2839 free_test_context(test_context);
2840 }
2841
2842 struct sincos_table
2843 {
2844 float *sin;
2845 float *cos;
2846 };
2847
free_sincos_table(struct sincos_table * sincos_table)2848 static void free_sincos_table(struct sincos_table *sincos_table)
2849 {
2850 HeapFree(GetProcessHeap(), 0, sincos_table->cos);
2851 HeapFree(GetProcessHeap(), 0, sincos_table->sin);
2852 }
2853
2854 /* pre compute sine and cosine tables; caller must free */
compute_sincos_table(struct sincos_table * sincos_table,float angle_start,float angle_step,int n)2855 static BOOL compute_sincos_table(struct sincos_table *sincos_table, float angle_start, float angle_step, int n)
2856 {
2857 float angle;
2858 int i;
2859
2860 sincos_table->sin = HeapAlloc(GetProcessHeap(), 0, n * sizeof(*sincos_table->sin));
2861 if (!sincos_table->sin)
2862 {
2863 return FALSE;
2864 }
2865 sincos_table->cos = HeapAlloc(GetProcessHeap(), 0, n * sizeof(*sincos_table->cos));
2866 if (!sincos_table->cos)
2867 {
2868 HeapFree(GetProcessHeap(), 0, sincos_table->sin);
2869 return FALSE;
2870 }
2871
2872 angle = angle_start;
2873 for (i = 0; i < n; i++)
2874 {
2875 sincos_table->sin[i] = sin(angle);
2876 sincos_table->cos[i] = cos(angle);
2877 angle += angle_step;
2878 }
2879
2880 return TRUE;
2881 }
2882
vertex_index(UINT slices,int slice,int stack)2883 static WORD vertex_index(UINT slices, int slice, int stack)
2884 {
2885 return stack*slices+slice+1;
2886 }
2887
2888 /* slices = subdivisions along xy plane, stacks = subdivisions along z axis */
compute_sphere(struct mesh * mesh,FLOAT radius,UINT slices,UINT stacks)2889 static BOOL compute_sphere(struct mesh *mesh, FLOAT radius, UINT slices, UINT stacks)
2890 {
2891 float theta_step, theta_start;
2892 struct sincos_table theta;
2893 float phi_step, phi_start;
2894 struct sincos_table phi;
2895 DWORD number_of_vertices, number_of_faces;
2896 DWORD vertex, face;
2897 int slice, stack;
2898
2899 /* theta = angle on xy plane wrt x axis */
2900 theta_step = D3DX_PI / stacks;
2901 theta_start = theta_step;
2902
2903 /* phi = angle on xz plane wrt z axis */
2904 phi_step = -2 * D3DX_PI / slices;
2905 phi_start = D3DX_PI / 2;
2906
2907 if (!compute_sincos_table(&theta, theta_start, theta_step, stacks))
2908 {
2909 return FALSE;
2910 }
2911 if (!compute_sincos_table(&phi, phi_start, phi_step, slices))
2912 {
2913 free_sincos_table(&theta);
2914 return FALSE;
2915 }
2916
2917 number_of_vertices = 2 + slices * (stacks-1);
2918 number_of_faces = 2 * slices + (stacks - 2) * (2 * slices);
2919
2920 if (!new_mesh(mesh, number_of_vertices, number_of_faces))
2921 {
2922 free_sincos_table(&phi);
2923 free_sincos_table(&theta);
2924 return FALSE;
2925 }
2926
2927 vertex = 0;
2928 face = 0;
2929
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 mesh->vertices[vertex].position.x = 0.0f;
2934 mesh->vertices[vertex].position.y = 0.0f;
2935 mesh->vertices[vertex].position.z = radius;
2936 vertex++;
2937
2938 for (stack = 0; stack < stacks - 1; stack++)
2939 {
2940 for (slice = 0; slice < slices; slice++)
2941 {
2942 mesh->vertices[vertex].normal.x = theta.sin[stack] * phi.cos[slice];
2943 mesh->vertices[vertex].normal.y = theta.sin[stack] * phi.sin[slice];
2944 mesh->vertices[vertex].normal.z = theta.cos[stack];
2945 mesh->vertices[vertex].position.x = radius * theta.sin[stack] * phi.cos[slice];
2946 mesh->vertices[vertex].position.y = radius * theta.sin[stack] * phi.sin[slice];
2947 mesh->vertices[vertex].position.z = radius * theta.cos[stack];
2948 vertex++;
2949
2950 if (slice > 0)
2951 {
2952 if (stack == 0)
2953 {
2954 /* top stack is triangle fan */
2955 mesh->faces[face][0] = 0;
2956 mesh->faces[face][1] = slice + 1;
2957 mesh->faces[face][2] = slice;
2958 face++;
2959 }
2960 else
2961 {
2962 /* stacks in between top and bottom are quad strips */
2963 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
2964 mesh->faces[face][1] = vertex_index(slices, slice, stack-1);
2965 mesh->faces[face][2] = vertex_index(slices, slice-1, stack);
2966 face++;
2967
2968 mesh->faces[face][0] = vertex_index(slices, slice, stack-1);
2969 mesh->faces[face][1] = vertex_index(slices, slice, stack);
2970 mesh->faces[face][2] = vertex_index(slices, slice-1, stack);
2971 face++;
2972 }
2973 }
2974 }
2975
2976 if (stack == 0)
2977 {
2978 mesh->faces[face][0] = 0;
2979 mesh->faces[face][1] = 1;
2980 mesh->faces[face][2] = slice;
2981 face++;
2982 }
2983 else
2984 {
2985 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
2986 mesh->faces[face][1] = vertex_index(slices, 0, stack-1);
2987 mesh->faces[face][2] = vertex_index(slices, slice-1, stack);
2988 face++;
2989
2990 mesh->faces[face][0] = vertex_index(slices, 0, stack-1);
2991 mesh->faces[face][1] = vertex_index(slices, 0, stack);
2992 mesh->faces[face][2] = vertex_index(slices, slice-1, stack);
2993 face++;
2994 }
2995 }
2996
2997 mesh->vertices[vertex].position.x = 0.0f;
2998 mesh->vertices[vertex].position.y = 0.0f;
2999 mesh->vertices[vertex].position.z = -radius;
3000 mesh->vertices[vertex].normal.x = 0.0f;
3001 mesh->vertices[vertex].normal.y = 0.0f;
3002 mesh->vertices[vertex].normal.z = -1.0f;
3003
3004 /* bottom stack is triangle fan */
3005 for (slice = 1; slice < slices; slice++)
3006 {
3007 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
3008 mesh->faces[face][1] = vertex_index(slices, slice, stack-1);
3009 mesh->faces[face][2] = vertex;
3010 face++;
3011 }
3012
3013 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
3014 mesh->faces[face][1] = vertex_index(slices, 0, stack-1);
3015 mesh->faces[face][2] = vertex;
3016
3017 free_sincos_table(&phi);
3018 free_sincos_table(&theta);
3019
3020 return TRUE;
3021 }
3022
test_sphere(IDirect3DDevice9 * device,FLOAT radius,UINT slices,UINT stacks)3023 static void test_sphere(IDirect3DDevice9 *device, FLOAT radius, UINT slices, UINT stacks)
3024 {
3025 HRESULT hr;
3026 ID3DXMesh *sphere;
3027 struct mesh mesh;
3028 char name[256];
3029
3030 hr = D3DXCreateSphere(device, radius, slices, stacks, &sphere, NULL);
3031 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
3032 if (hr != D3D_OK)
3033 {
3034 skip("Couldn't create sphere\n");
3035 return;
3036 }
3037
3038 if (!compute_sphere(&mesh, radius, slices, stacks))
3039 {
3040 skip("Couldn't create mesh\n");
3041 sphere->lpVtbl->Release(sphere);
3042 return;
3043 }
3044
3045 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
3046
3047 sprintf(name, "sphere (%g, %u, %u)", radius, slices, stacks);
3048 compare_mesh(name, sphere, &mesh);
3049
3050 free_mesh(&mesh);
3051
3052 sphere->lpVtbl->Release(sphere);
3053 }
3054
D3DXCreateSphereTest(void)3055 static void D3DXCreateSphereTest(void)
3056 {
3057 HRESULT hr;
3058 IDirect3DDevice9* device;
3059 ID3DXMesh* sphere = NULL;
3060 struct test_context *test_context;
3061
3062 hr = D3DXCreateSphere(NULL, 0.0f, 0, 0, NULL, NULL);
3063 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3064
3065 hr = D3DXCreateSphere(NULL, 0.1f, 0, 0, NULL, NULL);
3066 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3067
3068 hr = D3DXCreateSphere(NULL, 0.0f, 1, 0, NULL, NULL);
3069 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3070
3071 hr = D3DXCreateSphere(NULL, 0.0f, 0, 1, NULL, NULL);
3072 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3073
3074 if (!(test_context = new_test_context()))
3075 {
3076 skip("Couldn't create test context\n");
3077 return;
3078 }
3079 device = test_context->device;
3080
3081 hr = D3DXCreateSphere(device, 1.0f, 1, 1, &sphere, NULL);
3082 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3083
3084 hr = D3DXCreateSphere(device, 1.0f, 2, 1, &sphere, NULL);
3085 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
3086
3087 hr = D3DXCreateSphere(device, 1.0f, 1, 2, &sphere, NULL);
3088 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
3089
3090 hr = D3DXCreateSphere(device, -0.1f, 1, 2, &sphere, NULL);
3091 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
3092
3093 test_sphere(device, 0.0f, 2, 2);
3094 test_sphere(device, 1.0f, 2, 2);
3095 test_sphere(device, 1.0f, 3, 2);
3096 test_sphere(device, 1.0f, 4, 4);
3097 test_sphere(device, 1.0f, 3, 4);
3098 test_sphere(device, 5.0f, 6, 7);
3099 test_sphere(device, 10.0f, 11, 12);
3100
3101 free_test_context(test_context);
3102 }
3103
compute_cylinder(struct mesh * mesh,FLOAT radius1,FLOAT radius2,FLOAT length,UINT slices,UINT stacks)3104 static BOOL compute_cylinder(struct mesh *mesh, FLOAT radius1, FLOAT radius2, FLOAT length, UINT slices, UINT stacks)
3105 {
3106 float theta_step, theta_start;
3107 struct sincos_table theta;
3108 FLOAT delta_radius, radius, radius_step;
3109 FLOAT z, z_step, z_normal;
3110 DWORD number_of_vertices, number_of_faces;
3111 DWORD vertex, face;
3112 int slice, stack;
3113
3114 /* theta = angle on xy plane wrt x axis */
3115 theta_step = -2 * D3DX_PI / slices;
3116 theta_start = D3DX_PI / 2;
3117
3118 if (!compute_sincos_table(&theta, theta_start, theta_step, slices))
3119 {
3120 return FALSE;
3121 }
3122
3123 number_of_vertices = 2 + (slices * (3 + stacks));
3124 number_of_faces = 2 * slices + stacks * (2 * slices);
3125
3126 if (!new_mesh(mesh, number_of_vertices, number_of_faces))
3127 {
3128 free_sincos_table(&theta);
3129 return FALSE;
3130 }
3131
3132 vertex = 0;
3133 face = 0;
3134
3135 delta_radius = radius1 - radius2;
3136 radius = radius1;
3137 radius_step = delta_radius / stacks;
3138
3139 z = -length / 2;
3140 z_step = length / stacks;
3141 z_normal = delta_radius / length;
3142 if (isnan(z_normal))
3143 {
3144 z_normal = 0.0f;
3145 }
3146
3147 mesh->vertices[vertex].normal.x = 0.0f;
3148 mesh->vertices[vertex].normal.y = 0.0f;
3149 mesh->vertices[vertex].normal.z = -1.0f;
3150 mesh->vertices[vertex].position.x = 0.0f;
3151 mesh->vertices[vertex].position.y = 0.0f;
3152 mesh->vertices[vertex++].position.z = z;
3153
3154 for (slice = 0; slice < slices; slice++, vertex++)
3155 {
3156 mesh->vertices[vertex].normal.x = 0.0f;
3157 mesh->vertices[vertex].normal.y = 0.0f;
3158 mesh->vertices[vertex].normal.z = -1.0f;
3159 mesh->vertices[vertex].position.x = radius * theta.cos[slice];
3160 mesh->vertices[vertex].position.y = radius * theta.sin[slice];
3161 mesh->vertices[vertex].position.z = z;
3162
3163 if (slice > 0)
3164 {
3165 mesh->faces[face][0] = 0;
3166 mesh->faces[face][1] = slice;
3167 mesh->faces[face++][2] = slice + 1;
3168 }
3169 }
3170
3171 mesh->faces[face][0] = 0;
3172 mesh->faces[face][1] = slice;
3173 mesh->faces[face++][2] = 1;
3174
3175 for (stack = 1; stack <= stacks+1; stack++)
3176 {
3177 for (slice = 0; slice < slices; slice++, vertex++)
3178 {
3179 mesh->vertices[vertex].normal.x = theta.cos[slice];
3180 mesh->vertices[vertex].normal.y = theta.sin[slice];
3181 mesh->vertices[vertex].normal.z = z_normal;
3182 D3DXVec3Normalize(&mesh->vertices[vertex].normal, &mesh->vertices[vertex].normal);
3183 mesh->vertices[vertex].position.x = radius * theta.cos[slice];
3184 mesh->vertices[vertex].position.y = radius * theta.sin[slice];
3185 mesh->vertices[vertex].position.z = z;
3186
3187 if (stack > 1 && slice > 0)
3188 {
3189 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
3190 mesh->faces[face][1] = vertex_index(slices, slice-1, stack);
3191 mesh->faces[face++][2] = vertex_index(slices, slice, stack-1);
3192
3193 mesh->faces[face][0] = vertex_index(slices, slice, stack-1);
3194 mesh->faces[face][1] = vertex_index(slices, slice-1, stack);
3195 mesh->faces[face++][2] = vertex_index(slices, slice, stack);
3196 }
3197 }
3198
3199 if (stack > 1)
3200 {
3201 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
3202 mesh->faces[face][1] = vertex_index(slices, slice-1, stack);
3203 mesh->faces[face++][2] = vertex_index(slices, 0, stack-1);
3204
3205 mesh->faces[face][0] = vertex_index(slices, 0, stack-1);
3206 mesh->faces[face][1] = vertex_index(slices, slice-1, stack);
3207 mesh->faces[face++][2] = vertex_index(slices, 0, stack);
3208 }
3209
3210 if (stack < stacks + 1)
3211 {
3212 z += z_step;
3213 radius -= radius_step;
3214 }
3215 }
3216
3217 for (slice = 0; slice < slices; slice++, vertex++)
3218 {
3219 mesh->vertices[vertex].normal.x = 0.0f;
3220 mesh->vertices[vertex].normal.y = 0.0f;
3221 mesh->vertices[vertex].normal.z = 1.0f;
3222 mesh->vertices[vertex].position.x = radius * theta.cos[slice];
3223 mesh->vertices[vertex].position.y = radius * theta.sin[slice];
3224 mesh->vertices[vertex].position.z = z;
3225
3226 if (slice > 0)
3227 {
3228 mesh->faces[face][0] = vertex_index(slices, slice-1, stack);
3229 mesh->faces[face][1] = number_of_vertices - 1;
3230 mesh->faces[face++][2] = vertex_index(slices, slice, stack);
3231 }
3232 }
3233
3234 mesh->vertices[vertex].position.x = 0.0f;
3235 mesh->vertices[vertex].position.y = 0.0f;
3236 mesh->vertices[vertex].position.z = z;
3237 mesh->vertices[vertex].normal.x = 0.0f;
3238 mesh->vertices[vertex].normal.y = 0.0f;
3239 mesh->vertices[vertex].normal.z = 1.0f;
3240
3241 mesh->faces[face][0] = vertex_index(slices, slice-1, stack);
3242 mesh->faces[face][1] = number_of_vertices - 1;
3243 mesh->faces[face][2] = vertex_index(slices, 0, stack);
3244
3245 free_sincos_table(&theta);
3246
3247 return TRUE;
3248 }
3249
test_cylinder(IDirect3DDevice9 * device,FLOAT radius1,FLOAT radius2,FLOAT length,UINT slices,UINT stacks)3250 static void test_cylinder(IDirect3DDevice9 *device, FLOAT radius1, FLOAT radius2, FLOAT length, UINT slices, UINT stacks)
3251 {
3252 HRESULT hr;
3253 ID3DXMesh *cylinder;
3254 struct mesh mesh;
3255 char name[256];
3256
3257 hr = D3DXCreateCylinder(device, radius1, radius2, length, slices, stacks, &cylinder, NULL);
3258 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
3259 if (hr != D3D_OK)
3260 {
3261 skip("Couldn't create cylinder\n");
3262 return;
3263 }
3264
3265 if (!compute_cylinder(&mesh, radius1, radius2, length, slices, stacks))
3266 {
3267 skip("Couldn't create mesh\n");
3268 cylinder->lpVtbl->Release(cylinder);
3269 return;
3270 }
3271
3272 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
3273
3274 sprintf(name, "cylinder (%g, %g, %g, %u, %u)", radius1, radius2, length, slices, stacks);
3275 compare_mesh(name, cylinder, &mesh);
3276
3277 free_mesh(&mesh);
3278
3279 cylinder->lpVtbl->Release(cylinder);
3280 }
3281
D3DXCreateCylinderTest(void)3282 static void D3DXCreateCylinderTest(void)
3283 {
3284 HRESULT hr;
3285 IDirect3DDevice9* device;
3286 ID3DXMesh* cylinder = NULL;
3287 struct test_context *test_context;
3288
3289 hr = D3DXCreateCylinder(NULL, 0.0f, 0.0f, 0.0f, 0, 0, NULL, NULL);
3290 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3291
3292 hr = D3DXCreateCylinder(NULL, 1.0f, 1.0f, 1.0f, 2, 1, &cylinder, NULL);
3293 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3294
3295 if (!(test_context = new_test_context()))
3296 {
3297 skip("Couldn't create test context\n");
3298 return;
3299 }
3300 device = test_context->device;
3301
3302 hr = D3DXCreateCylinder(device, -0.1f, 1.0f, 1.0f, 2, 1, &cylinder, NULL);
3303 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3304
3305 hr = D3DXCreateCylinder(device, 0.0f, 1.0f, 1.0f, 2, 1, &cylinder, NULL);
3306 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n",hr);
3307
3308 if (SUCCEEDED(hr) && cylinder)
3309 {
3310 cylinder->lpVtbl->Release(cylinder);
3311 }
3312
3313 hr = D3DXCreateCylinder(device, 1.0f, -0.1f, 1.0f, 2, 1, &cylinder, NULL);
3314 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3315
3316 hr = D3DXCreateCylinder(device, 1.0f, 0.0f, 1.0f, 2, 1, &cylinder, NULL);
3317 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n",hr);
3318
3319 if (SUCCEEDED(hr) && cylinder)
3320 {
3321 cylinder->lpVtbl->Release(cylinder);
3322 }
3323
3324 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, -0.1f, 2, 1, &cylinder, NULL);
3325 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3326
3327 /* Test with length == 0.0f succeeds */
3328 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, 0.0f, 2, 1, &cylinder, NULL);
3329 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n",hr);
3330
3331 if (SUCCEEDED(hr) && cylinder)
3332 {
3333 cylinder->lpVtbl->Release(cylinder);
3334 }
3335
3336 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, 1.0f, 1, 1, &cylinder, NULL);
3337 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3338
3339 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, 1.0f, 2, 0, &cylinder, NULL);
3340 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3341
3342 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, 1.0f, 2, 1, NULL, NULL);
3343 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
3344
3345 test_cylinder(device, 0.0f, 0.0f, 0.0f, 2, 1);
3346 test_cylinder(device, 1.0f, 1.0f, 1.0f, 2, 1);
3347 test_cylinder(device, 1.0f, 1.0f, 2.0f, 3, 4);
3348 test_cylinder(device, 3.0f, 2.0f, 4.0f, 3, 4);
3349 test_cylinder(device, 2.0f, 3.0f, 4.0f, 3, 4);
3350 test_cylinder(device, 3.0f, 4.0f, 5.0f, 11, 20);
3351
3352 free_test_context(test_context);
3353 }
3354
compute_torus(struct mesh * mesh,float innerradius,float outerradius,UINT sides,UINT rings)3355 static BOOL compute_torus(struct mesh *mesh, float innerradius, float outerradius, UINT sides, UINT rings)
3356 {
3357 float phi, phi_step, sin_phi, cos_phi;
3358 float theta, theta_step, sin_theta, cos_theta;
3359 unsigned int numvert, numfaces, i, j;
3360
3361 numvert = sides * rings;
3362 numfaces = numvert * 2;
3363
3364 if (!new_mesh(mesh, numvert, numfaces))
3365 return FALSE;
3366
3367 phi_step = D3DX_PI / sides * 2.0f;
3368 theta_step = D3DX_PI / rings * -2.0f;
3369
3370 theta = 0.0f;
3371
3372 for (i = 0; i < rings; ++i)
3373 {
3374 phi = 0.0f;
3375
3376 cos_theta = cosf(theta);
3377 sin_theta = sinf(theta);
3378
3379 for (j = 0; j < sides; ++j)
3380 {
3381 sin_phi = sinf(phi);
3382 cos_phi = cosf(phi);
3383
3384 mesh->vertices[i * sides + j].position.x = (innerradius * cos_phi + outerradius) * cos_theta;
3385 mesh->vertices[i * sides + j].position.y = (innerradius * cos_phi + outerradius) * sin_theta;
3386 mesh->vertices[i * sides + j].position.z = innerradius * sin_phi;
3387 mesh->vertices[i * sides + j].normal.x = cos_phi * cos_theta;
3388 mesh->vertices[i * sides + j].normal.y = cos_phi * sin_theta;
3389 mesh->vertices[i * sides + j].normal.z = sin_phi;
3390
3391 phi += phi_step;
3392 }
3393
3394 theta += theta_step;
3395 }
3396
3397 for (i = 0; i < numfaces - sides * 2; ++i)
3398 {
3399 mesh->faces[i][0] = i % 2 ? i / 2 + sides : i / 2;
3400 mesh->faces[i][1] = (i / 2 + 1) % sides ? i / 2 + 1 : i / 2 + 1 - sides;
3401 mesh->faces[i][2] = (i + 1) % (sides * 2) ? (i + 1) / 2 + sides : (i + 1) / 2;
3402 }
3403
3404 for (j = 0; i < numfaces; ++i, ++j)
3405 {
3406 mesh->faces[i][0] = i % 2 ? j / 2 : i / 2;
3407 mesh->faces[i][1] = (i / 2 + 1) % sides ? i / 2 + 1 : i / 2 + 1 - sides;
3408 mesh->faces[i][2] = i == numfaces - 1 ? 0 : (j + 1) / 2;
3409 }
3410
3411 return TRUE;
3412 }
3413
test_torus(IDirect3DDevice9 * device,float innerradius,float outerradius,UINT sides,UINT rings)3414 static void test_torus(IDirect3DDevice9 *device, float innerradius, float outerradius, UINT sides, UINT rings)
3415 {
3416 HRESULT hr;
3417 ID3DXMesh *torus;
3418 struct mesh mesh;
3419 char name[256];
3420
3421 hr = D3DXCreateTorus(device, innerradius, outerradius, sides, rings, &torus, NULL);
3422 ok(hr == D3D_OK, "Got result %#x, expected 0 (D3D_OK)\n", hr);
3423 if (hr != D3D_OK)
3424 {
3425 skip("Couldn't create torus\n");
3426 return;
3427 }
3428
3429 if (!compute_torus(&mesh, innerradius, outerradius, sides, rings))
3430 {
3431 skip("Couldn't create mesh\n");
3432 torus->lpVtbl->Release(torus);
3433 return;
3434 }
3435
3436 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
3437
3438 sprintf(name, "torus (%g, %g, %u, %u)", innerradius, outerradius, sides, rings);
3439 compare_mesh(name, torus, &mesh);
3440
3441 free_mesh(&mesh);
3442
3443 torus->lpVtbl->Release(torus);
3444 }
3445
D3DXCreateTorusTest(void)3446 static void D3DXCreateTorusTest(void)
3447 {
3448 HRESULT hr;
3449 IDirect3DDevice9* device;
3450 ID3DXMesh* torus = NULL;
3451 struct test_context *test_context;
3452
3453 if (!(test_context = new_test_context()))
3454 {
3455 skip("Couldn't create test context\n");
3456 return;
3457 }
3458 device = test_context->device;
3459
3460 hr = D3DXCreateTorus(NULL, 0.0f, 0.0f, 3, 3, &torus, NULL);
3461 ok(hr == D3DERR_INVALIDCALL, "Got result %#x, expected %#x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
3462
3463 hr = D3DXCreateTorus(device, -1.0f, 0.0f, 3, 3, &torus, NULL);
3464 ok(hr == D3DERR_INVALIDCALL, "Got result %#x, expected %#x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
3465
3466 hr = D3DXCreateTorus(device, 0.0f, -1.0f, 3, 3, &torus, NULL);
3467 ok(hr == D3DERR_INVALIDCALL, "Got result %#x, expected %#x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
3468
3469 hr = D3DXCreateTorus(device, 0.0f, 0.0f, 2, 3, &torus, NULL);
3470 ok(hr == D3DERR_INVALIDCALL, "Got result %#x, expected %#x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
3471
3472 hr = D3DXCreateTorus(device, 0.0f, 0.0f, 3, 2, &torus, NULL);
3473 ok(hr == D3DERR_INVALIDCALL, "Got result %#x, expected %#x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
3474
3475 hr = D3DXCreateTorus(device, 0.0f, 0.0f, 3, 3, NULL, NULL);
3476 ok(hr == D3DERR_INVALIDCALL, "Got result %#x, expected %#x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
3477
3478 test_torus(device, 0.0f, 0.0f, 3, 3);
3479 test_torus(device, 1.0f, 1.0f, 3, 3);
3480 test_torus(device, 1.0f, 1.0f, 32, 64);
3481 test_torus(device, 0.0f, 1.0f, 5, 5);
3482 test_torus(device, 1.0f, 0.0f, 5, 5);
3483 test_torus(device, 5.0f, 0.2f, 8, 8);
3484 test_torus(device, 0.2f, 1.0f, 60, 3);
3485 test_torus(device, 0.2f, 1.0f, 8, 70);
3486
3487 free_test_context(test_context);
3488 }
3489
3490 struct dynamic_array
3491 {
3492 int count, capacity;
3493 void *items;
3494 };
3495
3496 enum pointtype {
3497 POINTTYPE_CURVE = 0,
3498 POINTTYPE_CORNER,
3499 POINTTYPE_CURVE_START,
3500 POINTTYPE_CURVE_END,
3501 POINTTYPE_CURVE_MIDDLE,
3502 };
3503
3504 struct point2d
3505 {
3506 D3DXVECTOR2 pos;
3507 enum pointtype corner;
3508 };
3509
3510 /* is a dynamic_array */
3511 struct outline
3512 {
3513 int count, capacity;
3514 struct point2d *items;
3515 };
3516
3517 /* is a dynamic_array */
3518 struct outline_array
3519 {
3520 int count, capacity;
3521 struct outline *items;
3522 };
3523
3524 struct glyphinfo
3525 {
3526 struct outline_array outlines;
3527 float offset_x;
3528 };
3529
reserve(struct dynamic_array * array,int count,int itemsize)3530 static BOOL reserve(struct dynamic_array *array, int count, int itemsize)
3531 {
3532 if (count > array->capacity) {
3533 void *new_buffer;
3534 int new_capacity;
3535 if (array->items && array->capacity) {
3536 new_capacity = max(array->capacity * 2, count);
3537 new_buffer = HeapReAlloc(GetProcessHeap(), 0, array->items, new_capacity * itemsize);
3538 } else {
3539 new_capacity = max(16, count);
3540 new_buffer = HeapAlloc(GetProcessHeap(), 0, new_capacity * itemsize);
3541 }
3542 if (!new_buffer)
3543 return FALSE;
3544 array->items = new_buffer;
3545 array->capacity = new_capacity;
3546 }
3547 return TRUE;
3548 }
3549
add_point(struct outline * array)3550 static struct point2d *add_point(struct outline *array)
3551 {
3552 struct point2d *item;
3553
3554 if (!reserve((struct dynamic_array *)array, array->count + 1, sizeof(array->items[0])))
3555 return NULL;
3556
3557 item = &array->items[array->count++];
3558 ZeroMemory(item, sizeof(*item));
3559 return item;
3560 }
3561
add_outline(struct outline_array * array)3562 static struct outline *add_outline(struct outline_array *array)
3563 {
3564 struct outline *item;
3565
3566 if (!reserve((struct dynamic_array *)array, array->count + 1, sizeof(array->items[0])))
3567 return NULL;
3568
3569 item = &array->items[array->count++];
3570 ZeroMemory(item, sizeof(*item));
3571 return item;
3572 }
3573
convert_fixed_to_float(POINTFX * pt,int count,float emsquare)3574 static inline D3DXVECTOR2 *convert_fixed_to_float(POINTFX *pt, int count, float emsquare)
3575 {
3576 D3DXVECTOR2 *ret = (D3DXVECTOR2*)pt;
3577 while (count--) {
3578 D3DXVECTOR2 *pt_flt = (D3DXVECTOR2*)pt;
3579 pt_flt->x = (pt->x.value + pt->x.fract / (float)0x10000) / emsquare;
3580 pt_flt->y = (pt->y.value + pt->y.fract / (float)0x10000) / emsquare;
3581 pt++;
3582 }
3583 return ret;
3584 }
3585
add_bezier_points(struct outline * outline,const D3DXVECTOR2 * p1,const D3DXVECTOR2 * p2,const D3DXVECTOR2 * p3,float max_deviation)3586 static HRESULT add_bezier_points(struct outline *outline, const D3DXVECTOR2 *p1,
3587 const D3DXVECTOR2 *p2, const D3DXVECTOR2 *p3,
3588 float max_deviation)
3589 {
3590 D3DXVECTOR2 split1 = {0, 0}, split2 = {0, 0}, middle, vec;
3591 float deviation;
3592
3593 D3DXVec2Scale(&split1, D3DXVec2Add(&split1, p1, p2), 0.5f);
3594 D3DXVec2Scale(&split2, D3DXVec2Add(&split2, p2, p3), 0.5f);
3595 D3DXVec2Scale(&middle, D3DXVec2Add(&middle, &split1, &split2), 0.5f);
3596
3597 deviation = D3DXVec2Length(D3DXVec2Subtract(&vec, &middle, p2));
3598 if (deviation < max_deviation) {
3599 struct point2d *pt = add_point(outline);
3600 if (!pt) return E_OUTOFMEMORY;
3601 pt->pos = *p2;
3602 pt->corner = POINTTYPE_CURVE;
3603 /* the end point is omitted because the end line merges into the next segment of
3604 * the split bezier curve, and the end of the split bezier curve is added outside
3605 * this recursive function. */
3606 } else {
3607 HRESULT hr = add_bezier_points(outline, p1, &split1, &middle, max_deviation);
3608 if (hr != S_OK) return hr;
3609 hr = add_bezier_points(outline, &middle, &split2, p3, max_deviation);
3610 if (hr != S_OK) return hr;
3611 }
3612
3613 return S_OK;
3614 }
3615
is_direction_similar(D3DXVECTOR2 * dir1,D3DXVECTOR2 * dir2,float cos_theta)3616 static inline BOOL is_direction_similar(D3DXVECTOR2 *dir1, D3DXVECTOR2 *dir2, float cos_theta)
3617 {
3618 /* dot product = cos(theta) */
3619 return D3DXVec2Dot(dir1, dir2) > cos_theta;
3620 }
3621
unit_vec2(D3DXVECTOR2 * dir,const D3DXVECTOR2 * pt1,const D3DXVECTOR2 * pt2)3622 static inline D3DXVECTOR2 *unit_vec2(D3DXVECTOR2 *dir, const D3DXVECTOR2 *pt1, const D3DXVECTOR2 *pt2)
3623 {
3624 return D3DXVec2Normalize(D3DXVec2Subtract(dir, pt2, pt1), dir);
3625 }
3626
attempt_line_merge(struct outline * outline,int pt_index,const D3DXVECTOR2 * nextpt,BOOL to_curve)3627 static BOOL attempt_line_merge(struct outline *outline,
3628 int pt_index,
3629 const D3DXVECTOR2 *nextpt,
3630 BOOL to_curve)
3631 {
3632 D3DXVECTOR2 curdir, lastdir;
3633 struct point2d *prevpt, *pt;
3634 BOOL ret = FALSE;
3635 const float cos_half = cos(D3DXToRadian(0.5f));
3636
3637 pt = &outline->items[pt_index];
3638 pt_index = (pt_index - 1 + outline->count) % outline->count;
3639 prevpt = &outline->items[pt_index];
3640
3641 if (to_curve)
3642 pt->corner = pt->corner != POINTTYPE_CORNER ? POINTTYPE_CURVE_MIDDLE : POINTTYPE_CURVE_START;
3643
3644 if (outline->count < 2)
3645 return FALSE;
3646
3647 /* remove last point if the next line continues the last line */
3648 unit_vec2(&lastdir, &prevpt->pos, &pt->pos);
3649 unit_vec2(&curdir, &pt->pos, nextpt);
3650 if (is_direction_similar(&lastdir, &curdir, cos_half))
3651 {
3652 outline->count--;
3653 if (pt->corner == POINTTYPE_CURVE_END)
3654 prevpt->corner = pt->corner;
3655 if (prevpt->corner == POINTTYPE_CURVE_END && to_curve)
3656 prevpt->corner = POINTTYPE_CURVE_MIDDLE;
3657 pt = prevpt;
3658
3659 ret = TRUE;
3660 if (outline->count < 2)
3661 return ret;
3662
3663 pt_index = (pt_index - 1 + outline->count) % outline->count;
3664 prevpt = &outline->items[pt_index];
3665 unit_vec2(&lastdir, &prevpt->pos, &pt->pos);
3666 unit_vec2(&curdir, &pt->pos, nextpt);
3667 }
3668 return ret;
3669 }
3670
create_outline(struct glyphinfo * glyph,void * raw_outline,int datasize,float max_deviation,float emsquare)3671 static HRESULT create_outline(struct glyphinfo *glyph, void *raw_outline, int datasize,
3672 float max_deviation, float emsquare)
3673 {
3674 const float cos_45 = cos(D3DXToRadian(45.0f));
3675 const float cos_90 = cos(D3DXToRadian(90.0f));
3676 TTPOLYGONHEADER *header = (TTPOLYGONHEADER *)raw_outline;
3677
3678 while ((char *)header < (char *)raw_outline + datasize)
3679 {
3680 TTPOLYCURVE *curve = (TTPOLYCURVE *)(header + 1);
3681 struct point2d *lastpt, *pt;
3682 D3DXVECTOR2 lastdir;
3683 D3DXVECTOR2 *pt_flt;
3684 int j;
3685 struct outline *outline = add_outline(&glyph->outlines);
3686
3687 if (!outline)
3688 return E_OUTOFMEMORY;
3689
3690 pt = add_point(outline);
3691 if (!pt)
3692 return E_OUTOFMEMORY;
3693 pt_flt = convert_fixed_to_float(&header->pfxStart, 1, emsquare);
3694 pt->pos = *pt_flt;
3695 pt->corner = POINTTYPE_CORNER;
3696
3697 if (header->dwType != TT_POLYGON_TYPE)
3698 trace("Unknown header type %d\n", header->dwType);
3699
3700 while ((char *)curve < (char *)header + header->cb)
3701 {
3702 D3DXVECTOR2 bezier_start = outline->items[outline->count - 1].pos;
3703 BOOL to_curve = curve->wType != TT_PRIM_LINE && curve->cpfx > 1;
3704
3705 if (!curve->cpfx) {
3706 curve = (TTPOLYCURVE *)&curve->apfx[curve->cpfx];
3707 continue;
3708 }
3709
3710 pt_flt = convert_fixed_to_float(curve->apfx, curve->cpfx, emsquare);
3711
3712 attempt_line_merge(outline, outline->count - 1, &pt_flt[0], to_curve);
3713
3714 if (to_curve)
3715 {
3716 HRESULT hr;
3717 int count = curve->cpfx;
3718 j = 0;
3719
3720 while (count > 2)
3721 {
3722 D3DXVECTOR2 bezier_end;
3723
3724 D3DXVec2Scale(&bezier_end, D3DXVec2Add(&bezier_end, &pt_flt[j], &pt_flt[j+1]), 0.5f);
3725 hr = add_bezier_points(outline, &bezier_start, &pt_flt[j], &bezier_end, max_deviation);
3726 if (hr != S_OK)
3727 return hr;
3728 bezier_start = bezier_end;
3729 count--;
3730 j++;
3731 }
3732 hr = add_bezier_points(outline, &bezier_start, &pt_flt[j], &pt_flt[j+1], max_deviation);
3733 if (hr != S_OK)
3734 return hr;
3735
3736 pt = add_point(outline);
3737 if (!pt)
3738 return E_OUTOFMEMORY;
3739 j++;
3740 pt->pos = pt_flt[j];
3741 pt->corner = POINTTYPE_CURVE_END;
3742 } else {
3743 for (j = 0; j < curve->cpfx; j++)
3744 {
3745 pt = add_point(outline);
3746 if (!pt)
3747 return E_OUTOFMEMORY;
3748 pt->pos = pt_flt[j];
3749 pt->corner = POINTTYPE_CORNER;
3750 }
3751 }
3752
3753 curve = (TTPOLYCURVE *)&curve->apfx[curve->cpfx];
3754 }
3755
3756 /* remove last point if the next line continues the last line */
3757 if (outline->count >= 3) {
3758 BOOL to_curve;
3759
3760 lastpt = &outline->items[outline->count - 1];
3761 pt = &outline->items[0];
3762 if (pt->pos.x == lastpt->pos.x && pt->pos.y == lastpt->pos.y) {
3763 if (lastpt->corner == POINTTYPE_CURVE_END)
3764 {
3765 if (pt->corner == POINTTYPE_CURVE_START)
3766 pt->corner = POINTTYPE_CURVE_MIDDLE;
3767 else
3768 pt->corner = POINTTYPE_CURVE_END;
3769 }
3770 outline->count--;
3771 } else {
3772 /* outline closed with a line from end to start point */
3773 attempt_line_merge(outline, outline->count - 1, &pt->pos, FALSE);
3774 }
3775 lastpt = &outline->items[0];
3776 to_curve = lastpt->corner != POINTTYPE_CORNER && lastpt->corner != POINTTYPE_CURVE_END;
3777 if (lastpt->corner == POINTTYPE_CURVE_START)
3778 lastpt->corner = POINTTYPE_CORNER;
3779 pt = &outline->items[1];
3780 if (attempt_line_merge(outline, 0, &pt->pos, to_curve))
3781 *lastpt = outline->items[outline->count];
3782 }
3783
3784 lastpt = &outline->items[outline->count - 1];
3785 pt = &outline->items[0];
3786 unit_vec2(&lastdir, &lastpt->pos, &pt->pos);
3787 for (j = 0; j < outline->count; j++)
3788 {
3789 D3DXVECTOR2 curdir;
3790
3791 lastpt = pt;
3792 pt = &outline->items[(j + 1) % outline->count];
3793 unit_vec2(&curdir, &lastpt->pos, &pt->pos);
3794
3795 switch (lastpt->corner)
3796 {
3797 case POINTTYPE_CURVE_START:
3798 case POINTTYPE_CURVE_END:
3799 if (!is_direction_similar(&lastdir, &curdir, cos_45))
3800 lastpt->corner = POINTTYPE_CORNER;
3801 break;
3802 case POINTTYPE_CURVE_MIDDLE:
3803 if (!is_direction_similar(&lastdir, &curdir, cos_90))
3804 lastpt->corner = POINTTYPE_CORNER;
3805 else
3806 lastpt->corner = POINTTYPE_CURVE;
3807 break;
3808 default:
3809 break;
3810 }
3811 lastdir = curdir;
3812 }
3813
3814 header = (TTPOLYGONHEADER *)((char *)header + header->cb);
3815 }
3816 return S_OK;
3817 }
3818
free_outline(struct outline * outline)3819 static void free_outline(struct outline *outline)
3820 {
3821 HeapFree(GetProcessHeap(), 0, outline->items);
3822 }
3823
free_glyphinfo(struct glyphinfo * glyph)3824 static void free_glyphinfo(struct glyphinfo *glyph)
3825 {
3826 unsigned int i;
3827
3828 for (i = 0; i < glyph->outlines.count; ++i)
3829 free_outline(&glyph->outlines.items[i]);
3830 HeapFree(GetProcessHeap(), 0, glyph->outlines.items);
3831 }
3832
compute_text_mesh(struct mesh * mesh,const char * text,float deviation,float extrusion,float otmEMSquare,const struct glyphinfo * glyphs)3833 static void compute_text_mesh(struct mesh *mesh, const char *text,
3834 float deviation, float extrusion, float otmEMSquare, const struct glyphinfo *glyphs)
3835 {
3836 DWORD nb_vertices, nb_faces;
3837 DWORD nb_corners, nb_outline_points;
3838 int textlen = 0;
3839 int i;
3840 struct vertex *vertex_ptr;
3841 face *face_ptr;
3842
3843 textlen = strlen(text);
3844
3845 /* corner points need an extra vertex for the different side faces normals */
3846 nb_corners = 0;
3847 nb_outline_points = 0;
3848 for (i = 0; i < textlen; i++)
3849 {
3850 int j;
3851 for (j = 0; j < glyphs[i].outlines.count; j++)
3852 {
3853 int k;
3854 struct outline *outline = &glyphs[i].outlines.items[j];
3855 nb_outline_points += outline->count;
3856 nb_corners++; /* first outline point always repeated as a corner */
3857 for (k = 1; k < outline->count; k++)
3858 if (outline->items[k].corner)
3859 nb_corners++;
3860 }
3861 }
3862
3863 nb_vertices = (nb_outline_points + nb_corners) * 2 + textlen;
3864 nb_faces = nb_outline_points * 2;
3865
3866 ok(new_mesh(mesh, nb_vertices, nb_faces), "Failed to create reference text mesh.\n");
3867
3868 /* convert 2D vertices and faces into 3D mesh */
3869 vertex_ptr = mesh->vertices;
3870 face_ptr = mesh->faces;
3871 for (i = 0; i < textlen; i++)
3872 {
3873 int j;
3874
3875 /* side vertices and faces */
3876 for (j = 0; j < glyphs[i].outlines.count; j++)
3877 {
3878 struct vertex *outline_vertices = vertex_ptr;
3879 struct outline *outline = &glyphs[i].outlines.items[j];
3880 int k;
3881 struct point2d *prevpt = &outline->items[outline->count - 1];
3882 struct point2d *pt = &outline->items[0];
3883
3884 for (k = 1; k <= outline->count; k++)
3885 {
3886 struct vertex vtx;
3887 struct point2d *nextpt = &outline->items[k % outline->count];
3888 WORD vtx_idx = vertex_ptr - mesh->vertices;
3889 D3DXVECTOR2 vec;
3890
3891 if (pt->corner == POINTTYPE_CURVE_START)
3892 D3DXVec2Subtract(&vec, &pt->pos, &prevpt->pos);
3893 else if (pt->corner)
3894 D3DXVec2Subtract(&vec, &nextpt->pos, &pt->pos);
3895 else
3896 D3DXVec2Subtract(&vec, &nextpt->pos, &prevpt->pos);
3897 D3DXVec2Normalize(&vec, &vec);
3898 vtx.normal.x = -vec.y;
3899 vtx.normal.y = vec.x;
3900 vtx.normal.z = 0;
3901
3902 vtx.position.x = pt->pos.x + glyphs[i].offset_x;
3903 vtx.position.y = pt->pos.y;
3904 vtx.position.z = 0;
3905 *vertex_ptr++ = vtx;
3906
3907 vtx.position.z = -extrusion;
3908 *vertex_ptr++ = vtx;
3909
3910 vtx.position.x = nextpt->pos.x + glyphs[i].offset_x;
3911 vtx.position.y = nextpt->pos.y;
3912 if (pt->corner && nextpt->corner && nextpt->corner != POINTTYPE_CURVE_END) {
3913 vtx.position.z = -extrusion;
3914 *vertex_ptr++ = vtx;
3915 vtx.position.z = 0;
3916 *vertex_ptr++ = vtx;
3917
3918 (*face_ptr)[0] = vtx_idx;
3919 (*face_ptr)[1] = vtx_idx + 2;
3920 (*face_ptr)[2] = vtx_idx + 1;
3921 face_ptr++;
3922
3923 (*face_ptr)[0] = vtx_idx;
3924 (*face_ptr)[1] = vtx_idx + 3;
3925 (*face_ptr)[2] = vtx_idx + 2;
3926 face_ptr++;
3927 } else {
3928 if (nextpt->corner) {
3929 if (nextpt->corner == POINTTYPE_CURVE_END) {
3930 struct point2d *nextpt2 = &outline->items[(k + 1) % outline->count];
3931 D3DXVec2Subtract(&vec, &nextpt2->pos, &nextpt->pos);
3932 } else {
3933 D3DXVec2Subtract(&vec, &nextpt->pos, &pt->pos);
3934 }
3935 D3DXVec2Normalize(&vec, &vec);
3936 vtx.normal.x = -vec.y;
3937 vtx.normal.y = vec.x;
3938
3939 vtx.position.z = 0;
3940 *vertex_ptr++ = vtx;
3941 vtx.position.z = -extrusion;
3942 *vertex_ptr++ = vtx;
3943 }
3944
3945 (*face_ptr)[0] = vtx_idx;
3946 (*face_ptr)[1] = vtx_idx + 3;
3947 (*face_ptr)[2] = vtx_idx + 1;
3948 face_ptr++;
3949
3950 (*face_ptr)[0] = vtx_idx;
3951 (*face_ptr)[1] = vtx_idx + 2;
3952 (*face_ptr)[2] = vtx_idx + 3;
3953 face_ptr++;
3954 }
3955
3956 prevpt = pt;
3957 pt = nextpt;
3958 }
3959 if (!pt->corner) {
3960 *vertex_ptr++ = *outline_vertices++;
3961 *vertex_ptr++ = *outline_vertices++;
3962 }
3963 }
3964
3965 /* FIXME: compute expected faces */
3966 /* Add placeholder to separate glyph outlines */
3967 vertex_ptr->position.x = 0;
3968 vertex_ptr->position.y = 0;
3969 vertex_ptr->position.z = 0;
3970 vertex_ptr->normal.x = 0;
3971 vertex_ptr->normal.y = 0;
3972 vertex_ptr->normal.z = 1;
3973 vertex_ptr++;
3974 }
3975 }
3976
compare_text_outline_mesh(const char * name,ID3DXMesh * d3dxmesh,struct mesh * mesh,size_t textlen,float extrusion,const struct glyphinfo * glyphs)3977 static void compare_text_outline_mesh(const char *name, ID3DXMesh *d3dxmesh, struct mesh *mesh,
3978 size_t textlen, float extrusion, const struct glyphinfo *glyphs)
3979 {
3980 HRESULT hr;
3981 DWORD number_of_vertices, number_of_faces;
3982 IDirect3DVertexBuffer9 *vertex_buffer = NULL;
3983 IDirect3DIndexBuffer9 *index_buffer = NULL;
3984 D3DVERTEXBUFFER_DESC vertex_buffer_description;
3985 D3DINDEXBUFFER_DESC index_buffer_description;
3986 struct vertex *vertices = NULL;
3987 face *faces = NULL;
3988 int expected, i;
3989 int vtx_idx1, face_idx1, vtx_idx2, face_idx2;
3990
3991 number_of_vertices = d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh);
3992 number_of_faces = d3dxmesh->lpVtbl->GetNumFaces(d3dxmesh);
3993
3994 hr = d3dxmesh->lpVtbl->GetVertexBuffer(d3dxmesh, &vertex_buffer);
3995 ok(hr == D3D_OK, "Test %s, unexpected hr %#x.\n", name, hr);
3996 hr = IDirect3DVertexBuffer9_GetDesc(vertex_buffer, &vertex_buffer_description);
3997 ok(hr == D3D_OK, "Test %s, unexpected hr %#x.\n", name, hr);
3998 ok(vertex_buffer_description.Format == D3DFMT_VERTEXDATA, "Test %s, unexpected format %u.\n",
3999 name, vertex_buffer_description.Format);
4000 ok(vertex_buffer_description.Type == D3DRTYPE_VERTEXBUFFER, "Test %s, unexpected resource type %u.\n",
4001 name, vertex_buffer_description.Type);
4002 ok(!vertex_buffer_description.Usage, "Test %s, unexpected usage %#x.\n", name, vertex_buffer_description.Usage);
4003 ok(vertex_buffer_description.Pool == D3DPOOL_MANAGED, "Test %s, unexpected pool %u.\n",
4004 name, vertex_buffer_description.Pool);
4005 ok(vertex_buffer_description.FVF == mesh->fvf, "Test %s, unexpected FVF %#x (expected %#x).\n",
4006 name, vertex_buffer_description.FVF, mesh->fvf);
4007 if (!mesh->fvf)
4008 expected = number_of_vertices * mesh->vertex_size;
4009 else
4010 expected = number_of_vertices * D3DXGetFVFVertexSize(mesh->fvf);
4011 ok(vertex_buffer_description.Size == expected, "Test %s, unexpected size %u (expected %u).\n",
4012 name, vertex_buffer_description.Size, expected);
4013
4014 hr = d3dxmesh->lpVtbl->GetIndexBuffer(d3dxmesh, &index_buffer);
4015 ok(hr == D3D_OK, "Test %s, unexpected hr %#x.\n", name, hr);
4016 hr = IDirect3DIndexBuffer9_GetDesc(index_buffer, &index_buffer_description);
4017 ok(hr == D3D_OK, "Test %s, unexpected hr %#x.\n", name, hr);
4018 ok(index_buffer_description.Format == D3DFMT_INDEX16, "Test %s, unexpected format %u.\n",
4019 name, index_buffer_description.Format);
4020 ok(index_buffer_description.Type == D3DRTYPE_INDEXBUFFER, "Test %s, unexpected resource type %u.\n",
4021 name, index_buffer_description.Type);
4022 ok(!index_buffer_description.Usage, "Test %s, unexpected usage %#x.\n",
4023 name, index_buffer_description.Usage);
4024 ok(index_buffer_description.Pool == D3DPOOL_MANAGED, "Test %s, unexpected pool %u.\n",
4025 name, index_buffer_description.Pool);
4026 expected = number_of_faces * sizeof(WORD) * 3;
4027 ok(index_buffer_description.Size == expected, "Test %s, unexpected size %u.\n",
4028 name, index_buffer_description.Size);
4029
4030 hr = IDirect3DVertexBuffer9_Lock(vertex_buffer, 0, number_of_vertices * sizeof(D3DXVECTOR3) * 2,
4031 (void **)&vertices, D3DLOCK_DISCARD);
4032 ok(hr == D3D_OK, "Test %s, unexpected hr %#x.\n", name, hr);
4033 hr = IDirect3DIndexBuffer9_Lock(index_buffer, 0, number_of_faces * sizeof(WORD) * 3,
4034 (void **)&faces, D3DLOCK_DISCARD);
4035 ok(hr == D3D_OK, "Test %s, unexpected hr %#x.\n", name, hr);
4036 face_idx1 = 0;
4037 vtx_idx2 = 0;
4038 face_idx2 = 0;
4039 vtx_idx1 = 0;
4040 for (i = 0; i < textlen; i++)
4041 {
4042 int nb_outline_vertices1, nb_outline_faces1;
4043 int nb_outline_vertices2, nb_outline_faces2;
4044 int nb_back_vertices, nb_back_faces;
4045 int first_vtx1, first_vtx2;
4046 int first_face1, first_face2;
4047 int j;
4048
4049 first_vtx1 = vtx_idx1;
4050 first_vtx2 = vtx_idx2;
4051 /* Glyphs without outlines do not generate any vertices. */
4052 if (glyphs[i].outlines.count > 0)
4053 {
4054 for (; vtx_idx1 < number_of_vertices; vtx_idx1++)
4055 {
4056 if (vertices[vtx_idx1].normal.z != 0)
4057 break;
4058 }
4059
4060 for (; vtx_idx2 < mesh->number_of_vertices; vtx_idx2++)
4061 {
4062 if (mesh->vertices[vtx_idx2].normal.z != 0)
4063 break;
4064 }
4065 }
4066 nb_outline_vertices1 = vtx_idx1 - first_vtx1;
4067 nb_outline_vertices2 = vtx_idx2 - first_vtx2;
4068 ok(nb_outline_vertices1 == nb_outline_vertices2,
4069 "Test %s, glyph %d, outline vertex count result %d, expected %d\n", name, i,
4070 nb_outline_vertices1, nb_outline_vertices2);
4071
4072 for (j = 0; j < min(nb_outline_vertices1, nb_outline_vertices2); j++)
4073 {
4074 vtx_idx1 = first_vtx1 + j;
4075 vtx_idx2 = first_vtx2 + j;
4076 ok(compare_vec3(vertices[vtx_idx1].position, mesh->vertices[vtx_idx2].position),
4077 "Test %s, glyph %d, vertex position %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1,
4078 vertices[vtx_idx1].position.x, vertices[vtx_idx1].position.y, vertices[vtx_idx1].position.z,
4079 mesh->vertices[vtx_idx2].position.x, mesh->vertices[vtx_idx2].position.y, mesh->vertices[vtx_idx2].position.z);
4080 ok(compare_vec3(vertices[vtx_idx1].normal, mesh->vertices[first_vtx2 + j].normal),
4081 "Test %s, glyph %d, vertex normal %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1,
4082 vertices[vtx_idx1].normal.x, vertices[vtx_idx1].normal.y, vertices[vtx_idx1].normal.z,
4083 mesh->vertices[vtx_idx2].normal.x, mesh->vertices[vtx_idx2].normal.y, mesh->vertices[vtx_idx2].normal.z);
4084 }
4085 vtx_idx1 = first_vtx1 + nb_outline_vertices1;
4086 vtx_idx2 = first_vtx2 + nb_outline_vertices2;
4087
4088 first_face1 = face_idx1;
4089 first_face2 = face_idx2;
4090 for (; face_idx1 < number_of_faces; face_idx1++)
4091 {
4092 if (faces[face_idx1][0] >= vtx_idx1 ||
4093 faces[face_idx1][1] >= vtx_idx1 ||
4094 faces[face_idx1][2] >= vtx_idx1)
4095 break;
4096 }
4097 for (; face_idx2 < mesh->number_of_faces; face_idx2++)
4098 {
4099 if (mesh->faces[face_idx2][0] >= vtx_idx2 ||
4100 mesh->faces[face_idx2][1] >= vtx_idx2 ||
4101 mesh->faces[face_idx2][2] >= vtx_idx2)
4102 break;
4103 }
4104 nb_outline_faces1 = face_idx1 - first_face1;
4105 nb_outline_faces2 = face_idx2 - first_face2;
4106 ok(nb_outline_faces1 == nb_outline_faces2,
4107 "Test %s, glyph %d, outline face count result %d, expected %d\n", name, i,
4108 nb_outline_faces1, nb_outline_faces2);
4109
4110 for (j = 0; j < min(nb_outline_faces1, nb_outline_faces2); j++)
4111 {
4112 face_idx1 = first_face1 + j;
4113 face_idx2 = first_face2 + j;
4114 ok(faces[face_idx1][0] - first_vtx1 == mesh->faces[face_idx2][0] - first_vtx2 &&
4115 faces[face_idx1][1] - first_vtx1 == mesh->faces[face_idx2][1] - first_vtx2 &&
4116 faces[face_idx1][2] - first_vtx1 == mesh->faces[face_idx2][2] - first_vtx2,
4117 "Test %s, glyph %d, face %d, result (%d, %d, %d), expected (%d, %d, %d)\n", name, i, face_idx1,
4118 faces[face_idx1][0], faces[face_idx1][1], faces[face_idx1][2],
4119 mesh->faces[face_idx2][0] - first_vtx2 + first_vtx1,
4120 mesh->faces[face_idx2][1] - first_vtx2 + first_vtx1,
4121 mesh->faces[face_idx2][2] - first_vtx2 + first_vtx1);
4122 }
4123 face_idx1 = first_face1 + nb_outline_faces1;
4124 face_idx2 = first_face2 + nb_outline_faces2;
4125
4126 /* partial test on back vertices and faces */
4127 first_vtx1 = vtx_idx1;
4128 for (; vtx_idx1 < number_of_vertices; vtx_idx1++) {
4129 struct vertex vtx;
4130
4131 if (vertices[vtx_idx1].normal.z != 1.0f)
4132 break;
4133
4134 vtx.position.z = 0.0f;
4135 vtx.normal.x = 0.0f;
4136 vtx.normal.y = 0.0f;
4137 vtx.normal.z = 1.0f;
4138 ok(compare(vertices[vtx_idx1].position.z, vtx.position.z),
4139 "Test %s, glyph %d, vertex position.z %d, result %g, expected %g\n", name, i, vtx_idx1,
4140 vertices[vtx_idx1].position.z, vtx.position.z);
4141 ok(compare_vec3(vertices[vtx_idx1].normal, vtx.normal),
4142 "Test %s, glyph %d, vertex normal %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1,
4143 vertices[vtx_idx1].normal.x, vertices[vtx_idx1].normal.y, vertices[vtx_idx1].normal.z,
4144 vtx.normal.x, vtx.normal.y, vtx.normal.z);
4145 }
4146 nb_back_vertices = vtx_idx1 - first_vtx1;
4147 first_face1 = face_idx1;
4148 for (; face_idx1 < number_of_faces; face_idx1++)
4149 {
4150 const D3DXVECTOR3 *vtx1, *vtx2, *vtx3;
4151 D3DXVECTOR3 normal;
4152 D3DXVECTOR3 v1 = {0, 0, 0};
4153 D3DXVECTOR3 v2 = {0, 0, 0};
4154 D3DXVECTOR3 forward = {0.0f, 0.0f, 1.0f};
4155
4156 if (faces[face_idx1][0] >= vtx_idx1 ||
4157 faces[face_idx1][1] >= vtx_idx1 ||
4158 faces[face_idx1][2] >= vtx_idx1)
4159 break;
4160
4161 vtx1 = &vertices[faces[face_idx1][0]].position;
4162 vtx2 = &vertices[faces[face_idx1][1]].position;
4163 vtx3 = &vertices[faces[face_idx1][2]].position;
4164
4165 D3DXVec3Subtract(&v1, vtx2, vtx1);
4166 D3DXVec3Subtract(&v2, vtx3, vtx2);
4167 D3DXVec3Cross(&normal, &v1, &v2);
4168 D3DXVec3Normalize(&normal, &normal);
4169 ok(!D3DXVec3Length(&normal) || compare_vec3(normal, forward),
4170 "Test %s, glyph %d, face %d normal, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, face_idx1,
4171 normal.x, normal.y, normal.z, forward.x, forward.y, forward.z);
4172 }
4173 nb_back_faces = face_idx1 - first_face1;
4174
4175 /* compare front and back faces & vertices */
4176 if (extrusion == 0.0f) {
4177 /* Oddly there are only back faces in this case */
4178 nb_back_vertices /= 2;
4179 nb_back_faces /= 2;
4180 face_idx1 -= nb_back_faces;
4181 vtx_idx1 -= nb_back_vertices;
4182 }
4183 for (j = 0; j < nb_back_vertices; j++)
4184 {
4185 struct vertex vtx = vertices[first_vtx1];
4186 vtx.position.z = -extrusion;
4187 vtx.normal.x = 0.0f;
4188 vtx.normal.y = 0.0f;
4189 vtx.normal.z = extrusion == 0.0f ? 1.0f : -1.0f;
4190 ok(compare_vec3(vertices[vtx_idx1].position, vtx.position),
4191 "Test %s, glyph %d, vertex position %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1,
4192 vertices[vtx_idx1].position.x, vertices[vtx_idx1].position.y, vertices[vtx_idx1].position.z,
4193 vtx.position.x, vtx.position.y, vtx.position.z);
4194 ok(compare_vec3(vertices[vtx_idx1].normal, vtx.normal),
4195 "Test %s, glyph %d, vertex normal %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1,
4196 vertices[vtx_idx1].normal.x, vertices[vtx_idx1].normal.y, vertices[vtx_idx1].normal.z,
4197 vtx.normal.x, vtx.normal.y, vtx.normal.z);
4198 vtx_idx1++;
4199 first_vtx1++;
4200 }
4201 for (j = 0; j < nb_back_faces; j++)
4202 {
4203 int f1, f2;
4204 if (extrusion == 0.0f) {
4205 f1 = 1;
4206 f2 = 2;
4207 } else {
4208 f1 = 2;
4209 f2 = 1;
4210 }
4211 ok(faces[face_idx1][0] == faces[first_face1][0] + nb_back_vertices &&
4212 faces[face_idx1][1] == faces[first_face1][f1] + nb_back_vertices &&
4213 faces[face_idx1][2] == faces[first_face1][f2] + nb_back_vertices,
4214 "Test %s, glyph %d, face %d, result (%d, %d, %d), expected (%d, %d, %d)\n", name, i, face_idx1,
4215 faces[face_idx1][0], faces[face_idx1][1], faces[face_idx1][2],
4216 faces[first_face1][0] - nb_back_faces,
4217 faces[first_face1][f1] - nb_back_faces,
4218 faces[first_face1][f2] - nb_back_faces);
4219 first_face1++;
4220 face_idx1++;
4221 }
4222
4223 /* skip to the outline for the next glyph */
4224 for (; vtx_idx2 < mesh->number_of_vertices; vtx_idx2++) {
4225 if (mesh->vertices[vtx_idx2].normal.z == 0)
4226 break;
4227 }
4228 for (; face_idx2 < mesh->number_of_faces; face_idx2++)
4229 {
4230 if (mesh->faces[face_idx2][0] >= vtx_idx2 ||
4231 mesh->faces[face_idx2][1] >= vtx_idx2 ||
4232 mesh->faces[face_idx2][2] >= vtx_idx2) break;
4233 }
4234 }
4235
4236 IDirect3DIndexBuffer9_Unlock(index_buffer);
4237 IDirect3DVertexBuffer9_Unlock(vertex_buffer);
4238 IDirect3DIndexBuffer9_Release(index_buffer);
4239 IDirect3DVertexBuffer9_Release(vertex_buffer);
4240 }
4241
test_createtext(IDirect3DDevice9 * device,HDC hdc,const char * text,float deviation,float extrusion)4242 static void test_createtext(IDirect3DDevice9 *device, HDC hdc, const char *text, float deviation, float extrusion)
4243 {
4244 static const MAT2 identity = {{0, 1}, {0, 0}, {0, 0}, {0, 1}};
4245 HRESULT hr;
4246 ID3DXMesh *d3dxmesh = NULL;
4247 struct mesh mesh = {0};
4248 char name[256];
4249 OUTLINETEXTMETRICA otm;
4250 GLYPHMETRICS gm;
4251 struct glyphinfo *glyphs;
4252 GLYPHMETRICSFLOAT *glyphmetrics_float = HeapAlloc(GetProcessHeap(), 0, sizeof(GLYPHMETRICSFLOAT) * strlen(text));
4253 int i;
4254 LOGFONTA lf;
4255 float offset_x;
4256 size_t textlen;
4257 HFONT font = NULL, oldfont = NULL;
4258 char *raw_outline;
4259
4260 sprintf(name, "text ('%s', %f, %f)", text, deviation, extrusion);
4261
4262 hr = D3DXCreateTextA(device, hdc, text, deviation, extrusion, &d3dxmesh, NULL, glyphmetrics_float);
4263 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
4264
4265 /* must select a modified font having lfHeight = otm.otmEMSquare before
4266 * calling GetGlyphOutline to get the expected values */
4267 ok(GetObjectA(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf), "Failed to get current DC font.\n");
4268 ok(GetOutlineTextMetricsA(hdc, sizeof(otm), &otm), "Failed to get DC font outline.\n");
4269 lf.lfHeight = otm.otmEMSquare;
4270 lf.lfWidth = 0;
4271 ok(!!(font = CreateFontIndirectA(&lf)), "Failed to create font.\n");
4272
4273 textlen = strlen(text);
4274 glyphs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, textlen * sizeof(*glyphs));
4275 oldfont = SelectObject(hdc, font);
4276
4277 for (i = 0; i < textlen; i++)
4278 {
4279 GetGlyphOutlineA(hdc, text[i], GGO_NATIVE, &gm, 0, NULL, &identity);
4280 compare_float(glyphmetrics_float[i].gmfBlackBoxX, gm.gmBlackBoxX / (float)otm.otmEMSquare);
4281 compare_float(glyphmetrics_float[i].gmfBlackBoxY, gm.gmBlackBoxY / (float)otm.otmEMSquare);
4282 compare_float(glyphmetrics_float[i].gmfptGlyphOrigin.x, gm.gmptGlyphOrigin.x / (float)otm.otmEMSquare);
4283 compare_float(glyphmetrics_float[i].gmfptGlyphOrigin.y, gm.gmptGlyphOrigin.y / (float)otm.otmEMSquare);
4284 compare_float(glyphmetrics_float[i].gmfCellIncX, gm.gmCellIncX / (float)otm.otmEMSquare);
4285 compare_float(glyphmetrics_float[i].gmfCellIncY, gm.gmCellIncY / (float)otm.otmEMSquare);
4286 }
4287
4288 if (deviation == 0.0f)
4289 deviation = 1.0f / otm.otmEMSquare;
4290
4291 offset_x = 0.0f;
4292 for (i = 0; i < textlen; i++)
4293 {
4294 DWORD datasize;
4295
4296 glyphs[i].offset_x = offset_x;
4297
4298 datasize = GetGlyphOutlineA(hdc, text[i], GGO_NATIVE, &gm, 0, NULL, &identity);
4299 ok(datasize != GDI_ERROR, "Failed to retrieve GDI glyph outline size.\n");
4300 raw_outline = HeapAlloc(GetProcessHeap(), 0, datasize);
4301 datasize = GetGlyphOutlineA(hdc, text[i], GGO_NATIVE, &gm, datasize, raw_outline, &identity);
4302 ok(datasize != GDI_ERROR, "Failed to retrieve GDI glyph outline.\n");
4303 create_outline(&glyphs[i], raw_outline, datasize, deviation, otm.otmEMSquare);
4304 HeapFree(GetProcessHeap(), 0, raw_outline);
4305
4306 offset_x += gm.gmCellIncX / (float)otm.otmEMSquare;
4307 }
4308
4309 SelectObject(hdc, oldfont);
4310
4311 compute_text_mesh(&mesh, text, deviation, extrusion, otm.otmEMSquare, glyphs);
4312 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
4313
4314 compare_text_outline_mesh(name, d3dxmesh, &mesh, textlen, extrusion, glyphs);
4315
4316 free_mesh(&mesh);
4317 d3dxmesh->lpVtbl->Release(d3dxmesh);
4318 DeleteObject(font);
4319 HeapFree(GetProcessHeap(), 0, glyphmetrics_float);
4320
4321 for (i = 0; i < textlen; i++)
4322 free_glyphinfo(&glyphs[i]);
4323 HeapFree(GetProcessHeap(), 0, glyphs);
4324 }
4325
D3DXCreateTextTest(void)4326 static void D3DXCreateTextTest(void)
4327 {
4328 HRESULT hr;
4329 HDC hdc;
4330 IDirect3DDevice9* device;
4331 ID3DXMesh* d3dxmesh = NULL;
4332 HFONT hFont;
4333 OUTLINETEXTMETRICA otm;
4334 int number_of_vertices;
4335 int number_of_faces;
4336 struct test_context *test_context;
4337
4338 if (!(test_context = new_test_context()))
4339 {
4340 skip("Couldn't create test context\n");
4341 return;
4342 }
4343 device = test_context->device;
4344
4345 hdc = CreateCompatibleDC(NULL);
4346
4347 hFont = CreateFontA(12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
4348 CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, "Arial");
4349 SelectObject(hdc, hFont);
4350 GetOutlineTextMetricsA(hdc, sizeof(otm), &otm);
4351
4352 hr = D3DXCreateTextA(device, hdc, "wine", 0.001f, 0.4f, NULL, NULL, NULL);
4353 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4354
4355 /* D3DXCreateTextA page faults from passing NULL text */
4356
4357 hr = D3DXCreateTextW(device, hdc, NULL, 0.001f, 0.4f, &d3dxmesh, NULL, NULL);
4358 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4359
4360 hr = D3DXCreateTextA(device, hdc, "", 0.001f, 0.4f, &d3dxmesh, NULL, NULL);
4361 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4362
4363 hr = D3DXCreateTextA(device, hdc, " ", 0.001f, 0.4f, &d3dxmesh, NULL, NULL);
4364 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4365
4366 hr = D3DXCreateTextA(NULL, hdc, "wine", 0.001f, 0.4f, &d3dxmesh, NULL, NULL);
4367 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4368
4369 hr = D3DXCreateTextA(device, NULL, "wine", 0.001f, 0.4f, &d3dxmesh, NULL, NULL);
4370 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4371
4372 hr = D3DXCreateTextA(device, hdc, "wine", -FLT_MIN, 0.4f, &d3dxmesh, NULL, NULL);
4373 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4374
4375 hr = D3DXCreateTextA(device, hdc, "wine", 0.001f, -FLT_MIN, &d3dxmesh, NULL, NULL);
4376 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4377
4378 /* deviation = 0.0f treated as if deviation = 1.0f / otm.otmEMSquare */
4379 hr = D3DXCreateTextA(device, hdc, "wine", 1.0f / otm.otmEMSquare, 0.4f, &d3dxmesh, NULL, NULL);
4380 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
4381 number_of_vertices = d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh);
4382 number_of_faces = d3dxmesh->lpVtbl->GetNumFaces(d3dxmesh);
4383 d3dxmesh->lpVtbl->Release(d3dxmesh);
4384
4385 hr = D3DXCreateTextA(device, hdc, "wine", 0.0f, 0.4f, &d3dxmesh, NULL, NULL);
4386 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
4387 ok(number_of_vertices == d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh),
4388 "Got %d vertices, expected %d\n",
4389 d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh), number_of_vertices);
4390 ok(number_of_faces == d3dxmesh->lpVtbl->GetNumFaces(d3dxmesh),
4391 "Got %d faces, expected %d\n",
4392 d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh), number_of_faces);
4393 d3dxmesh->lpVtbl->Release(d3dxmesh);
4394
4395 if (0)
4396 {
4397 /* too much detail requested, so will appear to hang */
4398 trace("Waiting for D3DXCreateText to finish with deviation = FLT_MIN ...\n");
4399 hr = D3DXCreateTextA(device, hdc, "wine", FLT_MIN, 0.4f, &d3dxmesh, NULL, NULL);
4400 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
4401 if (SUCCEEDED(hr) && d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh);
4402 trace("D3DXCreateText finish with deviation = FLT_MIN\n");
4403 }
4404
4405 hr = D3DXCreateTextA(device, hdc, "wine", 0.001f, 0.4f, &d3dxmesh, NULL, NULL);
4406 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
4407 if (SUCCEEDED(hr) && d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh);
4408
4409 test_createtext(device, hdc, "wine", FLT_MAX, 0.4f);
4410 test_createtext(device, hdc, "wine", 0.001f, FLT_MIN);
4411 test_createtext(device, hdc, "wine", 0.001f, 0.0f);
4412 test_createtext(device, hdc, "wine", 0.001f, FLT_MAX);
4413 test_createtext(device, hdc, "wine", 0.0f, 1.0f);
4414 test_createtext(device, hdc, " wine", 1.0f, 0.0f);
4415 test_createtext(device, hdc, "wine ", 1.0f, 0.0f);
4416 test_createtext(device, hdc, "wi ne", 1.0f, 0.0f);
4417
4418 DeleteDC(hdc);
4419 DeleteObject(hFont);
4420
4421 free_test_context(test_context);
4422 }
4423
test_get_decl_length(void)4424 static void test_get_decl_length(void)
4425 {
4426 static const D3DVERTEXELEMENT9 declaration1[] =
4427 {
4428 {0, 0, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4429 {1, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4430 {2, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4431 {3, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4432 {4, 0, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4433 {5, 0, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4434 {6, 0, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4435 {7, 0, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4436 {8, 0, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4437 {9, 0, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4438 {10, 0, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4439 {11, 0, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4440 {12, 0, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4441 {13, 0, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4442 {14, 0, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4443 D3DDECL_END(),
4444 };
4445 static const D3DVERTEXELEMENT9 declaration2[] =
4446 {
4447 {0, 8, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4448 {1, 8, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4449 {2, 8, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4450 {3, 8, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4451 {4, 8, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4452 {5, 8, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4453 {6, 8, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4454 {7, 8, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4455 {0, 8, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4456 {1, 8, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4457 {2, 8, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4458 {3, 8, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4459 {4, 8, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4460 {5, 8, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4461 {6, 8, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4462 {7, 8, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4463 D3DDECL_END(),
4464 };
4465 UINT size;
4466
4467 size = D3DXGetDeclLength(declaration1);
4468 ok(size == 15, "Got size %u, expected 15.\n", size);
4469
4470 size = D3DXGetDeclLength(declaration2);
4471 ok(size == 16, "Got size %u, expected 16.\n", size);
4472 }
4473
test_get_decl_vertex_size(void)4474 static void test_get_decl_vertex_size(void)
4475 {
4476 static const D3DVERTEXELEMENT9 declaration1[] =
4477 {
4478 {0, 0, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4479 {1, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4480 {2, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4481 {3, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4482 {4, 0, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4483 {5, 0, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4484 {6, 0, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4485 {7, 0, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4486 {8, 0, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4487 {9, 0, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4488 {10, 0, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4489 {11, 0, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4490 {12, 0, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4491 {13, 0, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4492 {14, 0, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4493 D3DDECL_END(),
4494 };
4495 static const D3DVERTEXELEMENT9 declaration2[] =
4496 {
4497 {0, 8, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4498 {1, 8, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4499 {2, 8, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4500 {3, 8, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4501 {4, 8, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4502 {5, 8, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4503 {6, 8, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4504 {7, 8, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4505 {0, 8, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4506 {1, 8, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4507 {2, 8, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4508 {3, 8, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4509 {4, 8, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4510 {5, 8, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4511 {6, 8, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4512 {7, 8, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4513 D3DDECL_END(),
4514 };
4515 static const UINT sizes1[] =
4516 {
4517 4, 8, 12, 16,
4518 4, 4, 4, 8,
4519 4, 4, 8, 4,
4520 4, 4, 8, 0,
4521 };
4522 static const UINT sizes2[] =
4523 {
4524 12, 16, 20, 24,
4525 12, 12, 16, 16,
4526 };
4527 unsigned int i;
4528 UINT size;
4529
4530 size = D3DXGetDeclVertexSize(NULL, 0);
4531 ok(size == 0, "Got size %#x, expected 0.\n", size);
4532
4533 for (i = 0; i < 16; ++i)
4534 {
4535 size = D3DXGetDeclVertexSize(declaration1, i);
4536 ok(size == sizes1[i], "Got size %u for stream %u, expected %u.\n", size, i, sizes1[i]);
4537 }
4538
4539 for (i = 0; i < 8; ++i)
4540 {
4541 size = D3DXGetDeclVertexSize(declaration2, i);
4542 ok(size == sizes2[i], "Got size %u for stream %u, expected %u.\n", size, i, sizes2[i]);
4543 }
4544 }
4545
D3DXGenerateAdjacencyTest(void)4546 static void D3DXGenerateAdjacencyTest(void)
4547 {
4548 HRESULT hr;
4549 IDirect3DDevice9 *device;
4550 ID3DXMesh *d3dxmesh = NULL;
4551 D3DXVECTOR3 *vertices = NULL;
4552 WORD *indices = NULL;
4553 int i;
4554 struct {
4555 DWORD num_vertices;
4556 D3DXVECTOR3 vertices[6];
4557 DWORD num_faces;
4558 WORD indices[3 * 3];
4559 FLOAT epsilon;
4560 DWORD adjacency[3 * 3];
4561 } test_data[] = {
4562 { /* for epsilon < 0, indices must match for faces to be adjacent */
4563 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}},
4564 2, {0, 1, 2, 0, 2, 3},
4565 -1.0,
4566 {-1, -1, 1, 0, -1, -1},
4567 },
4568 {
4569 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}},
4570 2, {0, 1, 2, 3, 4, 5},
4571 -1.0,
4572 {-1, -1, -1, -1, -1, -1},
4573 },
4574 { /* for epsilon == 0, indices or vertices must match for faces to be adjacent */
4575 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}},
4576 2, {0, 1, 2, 3, 4, 5},
4577 0.0,
4578 {-1, -1, 1, 0, -1, -1},
4579 },
4580 { /* for epsilon > 0, vertices must be less than (but NOT equal to) epsilon distance away */
4581 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}},
4582 2, {0, 1, 2, 3, 4, 5},
4583 0.25,
4584 {-1, -1, -1, -1, -1, -1},
4585 },
4586 { /* for epsilon > 0, vertices must be less than (but NOT equal to) epsilon distance away */
4587 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}},
4588 2, {0, 1, 2, 3, 4, 5},
4589 0.250001,
4590 {-1, -1, 1, 0, -1, -1},
4591 },
4592 { /* length between vertices are compared to epsilon, not the individual dimension deltas */
4593 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}},
4594 2, {0, 1, 2, 3, 4, 5},
4595 0.353, /* < sqrt(0.25*0.25 + 0.25*0.25) */
4596 {-1, -1, -1, -1, -1, -1},
4597 },
4598 {
4599 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}},
4600 2, {0, 1, 2, 3, 4, 5},
4601 0.354, /* > sqrt(0.25*0.25 + 0.25*0.25) */
4602 {-1, -1, 1, 0, -1, -1},
4603 },
4604 { /* adjacent faces must have opposite winding orders at the shared edge */
4605 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}},
4606 2, {0, 1, 2, 0, 3, 2},
4607 0.0,
4608 {-1, -1, -1, -1, -1, -1},
4609 },
4610 };
4611 struct test_context *test_context;
4612
4613 if (!(test_context = new_test_context()))
4614 {
4615 skip("Couldn't create test context\n");
4616 return;
4617 }
4618 device = test_context->device;
4619
4620 for (i = 0; i < ARRAY_SIZE(test_data); i++)
4621 {
4622 DWORD adjacency[ARRAY_SIZE(test_data[0].adjacency)];
4623 int j;
4624
4625 if (d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh);
4626 d3dxmesh = NULL;
4627
4628 hr = D3DXCreateMeshFVF(test_data[i].num_faces, test_data[i].num_vertices, 0, D3DFVF_XYZ, device, &d3dxmesh);
4629 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
4630
4631 hr = d3dxmesh->lpVtbl->LockVertexBuffer(d3dxmesh, D3DLOCK_DISCARD, (void**)&vertices);
4632 ok(hr == D3D_OK, "test %d: Got result %x, expected %x (D3D_OK)\n", i, hr, D3D_OK);
4633 if (FAILED(hr)) continue;
4634 CopyMemory(vertices, test_data[i].vertices, test_data[i].num_vertices * sizeof(test_data[0].vertices[0]));
4635 d3dxmesh->lpVtbl->UnlockVertexBuffer(d3dxmesh);
4636
4637 hr = d3dxmesh->lpVtbl->LockIndexBuffer(d3dxmesh, D3DLOCK_DISCARD, (void**)&indices);
4638 ok(hr == D3D_OK, "test %d: Got result %x, expected %x (D3D_OK)\n", i, hr, D3D_OK);
4639 if (FAILED(hr)) continue;
4640 CopyMemory(indices, test_data[i].indices, test_data[i].num_faces * 3 * sizeof(test_data[0].indices[0]));
4641 d3dxmesh->lpVtbl->UnlockIndexBuffer(d3dxmesh);
4642
4643 if (i == 0) {
4644 hr = d3dxmesh->lpVtbl->GenerateAdjacency(d3dxmesh, 0.0f, NULL);
4645 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
4646 }
4647
4648 hr = d3dxmesh->lpVtbl->GenerateAdjacency(d3dxmesh, test_data[i].epsilon, adjacency);
4649 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
4650 if (FAILED(hr)) continue;
4651
4652 for (j = 0; j < test_data[i].num_faces * 3; j++)
4653 ok(adjacency[j] == test_data[i].adjacency[j],
4654 "Test %d adjacency %d: Got result %u, expected %u\n", i, j,
4655 adjacency[j], test_data[i].adjacency[j]);
4656 }
4657 if (d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh);
4658
4659 free_test_context(test_context);
4660 }
4661
test_update_semantics(void)4662 static void test_update_semantics(void)
4663 {
4664 HRESULT hr;
4665 struct test_context *test_context = NULL;
4666 ID3DXMesh *mesh = NULL;
4667 D3DVERTEXELEMENT9 declaration0[] =
4668 {
4669 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4670 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4671 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4672 D3DDECL_END()
4673 };
4674 D3DVERTEXELEMENT9 declaration_pos_type_color[] =
4675 {
4676 {0, 0, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4677 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4678 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4679 D3DDECL_END()
4680 };
4681 D3DVERTEXELEMENT9 declaration_smaller[] =
4682 {
4683 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4684 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4685 D3DDECL_END()
4686 };
4687 D3DVERTEXELEMENT9 declaration_larger[] =
4688 {
4689 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4690 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4691 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4692 {0, 40, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT, 0},
4693 D3DDECL_END()
4694 };
4695 D3DVERTEXELEMENT9 declaration_multiple_streams[] =
4696 {
4697 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4698 {1, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT, 0},
4699 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4700 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4701
4702 D3DDECL_END()
4703 };
4704 D3DVERTEXELEMENT9 declaration_double_usage[] =
4705 {
4706 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4707 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4708 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4709 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4710 D3DDECL_END()
4711 };
4712 D3DVERTEXELEMENT9 declaration_undefined_type[] =
4713 {
4714 {0, 0, D3DDECLTYPE_UNUSED+1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4715 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4716 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4717 D3DDECL_END()
4718 };
4719 D3DVERTEXELEMENT9 declaration_not_4_byte_aligned_offset[] =
4720 {
4721 {0, 3, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4722 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
4723 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4724 D3DDECL_END()
4725 };
4726 static const struct
4727 {
4728 D3DXVECTOR3 position0;
4729 D3DXVECTOR3 position1;
4730 D3DXVECTOR3 normal;
4731 DWORD color;
4732 }
4733 vertices[] =
4734 {
4735 { { 0.0f, 1.0f, 0.f}, { 1.0f, 0.0f, 0.f}, {0.0f, 0.0f, 1.0f}, 0xffff0000 },
4736 { { 1.0f, -1.0f, 0.f}, {-1.0f, -1.0f, 0.f}, {0.0f, 0.0f, 1.0f}, 0xff00ff00 },
4737 { {-1.0f, -1.0f, 0.f}, {-1.0f, 1.0f, 0.f}, {0.0f, 0.0f, 1.0f}, 0xff0000ff },
4738 };
4739 unsigned int faces[] = {0, 1, 2};
4740 unsigned int attributes[] = {0};
4741 unsigned int num_faces = ARRAY_SIZE(faces) / 3;
4742 unsigned int num_vertices = ARRAY_SIZE(vertices);
4743 int offset = sizeof(D3DXVECTOR3);
4744 DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
4745 void *vertex_buffer;
4746 void *index_buffer;
4747 DWORD *attributes_buffer;
4748 D3DVERTEXELEMENT9 declaration[MAX_FVF_DECL_SIZE];
4749 D3DVERTEXELEMENT9 *decl_ptr;
4750 DWORD exp_vertex_size = sizeof(*vertices);
4751 DWORD vertex_size = 0;
4752 int equal;
4753 int i = 0;
4754 int *decl_mem;
4755 int filler_a = 0xaaaaaaaa;
4756 int filler_b = 0xbbbbbbbb;
4757
4758 test_context = new_test_context();
4759 if (!test_context)
4760 {
4761 skip("Couldn't create a test_context\n");
4762 goto cleanup;
4763 }
4764
4765 hr = D3DXCreateMesh(num_faces, num_vertices, options, declaration0,
4766 test_context->device, &mesh);
4767 if (FAILED(hr))
4768 {
4769 skip("Couldn't create test mesh %#x\n", hr);
4770 goto cleanup;
4771 }
4772
4773 mesh->lpVtbl->LockVertexBuffer(mesh, 0, &vertex_buffer);
4774 memcpy(vertex_buffer, vertices, sizeof(vertices));
4775 mesh->lpVtbl->UnlockVertexBuffer(mesh);
4776
4777 mesh->lpVtbl->LockIndexBuffer(mesh, 0, &index_buffer);
4778 memcpy(index_buffer, faces, sizeof(faces));
4779 mesh->lpVtbl->UnlockIndexBuffer(mesh);
4780
4781 mesh->lpVtbl->LockAttributeBuffer(mesh, 0, &attributes_buffer);
4782 memcpy(attributes_buffer, attributes, sizeof(attributes));
4783 mesh->lpVtbl->UnlockAttributeBuffer(mesh);
4784
4785 /* Get the declaration and try to change it */
4786 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4787 if (FAILED(hr))
4788 {
4789 skip("Couldn't get vertex declaration %#x\n", hr);
4790 goto cleanup;
4791 }
4792 equal = memcmp(declaration, declaration0, sizeof(declaration0));
4793 ok(equal == 0, "Vertex declarations were not equal\n");
4794
4795 for (decl_ptr = declaration; decl_ptr->Stream != 0xFF; decl_ptr++)
4796 {
4797 if (decl_ptr->Usage == D3DDECLUSAGE_POSITION)
4798 {
4799 /* Use second vertex position instead of first */
4800 decl_ptr->Offset = offset;
4801 }
4802 }
4803
4804 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration);
4805 ok(hr == D3D_OK, "Test UpdateSemantics, got %#x expected %#x\n", hr, D3D_OK);
4806
4807 /* Check that declaration was written by getting it again */
4808 memset(declaration, 0, sizeof(declaration));
4809 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4810 if (FAILED(hr))
4811 {
4812 skip("Couldn't get vertex declaration %#x\n", hr);
4813 goto cleanup;
4814 }
4815
4816 for (decl_ptr = declaration; decl_ptr->Stream != 0xFF; decl_ptr++)
4817 {
4818 if (decl_ptr->Usage == D3DDECLUSAGE_POSITION)
4819 {
4820 ok(decl_ptr->Offset == offset, "Test UpdateSemantics, got offset %d expected %d\n",
4821 decl_ptr->Offset, offset);
4822 }
4823 }
4824
4825 /* Check that GetDeclaration only writes up to the D3DDECL_END() marker and
4826 * not the full MAX_FVF_DECL_SIZE elements.
4827 */
4828 memset(declaration, filler_a, sizeof(declaration));
4829 memcpy(declaration, declaration0, sizeof(declaration0));
4830 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration);
4831 ok(hr == D3D_OK, "Test UpdateSemantics, "
4832 "got %#x expected D3D_OK\n", hr);
4833 memset(declaration, filler_b, sizeof(declaration));
4834 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4835 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4836 decl_mem = (int*)declaration;
4837 for (i = sizeof(declaration0)/sizeof(*decl_mem); i < sizeof(declaration)/sizeof(*decl_mem); i++)
4838 {
4839 equal = memcmp(&decl_mem[i], &filler_b, sizeof(filler_b));
4840 ok(equal == 0,
4841 "GetDeclaration wrote past the D3DDECL_END() marker. "
4842 "Got %#x, expected %#x\n", decl_mem[i], filler_b);
4843 if (equal != 0) break;
4844 }
4845
4846 /* UpdateSemantics does not check for overlapping fields */
4847 memset(declaration, 0, sizeof(declaration));
4848 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4849 if (FAILED(hr))
4850 {
4851 skip("Couldn't get vertex declaration %#x\n", hr);
4852 goto cleanup;
4853 }
4854
4855 for (decl_ptr = declaration; decl_ptr->Stream != 0xFF; decl_ptr++)
4856 {
4857 if (decl_ptr->Type == D3DDECLTYPE_FLOAT3)
4858 {
4859 decl_ptr->Type = D3DDECLTYPE_FLOAT4;
4860 }
4861 }
4862
4863 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration);
4864 ok(hr == D3D_OK, "Test UpdateSemantics for overlapping fields, "
4865 "got %#x expected D3D_OK\n", hr);
4866
4867 /* Set the position type to color instead of float3 */
4868 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_pos_type_color);
4869 ok(hr == D3D_OK, "Test UpdateSemantics position type color, "
4870 "got %#x expected D3D_OK\n", hr);
4871
4872 /* The following test cases show that NULL, smaller or larger declarations,
4873 * and declarations with non-zero Stream values are not accepted.
4874 * UpdateSemantics returns D3DERR_INVALIDCALL and the previously set
4875 * declaration will be used by DrawSubset, GetNumBytesPerVertex, and
4876 * GetDeclaration.
4877 */
4878
4879 /* Null declaration (invalid declaration) */
4880 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4881 hr = mesh->lpVtbl->UpdateSemantics(mesh, NULL);
4882 ok(hr == D3DERR_INVALIDCALL, "Test UpdateSemantics null pointer declaration, "
4883 "got %#x expected D3DERR_INVALIDCALL\n", hr);
4884 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4885 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4886 vertex_size, exp_vertex_size);
4887 memset(declaration, 0, sizeof(declaration));
4888 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4889 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4890 equal = memcmp(declaration, declaration0, sizeof(declaration0));
4891 ok(equal == 0, "Vertex declarations were not equal\n");
4892
4893 /* Smaller vertex declaration (invalid declaration) */
4894 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4895 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_smaller);
4896 ok(hr == D3DERR_INVALIDCALL, "Test UpdateSemantics for smaller vertex declaration, "
4897 "got %#x expected D3DERR_INVALIDCALL\n", hr);
4898 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4899 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4900 vertex_size, exp_vertex_size);
4901 memset(declaration, 0, sizeof(declaration));
4902 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4903 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4904 equal = memcmp(declaration, declaration0, sizeof(declaration0));
4905 ok(equal == 0, "Vertex declarations were not equal\n");
4906
4907 /* Larger vertex declaration (invalid declaration) */
4908 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4909 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_larger);
4910 ok(hr == D3DERR_INVALIDCALL, "Test UpdateSemantics for larger vertex declaration, "
4911 "got %#x expected D3DERR_INVALIDCALL\n", hr);
4912 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4913 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4914 vertex_size, exp_vertex_size);
4915 memset(declaration, 0, sizeof(declaration));
4916 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4917 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4918 equal = memcmp(declaration, declaration0, sizeof(declaration0));
4919 ok(equal == 0, "Vertex declarations were not equal\n");
4920
4921 /* Use multiple streams and keep the same vertex size (invalid declaration) */
4922 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4923 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_multiple_streams);
4924 ok(hr == D3DERR_INVALIDCALL, "Test UpdateSemantics using multiple streams, "
4925 "got %#x expected D3DERR_INVALIDCALL\n", hr);
4926 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4927 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4928 vertex_size, exp_vertex_size);
4929 memset(declaration, 0, sizeof(declaration));
4930 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4931 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4932 equal = memcmp(declaration, declaration0, sizeof(declaration0));
4933 ok(equal == 0, "Vertex declarations were not equal\n");
4934
4935 /* The next following test cases show that some invalid declarations are
4936 * accepted with a D3D_OK. An access violation is thrown on Windows if
4937 * DrawSubset is called. The methods GetNumBytesPerVertex and GetDeclaration
4938 * are not affected, which indicates that the declaration is cached.
4939 */
4940
4941 /* Double usage (invalid declaration) */
4942 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4943 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_double_usage);
4944 ok(hr == D3D_OK, "Test UpdateSemantics double usage, "
4945 "got %#x expected D3D_OK\n", hr);
4946 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4947 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4948 vertex_size, exp_vertex_size);
4949 memset(declaration, 0, sizeof(declaration));
4950 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4951 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4952 equal = memcmp(declaration, declaration_double_usage, sizeof(declaration_double_usage));
4953 ok(equal == 0, "Vertex declarations were not equal\n");
4954
4955 /* Set the position to an undefined type (invalid declaration) */
4956 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4957 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_undefined_type);
4958 ok(hr == D3D_OK, "Test UpdateSemantics undefined type, "
4959 "got %#x expected D3D_OK\n", hr);
4960 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4961 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4962 vertex_size, exp_vertex_size);
4963 memset(declaration, 0, sizeof(declaration));
4964 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4965 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4966 equal = memcmp(declaration, declaration_undefined_type, sizeof(declaration_undefined_type));
4967 ok(equal == 0, "Vertex declarations were not equal\n");
4968
4969 /* Use a not 4 byte aligned offset (invalid declaration) */
4970 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
4971 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_not_4_byte_aligned_offset);
4972 ok(hr == D3D_OK, "Test UpdateSemantics not 4 byte aligned offset, "
4973 "got %#x expected D3D_OK\n", hr);
4974 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
4975 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
4976 vertex_size, exp_vertex_size);
4977 memset(declaration, 0, sizeof(declaration));
4978 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
4979 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
4980 equal = memcmp(declaration, declaration_not_4_byte_aligned_offset,
4981 sizeof(declaration_not_4_byte_aligned_offset));
4982 ok(equal == 0, "Vertex declarations were not equal\n");
4983
4984 cleanup:
4985 if (mesh)
4986 mesh->lpVtbl->Release(mesh);
4987
4988 free_test_context(test_context);
4989 }
4990
test_create_skin_info(void)4991 static void test_create_skin_info(void)
4992 {
4993 D3DVERTEXELEMENT9 empty_declaration[] = { D3DDECL_END() };
4994 D3DVERTEXELEMENT9 declaration_out[MAX_FVF_DECL_SIZE];
4995 const D3DVERTEXELEMENT9 declaration_with_nonzero_stream[] = {
4996 {1, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
4997 D3DDECL_END()
4998 };
4999 D3DVERTEXELEMENT9 declaration[MAX_FVF_DECL_SIZE];
5000 DWORD exp_vertices[2], vertices[2];
5001 float exp_weights[2], weights[2];
5002 const char *exp_string, *string;
5003 ID3DXSkinInfo *skininfo = NULL;
5004 DWORD exp_fvf, fvf;
5005 unsigned int i;
5006 HRESULT hr;
5007
5008 hr = D3DXCreateSkinInfo(0, empty_declaration, 0, &skininfo);
5009 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5010 if (skininfo) IUnknown_Release(skininfo);
5011 skininfo = NULL;
5012
5013 hr = D3DXCreateSkinInfo(1, NULL, 1, &skininfo);
5014 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5015
5016 hr = D3DXCreateSkinInfo(1, declaration_with_nonzero_stream, 1, &skininfo);
5017 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5018
5019 hr = D3DXCreateSkinInfoFVF(1, 0, 1, &skininfo);
5020 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5021 if (skininfo)
5022 {
5023 ID3DXSkinInfo *clone = NULL;
5024 DWORD dword_result;
5025 float flt_result;
5026 const char *string_result;
5027 D3DXMATRIX *transform;
5028 D3DXMATRIX identity_matrix;
5029
5030 /* test initial values */
5031 hr = skininfo->lpVtbl->GetDeclaration(skininfo, declaration_out);
5032 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5033 if (SUCCEEDED(hr))
5034 compare_elements(declaration_out, empty_declaration, __LINE__, 0);
5035
5036 dword_result = skininfo->lpVtbl->GetNumBones(skininfo);
5037 ok(dword_result == 1, "Expected 1, got %u\n", dword_result);
5038
5039 flt_result = skininfo->lpVtbl->GetMinBoneInfluence(skininfo);
5040 ok(flt_result == 0.0f, "Expected 0.0, got %g\n", flt_result);
5041
5042 string_result = skininfo->lpVtbl->GetBoneName(skininfo, 0);
5043 ok(string_result == NULL, "Expected NULL, got %p\n", string_result);
5044
5045 dword_result = skininfo->lpVtbl->GetFVF(skininfo);
5046 ok(dword_result == 0, "Expected 0, got %u\n", dword_result);
5047
5048 dword_result = skininfo->lpVtbl->GetNumBoneInfluences(skininfo, 0);
5049 ok(dword_result == 0, "Expected 0, got %u\n", dword_result);
5050
5051 dword_result = skininfo->lpVtbl->GetNumBoneInfluences(skininfo, 1);
5052 ok(dword_result == 0, "Expected 0, got %u\n", dword_result);
5053
5054 transform = skininfo->lpVtbl->GetBoneOffsetMatrix(skininfo, -1);
5055 ok(transform == NULL, "Expected NULL, got %p\n", transform);
5056
5057 hr = skininfo->lpVtbl->Clone(skininfo, &clone);
5058 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5059 IUnknown_Release(clone);
5060
5061 {
5062 /* test [GS]etBoneOffsetMatrix */
5063 hr = skininfo->lpVtbl->SetBoneOffsetMatrix(skininfo, 1, &identity_matrix);
5064 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5065
5066 hr = skininfo->lpVtbl->SetBoneOffsetMatrix(skininfo, 0, NULL);
5067 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5068
5069 D3DXMatrixIdentity(&identity_matrix);
5070 hr = skininfo->lpVtbl->SetBoneOffsetMatrix(skininfo, 0, &identity_matrix);
5071 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5072
5073 transform = skininfo->lpVtbl->GetBoneOffsetMatrix(skininfo, 0);
5074 check_matrix(transform, &identity_matrix);
5075 }
5076
5077 {
5078 /* test [GS]etBoneName */
5079 const char *name_in = "testBoneName";
5080 const char *string_result2;
5081
5082 hr = skininfo->lpVtbl->SetBoneName(skininfo, 1, name_in);
5083 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5084
5085 hr = skininfo->lpVtbl->SetBoneName(skininfo, 0, NULL);
5086 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5087
5088 hr = skininfo->lpVtbl->SetBoneName(skininfo, 0, name_in);
5089 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5090
5091 string_result = skininfo->lpVtbl->GetBoneName(skininfo, 0);
5092 ok(string_result != NULL, "Expected non-NULL string, got %p\n", string_result);
5093 ok(!strcmp(string_result, name_in), "Expected '%s', got '%s'\n", name_in, string_result);
5094
5095 string_result2 = skininfo->lpVtbl->GetBoneName(skininfo, 0);
5096 ok(string_result == string_result2, "Expected %p, got %p\n", string_result, string_result2);
5097
5098 string_result = skininfo->lpVtbl->GetBoneName(skininfo, 1);
5099 ok(string_result == NULL, "Expected NULL, got %p\n", string_result);
5100 }
5101
5102 {
5103 /* test [GS]etBoneInfluence */
5104 DWORD num_influences;
5105
5106 /* vertex and weight arrays untouched when num_influences is 0 */
5107 vertices[0] = 0xdeadbeef;
5108 weights[0] = FLT_MAX;
5109 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, vertices, weights);
5110 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5111 ok(vertices[0] == 0xdeadbeef, "expected 0xdeadbeef, got %#x\n", vertices[0]);
5112 ok(weights[0] == FLT_MAX, "expected %g, got %g\n", FLT_MAX, weights[0]);
5113
5114 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 1, vertices, weights);
5115 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5116
5117 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, NULL, NULL);
5118 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5119
5120 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, vertices, NULL);
5121 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5122
5123 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, NULL, weights);
5124 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5125
5126
5127 /* no vertex or weight value checking */
5128 exp_vertices[0] = 0;
5129 exp_vertices[1] = 0x87654321;
5130 exp_weights[0] = 0.5;
5131 exp_weights[1] = NAN;
5132 num_influences = 2;
5133
5134 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 1, num_influences, vertices, weights);
5135 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5136
5137 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, num_influences, NULL, weights);
5138 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5139
5140 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, num_influences, vertices, NULL);
5141 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5142
5143 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, num_influences, NULL, NULL);
5144 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5145
5146 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, num_influences, exp_vertices, exp_weights);
5147 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5148
5149 memset(vertices, 0, sizeof(vertices));
5150 memset(weights, 0, sizeof(weights));
5151 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, vertices, weights);
5152 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5153 for (i = 0; i < num_influences; i++) {
5154 ok(exp_vertices[i] == vertices[i],
5155 "influence[%d]: expected vertex %u, got %u\n", i, exp_vertices[i], vertices[i]);
5156 ok((isnan(exp_weights[i]) && isnan(weights[i])) || exp_weights[i] == weights[i],
5157 "influence[%d]: expected weights %g, got %g\n", i, exp_weights[i], weights[i]);
5158 }
5159
5160 /* vertices and weights aren't returned after setting num_influences to 0 */
5161 memset(vertices, 0, sizeof(vertices));
5162 memset(weights, 0, sizeof(weights));
5163 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, 0, vertices, weights);
5164 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5165
5166 vertices[0] = 0xdeadbeef;
5167 weights[0] = FLT_MAX;
5168 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, vertices, weights);
5169 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5170 ok(vertices[0] == 0xdeadbeef, "expected vertex 0xdeadbeef, got %u\n", vertices[0]);
5171 ok(weights[0] == FLT_MAX, "expected weight %g, got %g\n", FLT_MAX, weights[0]);
5172
5173 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, num_influences, exp_vertices, exp_weights);
5174 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5175 }
5176
5177 {
5178 /* test [GS]etFVF and [GS]etDeclaration */
5179 D3DVERTEXELEMENT9 declaration_in[MAX_FVF_DECL_SIZE];
5180 DWORD got_fvf;
5181
5182 fvf = D3DFVF_XYZ;
5183 hr = skininfo->lpVtbl->SetDeclaration(skininfo, NULL);
5184 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5185
5186 hr = skininfo->lpVtbl->SetDeclaration(skininfo, declaration_with_nonzero_stream);
5187 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5188
5189 hr = skininfo->lpVtbl->SetFVF(skininfo, 0);
5190 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5191
5192 hr = D3DXDeclaratorFromFVF(fvf, declaration_in);
5193 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5194 hr = skininfo->lpVtbl->SetDeclaration(skininfo, declaration_in);
5195 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5196 got_fvf = skininfo->lpVtbl->GetFVF(skininfo);
5197 ok(fvf == got_fvf, "Expected %#x, got %#x\n", fvf, got_fvf);
5198 hr = skininfo->lpVtbl->GetDeclaration(skininfo, declaration_out);
5199 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5200 compare_elements(declaration_out, declaration_in, __LINE__, 0);
5201
5202 hr = skininfo->lpVtbl->SetDeclaration(skininfo, empty_declaration);
5203 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5204 got_fvf = skininfo->lpVtbl->GetFVF(skininfo);
5205 ok(got_fvf == 0, "Expected 0, got %#x\n", got_fvf);
5206 hr = skininfo->lpVtbl->GetDeclaration(skininfo, declaration_out);
5207 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5208 compare_elements(declaration_out, empty_declaration, __LINE__, 0);
5209
5210 hr = skininfo->lpVtbl->SetFVF(skininfo, fvf);
5211 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5212 got_fvf = skininfo->lpVtbl->GetFVF(skininfo);
5213 ok(fvf == got_fvf, "Expected %#x, got %#x\n", fvf, got_fvf);
5214 hr = skininfo->lpVtbl->GetDeclaration(skininfo, declaration_out);
5215 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5216 compare_elements(declaration_out, declaration_in, __LINE__, 0);
5217 }
5218
5219 /* Test Clone() */
5220 hr = skininfo->lpVtbl->Clone(skininfo, NULL);
5221 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5222
5223 clone = NULL;
5224 hr = skininfo->lpVtbl->Clone(skininfo, &clone);
5225 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5226
5227 hr = clone->lpVtbl->GetDeclaration(clone, declaration);
5228 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5229 compare_elements(declaration, declaration_out, __LINE__, 0);
5230
5231 hr = D3DXFVFFromDeclarator(declaration_out, &exp_fvf);
5232 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5233 fvf = clone->lpVtbl->GetFVF(clone);
5234 ok(fvf == exp_fvf, "Got unexpected fvf %#x.\n", fvf);
5235
5236 exp_string = skininfo->lpVtbl->GetBoneName(skininfo, 0);
5237 string = clone->lpVtbl->GetBoneName(clone, 0);
5238 ok(!strcmp(string, exp_string), "Got unexpected bone 0 name %s.\n", debugstr_a(string));
5239
5240 transform = clone->lpVtbl->GetBoneOffsetMatrix(clone, 0);
5241 check_matrix(transform, &identity_matrix);
5242
5243 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, exp_vertices, exp_weights);
5244 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5245 hr = clone->lpVtbl->GetBoneInfluence(clone, 0, vertices, weights);
5246 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5247
5248 for (i = 0; i < ARRAY_SIZE(vertices); ++i)
5249 {
5250 ok(vertices[i] == exp_vertices[i], "influence[%u]: got unexpected vertex %u, expected %u.\n",
5251 i, vertices[i], exp_vertices[i]);
5252 ok(((DWORD *)weights)[i] == ((DWORD *)exp_weights)[i],
5253 "influence[%u]: got unexpected weight %.8e, expected %.8e.\n", i, weights[i], exp_weights[i]);
5254 }
5255
5256 IUnknown_Release(clone);
5257 }
5258 if (skininfo) IUnknown_Release(skininfo);
5259 skininfo = NULL;
5260
5261 hr = D3DXCreateSkinInfoFVF(1, D3DFVF_XYZ, 1, NULL);
5262 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5263
5264 hr = D3DXCreateSkinInfo(1, NULL, 1, &skininfo);
5265 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
5266 }
5267
test_update_skinned_mesh(void)5268 static void test_update_skinned_mesh(void)
5269 {
5270 static DWORD bone0_vertices[2] = { 1, 3 };
5271 static FLOAT bone0_weights[2] = { 1.0f, 0.5f };
5272 static DWORD bone1_vertices[2] = { 2, 3 };
5273 static FLOAT bone1_weights[2] = { 1.0f, 0.5f };
5274 static D3DMATRIX bones_matrix[2] =
5275 { { { {
5276 1.0f, 0.0f, 0.0f, 0.0f,
5277 0.0f, 1.0f, 0.0f, 0.0f,
5278 0.0f, 0.0f, 1.0f, 0.0f,
5279 2.0f, 2.0f, 4.0f, 1.0f
5280 } } },
5281 { { {
5282 1.0f, 0.0f, 0.0f, 0.0f,
5283 0.0f, 1.0f, 0.0f, 0.0f,
5284 0.0f, 0.0f, 1.0f, 0.0f,
5285 -4.0f, -4.0f, 4.0f, 1.0f
5286 } } } };
5287 static D3DVECTOR vertices_src[] = {{ 1.0f, 1.0f, 1.0f },
5288 { 1.0f, 0.0f, 0.0f },
5289 { 1.0f, 1.0f, -1.0f },
5290 { 0.0f, 1.0f, 0.0f },
5291 { -1.0f, -1.0f, 1.0f },
5292 { 0.0f, 0.0f, 1.0f },
5293 { -1.0f, -1.0f, -1.0f },
5294 { -1.0f, 0.0f, 0.0f },
5295 };
5296 static D3DVECTOR vertices_ref[] = {{ 0.0f, 0.0f, 0.0f },
5297 { 0.0f, 0.0f, 0.0f },
5298 { 3.0f, 3.0f, 3.0f },
5299 { 0.0f, 1.0f, 0.0f },
5300 { -5.0f, -5.0f, 5.0f },
5301 { 0.0f, 0.0f, 1.0f },
5302 { -2.0f, -2.0f, 3.0f },
5303 { -1.0f, 0.0f, 0.0f },
5304 };
5305 D3DVECTOR vertices_dest[8];
5306 HRESULT hr;
5307 ID3DXSkinInfo *skin_info;
5308 D3DXMATRIX matrix;
5309 int i;
5310
5311 D3DXMatrixIdentity(&matrix);
5312 for (i = 0; i < 8; i++)
5313 {
5314 vertices_dest[i].x = 10000.0f;
5315 vertices_dest[i].y = 10000.0f;
5316 vertices_dest[i].z = 10000.0f;
5317 }
5318
5319 hr = D3DXCreateSkinInfoFVF(4, D3DFVF_XYZ | D3DFVF_NORMAL, 2, &skin_info);
5320 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5321
5322 skin_info->lpVtbl->SetBoneInfluence(skin_info, 0, 2, bone0_vertices, bone0_weights);
5323 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5324 skin_info->lpVtbl->SetBoneOffsetMatrix(skin_info, 0, &matrix);
5325 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5326 skin_info->lpVtbl->SetBoneInfluence(skin_info, 1, 2, bone1_vertices, bone1_weights);
5327 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5328 skin_info->lpVtbl->SetBoneOffsetMatrix(skin_info, 1, &matrix);
5329 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5330 skin_info->lpVtbl->UpdateSkinnedMesh(skin_info, bones_matrix, NULL, vertices_src, vertices_dest);
5331 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
5332 for (i = 0; i < 4; i++)
5333 {
5334 ok(compare(vertices_dest[i*2].x, vertices_ref[i*2].x), "Vertex[%d].position.x: got %g, expected %g\n",
5335 i, vertices_dest[i*2].x, vertices_ref[i*2].x);
5336 ok(compare(vertices_dest[i*2].y, vertices_ref[i*2].y), "Vertex[%d].position.y: got %g, expected %g\n",
5337 i, vertices_dest[i*2].y, vertices_ref[i*2].y);
5338 ok(compare(vertices_dest[i*2].z, vertices_ref[i*2].z), "Vertex[%d].position.z: got %g, expected %g\n",
5339 i, vertices_dest[i*2].z, vertices_ref[i*2].z);
5340 ok(compare(vertices_dest[i*2+1].x, vertices_ref[i*2+1].x), "Vertex[%d].normal.x: got %g, expected %g\n",
5341 i, vertices_dest[i*2+1].x, vertices_ref[i*2+1].x);
5342 ok(compare(vertices_dest[i*2+1].y, vertices_ref[i*2+1].y), "Vertex[%d].normal.y: got %g, expected %g\n",
5343 i, vertices_dest[i*2+1].y, vertices_ref[i*2+1].y);
5344 ok(compare(vertices_dest[i*2+1].z, vertices_ref[i*2+1].z), "Vertex[%d].normal.z: got %g, expected %g\n",
5345 i, vertices_dest[i*2+1].z, vertices_ref[i*2+1].z);
5346 }
5347 skin_info->lpVtbl->Release(skin_info);
5348 }
5349
test_convert_adjacency_to_point_reps(void)5350 static void test_convert_adjacency_to_point_reps(void)
5351 {
5352 HRESULT hr;
5353 struct test_context *test_context = NULL;
5354 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
5355 const DWORD options_16bit = D3DXMESH_SYSTEMMEM;
5356 const D3DVERTEXELEMENT9 declaration[] =
5357 {
5358 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
5359 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
5360 {0, 24, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
5361 D3DDECL_END()
5362 };
5363 const unsigned int VERTS_PER_FACE = 3;
5364 void *vertex_buffer;
5365 void *index_buffer;
5366 DWORD *attributes_buffer;
5367 int i, j;
5368 enum color { RED = 0xffff0000, GREEN = 0xff00ff00, BLUE = 0xff0000ff};
5369 struct vertex_pnc
5370 {
5371 D3DXVECTOR3 position;
5372 D3DXVECTOR3 normal;
5373 enum color color; /* In case of manual visual inspection */
5374 };
5375 #ifndef __REACTOS__
5376 D3DXVECTOR3 up = {0.0f, 0.0f, 1.0f};
5377 #else
5378 #define up {0.0f, 0.0f, 1.0f}
5379 #endif
5380 /* mesh0 (one face)
5381 *
5382 * 0--1
5383 * | /
5384 * |/
5385 * 2
5386 */
5387 const struct vertex_pnc vertices0[] =
5388 {
5389 {{ 0.0f, 3.0f, 0.f}, up, RED},
5390 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5391 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5392 };
5393 const DWORD indices0[] = {0, 1, 2};
5394 const unsigned int num_vertices0 = ARRAY_SIZE(vertices0);
5395 const unsigned int num_faces0 = ARRAY_SIZE(indices0) / VERTS_PER_FACE;
5396 const DWORD adjacency0[] = {-1, -1, -1};
5397 const DWORD exp_point_rep0[] = {0, 1, 2};
5398 /* mesh1 (right)
5399 *
5400 * 0--1 3
5401 * | / /|
5402 * |/ / |
5403 * 2 5--4
5404 */
5405 const struct vertex_pnc vertices1[] =
5406 {
5407 {{ 0.0f, 3.0f, 0.f}, up, RED},
5408 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5409 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5410
5411 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5412 {{ 3.0f, 0.0f, 0.f}, up, RED},
5413 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5414 };
5415 const DWORD indices1[] = {0, 1, 2, 3, 4, 5};
5416 const unsigned int num_vertices1 = ARRAY_SIZE(vertices1);
5417 const unsigned int num_faces1 = ARRAY_SIZE(indices1) / VERTS_PER_FACE;
5418 const DWORD adjacency1[] = {-1, 1, -1, -1, -1, 0};
5419 const DWORD exp_point_rep1[] = {0, 1, 2, 1, 4, 2};
5420 /* mesh2 (left)
5421 *
5422 * 3 0--1
5423 * /| | /
5424 * / | |/
5425 * 5--4 2
5426 */
5427 const struct vertex_pnc vertices2[] =
5428 {
5429 {{ 0.0f, 3.0f, 0.f}, up, RED},
5430 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5431 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5432
5433 {{-1.0f, 3.0f, 0.f}, up, RED},
5434 {{-1.0f, 0.0f, 0.f}, up, GREEN},
5435 {{-3.0f, 0.0f, 0.f}, up, BLUE},
5436 };
5437 const DWORD indices2[] = {0, 1, 2, 3, 4, 5};
5438 const unsigned int num_vertices2 = ARRAY_SIZE(vertices2);
5439 const unsigned int num_faces2 = ARRAY_SIZE(indices2) / VERTS_PER_FACE;
5440 const DWORD adjacency2[] = {-1, -1, 1, 0, -1, -1};
5441 const DWORD exp_point_rep2[] = {0, 1, 2, 0, 2, 5};
5442 /* mesh3 (above)
5443 *
5444 * 3
5445 * /|
5446 * / |
5447 * 5--4
5448 * 0--1
5449 * | /
5450 * |/
5451 * 2
5452 */
5453 struct vertex_pnc vertices3[] =
5454 {
5455 {{ 0.0f, 3.0f, 0.f}, up, RED},
5456 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5457 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5458
5459 {{ 2.0f, 7.0f, 0.f}, up, BLUE},
5460 {{ 2.0f, 4.0f, 0.f}, up, GREEN},
5461 {{ 0.0f, 4.0f, 0.f}, up, RED},
5462 };
5463 const DWORD indices3[] = {0, 1, 2, 3, 4, 5};
5464 const unsigned int num_vertices3 = ARRAY_SIZE(vertices3);
5465 const unsigned int num_faces3 = ARRAY_SIZE(indices3) / VERTS_PER_FACE;
5466 const DWORD adjacency3[] = {1, -1, -1, -1, 0, -1};
5467 const DWORD exp_point_rep3[] = {0, 1, 2, 3, 1, 0};
5468 /* mesh4 (below, tip against tip)
5469 *
5470 * 0--1
5471 * | /
5472 * |/
5473 * 2
5474 * 3
5475 * |\
5476 * | \
5477 * 5--4
5478 */
5479 struct vertex_pnc vertices4[] =
5480 {
5481 {{ 0.0f, 3.0f, 0.f}, up, RED},
5482 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5483 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5484
5485 {{ 0.0f, -4.0f, 0.f}, up, BLUE},
5486 {{ 2.0f, -7.0f, 0.f}, up, GREEN},
5487 {{ 0.0f, -7.0f, 0.f}, up, RED},
5488 };
5489 const DWORD indices4[] = {0, 1, 2, 3, 4, 5};
5490 const unsigned int num_vertices4 = ARRAY_SIZE(vertices4);
5491 const unsigned int num_faces4 = ARRAY_SIZE(indices4) / VERTS_PER_FACE;
5492 const DWORD adjacency4[] = {-1, -1, -1, -1, -1, -1};
5493 const DWORD exp_point_rep4[] = {0, 1, 2, 3, 4, 5};
5494 /* mesh5 (gap in mesh)
5495 *
5496 * 0 3-----4 15
5497 * / \ \ / / \
5498 * / \ \ / / \
5499 * 2-----1 5 17-----16
5500 * 6-----7 9 12-----13
5501 * \ / / \ \ /
5502 * \ / / \ \ /
5503 * 8 10-----11 14
5504 *
5505 */
5506 const struct vertex_pnc vertices5[] =
5507 {
5508 {{ 0.0f, 1.0f, 0.f}, up, RED},
5509 {{ 1.0f, -1.0f, 0.f}, up, GREEN},
5510 {{-1.0f, -1.0f, 0.f}, up, BLUE},
5511
5512 {{ 0.1f, 1.0f, 0.f}, up, RED},
5513 {{ 2.1f, 1.0f, 0.f}, up, BLUE},
5514 {{ 1.1f, -1.0f, 0.f}, up, GREEN},
5515
5516 {{-1.0f, -1.1f, 0.f}, up, BLUE},
5517 {{ 1.0f, -1.1f, 0.f}, up, GREEN},
5518 {{ 0.0f, -3.1f, 0.f}, up, RED},
5519
5520 {{ 1.1f, -1.1f, 0.f}, up, GREEN},
5521 {{ 2.1f, -3.1f, 0.f}, up, BLUE},
5522 {{ 0.1f, -3.1f, 0.f}, up, RED},
5523
5524 {{ 1.2f, -1.1f, 0.f}, up, GREEN},
5525 {{ 3.2f, -1.1f, 0.f}, up, RED},
5526 {{ 2.2f, -3.1f, 0.f}, up, BLUE},
5527
5528 {{ 2.2f, 1.0f, 0.f}, up, BLUE},
5529 {{ 3.2f, -1.0f, 0.f}, up, RED},
5530 {{ 1.2f, -1.0f, 0.f}, up, GREEN},
5531 };
5532 const DWORD indices5[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17};
5533 const unsigned int num_vertices5 = ARRAY_SIZE(vertices5);
5534 const unsigned int num_faces5 = ARRAY_SIZE(indices5) / VERTS_PER_FACE;
5535 const DWORD adjacency5[] = {-1, 2, -1, -1, 5, -1, 0, -1, -1, 4, -1, -1, 5, -1, 3, -1, 4, 1};
5536 const DWORD exp_point_rep5[] = {0, 1, 2, 3, 4, 5, 2, 1, 8, 5, 10, 11, 5, 13, 10, 4, 13, 5};
5537 const WORD indices5_16bit[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17};
5538 /* mesh6 (indices re-ordering)
5539 *
5540 * 0--1 6 3
5541 * | / /| |\
5542 * |/ / | | \
5543 * 2 8--7 5--4
5544 */
5545 const struct vertex_pnc vertices6[] =
5546 {
5547 {{ 0.0f, 3.0f, 0.f}, up, RED},
5548 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5549 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5550
5551 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5552 {{ 3.0f, 0.0f, 0.f}, up, RED},
5553 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5554
5555 {{ 4.0f, 3.0f, 0.f}, up, GREEN},
5556 {{ 6.0f, 0.0f, 0.f}, up, BLUE},
5557 {{ 4.0f, 0.0f, 0.f}, up, RED},
5558 };
5559 const DWORD indices6[] = {0, 1, 2, 6, 7, 8, 3, 4, 5};
5560 const unsigned int num_vertices6 = ARRAY_SIZE(vertices6);
5561 const unsigned int num_faces6 = ARRAY_SIZE(indices6) / VERTS_PER_FACE;
5562 const DWORD adjacency6[] = {-1, 1, -1, 2, -1, 0, -1, -1, 1};
5563 const DWORD exp_point_rep6[] = {0, 1, 2, 1, 4, 5, 1, 5, 2};
5564 /* mesh7 (expands collapsed triangle)
5565 *
5566 * 0--1 3
5567 * | / /|
5568 * |/ / |
5569 * 2 5--4
5570 */
5571 const struct vertex_pnc vertices7[] =
5572 {
5573 {{ 0.0f, 3.0f, 0.f}, up, RED},
5574 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5575 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5576
5577 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5578 {{ 3.0f, 0.0f, 0.f}, up, RED},
5579 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5580 };
5581 const DWORD indices7[] = {0, 1, 2, 3, 3, 3}; /* Face 1 is collapsed*/
5582 const unsigned int num_vertices7 = ARRAY_SIZE(vertices7);
5583 const unsigned int num_faces7 = ARRAY_SIZE(indices7) / VERTS_PER_FACE;
5584 const DWORD adjacency7[] = {-1, -1, -1, -1, -1, -1};
5585 const DWORD exp_point_rep7[] = {0, 1, 2, 3, 4, 5};
5586 /* mesh8 (indices re-ordering and double replacement)
5587 *
5588 * 0--1 9 6
5589 * | / /| |\
5590 * |/ / | | \
5591 * 2 11-10 8--7
5592 * 3--4
5593 * | /
5594 * |/
5595 * 5
5596 */
5597 const struct vertex_pnc vertices8[] =
5598 {
5599 {{ 0.0f, 3.0f, 0.f}, up, RED},
5600 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5601 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5602
5603 {{ 4.0, -4.0, 0.f}, up, RED},
5604 {{ 6.0, -4.0, 0.f}, up, BLUE},
5605 {{ 4.0, -7.0, 0.f}, up, GREEN},
5606
5607 {{ 4.0f, 3.0f, 0.f}, up, GREEN},
5608 {{ 6.0f, 0.0f, 0.f}, up, BLUE},
5609 {{ 4.0f, 0.0f, 0.f}, up, RED},
5610
5611 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5612 {{ 3.0f, 0.0f, 0.f}, up, RED},
5613 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5614 };
5615 const DWORD indices8[] = {0, 1, 2, 9, 10, 11, 6, 7, 8, 3, 4, 5};
5616 const unsigned int num_vertices8 = ARRAY_SIZE(vertices8);
5617 const unsigned int num_faces8 = ARRAY_SIZE(indices8) / VERTS_PER_FACE;
5618 const DWORD adjacency8[] = {-1, 1, -1, 2, -1, 0, -1, 3, 1, 2, -1, -1};
5619 const DWORD exp_point_rep8[] = {0, 1, 2, 3, 4, 5, 1, 4, 3, 1, 3, 2};
5620 /* mesh9 (right, shared vertices)
5621 *
5622 * 0--1
5623 * | /|
5624 * |/ |
5625 * 2--3
5626 */
5627 const struct vertex_pnc vertices9[] =
5628 {
5629 {{ 0.0f, 3.0f, 0.f}, up, RED},
5630 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5631 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5632
5633 {{ 2.0f, 0.0f, 0.f}, up, RED},
5634 };
5635 const DWORD indices9[] = {0, 1, 2, 1, 3, 2};
5636 const unsigned int num_vertices9 = ARRAY_SIZE(vertices9);
5637 const unsigned int num_faces9 = ARRAY_SIZE(indices9) / VERTS_PER_FACE;
5638 const DWORD adjacency9[] = {-1, 1, -1, -1, -1, 0};
5639 const DWORD exp_point_rep9[] = {0, 1, 2, 3};
5640 /* All mesh data */
5641 ID3DXMesh *mesh = NULL;
5642 ID3DXMesh *mesh_null_check = NULL;
5643 unsigned int attributes[] = {0};
5644 struct
5645 {
5646 const struct vertex_pnc *vertices;
5647 const DWORD *indices;
5648 const DWORD num_vertices;
5649 const DWORD num_faces;
5650 const DWORD *adjacency;
5651 const DWORD *exp_point_reps;
5652 const DWORD options;
5653 }
5654 tc[] =
5655 {
5656 {
5657 vertices0,
5658 indices0,
5659 num_vertices0,
5660 num_faces0,
5661 adjacency0,
5662 exp_point_rep0,
5663 options
5664 },
5665 {
5666 vertices1,
5667 indices1,
5668 num_vertices1,
5669 num_faces1,
5670 adjacency1,
5671 exp_point_rep1,
5672 options
5673 },
5674 {
5675 vertices2,
5676 indices2,
5677 num_vertices2,
5678 num_faces2,
5679 adjacency2,
5680 exp_point_rep2,
5681 options
5682 },
5683 {
5684 vertices3,
5685 indices3,
5686 num_vertices3,
5687 num_faces3,
5688 adjacency3,
5689 exp_point_rep3,
5690 options
5691 },
5692 {
5693 vertices4,
5694 indices4,
5695 num_vertices4,
5696 num_faces4,
5697 adjacency4,
5698 exp_point_rep4,
5699 options
5700 },
5701 {
5702 vertices5,
5703 indices5,
5704 num_vertices5,
5705 num_faces5,
5706 adjacency5,
5707 exp_point_rep5,
5708 options
5709 },
5710 {
5711 vertices6,
5712 indices6,
5713 num_vertices6,
5714 num_faces6,
5715 adjacency6,
5716 exp_point_rep6,
5717 options
5718 },
5719 {
5720 vertices7,
5721 indices7,
5722 num_vertices7,
5723 num_faces7,
5724 adjacency7,
5725 exp_point_rep7,
5726 options
5727 },
5728 {
5729 vertices8,
5730 indices8,
5731 num_vertices8,
5732 num_faces8,
5733 adjacency8,
5734 exp_point_rep8,
5735 options
5736 },
5737 {
5738 vertices9,
5739 indices9,
5740 num_vertices9,
5741 num_faces9,
5742 adjacency9,
5743 exp_point_rep9,
5744 options
5745 },
5746 {
5747 vertices5,
5748 (DWORD*)indices5_16bit,
5749 num_vertices5,
5750 num_faces5,
5751 adjacency5,
5752 exp_point_rep5,
5753 options_16bit
5754 },
5755 };
5756 DWORD *point_reps = NULL;
5757
5758 test_context = new_test_context();
5759 if (!test_context)
5760 {
5761 skip("Couldn't create test context\n");
5762 goto cleanup;
5763 }
5764
5765 for (i = 0; i < ARRAY_SIZE(tc); i++)
5766 {
5767 hr = D3DXCreateMesh(tc[i].num_faces, tc[i].num_vertices, tc[i].options, declaration,
5768 test_context->device, &mesh);
5769 if (FAILED(hr))
5770 {
5771 skip("Couldn't create mesh %d. Got %x expected D3D_OK\n", i, hr);
5772 goto cleanup;
5773 }
5774
5775 if (i == 0) /* Save first mesh for later NULL checks */
5776 mesh_null_check = mesh;
5777
5778 point_reps = HeapAlloc(GetProcessHeap(), 0, tc[i].num_vertices * sizeof(*point_reps));
5779 if (!point_reps)
5780 {
5781 skip("Couldn't allocate point reps array.\n");
5782 goto cleanup;
5783 }
5784
5785 hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, &vertex_buffer);
5786 if (FAILED(hr))
5787 {
5788 skip("Couldn't lock vertex buffer.\n");
5789 goto cleanup;
5790 }
5791 memcpy(vertex_buffer, tc[i].vertices, tc[i].num_vertices * sizeof(*tc[i].vertices));
5792 hr = mesh->lpVtbl->UnlockVertexBuffer(mesh);
5793 if (FAILED(hr))
5794 {
5795 skip("Couldn't unlock vertex buffer.\n");
5796 goto cleanup;
5797 }
5798
5799 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, &index_buffer);
5800 if (FAILED(hr))
5801 {
5802 skip("Couldn't lock index buffer.\n");
5803 goto cleanup;
5804 }
5805 if (tc[i].options & D3DXMESH_32BIT)
5806 {
5807 memcpy(index_buffer, tc[i].indices, VERTS_PER_FACE * tc[i].num_faces * sizeof(DWORD));
5808 }
5809 else
5810 {
5811 memcpy(index_buffer, tc[i].indices, VERTS_PER_FACE * tc[i].num_faces * sizeof(WORD));
5812 }
5813 hr = mesh->lpVtbl->UnlockIndexBuffer(mesh);
5814 if (FAILED(hr)) {
5815 skip("Couldn't unlock index buffer.\n");
5816 goto cleanup;
5817 }
5818
5819 hr = mesh->lpVtbl->LockAttributeBuffer(mesh, 0, &attributes_buffer);
5820 if (FAILED(hr))
5821 {
5822 skip("Couldn't lock attributes buffer.\n");
5823 goto cleanup;
5824 }
5825 memcpy(attributes_buffer, attributes, sizeof(attributes));
5826 hr = mesh->lpVtbl->UnlockAttributeBuffer(mesh);
5827 if (FAILED(hr))
5828 {
5829 skip("Couldn't unlock attributes buffer.\n");
5830 goto cleanup;
5831 }
5832
5833 /* Convert adjacency to point representation */
5834 for (j = 0; j < tc[i].num_vertices; j++) point_reps[j] = -1;
5835 hr = mesh->lpVtbl->ConvertAdjacencyToPointReps(mesh, tc[i].adjacency, point_reps);
5836 ok(hr == D3D_OK, "ConvertAdjacencyToPointReps failed case %d. "
5837 "Got %x expected D3D_OK\n", i, hr);
5838
5839 /* Check point representation */
5840 for (j = 0; j < tc[i].num_vertices; j++)
5841 {
5842 ok(point_reps[j] == tc[i].exp_point_reps[j],
5843 "Unexpected point representation at (%d, %d)."
5844 " Got %d expected %d\n",
5845 i, j, point_reps[j], tc[i].exp_point_reps[j]);
5846 }
5847
5848 HeapFree(GetProcessHeap(), 0, point_reps);
5849 point_reps = NULL;
5850
5851 if (i != 0) /* First mesh will be freed during cleanup */
5852 mesh->lpVtbl->Release(mesh);
5853 }
5854
5855 /* NULL checks */
5856 hr = mesh_null_check->lpVtbl->ConvertAdjacencyToPointReps(mesh_null_check, tc[0].adjacency, NULL);
5857 ok(hr == D3DERR_INVALIDCALL, "ConvertAdjacencyToPointReps point_reps NULL. "
5858 "Got %x expected D3DERR_INVALIDCALL\n", hr);
5859 hr = mesh_null_check->lpVtbl->ConvertAdjacencyToPointReps(mesh_null_check, NULL, NULL);
5860 ok(hr == D3DERR_INVALIDCALL, "ConvertAdjacencyToPointReps adjacency and point_reps NULL. "
5861 "Got %x expected D3DERR_INVALIDCALL\n", hr);
5862
5863 cleanup:
5864 if (mesh_null_check)
5865 mesh_null_check->lpVtbl->Release(mesh_null_check);
5866 HeapFree(GetProcessHeap(), 0, point_reps);
5867 free_test_context(test_context);
5868 #ifdef __REACTOS__
5869 #undef up
5870 #endif
5871 }
5872
test_convert_point_reps_to_adjacency(void)5873 static void test_convert_point_reps_to_adjacency(void)
5874 {
5875 HRESULT hr;
5876 struct test_context *test_context = NULL;
5877 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
5878 const DWORD options_16bit = D3DXMESH_SYSTEMMEM;
5879 const D3DVERTEXELEMENT9 declaration[] =
5880 {
5881 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
5882 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
5883 {0, 24, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
5884 D3DDECL_END()
5885 };
5886 const unsigned int VERTS_PER_FACE = 3;
5887 void *vertex_buffer;
5888 void *index_buffer;
5889 DWORD *attributes_buffer;
5890 int i, j;
5891 enum color { RED = 0xffff0000, GREEN = 0xff00ff00, BLUE = 0xff0000ff};
5892 struct vertex_pnc
5893 {
5894 D3DXVECTOR3 position;
5895 D3DXVECTOR3 normal;
5896 enum color color; /* In case of manual visual inspection */
5897 };
5898 #ifndef __REACTOS__
5899 D3DXVECTOR3 up = {0.0f, 0.0f, 1.0f};
5900 #else
5901 #define up {0.0f, 0.0f, 1.0f}
5902 #endif
5903
5904 /* mesh0 (one face)
5905 *
5906 * 0--1
5907 * | /
5908 * |/
5909 * 2
5910 */
5911 const struct vertex_pnc vertices0[] =
5912 {
5913 {{ 0.0f, 3.0f, 0.f}, up, RED},
5914 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5915 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5916 };
5917 const DWORD indices0[] = {0, 1, 2};
5918 const unsigned int num_vertices0 = ARRAY_SIZE(vertices0);
5919 const unsigned int num_faces0 = num_vertices0 / VERTS_PER_FACE;
5920 const DWORD exp_adjacency0[] = {-1, -1, -1};
5921 const DWORD exp_id_adjacency0[] = {-1, -1, -1};
5922 const DWORD point_rep0[] = {0, 1, 2};
5923 /* mesh1 (right)
5924 *
5925 * 0--1 3
5926 * | / /|
5927 * |/ / |
5928 * 2 5--4
5929 */
5930 const struct vertex_pnc vertices1[] =
5931 {
5932 {{ 0.0f, 3.0f, 0.f}, up, RED},
5933 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5934 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5935
5936 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
5937 {{ 3.0f, 0.0f, 0.f}, up, RED},
5938 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
5939 };
5940 const DWORD indices1[] = {0, 1, 2, 3, 4, 5};
5941 const unsigned int num_vertices1 = ARRAY_SIZE(vertices1);
5942 const unsigned int num_faces1 = num_vertices1 / VERTS_PER_FACE;
5943 const DWORD exp_adjacency1[] = {-1, 1, -1, -1, -1, 0};
5944 const DWORD exp_id_adjacency1[] = {-1, -1, -1, -1, -1, -1};
5945 const DWORD point_rep1[] = {0, 1, 2, 1, 4, 2};
5946 /* mesh2 (left)
5947 *
5948 * 3 0--1
5949 * /| | /
5950 * / | |/
5951 * 5--4 2
5952 */
5953 const struct vertex_pnc vertices2[] =
5954 {
5955 {{ 0.0f, 3.0f, 0.f}, up, RED},
5956 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5957 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5958
5959 {{-1.0f, 3.0f, 0.f}, up, RED},
5960 {{-1.0f, 0.0f, 0.f}, up, GREEN},
5961 {{-3.0f, 0.0f, 0.f}, up, BLUE},
5962 };
5963 const DWORD indices2[] = {0, 1, 2, 3, 4, 5};
5964 const unsigned int num_vertices2 = ARRAY_SIZE(vertices2);
5965 const unsigned int num_faces2 = num_vertices2 / VERTS_PER_FACE;
5966 const DWORD exp_adjacency2[] = {-1, -1, 1, 0, -1, -1};
5967 const DWORD exp_id_adjacency2[] = {-1, -1, -1, -1, -1, -1};
5968 const DWORD point_rep2[] = {0, 1, 2, 0, 2, 5};
5969 /* mesh3 (above)
5970 *
5971 * 3
5972 * /|
5973 * / |
5974 * 5--4
5975 * 0--1
5976 * | /
5977 * |/
5978 * 2
5979 */
5980 struct vertex_pnc vertices3[] =
5981 {
5982 {{ 0.0f, 3.0f, 0.f}, up, RED},
5983 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
5984 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
5985
5986 {{ 2.0f, 7.0f, 0.f}, up, BLUE},
5987 {{ 2.0f, 4.0f, 0.f}, up, GREEN},
5988 {{ 0.0f, 4.0f, 0.f}, up, RED},
5989 };
5990 const DWORD indices3[] = {0, 1, 2, 3, 4, 5};
5991 const unsigned int num_vertices3 = ARRAY_SIZE(vertices3);
5992 const unsigned int num_faces3 = num_vertices3 / VERTS_PER_FACE;
5993 const DWORD exp_adjacency3[] = {1, -1, -1, -1, 0, -1};
5994 const DWORD exp_id_adjacency3[] = {-1, -1, -1, -1, -1, -1};
5995 const DWORD point_rep3[] = {0, 1, 2, 3, 1, 0};
5996 /* mesh4 (below, tip against tip)
5997 *
5998 * 0--1
5999 * | /
6000 * |/
6001 * 2
6002 * 3
6003 * |\
6004 * | \
6005 * 5--4
6006 */
6007 struct vertex_pnc vertices4[] =
6008 {
6009 {{ 0.0f, 3.0f, 0.f}, up, RED},
6010 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
6011 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
6012
6013 {{ 0.0f, -4.0f, 0.f}, up, BLUE},
6014 {{ 2.0f, -7.0f, 0.f}, up, GREEN},
6015 {{ 0.0f, -7.0f, 0.f}, up, RED},
6016 };
6017 const DWORD indices4[] = {0, 1, 2, 3, 4, 5};
6018 const unsigned int num_vertices4 = ARRAY_SIZE(vertices4);
6019 const unsigned int num_faces4 = num_vertices4 / VERTS_PER_FACE;
6020 const DWORD exp_adjacency4[] = {-1, -1, -1, -1, -1, -1};
6021 const DWORD exp_id_adjacency4[] = {-1, -1, -1, -1, -1, -1};
6022 const DWORD point_rep4[] = {0, 1, 2, 3, 4, 5};
6023 /* mesh5 (gap in mesh)
6024 *
6025 * 0 3-----4 15
6026 * / \ \ / / \
6027 * / \ \ / / \
6028 * 2-----1 5 17-----16
6029 * 6-----7 9 12-----13
6030 * \ / / \ \ /
6031 * \ / / \ \ /
6032 * 8 10-----11 14
6033 *
6034 */
6035 const struct vertex_pnc vertices5[] =
6036 {
6037 {{ 0.0f, 1.0f, 0.f}, up, RED},
6038 {{ 1.0f, -1.0f, 0.f}, up, GREEN},
6039 {{-1.0f, -1.0f, 0.f}, up, BLUE},
6040
6041 {{ 0.1f, 1.0f, 0.f}, up, RED},
6042 {{ 2.1f, 1.0f, 0.f}, up, BLUE},
6043 {{ 1.1f, -1.0f, 0.f}, up, GREEN},
6044
6045 {{-1.0f, -1.1f, 0.f}, up, BLUE},
6046 {{ 1.0f, -1.1f, 0.f}, up, GREEN},
6047 {{ 0.0f, -3.1f, 0.f}, up, RED},
6048
6049 {{ 1.1f, -1.1f, 0.f}, up, GREEN},
6050 {{ 2.1f, -3.1f, 0.f}, up, BLUE},
6051 {{ 0.1f, -3.1f, 0.f}, up, RED},
6052
6053 {{ 1.2f, -1.1f, 0.f}, up, GREEN},
6054 {{ 3.2f, -1.1f, 0.f}, up, RED},
6055 {{ 2.2f, -3.1f, 0.f}, up, BLUE},
6056
6057 {{ 2.2f, 1.0f, 0.f}, up, BLUE},
6058 {{ 3.2f, -1.0f, 0.f}, up, RED},
6059 {{ 1.2f, -1.0f, 0.f}, up, GREEN},
6060 };
6061 const DWORD indices5[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17};
6062 const unsigned int num_vertices5 = ARRAY_SIZE(vertices5);
6063 const unsigned int num_faces5 = num_vertices5 / VERTS_PER_FACE;
6064 const DWORD exp_adjacency5[] = {-1, 2, -1, -1, 5, -1, 0, -1, -1, 4, -1, -1, 5, -1, 3, -1, 4, 1};
6065 const DWORD exp_id_adjacency5[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
6066 const DWORD point_rep5[] = {0, 1, 2, 3, 4, 5, 2, 1, 8, 5, 10, 11, 5, 13, 10, 4, 13, 5};
6067 /* mesh6 (indices re-ordering)
6068 *
6069 * 0--1 6 3
6070 * | / /| |\
6071 * |/ / | | \
6072 * 2 8--7 5--4
6073 */
6074 const struct vertex_pnc vertices6[] =
6075 {
6076 {{ 0.0f, 3.0f, 0.f}, up, RED},
6077 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
6078 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
6079
6080 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
6081 {{ 3.0f, 0.0f, 0.f}, up, RED},
6082 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
6083
6084 {{ 4.0f, 3.0f, 0.f}, up, GREEN},
6085 {{ 6.0f, 0.0f, 0.f}, up, BLUE},
6086 {{ 4.0f, 0.0f, 0.f}, up, RED},
6087 };
6088 const DWORD indices6[] = {0, 1, 2, 6, 7, 8, 3, 4, 5};
6089 const unsigned int num_vertices6 = ARRAY_SIZE(vertices6);
6090 const unsigned int num_faces6 = num_vertices6 / VERTS_PER_FACE;
6091 const DWORD exp_adjacency6[] = {-1, 1, -1, 2, -1, 0, -1, -1, 1};
6092 const DWORD exp_id_adjacency6[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1};
6093 const DWORD point_rep6[] = {0, 1, 2, 1, 4, 5, 1, 5, 2};
6094 /* mesh7 (expands collapsed triangle)
6095 *
6096 * 0--1 3
6097 * | / /|
6098 * |/ / |
6099 * 2 5--4
6100 */
6101 const struct vertex_pnc vertices7[] =
6102 {
6103 {{ 0.0f, 3.0f, 0.f}, up, RED},
6104 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
6105 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
6106
6107 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
6108 {{ 3.0f, 0.0f, 0.f}, up, RED},
6109 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
6110 };
6111 const DWORD indices7[] = {0, 1, 2, 3, 3, 3}; /* Face 1 is collapsed*/
6112 const unsigned int num_vertices7 = ARRAY_SIZE(vertices7);
6113 const unsigned int num_faces7 = num_vertices7 / VERTS_PER_FACE;
6114 const DWORD exp_adjacency7[] = {-1, -1, -1, -1, -1, -1};
6115 const DWORD exp_id_adjacency7[] = {-1, -1, -1, -1, -1, -1};
6116 const DWORD point_rep7[] = {0, 1, 2, 3, 4, 5};
6117 /* mesh8 (indices re-ordering and double replacement)
6118 *
6119 * 0--1 9 6
6120 * | / /| |\
6121 * |/ / | | \
6122 * 2 11-10 8--7
6123 * 3--4
6124 * | /
6125 * |/
6126 * 5
6127 */
6128 const struct vertex_pnc vertices8[] =
6129 {
6130 {{ 0.0f, 3.0f, 0.f}, up, RED},
6131 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
6132 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
6133
6134 {{ 4.0, -4.0, 0.f}, up, RED},
6135 {{ 6.0, -4.0, 0.f}, up, BLUE},
6136 {{ 4.0, -7.0, 0.f}, up, GREEN},
6137
6138 {{ 4.0f, 3.0f, 0.f}, up, GREEN},
6139 {{ 6.0f, 0.0f, 0.f}, up, BLUE},
6140 {{ 4.0f, 0.0f, 0.f}, up, RED},
6141
6142 {{ 3.0f, 3.0f, 0.f}, up, GREEN},
6143 {{ 3.0f, 0.0f, 0.f}, up, RED},
6144 {{ 1.0f, 0.0f, 0.f}, up, BLUE},
6145 };
6146 const DWORD indices8[] = {0, 1, 2, 9, 10, 11, 6, 7, 8, 3, 4, 5};
6147 const WORD indices8_16bit[] = {0, 1, 2, 9, 10, 11, 6, 7, 8, 3, 4, 5};
6148 const unsigned int num_vertices8 = ARRAY_SIZE(vertices8);
6149 const unsigned int num_faces8 = num_vertices8 / VERTS_PER_FACE;
6150 const DWORD exp_adjacency8[] = {-1, 1, -1, 2, -1, 0, -1, 3, 1, 2, -1, -1};
6151 const DWORD exp_id_adjacency8[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
6152 const DWORD point_rep8[] = {0, 1, 2, 3, 4, 5, 1, 4, 3, 1, 3, 2};
6153 /* mesh9 (right, shared vertices)
6154 *
6155 * 0--1
6156 * | /|
6157 * |/ |
6158 * 2--3
6159 */
6160 const struct vertex_pnc vertices9[] =
6161 {
6162 {{ 0.0f, 3.0f, 0.f}, up, RED},
6163 {{ 2.0f, 3.0f, 0.f}, up, GREEN},
6164 {{ 0.0f, 0.0f, 0.f}, up, BLUE},
6165
6166 {{ 2.0f, 0.0f, 0.f}, up, RED},
6167 };
6168 const DWORD indices9[] = {0, 1, 2, 1, 3, 2};
6169 const unsigned int num_vertices9 = ARRAY_SIZE(vertices9);
6170 const unsigned int num_faces9 = 2;
6171 const DWORD exp_adjacency9[] = {-1, 1, -1, -1, -1, 0};
6172 const DWORD exp_id_adjacency9[] = {-1, 1, -1, -1, -1, 0};
6173 const DWORD point_rep9[] = {0, 1, 2, 3};
6174 /* All mesh data */
6175 ID3DXMesh *mesh = NULL;
6176 ID3DXMesh *mesh_null_check = NULL;
6177 unsigned int attributes[] = {0};
6178 struct
6179 {
6180 const struct vertex_pnc *vertices;
6181 const DWORD *indices;
6182 const DWORD num_vertices;
6183 const DWORD num_faces;
6184 const DWORD *point_reps;
6185 const DWORD *exp_adjacency;
6186 const DWORD *exp_id_adjacency;
6187 const DWORD options;
6188 }
6189 tc[] =
6190 {
6191 {
6192 vertices0,
6193 indices0,
6194 num_vertices0,
6195 num_faces0,
6196 point_rep0,
6197 exp_adjacency0,
6198 exp_id_adjacency0,
6199 options
6200 },
6201 {
6202 vertices1,
6203 indices1,
6204 num_vertices1,
6205 num_faces1,
6206 point_rep1,
6207 exp_adjacency1,
6208 exp_id_adjacency1,
6209 options
6210 },
6211 {
6212 vertices2,
6213 indices2,
6214 num_vertices2,
6215 num_faces2,
6216 point_rep2,
6217 exp_adjacency2,
6218 exp_id_adjacency2,
6219 options
6220 },
6221 {
6222 vertices3,
6223 indices3,
6224 num_vertices3,
6225 num_faces3,
6226 point_rep3,
6227 exp_adjacency3,
6228 exp_id_adjacency3,
6229 options
6230 },
6231 {
6232 vertices4,
6233 indices4,
6234 num_vertices4,
6235 num_faces4,
6236 point_rep4,
6237 exp_adjacency4,
6238 exp_id_adjacency4,
6239 options
6240 },
6241 {
6242 vertices5,
6243 indices5,
6244 num_vertices5,
6245 num_faces5,
6246 point_rep5,
6247 exp_adjacency5,
6248 exp_id_adjacency5,
6249 options
6250 },
6251 {
6252 vertices6,
6253 indices6,
6254 num_vertices6,
6255 num_faces6,
6256 point_rep6,
6257 exp_adjacency6,
6258 exp_id_adjacency6,
6259 options
6260 },
6261 {
6262 vertices7,
6263 indices7,
6264 num_vertices7,
6265 num_faces7,
6266 point_rep7,
6267 exp_adjacency7,
6268 exp_id_adjacency7,
6269 options
6270 },
6271 {
6272 vertices8,
6273 indices8,
6274 num_vertices8,
6275 num_faces8,
6276 point_rep8,
6277 exp_adjacency8,
6278 exp_id_adjacency8,
6279 options
6280 },
6281 {
6282 vertices9,
6283 indices9,
6284 num_vertices9,
6285 num_faces9,
6286 point_rep9,
6287 exp_adjacency9,
6288 exp_id_adjacency9,
6289 options
6290 },
6291 {
6292 vertices8,
6293 (DWORD*)indices8_16bit,
6294 num_vertices8,
6295 num_faces8,
6296 point_rep8,
6297 exp_adjacency8,
6298 exp_id_adjacency8,
6299 options_16bit
6300 },
6301 };
6302 DWORD *adjacency = NULL;
6303 #ifdef __REACTOS__
6304 #undef up
6305 #endif
6306
6307 test_context = new_test_context();
6308 if (!test_context)
6309 {
6310 skip("Couldn't create test context\n");
6311 goto cleanup;
6312 }
6313
6314 for (i = 0; i < ARRAY_SIZE(tc); i++)
6315 {
6316 hr = D3DXCreateMesh(tc[i].num_faces, tc[i].num_vertices, tc[i].options,
6317 declaration, test_context->device, &mesh);
6318 if (FAILED(hr))
6319 {
6320 skip("Couldn't create mesh %d. Got %x expected D3D_OK\n", i, hr);
6321 goto cleanup;
6322 }
6323
6324 if (i == 0) /* Save first mesh for later NULL checks */
6325 mesh_null_check = mesh;
6326
6327 adjacency = HeapAlloc(GetProcessHeap(), 0, VERTS_PER_FACE * tc[i].num_faces * sizeof(*adjacency));
6328 if (!adjacency)
6329 {
6330 skip("Couldn't allocate adjacency array.\n");
6331 goto cleanup;
6332 }
6333
6334 hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, &vertex_buffer);
6335 if (FAILED(hr))
6336 {
6337 skip("Couldn't lock vertex buffer.\n");
6338 goto cleanup;
6339 }
6340 memcpy(vertex_buffer, tc[i].vertices, tc[i].num_vertices * sizeof(*tc[i].vertices));
6341 hr = mesh->lpVtbl->UnlockVertexBuffer(mesh);
6342 if (FAILED(hr))
6343 {
6344 skip("Couldn't unlock vertex buffer.\n");
6345 goto cleanup;
6346 }
6347 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, &index_buffer);
6348 if (FAILED(hr))
6349 {
6350 skip("Couldn't lock index buffer.\n");
6351 goto cleanup;
6352 }
6353 if (tc[i].options & D3DXMESH_32BIT)
6354 {
6355 memcpy(index_buffer, tc[i].indices, VERTS_PER_FACE * tc[i].num_faces * sizeof(DWORD));
6356 }
6357 else
6358 {
6359 memcpy(index_buffer, tc[i].indices, VERTS_PER_FACE * tc[i].num_faces * sizeof(WORD));
6360 }
6361 hr = mesh->lpVtbl->UnlockIndexBuffer(mesh);
6362 if (FAILED(hr)) {
6363 skip("Couldn't unlock index buffer.\n");
6364 goto cleanup;
6365 }
6366
6367 hr = mesh->lpVtbl->LockAttributeBuffer(mesh, 0, &attributes_buffer);
6368 if (FAILED(hr))
6369 {
6370 skip("Couldn't lock attributes buffer.\n");
6371 goto cleanup;
6372 }
6373 memcpy(attributes_buffer, attributes, sizeof(attributes));
6374 hr = mesh->lpVtbl->UnlockAttributeBuffer(mesh);
6375 if (FAILED(hr))
6376 {
6377 skip("Couldn't unlock attributes buffer.\n");
6378 goto cleanup;
6379 }
6380
6381 /* Convert point representation to adjacency*/
6382 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++) adjacency[j] = -2;
6383
6384 hr = mesh->lpVtbl->ConvertPointRepsToAdjacency(mesh, tc[i].point_reps, adjacency);
6385 ok(hr == D3D_OK, "ConvertPointRepsToAdjacency failed case %d. "
6386 "Got %x expected D3D_OK\n", i, hr);
6387 /* Check adjacency */
6388 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
6389 {
6390 ok(adjacency[j] == tc[i].exp_adjacency[j],
6391 "Unexpected adjacency information at (%d, %d)."
6392 " Got %d expected %d\n",
6393 i, j, adjacency[j], tc[i].exp_adjacency[j]);
6394 }
6395
6396 /* NULL point representation is considered identity. */
6397 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++) adjacency[j] = -2;
6398 hr = mesh_null_check->lpVtbl->ConvertPointRepsToAdjacency(mesh, NULL, adjacency);
6399 ok(hr == D3D_OK, "ConvertPointRepsToAdjacency NULL point_reps. "
6400 "Got %x expected D3D_OK\n", hr);
6401 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
6402 {
6403 ok(adjacency[j] == tc[i].exp_id_adjacency[j],
6404 "Unexpected adjacency information (id) at (%d, %d)."
6405 " Got %d expected %d\n",
6406 i, j, adjacency[j], tc[i].exp_id_adjacency[j]);
6407 }
6408
6409 HeapFree(GetProcessHeap(), 0, adjacency);
6410 adjacency = NULL;
6411 if (i != 0) /* First mesh will be freed during cleanup */
6412 mesh->lpVtbl->Release(mesh);
6413 }
6414
6415 /* NULL checks */
6416 hr = mesh_null_check->lpVtbl->ConvertPointRepsToAdjacency(mesh_null_check, tc[0].point_reps, NULL);
6417 ok(hr == D3DERR_INVALIDCALL, "ConvertPointRepsToAdjacency NULL adjacency. "
6418 "Got %x expected D3DERR_INVALIDCALL\n", hr);
6419 hr = mesh_null_check->lpVtbl->ConvertPointRepsToAdjacency(mesh_null_check, NULL, NULL);
6420 ok(hr == D3DERR_INVALIDCALL, "ConvertPointRepsToAdjacency NULL point_reps and adjacency. "
6421 "Got %x expected D3DERR_INVALIDCALL\n", hr);
6422
6423 cleanup:
6424 if (mesh_null_check)
6425 mesh_null_check->lpVtbl->Release(mesh_null_check);
6426 HeapFree(GetProcessHeap(), 0, adjacency);
6427 free_test_context(test_context);
6428 }
6429
init_test_mesh(const DWORD num_faces,const DWORD num_vertices,const DWORD options,const D3DVERTEXELEMENT9 * declaration,IDirect3DDevice9 * device,ID3DXMesh ** mesh_ptr,const void * vertices,const DWORD vertex_size,const DWORD * indices,const DWORD * attributes)6430 static HRESULT init_test_mesh(const DWORD num_faces, const DWORD num_vertices,
6431 const DWORD options,
6432 const D3DVERTEXELEMENT9 *declaration,
6433 IDirect3DDevice9 *device, ID3DXMesh **mesh_ptr,
6434 const void *vertices, const DWORD vertex_size,
6435 const DWORD *indices, const DWORD *attributes)
6436 {
6437 HRESULT hr;
6438 void *vertex_buffer;
6439 void *index_buffer;
6440 DWORD *attributes_buffer;
6441 ID3DXMesh *mesh = NULL;
6442
6443 hr = D3DXCreateMesh(num_faces, num_vertices, options, declaration, device, mesh_ptr);
6444 if (FAILED(hr))
6445 {
6446 skip("Couldn't create mesh. Got %x expected D3D_OK\n", hr);
6447 goto cleanup;
6448 }
6449 mesh = *mesh_ptr;
6450
6451 hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, &vertex_buffer);
6452 if (FAILED(hr))
6453 {
6454 skip("Couldn't lock vertex buffer.\n");
6455 goto cleanup;
6456 }
6457 memcpy(vertex_buffer, vertices, num_vertices * vertex_size);
6458 hr = mesh->lpVtbl->UnlockVertexBuffer(mesh);
6459 if (FAILED(hr))
6460 {
6461 skip("Couldn't unlock vertex buffer.\n");
6462 goto cleanup;
6463 }
6464
6465 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, &index_buffer);
6466 if (FAILED(hr))
6467 {
6468 skip("Couldn't lock index buffer.\n");
6469 goto cleanup;
6470 }
6471 if (options & D3DXMESH_32BIT)
6472 {
6473 if (indices)
6474 memcpy(index_buffer, indices, 3 * num_faces * sizeof(DWORD));
6475 else
6476 {
6477 /* Fill index buffer with 0, 1, 2, ...*/
6478 DWORD *indices_32bit = (DWORD*)index_buffer;
6479 UINT i;
6480 for (i = 0; i < 3 * num_faces; i++)
6481 indices_32bit[i] = i;
6482 }
6483 }
6484 else
6485 {
6486 if (indices)
6487 memcpy(index_buffer, indices, 3 * num_faces * sizeof(WORD));
6488 else
6489 {
6490 /* Fill index buffer with 0, 1, 2, ...*/
6491 WORD *indices_16bit = (WORD*)index_buffer;
6492 UINT i;
6493 for (i = 0; i < 3 * num_faces; i++)
6494 indices_16bit[i] = i;
6495 }
6496 }
6497 hr = mesh->lpVtbl->UnlockIndexBuffer(mesh);
6498 if (FAILED(hr)) {
6499 skip("Couldn't unlock index buffer.\n");
6500 goto cleanup;
6501 }
6502
6503 hr = mesh->lpVtbl->LockAttributeBuffer(mesh, 0, &attributes_buffer);
6504 if (FAILED(hr))
6505 {
6506 skip("Couldn't lock attributes buffer.\n");
6507 goto cleanup;
6508 }
6509
6510 if (attributes)
6511 memcpy(attributes_buffer, attributes, num_faces * sizeof(*attributes));
6512 else
6513 memset(attributes_buffer, 0, num_faces * sizeof(*attributes));
6514
6515 hr = mesh->lpVtbl->UnlockAttributeBuffer(mesh);
6516 if (FAILED(hr))
6517 {
6518 skip("Couldn't unlock attributes buffer.\n");
6519 goto cleanup;
6520 }
6521
6522 hr = D3D_OK;
6523 cleanup:
6524 return hr;
6525 }
6526
6527 /* Using structs instead of bit-fields in order to avoid compiler issues. */
6528 struct udec3
6529 {
6530 UINT x;
6531 UINT y;
6532 UINT z;
6533 UINT w;
6534 };
6535
6536 struct dec3n
6537 {
6538 INT x;
6539 INT y;
6540 INT z;
6541 INT w;
6542 };
6543
init_udec3_dword(UINT x,UINT y,UINT z,UINT w)6544 static DWORD init_udec3_dword(UINT x, UINT y, UINT z, UINT w)
6545 {
6546 DWORD d = 0;
6547
6548 d |= x & 0x3ff;
6549 d |= (y << 10) & 0xffc00;
6550 d |= (z << 20) & 0x3ff00000;
6551 d |= (w << 30) & 0xc0000000;
6552
6553 return d;
6554 }
6555
init_dec3n_dword(INT x,INT y,INT z,INT w)6556 static DWORD init_dec3n_dword(INT x, INT y, INT z, INT w)
6557 {
6558 DWORD d = 0;
6559
6560 d |= x & 0x3ff;
6561 d |= (y << 10) & 0xffc00;
6562 d |= (z << 20) & 0x3ff00000;
6563 d |= (w << 30) & 0xc0000000;
6564
6565 return d;
6566 }
6567
dword_to_udec3(DWORD d)6568 static struct udec3 dword_to_udec3(DWORD d)
6569 {
6570 struct udec3 v;
6571
6572 v.x = d & 0x3ff;
6573 v.y = (d & 0xffc00) >> 10;
6574 v.z = (d & 0x3ff00000) >> 20;
6575 v.w = (d & 0xc0000000) >> 30;
6576
6577 return v;
6578 }
6579
dword_to_dec3n(DWORD d)6580 static struct dec3n dword_to_dec3n(DWORD d)
6581 {
6582 struct dec3n v;
6583
6584 v.x = d & 0x3ff;
6585 v.y = (d & 0xffc00) >> 10;
6586 v.z = (d & 0x3ff00000) >> 20;
6587 v.w = (d & 0xc0000000) >> 30;
6588
6589 return v;
6590 }
6591
check_vertex_components(int line,int mesh_number,int vertex_number,BYTE * got_ptr,const BYTE * exp_ptr,D3DVERTEXELEMENT9 * declaration)6592 static void check_vertex_components(int line, int mesh_number, int vertex_number, BYTE *got_ptr, const BYTE *exp_ptr, D3DVERTEXELEMENT9 *declaration)
6593 {
6594 const char *usage_strings[] =
6595 {
6596 "position",
6597 "blend weight",
6598 "blend indices",
6599 "normal",
6600 "point size",
6601 "texture coordinates",
6602 "tangent",
6603 "binormal",
6604 "tessellation factor",
6605 "position transformed",
6606 "color",
6607 "fog",
6608 "depth",
6609 "sample"
6610 };
6611 D3DVERTEXELEMENT9 *decl_ptr;
6612 const float PRECISION = 1e-5f;
6613
6614 for (decl_ptr = declaration; decl_ptr->Stream != 0xFF; decl_ptr++)
6615 {
6616 switch (decl_ptr->Type)
6617 {
6618 case D3DDECLTYPE_FLOAT1:
6619 {
6620 FLOAT *got = (FLOAT*)(got_ptr + decl_ptr->Offset);
6621 FLOAT *exp = (FLOAT*)(exp_ptr + decl_ptr->Offset);
6622 FLOAT diff = fabsf(*got - *exp);
6623 ok_(__FILE__,line)(diff <= PRECISION, "Mesh %d: Got %f for vertex %d %s, expected %f.\n",
6624 mesh_number, *got, vertex_number, usage_strings[decl_ptr->Usage], *exp);
6625 break;
6626 }
6627 case D3DDECLTYPE_FLOAT2:
6628 {
6629 D3DXVECTOR2 *got = (D3DXVECTOR2*)(got_ptr + decl_ptr->Offset);
6630 D3DXVECTOR2 *exp = (D3DXVECTOR2*)(exp_ptr + decl_ptr->Offset);
6631 FLOAT diff = max(fabsf(got->x - exp->x), fabsf(got->y - exp->y));
6632 ok_(__FILE__,line)(diff <= PRECISION, "Mesh %d: Got (%f, %f) for vertex %d %s, expected (%f, %f).\n",
6633 mesh_number, got->x, got->y, vertex_number, usage_strings[decl_ptr->Usage], exp->x, exp->y);
6634 break;
6635 }
6636 case D3DDECLTYPE_FLOAT3:
6637 {
6638 D3DXVECTOR3 *got = (D3DXVECTOR3*)(got_ptr + decl_ptr->Offset);
6639 D3DXVECTOR3 *exp = (D3DXVECTOR3*)(exp_ptr + decl_ptr->Offset);
6640 FLOAT diff = max(fabsf(got->x - exp->x), fabsf(got->y - exp->y));
6641 diff = max(diff, fabsf(got->z - exp->z));
6642 ok_(__FILE__,line)(diff <= PRECISION, "Mesh %d: Got (%f, %f, %f) for vertex %d %s, expected (%f, %f, %f).\n",
6643 mesh_number, got->x, got->y, got->z, vertex_number, usage_strings[decl_ptr->Usage], exp->x, exp->y, exp->z);
6644 break;
6645 }
6646 case D3DDECLTYPE_FLOAT4:
6647 {
6648 D3DXVECTOR4 *got = (D3DXVECTOR4*)(got_ptr + decl_ptr->Offset);
6649 D3DXVECTOR4 *exp = (D3DXVECTOR4*)(exp_ptr + decl_ptr->Offset);
6650 FLOAT diff = max(fabsf(got->x - exp->x), fabsf(got->y - exp->y));
6651 diff = max(diff, fabsf(got->z - exp->z));
6652 diff = max(diff, fabsf(got->w - exp->w));
6653 ok_(__FILE__,line)(diff <= PRECISION, "Mesh %d: Got (%f, %f, %f, %f) for vertex %d %s, expected (%f, %f, %f, %f).\n",
6654 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);
6655 break;
6656 }
6657 case D3DDECLTYPE_D3DCOLOR:
6658 {
6659 BYTE *got = got_ptr + decl_ptr->Offset;
6660 const BYTE *exp = exp_ptr + decl_ptr->Offset;
6661 BOOL same_color = got[0] == exp[0] && got[1] == exp[1]
6662 && got[2] == exp[2] && got[3] == exp[3];
6663 const char *color_types[] = {"diffuse", "specular", "undefined color"};
6664 BYTE usage_index = decl_ptr->UsageIndex;
6665 if (usage_index > 1) usage_index = 2;
6666 ok_(__FILE__,line)(same_color, "Mesh %d: Got (%u, %u, %u, %u) for vertex %d %s, expected (%u, %u, %u, %u).\n",
6667 mesh_number, got[0], got[1], got[2], got[3], vertex_number, color_types[usage_index], exp[0], exp[1], exp[2], exp[3]);
6668 break;
6669 }
6670 case D3DDECLTYPE_UBYTE4:
6671 case D3DDECLTYPE_UBYTE4N:
6672 {
6673 BYTE *got = got_ptr + decl_ptr->Offset;
6674 const BYTE *exp = exp_ptr + decl_ptr->Offset;
6675 BOOL same = got[0] == exp[0] && got[1] == exp[1]
6676 && got[2] == exp[2] && got[3] == exp[3];
6677 ok_(__FILE__,line)(same, "Mesh %d: Got (%u, %u, %u, %u) for vertex %d %s, expected (%u, %u, %u, %u).\n",
6678 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]);
6679 break;
6680 }
6681 case D3DDECLTYPE_SHORT2:
6682 case D3DDECLTYPE_SHORT2N:
6683 {
6684 SHORT *got = (SHORT*)(got_ptr + decl_ptr->Offset);
6685 SHORT *exp = (SHORT*)(exp_ptr + decl_ptr->Offset);
6686 BOOL same = got[0] == exp[0] && got[1] == exp[1];
6687 ok_(__FILE__,line)(same, "Mesh %d: Got (%hd, %hd) for vertex %d %s, expected (%hd, %hd).\n",
6688 mesh_number, got[0], got[1], vertex_number, usage_strings[decl_ptr->Usage], exp[0], exp[1]);
6689 break;
6690 }
6691 case D3DDECLTYPE_SHORT4:
6692 case D3DDECLTYPE_SHORT4N:
6693 {
6694 SHORT *got = (SHORT*)(got_ptr + decl_ptr->Offset);
6695 SHORT *exp = (SHORT*)(exp_ptr + decl_ptr->Offset);
6696 BOOL same = got[0] == exp[0] && got[1] == exp[1]
6697 && got[2] == exp[2] && got[3] == exp[3];
6698 ok_(__FILE__,line)(same, "Mesh %d: Got (%hd, %hd, %hd, %hd) for vertex %d %s, expected (%hd, %hd, %hd, %hd).\n",
6699 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]);
6700 break;
6701 }
6702 case D3DDECLTYPE_USHORT2N:
6703 {
6704 USHORT *got = (USHORT*)(got_ptr + decl_ptr->Offset);
6705 USHORT *exp = (USHORT*)(exp_ptr + decl_ptr->Offset);
6706 BOOL same = got[0] == exp[0] && got[1] == exp[1];
6707 ok_(__FILE__,line)(same, "Mesh %d: Got (%hu, %hu) for vertex %d %s, expected (%hu, %hu).\n",
6708 mesh_number, got[0], got[1], vertex_number, usage_strings[decl_ptr->Usage], exp[0], exp[1]);
6709 break;
6710 }
6711 case D3DDECLTYPE_USHORT4N:
6712 {
6713 USHORT *got = (USHORT*)(got_ptr + decl_ptr->Offset);
6714 USHORT *exp = (USHORT*)(exp_ptr + decl_ptr->Offset);
6715 BOOL same = got[0] == exp[0] && got[1] == exp[1]
6716 && got[2] == exp[2] && got[3] == exp[3];
6717 ok_(__FILE__,line)(same, "Mesh %d: Got (%hu, %hu, %hu, %hu) for vertex %d %s, expected (%hu, %hu, %hu, %hu).\n",
6718 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]);
6719 break;
6720 }
6721 case D3DDECLTYPE_UDEC3:
6722 {
6723 DWORD *got = (DWORD*)(got_ptr + decl_ptr->Offset);
6724 DWORD *exp = (DWORD*)(exp_ptr + decl_ptr->Offset);
6725 BOOL same = memcmp(got, exp, sizeof(*got)) == 0;
6726 struct udec3 got_udec3 = dword_to_udec3(*got);
6727 struct udec3 exp_udec3 = dword_to_udec3(*exp);
6728 ok_(__FILE__,line)(same, "Mesh %d: Got (%u, %u, %u, %u) for vertex %d %s, expected (%u, %u, %u, %u).\n",
6729 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);
6730
6731 break;
6732 }
6733 case D3DDECLTYPE_DEC3N:
6734 {
6735 DWORD *got = (DWORD*)(got_ptr + decl_ptr->Offset);
6736 DWORD *exp = (DWORD*)(exp_ptr + decl_ptr->Offset);
6737 BOOL same = memcmp(got, exp, sizeof(*got)) == 0;
6738 struct dec3n got_dec3n = dword_to_dec3n(*got);
6739 struct dec3n exp_dec3n = dword_to_dec3n(*exp);
6740 ok_(__FILE__,line)(same, "Mesh %d: Got (%d, %d, %d, %d) for vertex %d %s, expected (%d, %d, %d, %d).\n",
6741 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);
6742 break;
6743 }
6744 case D3DDECLTYPE_FLOAT16_2:
6745 {
6746 WORD *got = (WORD*)(got_ptr + decl_ptr->Offset);
6747 WORD *exp = (WORD*)(exp_ptr + decl_ptr->Offset);
6748 BOOL same = got[0] == exp[0] && got[1] == exp[1];
6749 ok_(__FILE__,line)(same, "Mesh %d: Got (%hx, %hx) for vertex %d %s, expected (%hx, %hx).\n",
6750 mesh_number, got[0], got[1], vertex_number, usage_strings[decl_ptr->Usage], exp[0], exp[1]);
6751 break;
6752 }
6753 case D3DDECLTYPE_FLOAT16_4:
6754 {
6755 WORD *got = (WORD*)(got_ptr + decl_ptr->Offset);
6756 WORD *exp = (WORD*)(exp_ptr + decl_ptr->Offset);
6757 BOOL same = got[0] == exp[0] && got[1] == exp[1]
6758 && got[2] == exp[2] && got[3] == exp[3];
6759 ok_(__FILE__,line)(same, "Mesh %d: Got (%hx, %hx, %hx, %hx) for vertex %d %s, expected (%hx, %hx, %hx, %hx).\n",
6760 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]);
6761 break;
6762 }
6763 default:
6764 break;
6765 }
6766 }
6767 }
6768
test_weld_vertices(void)6769 static void test_weld_vertices(void)
6770 {
6771 HRESULT hr;
6772 struct test_context *test_context = NULL;
6773 DWORD i;
6774 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
6775 const DWORD options_16bit = D3DXMESH_SYSTEMMEM;
6776 BYTE *vertices = NULL;
6777 DWORD *indices = NULL;
6778 WORD *indices_16bit = NULL;
6779 const UINT VERTS_PER_FACE = 3;
6780 #ifndef __REACTOS__
6781 const D3DXVECTOR3 up = {0.0f, 0.0f, 1.0f};
6782 #else
6783 #define up {0.0f, 0.0f, 1.0f}
6784 #endif
6785 struct vertex_normal
6786 {
6787 D3DXVECTOR3 position;
6788 D3DXVECTOR3 normal;
6789 };
6790 struct vertex_blendweight
6791 {
6792 D3DXVECTOR3 position;
6793 FLOAT blendweight;
6794 };
6795 struct vertex_texcoord
6796 {
6797 D3DXVECTOR3 position;
6798 D3DXVECTOR2 texcoord;
6799 };
6800 struct vertex_color
6801 {
6802 D3DXVECTOR3 position;
6803 DWORD color;
6804 };
6805 struct vertex_color_ubyte4
6806 {
6807 D3DXVECTOR3 position;
6808 BYTE color[4];
6809 };
6810 struct vertex_texcoord_short2
6811 {
6812 D3DXVECTOR3 position;
6813 SHORT texcoord[2];
6814 };
6815 struct vertex_texcoord_ushort2n
6816 {
6817 D3DXVECTOR3 position;
6818 USHORT texcoord[2];
6819 };
6820 struct vertex_normal_short4
6821 {
6822 D3DXVECTOR3 position;
6823 SHORT normal[4];
6824 };
6825 struct vertex_texcoord_float16_2
6826 {
6827 D3DXVECTOR3 position;
6828 WORD texcoord[2];
6829 };
6830 struct vertex_texcoord_float16_4
6831 {
6832 D3DXVECTOR3 position;
6833 WORD texcoord[4];
6834 };
6835 struct vertex_normal_udec3
6836 {
6837 D3DXVECTOR3 position;
6838 DWORD normal;
6839 };
6840 struct vertex_normal_dec3n
6841 {
6842 D3DXVECTOR3 position;
6843 DWORD normal;
6844 };
6845 UINT vertex_size_normal = sizeof(struct vertex_normal);
6846 UINT vertex_size_blendweight = sizeof(struct vertex_blendweight);
6847 UINT vertex_size_texcoord = sizeof(struct vertex_texcoord);
6848 UINT vertex_size_color = sizeof(struct vertex_color);
6849 UINT vertex_size_color_ubyte4 = sizeof(struct vertex_color_ubyte4);
6850 UINT vertex_size_texcoord_short2 = sizeof(struct vertex_texcoord_short2);
6851 UINT vertex_size_normal_short4 = sizeof(struct vertex_normal_short4);
6852 UINT vertex_size_texcoord_float16_2 = sizeof(struct vertex_texcoord_float16_2);
6853 UINT vertex_size_texcoord_float16_4 = sizeof(struct vertex_texcoord_float16_4);
6854 UINT vertex_size_normal_udec3 = sizeof(struct vertex_normal_udec3);
6855 UINT vertex_size_normal_dec3n = sizeof(struct vertex_normal_dec3n);
6856 D3DVERTEXELEMENT9 declaration_normal[] =
6857 {
6858 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6859 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6860 D3DDECL_END()
6861 };
6862 D3DVERTEXELEMENT9 declaration_normal3[] =
6863 {
6864 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 3},
6865 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6866 D3DDECL_END()
6867 };
6868 D3DVERTEXELEMENT9 declaration_blendweight[] =
6869 {
6870 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6871 {0, 12, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BLENDWEIGHT, 0},
6872 D3DDECL_END()
6873 };
6874 D3DVERTEXELEMENT9 declaration_texcoord[] =
6875 {
6876 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6877 {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6878 D3DDECL_END()
6879 };
6880 D3DVERTEXELEMENT9 declaration_color[] =
6881 {
6882 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6883 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
6884 D3DDECL_END()
6885 };
6886 D3DVERTEXELEMENT9 declaration_color_ubyte4n[] =
6887 {
6888 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6889 {0, 12, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
6890 D3DDECL_END()
6891 };
6892 D3DVERTEXELEMENT9 declaration_color_ubyte4[] =
6893 {
6894 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6895 {0, 12, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
6896 D3DDECL_END()
6897 };
6898 D3DVERTEXELEMENT9 declaration_texcoord_short2[] =
6899 {
6900 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6901 {0, 12, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6902 D3DDECL_END()
6903 };
6904 D3DVERTEXELEMENT9 declaration_texcoord_short2n[] =
6905 {
6906 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6907 {0, 12, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6908 D3DDECL_END()
6909 };
6910 D3DVERTEXELEMENT9 declaration_texcoord_ushort2n[] =
6911 {
6912 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6913 {0, 12, D3DDECLTYPE_USHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6914 D3DDECL_END()
6915 };
6916 D3DVERTEXELEMENT9 declaration_normal_short4[] =
6917 {
6918 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6919 {0, 12, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6920 D3DDECL_END()
6921 };
6922 D3DVERTEXELEMENT9 declaration_normal_short4n[] =
6923 {
6924 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6925 {0, 12, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6926 D3DDECL_END()
6927 };
6928 D3DVERTEXELEMENT9 declaration_normal_ushort4n[] =
6929 {
6930 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6931 {0, 12, D3DDECLTYPE_USHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6932 D3DDECL_END()
6933 };
6934 D3DVERTEXELEMENT9 declaration_texcoord10[] =
6935 {
6936 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6937 {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 10},
6938 D3DDECL_END()
6939 };
6940 D3DVERTEXELEMENT9 declaration_color2[] =
6941 {
6942 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6943 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 2},
6944 D3DDECL_END()
6945 };
6946 D3DVERTEXELEMENT9 declaration_color1[] =
6947 {
6948 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6949 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 1},
6950 D3DDECL_END()
6951 };
6952 D3DVERTEXELEMENT9 declaration_texcoord_float16_2[] =
6953 {
6954 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6955 {0, 12, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6956 D3DDECL_END()
6957 };
6958 D3DVERTEXELEMENT9 declaration_texcoord_float16_4[] =
6959 {
6960 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6961 {0, 12, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
6962 D3DDECL_END()
6963 };
6964 D3DVERTEXELEMENT9 declaration_normal_udec3[] =
6965 {
6966 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6967 {0, 12, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6968 D3DDECL_END()
6969 };
6970 D3DVERTEXELEMENT9 declaration_normal_dec3n[] =
6971 {
6972 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6973 {0, 12, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
6974 D3DDECL_END()
6975 };
6976 /* Test 0. One face and no welding.
6977 *
6978 * 0--1
6979 * | /
6980 * |/
6981 * 2
6982 */
6983 const struct vertex vertices0[] =
6984 {
6985 {{ 0.0f, 3.0f, 0.f}, up},
6986 {{ 2.0f, 3.0f, 0.f}, up},
6987 {{ 0.0f, 0.0f, 0.f}, up},
6988 };
6989 const DWORD indices0[] = {0, 1, 2};
6990 const DWORD attributes0[] = {0};
6991 const DWORD exp_indices0[] = {0, 1, 2};
6992 const UINT num_vertices0 = ARRAY_SIZE(vertices0);
6993 const UINT num_faces0 = ARRAY_SIZE(indices0) / VERTS_PER_FACE;
6994 const DWORD flags0 = D3DXWELDEPSILONS_WELDALL;
6995 /* epsilons0 is NULL */
6996 const DWORD adjacency0[] = {-1, -1, -1};
6997 const struct vertex exp_vertices0[] =
6998 {
6999 {{ 0.0f, 3.0f, 0.f}, up},
7000 {{ 2.0f, 3.0f, 0.f}, up},
7001 {{ 0.0f, 0.0f, 0.f}, up},
7002 };
7003 const DWORD exp_face_remap0[] = {0};
7004 const DWORD exp_vertex_remap0[] = {0, 1, 2};
7005 const DWORD exp_new_num_vertices0 = ARRAY_SIZE(exp_vertices0);
7006 /* Test 1. Two vertices should be removed without regard to epsilon.
7007 *
7008 * 0--1 3
7009 * | / /|
7010 * |/ / |
7011 * 2 5--4
7012 */
7013 const struct vertex_normal vertices1[] =
7014 {
7015 {{ 0.0f, 3.0f, 0.f}, up},
7016 {{ 2.0f, 3.0f, 0.f}, up},
7017 {{ 0.0f, 0.0f, 0.f}, up},
7018
7019 {{ 3.0f, 3.0f, 0.f}, up},
7020 {{ 3.0f, 0.0f, 0.f}, up},
7021 {{ 1.0f, 0.0f, 0.f}, up},
7022 };
7023 const DWORD indices1[] = {0, 1, 2, 3, 4, 5};
7024 const DWORD attributes1[] = {0, 0};
7025 const UINT num_vertices1 = ARRAY_SIZE(vertices1);
7026 const UINT num_faces1 = ARRAY_SIZE(indices1) / VERTS_PER_FACE;
7027 const DWORD flags1 = D3DXWELDEPSILONS_WELDALL;
7028 /* epsilons1 is NULL */
7029 const DWORD adjacency1[] = {-1, 1, -1, -1, -1, 0};
7030 const struct vertex_normal exp_vertices1[] =
7031 {
7032 {{ 0.0f, 3.0f, 0.f}, up},
7033 {{ 2.0f, 3.0f, 0.f}, up},
7034 {{ 0.0f, 0.0f, 0.f}, up},
7035
7036 {{ 3.0f, 0.0f, 0.f}, up}
7037 };
7038 const DWORD exp_indices1[] = {0, 1, 2, 1, 3, 2};
7039 const DWORD exp_face_remap1[] = {0, 1};
7040 const DWORD exp_vertex_remap1[] = {0, 1, 2, 4, -1, -1};
7041 const DWORD exp_new_num_vertices1 = ARRAY_SIZE(exp_vertices1);
7042 /* Test 2. Two faces. No vertices should be removed because of normal
7043 * epsilon, but the positions should be replaced. */
7044 const struct vertex_normal vertices2[] =
7045 {
7046 {{ 0.0f, 3.0f, 0.f}, up},
7047 {{ 2.0f, 3.0f, 0.f}, up},
7048 {{ 0.0f, 0.0f, 0.f}, up},
7049
7050 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
7051 {{ 3.0f, 0.0f, 0.f}, up},
7052 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
7053 };
7054 const DWORD indices2[] = {0, 1, 2, 3, 4, 5};
7055 const DWORD attributes2[] = {0, 0};
7056 const UINT num_vertices2 = ARRAY_SIZE(vertices2);
7057 const UINT num_faces2 = ARRAY_SIZE(indices2) / VERTS_PER_FACE;
7058 DWORD flags2 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7059 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};
7060 const DWORD adjacency2[] = {-1, 1, -1, -1, -1, 0};
7061 const struct vertex_normal exp_vertices2[] =
7062 {
7063 {{ 0.0f, 3.0f, 0.f}, up},
7064 {{ 2.0f, 3.0f, 0.f}, up},
7065 {{ 0.0f, 0.0f, 0.f}, up},
7066
7067 {{ 2.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
7068 {{ 3.0f, 0.0f, 0.f}, up},
7069 {{ 0.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
7070 };
7071 const DWORD exp_indices2[] = {0, 1, 2, 3, 4, 5};
7072 const DWORD exp_face_remap2[] = {0, 1};
7073 const DWORD exp_vertex_remap2[] = {0, 1, 2, 3, 4, 5};
7074 const DWORD exp_new_num_vertices2 = ARRAY_SIZE(exp_vertices2);
7075 /* Test 3. Two faces. One vertex should be removed because of normal epsilon. */
7076 const struct vertex_normal vertices3[] =
7077 {
7078 {{ 0.0f, 3.0f, 0.f}, up},
7079 {{ 2.0f, 3.0f, 0.f}, up},
7080 {{ 0.0f, 0.0f, 0.f}, up},
7081
7082 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
7083 {{ 3.0f, 0.0f, 0.f}, up},
7084 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
7085 };
7086 const DWORD indices3[] = {0, 1, 2, 3, 4, 5};
7087 const DWORD attributes3[] = {0, 0};
7088 const UINT num_vertices3 = ARRAY_SIZE(vertices3);
7089 const UINT num_faces3 = ARRAY_SIZE(indices3) / VERTS_PER_FACE;
7090 DWORD flags3 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7091 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};
7092 const DWORD adjacency3[] = {-1, 1, -1, -1, -1, 0};
7093 const struct vertex_normal exp_vertices3[] =
7094 {
7095 {{ 0.0f, 3.0f, 0.f}, up},
7096 {{ 2.0f, 3.0f, 0.f}, up},
7097 {{ 0.0f, 0.0f, 0.f}, up},
7098
7099 {{ 3.0f, 0.0f, 0.f}, up},
7100 {{ 0.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
7101 };
7102 const DWORD exp_indices3[] = {0, 1, 2, 1, 3, 4};
7103 const DWORD exp_face_remap3[] = {0, 1};
7104 const DWORD exp_vertex_remap3[] = {0, 1, 2, 4, 5, -1};
7105 const DWORD exp_new_num_vertices3 = ARRAY_SIZE(exp_vertices3);
7106 /* Test 4 Two faces. Two vertices should be removed. */
7107 const struct vertex_normal vertices4[] =
7108 {
7109 {{ 0.0f, 3.0f, 0.f}, up},
7110 {{ 2.0f, 3.0f, 0.f}, up},
7111 {{ 0.0f, 0.0f, 0.f}, up},
7112
7113 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
7114 {{ 3.0f, 0.0f, 0.f}, up},
7115 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
7116 };
7117 const DWORD indices4[] = {0, 1, 2, 3, 4, 5};
7118 const DWORD attributes4[] = {0, 0};
7119 const UINT num_vertices4 = ARRAY_SIZE(vertices4);
7120 const UINT num_faces4 = ARRAY_SIZE(indices4) / VERTS_PER_FACE;
7121 DWORD flags4 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7122 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};
7123 const DWORD adjacency4[] = {-1, 1, -1, -1, -1, 0};
7124 const struct vertex_normal exp_vertices4[] =
7125 {
7126 {{ 0.0f, 3.0f, 0.f}, up},
7127 {{ 2.0f, 3.0f, 0.f}, up},
7128 {{ 0.0f, 0.0f, 0.f}, up},
7129
7130 {{ 3.0f, 0.0f, 0.f}, up},
7131 };
7132 const DWORD exp_indices4[] = {0, 1, 2, 1, 3, 2};
7133 const DWORD exp_face_remap4[] = {0, 1};
7134 const DWORD exp_vertex_remap4[] = {0, 1, 2, 4, -1, -1};
7135 const DWORD exp_new_num_vertices4 = ARRAY_SIZE(exp_vertices4);
7136 /* Test 5. Odd face ordering.
7137 *
7138 * 0--1 6 3
7139 * | / /| |\
7140 * |/ / | | \
7141 * 2 8--7 5--4
7142 */
7143 const struct vertex_normal vertices5[] =
7144 {
7145 {{ 0.0f, 3.0f, 0.f}, up},
7146 {{ 2.0f, 3.0f, 0.f}, up},
7147 {{ 0.0f, 0.0f, 0.f}, up},
7148
7149 {{ 3.0f, 3.0f, 0.f}, up},
7150 {{ 3.0f, 0.0f, 0.f}, up},
7151 {{ 1.0f, 0.0f, 0.f}, up},
7152
7153 {{ 4.0f, 3.0f, 0.f}, up},
7154 {{ 6.0f, 0.0f, 0.f}, up},
7155 {{ 4.0f, 0.0f, 0.f}, up},
7156 };
7157 const DWORD indices5[] = {0, 1, 2, 6, 7, 8, 3, 4, 5};
7158 const DWORD exp_indices5[] = {0, 1, 2, 1, 4, 2, 1, 3, 4};
7159 const DWORD attributes5[] = {0, 0, 0};
7160 const UINT num_vertices5 = ARRAY_SIZE(vertices5);
7161 const UINT num_faces5 = ARRAY_SIZE(indices5) / VERTS_PER_FACE;
7162 DWORD flags5 = D3DXWELDEPSILONS_WELDALL;
7163 const DWORD adjacency5[] = {-1, 1, -1, 2, -1, 0, -1, -1, 1};
7164 const struct vertex_normal exp_vertices5[] =
7165 {
7166 {{ 0.0f, 3.0f, 0.f}, up},
7167 {{ 2.0f, 3.0f, 0.f}, up},
7168 {{ 0.0f, 0.0f, 0.f}, up},
7169
7170 {{ 3.0f, 0.0f, 0.f}, up},
7171 {{ 1.0f, 0.0f, 0.f}, up},
7172 };
7173 const DWORD exp_face_remap5[] = {0, 1, 2};
7174 const DWORD exp_vertex_remap5[] = {0, 1, 2, 4, 5, -1, -1, -1, -1};
7175 const DWORD exp_new_num_vertices5 = ARRAY_SIZE(exp_vertices5);
7176 /* Test 6. Two faces. Do not remove flag is used, so no vertices should be
7177 * removed. */
7178 const struct vertex_normal vertices6[] =
7179 {
7180 {{ 0.0f, 3.0f, 0.f}, up},
7181 {{ 2.0f, 3.0f, 0.f}, up},
7182 {{ 0.0f, 0.0f, 0.f}, up},
7183
7184 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
7185 {{ 3.0f, 0.0f, 0.f}, up},
7186 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
7187 };
7188 const DWORD indices6[] = {0, 1, 2, 3, 4, 5};
7189 const DWORD attributes6[] = {0, 0};
7190 const UINT num_vertices6 = ARRAY_SIZE(vertices6);
7191 const UINT num_faces6 = ARRAY_SIZE(indices6) / VERTS_PER_FACE;
7192 DWORD flags6 = D3DXWELDEPSILONS_WELDPARTIALMATCHES | D3DXWELDEPSILONS_DONOTREMOVEVERTICES;
7193 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};
7194 const DWORD adjacency6[] = {-1, 1, -1, -1, -1, 0};
7195 const struct vertex_normal exp_vertices6[] =
7196 {
7197 {{ 0.0f, 3.0f, 0.f}, up},
7198 {{ 2.0f, 3.0f, 0.f}, up},
7199 {{ 0.0f, 0.0f, 0.f}, up},
7200
7201 {{ 2.0f, 3.0f, 0.f}, up},
7202 {{ 3.0f, 0.0f, 0.f}, up},
7203 {{ 0.0f, 0.0f, 0.f}, up},
7204
7205 };
7206 const DWORD exp_indices6[] = {0, 1, 2, 3, 4, 5};
7207 const DWORD exp_face_remap6[] = {0, 1};
7208 const DWORD exp_vertex_remap6[] = {0, 1, 2, 3, 4, 5};
7209 const DWORD exp_new_num_vertices6 = ARRAY_SIZE(exp_vertices6);
7210 /* Test 7. Same as test 6 but with 16 bit indices. */
7211 const WORD indices6_16bit[] = {0, 1, 2, 3, 4, 5};
7212 /* Test 8. No flags. Same result as D3DXWELDEPSILONS_WELDPARTIALMATCHES. */
7213 const struct vertex_normal vertices8[] =
7214 {
7215 {{ 0.0f, 3.0f, 0.f}, up},
7216 {{ 2.0f, 3.0f, 0.f}, up},
7217 {{ 0.0f, 0.0f, 0.f}, up},
7218
7219 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
7220 {{ 3.0f, 0.0f, 0.f}, up},
7221 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
7222 };
7223 const DWORD indices8[] = {0, 1, 2, 1, 3, 4};
7224 const DWORD attributes8[] = {0, 0};
7225 const UINT num_vertices8 = ARRAY_SIZE(vertices8);
7226 const UINT num_faces8 = ARRAY_SIZE(indices8) / VERTS_PER_FACE;
7227 DWORD flags8 = 0;
7228 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};
7229 const DWORD adjacency8[] = {-1, 1, -1, -1, -1, 0};
7230 const struct vertex_normal exp_vertices8[] =
7231 {
7232 {{ 0.0f, 3.0f, 0.f}, up},
7233 {{ 2.0f, 3.0f, 0.f}, up},
7234 {{ 0.0f, 0.0f, 0.f}, up},
7235
7236 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
7237 {{ 3.0f, 0.0f, 0.f}, up},
7238 };
7239 const DWORD exp_indices8[] = {0, 1, 2, 1, 3, 4};
7240 const DWORD exp_face_remap8[] = {0, 1};
7241 const DWORD exp_vertex_remap8[] = {0, 1, 2, 3, 4, -1};
7242 const DWORD exp_new_num_vertices8 = ARRAY_SIZE(exp_vertices8);
7243 /* Test 9. Vertices are removed even though they belong to separate
7244 * attribute groups if D3DXWELDEPSILONS_DONOTSPLIT is set. */
7245 const struct vertex_normal vertices9[] =
7246 {
7247 {{ 0.0f, 3.0f, 0.f}, up},
7248 {{ 2.0f, 3.0f, 0.f}, up},
7249 {{ 0.0f, 0.0f, 0.f}, up},
7250
7251 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
7252 {{ 3.0f, 0.0f, 0.f}, up},
7253 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
7254 };
7255 const DWORD indices9[] = {0, 1, 2, 3, 4, 5};
7256 const DWORD attributes9[] = {0, 1};
7257 const UINT num_vertices9 = ARRAY_SIZE(vertices9);
7258 const UINT num_faces9 = ARRAY_SIZE(indices9) / VERTS_PER_FACE;
7259 DWORD flags9 = D3DXWELDEPSILONS_WELDPARTIALMATCHES | D3DXWELDEPSILONS_DONOTSPLIT;
7260 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};
7261 const DWORD adjacency9[] = {-1, 1, -1, -1, -1, 0};
7262 const struct vertex_normal exp_vertices9[] =
7263 {
7264 {{ 0.0f, 3.0f, 0.f}, up},
7265 {{ 2.0f, 3.0f, 0.f}, up},
7266 {{ 0.0f, 0.0f, 0.f}, up},
7267
7268 {{ 3.0f, 0.0f, 0.f}, up},
7269 };
7270 const DWORD exp_indices9[] = {0, 1, 2, 1, 3, 2};
7271 const DWORD exp_face_remap9[] = {0, 1};
7272 const DWORD exp_vertex_remap9[] = {0, 1, 2, 4, -1, -1};
7273 const DWORD exp_new_num_vertices9 = ARRAY_SIZE(exp_vertices9);
7274 /* Test 10. Weld blendweight (FLOAT1). */
7275 const struct vertex_blendweight vertices10[] =
7276 {
7277 {{ 0.0f, 3.0f, 0.f}, 1.0f},
7278 {{ 2.0f, 3.0f, 0.f}, 1.0f},
7279 {{ 0.0f, 0.0f, 0.f}, 1.0f},
7280
7281 {{ 3.0f, 3.0f, 0.f}, 0.9},
7282 {{ 3.0f, 0.0f, 0.f}, 1.0},
7283 {{ 1.0f, 0.0f, 0.f}, 0.4},
7284 };
7285 const DWORD indices10[] = {0, 1, 2, 3, 4, 5};
7286 const DWORD attributes10[] = {0, 0};
7287 const UINT num_vertices10 = ARRAY_SIZE(vertices10);
7288 const UINT num_faces10 = ARRAY_SIZE(indices10) / VERTS_PER_FACE;
7289 DWORD flags10 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7290 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};
7291 const DWORD adjacency10[] = {-1, 1, -1, -1, -1, 0};
7292 const struct vertex_blendweight exp_vertices10[] =
7293 {
7294 {{ 0.0f, 3.0f, 0.f}, 1.0f},
7295 {{ 2.0f, 3.0f, 0.f}, 1.0f},
7296 {{ 0.0f, 0.0f, 0.f}, 1.0f},
7297
7298 {{ 3.0f, 0.0f, 0.f}, 1.0},
7299 {{ 0.0f, 0.0f, 0.f}, 0.4},
7300 };
7301 const DWORD exp_indices10[] = {0, 1, 2, 1, 3, 4};
7302 const DWORD exp_face_remap10[] = {0, 1};
7303 const DWORD exp_vertex_remap10[] = {0, 1, 2, 4, 5, -1};
7304 const DWORD exp_new_num_vertices10 = ARRAY_SIZE(exp_vertices10);
7305 /* Test 11. Weld texture coordinates. */
7306 const struct vertex_texcoord vertices11[] =
7307 {
7308 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f}},
7309 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.7f}},
7310 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
7311
7312 {{ 3.0f, 3.0f, 0.f}, {0.2f, 0.3f}},
7313 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f}},
7314 {{ 1.0f, 0.0f, 0.f}, {0.1f, 0.2f}}
7315 };
7316 const DWORD indices11[] = {0, 1, 2, 3, 4, 5};
7317 const DWORD attributes11[] = {0, 0};
7318 const UINT num_vertices11 = ARRAY_SIZE(vertices11);
7319 const UINT num_faces11 = ARRAY_SIZE(indices11) / VERTS_PER_FACE;
7320 DWORD flags11 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7321 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};
7322 const DWORD adjacency11[] = {-1, 1, -1, -1, -1, 0};
7323 const struct vertex_texcoord exp_vertices11[] =
7324 {
7325 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f}},
7326 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.7f}},
7327 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
7328
7329 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f}},
7330 {{ 0.0f, 0.0f, 0.f}, {0.1f, 0.2f}},
7331 };
7332 const DWORD exp_indices11[] = {0, 1, 2, 1, 3, 4};
7333 const DWORD exp_face_remap11[] = {0, 1};
7334 const DWORD exp_vertex_remap11[] = {0, 1, 2, 4, 5, -1};
7335 const DWORD exp_new_num_vertices11 = ARRAY_SIZE(exp_vertices11);
7336 /* Test 12. Weld with color. */
7337 const struct vertex_color vertices12[] =
7338 {
7339 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7340 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7341 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7342
7343 {{ 3.0f, 3.0f, 0.f}, 0x00000000},
7344 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7345 {{ 1.0f, 0.0f, 0.f}, 0x88888888},
7346 };
7347 const DWORD indices12[] = {0, 1, 2, 3, 4, 5};
7348 const DWORD attributes12[] = {0, 0};
7349 const UINT num_vertices12 = ARRAY_SIZE(vertices12);
7350 const UINT num_faces12 = ARRAY_SIZE(indices12) / VERTS_PER_FACE;
7351 DWORD flags12 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7352 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};
7353 const DWORD adjacency12[] = {-1, 1, -1, -1, -1, 0};
7354 const struct vertex_color exp_vertices12[] =
7355 {
7356 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7357 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7358 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7359
7360 {{ 2.0f, 3.0f, 0.f}, 0x00000000},
7361 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7362 };
7363 const DWORD exp_indices12[] = {0, 1, 2, 3, 4, 2};
7364 const DWORD exp_face_remap12[] = {0, 1};
7365 const DWORD exp_vertex_remap12[] = {0, 1, 2, 3, 4, -1};
7366 const DWORD exp_new_num_vertices12 = ARRAY_SIZE(exp_vertices12);
7367 /* Test 13. Two faces. One vertex should be removed because of normal epsilon.
7368 * This is similar to test 3, but the declaration has been changed to NORMAL3.
7369 */
7370 const struct vertex_normal vertices13[] =
7371 {
7372 {{ 0.0f, 3.0f, 0.f}, up},
7373 {{ 2.0f, 3.0f, 0.f}, up},
7374 {{ 0.0f, 0.0f, 0.f}, up},
7375
7376 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}},
7377 {{ 3.0f, 0.0f, 0.f}, up},
7378 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
7379 };
7380 const DWORD indices13[] = {0, 1, 2, 3, 4, 5};
7381 const DWORD attributes13[] = {0, 0};
7382 const UINT num_vertices13 = ARRAY_SIZE(vertices3);
7383 const UINT num_faces13 = ARRAY_SIZE(indices3) / VERTS_PER_FACE;
7384 DWORD flags13 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7385 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};
7386 const DWORD adjacency13[] = {-1, 1, -1, -1, -1, 0};
7387 const struct vertex_normal exp_vertices13[] =
7388 {
7389 {{ 0.0f, 3.0f, 0.f}, up},
7390 {{ 2.0f, 3.0f, 0.f}, up},
7391 {{ 0.0f, 0.0f, 0.f}, up},
7392
7393 {{ 3.0f, 0.0f, 0.f}, up},
7394 {{ 0.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}},
7395 };
7396 const DWORD exp_indices13[] = {0, 1, 2, 1, 3, 4};
7397 const DWORD exp_face_remap13[] = {0, 1};
7398 const DWORD exp_vertex_remap13[] = {0, 1, 2, 4, 5, -1};
7399 const DWORD exp_new_num_vertices13 = ARRAY_SIZE(exp_vertices13);
7400 /* Test 14. Another test for welding with color. */
7401 const struct vertex_color vertices14[] =
7402 {
7403 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7404 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7405 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7406
7407 {{ 3.0f, 3.0f, 0.f}, 0x00000000},
7408 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7409 {{ 1.0f, 0.0f, 0.f}, 0x01010101},
7410 };
7411 const DWORD indices14[] = {0, 1, 2, 3, 4, 5};
7412 const DWORD attributes14[] = {0, 0};
7413 const UINT num_vertices14 = ARRAY_SIZE(vertices14);
7414 const UINT num_faces14 = ARRAY_SIZE(indices14) / VERTS_PER_FACE;
7415 DWORD flags14 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7416 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};
7417 const DWORD adjacency14[] = {-1, 1, -1, -1, -1, 0};
7418 const struct vertex_color exp_vertices14[] =
7419 {
7420 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7421 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7422 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7423
7424 {{ 2.0f, 3.0f, 0.f}, 0x00000000},
7425 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7426 };
7427 const DWORD exp_indices14[] = {0, 1, 2, 3, 4, 2};
7428 const DWORD exp_face_remap14[] = {0, 1};
7429 const DWORD exp_vertex_remap14[] = {0, 1, 2, 3, 4, -1};
7430 const DWORD exp_new_num_vertices14 = ARRAY_SIZE(exp_vertices14);
7431 /* Test 15. Weld with color, but as UBYTE4N instead of D3DCOLOR. It shows
7432 * that UBYTE4N and D3DCOLOR are compared the same way.
7433 */
7434 const struct vertex_color_ubyte4 vertices15[] =
7435 {
7436 {{ 0.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7437 {{ 2.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7438 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7439
7440 {{ 3.0f, 3.0f, 0.f}, { 0, 0, 0, 0}},
7441 {{ 3.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7442 {{ 1.0f, 0.0f, 0.f}, { 1, 1, 1, 1}},
7443 };
7444 const DWORD indices15[] = {0, 1, 2, 3, 4, 5};
7445 const DWORD attributes15[] = {0, 0};
7446 const UINT num_vertices15 = ARRAY_SIZE(vertices15);
7447 const UINT num_faces15 = ARRAY_SIZE(indices15) / VERTS_PER_FACE;
7448 DWORD flags15 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7449 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};
7450 const DWORD adjacency15[] = {-1, 1, -1, -1, -1, 0};
7451 const struct vertex_color_ubyte4 exp_vertices15[] =
7452 {
7453 {{ 0.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7454 {{ 2.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7455 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7456
7457 {{ 2.0f, 3.0f, 0.f}, { 0, 0, 0, 0}},
7458 {{ 3.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7459 };
7460 const DWORD exp_indices15[] = {0, 1, 2, 3, 4, 2};
7461 const DWORD exp_face_remap15[] = {0, 1};
7462 const DWORD exp_vertex_remap15[] = {0, 1, 2, 3, 4, -1};
7463 const DWORD exp_new_num_vertices15 = ARRAY_SIZE(exp_vertices15);
7464 /* Test 16. Weld with color, but as UBYTE4 instead of D3DCOLOR. It shows
7465 * that UBYTE4 is not normalized and that epsilon is truncated and compared
7466 * directly to each of the four bytes.
7467 */
7468 const struct vertex_color_ubyte4 vertices16[] =
7469 {
7470 {{ 0.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7471 {{ 2.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7472 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7473
7474 {{ 3.0f, 3.0f, 0.f}, { 0, 0, 0, 0}},
7475 {{ 3.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7476 {{ 1.0f, 0.0f, 0.f}, { 1, 1, 1, 1}},
7477 };
7478 const DWORD indices16[] = {0, 1, 2, 3, 4, 5};
7479 const DWORD attributes16[] = {0, 0};
7480 const UINT num_vertices16 = ARRAY_SIZE(vertices16);
7481 const UINT num_faces16 = ARRAY_SIZE(indices16) / VERTS_PER_FACE;
7482 DWORD flags16 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7483 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};
7484 const DWORD adjacency16[] = {-1, 1, -1, -1, -1, 0};
7485 const struct vertex_color_ubyte4 exp_vertices16[] =
7486 {
7487 {{ 0.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7488 {{ 2.0f, 3.0f, 0.f}, {255, 255, 255, 255}},
7489 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7490
7491 {{ 2.0f, 3.0f, 0.f}, { 0, 0, 0, 0}},
7492 {{ 3.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
7493 };
7494 const DWORD exp_indices16[] = {0, 1, 2, 3, 4, 2};
7495 const DWORD exp_face_remap16[] = {0, 1};
7496 const DWORD exp_vertex_remap16[] = {0, 1, 2, 3, 4, -1};
7497 const DWORD exp_new_num_vertices16 = ARRAY_SIZE(exp_vertices16);
7498 /* Test 17. Weld texture coordinates but as SHORT2 instead of D3DXVECTOR2.*/
7499 const struct vertex_texcoord_short2 vertices17[] =
7500 {
7501 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7502 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7503 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7504
7505 {{ 3.0f, 3.0f, 0.f}, {32767, 32767}},
7506 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7507 {{ 1.0f, 0.0f, 0.f}, {32766, 32766}},
7508 };
7509 const DWORD indices17[] = {0, 1, 2, 3, 4, 5};
7510 const DWORD attributes17[] = {0, 0};
7511 const UINT num_vertices17 = ARRAY_SIZE(vertices17);
7512 const UINT num_faces17 = ARRAY_SIZE(indices17) / VERTS_PER_FACE;
7513 DWORD flags17 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7514 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};
7515 const DWORD adjacency17[] = {-1, 1, -1, -1, -1, 0};
7516 const struct vertex_texcoord_short2 exp_vertices17[] =
7517 {
7518 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7519 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7520 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7521
7522 {{ 2.0f, 3.0f, 0.f}, {32767, 32767}},
7523 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7524 };
7525 const DWORD exp_indices17[] = {0, 1, 2, 3, 4, 2};
7526 const DWORD exp_face_remap17[] = {0, 1};
7527 const DWORD exp_vertex_remap17[] = {0, 1, 2, 3, 4, -1};
7528 const DWORD exp_new_num_vertices17 = ARRAY_SIZE(exp_vertices17);
7529 /* Test 18. Weld texture coordinates but as SHORT2N instead of D3DXVECTOR2. */
7530 const struct vertex_texcoord_short2 vertices18[] =
7531 {
7532 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7533 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7534 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7535
7536 {{ 3.0f, 3.0f, 0.f}, {32767, 32767}},
7537 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7538 {{ 1.0f, 0.0f, 0.f}, {32766, 32766}},
7539 };
7540 const DWORD indices18[] = {0, 1, 2, 3, 4, 5};
7541 const DWORD attributes18[] = {0, 0};
7542 const UINT num_vertices18 = ARRAY_SIZE(vertices18);
7543 const UINT num_faces18 = ARRAY_SIZE(indices18) / VERTS_PER_FACE;
7544 DWORD flags18 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7545 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};
7546 const DWORD adjacency18[] = {-1, 1, -1, -1, -1, 0};
7547 const struct vertex_texcoord_short2 exp_vertices18[] =
7548 {
7549 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7550 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7551 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7552
7553 {{ 2.0f, 3.0f, 0.f}, {32767, 32767}},
7554 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7555 };
7556 const DWORD exp_indices18[] = {0, 1, 2, 3, 4, 2};
7557 const DWORD exp_face_remap18[] = {0, 1};
7558 const DWORD exp_vertex_remap18[] = {0, 1, 2, 3, 4, -1};
7559 const DWORD exp_new_num_vertices18 = ARRAY_SIZE(exp_vertices18);
7560 /* Test 19. Weld texture coordinates but as USHORT2N instead of D3DXVECTOR2. */
7561 const struct vertex_texcoord_ushort2n vertices19[] =
7562 {
7563 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7564 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7565 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7566
7567 {{ 3.0f, 3.0f, 0.f}, {65535, 65535}},
7568 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7569 {{ 1.0f, 0.0f, 0.f}, {65534, 65534}},
7570 };
7571 const DWORD indices19[] = {0, 1, 2, 3, 4, 5};
7572 const DWORD attributes19[] = {0, 0};
7573 const UINT num_vertices19 = ARRAY_SIZE(vertices19);
7574 const UINT num_faces19 = ARRAY_SIZE(indices19) / VERTS_PER_FACE;
7575 DWORD flags19 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7576 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};
7577 const DWORD adjacency19[] = {-1, 1, -1, -1, -1, 0};
7578 const struct vertex_texcoord_ushort2n exp_vertices19[] =
7579 {
7580 {{ 0.0f, 3.0f, 0.f}, { 0, 0}},
7581 {{ 2.0f, 3.0f, 0.f}, { 0, 0}},
7582 {{ 0.0f, 0.0f, 0.f}, { 0, 0}},
7583
7584 {{ 2.0f, 3.0f, 0.f}, {65535, 65535}},
7585 {{ 3.0f, 0.0f, 0.f}, {0, 0}},
7586 };
7587 const DWORD exp_indices19[] = {0, 1, 2, 3, 4, 2};
7588 const DWORD exp_face_remap19[] = {0, 1};
7589 const DWORD exp_vertex_remap19[] = {0, 1, 2, 3, 4, -1};
7590 const DWORD exp_new_num_vertices19 = ARRAY_SIZE(exp_vertices19);
7591 /* Test 20. Weld normal as SHORT4 instead of D3DXVECTOR3. */
7592 const struct vertex_normal_short4 vertices20[] =
7593 {
7594 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7595 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7596 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7597
7598 {{ 3.0f, 3.0f, 0.f}, {32767, 32767, 32767, 32767}},
7599 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7600 {{ 1.0f, 0.0f, 0.f}, {32766, 32766, 32766, 32766}},
7601 };
7602 const DWORD indices20[] = {0, 1, 2, 3, 4, 5};
7603 const DWORD attributes20[] = {0, 0};
7604 const UINT num_vertices20 = ARRAY_SIZE(vertices20);
7605 const UINT num_faces20 = ARRAY_SIZE(indices20) / VERTS_PER_FACE;
7606 DWORD flags20 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7607 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};
7608 const DWORD adjacency20[] = {-1, 1, -1, -1, -1, 0};
7609 const struct vertex_normal_short4 exp_vertices20[] =
7610 {
7611 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7612 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7613 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7614
7615 {{ 2.0f, 3.0f, 0.f}, {32767, 32767, 32767, 32767}},
7616 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7617 };
7618 const DWORD exp_indices20[] = {0, 1, 2, 3, 4, 2};
7619 const DWORD exp_face_remap20[] = {0, 1};
7620 const DWORD exp_vertex_remap20[] = {0, 1, 2, 3, 4, -1};
7621 const DWORD exp_new_num_vertices20 = ARRAY_SIZE(exp_vertices20);
7622 /* Test 21. Weld normal as SHORT4N instead of D3DXVECTOR3. */
7623 const struct vertex_normal_short4 vertices21[] =
7624 {
7625 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7626 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7627 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7628
7629 {{ 3.0f, 3.0f, 0.f}, {32767, 32767, 32767, 32767}},
7630 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7631 {{ 1.0f, 0.0f, 0.f}, {32766, 32766, 32766, 32766}},
7632 };
7633 const DWORD indices21[] = {0, 1, 2, 3, 4, 5};
7634 const DWORD attributes21[] = {0, 0};
7635 const UINT num_vertices21 = ARRAY_SIZE(vertices21);
7636 const UINT num_faces21 = ARRAY_SIZE(indices21) / VERTS_PER_FACE;
7637 DWORD flags21 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7638 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};
7639 const DWORD adjacency21[] = {-1, 1, -1, -1, -1, 0};
7640 const struct vertex_normal_short4 exp_vertices21[] =
7641 {
7642 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7643 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7644 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7645
7646 {{ 2.0f, 3.0f, 0.f}, {32767, 32767, 32767, 32767}},
7647 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7648 };
7649 const DWORD exp_indices21[] = {0, 1, 2, 3, 4, 2};
7650 const DWORD exp_face_remap21[] = {0, 1};
7651 const DWORD exp_vertex_remap21[] = {0, 1, 2, 3, 4, -1};
7652 const DWORD exp_new_num_vertices21 = ARRAY_SIZE(exp_vertices21);
7653 /* Test 22. Weld normal as USHORT4N instead of D3DXVECTOR3. */
7654 const struct vertex_normal_short4 vertices22[] =
7655 {
7656 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7657 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7658 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7659
7660 {{ 3.0f, 3.0f, 0.f}, {-1, -1, -1, -1}},
7661 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7662 {{ 1.0f, 0.0f, 0.f}, {-2, -2, -2, -2}},
7663 };
7664 const DWORD indices22[] = {0, 1, 2, 3, 4, 5};
7665 const DWORD attributes22[] = {0, 0};
7666 const UINT num_vertices22 = ARRAY_SIZE(vertices22);
7667 const UINT num_faces22 = ARRAY_SIZE(indices22) / VERTS_PER_FACE;
7668 DWORD flags22 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7669 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};
7670 const DWORD adjacency22[] = {-1, 1, -1, -1, -1, 0};
7671 const struct vertex_normal_short4 exp_vertices22[] =
7672 {
7673 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7674 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
7675 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7676
7677 {{ 2.0f, 3.0f, 0.f}, {-1, -1, -1, -1}},
7678 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}},
7679 };
7680 const DWORD exp_indices22[] = {0, 1, 2, 3, 4, 2};
7681 const DWORD exp_face_remap22[] = {0, 1};
7682 const DWORD exp_vertex_remap22[] = {0, 1, 2, 3, 4, -1};
7683 const DWORD exp_new_num_vertices22 = ARRAY_SIZE(exp_vertices22);
7684 /* Test 23. Weld texture coordinates as FLOAT16_2. Similar to test 11, but
7685 * with texture coordinates converted to float16 in hex. */
7686 const struct vertex_texcoord_float16_2 vertices23[] =
7687 {
7688 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
7689 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */
7690 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */
7691
7692 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd}}, /* {0.2f, 0.3f} */
7693 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
7694 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */
7695 };
7696 const DWORD indices23[] = {0, 1, 2, 3, 4, 5};
7697 const DWORD attributes23[] = {0, 0};
7698 const UINT num_vertices23 = ARRAY_SIZE(vertices23);
7699 const UINT num_faces23 = ARRAY_SIZE(indices23) / VERTS_PER_FACE;
7700 DWORD flags23 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7701 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};
7702 const DWORD adjacency23[] = {-1, 1, -1, -1, -1, 0};
7703 const struct vertex_texcoord_float16_2 exp_vertices23[] =
7704 {
7705 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
7706 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */
7707 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */
7708
7709 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
7710 {{ 0.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */
7711 };
7712 const DWORD exp_indices23[] = {0, 1, 2, 1, 3, 4};
7713 const DWORD exp_face_remap23[] = {0, 1};
7714 const DWORD exp_vertex_remap23[] = {0, 1, 2, 4, 5, -1};
7715 const DWORD exp_new_num_vertices23 = ARRAY_SIZE(exp_vertices23);
7716 /* Test 24. Weld texture coordinates as FLOAT16_4. Similar to test 24. */
7717 const struct vertex_texcoord_float16_4 vertices24[] =
7718 {
7719 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}},
7720 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a, 0x3800, 0x399a}},
7721 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd, 0xb266, 0xb4cd}},
7722
7723 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd, 0x3266, 0x34cd}},
7724 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}},
7725 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266, 0x2e66, 0x3266}},
7726 };
7727 const DWORD indices24[] = {0, 1, 2, 3, 4, 5};
7728 const DWORD attributes24[] = {0, 0};
7729 const UINT num_vertices24 = ARRAY_SIZE(vertices24);
7730 const UINT num_faces24 = ARRAY_SIZE(indices24) / VERTS_PER_FACE;
7731 DWORD flags24 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7732 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};
7733 const DWORD adjacency24[] = {-1, 1, -1, -1, -1, 0};
7734 const struct vertex_texcoord_float16_4 exp_vertices24[] =
7735 {
7736 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}},
7737 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a, 0x3800, 0x399a}},
7738 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd, 0xb266, 0xb4cd}},
7739
7740 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}},
7741 {{ 0.0f, 0.0f, 0.f}, {0x2e66, 0x3266, 0x2e66, 0x3266}},
7742 };
7743 const DWORD exp_indices24[] = {0, 1, 2, 1, 3, 4};
7744 const DWORD exp_face_remap24[] = {0, 1};
7745 const DWORD exp_vertex_remap24[] = {0, 1, 2, 4, 5, -1};
7746 const DWORD exp_new_num_vertices24 = ARRAY_SIZE(exp_vertices24);
7747 /* Test 25. Weld texture coordinates with usage index 10 (TEXCOORD10). The
7748 * usage index is capped at 7, so the epsilon for TEXCOORD7 is used instead.
7749 */
7750 const struct vertex_texcoord vertices25[] =
7751 {
7752 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f}},
7753 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.7f}},
7754 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
7755
7756 {{ 3.0f, 3.0f, 0.f}, {0.2f, 0.3f}},
7757 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f}},
7758 {{ 1.0f, 0.0f, 0.f}, {0.1f, 0.2f}}
7759 };
7760 const DWORD indices25[] = {0, 1, 2, 3, 4, 5};
7761 const DWORD attributes25[] = {0, 0};
7762 const UINT num_vertices25 = ARRAY_SIZE(vertices25);
7763 const UINT num_faces25 = ARRAY_SIZE(indices25) / VERTS_PER_FACE;
7764 DWORD flags25 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7765 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};
7766 const DWORD adjacency25[] = {-1, 1, -1, -1, -1, 0};
7767 const struct vertex_texcoord exp_vertices25[] =
7768 {
7769 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f}},
7770 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.7f}},
7771 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
7772
7773 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f}},
7774 {{ 0.0f, 0.0f, 0.f}, {0.1f, 0.2f}},
7775 };
7776 const DWORD exp_indices25[] = {0, 1, 2, 1, 3, 4};
7777 const DWORD exp_face_remap25[] = {0, 1};
7778 const DWORD exp_vertex_remap25[] = {0, 1, 2, 4, 5, -1};
7779 const DWORD exp_new_num_vertices25 = ARRAY_SIZE(exp_vertices25);
7780 /* Test 26. Weld color with usage index larger than 1. Shows that none of
7781 * the epsilon values are used. */
7782 const struct vertex_color vertices26[] =
7783 {
7784 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7785 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7786 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7787
7788 {{ 3.0f, 3.0f, 0.f}, 0x00000000},
7789 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7790 {{ 1.0f, 0.0f, 0.f}, 0x01010101},
7791 };
7792 const DWORD indices26[] = {0, 1, 2, 3, 4, 5};
7793 const DWORD attributes26[] = {0, 0};
7794 const UINT num_vertices26 = ARRAY_SIZE(vertices26);
7795 const UINT num_faces26 = ARRAY_SIZE(indices26) / VERTS_PER_FACE;
7796 DWORD flags26 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7797 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};
7798 const DWORD adjacency26[] = {-1, 1, -1, -1, -1, 0};
7799 const struct vertex_color exp_vertices26[] =
7800 {
7801 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7802 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF},
7803 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7804
7805 {{ 2.0f, 3.0f, 0.f}, 0x00000000},
7806 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF},
7807 {{ 0.0f, 0.0f, 0.f}, 0x01010101},
7808 };
7809 const DWORD exp_indices26[] = {0, 1, 2, 3, 4, 5};
7810 const DWORD exp_face_remap26[] = {0, 1};
7811 const DWORD exp_vertex_remap26[] = {0, 1, 2, 3, 4, 5};
7812 const DWORD exp_new_num_vertices26 = ARRAY_SIZE(exp_vertices26);
7813 /* Test 27. Weld color with usage index 1 (specular). */
7814 /* Previously this test used float color values and index > 1 but that case
7815 * appears to be effectively unhandled in native so the test gave
7816 * inconsistent results. */
7817 const struct vertex_color vertices27[] =
7818 {
7819 {{ 0.0f, 3.0f, 0.0f}, 0x00000000},
7820 {{ 2.0f, 3.0f, 0.0f}, 0x10203040},
7821 {{ 0.0f, 0.0f, 0.0f}, 0x50607080},
7822
7823 {{ 3.0f, 3.0f, 0.0f}, 0x11213141},
7824 {{ 3.0f, 0.0f, 0.0f}, 0xffffffff},
7825 {{ 1.0f, 0.0f, 0.0f}, 0x51617181},
7826 };
7827 const DWORD indices27[] = {0, 1, 2, 3, 4, 5};
7828 const DWORD attributes27[] = {0, 0};
7829 const UINT num_vertices27 = ARRAY_SIZE(vertices27);
7830 const UINT num_faces27 = ARRAY_SIZE(indices27) / VERTS_PER_FACE;
7831 DWORD flags27 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7832 const D3DXWELDEPSILONS epsilons27 =
7833 {
7834 1.1f, 0.0f, 0.0f, 0.0f, 2.0f / 255.0f, 0.0f,
7835 {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, 0.0f, 0.0f, 0.0f
7836 };
7837 const DWORD adjacency27[] = {-1, 1, -1, -1, -1, 0};
7838 const struct vertex_color exp_vertices27[] =
7839 {
7840 {{ 0.0f, 3.0f, 0.0f}, 0x00000000},
7841 {{ 2.0f, 3.0f, 0.0f}, 0x10203040},
7842 {{ 0.0f, 0.0f, 0.0f}, 0x50607080},
7843
7844 {{ 3.0f, 0.0f, 0.0f}, 0xffffffff},
7845 };
7846 const DWORD exp_indices27[] = {0, 1, 2, 1, 3, 2};
7847 const DWORD exp_face_remap27[] = {0, 1};
7848 const DWORD exp_vertex_remap27[] = {0, 1, 2, 4, -1, -1};
7849 const DWORD exp_new_num_vertices27 = ARRAY_SIZE(exp_vertices27);
7850 /* Test 28. Weld one normal with UDEC3. */
7851 const DWORD dword_udec3_zero = init_udec3_dword(0, 0, 0, 1);
7852 const DWORD dword_udec3_1023 = init_udec3_dword(1023, 1023, 1023, 1);
7853 const DWORD dword_udec3_1022 = init_udec3_dword(1022, 1022, 1022, 1);
7854 const struct vertex_normal_udec3 vertices28[] =
7855 {
7856 {{ 0.0f, 3.0f, 0.f}, dword_udec3_zero},
7857 {{ 2.0f, 3.0f, 0.f}, dword_udec3_zero},
7858 {{ 0.0f, 0.0f, 0.f}, dword_udec3_zero},
7859
7860 {{ 3.0f, 3.0f, 0.f}, dword_udec3_1023},
7861 {{ 3.0f, 0.0f, 0.f}, dword_udec3_zero},
7862 {{ 1.0f, 0.0f, 0.f}, dword_udec3_1022},
7863 };
7864 const DWORD indices28[] = {0, 1, 2, 3, 4, 5};
7865 const DWORD attributes28[] = {0, 0};
7866 const UINT num_vertices28 = ARRAY_SIZE(vertices28);
7867 const UINT num_faces28 = ARRAY_SIZE(indices28) / VERTS_PER_FACE;
7868 DWORD flags28 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7869 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};
7870 const DWORD adjacency28[] = {-1, 1, -1, -1, -1, 0};
7871 const struct vertex_normal_udec3 exp_vertices28[] =
7872 {
7873 {{ 0.0f, 3.0f, 0.f}, dword_udec3_zero},
7874 {{ 2.0f, 3.0f, 0.f}, dword_udec3_zero},
7875 {{ 0.0f, 0.0f, 0.f}, dword_udec3_zero},
7876
7877 {{ 2.0f, 3.0f, 0.f}, dword_udec3_1023},
7878 {{ 3.0f, 0.0f, 0.f}, dword_udec3_zero},
7879 };
7880 const DWORD exp_indices28[] = {0, 1, 2, 3, 4, 2};
7881 const DWORD exp_face_remap28[] = {0, 1};
7882 const DWORD exp_vertex_remap28[] = {0, 1, 2, 3, 4, -1};
7883 const DWORD exp_new_num_vertices28 = ARRAY_SIZE(exp_vertices28);
7884 /* Test 29. Weld one normal with DEC3N. */
7885 const DWORD dword_dec3n_zero = init_dec3n_dword(0, 0, 0, 1);
7886 const DWORD dword_dec3n_511 = init_dec3n_dword(511, 511, 511, 1);
7887 const DWORD dword_dec3n_510 = init_dec3n_dword(510, 510, 510, 1);
7888 const struct vertex_normal_dec3n vertices29[] =
7889 {
7890 {{ 0.0f, 3.0f, 0.f}, dword_dec3n_zero},
7891 {{ 2.0f, 3.0f, 0.f}, dword_dec3n_zero},
7892 {{ 0.0f, 0.0f, 0.f}, dword_dec3n_zero},
7893
7894 {{ 3.0f, 3.0f, 0.f}, dword_dec3n_511},
7895 {{ 3.0f, 0.0f, 0.f}, dword_dec3n_zero},
7896 {{ 1.0f, 0.0f, 0.f}, dword_dec3n_510},
7897 };
7898 const DWORD indices29[] = {0, 1, 2, 3, 4, 5};
7899 const DWORD attributes29[] = {0, 0};
7900 const UINT num_vertices29 = ARRAY_SIZE(vertices29);
7901 const UINT num_faces29 = ARRAY_SIZE(indices29) / VERTS_PER_FACE;
7902 DWORD flags29 = D3DXWELDEPSILONS_WELDPARTIALMATCHES;
7903 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};
7904 const DWORD adjacency29[] = {-1, 1, -1, -1, -1, 0};
7905 const struct vertex_normal_dec3n exp_vertices29[] =
7906 {
7907 {{ 0.0f, 3.0f, 0.f}, dword_dec3n_zero},
7908 {{ 2.0f, 3.0f, 0.f}, dword_dec3n_zero},
7909 {{ 0.0f, 0.0f, 0.f}, dword_dec3n_zero},
7910
7911 {{ 2.0f, 3.0f, 0.f}, dword_dec3n_511},
7912 {{ 3.0f, 0.0f, 0.f}, dword_dec3n_zero},
7913 };
7914 const DWORD exp_indices29[] = {0, 1, 2, 3, 4, 2};
7915 const DWORD exp_face_remap29[] = {0, 1};
7916 const DWORD exp_vertex_remap29[] = {0, 1, 2, 3, 4, -1};
7917 const DWORD exp_new_num_vertices29 = ARRAY_SIZE(exp_vertices29);
7918 /* All mesh data */
7919 DWORD *adjacency_out = NULL;
7920 DWORD *face_remap = NULL;
7921 ID3DXMesh *mesh = NULL;
7922 ID3DXBuffer *vertex_remap = NULL;
7923 struct
7924 {
7925 const BYTE *vertices;
7926 const DWORD *indices;
7927 const DWORD *attributes;
7928 const DWORD num_vertices;
7929 const DWORD num_faces;
7930 const DWORD options;
7931 D3DVERTEXELEMENT9 *declaration;
7932 const UINT vertex_size;
7933 const DWORD flags;
7934 const D3DXWELDEPSILONS *epsilons;
7935 const DWORD *adjacency;
7936 const BYTE *exp_vertices;
7937 const DWORD *exp_indices;
7938 const DWORD *exp_face_remap;
7939 const DWORD *exp_vertex_remap;
7940 const DWORD exp_new_num_vertices;
7941 }
7942 tc[] =
7943 {
7944 {
7945 (BYTE*)vertices0,
7946 indices0,
7947 attributes0,
7948 num_vertices0,
7949 num_faces0,
7950 options,
7951 declaration_normal,
7952 vertex_size_normal,
7953 flags0,
7954 NULL,
7955 adjacency0,
7956 (BYTE*)exp_vertices0,
7957 exp_indices0,
7958 exp_face_remap0,
7959 exp_vertex_remap0,
7960 exp_new_num_vertices0
7961 },
7962 {
7963 (BYTE*)vertices1,
7964 indices1,
7965 attributes1,
7966 num_vertices1,
7967 num_faces1,
7968 options,
7969 declaration_normal,
7970 vertex_size_normal,
7971 flags1,
7972 NULL,
7973 adjacency1,
7974 (BYTE*)exp_vertices1,
7975 exp_indices1,
7976 exp_face_remap1,
7977 exp_vertex_remap1,
7978 exp_new_num_vertices1
7979 },
7980 {
7981 (BYTE*)vertices2,
7982 indices2,
7983 attributes2,
7984 num_vertices2,
7985 num_faces2,
7986 options,
7987 declaration_normal,
7988 vertex_size_normal,
7989 flags2,
7990 &epsilons2,
7991 adjacency2,
7992 (BYTE*)exp_vertices2,
7993 exp_indices2,
7994 exp_face_remap2,
7995 exp_vertex_remap2,
7996 exp_new_num_vertices2
7997 },
7998 {
7999 (BYTE*)vertices3,
8000 indices3,
8001 attributes3,
8002 num_vertices3,
8003 num_faces3,
8004 options,
8005 declaration_normal,
8006 vertex_size_normal,
8007 flags3,
8008 &epsilons3,
8009 adjacency3,
8010 (BYTE*)exp_vertices3,
8011 exp_indices3,
8012 exp_face_remap3,
8013 exp_vertex_remap3,
8014 exp_new_num_vertices3
8015 },
8016 {
8017 (BYTE*)vertices4,
8018 indices4,
8019 attributes4,
8020 num_vertices4,
8021 num_faces4,
8022 options,
8023 declaration_normal,
8024 vertex_size_normal,
8025 flags4,
8026 &epsilons4,
8027 adjacency4,
8028 (BYTE*)exp_vertices4,
8029 exp_indices4,
8030 exp_face_remap4,
8031 exp_vertex_remap4,
8032 exp_new_num_vertices4
8033 },
8034 /* Unusual ordering. */
8035 {
8036 (BYTE*)vertices5,
8037 indices5,
8038 attributes5,
8039 num_vertices5,
8040 num_faces5,
8041 options,
8042 declaration_normal,
8043 vertex_size_normal,
8044 flags5,
8045 NULL,
8046 adjacency5,
8047 (BYTE*)exp_vertices5,
8048 exp_indices5,
8049 exp_face_remap5,
8050 exp_vertex_remap5,
8051 exp_new_num_vertices5
8052 },
8053 {
8054 (BYTE*)vertices6,
8055 indices6,
8056 attributes6,
8057 num_vertices6,
8058 num_faces6,
8059 options,
8060 declaration_normal,
8061 vertex_size_normal,
8062 flags6,
8063 &epsilons6,
8064 adjacency6,
8065 (BYTE*)exp_vertices6,
8066 exp_indices6,
8067 exp_face_remap6,
8068 exp_vertex_remap6,
8069 exp_new_num_vertices6
8070 },
8071 {
8072 (BYTE*)vertices6,
8073 (DWORD*)indices6_16bit,
8074 attributes6,
8075 num_vertices6,
8076 num_faces6,
8077 options_16bit,
8078 declaration_normal,
8079 vertex_size_normal,
8080 flags6,
8081 &epsilons6,
8082 adjacency6,
8083 (BYTE*)exp_vertices6,
8084 exp_indices6,
8085 exp_face_remap6,
8086 exp_vertex_remap6,
8087 exp_new_num_vertices6
8088 },
8089 {
8090 (BYTE*)vertices8,
8091 indices8,
8092 attributes8,
8093 num_vertices8,
8094 num_faces8,
8095 options,
8096 declaration_normal,
8097 vertex_size_normal,
8098 flags8,
8099 &epsilons8,
8100 adjacency8,
8101 (BYTE*)exp_vertices8,
8102 exp_indices8,
8103 exp_face_remap8,
8104 exp_vertex_remap8,
8105 exp_new_num_vertices8
8106 },
8107 {
8108 (BYTE*)vertices9,
8109 indices9,
8110 attributes9,
8111 num_vertices9,
8112 num_faces9,
8113 options,
8114 declaration_normal,
8115 vertex_size_normal,
8116 flags9,
8117 &epsilons9,
8118 adjacency9,
8119 (BYTE*)exp_vertices9,
8120 exp_indices9,
8121 exp_face_remap9,
8122 exp_vertex_remap9,
8123 exp_new_num_vertices9
8124 },
8125 {
8126 (BYTE*)vertices10,
8127 indices10,
8128 attributes10,
8129 num_vertices10,
8130 num_faces10,
8131 options,
8132 declaration_blendweight,
8133 vertex_size_blendweight,
8134 flags10,
8135 &epsilons10,
8136 adjacency10,
8137 (BYTE*)exp_vertices10,
8138 exp_indices10,
8139 exp_face_remap10,
8140 exp_vertex_remap10,
8141 exp_new_num_vertices10
8142 },
8143 {
8144 (BYTE*)vertices11,
8145 indices11,
8146 attributes11,
8147 num_vertices11,
8148 num_faces11,
8149 options,
8150 declaration_texcoord,
8151 vertex_size_texcoord,
8152 flags11,
8153 &epsilons11,
8154 adjacency11,
8155 (BYTE*)exp_vertices11,
8156 exp_indices11,
8157 exp_face_remap11,
8158 exp_vertex_remap11,
8159 exp_new_num_vertices11
8160 },
8161 {
8162 (BYTE*)vertices12,
8163 indices12,
8164 attributes12,
8165 num_vertices12,
8166 num_faces12,
8167 options,
8168 declaration_color,
8169 vertex_size_color,
8170 flags12,
8171 &epsilons12,
8172 adjacency12,
8173 (BYTE*)exp_vertices12,
8174 exp_indices12,
8175 exp_face_remap12,
8176 exp_vertex_remap12,
8177 exp_new_num_vertices12
8178 },
8179 {
8180 (BYTE*)vertices13,
8181 indices13,
8182 attributes13,
8183 num_vertices13,
8184 num_faces13,
8185 options,
8186 declaration_normal3,
8187 vertex_size_normal,
8188 flags13,
8189 &epsilons13,
8190 adjacency13,
8191 (BYTE*)exp_vertices13,
8192 exp_indices13,
8193 exp_face_remap13,
8194 exp_vertex_remap13,
8195 exp_new_num_vertices13
8196 },
8197 {
8198 (BYTE*)vertices14,
8199 indices14,
8200 attributes14,
8201 num_vertices14,
8202 num_faces14,
8203 options,
8204 declaration_color,
8205 vertex_size_color,
8206 flags14,
8207 &epsilons14,
8208 adjacency14,
8209 (BYTE*)exp_vertices14,
8210 exp_indices14,
8211 exp_face_remap14,
8212 exp_vertex_remap14,
8213 exp_new_num_vertices14
8214 },
8215 {
8216 (BYTE*)vertices15,
8217 indices15,
8218 attributes15,
8219 num_vertices15,
8220 num_faces15,
8221 options,
8222 declaration_color_ubyte4n,
8223 vertex_size_color_ubyte4, /* UBYTE4 same size as UBYTE4N */
8224 flags15,
8225 &epsilons15,
8226 adjacency15,
8227 (BYTE*)exp_vertices15,
8228 exp_indices15,
8229 exp_face_remap15,
8230 exp_vertex_remap15,
8231 exp_new_num_vertices15
8232 },
8233 {
8234 (BYTE*)vertices16,
8235 indices16,
8236 attributes16,
8237 num_vertices16,
8238 num_faces16,
8239 options,
8240 declaration_color_ubyte4,
8241 vertex_size_color_ubyte4,
8242 flags16,
8243 &epsilons16,
8244 adjacency16,
8245 (BYTE*)exp_vertices16,
8246 exp_indices16,
8247 exp_face_remap16,
8248 exp_vertex_remap16,
8249 exp_new_num_vertices16
8250 },
8251 {
8252 (BYTE*)vertices17,
8253 indices17,
8254 attributes17,
8255 num_vertices17,
8256 num_faces17,
8257 options,
8258 declaration_texcoord_short2,
8259 vertex_size_texcoord_short2,
8260 flags17,
8261 &epsilons17,
8262 adjacency17,
8263 (BYTE*)exp_vertices17,
8264 exp_indices17,
8265 exp_face_remap17,
8266 exp_vertex_remap17,
8267 exp_new_num_vertices17
8268 },
8269 {
8270 (BYTE*)vertices18,
8271 indices18,
8272 attributes18,
8273 num_vertices18,
8274 num_faces18,
8275 options,
8276 declaration_texcoord_short2n,
8277 vertex_size_texcoord_short2, /* SHORT2 same size as SHORT2N */
8278 flags18,
8279 &epsilons18,
8280 adjacency18,
8281 (BYTE*)exp_vertices18,
8282 exp_indices18,
8283 exp_face_remap18,
8284 exp_vertex_remap18,
8285 exp_new_num_vertices18
8286 },
8287 {
8288 (BYTE*)vertices19,
8289 indices19,
8290 attributes19,
8291 num_vertices19,
8292 num_faces19,
8293 options,
8294 declaration_texcoord_ushort2n,
8295 vertex_size_texcoord_short2, /* SHORT2 same size as USHORT2N */
8296 flags19,
8297 &epsilons19,
8298 adjacency19,
8299 (BYTE*)exp_vertices19,
8300 exp_indices19,
8301 exp_face_remap19,
8302 exp_vertex_remap19,
8303 exp_new_num_vertices19
8304 },
8305 {
8306 (BYTE*)vertices20,
8307 indices20,
8308 attributes20,
8309 num_vertices20,
8310 num_faces20,
8311 options,
8312 declaration_normal_short4,
8313 vertex_size_normal_short4,
8314 flags20,
8315 &epsilons20,
8316 adjacency20,
8317 (BYTE*)exp_vertices20,
8318 exp_indices20,
8319 exp_face_remap20,
8320 exp_vertex_remap20,
8321 exp_new_num_vertices20
8322 },
8323 {
8324 (BYTE*)vertices21,
8325 indices21,
8326 attributes21,
8327 num_vertices21,
8328 num_faces21,
8329 options,
8330 declaration_normal_short4n,
8331 vertex_size_normal_short4, /* SHORT4 same size as SHORT4N */
8332 flags21,
8333 &epsilons21,
8334 adjacency21,
8335 (BYTE*)exp_vertices21,
8336 exp_indices21,
8337 exp_face_remap21,
8338 exp_vertex_remap21,
8339 exp_new_num_vertices21
8340 },
8341 {
8342 (BYTE*)vertices22,
8343 indices22,
8344 attributes22,
8345 num_vertices22,
8346 num_faces22,
8347 options,
8348 declaration_normal_ushort4n,
8349 vertex_size_normal_short4, /* SHORT4 same size as USHORT4N */
8350 flags22,
8351 &epsilons22,
8352 adjacency22,
8353 (BYTE*)exp_vertices22,
8354 exp_indices22,
8355 exp_face_remap22,
8356 exp_vertex_remap22,
8357 exp_new_num_vertices22
8358 },
8359 {
8360 (BYTE*)vertices23,
8361 indices23,
8362 attributes23,
8363 num_vertices23,
8364 num_faces23,
8365 options,
8366 declaration_texcoord_float16_2,
8367 vertex_size_texcoord_float16_2,
8368 flags23,
8369 &epsilons23,
8370 adjacency23,
8371 (BYTE*)exp_vertices23,
8372 exp_indices23,
8373 exp_face_remap23,
8374 exp_vertex_remap23,
8375 exp_new_num_vertices23
8376 },
8377 {
8378 (BYTE*)vertices24,
8379 indices24,
8380 attributes24,
8381 num_vertices24,
8382 num_faces24,
8383 options,
8384 declaration_texcoord_float16_4,
8385 vertex_size_texcoord_float16_4,
8386 flags24,
8387 &epsilons24,
8388 adjacency24,
8389 (BYTE*)exp_vertices24,
8390 exp_indices24,
8391 exp_face_remap24,
8392 exp_vertex_remap24,
8393 exp_new_num_vertices24
8394 },
8395 {
8396 (BYTE*)vertices25,
8397 indices25,
8398 attributes25,
8399 num_vertices25,
8400 num_faces25,
8401 options,
8402 declaration_texcoord10,
8403 vertex_size_texcoord,
8404 flags25,
8405 &epsilons25,
8406 adjacency25,
8407 (BYTE*)exp_vertices25,
8408 exp_indices25,
8409 exp_face_remap25,
8410 exp_vertex_remap25,
8411 exp_new_num_vertices25
8412 },
8413 {
8414 (BYTE*)vertices26,
8415 indices26,
8416 attributes26,
8417 num_vertices26,
8418 num_faces26,
8419 options,
8420 declaration_color2,
8421 vertex_size_color,
8422 flags26,
8423 &epsilons26,
8424 adjacency26,
8425 (BYTE*)exp_vertices26,
8426 exp_indices26,
8427 exp_face_remap26,
8428 exp_vertex_remap26,
8429 exp_new_num_vertices26
8430 },
8431 {
8432 (BYTE*)vertices27,
8433 indices27,
8434 attributes27,
8435 num_vertices27,
8436 num_faces27,
8437 options,
8438 declaration_color1,
8439 vertex_size_color,
8440 flags27,
8441 &epsilons27,
8442 adjacency27,
8443 (BYTE*)exp_vertices27,
8444 exp_indices27,
8445 exp_face_remap27,
8446 exp_vertex_remap27,
8447 exp_new_num_vertices27
8448 },
8449 {
8450 (BYTE*)vertices28,
8451 indices28,
8452 attributes28,
8453 num_vertices28,
8454 num_faces28,
8455 options,
8456 declaration_normal_udec3,
8457 vertex_size_normal_udec3,
8458 flags28,
8459 &epsilons28,
8460 adjacency28,
8461 (BYTE*)exp_vertices28,
8462 exp_indices28,
8463 exp_face_remap28,
8464 exp_vertex_remap28,
8465 exp_new_num_vertices28
8466 },
8467 {
8468 (BYTE*)vertices29,
8469 indices29,
8470 attributes29,
8471 num_vertices29,
8472 num_faces29,
8473 options,
8474 declaration_normal_dec3n,
8475 vertex_size_normal_dec3n,
8476 flags29,
8477 &epsilons29,
8478 adjacency29,
8479 (BYTE*)exp_vertices29,
8480 exp_indices29,
8481 exp_face_remap29,
8482 exp_vertex_remap29,
8483 exp_new_num_vertices29
8484 }
8485 };
8486 #ifdef __REACTOS__
8487 #undef up
8488 #endif
8489
8490 test_context = new_test_context();
8491 if (!test_context)
8492 {
8493 skip("Couldn't create test context\n");
8494 goto cleanup;
8495 }
8496
8497 for (i = 0; i < ARRAY_SIZE(tc); i++)
8498 {
8499 DWORD j;
8500 DWORD *vertex_remap_ptr;
8501 DWORD new_num_vertices;
8502
8503 hr = init_test_mesh(tc[i].num_faces, tc[i].num_vertices, tc[i].options,
8504 tc[i].declaration, test_context->device, &mesh,
8505 tc[i].vertices, tc[i].vertex_size,
8506 tc[i].indices, tc[i].attributes);
8507 if (FAILED(hr))
8508 {
8509 skip("Couldn't initialize test mesh %d.\n", i);
8510 goto cleanup;
8511 }
8512
8513 /* Allocate out parameters */
8514 adjacency_out = HeapAlloc(GetProcessHeap(), 0, VERTS_PER_FACE * tc[i].num_faces * sizeof(*adjacency_out));
8515 if (!adjacency_out)
8516 {
8517 skip("Couldn't allocate adjacency_out array.\n");
8518 goto cleanup;
8519 }
8520 face_remap = HeapAlloc(GetProcessHeap(), 0, tc[i].num_faces * sizeof(*face_remap));
8521 if (!face_remap)
8522 {
8523 skip("Couldn't allocate face_remap array.\n");
8524 goto cleanup;
8525 }
8526
8527 hr = D3DXWeldVertices(mesh, tc[i].flags, tc[i].epsilons, tc[i].adjacency,
8528 adjacency_out, face_remap, &vertex_remap);
8529 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
8530 /* Check number of vertices*/
8531 new_num_vertices = mesh->lpVtbl->GetNumVertices(mesh);
8532 ok(new_num_vertices == tc[i].exp_new_num_vertices,
8533 "Mesh %d: new_num_vertices == %d, expected %d.\n",
8534 i, new_num_vertices, tc[i].exp_new_num_vertices);
8535 /* Check index buffer */
8536 if (tc[i].options & D3DXMESH_32BIT)
8537 {
8538 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, (void**)&indices);
8539 if (FAILED(hr))
8540 {
8541 skip("Couldn't lock index buffer.\n");
8542 goto cleanup;
8543 }
8544 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
8545 {
8546 ok(indices[j] == tc[i].exp_indices[j],
8547 "Mesh %d: indices[%d] == %d, expected %d\n",
8548 i, j, indices[j], tc[i].exp_indices[j]);
8549 }
8550 }
8551 else
8552 {
8553 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, (void**)&indices_16bit);
8554 if (FAILED(hr))
8555 {
8556 skip("Couldn't lock index buffer.\n");
8557 goto cleanup;
8558 }
8559 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
8560 {
8561 ok(indices_16bit[j] == tc[i].exp_indices[j],
8562 "Mesh %d: indices_16bit[%d] == %d, expected %d\n",
8563 i, j, indices_16bit[j], tc[i].exp_indices[j]);
8564 }
8565 }
8566 mesh->lpVtbl->UnlockIndexBuffer(mesh);
8567 indices = NULL;
8568 indices_16bit = NULL;
8569 /* Check adjacency_out */
8570 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
8571 {
8572 ok(adjacency_out[j] == tc[i].adjacency[j],
8573 "Mesh %d: adjacency_out[%d] == %d, expected %d\n",
8574 i, j, adjacency_out[j], tc[i].adjacency[j]);
8575 }
8576 /* Check face_remap */
8577 for (j = 0; j < tc[i].num_faces; j++)
8578 {
8579 ok(face_remap[j] == tc[i].exp_face_remap[j],
8580 "Mesh %d: face_remap[%d] == %d, expected %d\n",
8581 i, j, face_remap[j], tc[i].exp_face_remap[j]);
8582 }
8583 /* Check vertex_remap */
8584 vertex_remap_ptr = vertex_remap->lpVtbl->GetBufferPointer(vertex_remap);
8585 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
8586 {
8587 ok(vertex_remap_ptr[j] == tc[i].exp_vertex_remap[j],
8588 "Mesh %d: vertex_remap_ptr[%d] == %d, expected %d\n",
8589 i, j, vertex_remap_ptr[j], tc[i].exp_vertex_remap[j]);
8590 }
8591 /* Check vertex buffer */
8592 hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, (void*)&vertices);
8593 if (FAILED(hr))
8594 {
8595 skip("Couldn't lock vertex buffer.\n");
8596 goto cleanup;
8597 }
8598 /* Check contents of re-ordered vertex buffer */
8599 for (j = 0; j < tc[i].exp_new_num_vertices; j++)
8600 {
8601 int index = tc[i].vertex_size*j;
8602 check_vertex_components(__LINE__, i, j, &vertices[index], &tc[i].exp_vertices[index], tc[i].declaration);
8603 }
8604 mesh->lpVtbl->UnlockVertexBuffer(mesh);
8605 vertices = NULL;
8606
8607 /* Free mesh and output data */
8608 HeapFree(GetProcessHeap(), 0, adjacency_out);
8609 adjacency_out = NULL;
8610 HeapFree(GetProcessHeap(), 0, face_remap);
8611 face_remap = NULL;
8612 vertex_remap->lpVtbl->Release(vertex_remap);
8613 vertex_remap = NULL;
8614 mesh->lpVtbl->Release(mesh);
8615 mesh = NULL;
8616 }
8617
8618 cleanup:
8619 HeapFree(GetProcessHeap(), 0, adjacency_out);
8620 HeapFree(GetProcessHeap(), 0, face_remap);
8621 if (indices) mesh->lpVtbl->UnlockIndexBuffer(mesh);
8622 if (indices_16bit) mesh->lpVtbl->UnlockIndexBuffer(mesh);
8623 if (mesh) mesh->lpVtbl->Release(mesh);
8624 if (vertex_remap) vertex_remap->lpVtbl->Release(vertex_remap);
8625 if (vertices) mesh->lpVtbl->UnlockVertexBuffer(mesh);
8626 free_test_context(test_context);
8627 }
8628
test_clone_mesh(void)8629 static void test_clone_mesh(void)
8630 {
8631 HRESULT hr;
8632 struct test_context *test_context = NULL;
8633 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
8634 D3DVERTEXELEMENT9 declaration_pn[] =
8635 {
8636 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8637 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
8638 D3DDECL_END()
8639 };
8640 D3DVERTEXELEMENT9 declaration_pntc[] =
8641 {
8642 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8643 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
8644 {0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8645 D3DDECL_END()
8646 };
8647 D3DVERTEXELEMENT9 declaration_ptcn[] =
8648 {
8649 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8650 {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8651 {0, 20, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
8652 D3DDECL_END()
8653 };
8654 D3DVERTEXELEMENT9 declaration_ptc[] =
8655 {
8656 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8657 {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8658 D3DDECL_END()
8659 };
8660 D3DVERTEXELEMENT9 declaration_ptc_float16_2[] =
8661 {
8662 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8663 {0, 12, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8664 D3DDECL_END()
8665 };
8666 D3DVERTEXELEMENT9 declaration_ptc_float16_4[] =
8667 {
8668 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8669 {0, 12, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8670 D3DDECL_END()
8671 };
8672 D3DVERTEXELEMENT9 declaration_ptc_float1[] =
8673 {
8674 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8675 {0, 12, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8676 D3DDECL_END()
8677 };
8678 D3DVERTEXELEMENT9 declaration_ptc_float3[] =
8679 {
8680 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8681 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8682 D3DDECL_END()
8683 };
8684 D3DVERTEXELEMENT9 declaration_ptc_float4[] =
8685 {
8686 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8687 {0, 12, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8688 D3DDECL_END()
8689 };
8690 D3DVERTEXELEMENT9 declaration_ptc_d3dcolor[] =
8691 {
8692 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8693 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8694 D3DDECL_END()
8695 };
8696 D3DVERTEXELEMENT9 declaration_ptc_ubyte4[] =
8697 {
8698 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8699 {0, 12, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8700 D3DDECL_END()
8701 };
8702 D3DVERTEXELEMENT9 declaration_ptc_ubyte4n[] =
8703 {
8704 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8705 {0, 12, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8706 D3DDECL_END()
8707 };
8708 D3DVERTEXELEMENT9 declaration_ptc_short2[] =
8709 {
8710 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8711 {0, 12, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8712 D3DDECL_END()
8713 };
8714 D3DVERTEXELEMENT9 declaration_ptc_short4[] =
8715 {
8716 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8717 {0, 12, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8718 D3DDECL_END()
8719 };
8720 D3DVERTEXELEMENT9 declaration_ptc_short2n[] =
8721 {
8722 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8723 {0, 12, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8724 D3DDECL_END()
8725 };
8726 D3DVERTEXELEMENT9 declaration_ptc_short4n[] =
8727 {
8728 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8729 {0, 12, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8730 D3DDECL_END()
8731 };
8732 D3DVERTEXELEMENT9 declaration_ptc_ushort2n[] =
8733 {
8734 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8735 {0, 12, D3DDECLTYPE_USHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8736 D3DDECL_END()
8737 };
8738 D3DVERTEXELEMENT9 declaration_ptc_ushort4n[] =
8739 {
8740 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8741 {0, 12, D3DDECLTYPE_USHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8742 D3DDECL_END()
8743 };
8744 D3DVERTEXELEMENT9 declaration_ptc_float16_2_partialu[] =
8745 {
8746 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8747 {0, 12, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_PARTIALU, D3DDECLUSAGE_TEXCOORD, 0},
8748 D3DDECL_END()
8749 };
8750 D3DVERTEXELEMENT9 declaration_pntc1[] =
8751 {
8752 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8753 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
8754 {0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
8755 D3DDECL_END()
8756 };
8757 const unsigned int VERTS_PER_FACE = 3;
8758 BYTE *vertices = NULL;
8759 INT i;
8760 struct vertex_pn
8761 {
8762 D3DXVECTOR3 position;
8763 D3DXVECTOR3 normal;
8764 };
8765 struct vertex_pntc
8766 {
8767 D3DXVECTOR3 position;
8768 D3DXVECTOR3 normal;
8769 D3DXVECTOR2 texcoords;
8770 };
8771 struct vertex_ptcn
8772 {
8773 D3DXVECTOR3 position;
8774 D3DXVECTOR2 texcoords;
8775 D3DXVECTOR3 normal;
8776 };
8777 struct vertex_ptc
8778 {
8779 D3DXVECTOR3 position;
8780 D3DXVECTOR2 texcoords;
8781 };
8782 struct vertex_ptc_float16_2
8783 {
8784 D3DXVECTOR3 position;
8785 WORD texcoords[2]; /* float16_2 */
8786 };
8787 struct vertex_ptc_float16_4
8788 {
8789 D3DXVECTOR3 position;
8790 WORD texcoords[4]; /* float16_4 */
8791 };
8792 struct vertex_ptc_float1
8793 {
8794 D3DXVECTOR3 position;
8795 FLOAT texcoords;
8796 };
8797 struct vertex_ptc_float3
8798 {
8799 D3DXVECTOR3 position;
8800 FLOAT texcoords[3];
8801 };
8802 struct vertex_ptc_float4
8803 {
8804 D3DXVECTOR3 position;
8805 FLOAT texcoords[4];
8806 };
8807 struct vertex_ptc_d3dcolor
8808 {
8809 D3DXVECTOR3 position;
8810 BYTE texcoords[4];
8811 };
8812 struct vertex_ptc_ubyte4
8813 {
8814 D3DXVECTOR3 position;
8815 BYTE texcoords[4];
8816 };
8817 struct vertex_ptc_ubyte4n
8818 {
8819 D3DXVECTOR3 position;
8820 BYTE texcoords[4];
8821 };
8822 struct vertex_ptc_short2
8823 {
8824 D3DXVECTOR3 position;
8825 SHORT texcoords[2];
8826 };
8827 struct vertex_ptc_short4
8828 {
8829 D3DXVECTOR3 position;
8830 SHORT texcoords[4];
8831 };
8832 struct vertex_ptc_ushort2n
8833 {
8834 D3DXVECTOR3 position;
8835 USHORT texcoords[2];
8836 };
8837 struct vertex_ptc_ushort4n
8838 {
8839 D3DXVECTOR3 position;
8840 USHORT texcoords[4];
8841 };
8842 struct vertex_ptc_udec3
8843 {
8844 D3DXVECTOR3 position;
8845 DWORD texcoords;
8846 };
8847 struct vertex_ptc_dec3n
8848 {
8849 D3DXVECTOR3 position;
8850 DWORD texcoords;
8851 };
8852 #ifndef __REACTOS__
8853 D3DXVECTOR3 up = {0.0f, 0.0f, 1.0f};
8854 D3DXVECTOR2 zero_vec2 = {0.0f, 0.0f};
8855 #else
8856 #define up {0.0f, 0.0f, 1.0f}
8857 #define zero_vec2 {0.0f, 0.0f}
8858 #endif
8859 /* Test 0. Check that a mesh can be cloned if the new declaration is the
8860 * same as the one used to create the mesh.
8861 *
8862 * 0--1 3
8863 * | / /|
8864 * |/ / |
8865 * 2 5--4
8866 */
8867 const struct vertex_pn vertices0[] =
8868 {
8869 {{ 0.0f, 3.0f, 0.f}, up},
8870 {{ 2.0f, 3.0f, 0.f}, up},
8871 {{ 0.0f, 0.0f, 0.f}, up},
8872
8873 {{ 3.0f, 3.0f, 0.f}, up},
8874 {{ 3.0f, 0.0f, 0.f}, up},
8875 {{ 1.0f, 0.0f, 0.f}, up},
8876 };
8877 const UINT num_vertices0 = ARRAY_SIZE(vertices0);
8878 const UINT num_faces0 = ARRAY_SIZE(vertices0) / VERTS_PER_FACE;
8879 const UINT vertex_size0 = sizeof(*vertices0);
8880 /* Test 1. Check that 16-bit indices are handled. */
8881 const DWORD options_16bit = D3DXMESH_SYSTEMMEM;
8882 /* Test 2. Check that the size of each vertex is increased and the data
8883 * moved if the new declaration adds an element after the original elements.
8884 */
8885 const struct vertex_pntc exp_vertices2[] =
8886 {
8887 {{ 0.0f, 3.0f, 0.f}, up, zero_vec2},
8888 {{ 2.0f, 3.0f, 0.f}, up, zero_vec2},
8889 {{ 0.0f, 0.0f, 0.f}, up, zero_vec2},
8890
8891 {{ 3.0f, 3.0f, 0.f}, up, zero_vec2},
8892 {{ 3.0f, 0.0f, 0.f}, up, zero_vec2},
8893 {{ 1.0f, 0.0f, 0.f}, up, zero_vec2},
8894 };
8895 const UINT exp_vertex_size2 = sizeof(*exp_vertices2);
8896 /* Test 3. Check that the size of each vertex is increased and the data
8897 * moved if the new declaration adds an element between the original
8898 * elements.
8899 */
8900 const struct vertex_ptcn exp_vertices3[] =
8901 {
8902 {{ 0.0f, 3.0f, 0.f}, zero_vec2, up},
8903 {{ 2.0f, 3.0f, 0.f}, zero_vec2, up},
8904 {{ 0.0f, 0.0f, 0.f}, zero_vec2, up},
8905
8906 {{ 3.0f, 3.0f, 0.f}, zero_vec2, up},
8907 {{ 3.0f, 0.0f, 0.f}, zero_vec2, up},
8908 {{ 1.0f, 0.0f, 0.f}, zero_vec2, up},
8909 };
8910 const UINT exp_vertex_size3 = sizeof(*exp_vertices3);
8911 /* Test 4. Test that data types can be converted, e.g. FLOAT2 to FLOAT16_2. */
8912 const struct vertex_ptc vertices4[] =
8913 {
8914 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8915 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8916 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
8917
8918 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8919 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
8920 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
8921 };
8922 const UINT num_vertices4 = ARRAY_SIZE(vertices4);
8923 const UINT num_faces4 = ARRAY_SIZE(vertices4) / VERTS_PER_FACE;
8924 const UINT vertex_size4 = sizeof(*vertices4);
8925 const struct vertex_ptc_float16_2 exp_vertices4[] =
8926 {
8927 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
8928 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */
8929 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */
8930
8931 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd}}, /* {0.2f, 0.3f} */
8932 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
8933 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */
8934 };
8935 const UINT exp_vertex_size4 = sizeof(*exp_vertices4);
8936 /* Test 5. Convert FLOAT2 to FLOAT16_4. */
8937 const struct vertex_ptc vertices5[] =
8938 {
8939 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8940 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8941 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
8942
8943 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8944 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
8945 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
8946 };
8947 const UINT num_vertices5 = ARRAY_SIZE(vertices5);
8948 const UINT num_faces5 = ARRAY_SIZE(vertices5) / VERTS_PER_FACE;
8949 const UINT vertex_size5 = sizeof(*vertices5);
8950 const struct vertex_ptc_float16_4 exp_vertices5[] =
8951 {
8952 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00, 0, 0x3c00}}, /* {1.0f, 1.0f, 0.0f, 1.0f} */
8953 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a, 0, 0x3c00}}, /* {0.5f, 0.7f, 0.0f, 1.0f} */
8954 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd, 0, 0x3c00}}, /* {-0.2f, -0.3f, 0.0f, 1.0f} */
8955
8956 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd, 0, 0x3c00}}, /* {0.2f, 0.3f, 0.0f, 1.0f} */
8957 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00, 0, 0x3c00}}, /* {1.0f, 1.0f, 0.0f, 1.0f} */
8958 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266, 0, 0x3c00}}, /* {0.1f, 0.2f, 0.0f, 1.0f} */
8959 };
8960 const UINT exp_vertex_size5 = sizeof(*exp_vertices5);
8961 /* Test 6. Convert FLOAT2 to FLOAT1. */
8962 const struct vertex_ptc vertices6[] =
8963 {
8964 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8965 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8966 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
8967
8968 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8969 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
8970 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
8971 };
8972 const UINT num_vertices6 = ARRAY_SIZE(vertices6);
8973 const UINT num_faces6 = ARRAY_SIZE(vertices6) / VERTS_PER_FACE;
8974 const UINT vertex_size6 = sizeof(*vertices6);
8975 const struct vertex_ptc_float1 exp_vertices6[] =
8976 {
8977 {{ 0.0f, 3.0f, 0.f}, 1.0f},
8978 {{ 2.0f, 3.0f, 0.f}, 0.5f},
8979 {{ 0.0f, 0.0f, 0.f}, -0.2f},
8980
8981 {{ 3.0f, 3.0f, 0.f}, 0.2f},
8982 {{ 3.0f, 0.0f, 0.f}, 1.0f},
8983 {{ 1.0f, 0.0f, 0.f}, 0.1f},
8984 };
8985 const UINT exp_vertex_size6 = sizeof(*exp_vertices6);
8986 /* Test 7. Convert FLOAT2 to FLOAT3. */
8987 const struct vertex_ptc vertices7[] =
8988 {
8989 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
8990 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
8991 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
8992
8993 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
8994 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
8995 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
8996 };
8997 const UINT num_vertices7 = ARRAY_SIZE(vertices7);
8998 const UINT num_faces7 = ARRAY_SIZE(vertices7) / VERTS_PER_FACE;
8999 const UINT vertex_size7 = sizeof(*vertices7);
9000 const struct vertex_ptc_float3 exp_vertices7[] =
9001 {
9002 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f, 0.0f}},
9003 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f, 0.0f}},
9004 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f, 0.0f}},
9005
9006 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f, 0.0f}},
9007 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f, 0.0f}},
9008 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f, 0.0f}},
9009 };
9010 const UINT exp_vertex_size7 = sizeof(*exp_vertices7);
9011 /* Test 8. Convert FLOAT2 to FLOAT4. */
9012 const struct vertex_ptc vertices8[] =
9013 {
9014 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
9015 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
9016 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
9017
9018 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
9019 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
9020 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
9021 };
9022 const UINT num_vertices8 = ARRAY_SIZE(vertices8);
9023 const UINT num_faces8 = ARRAY_SIZE(vertices8) / VERTS_PER_FACE;
9024 const UINT vertex_size8 = sizeof(*vertices8);
9025 const struct vertex_ptc_float4 exp_vertices8[] =
9026 {
9027 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f, 0.0f, 1.0f}},
9028 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f, 0.0f, 1.0f}},
9029 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f, 0.0f, 1.0f}},
9030
9031 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f, 0.0f, 1.0f}},
9032 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f, 0.0f, 1.0f}},
9033 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f, 0.0f, 1.0f}},
9034 };
9035 const UINT exp_vertex_size8 = sizeof(*exp_vertices8);
9036 /* Test 9. Convert FLOAT2 to D3DCOLOR. */
9037 const struct vertex_ptc vertices9[] =
9038 {
9039 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
9040 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
9041 {{ 0.0f, 0.0f, 0.f}, {-0.4f, -0.6f}},
9042
9043 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
9044 {{ 3.0f, 0.0f, 0.f}, { 2.0f, 256.0f}},
9045 {{ 1.0f, 0.0f, 0.f}, { 0.11f, 0.2f}},
9046 };
9047 const UINT num_vertices9 = ARRAY_SIZE(vertices9);
9048 const UINT num_faces9 = ARRAY_SIZE(vertices9) / VERTS_PER_FACE;
9049 const UINT vertex_size9 = sizeof(*vertices9);
9050 const struct vertex_ptc_d3dcolor exp_vertices9[] =
9051 {
9052 {{ 0.0f, 3.0f, 0.f}, {0, 255, 255, 255}},
9053 {{ 2.0f, 3.0f, 0.f}, {0, 179, 128, 255}},
9054 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 255}},
9055
9056 {{ 3.0f, 3.0f, 0.f}, {0, 77, 51, 255}},
9057 {{ 3.0f, 0.0f, 0.f}, {0, 255, 255, 255}},
9058 {{ 1.0f, 0.0f, 0.f}, {0, 51, 28, 255}},
9059 };
9060 const UINT exp_vertex_size9 = sizeof(*exp_vertices9);
9061 /* Test 10. Convert FLOAT2 to UBYTE4. */
9062 const struct vertex_ptc vertices10[] =
9063 {
9064 {{ 0.0f, 3.0f, 0.f}, { 0.0f, 1.0f}},
9065 {{ 2.0f, 3.0f, 0.f}, { 2.0f, 3.0f}},
9066 {{ 0.0f, 0.0f, 0.f}, { 254.0f, 255.0f}},
9067
9068 {{ 3.0f, 3.0f, 0.f}, { 256.0f, 257.0f}},
9069 {{ 3.0f, 0.0f, 0.f}, { 1.4f, 1.5f}},
9070 {{ 1.0f, 0.0f, 0.f}, {-4.0f, -5.0f}},
9071 };
9072 const UINT num_vertices10 = ARRAY_SIZE(vertices10);
9073 const UINT num_faces10 = ARRAY_SIZE(vertices10) / VERTS_PER_FACE;
9074 const UINT vertex_size10 = sizeof(*vertices10);
9075 const struct vertex_ptc_ubyte4 exp_vertices10[] =
9076 {
9077 {{ 0.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
9078 {{ 2.0f, 3.0f, 0.f}, {2, 3, 0, 1}},
9079 {{ 0.0f, 0.0f, 0.f}, {254, 255, 0, 1}},
9080
9081 {{ 3.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
9082 {{ 3.0f, 0.0f, 0.f}, {1, 2, 0, 1}},
9083 {{ 1.0f, 0.0f, 0.f}, {0, 0, 0, 1}},
9084 };
9085 const UINT exp_vertex_size10 = sizeof(*exp_vertices10);
9086 /* Test 11. Convert FLOAT2 to SHORT2. */
9087 const struct vertex_ptc vertices11[] =
9088 {
9089 {{ 0.0f, 3.0f, 0.f}, { 1.0f, -1.0f}},
9090 {{ 2.0f, 3.0f, 0.f}, { 0.4f, 0.5f}},
9091 {{ 0.0f, 0.0f, 0.f}, {-0.5f, -5.0f}},
9092
9093 {{ 3.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MIN}},
9094 {{ 3.0f, 0.0f, 0.f}, {SHRT_MAX + 1.0f, SHRT_MIN - 1.0f}},
9095 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX + 2.0f, SHRT_MIN - 2.0f}},
9096
9097 {{ 4.0f, 3.0f, 0.f}, {2 * SHRT_MAX, 2 * SHRT_MIN}},
9098 {{ 6.0f, 0.0f, 0.f}, {3 * SHRT_MAX, 3 * SHRT_MIN}},
9099 {{ 4.0f, 0.0f, 0.f}, {4 * SHRT_MAX, 4 * SHRT_MIN}},
9100 };
9101 const UINT num_vertices11 = ARRAY_SIZE(vertices11);
9102 const UINT num_faces11 = ARRAY_SIZE(vertices11) / VERTS_PER_FACE;
9103 const UINT vertex_size11 = sizeof(*vertices11);
9104 const struct vertex_ptc_short2 exp_vertices11[] =
9105 {
9106 {{ 0.0f, 3.0f, 0.f}, {1, 0}},
9107 {{ 2.0f, 3.0f, 0.f}, {0, 1}},
9108 {{ 0.0f, 0.0f, 0.f}, {0, -4}},
9109
9110 {{ 3.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MIN + 1}},
9111 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MIN}},
9112 {{ 1.0f, 0.0f, 0.f}, {SHRT_MIN + 1, SHRT_MAX}},
9113
9114 {{ 4.0f, 3.0f, 0.f}, {-2, 1}},
9115 {{ 6.0f, 0.0f, 0.f}, {32765, -32767}},
9116 {{ 4.0f, 0.0f, 0.f}, {-4, 1}},
9117 };
9118 const UINT exp_vertex_size11 = sizeof(*exp_vertices11);
9119 /* Test 12. Convert FLOAT2 to SHORT4. */
9120 const struct vertex_ptc vertices12[] =
9121 {
9122 {{ 0.0f, 3.0f, 0.f}, { 1.0f, -1.0f}},
9123 {{ 2.0f, 3.0f, 0.f}, { 0.4f, 0.5f}},
9124 {{ 0.0f, 0.0f, 0.f}, {-0.5f, -5.0f}},
9125
9126 {{ 3.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MIN}},
9127 {{ 3.0f, 0.0f, 0.f}, {SHRT_MAX + 1.0f, SHRT_MIN - 1.0f}},
9128 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX + 2.0f, SHRT_MIN - 2.0f}},
9129
9130 {{ 4.0f, 3.0f, 0.f}, {2 * SHRT_MAX, 2 * SHRT_MIN}},
9131 {{ 6.0f, 0.0f, 0.f}, {3 * SHRT_MAX, 3 * SHRT_MIN}},
9132 {{ 4.0f, 0.0f, 0.f}, {4 * SHRT_MAX, 4 * SHRT_MIN}},
9133 };
9134 const UINT num_vertices12 = ARRAY_SIZE(vertices12);
9135 const UINT num_faces12 = ARRAY_SIZE(vertices12) / VERTS_PER_FACE;
9136 const UINT vertex_size12 = sizeof(*vertices12);
9137 const struct vertex_ptc_short4 exp_vertices12[] =
9138 {
9139 {{ 0.0f, 3.0f, 0.f}, {1, 0, 0, 1}},
9140 {{ 2.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
9141 {{ 0.0f, 0.0f, 0.f}, {0, -4, 0, 1}},
9142
9143 {{ 3.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MIN + 1, 0, 1}},
9144 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MIN, 0, 1}},
9145 {{ 1.0f, 0.0f, 0.f}, {SHRT_MIN + 1, SHRT_MAX, 0, 1}},
9146
9147 {{ 4.0f, 3.0f, 0.f}, {-2, 1, 0, 1}},
9148 {{ 6.0f, 0.0f, 0.f}, {32765, -32767, 0, 1}},
9149 {{ 4.0f, 0.0f, 0.f}, {-4, 1, 0, 1}},
9150 };
9151 const UINT exp_vertex_size12 = sizeof(*exp_vertices12);
9152 /* Test 13. Convert FLOAT2 to UBYTE4N. */
9153 const struct vertex_ptc vertices13[] =
9154 {
9155 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 2.0f}},
9156 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
9157 {{ 0.0f, 0.0f, 0.f}, {-0.4f, -0.5f}},
9158
9159 {{ 3.0f, 3.0f, 0.f}, {-0.6f, -1.0f}},
9160 {{ 3.0f, 0.0f, 0.f}, {UCHAR_MAX, UCHAR_MAX + 1}},
9161 {{ 1.0f, 0.0f, 0.f}, {2 * UCHAR_MAX, -UCHAR_MAX}},
9162 };
9163 const UINT num_vertices13 = ARRAY_SIZE(vertices13);
9164 const UINT num_faces13 = ARRAY_SIZE(vertices13) / VERTS_PER_FACE;
9165 const UINT vertex_size13 = sizeof(*vertices13);
9166 const struct vertex_ptc_ubyte4n exp_vertices13[] =
9167 {
9168 {{ 0.0f, 3.0f, 0.f}, {255, 255, 0, 255}},
9169 {{ 2.0f, 3.0f, 0.f}, {128, 179, 0, 255}},
9170 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 255}},
9171
9172 {{ 3.0f, 3.0f, 0.f}, {0, 0, 0, 255}},
9173 {{ 3.0f, 0.0f, 0.f}, {255, 255, 0, 255}},
9174 {{ 1.0f, 0.0f, 0.f}, {255, 0, 0, 255}},
9175 };
9176 const UINT exp_vertex_size13 = sizeof(*exp_vertices13);
9177 /* Test 14. Convert FLOAT2 to SHORT2N. */
9178 const struct vertex_ptc vertices14[] =
9179 {
9180 {{ 0.0f, 3.0f, 0.f}, {1.0f, 2.0f}},
9181 {{ 2.0f, 3.0f, 0.f}, {0.4f, 0.5f}},
9182 {{ 0.0f, 0.0f, 0.f}, {0.6f, -1.0f}},
9183
9184 {{ 3.0f, 3.0f, 0.f}, {-0.4f, -0.5f}},
9185 {{ 3.0f, 0.0f, 0.f}, {-0.9f, -0.99997}},
9186 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX, SHRT_MIN}},
9187 };
9188 const UINT num_vertices14 = ARRAY_SIZE(vertices14);
9189 const UINT num_faces14 = ARRAY_SIZE(vertices14) / VERTS_PER_FACE;
9190 const UINT vertex_size14 = sizeof(*vertices14);
9191 const struct vertex_ptc_short2 exp_vertices14[] =
9192 {
9193 {{ 0.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MAX}},
9194 {{ 2.0f, 3.0f, 0.f}, {13107, 16384}},
9195 {{ 0.0f, 0.0f, 0.f}, {19660, SHRT_MIN + 2}},
9196
9197 {{ 3.0f, 3.0f, 0.f}, {-13106, -16383}},
9198 {{ 3.0f, 0.0f, 0.f}, {-29489, SHRT_MIN + 3}},
9199 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX, SHRT_MIN + 2}},
9200 };
9201 const UINT exp_vertex_size14 = sizeof(*exp_vertices14);
9202 /* Test 15. Convert FLOAT2 to SHORT4N. */
9203 const struct vertex_ptc vertices15[] =
9204 {
9205 {{ 0.0f, 3.0f, 0.f}, {1.0f, 2.0f}},
9206 {{ 2.0f, 3.0f, 0.f}, {0.4f, 0.5f}},
9207 {{ 0.0f, 0.0f, 0.f}, {0.6f, -1.0f}},
9208
9209 {{ 3.0f, 3.0f, 0.f}, {-0.4f, -0.5f}},
9210 {{ 3.0f, 0.0f, 0.f}, {-0.9f, -0.99997}},
9211 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX, SHRT_MIN}},
9212 };
9213 const UINT num_vertices15 = ARRAY_SIZE(vertices15);
9214 const UINT num_faces15 = ARRAY_SIZE(vertices15) / VERTS_PER_FACE;
9215 const UINT vertex_size15 = sizeof(*vertices15);
9216 const struct vertex_ptc_short4 exp_vertices15[] =
9217 {
9218 {{ 0.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MAX, 0, SHRT_MAX}},
9219 {{ 2.0f, 3.0f, 0.f}, {13107, 16384, 0, SHRT_MAX}},
9220 {{ 0.0f, 0.0f, 0.f}, {19660, SHRT_MIN + 2, 0, SHRT_MAX}},
9221
9222 {{ 3.0f, 3.0f, 0.f}, {-13106, -16383, 0, SHRT_MAX}},
9223 {{ 3.0f, 0.0f, 0.f}, {-29489, SHRT_MIN + 3, 0, SHRT_MAX}},
9224 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX, SHRT_MIN + 2, 0, SHRT_MAX}},
9225 };
9226 const UINT exp_vertex_size15 = sizeof(*exp_vertices15);
9227 /* Test 16. Convert FLOAT2 to USHORT2N. */
9228 const struct vertex_ptc vertices16[] =
9229 {
9230 {{ 0.0f, 3.0f, 0.f}, {1.0f, 2.0f}},
9231 {{ 2.0f, 3.0f, 0.f}, {0.4f, 0.5f}},
9232 {{ 0.0f, 0.0f, 0.f}, {0.6f, -1.0f}},
9233
9234 {{ 3.0f, 3.0f, 0.f}, {-0.4f, -0.5f}},
9235 {{ 3.0f, 0.0f, 0.f}, {-0.9f, 0.99998f}},
9236 {{ 1.0f, 0.0f, 0.f}, {USHRT_MAX, 0.0f}},
9237 };
9238 const UINT num_vertices16 = ARRAY_SIZE(vertices16);
9239 const UINT num_faces16 = ARRAY_SIZE(vertices16) / VERTS_PER_FACE;
9240 const UINT vertex_size16 = sizeof(*vertices16);
9241 const struct vertex_ptc_ushort2n exp_vertices16[] =
9242 {
9243 {{ 0.0f, 3.0f, 0.f}, {USHRT_MAX, USHRT_MAX}},
9244 {{ 2.0f, 3.0f, 0.f}, {26214, 32768}},
9245 {{ 0.0f, 0.0f, 0.f}, {39321, 0}},
9246
9247 {{ 3.0f, 3.0f, 0.f}, {0, 0}},
9248 {{ 3.0f, 0.0f, 0.f}, {0, USHRT_MAX - 1}},
9249 {{ 1.0f, 0.0f, 0.f}, {USHRT_MAX, 0}},
9250 };
9251 const UINT exp_vertex_size16 = sizeof(*exp_vertices16);
9252 /* Test 17. Convert FLOAT2 to USHORT4N. */
9253 const struct vertex_ptc vertices17[] =
9254 {
9255 {{ 0.0f, 3.0f, 0.f}, {1.0f, 2.0f}},
9256 {{ 2.0f, 3.0f, 0.f}, {0.4f, 0.5f}},
9257 {{ 0.0f, 0.0f, 0.f}, {0.6f, -1.0f}},
9258
9259 {{ 3.0f, 3.0f, 0.f}, {-0.4f, -0.5f}},
9260 {{ 3.0f, 0.0f, 0.f}, {-0.9f, 0.99998f}},
9261 {{ 1.0f, 0.0f, 0.f}, {USHRT_MAX, 0.0f}},
9262 };
9263 const UINT num_vertices17 = ARRAY_SIZE(vertices17);
9264 const UINT num_faces17 = ARRAY_SIZE(vertices17) / VERTS_PER_FACE;
9265 const UINT vertex_size17 = sizeof(*vertices17);
9266 const struct vertex_ptc_ushort4n exp_vertices17[] =
9267 {
9268 {{ 0.0f, 3.0f, 0.f}, {USHRT_MAX, USHRT_MAX, 0, USHRT_MAX}},
9269 {{ 2.0f, 3.0f, 0.f}, {26214, 32768, 0, USHRT_MAX}},
9270 {{ 0.0f, 0.0f, 0.f}, {39321, 0, 0, USHRT_MAX}},
9271
9272 {{ 3.0f, 3.0f, 0.f}, {0, 0, 0, USHRT_MAX}},
9273 {{ 3.0f, 0.0f, 0.f}, {0, USHRT_MAX - 1, 0, USHRT_MAX}},
9274 {{ 1.0f, 0.0f, 0.f}, {USHRT_MAX, 0, 0, USHRT_MAX}},
9275 };
9276 const UINT exp_vertex_size17 = sizeof(*exp_vertices17);
9277 /* Test 18. Test that the method field is compared by converting a FLOAT2 to
9278 * FLOAT16_2. where the method field has been change from
9279 * D3DDECLMETHOD_DEFAULT to D3DDECLMETHOD_PARTIALU. */
9280 const struct vertex_ptc vertices18[] =
9281 {
9282 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}},
9283 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}},
9284 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}},
9285
9286 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}},
9287 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}},
9288 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}},
9289 };
9290 const UINT num_vertices18 = ARRAY_SIZE(vertices18);
9291 const UINT num_faces18 = ARRAY_SIZE(vertices18) / VERTS_PER_FACE;
9292 const UINT vertex_size18 = sizeof(*vertices18);
9293 const struct vertex_ptc_float16_2 exp_vertices18[] =
9294 {
9295 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
9296 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */
9297 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */
9298
9299 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd}}, /* {0.2f, 0.3f} */
9300 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
9301 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */
9302 };
9303 const UINT exp_vertex_size18 = sizeof(*exp_vertices18);
9304 /* Test 19. Test that data is lost if usage index changes, e.g. TEXCOORD0
9305 * TEXCOORD1. */
9306 const struct vertex_pntc vertices19[] =
9307 {
9308 {{ 0.0f, 3.0f, 0.f}, up, { 1.0f, 1.0f}},
9309 {{ 2.0f, 3.0f, 0.f}, up, { 0.5f, 0.7f}},
9310 {{ 0.0f, 0.0f, 0.f}, up, {-0.2f, -0.3f}},
9311
9312 {{ 3.0f, 3.0f, 0.f}, up, { 0.2f, 0.3f}},
9313 {{ 3.0f, 0.0f, 0.f}, up, { 1.0f, 1.0f}},
9314 {{ 1.0f, 0.0f, 0.f}, up, { 0.1f, 0.2f}},
9315 };
9316 const UINT num_vertices19 = ARRAY_SIZE(vertices19);
9317 const UINT num_faces19 = ARRAY_SIZE(vertices19) / VERTS_PER_FACE;
9318 const UINT vertex_size19 = sizeof(*vertices19);
9319 const struct vertex_pntc exp_vertices19[] =
9320 {
9321 {{ 0.0f, 3.0f, 0.f}, up, zero_vec2},
9322 {{ 2.0f, 3.0f, 0.f}, up, zero_vec2},
9323 {{ 0.0f, 0.0f, 0.f}, up, zero_vec2},
9324
9325 {{ 3.0f, 3.0f, 0.f}, up, zero_vec2},
9326 {{ 3.0f, 0.0f, 0.f}, up, zero_vec2},
9327 {{ 1.0f, 0.0f, 0.f}, up, zero_vec2},
9328 };
9329 const UINT exp_vertex_size19 = sizeof(*exp_vertices19);
9330 /* Test 20. Another test that data is lost if usage index changes, e.g.
9331 * TEXCOORD1 to TEXCOORD0. */
9332 const struct vertex_pntc vertices20[] =
9333 {
9334 {{ 0.0f, 3.0f, 0.f}, up, { 1.0f, 1.0f}},
9335 {{ 2.0f, 3.0f, 0.f}, up, { 0.5f, 0.7f}},
9336 {{ 0.0f, 0.0f, 0.f}, up, {-0.2f, -0.3f}},
9337
9338 {{ 3.0f, 3.0f, 0.f}, up, { 0.2f, 0.3f}},
9339 {{ 3.0f, 0.0f, 0.f}, up, { 1.0f, 1.0f}},
9340 {{ 1.0f, 0.0f, 0.f}, up, { 0.1f, 0.2f}},
9341 };
9342 const UINT num_vertices20 = ARRAY_SIZE(vertices20);
9343 const UINT num_faces20 = ARRAY_SIZE(vertices20) / VERTS_PER_FACE;
9344 const UINT vertex_size20 = sizeof(*vertices20);
9345 const struct vertex_pntc exp_vertices20[] =
9346 {
9347 {{ 0.0f, 3.0f, 0.f}, up, zero_vec2},
9348 {{ 2.0f, 3.0f, 0.f}, up, zero_vec2},
9349 {{ 0.0f, 0.0f, 0.f}, up, zero_vec2},
9350
9351 {{ 3.0f, 3.0f, 0.f}, up, zero_vec2},
9352 {{ 3.0f, 0.0f, 0.f}, up, zero_vec2},
9353 {{ 1.0f, 0.0f, 0.f}, up, zero_vec2},
9354 };
9355 const UINT exp_vertex_size20 = sizeof(*exp_vertices20);
9356 /* Test 21. Convert FLOAT1 to FLOAT2. */
9357 const struct vertex_ptc_float1 vertices21[] =
9358 {
9359 {{ 0.0f, 3.0f, 0.f}, 1.0f},
9360 {{ 2.0f, 3.0f, 0.f}, 0.5f},
9361 {{ 0.0f, 0.0f, 0.f}, -0.2f},
9362
9363 {{ 3.0f, 3.0f, 0.f}, 0.2f},
9364 {{ 3.0f, 0.0f, 0.f}, 1.0f},
9365 {{ 1.0f, 0.0f, 0.f}, 0.1f},
9366 };
9367 const UINT num_vertices21 = ARRAY_SIZE(vertices21);
9368 const UINT num_faces21 = ARRAY_SIZE(vertices21) / VERTS_PER_FACE;
9369 const UINT vertex_size21 = sizeof(*vertices21);
9370 const struct vertex_ptc exp_vertices21[] =
9371 {
9372 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 0.0f}},
9373 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.0f}},
9374 {{ 0.0f, 0.0f, 0.f}, {-0.2f, 0.0f}},
9375
9376 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.0f}},
9377 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 0.0f}},
9378 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.0f}},
9379 };
9380 const UINT exp_vertex_size21 = sizeof(*exp_vertices21);
9381 /* Test 22. Convert FLOAT1 to FLOAT3. */
9382 const struct vertex_ptc_float1 vertices22[] =
9383 {
9384 {{ 0.0f, 3.0f, 0.f}, 1.0f},
9385 {{ 2.0f, 3.0f, 0.f}, 0.5f},
9386 {{ 0.0f, 0.0f, 0.f}, -0.2f},
9387
9388 {{ 3.0f, 3.0f, 0.f}, 0.2f},
9389 {{ 3.0f, 0.0f, 0.f}, 1.0f},
9390 {{ 1.0f, 0.0f, 0.f}, 0.1f},
9391 };
9392 const UINT num_vertices22 = ARRAY_SIZE(vertices22);
9393 const UINT num_faces22 = ARRAY_SIZE(vertices22) / VERTS_PER_FACE;
9394 const UINT vertex_size22 = sizeof(*vertices22);
9395 const struct vertex_ptc_float3 exp_vertices22[] =
9396 {
9397 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 0.0f, 0.0f}},
9398 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.0f, 0.0f}},
9399 {{ 0.0f, 0.0f, 0.f}, {-0.2f, 0.0f, 0.0f}},
9400
9401 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.0f, 0.0f}},
9402 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 0.0f, 0.0f}},
9403 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.0f, 0.0f}},
9404 };
9405 const UINT exp_vertex_size22 = sizeof(*exp_vertices22);
9406 /* Test 23. Convert FLOAT1 to FLOAT4. */
9407 const struct vertex_ptc_float1 vertices23[] =
9408 {
9409 {{ 0.0f, 3.0f, 0.f}, 1.0f},
9410 {{ 2.0f, 3.0f, 0.f}, 0.5f},
9411 {{ 0.0f, 0.0f, 0.f}, -0.2f},
9412
9413 {{ 3.0f, 3.0f, 0.f}, 0.2f},
9414 {{ 3.0f, 0.0f, 0.f}, 1.0f},
9415 {{ 1.0f, 0.0f, 0.f}, 0.1f},
9416 };
9417 const UINT num_vertices23 = ARRAY_SIZE(vertices23);
9418 const UINT num_faces23 = ARRAY_SIZE(vertices23) / VERTS_PER_FACE;
9419 const UINT vertex_size23 = sizeof(*vertices23);
9420 const struct vertex_ptc_float4 exp_vertices23[] =
9421 {
9422 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 0.0f, 0.0f, 1.0f}},
9423 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.0f, 0.0f, 1.0f}},
9424 {{ 0.0f, 0.0f, 0.f}, {-0.2f, 0.0f, 0.0f, 1.0f}},
9425
9426 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.0f, 0.0f, 1.0f}},
9427 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 0.0f, 0.0f, 1.0f}},
9428 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.0f, 0.0f, 1.0f}},
9429 };
9430 const UINT exp_vertex_size23 = sizeof(*exp_vertices23);
9431 /* Test 24. Convert FLOAT1 to D3DCOLOR. */
9432 const struct vertex_ptc_float1 vertices24[] =
9433 {
9434 {{ 0.0f, 3.0f, 0.f}, 1.0f},
9435 {{ 2.0f, 3.0f, 0.f}, 0.5f},
9436 {{ 0.0f, 0.0f, 0.f}, -0.2f},
9437
9438 {{ 3.0f, 3.0f, 0.f}, 0.2f},
9439 {{ 3.0f, 0.0f, 0.f}, 1.0f},
9440 {{ 1.0f, 0.0f, 0.f}, 0.11f},
9441 };
9442 const UINT num_vertices24 = ARRAY_SIZE(vertices24);
9443 const UINT num_faces24 = ARRAY_SIZE(vertices24) / VERTS_PER_FACE;
9444 const UINT vertex_size24 = sizeof(*vertices24);
9445 const struct vertex_ptc_d3dcolor exp_vertices24[] =
9446 {
9447 {{ 0.0f, 3.0f, 0.f}, {0, 0, 255, 255}},
9448 {{ 2.0f, 3.0f, 0.f}, {0, 0, 128, 255}},
9449 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 255}},
9450
9451 {{ 3.0f, 3.0f, 0.f}, {0, 0, 51, 255}},
9452 {{ 3.0f, 0.0f, 0.f}, {0, 0, 255, 255}},
9453 {{ 1.0f, 0.0f, 0.f}, {0, 0, 28, 255}},
9454 };
9455 const UINT exp_vertex_size24 = sizeof(*exp_vertices24);
9456 /* Test 25. Convert FLOAT1 to ubyte4. */
9457 const struct vertex_ptc_float1 vertices25[] =
9458 {
9459 {{ 0.0f, 3.0f, 0.f}, 0.0f},
9460 {{ 2.0f, 3.0f, 0.f}, 1.4f},
9461 {{ 0.0f, 0.0f, 0.f}, 1.5f},
9462
9463 {{ 3.0f, 3.0f, 0.f}, 255.0f},
9464 {{ 3.0f, 0.0f, 0.f}, 256.0f},
9465 {{ 1.0f, 0.0f, 0.f}, -1.0f},
9466 };
9467 const UINT num_vertices25 = ARRAY_SIZE(vertices25);
9468 const UINT num_faces25 = ARRAY_SIZE(vertices25) / VERTS_PER_FACE;
9469 const UINT vertex_size25 = sizeof(*vertices25);
9470 const struct vertex_ptc_ubyte4 exp_vertices25[] =
9471 {
9472 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 1}},
9473 {{ 2.0f, 3.0f, 0.f}, {1, 0, 0, 1}},
9474 {{ 0.0f, 0.0f, 0.f}, {2, 0, 0, 1}},
9475
9476 {{ 3.0f, 3.0f, 0.f}, {255, 0, 0, 1}},
9477 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 1}},
9478 {{ 1.0f, 0.0f, 0.f}, {0, 0, 0, 1}},
9479 };
9480 const UINT exp_vertex_size25 = sizeof(*exp_vertices25);
9481 /* Test 26. Convert FLOAT4 to D3DCOLOR. */
9482 const struct vertex_ptc_float4 vertices26[] =
9483 {
9484 {{ 0.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.4f, 0.5f}},
9485 {{ 2.0f, 3.0f, 0.f}, {-0.4f, -0.5f, -1.0f, -2.0f}},
9486 {{ 0.0f, 0.0f, 0.f}, {254.0f, 255.0f, 256.0f, 257.0f}},
9487
9488 {{ 3.0f, 3.0f, 0.f}, {0.1f, 0.2f, 0.3f, 0.4f}},
9489 {{ 3.0f, 0.0f, 0.f}, {0.5f, 0.6f, 0.7f, 0.8f}},
9490 {{ 1.0f, 0.0f, 0.f}, {0.9f, 0.99f, 0.995f, 0.999f}},
9491 };
9492 const UINT num_vertices26 = ARRAY_SIZE(vertices26);
9493 const UINT num_faces26 = ARRAY_SIZE(vertices26) / VERTS_PER_FACE;
9494 const UINT vertex_size26 = sizeof(*vertices26);
9495 const struct vertex_ptc_d3dcolor exp_vertices26[] =
9496 {
9497 {{ 0.0f, 3.0f, 0.f}, {102, 255, 0, 128}},
9498 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9499 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
9500
9501 {{ 3.0f, 3.0f, 0.f}, {77, 51, 26, 102}},
9502 {{ 3.0f, 0.0f, 0.f}, {179, 153, 128, 204}},
9503 {{ 1.0f, 0.0f, 0.f}, {254, 252, 230, 255}},
9504 };
9505 const UINT exp_vertex_size26 = sizeof(*exp_vertices26);
9506 /* Test 27. Convert D3DCOLOR to FLOAT4. */
9507 const struct vertex_ptc_d3dcolor vertices27[] =
9508 {
9509 {{ 0.0f, 3.0f, 0.f}, {102, 255, 0, 128}},
9510 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9511 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}},
9512
9513 {{ 3.0f, 3.0f, 0.f}, {77, 51, 26, 102}},
9514 {{ 3.0f, 0.0f, 0.f}, {179, 153, 128, 204}},
9515 {{ 1.0f, 0.0f, 0.f}, {254, 252, 230, 255}},
9516 };
9517 const UINT num_vertices27 = ARRAY_SIZE(vertices27);
9518 const UINT num_faces27 = ARRAY_SIZE(vertices27) / VERTS_PER_FACE;
9519 const UINT vertex_size27 = sizeof(*vertices27);
9520 const struct vertex_ptc_float4 exp_vertices27[] =
9521 {
9522 {{ 0.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.4f, 0.501961f}},
9523 {{ 2.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9524 {{ 0.0f, 0.0f, 0.f}, {1.0f, 1.0f, 1.0f, 1.0f}},
9525
9526 {{ 3.0f, 3.0f, 0.f}, {0.101961f, 0.2f, 0.301961f, 0.4f}},
9527 {{ 3.0f, 0.0f, 0.f}, {0.501961f, 0.6f, 0.701961f, 0.8f}},
9528 {{ 1.0f, 0.0f, 0.f}, {0.901961f, 0.988235f, 0.996078f, 1.0f}},
9529 };
9530 const UINT exp_vertex_size27 = sizeof(*exp_vertices27);
9531 /* Test 28. Convert UBYTE4 to FLOAT4. */
9532 const struct vertex_ptc_ubyte4 vertices28[] =
9533 {
9534 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9535 {{ 2.0f, 3.0f, 0.f}, {1, 1, 1, 1}},
9536 {{ 0.0f, 0.0f, 0.f}, {1, 0, 1, 0}},
9537
9538 {{ 3.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
9539 {{ 3.0f, 0.0f, 0.f}, {10, 20, 30, 40}},
9540 {{ 1.0f, 0.0f, 0.f}, {50, 60, 127, 255}},
9541 };
9542 const UINT num_vertices28 = ARRAY_SIZE(vertices28);
9543 const UINT num_faces28 = ARRAY_SIZE(vertices28) / VERTS_PER_FACE;
9544 const UINT vertex_size28 = sizeof(*vertices28);
9545 const struct vertex_ptc_float4 exp_vertices28[] =
9546 {
9547 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9548 {{ 2.0f, 3.0f, 0.f}, {1.0f, 1.0f, 1.0f, 1.0f}},
9549 {{ 0.0f, 0.0f, 0.f}, {1.0f, 0.0f, 1.0f, 0.0f}},
9550
9551 {{ 3.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.0f, 1.0f}},
9552 {{ 3.0f, 0.0f, 0.f}, {10.0f, 20.0f, 30.0f, 40.0f}},
9553 {{ 1.0f, 0.0f, 0.f}, {50.0f, 60.0f, 127.0f, 255.0f}},
9554 };
9555 const UINT exp_vertex_size28 = sizeof(*exp_vertices28);
9556 /* Test 29. Convert SHORT2 to FLOAT4. */
9557 const struct vertex_ptc_short2 vertices29[] =
9558 {
9559 {{ 0.0f, 3.0f, 0.f}, {0, 0}},
9560 {{ 2.0f, 3.0f, 0.f}, {0, 1}},
9561 {{ 0.0f, 0.0f, 0.f}, {1, 0}},
9562
9563 {{ 3.0f, 3.0f, 0.f}, {1, 1}},
9564 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MAX}},
9565 {{ 1.0f, 0.0f, 0.f}, {-42, 42}},
9566 };
9567 const UINT num_vertices29 = ARRAY_SIZE(vertices29);
9568 const UINT num_faces29 = ARRAY_SIZE(vertices29) / VERTS_PER_FACE;
9569 const UINT vertex_size29 = sizeof(*vertices29);
9570 const struct vertex_ptc_float4 exp_vertices29[] =
9571 {
9572 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 1.0f}},
9573 {{ 2.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.0f, 1.0f }},
9574 {{ 0.0f, 0.0f, 0.f}, {1.0f, 0.0f, 0.0f, 1.0f}},
9575
9576 {{ 3.0f, 3.0f, 0.f}, {1.0f, 1.0f, 0.0f, 1.0f}},
9577 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MAX, 0.0f, 1.0f}},
9578 {{ 1.0f, 0.0f, 0.f}, {-42.0f, 42.0f, 0.0f, 1.0f}},
9579 };
9580 const UINT exp_vertex_size29 = sizeof(*exp_vertices29);
9581 /* Test 29. Convert SHORT4 to FLOAT4. */
9582 const struct vertex_ptc_short4 vertices30[] =
9583 {
9584 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9585 {{ 2.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
9586 {{ 0.0f, 0.0f, 0.f}, {1, 0, 1, 0}},
9587
9588 {{ 3.0f, 3.0f, 0.f}, {1, 1, 1, 1}},
9589 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MAX, 1, 0}},
9590 {{ 1.0f, 0.0f, 0.f}, {-42, 42, SHRT_MAX, SHRT_MIN}},
9591 };
9592 const UINT num_vertices30 = ARRAY_SIZE(vertices30);
9593 const UINT num_faces30 = ARRAY_SIZE(vertices30) / VERTS_PER_FACE;
9594 const UINT vertex_size30 = sizeof(*vertices30);
9595 const struct vertex_ptc_float4 exp_vertices30[] =
9596 {
9597 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9598 {{ 2.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.0f, 1.0f }},
9599 {{ 0.0f, 0.0f, 0.f}, {1.0f, 0.0f, 1.0f, 0.0f}},
9600
9601 {{ 3.0f, 3.0f, 0.f}, {1.0f, 1.0f, 1.0f, 1.0f}},
9602 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MAX, 1.0f, 0.0f}},
9603 {{ 1.0f, 0.0f, 0.f}, {-42.0f, 42.0f, SHRT_MAX, SHRT_MIN}},
9604 };
9605 const UINT exp_vertex_size30 = sizeof(*exp_vertices30);
9606 /* Test 31. Convert UBYTE4N to FLOAT4. */
9607 const struct vertex_ptc_ubyte4n vertices31[] =
9608 {
9609 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9610 {{ 2.0f, 3.0f, 0.f}, {1, 1, 1, 1}},
9611 {{ 0.0f, 0.0f, 0.f}, {1, 0, 1, 0}},
9612
9613 {{ 3.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
9614 {{ 3.0f, 0.0f, 0.f}, {10, 20, 30, 40}},
9615 {{ 1.0f, 0.0f, 0.f}, {50, 60, 70, UCHAR_MAX}},
9616 };
9617 const UINT num_vertices31 = ARRAY_SIZE(vertices31);
9618 const UINT num_faces31 = ARRAY_SIZE(vertices31) / VERTS_PER_FACE;
9619 const UINT vertex_size31 = sizeof(*vertices31);
9620 const struct vertex_ptc_float4 exp_vertices31[] =
9621 {
9622 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9623 {{ 2.0f, 3.0f, 0.f}, {(FLOAT)1/UCHAR_MAX, (FLOAT)1/UCHAR_MAX, (FLOAT)1/UCHAR_MAX, (FLOAT)1/UCHAR_MAX}},
9624 {{ 0.0f, 0.0f, 0.f}, {(FLOAT)1/UCHAR_MAX, 0.0f, (FLOAT)1/UCHAR_MAX, 0.0f}},
9625
9626 {{ 3.0f, 3.0f, 0.f}, {0.0f, (FLOAT)1/UCHAR_MAX, 0.0f, (FLOAT)1/UCHAR_MAX}},
9627 {{ 3.0f, 0.0f, 0.f}, {(FLOAT)10/UCHAR_MAX, (FLOAT)20/UCHAR_MAX, (FLOAT)30/UCHAR_MAX, (FLOAT)40/UCHAR_MAX}},
9628 {{ 1.0f, 0.0f, 0.f}, {(FLOAT)50/UCHAR_MAX, (FLOAT)60/UCHAR_MAX, (FLOAT)70/UCHAR_MAX, 1.0f}},
9629 };
9630 const UINT exp_vertex_size31 = sizeof(*exp_vertices31);
9631 /* Test 32. Convert SHORT2N to FLOAT4. */
9632 const struct vertex_ptc_short2 vertices32[] =
9633 {
9634 {{ 0.0f, 3.0f, 0.f}, {0, 0}},
9635 {{ 2.0f, 3.0f, 0.f}, {0, 1}},
9636 {{ 0.0f, 0.0f, 0.f}, {1, 0}},
9637
9638 {{ 3.0f, 3.0f, 0.f}, {1, 1}},
9639 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN + 1, SHRT_MAX}},
9640 {{ 1.0f, 0.0f, 0.f}, {-42, 42}},
9641 };
9642 const UINT num_vertices32 = ARRAY_SIZE(vertices32);
9643 const UINT num_faces32 = ARRAY_SIZE(vertices32) / VERTS_PER_FACE;
9644 const UINT vertex_size32 = sizeof(*vertices32);
9645 const struct vertex_ptc_float4 exp_vertices32[] =
9646 {
9647 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 1.0f}},
9648 {{ 2.0f, 3.0f, 0.f}, {0.0f, 1.0f/SHRT_MAX, 0.0f, 1.0f}},
9649 {{ 0.0f, 0.0f, 0.f}, {1.0f/SHRT_MAX, 0.0f, 0.0f, 1.0f}},
9650
9651 {{ 3.0f, 3.0f, 0.f}, {1.0f/SHRT_MAX, 1.0f/SHRT_MAX, 0.0f, 1.0f}},
9652 {{ 3.0f, 0.0f, 0.f}, {-1.0f, 1.0f, 0.0f, 1.0f}},
9653 {{ 1.0f, 0.0f, 0.f}, {-42.0f/SHRT_MAX, 42.0f/SHRT_MAX, 0.0f, 1.0f}},
9654 };
9655 const UINT exp_vertex_size32 = sizeof(*exp_vertices32);
9656 /* Test 33. Convert SHORT4N to FLOAT4. */
9657 const struct vertex_ptc_short4 vertices33[] =
9658 {
9659 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}},
9660 {{ 2.0f, 3.0f, 0.f}, {0, 1, 0, 1}},
9661 {{ 0.0f, 0.0f, 0.f}, {1, 0, 1, 0}},
9662
9663 {{ 3.0f, 3.0f, 0.f}, {1, 1, 1, 1}},
9664 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN + 1, SHRT_MAX, SHRT_MIN + 1, SHRT_MAX}},
9665 {{ 1.0f, 0.0f, 0.f}, {-42, 42, 1, 1}},
9666 };
9667 const UINT num_vertices33 = ARRAY_SIZE(vertices33);
9668 const UINT num_faces33 = ARRAY_SIZE(vertices33) / VERTS_PER_FACE;
9669 const UINT vertex_size33 = sizeof(*vertices33);
9670 const struct vertex_ptc_float4 exp_vertices33[] =
9671 {
9672 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9673 {{ 2.0f, 3.0f, 0.f}, {0.0f, 1.0f/SHRT_MAX, 0.0f, 1.0f/SHRT_MAX}},
9674 {{ 0.0f, 0.0f, 0.f}, {1.0f/SHRT_MAX, 0.0f, 1.0f/SHRT_MAX, 0.0f}},
9675
9676 {{ 3.0f, 3.0f, 0.f}, {1.0f/SHRT_MAX, 1.0f/SHRT_MAX, 1.0f/SHRT_MAX, 1.0f/SHRT_MAX}},
9677 {{ 3.0f, 0.0f, 0.f}, {-1.0f, 1.0f, -1.0f, 1.0f}},
9678 {{ 1.0f, 0.0f, 0.f}, {-42.0f/SHRT_MAX, 42.0f/SHRT_MAX, 1.0f/SHRT_MAX, 1.0f/SHRT_MAX}},
9679 };
9680 const UINT exp_vertex_size33 = sizeof(*exp_vertices33);
9681 /* Test 34. Convert FLOAT16_2 to FLOAT4. */
9682 const struct vertex_ptc_float16_2 vertices34[] =
9683 {
9684 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
9685 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */
9686 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */
9687
9688 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd}}, /* {0.2f, 0.3f} */
9689 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */
9690 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */
9691 };
9692 const UINT num_vertices34 = ARRAY_SIZE(vertices34);
9693 const UINT num_faces34 = ARRAY_SIZE(vertices34) / VERTS_PER_FACE;
9694 const UINT vertex_size34 = sizeof(*vertices34);
9695 const struct vertex_ptc_float4 exp_vertices34[] =
9696 {
9697 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f, 0.0f, 1.0f}},
9698 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.700195f, 0.0f, 1.0f}},
9699 {{ 0.0f, 0.0f, 0.f}, {-0.199951f, -0.300049f, 0.0f, 1.0f}},
9700
9701 {{ 3.0f, 3.0f, 0.f}, {0.199951f, 0.300049f, 0.0f, 1.0f}},
9702 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f, 0.0f, 1.0f}},
9703 {{ 1.0f, 0.0f, 0.f}, {0.099976f, 0.199951f, 0.0f, 1.0f}},
9704 };
9705 const UINT exp_vertex_size34 = sizeof(*exp_vertices34);
9706 /* Test 35. Convert FLOAT16_4 to FLOAT4. */
9707 const struct vertex_ptc_float16_4 vertices35[] =
9708 {
9709 {{ 0.0f, 3.0f, 0.f}, {0x0000, 0x0000, 0x0000, 0x0000}},
9710 {{ 2.0f, 3.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}},
9711 {{ 0.0f, 0.0f, 0.f}, {0x3c00, 0x0000, 0x3c00, 0x0000}},
9712
9713 {{ 3.0f, 3.0f, 0.f}, {0x0000, 0x3c00, 0x0000, 0x3c00}},
9714 {{ 3.0f, 0.0f, 0.f}, {0x3800, 0x399a, 0xb266, 0xb4cd}},
9715 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266, 0x2e66, 0x3266}},
9716 };
9717 const UINT num_vertices35 = ARRAY_SIZE(vertices35);
9718 const UINT num_faces35 = ARRAY_SIZE(vertices35) / VERTS_PER_FACE;
9719 const UINT vertex_size35 = sizeof(*vertices35);
9720 const struct vertex_ptc_float4 exp_vertices35[] =
9721 {
9722 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9723 {{ 2.0f, 3.0f, 0.f}, {1.0f, 1.0f, 1.0f, 1.0f}},
9724 {{ 0.0f, 0.0f, 0.f}, {1.0f, 0.0f, 1.0f, 0.0f}},
9725
9726 {{ 3.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.0f, 1.0f}},
9727 {{ 3.0f, 0.0f, 0.f}, {0.5f, 0.700195f, -0.199951f, -0.300049f}},
9728 {{ 1.0f, 0.0f, 0.f}, {0.099976f, 0.199951f, 0.099976f, 0.199951f}},
9729 };
9730 const UINT exp_vertex_size35 = sizeof(*exp_vertices35);
9731 /* Test 36. Check that vertex buffer sharing is ok. */
9732 const struct vertex_pn vertices36[] =
9733 {
9734 {{ 0.0f, 3.0f, 0.f}, up},
9735 {{ 2.0f, 3.0f, 0.f}, up},
9736 {{ 0.0f, 0.0f, 0.f}, up},
9737 };
9738 const UINT num_vertices36 = ARRAY_SIZE(vertices36);
9739 const UINT num_faces36 = ARRAY_SIZE(vertices36) / VERTS_PER_FACE;
9740 const UINT vertex_size36 = sizeof(*vertices36);
9741 const DWORD clone_options36 = options | D3DXMESH_VB_SHARE;
9742 /* Common mesh data */
9743 ID3DXMesh *mesh = NULL;
9744 ID3DXMesh *mesh_clone = NULL;
9745 struct
9746 {
9747 const BYTE *vertices;
9748 const DWORD *indices;
9749 const DWORD *attributes;
9750 const UINT num_vertices;
9751 const UINT num_faces;
9752 const UINT vertex_size;
9753 const DWORD create_options;
9754 const DWORD clone_options;
9755 D3DVERTEXELEMENT9 *declaration;
9756 D3DVERTEXELEMENT9 *new_declaration;
9757 const BYTE *exp_vertices;
9758 const UINT exp_vertex_size;
9759 }
9760 tc[] =
9761 {
9762 {
9763 (BYTE*)vertices0,
9764 NULL,
9765 NULL,
9766 num_vertices0,
9767 num_faces0,
9768 vertex_size0,
9769 options,
9770 options,
9771 declaration_pn,
9772 declaration_pn,
9773 (BYTE*)vertices0,
9774 vertex_size0
9775 },
9776 {
9777 (BYTE*)vertices0,
9778 NULL,
9779 NULL,
9780 num_vertices0,
9781 num_faces0,
9782 vertex_size0,
9783 options_16bit,
9784 options_16bit,
9785 declaration_pn,
9786 declaration_pn,
9787 (BYTE*)vertices0,
9788 vertex_size0
9789 },
9790 {
9791 (BYTE*)vertices0,
9792 NULL,
9793 NULL,
9794 num_vertices0,
9795 num_faces0,
9796 vertex_size0,
9797 options,
9798 options,
9799 declaration_pn,
9800 declaration_pntc,
9801 (BYTE*)exp_vertices2,
9802 exp_vertex_size2
9803 },
9804 {
9805 (BYTE*)vertices0,
9806 NULL,
9807 NULL,
9808 num_vertices0,
9809 num_faces0,
9810 vertex_size0,
9811 options,
9812 options,
9813 declaration_pn,
9814 declaration_ptcn,
9815 (BYTE*)exp_vertices3,
9816 exp_vertex_size3
9817 },
9818 {
9819 (BYTE*)vertices4,
9820 NULL,
9821 NULL,
9822 num_vertices4,
9823 num_faces4,
9824 vertex_size4,
9825 options,
9826 options,
9827 declaration_ptc,
9828 declaration_ptc_float16_2,
9829 (BYTE*)exp_vertices4,
9830 exp_vertex_size4
9831 },
9832 {
9833 (BYTE*)vertices5,
9834 NULL,
9835 NULL,
9836 num_vertices5,
9837 num_faces5,
9838 vertex_size5,
9839 options,
9840 options,
9841 declaration_ptc,
9842 declaration_ptc_float16_4,
9843 (BYTE*)exp_vertices5,
9844 exp_vertex_size5
9845 },
9846 {
9847 (BYTE*)vertices6,
9848 NULL,
9849 NULL,
9850 num_vertices6,
9851 num_faces6,
9852 vertex_size6,
9853 options,
9854 options,
9855 declaration_ptc,
9856 declaration_ptc_float1,
9857 (BYTE*)exp_vertices6,
9858 exp_vertex_size6
9859 },
9860 {
9861 (BYTE*)vertices7,
9862 NULL,
9863 NULL,
9864 num_vertices7,
9865 num_faces7,
9866 vertex_size7,
9867 options,
9868 options,
9869 declaration_ptc,
9870 declaration_ptc_float3,
9871 (BYTE*)exp_vertices7,
9872 exp_vertex_size7
9873 },
9874 {
9875 (BYTE*)vertices8,
9876 NULL,
9877 NULL,
9878 num_vertices8,
9879 num_faces8,
9880 vertex_size8,
9881 options,
9882 options,
9883 declaration_ptc,
9884 declaration_ptc_float4,
9885 (BYTE*)exp_vertices8,
9886 exp_vertex_size8
9887 },
9888 {
9889 (BYTE*)vertices9,
9890 NULL,
9891 NULL,
9892 num_vertices9,
9893 num_faces9,
9894 vertex_size9,
9895 options,
9896 options,
9897 declaration_ptc,
9898 declaration_ptc_d3dcolor,
9899 (BYTE*)exp_vertices9,
9900 exp_vertex_size9
9901 },
9902 {
9903 (BYTE*)vertices10,
9904 NULL,
9905 NULL,
9906 num_vertices10,
9907 num_faces10,
9908 vertex_size10,
9909 options,
9910 options,
9911 declaration_ptc,
9912 declaration_ptc_ubyte4,
9913 (BYTE*)exp_vertices10,
9914 exp_vertex_size10
9915 },
9916 {
9917 (BYTE*)vertices11,
9918 NULL,
9919 NULL,
9920 num_vertices11,
9921 num_faces11,
9922 vertex_size11,
9923 options,
9924 options,
9925 declaration_ptc,
9926 declaration_ptc_short2,
9927 (BYTE*)exp_vertices11,
9928 exp_vertex_size11
9929 },
9930 {
9931 (BYTE*)vertices12,
9932 NULL,
9933 NULL,
9934 num_vertices12,
9935 num_faces12,
9936 vertex_size12,
9937 options,
9938 options,
9939 declaration_ptc,
9940 declaration_ptc_short4,
9941 (BYTE*)exp_vertices12,
9942 exp_vertex_size12
9943 },
9944 {
9945 (BYTE*)vertices13,
9946 NULL,
9947 NULL,
9948 num_vertices13,
9949 num_faces13,
9950 vertex_size13,
9951 options,
9952 options,
9953 declaration_ptc,
9954 declaration_ptc_ubyte4n,
9955 (BYTE*)exp_vertices13,
9956 exp_vertex_size13
9957 },
9958 {
9959 (BYTE*)vertices14,
9960 NULL,
9961 NULL,
9962 num_vertices14,
9963 num_faces14,
9964 vertex_size14,
9965 options,
9966 options,
9967 declaration_ptc,
9968 declaration_ptc_short2n,
9969 (BYTE*)exp_vertices14,
9970 exp_vertex_size14
9971 },
9972 {
9973 (BYTE*)vertices15,
9974 NULL,
9975 NULL,
9976 num_vertices15,
9977 num_faces15,
9978 vertex_size15,
9979 options,
9980 options,
9981 declaration_ptc,
9982 declaration_ptc_short4n,
9983 (BYTE*)exp_vertices15,
9984 exp_vertex_size15
9985 },
9986 {
9987 (BYTE*)vertices16,
9988 NULL,
9989 NULL,
9990 num_vertices16,
9991 num_faces16,
9992 vertex_size16,
9993 options,
9994 options,
9995 declaration_ptc,
9996 declaration_ptc_ushort2n,
9997 (BYTE*)exp_vertices16,
9998 exp_vertex_size16
9999 },
10000 {
10001 (BYTE*)vertices17,
10002 NULL,
10003 NULL,
10004 num_vertices17,
10005 num_faces17,
10006 vertex_size17,
10007 options,
10008 options,
10009 declaration_ptc,
10010 declaration_ptc_ushort4n,
10011 (BYTE*)exp_vertices17,
10012 exp_vertex_size17
10013 },
10014 {
10015 (BYTE*)vertices18,
10016 NULL,
10017 NULL,
10018 num_vertices18,
10019 num_faces18,
10020 vertex_size18,
10021 options,
10022 options,
10023 declaration_ptc,
10024 declaration_ptc_float16_2_partialu,
10025 (BYTE*)exp_vertices18,
10026 exp_vertex_size18
10027 },
10028 {
10029 (BYTE*)vertices19,
10030 NULL,
10031 NULL,
10032 num_vertices19,
10033 num_faces19,
10034 vertex_size19,
10035 options,
10036 options,
10037 declaration_pntc,
10038 declaration_pntc1,
10039 (BYTE*)exp_vertices19,
10040 exp_vertex_size19
10041 },
10042 {
10043 (BYTE*)vertices20,
10044 NULL,
10045 NULL,
10046 num_vertices20,
10047 num_faces20,
10048 vertex_size20,
10049 options,
10050 options,
10051 declaration_pntc1,
10052 declaration_pntc,
10053 (BYTE*)exp_vertices20,
10054 exp_vertex_size20
10055 },
10056 {
10057 (BYTE*)vertices21,
10058 NULL,
10059 NULL,
10060 num_vertices21,
10061 num_faces21,
10062 vertex_size21,
10063 options,
10064 options,
10065 declaration_ptc_float1,
10066 declaration_ptc,
10067 (BYTE*)exp_vertices21,
10068 exp_vertex_size21
10069 },
10070 {
10071 (BYTE*)vertices22,
10072 NULL,
10073 NULL,
10074 num_vertices22,
10075 num_faces22,
10076 vertex_size22,
10077 options,
10078 options,
10079 declaration_ptc_float1,
10080 declaration_ptc_float3,
10081 (BYTE*)exp_vertices22,
10082 exp_vertex_size22
10083 },
10084 {
10085 (BYTE*)vertices23,
10086 NULL,
10087 NULL,
10088 num_vertices23,
10089 num_faces23,
10090 vertex_size23,
10091 options,
10092 options,
10093 declaration_ptc_float1,
10094 declaration_ptc_float4,
10095 (BYTE*)exp_vertices23,
10096 exp_vertex_size23
10097 },
10098 {
10099 (BYTE*)vertices24,
10100 NULL,
10101 NULL,
10102 num_vertices24,
10103 num_faces24,
10104 vertex_size24,
10105 options,
10106 options,
10107 declaration_ptc_float1,
10108 declaration_ptc_d3dcolor,
10109 (BYTE*)exp_vertices24,
10110 exp_vertex_size24
10111 },
10112 {
10113 (BYTE*)vertices25,
10114 NULL,
10115 NULL,
10116 num_vertices25,
10117 num_faces25,
10118 vertex_size25,
10119 options,
10120 options,
10121 declaration_ptc_float1,
10122 declaration_ptc_ubyte4,
10123 (BYTE*)exp_vertices25,
10124 exp_vertex_size25
10125 },
10126 {
10127 (BYTE*)vertices26,
10128 NULL,
10129 NULL,
10130 num_vertices26,
10131 num_faces26,
10132 vertex_size26,
10133 options,
10134 options,
10135 declaration_ptc_float4,
10136 declaration_ptc_d3dcolor,
10137 (BYTE*)exp_vertices26,
10138 exp_vertex_size26
10139 },
10140 {
10141 (BYTE*)vertices27,
10142 NULL,
10143 NULL,
10144 num_vertices27,
10145 num_faces27,
10146 vertex_size27,
10147 options,
10148 options,
10149 declaration_ptc_d3dcolor,
10150 declaration_ptc_float4,
10151 (BYTE*)exp_vertices27,
10152 exp_vertex_size27
10153 },
10154 {
10155 (BYTE*)vertices28,
10156 NULL,
10157 NULL,
10158 num_vertices28,
10159 num_faces28,
10160 vertex_size28,
10161 options,
10162 options,
10163 declaration_ptc_ubyte4,
10164 declaration_ptc_float4,
10165 (BYTE*)exp_vertices28,
10166 exp_vertex_size28
10167 },
10168 {
10169 (BYTE*)vertices29,
10170 NULL,
10171 NULL,
10172 num_vertices29,
10173 num_faces29,
10174 vertex_size29,
10175 options,
10176 options,
10177 declaration_ptc_short2,
10178 declaration_ptc_float4,
10179 (BYTE*)exp_vertices29,
10180 exp_vertex_size29
10181 },
10182 {
10183 (BYTE*)vertices30,
10184 NULL,
10185 NULL,
10186 num_vertices30,
10187 num_faces30,
10188 vertex_size30,
10189 options,
10190 options,
10191 declaration_ptc_short4,
10192 declaration_ptc_float4,
10193 (BYTE*)exp_vertices30,
10194 exp_vertex_size30
10195 },
10196 {
10197 (BYTE*)vertices31,
10198 NULL,
10199 NULL,
10200 num_vertices31,
10201 num_faces31,
10202 vertex_size31,
10203 options,
10204 options,
10205 declaration_ptc_ubyte4n,
10206 declaration_ptc_float4,
10207 (BYTE*)exp_vertices31,
10208 exp_vertex_size31
10209 },
10210 {
10211 (BYTE*)vertices32,
10212 NULL,
10213 NULL,
10214 num_vertices32,
10215 num_faces32,
10216 vertex_size32,
10217 options,
10218 options,
10219 declaration_ptc_short2n,
10220 declaration_ptc_float4,
10221 (BYTE*)exp_vertices32,
10222 exp_vertex_size32
10223 },
10224 {
10225 (BYTE*)vertices33,
10226 NULL,
10227 NULL,
10228 num_vertices33,
10229 num_faces33,
10230 vertex_size33,
10231 options,
10232 options,
10233 declaration_ptc_short4n,
10234 declaration_ptc_float4,
10235 (BYTE*)exp_vertices33,
10236 exp_vertex_size33
10237 },
10238 {
10239 (BYTE*)vertices34,
10240 NULL,
10241 NULL,
10242 num_vertices34,
10243 num_faces34,
10244 vertex_size34,
10245 options,
10246 options,
10247 declaration_ptc_float16_2,
10248 declaration_ptc_float4,
10249 (BYTE*)exp_vertices34,
10250 exp_vertex_size34
10251 },
10252 {
10253 (BYTE*)vertices35,
10254 NULL,
10255 NULL,
10256 num_vertices35,
10257 num_faces35,
10258 vertex_size35,
10259 options,
10260 options,
10261 declaration_ptc_float16_4,
10262 declaration_ptc_float4,
10263 (BYTE*)exp_vertices35,
10264 exp_vertex_size35
10265 },
10266 {
10267 (BYTE*)vertices36,
10268 NULL,
10269 NULL,
10270 num_vertices36,
10271 num_faces36,
10272 vertex_size36,
10273 options,
10274 clone_options36,
10275 declaration_pn,
10276 declaration_pn,
10277 (BYTE*)vertices36,
10278 vertex_size36
10279 },
10280 };
10281 #ifdef __REACTOS__
10282 #undef up
10283 #undef zero_vec2
10284 #endif
10285
10286 test_context = new_test_context();
10287 if (!test_context)
10288 {
10289 skip("Couldn't create test context\n");
10290 goto cleanup;
10291 }
10292
10293 for (i = 0; i < ARRAY_SIZE(tc); i++)
10294 {
10295 UINT j;
10296 D3DVERTEXELEMENT9 new_declaration[MAX_FVF_DECL_SIZE];
10297 UINT exp_new_decl_length, new_decl_length;
10298 UINT exp_new_decl_size, new_decl_size;
10299
10300 hr = init_test_mesh(tc[i].num_faces, tc[i].num_vertices,
10301 tc[i].create_options,
10302 tc[i].declaration,
10303 test_context->device, &mesh,
10304 tc[i].vertices, tc[i].vertex_size,
10305 tc[i].indices, tc[i].attributes);
10306 if (FAILED(hr))
10307 {
10308 skip("Couldn't initialize test mesh %d. Got %x expected D3D_OK\n", i, hr);
10309 goto cleanup;
10310 }
10311
10312 hr = mesh->lpVtbl->CloneMesh(mesh, tc[i].clone_options, tc[i].new_declaration,
10313 test_context->device, &mesh_clone);
10314 ok(hr == D3D_OK, "Test %u, got unexpected hr %#x.\n", i, hr);
10315
10316 hr = mesh_clone->lpVtbl->GetDeclaration(mesh_clone, new_declaration);
10317 ok(hr == D3D_OK, "Test %u, got unexpected hr %#x.\n", i, hr);
10318 /* Check declaration elements */
10319 for (j = 0; tc[i].new_declaration[j].Stream != 0xFF; j++)
10320 {
10321 ok(memcmp(&tc[i].new_declaration[j], &new_declaration[j], sizeof(*new_declaration)) == 0,
10322 "Test case %d failed. Declaration element %d did not match.\n", i, j);
10323 }
10324
10325 /* Check declaration length */
10326 exp_new_decl_length = D3DXGetDeclLength(tc[i].new_declaration);
10327 new_decl_length = D3DXGetDeclLength(new_declaration);
10328 ok(new_decl_length == exp_new_decl_length,
10329 "Test case %d failed. Got new declaration length %d, expected %d\n",
10330 i, new_decl_length, exp_new_decl_length);
10331
10332 /* Check declaration size */
10333 exp_new_decl_size = D3DXGetDeclVertexSize(tc[i].new_declaration, 0);
10334 new_decl_size = D3DXGetDeclVertexSize(new_declaration, 0);
10335 ok(new_decl_size == exp_new_decl_size,
10336 "Test case %d failed. Got new declaration size %d, expected %d\n",
10337 i, new_decl_size, exp_new_decl_size);
10338
10339 /* Check vertex data in cloned mesh */
10340 hr = mesh_clone->lpVtbl->LockVertexBuffer(mesh_clone, 0, (void**)&vertices);
10341 if (FAILED(hr))
10342 {
10343 skip("Couldn't lock cloned vertex buffer.\n");
10344 goto cleanup;
10345 }
10346 for (j = 0; j < tc[i].num_vertices; j++)
10347 {
10348 UINT index = tc[i].exp_vertex_size * j;
10349 check_vertex_components(__LINE__, i, j, &vertices[index], &tc[i].exp_vertices[index], tc[i].new_declaration);
10350 }
10351 hr = mesh_clone->lpVtbl->UnlockVertexBuffer(mesh_clone);
10352 if (FAILED(hr))
10353 {
10354 skip("Couldn't unlock vertex buffer.\n");
10355 goto cleanup;
10356 }
10357 vertices = NULL;
10358 mesh->lpVtbl->Release(mesh);
10359 mesh = NULL;
10360 mesh_clone->lpVtbl->Release(mesh_clone);
10361 mesh_clone = NULL;
10362 }
10363
10364 /* The following test shows that it is not possible to share a vertex buffer
10365 * with D3DXMESH_VB_SHARE and change the vertex declaration at the same
10366 * time. It reuses the test data from test 2.
10367 */
10368 hr = init_test_mesh(tc[2].num_faces, tc[2].num_vertices,
10369 tc[2].create_options,
10370 tc[2].declaration,
10371 test_context->device, &mesh,
10372 tc[2].vertices, tc[2].vertex_size,
10373 tc[2].indices, tc[2].attributes);
10374 if (FAILED(hr))
10375 {
10376 skip("Couldn't initialize test mesh for D3DXMESH_VB_SHARE case."
10377 " Got %x expected D3D_OK\n", hr);
10378 goto cleanup;
10379 }
10380
10381 hr = mesh->lpVtbl->CloneMesh(mesh, tc[2].create_options | D3DXMESH_VB_SHARE,
10382 tc[2].new_declaration, test_context->device,
10383 &mesh_clone);
10384 ok(hr == D3DERR_INVALIDCALL, "CloneMesh D3DXMESH_VB_SHARE with new"
10385 " declaration. Got %x, expected D3DERR_INVALIDCALL\n",
10386 hr);
10387 mesh->lpVtbl->Release(mesh);
10388 mesh = NULL;
10389 mesh_clone = NULL;
10390
10391 cleanup:
10392 if (vertices) mesh->lpVtbl->UnlockVertexBuffer(mesh);
10393 if (mesh) mesh->lpVtbl->Release(mesh);
10394 if (mesh_clone) mesh_clone->lpVtbl->Release(mesh_clone);
10395 free_test_context(test_context);
10396 }
10397
test_valid_mesh(void)10398 static void test_valid_mesh(void)
10399 {
10400 HRESULT hr;
10401 struct test_context *test_context = NULL;
10402 UINT i;
10403 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
10404 const D3DVERTEXELEMENT9 declaration[] =
10405 {
10406 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
10407 D3DDECL_END()
10408 };
10409 const unsigned int VERTS_PER_FACE = 3;
10410 /* mesh0 (one face)
10411 *
10412 * 0--1
10413 * | /
10414 * |/
10415 * 2
10416 */
10417 const D3DXVECTOR3 vertices0[] =
10418 {
10419 { 0.0f, 3.0f, 0.f},
10420 { 2.0f, 3.0f, 0.f},
10421 { 0.0f, 0.0f, 0.f},
10422 };
10423 const DWORD indices0[] = {0, 1, 2};
10424 const unsigned int num_vertices0 = ARRAY_SIZE(vertices0);
10425 const unsigned int num_faces0 = ARRAY_SIZE(indices0) / VERTS_PER_FACE;
10426 const DWORD adjacency0[] = {-1, -1, -1};
10427 const HRESULT exp_hr0 = D3D_OK;
10428 /* mesh1 (Simple bow-tie)
10429 *
10430 * 0--1 1--3
10431 * | / \ |
10432 * |/ \|
10433 * 2 4
10434 */
10435 const D3DXVECTOR3 vertices1[] =
10436 {
10437 { 0.0f, 3.0f, 0.f},
10438 { 2.0f, 3.0f, 0.f},
10439 { 0.0f, 0.0f, 0.f},
10440
10441 { 4.0f, 3.0f, 0.f},
10442 { 4.0f, 0.0f, 0.f},
10443 };
10444 const DWORD indices1[] = {0, 1, 2, 1, 3, 4};
10445 const unsigned int num_vertices1 = ARRAY_SIZE(vertices1);
10446 const unsigned int num_faces1 = ARRAY_SIZE(indices1) / VERTS_PER_FACE;
10447 const DWORD adjacency1[] = {-1, -1, -1, -1, -1, -1};
10448 const HRESULT exp_hr1 = D3DXERR_INVALIDMESH;
10449 /* Common mesh data */
10450 ID3DXMesh *mesh = NULL;
10451 UINT vertex_size = sizeof(D3DXVECTOR3);
10452 ID3DXBuffer *errors_and_warnings = NULL;
10453 struct
10454 {
10455 const D3DXVECTOR3 *vertices;
10456 const DWORD *indices;
10457 const UINT num_vertices;
10458 const UINT num_faces;
10459 const DWORD *adjacency;
10460 const HRESULT exp_hr;
10461 }
10462 tc[] =
10463 {
10464 {
10465 vertices0,
10466 indices0,
10467 num_vertices0,
10468 num_faces0,
10469 adjacency0,
10470 exp_hr0,
10471 },
10472 {
10473 vertices1,
10474 indices1,
10475 num_vertices1,
10476 num_faces1,
10477 adjacency1,
10478 exp_hr1,
10479 },
10480 };
10481
10482 test_context = new_test_context();
10483 if (!test_context)
10484 {
10485 skip("Couldn't create test context\n");
10486 goto cleanup;
10487 }
10488
10489 for (i = 0; i < ARRAY_SIZE(tc); i++)
10490 {
10491 hr = init_test_mesh(tc[i].num_faces, tc[i].num_vertices,
10492 options, declaration,
10493 test_context->device, &mesh,
10494 tc[i].vertices, vertex_size,
10495 tc[i].indices, NULL);
10496 if (FAILED(hr))
10497 {
10498 skip("Couldn't initialize test mesh %d. Got %x expected D3D_OK\n", i, hr);
10499 goto cleanup;
10500 }
10501
10502 hr = D3DXValidMesh(mesh, tc[i].adjacency, &errors_and_warnings);
10503 todo_wine ok(hr == tc[i].exp_hr, "Test %u, got unexpected hr %#x, expected %#x.\n", i, hr, tc[i].exp_hr);
10504
10505 /* Note errors_and_warnings is deliberately not checked because that
10506 * would require copying wast amounts of the text output. */
10507 if (errors_and_warnings)
10508 {
10509 ID3DXBuffer_Release(errors_and_warnings);
10510 errors_and_warnings = NULL;
10511 }
10512 mesh->lpVtbl->Release(mesh);
10513 mesh = NULL;
10514 }
10515
10516 cleanup:
10517 if (mesh) mesh->lpVtbl->Release(mesh);
10518 free_test_context(test_context);
10519 }
10520
test_optimize_vertices(void)10521 static void test_optimize_vertices(void)
10522 {
10523 HRESULT hr;
10524 DWORD vertex_remap[3];
10525 const DWORD indices[] = {0, 1, 2};
10526 const UINT num_faces = 1;
10527 const UINT num_vertices = 3;
10528
10529 hr = D3DXOptimizeVertices(indices, num_faces,
10530 num_vertices, FALSE,
10531 vertex_remap);
10532 ok(hr == D3D_OK, "D3DXOptimizeVertices failed. Got %x, expected D3D_OK.\n", hr);
10533
10534 /* vertex_remap must not be NULL */
10535 hr = D3DXOptimizeVertices(indices, num_faces,
10536 num_vertices, FALSE,
10537 NULL);
10538 ok(hr == D3DERR_INVALIDCALL, "D3DXOptimizeVertices passed NULL vertex_remap "
10539 "pointer. Got %x, expected D3DERR_INVALIDCALL.\n", hr);
10540 }
10541
test_optimize_faces(void)10542 static void test_optimize_faces(void)
10543 {
10544 HRESULT hr;
10545 UINT i;
10546 DWORD smallest_face_remap;
10547 /* mesh0
10548 *
10549 * 0--1
10550 * | /
10551 * |/
10552 * 2
10553 */
10554 const DWORD indices0[] = {0, 1, 2};
10555 const UINT num_faces0 = 1;
10556 const UINT num_vertices0 = 3;
10557 const DWORD exp_face_remap0[] = {0};
10558 /* mesh1
10559 *
10560 * 0--1 3
10561 * | / /|
10562 * |/ / |
10563 * 2 5--4
10564 */
10565 const DWORD indices1[] = {0, 1, 2, 3, 4, 5};
10566 const UINT num_faces1 = 2;
10567 const UINT num_vertices1 = 6;
10568 const DWORD exp_face_remap1[] = {1, 0};
10569 /* mesh2
10570 *
10571 * 0--1
10572 * | /|
10573 * |/ |
10574 * 2--3
10575 */
10576 const DWORD indices2[] = {0, 1, 2, 1, 3, 2};
10577 const UINT num_faces2 = 2;
10578 const UINT num_vertices2 = 4;
10579 const DWORD exp_face_remap2[] = {1, 0};
10580 /* mesh3
10581 *
10582 * 0--1
10583 * | /|
10584 * |/ |
10585 * 2--3
10586 * | /|
10587 * |/ |
10588 * 4--5
10589 */
10590 const DWORD indices3[] = {0, 1, 2, 1, 3, 2, 2, 3, 4, 3, 4, 5};
10591 const UINT num_faces3 = 4;
10592 const UINT num_vertices3 = 6;
10593 const DWORD exp_face_remap3[] = {3, 2, 1, 0};
10594 /* mesh4
10595 *
10596 * 0--1
10597 * | /|
10598 * |/ |
10599 * 2--3
10600 * | /|
10601 * |/ |
10602 * 4--5
10603 */
10604 const WORD indices4[] = {0, 1, 2, 1, 3, 2, 2, 3, 4, 3, 4, 5};
10605 const UINT num_faces4 = 4;
10606 const UINT num_vertices4 = 6;
10607 const DWORD exp_face_remap4[] = {3, 2, 1, 0};
10608 /* Test cases are stored in the tc array */
10609 struct
10610 {
10611 const VOID *indices;
10612 const UINT num_faces;
10613 const UINT num_vertices;
10614 const BOOL indices_are_32bit;
10615 const DWORD *exp_face_remap;
10616 }
10617 tc[] =
10618 {
10619 {
10620 indices0,
10621 num_faces0,
10622 num_vertices0,
10623 TRUE,
10624 exp_face_remap0
10625 },
10626 {
10627 indices1,
10628 num_faces1,
10629 num_vertices1,
10630 TRUE,
10631 exp_face_remap1
10632 },
10633 {
10634 indices2,
10635 num_faces2,
10636 num_vertices2,
10637 TRUE,
10638 exp_face_remap2
10639 },
10640 {
10641 indices3,
10642 num_faces3,
10643 num_vertices3,
10644 TRUE,
10645 exp_face_remap3
10646 },
10647 {
10648 indices4,
10649 num_faces4,
10650 num_vertices4,
10651 FALSE,
10652 exp_face_remap4
10653 },
10654 };
10655
10656 /* Go through all test cases */
10657 for (i = 0; i < ARRAY_SIZE(tc); i++)
10658 {
10659 DWORD j;
10660 DWORD *face_remap;
10661 face_remap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
10662 tc[i].num_faces*sizeof(*face_remap));
10663
10664 hr = D3DXOptimizeFaces(tc[i].indices, tc[i].num_faces,
10665 tc[i].num_vertices, tc[i].indices_are_32bit,
10666 face_remap);
10667 ok(hr == D3D_OK, "Test %u, got unexpected hr %#x.\n", i, hr);
10668
10669 /* Compare face remap with expected face remap */
10670 for (j = 0; j < tc[i].num_faces; j++)
10671 {
10672 ok(tc[i].exp_face_remap[j] == face_remap[j],
10673 "Test case %d: Got face %d at %d, expected %d\n", i,
10674 face_remap[j], j, tc[i].exp_face_remap[j]);
10675 }
10676
10677 HeapFree(GetProcessHeap(), 0, face_remap);
10678 }
10679
10680 /* face_remap must not be NULL */
10681 hr = D3DXOptimizeFaces(tc[0].indices, tc[0].num_faces,
10682 tc[0].num_vertices, tc[0].indices_are_32bit,
10683 NULL);
10684 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
10685
10686 /* Number of faces must be smaller than 2^15 */
10687 hr = D3DXOptimizeFaces(tc[0].indices, 2 << 15,
10688 tc[0].num_vertices, FALSE,
10689 &smallest_face_remap);
10690 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
10691 }
10692
clear_normals(ID3DXMesh * mesh)10693 static HRESULT clear_normals(ID3DXMesh *mesh)
10694 {
10695 HRESULT hr;
10696 BYTE *vertices;
10697 size_t normal_size;
10698 DWORD i, num_vertices, vertex_stride;
10699 const D3DXVECTOR4 normal = {NAN, NAN, NAN, NAN};
10700 D3DVERTEXELEMENT9 *normal_declaration = NULL;
10701 D3DVERTEXELEMENT9 declaration[MAX_FVF_DECL_SIZE] = {D3DDECL_END()};
10702
10703 if (FAILED(hr = mesh->lpVtbl->GetDeclaration(mesh, declaration)))
10704 return hr;
10705
10706 for (i = 0; declaration[i].Stream != 0xff; i++)
10707 {
10708 if (declaration[i].Usage == D3DDECLUSAGE_NORMAL && !declaration[i].UsageIndex)
10709 {
10710 normal_declaration = &declaration[i];
10711 break;
10712 }
10713 }
10714
10715 if (!normal_declaration)
10716 return D3DERR_INVALIDCALL;
10717
10718 if (normal_declaration->Type == D3DDECLTYPE_FLOAT3)
10719 {
10720 normal_size = sizeof(D3DXVECTOR3);
10721 }
10722 else if (normal_declaration->Type == D3DDECLTYPE_FLOAT4)
10723 {
10724 normal_size = sizeof(D3DXVECTOR4);
10725 }
10726 else
10727 {
10728 trace("Cannot clear normals\n");
10729 return E_NOTIMPL;
10730 }
10731
10732 num_vertices = mesh->lpVtbl->GetNumVertices(mesh);
10733 vertex_stride = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
10734
10735 if (FAILED(hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, (void **)&vertices)))
10736 return hr;
10737
10738 vertices += normal_declaration->Offset;
10739
10740 for (i = 0; i < num_vertices; i++, vertices += vertex_stride)
10741 memcpy(vertices, &normal, normal_size);
10742
10743 return mesh->lpVtbl->UnlockVertexBuffer(mesh);
10744 }
10745
compare_normals(unsigned int line,const char * test_name,ID3DXMesh * mesh,const D3DXVECTOR3 * normals,unsigned int num_normals)10746 static void compare_normals(unsigned int line, const char *test_name,
10747 ID3DXMesh *mesh, const D3DXVECTOR3 *normals, unsigned int num_normals)
10748 {
10749 unsigned int i;
10750 BYTE *vertices;
10751 DWORD num_vertices, vertex_stride;
10752 D3DVERTEXELEMENT9 *normal_declaration = NULL;
10753 D3DVERTEXELEMENT9 declaration[MAX_FVF_DECL_SIZE] = {D3DDECL_END()};
10754
10755 if (FAILED(mesh->lpVtbl->GetDeclaration(mesh, declaration)))
10756 {
10757 ok_(__FILE__, line)(0, "%s: Failed to get declaration\n", test_name);
10758 return;
10759 }
10760
10761 for (i = 0; declaration[i].Stream != 0xff; i++)
10762 {
10763 if (declaration[i].Usage == D3DDECLUSAGE_NORMAL && !declaration[i].UsageIndex)
10764 {
10765 normal_declaration = &declaration[i];
10766 break;
10767 }
10768 }
10769
10770 if (!normal_declaration)
10771 {
10772 ok_(__FILE__, line)(0, "%s: Mesh has no normals\n", test_name);
10773 return;
10774 }
10775
10776 if (normal_declaration->Type != D3DDECLTYPE_FLOAT3 && normal_declaration->Type != D3DDECLTYPE_FLOAT4)
10777 {
10778 ok_(__FILE__, line)(0, "%s: Mesh has invalid normals type\n", test_name);
10779 return;
10780 }
10781
10782 num_vertices = mesh->lpVtbl->GetNumVertices(mesh);
10783 vertex_stride = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
10784
10785 ok_(__FILE__, line)(num_vertices == num_normals, "%s: Expected %u vertices, got %u\n", test_name,
10786 num_normals, num_vertices);
10787
10788 if (FAILED(mesh->lpVtbl->LockVertexBuffer(mesh, 0, (void **)&vertices)))
10789 {
10790 ok_(__FILE__, line)(0, "%s: Failed to compare normals\n", test_name);
10791 return;
10792 }
10793
10794 vertices += normal_declaration->Offset;
10795
10796 for (i = 0; i < min(num_vertices, num_normals); i++, vertices += vertex_stride)
10797 {
10798 if (normal_declaration->Type == D3DDECLTYPE_FLOAT3)
10799 {
10800 const D3DXVECTOR3 *n = (D3DXVECTOR3 *)vertices;
10801 ok_(__FILE__, line)(compare_vec3(*n, normals[i]),
10802 "%s: normal %2u, expected (%f, %f, %f), got (%f, %f, %f)\n",
10803 test_name, i, normals[i].x, normals[i].y, normals[i].z, n->x, n->y, n->z);
10804 }
10805 else
10806 {
10807 const D3DXVECTOR4 *n = (D3DXVECTOR4 *)vertices;
10808 const D3DXVECTOR4 normal = {normals[i].x, normals[i].y, normals[i].z, 1.0f};
10809 ok_(__FILE__, line)(compare_vec4(*n, normal),
10810 "%s: normal %2u, expected (%f, %f, %f, %f), got (%f, %f, %f, %f)\n",
10811 test_name, i, normals[i].x, normals[i].y, normals[i].z, 1.0f,
10812 n->x, n->y, n->z, n->w);
10813 }
10814 }
10815
10816 mesh->lpVtbl->UnlockVertexBuffer(mesh);
10817 }
10818
compute_normals_D3DXComputeNormals(ID3DXMesh * mesh,const DWORD * adjacency)10819 static HRESULT compute_normals_D3DXComputeNormals(ID3DXMesh *mesh, const DWORD *adjacency)
10820 {
10821 return D3DXComputeNormals((ID3DXBaseMesh *)mesh, adjacency);
10822 }
10823
compute_normals_D3DXComputeTangentFrameEx(ID3DXMesh * mesh,const DWORD * adjacency)10824 static HRESULT compute_normals_D3DXComputeTangentFrameEx(ID3DXMesh *mesh, const DWORD *adjacency)
10825 {
10826 return D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
10827 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS,
10828 adjacency, -1.01f, -0.01f, -1.01f, NULL, NULL);
10829 }
10830
test_compute_normals(void)10831 static void test_compute_normals(void)
10832 {
10833 HRESULT hr;
10834 ULONG refcount;
10835 ID3DXMesh *mesh, *cloned_mesh;
10836 ID3DXBuffer *adjacency;
10837 IDirect3DDevice9 *device;
10838 struct test_context *test_context;
10839 unsigned int i;
10840
10841 static const struct compute_normals_func
10842 {
10843 const char *name;
10844 HRESULT (*apply)(ID3DXMesh *mesh, const DWORD *adjacency);
10845 }
10846 compute_normals_funcs[] =
10847 {
10848 {"D3DXComputeNormals", compute_normals_D3DXComputeNormals },
10849 {"D3DXComputeTangentFrameEx", compute_normals_D3DXComputeTangentFrameEx}
10850 };
10851
10852 static const D3DXVECTOR3 box_normals[24] =
10853 {
10854 {-1.0f, 0.0f, 0.0f}, {-1.0f, 0.0f, 0.0f}, {-1.0f, 0.0f, 0.0f}, {-1.0f, 0.0f, 0.0f},
10855 { 0.0f, 1.0f, 0.0f}, { 0.0f, 1.0f, 0.0f}, { 0.0f, 1.0f, 0.0f}, { 0.0f, 1.0f, 0.0f},
10856 { 1.0f, 0.0f, 0.0f}, { 1.0f, 0.0f, 0.0f}, { 1.0f, 0.0f, 0.0f}, { 1.0f, 0.0f, 0.0f},
10857 { 0.0f,-1.0f, 0.0f}, { 0.0f,-1.0f, 0.0f}, { 0.0f,-1.0f, 0.0f}, { 0.0f,-1.0f, 0.0f},
10858 { 0.0f, 0.0f, 1.0f}, { 0.0f, 0.0f, 1.0f}, { 0.0f, 0.0f, 1.0f}, { 0.0f, 0.0f, 1.0f},
10859 { 0.0f, 0.0f,-1.0f}, { 0.0f, 0.0f,-1.0f}, { 0.0f, 0.0f,-1.0f}, { 0.0f, 0.0f,-1.0f}
10860 };
10861 const float box_normal_component = 1.0f / sqrtf(3.0f);
10862 const D3DXVECTOR3 box_normals_adjacency[24] =
10863 {
10864 {-box_normal_component, -box_normal_component, -box_normal_component},
10865 {-box_normal_component, -box_normal_component, box_normal_component},
10866 {-box_normal_component, box_normal_component, box_normal_component},
10867 {-box_normal_component, box_normal_component, -box_normal_component},
10868 {-box_normal_component, box_normal_component, -box_normal_component},
10869 {-box_normal_component, box_normal_component, box_normal_component},
10870 { box_normal_component, box_normal_component, box_normal_component},
10871 { box_normal_component, box_normal_component, -box_normal_component},
10872 { box_normal_component, box_normal_component, -box_normal_component},
10873 { box_normal_component, box_normal_component, box_normal_component},
10874 { box_normal_component, -box_normal_component, box_normal_component},
10875 { box_normal_component, -box_normal_component, -box_normal_component},
10876 {-box_normal_component, -box_normal_component, box_normal_component},
10877 {-box_normal_component, -box_normal_component, -box_normal_component},
10878 { box_normal_component, -box_normal_component, -box_normal_component},
10879 { box_normal_component, -box_normal_component, box_normal_component},
10880 {-box_normal_component, -box_normal_component, box_normal_component},
10881 { box_normal_component, -box_normal_component, box_normal_component},
10882 { box_normal_component, box_normal_component, box_normal_component},
10883 {-box_normal_component, box_normal_component, box_normal_component},
10884 {-box_normal_component, -box_normal_component, -box_normal_component},
10885 {-box_normal_component, box_normal_component, -box_normal_component},
10886 { box_normal_component, box_normal_component, -box_normal_component},
10887 { box_normal_component, -box_normal_component, -box_normal_component}
10888 };
10889 static const D3DXVECTOR3 box_normals_adjacency_area[24] =
10890 {
10891 {-0.666667f, -0.333333f, -0.666667f}, {-0.333333f, -0.666667f, 0.666667f},
10892 {-0.816496f, 0.408248f, 0.408248f}, {-0.408248f, 0.816496f, -0.408248f},
10893 {-0.408248f, 0.816496f, -0.408248f}, {-0.816496f, 0.408248f, 0.408248f},
10894 { 0.333333f, 0.666667f, 0.666667f}, { 0.666667f, 0.333333f, -0.666667f},
10895 { 0.666667f, 0.333333f, -0.666667f}, { 0.333333f, 0.666667f, 0.666667f},
10896 { 0.816496f, -0.408248f, 0.408248f}, { 0.408248f, -0.816496f, -0.408248f},
10897 {-0.333333f, -0.666667f, 0.666667f}, {-0.666667f, -0.333333f, -0.666667f},
10898 { 0.408248f, -0.816496f, -0.408248f}, { 0.816496f, -0.408248f, 0.408248f},
10899 {-0.333333f, -0.666667f, 0.666667f}, { 0.816497f, -0.408248f, 0.408248f},
10900 { 0.333333f, 0.666667f, 0.666667f}, {-0.816497f, 0.408248f, 0.408248f},
10901 {-0.666667f, -0.333333f, -0.666667f}, {-0.408248f, 0.816497f, -0.408248f},
10902 { 0.666667f, 0.333333f, -0.666667f}, { 0.408248f, -0.816496f, -0.408248f}
10903 };
10904 static const D3DXVECTOR3 box_normals_position1f[24] = {{0}};
10905 static const D3DXVECTOR3 box_normals_position2f[24] =
10906 {
10907 {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f},
10908 {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, 1.0f},
10909 {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, -1.0f},
10910 {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f},
10911 {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, -1.0f},
10912 {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f},
10913 {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f},
10914 {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, -1.0f}
10915 };
10916
10917 static const D3DXVECTOR3 sphere_normals[22] =
10918 {
10919 { 0.000000f, -0.000000f, 1.000000f}, { 0.000000f, 0.582244f, 0.813014f},
10920 { 0.582244f, -0.000000f, 0.813014f}, {-0.000000f, -0.582244f, 0.813014f},
10921 {-0.582244f, 0.000000f, 0.813014f}, {-0.000000f, 0.890608f, 0.454772f},
10922 { 0.890608f, 0.000000f, 0.454772f}, { 0.000000f, -0.890608f, 0.454772f},
10923 {-0.890608f, -0.000000f, 0.454772f}, { 0.000000f, 1.000000f, -0.000000f},
10924 { 1.000000f, -0.000000f, -0.000000f}, {-0.000000f, -1.000000f, -0.000000f},
10925 {-1.000000f, 0.000000f, -0.000000f}, { 0.000000f, 0.890608f, -0.454773f},
10926 { 0.890608f, -0.000000f, -0.454772f}, {-0.000000f, -0.890608f, -0.454773f},
10927 {-0.890608f, 0.000000f, -0.454773f}, { 0.000000f, 0.582244f, -0.813015f},
10928 { 0.582244f, -0.000000f, -0.813015f}, { 0.000000f, -0.582244f, -0.813015f},
10929 {-0.582243f, 0.000000f, -0.813015f}, { 0.000000f, 0.000000f, -1.000000f}
10930 };
10931 static const D3DXVECTOR3 sphere_normals_area[22] =
10932 {
10933 { 0.000000f, -0.000000f, 1.000000f}, {-0.215311f, 0.554931f, 0.803550f},
10934 { 0.554931f, 0.215311f, 0.803550f}, { 0.215311f, -0.554931f, 0.803550f},
10935 {-0.554931f, -0.215311f, 0.803550f}, {-0.126638f, 0.872121f, 0.472618f},
10936 { 0.872121f, 0.126638f, 0.472618f}, { 0.126638f, -0.872121f, 0.472618f},
10937 {-0.872121f, -0.126637f, 0.472618f}, { 0.000000f, 1.000000f, -0.000000f},
10938 { 1.000000f, -0.000000f, -0.000000f}, {-0.000000f, -1.000000f, -0.000000f},
10939 {-1.000000f, 0.000000f, -0.000000f}, { 0.126638f, 0.872121f, -0.472618f},
10940 { 0.872121f, -0.126638f, -0.472618f}, {-0.126638f, -0.872121f, -0.472618f},
10941 {-0.872121f, 0.126638f, -0.472618f}, { 0.215311f, 0.554931f, -0.803550f},
10942 { 0.554931f, -0.215311f, -0.803550f}, {-0.215311f, -0.554931f, -0.803550f},
10943 {-0.554931f, 0.215311f, -0.803550f}, { 0.000000f, 0.000000f, -1.000000f}
10944 };
10945 static const D3DXVECTOR3 sphere_normals_equal[22] =
10946 {
10947 { 0.000000f, -0.000000f, 1.000000f}, {-0.134974f, 0.522078f, 0.842150f},
10948 { 0.522078f, 0.134974f, 0.842150f}, { 0.134974f, -0.522078f, 0.842150f},
10949 {-0.522078f, -0.134974f, 0.842150f}, {-0.026367f, 0.857121f, 0.514440f},
10950 { 0.857121f, 0.026367f, 0.514440f}, { 0.026367f, -0.857121f, 0.514440f},
10951 {-0.857121f, -0.026367f, 0.514440f}, { 0.000000f, 1.000000f, -0.000000f},
10952 { 1.000000f, -0.000000f, -0.000000f}, {-0.000000f, -1.000000f, -0.000000f},
10953 {-1.000000f, 0.000000f, -0.000000f}, { 0.026367f, 0.857121f, -0.514440f},
10954 { 0.857121f, -0.026367f, -0.514440f}, {-0.026367f, -0.857121f, -0.514440f},
10955 {-0.857121f, 0.026367f, -0.514440f}, { 0.134975f, 0.522078f, -0.842150f},
10956 { 0.522078f, -0.134975f, -0.842150f}, {-0.134974f, -0.522078f, -0.842150f},
10957 {-0.522078f, 0.134974f, -0.842150f}, { 0.000000f, 0.000000f, -1.000000f}
10958 };
10959
10960 static const D3DVERTEXELEMENT9 position3f_normal1f_declaration[] =
10961 {
10962 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
10963 {0, sizeof(D3DXVECTOR3), D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
10964 D3DDECL_END()
10965 };
10966 static const D3DVERTEXELEMENT9 position3f_normal2f_declaration[] =
10967 {
10968 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
10969 {0, sizeof(D3DXVECTOR3), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
10970 D3DDECL_END()
10971 };
10972 static const D3DVERTEXELEMENT9 normal4f_position3f_declaration[] =
10973 {
10974 {0, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
10975 {0, sizeof(D3DXVECTOR4), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
10976 D3DDECL_END()
10977 };
10978 static const D3DVERTEXELEMENT9 position1f_normal3f_declaration[] =
10979 {
10980 {0, 0, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
10981 {0, sizeof(float), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
10982 D3DDECL_END()
10983 };
10984 static const D3DVERTEXELEMENT9 position2f_normal3f_declaration[] =
10985 {
10986 {0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
10987 {0, sizeof(D3DXVECTOR2), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
10988 D3DDECL_END()
10989 };
10990 static const D3DVERTEXELEMENT9 position4f_normal3f_declaration[] =
10991 {
10992 {0, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
10993 {0, sizeof(D3DXVECTOR4), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
10994 D3DDECL_END()
10995 };
10996
10997 for (i = 0; i < ARRAY_SIZE(compute_normals_funcs); i++)
10998 {
10999 hr = compute_normals_funcs[i].apply(NULL, NULL);
11000 ok(hr == D3DERR_INVALIDCALL, "%s returned %#x, expected D3DERR_INVALIDCALL\n", compute_normals_funcs[i].name, hr);
11001 }
11002
11003 if (!(test_context = new_test_context()))
11004 {
11005 skip("Couldn't create test context\n");
11006 return;
11007 }
11008 device = test_context->device;
11009
11010 hr = D3DXCreateBox(device, 1.0f, 1.0f, 1.0f, &mesh, &adjacency);
11011 ok(SUCCEEDED(hr), "D3DXCreateBox failed %#x\n", hr);
11012
11013 /* Check wrong input */
11014 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
11015 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE, NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
11016 todo_wine ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr);
11017
11018 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DDECLUSAGE_NORMAL, 0,
11019 D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_BY_AREA | D3DXTANGENT_WEIGHT_EQUAL,
11020 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
11021 ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr);
11022
11023 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
11024 D3DDECLUSAGE_NORMAL, 0, 0, NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
11025 todo_wine ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr);
11026
11027 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
11028 D3DDECLUSAGE_NORMAL, 1, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS,
11029 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
11030 ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr);
11031
11032 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
11033 D3DX_DEFAULT, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS,
11034 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
11035 ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr);
11036
11037 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
11038 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_CALCULATE_NORMALS,
11039 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
11040 todo_wine ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr);
11041
11042 for (i = 0; i < ARRAY_SIZE(compute_normals_funcs); i++)
11043 {
11044 const struct compute_normals_func *func = &compute_normals_funcs[i];
11045
11046 /* Mesh without normals */
11047 hr = mesh->lpVtbl->CloneMeshFVF(mesh, 0, D3DFVF_XYZ, device, &cloned_mesh);
11048 ok(SUCCEEDED(hr), "CloneMeshFVF failed %#x\n", hr);
11049
11050 hr = func->apply(cloned_mesh, NULL);
11051 ok(hr == D3DERR_INVALIDCALL, "%s returned %#x, expected D3DERR_INVALIDCALL\n", func->name, hr);
11052
11053 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh);
11054 ok(!refcount, "Mesh has %u references left\n", refcount);
11055
11056 /* Mesh without positions */
11057 hr = mesh->lpVtbl->CloneMeshFVF(mesh, 0, D3DFVF_NORMAL, device, &cloned_mesh);
11058 ok(SUCCEEDED(hr), "CloneMeshFVF failed %#x\n", hr);
11059
11060 hr = func->apply(cloned_mesh, NULL);
11061 ok(hr == D3DERR_INVALIDCALL, "%s returned %#x, expected D3DERR_INVALIDCALL\n", func->name, hr);
11062
11063 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh);
11064 ok(!refcount, "Mesh has %u references left\n", refcount);
11065
11066 /* Mesh with D3DDECLTYPE_FLOAT1 normals */
11067 hr = mesh->lpVtbl->CloneMesh(mesh, 0, position3f_normal1f_declaration, device, &cloned_mesh);
11068 ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr);
11069
11070 hr = func->apply(cloned_mesh, NULL);
11071 ok(hr == D3DERR_INVALIDCALL, "%s returned %#x, expected D3DERR_INVALIDCALL\n", func->name, hr);
11072
11073 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh);
11074 ok(!refcount, "Mesh has %u references left\n", refcount);
11075
11076 /* Mesh with D3DDECLTYPE_FLOAT2 normals */
11077 hr = mesh->lpVtbl->CloneMesh(mesh, 0, position3f_normal2f_declaration, device, &cloned_mesh);
11078 ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr);
11079
11080 hr = func->apply(cloned_mesh, NULL);
11081 ok(hr == D3DERR_INVALIDCALL, "%s returned %#x, expected D3DERR_INVALIDCALL\n", func->name, hr);
11082
11083 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh);
11084 ok(!refcount, "Mesh has %u references left\n", refcount);
11085
11086 /* Mesh without adjacency data */
11087 hr = clear_normals(mesh);
11088 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr);
11089
11090 hr = func->apply(mesh, NULL);
11091 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr);
11092
11093 compare_normals(__LINE__, func->name, mesh, box_normals, ARRAY_SIZE(box_normals));
11094
11095 /* Mesh with adjacency data */
11096 hr = clear_normals(mesh);
11097 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr);
11098
11099 hr = func->apply(mesh, ID3DXBuffer_GetBufferPointer(adjacency));
11100 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr);
11101
11102 compare_normals(__LINE__, func->name, mesh, box_normals_adjacency, ARRAY_SIZE(box_normals_adjacency));
11103
11104 /* Mesh with custom vertex format, D3DDECLTYPE_FLOAT4 normals and adjacency */
11105 hr = mesh->lpVtbl->CloneMesh(mesh, 0, normal4f_position3f_declaration, device, &cloned_mesh);
11106 ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr);
11107
11108 hr = clear_normals(cloned_mesh);
11109 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr);
11110
11111 hr = func->apply(cloned_mesh, ID3DXBuffer_GetBufferPointer(adjacency));
11112 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr);
11113
11114 compare_normals(__LINE__, func->name, cloned_mesh, box_normals_adjacency, ARRAY_SIZE(box_normals_adjacency));
11115
11116 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh);
11117 ok(!refcount, "Mesh has %u references left\n", refcount);
11118
11119 /* Mesh with D3DDECLTYPE_FLOAT1 positions and D3DDECLTYPE_FLOAT3 normals */
11120 hr = mesh->lpVtbl->CloneMesh(mesh, 0, position1f_normal3f_declaration, device, &cloned_mesh);
11121 ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr);
11122
11123 hr = clear_normals(cloned_mesh);
11124 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr);
11125
11126 hr = func->apply(cloned_mesh, ID3DXBuffer_GetBufferPointer(adjacency));
11127 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr);
11128
11129 compare_normals(__LINE__, func->name, cloned_mesh, box_normals_position1f, ARRAY_SIZE(box_normals_position1f));
11130
11131 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh);
11132 ok(!refcount, "Mesh has %u references left\n", refcount);
11133
11134 /* Mesh with D3DDECLTYPE_FLOAT2 positions and D3DDECLTYPE_FLOAT3 normals */
11135 hr = mesh->lpVtbl->CloneMesh(mesh, 0, position2f_normal3f_declaration, device, &cloned_mesh);
11136 ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr);
11137
11138 hr = clear_normals(cloned_mesh);
11139 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr);
11140
11141 hr = func->apply(cloned_mesh, ID3DXBuffer_GetBufferPointer(adjacency));
11142 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr);
11143
11144 compare_normals(__LINE__, func->name, cloned_mesh, box_normals_position2f, ARRAY_SIZE(box_normals_position2f));
11145
11146 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh);
11147 ok(!refcount, "Mesh has %u references left\n", refcount);
11148
11149 /* Mesh with D3DDECLTYPE_FLOAT4 positions and D3DDECLTYPE_FLOAT3 normals */
11150 hr = mesh->lpVtbl->CloneMesh(mesh, 0, position4f_normal3f_declaration, device, &cloned_mesh);
11151 ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr);
11152
11153 hr = clear_normals(cloned_mesh);
11154 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr);
11155
11156 hr = func->apply(cloned_mesh, ID3DXBuffer_GetBufferPointer(adjacency));
11157 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr);
11158
11159 compare_normals(__LINE__, func->name, cloned_mesh, box_normals_adjacency, ARRAY_SIZE(box_normals_adjacency));
11160
11161 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh);
11162 ok(!refcount, "Mesh has %u references left\n", refcount);
11163 }
11164
11165 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
11166 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_BY_AREA,
11167 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
11168 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr);
11169
11170 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, box_normals, ARRAY_SIZE(box_normals));
11171
11172 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
11173 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_BY_AREA,
11174 ID3DXBuffer_GetBufferPointer(adjacency), -1.01f, -0.01f, -1.01f, NULL, NULL);
11175 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr);
11176
11177 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, box_normals_adjacency_area, ARRAY_SIZE(box_normals_adjacency_area));
11178
11179 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
11180 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_EQUAL,
11181 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
11182 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr);
11183
11184 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, box_normals, ARRAY_SIZE(box_normals));
11185
11186 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
11187 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_EQUAL,
11188 ID3DXBuffer_GetBufferPointer(adjacency), -1.01f, -0.01f, -1.01f, NULL, NULL);
11189 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr);
11190
11191 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, box_normals_adjacency_area, ARRAY_SIZE(box_normals_adjacency_area));
11192
11193 refcount = mesh->lpVtbl->Release(mesh);
11194 ok(!refcount, "Mesh has %u references left\n", refcount);
11195 refcount = ID3DXBuffer_Release(adjacency);
11196 ok(!refcount, "Buffer has %u references left\n", refcount);
11197
11198 hr = D3DXCreateSphere(device, 1.0f, 4, 6, &mesh, &adjacency);
11199 ok(SUCCEEDED(hr), "D3DXCreateSphere failed %#x\n", hr);
11200
11201 for (i = 0; i < ARRAY_SIZE(compute_normals_funcs); i++)
11202 {
11203 const struct compute_normals_func *func = &compute_normals_funcs[i];
11204
11205 /* Sphere without adjacency data */
11206 hr = clear_normals(mesh);
11207 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr);
11208
11209 hr = func->apply(mesh, NULL);
11210 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr);
11211
11212 compare_normals(__LINE__, func->name, mesh, sphere_normals, ARRAY_SIZE(sphere_normals));
11213
11214 /* Sphere with adjacency data */
11215 hr = clear_normals(mesh);
11216 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr);
11217
11218 hr = func->apply(mesh, ID3DXBuffer_GetBufferPointer(adjacency));
11219 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr);
11220
11221 compare_normals(__LINE__, func->name, mesh, sphere_normals, ARRAY_SIZE(sphere_normals));
11222 }
11223
11224 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
11225 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_BY_AREA,
11226 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
11227 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr);
11228
11229 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, sphere_normals_area, ARRAY_SIZE(sphere_normals_area));
11230
11231 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
11232 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_BY_AREA,
11233 ID3DXBuffer_GetBufferPointer(adjacency), -1.01f, -0.01f, -1.01f, NULL, NULL);
11234 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr);
11235
11236 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, sphere_normals_area, ARRAY_SIZE(sphere_normals_area));
11237
11238 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
11239 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_EQUAL,
11240 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
11241 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr);
11242
11243 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, sphere_normals_equal, ARRAY_SIZE(sphere_normals_equal));
11244
11245 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
11246 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_EQUAL,
11247 ID3DXBuffer_GetBufferPointer(adjacency), -1.01f, -0.01f, -1.01f, NULL, NULL);
11248 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr);
11249
11250 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, sphere_normals_equal, ARRAY_SIZE(sphere_normals_equal));
11251
11252 refcount = mesh->lpVtbl->Release(mesh);
11253 ok(!refcount, "Mesh has %u references left\n", refcount);
11254 refcount = ID3DXBuffer_Release(adjacency);
11255 ok(!refcount, "Buffer has %u references left\n", refcount);
11256
11257 free_test_context(test_context);
11258 }
11259
D3DXCreateAnimationControllerTest(void)11260 static void D3DXCreateAnimationControllerTest(void)
11261 {
11262 HRESULT hr;
11263 ID3DXAnimationController *animation;
11264 UINT value;
11265
11266 hr = D3DXCreateAnimationController(0, 0, 0, 0, NULL);
11267 ok(hr == D3D_OK, "Got unexpected hr returned %#x.\n", hr);
11268
11269 animation = (void*)0xdeadbeef;
11270 hr = D3DXCreateAnimationController(0, 1, 1, 1, &animation);
11271 ok(hr == D3D_OK, "Got unexpected hr returned %#x.\n", hr);
11272 ok(animation == (void*)0xdeadbeef, "Got unexpected animation %p.\n", animation);
11273
11274 animation = (void*)0xdeadbeef;
11275 hr = D3DXCreateAnimationController(1, 0, 1, 1, &animation);
11276 ok(hr == D3D_OK, "Got unexpected hr returned %#x.\n", hr);
11277 ok(animation == (void*)0xdeadbeef, "Got unexpected animation %p.\n", animation);
11278
11279 animation = (void*)0xdeadbeef;
11280 hr = D3DXCreateAnimationController(1, 1, 0, 1, &animation);
11281 ok(hr == D3D_OK, "Got unexpected hr returned %#x.\n", hr);
11282 ok(animation == (void*)0xdeadbeef, "Got unexpected animation %p.\n", animation);
11283
11284 animation = (void*)0xdeadbeef;
11285 hr = D3DXCreateAnimationController(1, 1, 1, 0, &animation);
11286 ok(hr == D3D_OK, "Got unexpected hr returned %#x.\n", hr);
11287 ok(animation == (void*)0xdeadbeef, "Got unexpected animation %p.\n", animation);
11288
11289 hr = D3DXCreateAnimationController(1, 1, 1, 1, &animation);
11290 ok(hr == D3D_OK, "Got unexpected hr returned %#x.\n", hr);
11291
11292 value = animation->lpVtbl->GetMaxNumAnimationOutputs(animation);
11293 ok(value == 1, "Got unexpected value %u.\n", value);
11294
11295 value = animation->lpVtbl->GetMaxNumAnimationSets(animation);
11296 ok(value == 1, "Got unexpected value %u.\n", value);
11297
11298 value = animation->lpVtbl->GetMaxNumTracks(animation);
11299 ok(value == 1, "Got unexpected value %u.\n", value);
11300
11301 value = animation->lpVtbl->GetMaxNumEvents(animation);
11302 ok(value == 1, "Got unexpected value %u.\n", value);
11303
11304 animation->lpVtbl->Release(animation);
11305
11306 hr = D3DXCreateAnimationController(100, 101, 102, 103, &animation);
11307 ok(hr == D3D_OK, "Got unexpected hr returned %#x.\n", hr);
11308
11309 value = animation->lpVtbl->GetMaxNumAnimationOutputs(animation);
11310 ok(value == 100, "Got unexpected value %u.\n", value);
11311
11312 value = animation->lpVtbl->GetMaxNumAnimationSets(animation);
11313 ok(value == 101, "Got unexpected value %u.\n", value);
11314
11315 value = animation->lpVtbl->GetMaxNumTracks(animation);
11316 ok(value == 102, "Got unexpected value %u.\n", value);
11317
11318 value = animation->lpVtbl->GetMaxNumEvents(animation);
11319 ok(value == 103, "Got unexpected value %u.\n", value);
11320
11321 animation->lpVtbl->Release(animation);
11322 }
11323
D3DXCreateKeyframedAnimationSetTest(void)11324 static void D3DXCreateKeyframedAnimationSetTest(void)
11325 {
11326 ID3DXKeyframedAnimationSet *set;
11327 D3DXPLAYBACK_TYPE type;
11328 unsigned int count;
11329 const char *name;
11330 HRESULT hr;
11331
11332 hr = D3DXCreateKeyframedAnimationSet("wine_bottle", 5.0, D3DXPLAY_LOOP, 0, 0, NULL, &set);
11333 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11334
11335 hr = D3DXCreateKeyframedAnimationSet("wine_bottle", 5.0, D3DXPLAY_LOOP, 10, 0, NULL, &set);
11336 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11337
11338 name = set->lpVtbl->GetName(set);
11339 ok(!strcmp(name, "wine_bottle"), "Got unexpected name %s.\n", debugstr_a(name));
11340
11341 type = set->lpVtbl->GetPlaybackType(set);
11342 ok(type == D3DXPLAY_LOOP, "Got unexpected value %u.\n", type);
11343
11344 count = set->lpVtbl->GetNumAnimations(set);
11345 ok(!count, "Got unexpected value %u.\n", count);
11346
11347 set->lpVtbl->Release(set);
11348 }
11349
test_D3DXFrameFind(void)11350 static void test_D3DXFrameFind(void)
11351 {
11352 static char n1[] = "name1";
11353 static char n2[] = "name2";
11354 static char n3[] = "name3";
11355 static char n4[] = "name4";
11356 static char n5[] = "name5";
11357 static char n6[] = "name6";
11358 static char N1[] = "Name1";
11359 D3DXFRAME root, sibling, sibling2, child, *ret;
11360 D3DXFRAME child2, child3;
11361
11362 ret = D3DXFrameFind(NULL, NULL);
11363 ok(ret == NULL, "Unexpected frame, %p.\n", ret);
11364
11365 ret = D3DXFrameFind(NULL, "test");
11366 ok(ret == NULL, "Unexpected frame, %p.\n", ret);
11367
11368 memset(&root, 0, sizeof(root));
11369
11370 ret = D3DXFrameFind(&root, NULL);
11371 ok(ret == &root, "Unexpected frame, %p.\n", ret);
11372
11373 root.Name = n1;
11374 ret = D3DXFrameFind(&root, NULL);
11375 ok(ret == NULL, "Unexpected frame, %p.\n", ret);
11376
11377 ret = D3DXFrameFind(&root, n1);
11378 ok(ret == &root, "Unexpected frame, %p.\n", ret);
11379
11380 ret = D3DXFrameFind(&root, N1);
11381 ok(ret == NULL, "Unexpected frame, %p.\n", ret);
11382
11383 /* Test siblings order traversal. */
11384 memset(&sibling, 0, sizeof(sibling));
11385 sibling.Name = n2;
11386 root.pFrameSibling = &sibling;
11387 ret = D3DXFrameFind(&root, n2);
11388 ok(ret == &sibling, "Unexpected frame, %p.\n", ret);
11389
11390 memset(&sibling2, 0, sizeof(sibling2));
11391 sibling2.Name = n2;
11392 sibling.pFrameSibling = &sibling2;
11393 ret = D3DXFrameFind(&root, n2);
11394 ok(ret == &sibling, "Unexpected frame, %p.\n", ret);
11395
11396 sibling2.Name = n3;
11397 ret = D3DXFrameFind(&root, n3);
11398 ok(ret == &sibling2, "Unexpected frame, %p.\n", ret);
11399
11400 /* Siblings first. */
11401 memset(&child, 0, sizeof(child));
11402 child.Name = n2;
11403 root.pFrameFirstChild = &child;
11404 ret = D3DXFrameFind(&root, n2);
11405 ok(ret == &sibling, "Unexpected frame, %p.\n", ret);
11406
11407 child.Name = n4;
11408 ret = D3DXFrameFind(&root, n4);
11409 ok(ret == &child, "Unexpected frame, %p.\n", ret);
11410
11411 /* Link a grandchild and another one for sibling. */
11412 memset(&child2, 0, sizeof(child2));
11413 memset(&child3, 0, sizeof(child3));
11414 child2.Name = child3.Name = n5;
11415 sibling.pFrameFirstChild = &child2;
11416 child.pFrameFirstChild = &child3;
11417 ret = D3DXFrameFind(&root, n5);
11418 ok(ret == &child2, "Unexpected frame, %p.\n", ret);
11419
11420 child3.Name = n6;
11421 ret = D3DXFrameFind(&root, n6);
11422 ok(ret == &child3, "Unexpected frame, %p.\n", ret);
11423 }
11424
get_mesh_data(const void * memory,SIZE_T length)11425 static ID3DXFileData *get_mesh_data(const void *memory, SIZE_T length)
11426 {
11427 ID3DXFileData *file_data, *ret = NULL;
11428 ID3DXFileEnumObject *enum_obj = NULL;
11429 D3DXF_FILELOADMEMORY source;
11430 ID3DXFile *file;
11431 SIZE_T i, count;
11432 GUID guid;
11433
11434 if (FAILED(D3DXFileCreate(&file)))
11435 return NULL;
11436
11437 if (FAILED(file->lpVtbl->RegisterTemplates(file, D3DRM_XTEMPLATES, D3DRM_XTEMPLATE_BYTES)))
11438 goto cleanup;
11439
11440 source.lpMemory = memory;
11441 source.dSize = length;
11442 if (FAILED(file->lpVtbl->CreateEnumObject(file, &source, D3DXF_FILELOAD_FROMMEMORY, &enum_obj)))
11443 goto cleanup;
11444
11445 if (FAILED(enum_obj->lpVtbl->GetChildren(enum_obj, &count)))
11446 goto cleanup;
11447
11448 for (i = 0; i < count; ++i)
11449 {
11450 if (FAILED(enum_obj->lpVtbl->GetChild(enum_obj, i, &file_data)))
11451 goto cleanup;
11452
11453 if (SUCCEEDED(file_data->lpVtbl->GetType(file_data, &guid))
11454 && IsEqualGUID(&guid, &TID_D3DRMMesh))
11455 {
11456 ret = file_data;
11457 break;
11458 }
11459 else
11460 {
11461 file_data->lpVtbl->Release(file_data);
11462 }
11463 }
11464
11465 cleanup:
11466 if (enum_obj)
11467 enum_obj->lpVtbl->Release(enum_obj);
11468 file->lpVtbl->Release(file);
11469
11470 return ret;
11471 }
11472
test_load_skin_mesh_from_xof(void)11473 static void test_load_skin_mesh_from_xof(void)
11474 {
11475 static const char simple_xfile[] =
11476 "xof 0303txt 0032"
11477 "Mesh {"
11478 "3;"
11479 "0.0; 0.0; 0.0;,"
11480 "0.0; 1.0; 0.0;,"
11481 "1.0; 1.0; 0.0;;"
11482 "1;"
11483 "3; 0, 1, 2;;"
11484 "}";
11485 static const D3DVERTEXELEMENT9 expected_declaration[] =
11486 {
11487 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
11488 D3DDECL_END(),
11489 };
11490 D3DVERTEXELEMENT9 declaration[MAX_FVF_DECL_SIZE];
11491 ID3DXBuffer *adjacency, *materials, *effects;
11492 DWORD max_influences[3], count, fvf;
11493 D3DPRESENT_PARAMETERS d3dpp;
11494 IDirect3DDevice9 *device;
11495 ID3DXSkinInfo *skin_info;
11496 ID3DXFileData *file_data;
11497 const char *bone_name;
11498 D3DXMATRIX *matrix;
11499 float influence;
11500 ID3DXMesh *mesh;
11501 IDirect3D9 *d3d;
11502 ULONG refcount;
11503 HRESULT hr;
11504 HWND hwnd;
11505
11506 if (!(hwnd = CreateWindowA("static", "d3dx9_test", WS_OVERLAPPEDWINDOW, 0, 0,
11507 640, 480, NULL, NULL, NULL, NULL)))
11508 {
11509 skip("Failed to create application window.\n");
11510 return;
11511 }
11512
11513 d3d = Direct3DCreate9(D3D_SDK_VERSION);
11514 if (!d3d)
11515 {
11516 skip("Failed to create d3d object.\n");
11517 DestroyWindow(hwnd);
11518 return;
11519 }
11520
11521 memset(&d3dpp, 0, sizeof(d3dpp));
11522 d3dpp.Windowed = TRUE;
11523 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
11524
11525 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
11526 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device);
11527 IDirect3D9_Release(d3d);
11528 if (FAILED(hr))
11529 {
11530 skip("Failed to create device, hr %#x.\n", hr);
11531 DestroyWindow(hwnd);
11532 return;
11533 }
11534
11535 file_data = get_mesh_data(simple_xfile, sizeof(simple_xfile) - 1);
11536 ok(!!file_data, "Failed to load mesh data.\n");
11537
11538 adjacency = materials = effects = (void *)0xdeadbeef;
11539 count = ~0u;
11540 skin_info = (void *)0xdeadbeef;
11541 mesh = (void *)0xdeadbeef;
11542
11543 hr = D3DXLoadSkinMeshFromXof(file_data, 0, device, &adjacency, &materials, &effects, &count,
11544 &skin_info, &mesh);
11545 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11546 ok(!!adjacency, "Got unexpected value %p.\n", adjacency);
11547 ok(!materials, "Got unexpected value %p.\n", materials);
11548 ok(!effects, "Got unexpected value %p.\n", effects);
11549 ok(!count, "Got unexpected value %u.\n", count);
11550 ok(!!skin_info, "Got unexpected value %p.\n", skin_info);
11551 ok(!!mesh, "Got unexpected value %p.\n", mesh);
11552 count = mesh->lpVtbl->GetNumVertices(mesh);
11553 ok(count == 3, "Got unexpected value %u.\n", count);
11554 count = mesh->lpVtbl->GetNumFaces(mesh);
11555 ok(count == 1, "Got unexpected value %u.\n", count);
11556
11557 hr = skin_info->lpVtbl->GetDeclaration(skin_info, declaration);
11558 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11559 compare_elements(declaration, expected_declaration, __LINE__, 0);
11560
11561 fvf = skin_info->lpVtbl->GetFVF(skin_info);
11562 ok(fvf == D3DFVF_XYZ, "Got unexpected value %u.\n", fvf);
11563
11564 count = skin_info->lpVtbl->GetNumBones(skin_info);
11565 ok(!count, "Got unexpected value %u.\n", count);
11566
11567 influence = skin_info->lpVtbl->GetMinBoneInfluence(skin_info);
11568 ok(!influence, "Got unexpected value %.8e.\n", influence);
11569
11570 memset(max_influences, 0x55, sizeof(max_influences));
11571 hr = skin_info->lpVtbl->GetMaxVertexInfluences(skin_info, max_influences);
11572 todo_wine ok(hr == D3D_OK, "Got unexpected value %#x.\n", hr);
11573 todo_wine ok(!max_influences[0], "Got unexpected value %u.\n", max_influences[0]);
11574 ok(max_influences[1] == 0x55555555, "Got unexpected value %u.\n", max_influences[1]);
11575 ok(max_influences[2] == 0x55555555, "Got unexpected value %u.\n", max_influences[2]);
11576
11577 bone_name = skin_info->lpVtbl->GetBoneName(skin_info, 0);
11578 ok(!bone_name, "Got unexpected value %p.\n", bone_name);
11579
11580 count = skin_info->lpVtbl->GetNumBoneInfluences(skin_info, 0);
11581 ok(!count, "Got unexpected value %u.\n", count);
11582
11583 count = skin_info->lpVtbl->GetNumBoneInfluences(skin_info, 1);
11584 ok(!count, "Got unexpected value %u.\n", count);
11585
11586 matrix = skin_info->lpVtbl->GetBoneOffsetMatrix(skin_info, -1);
11587 ok(!matrix, "Got unexpected value %p.\n", matrix);
11588
11589 matrix = skin_info->lpVtbl->GetBoneOffsetMatrix(skin_info, 0);
11590 ok(!matrix, "Got unexpected value %p.\n", matrix);
11591
11592 skin_info->lpVtbl->Release(skin_info);
11593 mesh->lpVtbl->Release(mesh);
11594 adjacency->lpVtbl->Release(adjacency);
11595 file_data->lpVtbl->Release(file_data);
11596 refcount = IDirect3DDevice9_Release(device);
11597 ok(!refcount, "Device has %u references left.\n", refcount);
11598 DestroyWindow(hwnd);
11599 }
11600
START_TEST(mesh)11601 START_TEST(mesh)
11602 {
11603 D3DXBoundProbeTest();
11604 D3DXComputeBoundingBoxTest();
11605 D3DXComputeBoundingSphereTest();
11606 D3DXGetFVFVertexSizeTest();
11607 D3DXIntersectTriTest();
11608 D3DXCreateMeshTest();
11609 D3DXCreateMeshFVFTest();
11610 D3DXLoadMeshTest();
11611 D3DXCreateBoxTest();
11612 D3DXCreatePolygonTest();
11613 D3DXCreateSphereTest();
11614 D3DXCreateCylinderTest();
11615 D3DXCreateTextTest();
11616 D3DXCreateTorusTest();
11617 D3DXCreateAnimationControllerTest();
11618 D3DXCreateKeyframedAnimationSetTest();
11619 test_get_decl_length();
11620 test_get_decl_vertex_size();
11621 test_fvf_decl_conversion();
11622 D3DXGenerateAdjacencyTest();
11623 test_update_semantics();
11624 test_create_skin_info();
11625 test_update_skinned_mesh();
11626 test_convert_adjacency_to_point_reps();
11627 test_convert_point_reps_to_adjacency();
11628 test_weld_vertices();
11629 test_clone_mesh();
11630 test_valid_mesh();
11631 test_optimize_vertices();
11632 test_optimize_faces();
11633 test_compute_normals();
11634 test_D3DXFrameFind();
11635 test_load_skin_mesh_from_xof();
11636 }
11637