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 */ 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 59 static BOOL compare(FLOAT u, FLOAT v) 60 { 61 return (fabs(u-v) < admitted_error); 62 } 63 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 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) 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 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 */ 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 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 209 static void free_mesh(struct mesh *mesh) 210 { 211 HeapFree(GetProcessHeap(), 0, mesh->faces); 212 HeapFree(GetProcessHeap(), 0, mesh->vertices); 213 } 214 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 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 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 439 rayposition.x = 5.0f; rayposition.y = 5.0f; rayposition.z = 9.0f; 440 result = D3DXSphereBoundProbe(¢er, radius, &rayposition, &raydirection); 441 ok(result == TRUE, "expected TRUE, received FALSE\n"); 442 443 rayposition.x = 45.0f; rayposition.y = -75.0f; rayposition.z = 49.0f; 444 result = D3DXSphereBoundProbe(¢er, radius, &rayposition, &raydirection); 445 ok(result == FALSE, "expected FALSE, received TRUE\n"); 446 447 rayposition.x = 5.0f; rayposition.y = 11.0f; rayposition.z = 9.0f; 448 result = D3DXSphereBoundProbe(¢er, radius, &rayposition, &raydirection); 449 ok(result == FALSE, "expected FALSE, received TRUE\n"); 450 } 451 452 static void D3DXComputeBoundingBoxTest(void) 453 { 454 D3DXVECTOR3 exp_max, exp_min, got_max, got_min, vertex[5]; 455 HRESULT hr; 456 457 vertex[0].x = 1.0f; vertex[0].y = 1.0f; vertex[0].z = 1.0f; 458 vertex[1].x = 1.0f; vertex[1].y = 1.0f; vertex[1].z = 1.0f; 459 vertex[2].x = 1.0f; vertex[2].y = 1.0f; vertex[2].z = 1.0f; 460 vertex[3].x = 1.0f; vertex[3].y = 1.0f; vertex[3].z = 1.0f; 461 vertex[4].x = 9.0f; vertex[4].y = 9.0f; vertex[4].z = 9.0f; 462 463 exp_min.x = 1.0f; exp_min.y = 1.0f; exp_min.z = 1.0f; 464 exp_max.x = 9.0f; exp_max.y = 9.0f; exp_max.z = 9.0f; 465 466 hr = D3DXComputeBoundingBox(&vertex[3],2,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_min,&got_max); 467 468 ok( hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 469 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); 470 ok( compare_vec3(exp_max,got_max), "Expected max: (%f, %f, %f), got: (%f, %f, %f)\n", exp_max.x,exp_max.y,exp_max.z,got_max.x,got_max.y,got_max.z); 471 472 /*________________________*/ 473 474 vertex[0].x = 2.0f; vertex[0].y = 5.9f; vertex[0].z = -1.2f; 475 vertex[1].x = -1.87f; vertex[1].y = 7.9f; vertex[1].z = 7.4f; 476 vertex[2].x = 7.43f; vertex[2].y = -0.9f; vertex[2].z = 11.9f; 477 vertex[3].x = -6.92f; vertex[3].y = 6.3f; vertex[3].z = -3.8f; 478 vertex[4].x = 11.4f; vertex[4].y = -8.1f; vertex[4].z = 4.5f; 479 480 exp_min.x = -6.92f; exp_min.y = -8.1f; exp_min.z = -3.80f; 481 exp_max.x = 11.4f; exp_max.y = 7.90f; exp_max.z = 11.9f; 482 483 hr = D3DXComputeBoundingBox(&vertex[0],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_min,&got_max); 484 485 ok( hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 486 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); 487 ok( compare_vec3(exp_max,got_max), "Expected max: (%f, %f, %f), got: (%f, %f, %f)\n", exp_max.x,exp_max.y,exp_max.z,got_max.x,got_max.y,got_max.z); 488 489 /*________________________*/ 490 491 vertex[0].x = 2.0f; vertex[0].y = 5.9f; vertex[0].z = -1.2f; 492 vertex[1].x = -1.87f; vertex[1].y = 7.9f; vertex[1].z = 7.4f; 493 vertex[2].x = 7.43f; vertex[2].y = -0.9f; vertex[2].z = 11.9f; 494 vertex[3].x = -6.92f; vertex[3].y = 6.3f; vertex[3].z = -3.8f; 495 vertex[4].x = 11.4f; vertex[4].y = -8.1f; vertex[4].z = 4.5f; 496 497 exp_min.x = -6.92f; exp_min.y = -0.9f; exp_min.z = -3.8f; 498 exp_max.x = 7.43f; exp_max.y = 7.90f; exp_max.z = 11.9f; 499 500 hr = D3DXComputeBoundingBox(&vertex[0],4,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_min,&got_max); 501 502 ok( hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 503 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); 504 ok( compare_vec3(exp_max,got_max), "Expected max: (%f, %f, %f), got: (%f, %f, %f)\n", exp_max.x,exp_max.y,exp_max.z,got_max.x,got_max.y,got_max.z); 505 506 /*________________________*/ 507 hr = D3DXComputeBoundingBox(NULL,5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_min,&got_max); 508 ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 509 510 /*________________________*/ 511 hr = D3DXComputeBoundingBox(&vertex[3],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),NULL,&got_max); 512 ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 513 514 /*________________________*/ 515 hr = D3DXComputeBoundingBox(&vertex[3],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_min,NULL); 516 ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 517 } 518 519 static void D3DXComputeBoundingSphereTest(void) 520 { 521 D3DXVECTOR3 exp_cen, got_cen, vertex[5]; 522 FLOAT exp_rad, got_rad; 523 HRESULT hr; 524 525 vertex[0].x = 1.0f; vertex[0].y = 1.0f; vertex[0].z = 1.0f; 526 vertex[1].x = 1.0f; vertex[1].y = 1.0f; vertex[1].z = 1.0f; 527 vertex[2].x = 1.0f; vertex[2].y = 1.0f; vertex[2].z = 1.0f; 528 vertex[3].x = 1.0f; vertex[3].y = 1.0f; vertex[3].z = 1.0f; 529 vertex[4].x = 9.0f; vertex[4].y = 9.0f; vertex[4].z = 9.0f; 530 531 exp_rad = 6.928203f; 532 exp_cen.x = 5.0; exp_cen.y = 5.0; exp_cen.z = 5.0; 533 534 hr = D3DXComputeBoundingSphere(&vertex[3],2,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_cen,&got_rad); 535 536 ok( hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 537 ok( compare(exp_rad, got_rad), "Expected radius: %f, got radius: %f\n", exp_rad, got_rad); 538 ok( compare_vec3(exp_cen,got_cen), "Expected center: (%f, %f, %f), got center: (%f, %f, %f)\n", exp_cen.x,exp_cen.y,exp_cen.z,got_cen.x,got_cen.y,got_cen.z); 539 540 /*________________________*/ 541 542 vertex[0].x = 2.0f; vertex[0].y = 5.9f; vertex[0].z = -1.2f; 543 vertex[1].x = -1.87f; vertex[1].y = 7.9f; vertex[1].z = 7.4f; 544 vertex[2].x = 7.43f; vertex[2].y = -0.9f; vertex[2].z = 11.9f; 545 vertex[3].x = -6.92f; vertex[3].y = 6.3f; vertex[3].z = -3.8f; 546 vertex[4].x = 11.4f; vertex[4].y = -8.1f; vertex[4].z = 4.5f; 547 548 exp_rad = 13.707883f; 549 exp_cen.x = 2.408f; exp_cen.y = 2.22f; exp_cen.z = 3.76f; 550 551 hr = D3DXComputeBoundingSphere(&vertex[0],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_cen,&got_rad); 552 553 ok( hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 554 ok( compare(exp_rad, got_rad), "Expected radius: %f, got radius: %f\n", exp_rad, got_rad); 555 ok( compare_vec3(exp_cen,got_cen), "Expected center: (%f, %f, %f), got center: (%f, %f, %f)\n", exp_cen.x,exp_cen.y,exp_cen.z,got_cen.x,got_cen.y,got_cen.z); 556 557 /*________________________*/ 558 hr = D3DXComputeBoundingSphere(NULL,5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_cen,&got_rad); 559 ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 560 561 /*________________________*/ 562 hr = D3DXComputeBoundingSphere(&vertex[3],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),NULL,&got_rad); 563 ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 564 565 /*________________________*/ 566 hr = D3DXComputeBoundingSphere(&vertex[3],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_cen,NULL); 567 ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 568 } 569 570 static void print_elements(const D3DVERTEXELEMENT9 *elements) 571 { 572 D3DVERTEXELEMENT9 last = D3DDECL_END(); 573 const D3DVERTEXELEMENT9 *ptr = elements; 574 int count = 0; 575 576 while (memcmp(ptr, &last, sizeof(D3DVERTEXELEMENT9))) 577 { 578 trace( 579 "[Element %d] Stream = %d, Offset = %d, Type = %d, Method = %d, Usage = %d, UsageIndex = %d\n", 580 count, ptr->Stream, ptr->Offset, ptr->Type, ptr->Method, ptr->Usage, ptr->UsageIndex); 581 ptr++; 582 count++; 583 } 584 } 585 586 static void compare_elements(const D3DVERTEXELEMENT9 *elements, const D3DVERTEXELEMENT9 *expected_elements, 587 unsigned int line, unsigned int test_id) 588 { 589 D3DVERTEXELEMENT9 last = D3DDECL_END(); 590 unsigned int i; 591 592 for (i = 0; i < MAX_FVF_DECL_SIZE; i++) 593 { 594 int end1 = memcmp(&elements[i], &last, sizeof(last)); 595 int end2 = memcmp(&expected_elements[i], &last, sizeof(last)); 596 int status; 597 598 if (!end1 && !end2) break; 599 600 status = !end1 ^ !end2; 601 ok(!status, "Line %u, test %u: Mismatch in size, test declaration is %s than expected.\n", 602 line, test_id, end1 ? "shorter" : "longer"); 603 if (status) 604 { 605 print_elements(elements); 606 break; 607 } 608 609 status = memcmp(&elements[i], &expected_elements[i], sizeof(D3DVERTEXELEMENT9)); 610 ok(!status, "Line %u, test %u: Mismatch in element %u.\n", line, test_id, i); 611 if (status) 612 { 613 print_elements(elements); 614 break; 615 } 616 } 617 } 618 619 static void test_fvf_to_decl(DWORD test_fvf, const D3DVERTEXELEMENT9 expected_elements[], 620 HRESULT expected_hr, unsigned int line, unsigned int test_id) 621 { 622 HRESULT hr; 623 D3DVERTEXELEMENT9 decl[MAX_FVF_DECL_SIZE]; 624 625 hr = D3DXDeclaratorFromFVF(test_fvf, decl); 626 ok(hr == expected_hr, 627 "Line %u, test %u: D3DXDeclaratorFromFVF returned %#x, expected %#x.\n", 628 line, test_id, hr, expected_hr); 629 if (SUCCEEDED(hr)) compare_elements(decl, expected_elements, line, test_id); 630 } 631 632 static void test_decl_to_fvf(const D3DVERTEXELEMENT9 *decl, DWORD expected_fvf, 633 HRESULT expected_hr, unsigned int line, unsigned int test_id) 634 { 635 HRESULT hr; 636 DWORD result_fvf = 0xdeadbeef; 637 638 hr = D3DXFVFFromDeclarator(decl, &result_fvf); 639 ok(hr == expected_hr, 640 "Line %u, test %u: D3DXFVFFromDeclarator returned %#x, expected %#x.\n", 641 line, test_id, hr, expected_hr); 642 if (SUCCEEDED(hr)) 643 { 644 ok(expected_fvf == result_fvf, "Line %u, test %u: Got FVF %#x, expected %#x.\n", 645 line, test_id, result_fvf, expected_fvf); 646 } 647 } 648 649 static void test_fvf_decl_conversion(void) 650 { 651 static const struct 652 { 653 D3DVERTEXELEMENT9 decl[MAXD3DDECLLENGTH + 1]; 654 DWORD fvf; 655 } 656 test_data[] = 657 { 658 {{ 659 D3DDECL_END(), 660 }, 0}, 661 {{ 662 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 663 D3DDECL_END(), 664 }, D3DFVF_XYZ}, 665 {{ 666 {0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITIONT, 0}, 667 D3DDECL_END(), 668 }, D3DFVF_XYZRHW}, 669 {{ 670 {0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITIONT, 0}, 671 D3DDECL_END(), 672 }, D3DFVF_XYZRHW}, 673 {{ 674 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 675 {0, 12, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, 676 D3DDECL_END(), 677 }, D3DFVF_XYZB1}, 678 {{ 679 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 680 {0, 12, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0}, 681 D3DDECL_END(), 682 }, D3DFVF_XYZB1 | D3DFVF_LASTBETA_UBYTE4}, 683 {{ 684 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 685 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0}, 686 D3DDECL_END(), 687 }, D3DFVF_XYZB1 | D3DFVF_LASTBETA_D3DCOLOR}, 688 {{ 689 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 690 {0, 12, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, 691 D3DDECL_END(), 692 }, D3DFVF_XYZB2}, 693 {{ 694 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 695 {0, 12, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, 696 {0, 16, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0}, 697 D3DDECL_END(), 698 }, D3DFVF_XYZB2 | D3DFVF_LASTBETA_UBYTE4}, 699 {{ 700 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 701 {0, 12, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, 702 {0, 16, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0}, 703 D3DDECL_END(), 704 }, D3DFVF_XYZB2 | D3DFVF_LASTBETA_D3DCOLOR}, 705 {{ 706 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 707 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, 708 D3DDECL_END(), 709 }, D3DFVF_XYZB3}, 710 {{ 711 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 712 {0, 12, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, 713 {0, 20, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0}, 714 D3DDECL_END(), 715 }, D3DFVF_XYZB3 | D3DFVF_LASTBETA_UBYTE4}, 716 {{ 717 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 718 {0, 12, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, 719 {0, 20, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0}, 720 D3DDECL_END(), 721 }, D3DFVF_XYZB3 | D3DFVF_LASTBETA_D3DCOLOR}, 722 {{ 723 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 724 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, 725 D3DDECL_END(), 726 }, D3DFVF_XYZB4}, 727 {{ 728 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 729 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, 730 {0, 24, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0}, 731 D3DDECL_END(), 732 }, D3DFVF_XYZB4 | D3DFVF_LASTBETA_UBYTE4}, 733 {{ 734 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 735 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, 736 {0, 24, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0}, 737 D3DDECL_END(), 738 }, D3DFVF_XYZB4 | D3DFVF_LASTBETA_D3DCOLOR}, 739 {{ 740 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 741 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, 742 {0, 28, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0}, 743 D3DDECL_END(), 744 }, D3DFVF_XYZB5 | D3DFVF_LASTBETA_UBYTE4}, 745 {{ 746 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 747 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, 748 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0}, 749 D3DDECL_END(), 750 }, D3DFVF_XYZB5 | D3DFVF_LASTBETA_D3DCOLOR}, 751 {{ 752 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0}, 753 D3DDECL_END(), 754 }, D3DFVF_NORMAL}, 755 {{ 756 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0}, 757 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0}, 758 D3DDECL_END(), 759 }, D3DFVF_NORMAL | D3DFVF_DIFFUSE}, 760 {{ 761 {0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_PSIZE, 0}, 762 D3DDECL_END(), 763 }, D3DFVF_PSIZE}, 764 {{ 765 {0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0}, 766 D3DDECL_END(), 767 }, D3DFVF_DIFFUSE}, 768 {{ 769 {0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1}, 770 D3DDECL_END(), 771 }, D3DFVF_SPECULAR}, 772 /* Make sure textures of different sizes work. */ 773 {{ 774 {0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0}, 775 D3DDECL_END(), 776 }, D3DFVF_TEXCOORDSIZE1(0) | D3DFVF_TEX1}, 777 {{ 778 {0, 0, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 0}, 779 D3DDECL_END(), 780 }, D3DFVF_TEXCOORDSIZE2(0) | D3DFVF_TEX1}, 781 {{ 782 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 0}, 783 D3DDECL_END(), 784 }, D3DFVF_TEXCOORDSIZE3(0) | D3DFVF_TEX1}, 785 {{ 786 {0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 0}, 787 D3DDECL_END(), 788 }, D3DFVF_TEXCOORDSIZE4(0) | D3DFVF_TEX1}, 789 /* Make sure the TEXCOORD index works correctly - try several textures. */ 790 {{ 791 {0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0}, 792 {0, 4, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 1}, 793 {0, 16, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 2}, 794 {0, 24, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 3}, 795 D3DDECL_END(), 796 }, D3DFVF_TEX4 | D3DFVF_TEXCOORDSIZE1(0) | D3DFVF_TEXCOORDSIZE3(1) 797 | D3DFVF_TEXCOORDSIZE2(2) | D3DFVF_TEXCOORDSIZE4(3)}, 798 /* Now try some combination tests. */ 799 {{ 800 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 801 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, 802 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0}, 803 {0, 32, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1}, 804 {0, 36, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 0}, 805 {0, 44, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 1}, 806 D3DDECL_END(), 807 }, D3DFVF_XYZB4 | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_TEX2 808 | D3DFVF_TEXCOORDSIZE2(0) | D3DFVF_TEXCOORDSIZE3(1)}, 809 {{ 810 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 811 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0}, 812 {0, 24, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_PSIZE, 0}, 813 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1}, 814 {0, 32, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0}, 815 {0, 36, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 1}, 816 D3DDECL_END(), 817 }, D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_PSIZE | D3DFVF_SPECULAR | D3DFVF_TEX2 818 | D3DFVF_TEXCOORDSIZE1(0) | D3DFVF_TEXCOORDSIZE4(1)}, 819 }; 820 unsigned int i; 821 822 for (i = 0; i < ARRAY_SIZE(test_data); ++i) 823 { 824 test_decl_to_fvf(test_data[i].decl, test_data[i].fvf, D3D_OK, __LINE__, i); 825 test_fvf_to_decl(test_data[i].fvf, test_data[i].decl, D3D_OK, __LINE__, i); 826 } 827 828 /* Usage indices for position and normal are apparently ignored. */ 829 { 830 const D3DVERTEXELEMENT9 decl[] = 831 { 832 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 1}, 833 D3DDECL_END(), 834 }; 835 test_decl_to_fvf(decl, D3DFVF_XYZ, D3D_OK, __LINE__, 0); 836 } 837 { 838 const D3DVERTEXELEMENT9 decl[] = 839 { 840 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 1}, 841 D3DDECL_END(), 842 }; 843 test_decl_to_fvf(decl, D3DFVF_NORMAL, D3D_OK, __LINE__, 0); 844 } 845 /* D3DFVF_LASTBETA_UBYTE4 and D3DFVF_LASTBETA_D3DCOLOR are ignored if 846 * there are no blend matrices. */ 847 { 848 const D3DVERTEXELEMENT9 decl[] = 849 { 850 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 851 D3DDECL_END(), 852 }; 853 test_fvf_to_decl(D3DFVF_XYZ | D3DFVF_LASTBETA_UBYTE4, decl, D3D_OK, __LINE__, 0); 854 } 855 { 856 const D3DVERTEXELEMENT9 decl[] = 857 { 858 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 859 D3DDECL_END(), 860 }; 861 test_fvf_to_decl(D3DFVF_XYZ | D3DFVF_LASTBETA_D3DCOLOR, decl, D3D_OK, __LINE__, 0); 862 } 863 /* D3DFVF_LASTBETA_UBYTE4 takes precedence over D3DFVF_LASTBETA_D3DCOLOR. */ 864 { 865 const D3DVERTEXELEMENT9 decl[] = 866 { 867 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 868 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, 869 {0, 28, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0}, 870 D3DDECL_END(), 871 }; 872 test_fvf_to_decl(D3DFVF_XYZB5 | D3DFVF_LASTBETA_D3DCOLOR | D3DFVF_LASTBETA_UBYTE4, 873 decl, D3D_OK, __LINE__, 0); 874 } 875 /* These are supposed to fail, both ways. */ 876 { 877 const D3DVERTEXELEMENT9 decl[] = 878 { 879 {0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITION, 0}, 880 D3DDECL_END(), 881 }; 882 test_decl_to_fvf(decl, D3DFVF_XYZW, D3DERR_INVALIDCALL, __LINE__, 0); 883 test_fvf_to_decl(D3DFVF_XYZW, decl, D3DERR_INVALIDCALL, __LINE__, 0); 884 } 885 { 886 const D3DVERTEXELEMENT9 decl[] = 887 { 888 {0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITION, 0}, 889 {0, 16, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0}, 890 D3DDECL_END(), 891 }; 892 test_decl_to_fvf(decl, D3DFVF_XYZW | D3DFVF_NORMAL, D3DERR_INVALIDCALL, __LINE__, 0); 893 test_fvf_to_decl(D3DFVF_XYZW | D3DFVF_NORMAL, decl, D3DERR_INVALIDCALL, __LINE__, 0); 894 } 895 { 896 const D3DVERTEXELEMENT9 decl[] = 897 { 898 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 899 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, 900 {0, 28, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDINDICES, 0}, 901 D3DDECL_END(), 902 }; 903 test_decl_to_fvf(decl, D3DFVF_XYZB5, D3DERR_INVALIDCALL, __LINE__, 0); 904 test_fvf_to_decl(D3DFVF_XYZB5, decl, D3DERR_INVALIDCALL, __LINE__, 0); 905 } 906 /* Test a declaration that can't be converted to an FVF. */ 907 { 908 const D3DVERTEXELEMENT9 decl[] = 909 { 910 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 911 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0}, 912 {0, 24, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_PSIZE, 0}, 913 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1}, 914 {0, 32, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0}, 915 /* 8 bytes padding */ 916 {0, 44, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 1}, 917 D3DDECL_END(), 918 }; 919 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0); 920 } 921 /* Elements must be ordered by offset. */ 922 { 923 const D3DVERTEXELEMENT9 decl[] = 924 { 925 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0}, 926 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 927 D3DDECL_END(), 928 }; 929 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0); 930 } 931 /* Basic tests for element order. */ 932 { 933 const D3DVERTEXELEMENT9 decl[] = 934 { 935 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 936 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0}, 937 {0, 16, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0}, 938 D3DDECL_END(), 939 }; 940 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0); 941 } 942 { 943 const D3DVERTEXELEMENT9 decl[] = 944 { 945 {0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0}, 946 {0, 4, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 947 D3DDECL_END(), 948 }; 949 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0); 950 } 951 { 952 const D3DVERTEXELEMENT9 decl[] = 953 { 954 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0}, 955 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 956 D3DDECL_END(), 957 }; 958 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0); 959 } 960 /* Textures must be ordered by texcoords. */ 961 { 962 const D3DVERTEXELEMENT9 decl[] = 963 { 964 {0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0}, 965 {0, 4, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 2}, 966 {0, 16, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 1}, 967 {0, 24, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 3}, 968 D3DDECL_END(), 969 }; 970 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0); 971 } 972 /* Duplicate elements are not allowed. */ 973 { 974 const D3DVERTEXELEMENT9 decl[] = 975 { 976 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 977 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0}, 978 {0, 16, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0}, 979 D3DDECL_END(), 980 }; 981 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0); 982 } 983 /* Invalid FVFs cannot be converted to a declarator. */ 984 test_fvf_to_decl(0xdeadbeef, NULL, D3DERR_INVALIDCALL, __LINE__, 0); 985 } 986 987 static void D3DXGetFVFVertexSizeTest(void) 988 { 989 UINT got; 990 991 compare_vertex_sizes (D3DFVF_XYZ, 12); 992 993 compare_vertex_sizes (D3DFVF_XYZB3, 24); 994 995 compare_vertex_sizes (D3DFVF_XYZB5, 32); 996 997 compare_vertex_sizes (D3DFVF_XYZ | D3DFVF_NORMAL, 24); 998 999 compare_vertex_sizes (D3DFVF_XYZ | D3DFVF_DIFFUSE, 16); 1000 1001 compare_vertex_sizes ( 1002 D3DFVF_XYZ | 1003 D3DFVF_TEX1 | 1004 D3DFVF_TEXCOORDSIZE1(0), 16); 1005 compare_vertex_sizes ( 1006 D3DFVF_XYZ | 1007 D3DFVF_TEX2 | 1008 D3DFVF_TEXCOORDSIZE1(0) | 1009 D3DFVF_TEXCOORDSIZE1(1), 20); 1010 1011 compare_vertex_sizes ( 1012 D3DFVF_XYZ | 1013 D3DFVF_TEX1 | 1014 D3DFVF_TEXCOORDSIZE2(0), 20); 1015 1016 compare_vertex_sizes ( 1017 D3DFVF_XYZ | 1018 D3DFVF_TEX2 | 1019 D3DFVF_TEXCOORDSIZE2(0) | 1020 D3DFVF_TEXCOORDSIZE2(1), 28); 1021 1022 compare_vertex_sizes ( 1023 D3DFVF_XYZ | 1024 D3DFVF_TEX6 | 1025 D3DFVF_TEXCOORDSIZE2(0) | 1026 D3DFVF_TEXCOORDSIZE2(1) | 1027 D3DFVF_TEXCOORDSIZE2(2) | 1028 D3DFVF_TEXCOORDSIZE2(3) | 1029 D3DFVF_TEXCOORDSIZE2(4) | 1030 D3DFVF_TEXCOORDSIZE2(5), 60); 1031 1032 compare_vertex_sizes ( 1033 D3DFVF_XYZ | 1034 D3DFVF_TEX8 | 1035 D3DFVF_TEXCOORDSIZE2(0) | 1036 D3DFVF_TEXCOORDSIZE2(1) | 1037 D3DFVF_TEXCOORDSIZE2(2) | 1038 D3DFVF_TEXCOORDSIZE2(3) | 1039 D3DFVF_TEXCOORDSIZE2(4) | 1040 D3DFVF_TEXCOORDSIZE2(5) | 1041 D3DFVF_TEXCOORDSIZE2(6) | 1042 D3DFVF_TEXCOORDSIZE2(7), 76); 1043 1044 compare_vertex_sizes ( 1045 D3DFVF_XYZ | 1046 D3DFVF_TEX1 | 1047 D3DFVF_TEXCOORDSIZE3(0), 24); 1048 1049 compare_vertex_sizes ( 1050 D3DFVF_XYZ | 1051 D3DFVF_TEX4 | 1052 D3DFVF_TEXCOORDSIZE3(0) | 1053 D3DFVF_TEXCOORDSIZE3(1) | 1054 D3DFVF_TEXCOORDSIZE3(2) | 1055 D3DFVF_TEXCOORDSIZE3(3), 60); 1056 1057 compare_vertex_sizes ( 1058 D3DFVF_XYZ | 1059 D3DFVF_TEX1 | 1060 D3DFVF_TEXCOORDSIZE4(0), 28); 1061 1062 compare_vertex_sizes ( 1063 D3DFVF_XYZ | 1064 D3DFVF_TEX2 | 1065 D3DFVF_TEXCOORDSIZE4(0) | 1066 D3DFVF_TEXCOORDSIZE4(1), 44); 1067 1068 compare_vertex_sizes ( 1069 D3DFVF_XYZ | 1070 D3DFVF_TEX3 | 1071 D3DFVF_TEXCOORDSIZE4(0) | 1072 D3DFVF_TEXCOORDSIZE4(1) | 1073 D3DFVF_TEXCOORDSIZE4(2), 60); 1074 1075 compare_vertex_sizes ( 1076 D3DFVF_XYZB5 | 1077 D3DFVF_NORMAL | 1078 D3DFVF_DIFFUSE | 1079 D3DFVF_SPECULAR | 1080 D3DFVF_TEX8 | 1081 D3DFVF_TEXCOORDSIZE4(0) | 1082 D3DFVF_TEXCOORDSIZE4(1) | 1083 D3DFVF_TEXCOORDSIZE4(2) | 1084 D3DFVF_TEXCOORDSIZE4(3) | 1085 D3DFVF_TEXCOORDSIZE4(4) | 1086 D3DFVF_TEXCOORDSIZE4(5) | 1087 D3DFVF_TEXCOORDSIZE4(6) | 1088 D3DFVF_TEXCOORDSIZE4(7), 180); 1089 } 1090 1091 static void D3DXIntersectTriTest(void) 1092 { 1093 BOOL exp_res, got_res; 1094 D3DXVECTOR3 position, ray, vertex[3]; 1095 FLOAT exp_dist, got_dist, exp_u, got_u, exp_v, got_v; 1096 1097 vertex[0].x = 1.0f; vertex[0].y = 0.0f; vertex[0].z = 0.0f; 1098 vertex[1].x = 2.0f; vertex[1].y = 0.0f; vertex[1].z = 0.0f; 1099 vertex[2].x = 1.0f; vertex[2].y = 1.0f; vertex[2].z = 0.0f; 1100 1101 position.x = -14.5f; position.y = -23.75f; position.z = -32.0f; 1102 1103 ray.x = 2.0f; ray.y = 3.0f; ray.z = 4.0f; 1104 1105 exp_res = TRUE; exp_u = 0.5f; exp_v = 0.25f; exp_dist = 8.0f; 1106 1107 got_res = D3DXIntersectTri(&vertex[0], &vertex[1], &vertex[2], &position, &ray, &got_u, &got_v, &got_dist); 1108 ok(got_res == exp_res, "Expected result %d, got %d.\n", exp_res, got_res); 1109 ok(compare(exp_u, got_u), "Expected u %f, got %f.\n", exp_u, got_u); 1110 ok(compare(exp_v, got_v), "Expected v %f, got %f.\n", exp_v, got_v); 1111 ok(compare(exp_dist, got_dist), "Expected distance %f, got %f.\n", exp_dist, got_dist); 1112 1113 got_res = D3DXIntersectTri(&vertex[0], &vertex[1], &vertex[2], &position, &ray, NULL, NULL, NULL); 1114 ok(got_res == exp_res, "Expected result %d, got %d.\n", exp_res, got_res); 1115 1116 vertex[2].x = 1.0f; vertex[2].y = 0.0f; vertex[2].z = 0.0f; 1117 vertex[1].x = 2.0f; vertex[1].y = 0.0f; vertex[1].z = 0.0f; 1118 vertex[0].x = 1.0f; vertex[0].y = 1.0f; vertex[0].z = 0.0f; 1119 1120 got_u = got_v = got_dist = 0.0f; 1121 got_res = D3DXIntersectTri(&vertex[0], &vertex[1], &vertex[2], &position, &ray, &got_u, &got_v, &got_dist); 1122 ok(got_res == exp_res, "Expected result %d, got %d.\n", exp_res, got_res); 1123 ok(compare(exp_u, got_u), "Expected u %f, got %f.\n", exp_u, got_u); 1124 ok(compare(exp_v, got_v), "Expected v %f, got %f.\n", exp_v, got_v); 1125 ok(compare(exp_dist, got_dist), "Expected distance %f, got %f.\n", exp_dist, got_dist); 1126 1127 vertex[2].x = 1.0f; vertex[2].y = 0.0f; vertex[2].z = 0.0f; 1128 vertex[1].x = 2.0f; vertex[1].y = 0.0f; vertex[1].z = -0.5f; 1129 vertex[0].x = 1.0f; vertex[0].y = 1.0f; vertex[0].z = -1.0f; 1130 exp_u = 0.375f; 1131 exp_v = 0.5625f; 1132 exp_dist = 7.9375f; 1133 got_u = got_v = got_dist = 0.0f; 1134 got_res = D3DXIntersectTri(&vertex[0], &vertex[1], &vertex[2], &position, &ray, &got_u, &got_v, &got_dist); 1135 ok(got_res == exp_res, "Expected result %d, got %d.\n", exp_res, got_res); 1136 ok(compare(exp_u, got_u), "Expected u %f, got %f.\n", exp_u, got_u); 1137 ok(compare(exp_v, got_v), "Expected v %f, got %f.\n", exp_v, got_v); 1138 ok(compare(exp_dist, got_dist), "Expected distance %f, got %f.\n", exp_dist, got_dist); 1139 1140 1141 /*Only positive ray is taken in account*/ 1142 1143 vertex[0].x = 1.0f; vertex[0].y = 0.0f; vertex[0].z = 0.0f; 1144 vertex[1].x = 2.0f; vertex[1].y = 0.0f; vertex[1].z = 0.0f; 1145 vertex[2].x = 1.0f; vertex[2].y = 1.0f; vertex[2].z = 0.0f; 1146 1147 position.x = 17.5f; position.y = 24.25f; position.z = 32.0f; 1148 1149 ray.x = 2.0f; ray.y = 3.0f; ray.z = 4.0f; 1150 1151 exp_res = FALSE; 1152 1153 got_res = D3DXIntersectTri(&vertex[0],&vertex[1],&vertex[2],&position,&ray,&got_u,&got_v,&got_dist); 1154 ok( got_res == exp_res, "Expected result = %d, got %d\n",exp_res,got_res); 1155 1156 got_res = D3DXIntersectTri(&vertex[0], &vertex[1], &vertex[2], &position, &ray, NULL, NULL, NULL); 1157 ok(got_res == exp_res, "Expected result = %d, got %d\n", exp_res, got_res); 1158 1159 /*Intersection between ray and triangle in a same plane is considered as empty*/ 1160 1161 vertex[0].x = 4.0f; vertex[0].y = 0.0f; vertex[0].z = 0.0f; 1162 vertex[1].x = 6.0f; vertex[1].y = 0.0f; vertex[1].z = 0.0f; 1163 vertex[2].x = 4.0f; vertex[2].y = 2.0f; vertex[2].z = 0.0f; 1164 1165 position.x = 1.0f; position.y = 1.0f; position.z = 0.0f; 1166 1167 ray.x = 1.0f; ray.y = 0.0f; ray.z = 0.0f; 1168 1169 exp_res = FALSE; 1170 1171 got_res = D3DXIntersectTri(&vertex[0],&vertex[1],&vertex[2],&position,&ray,&got_u,&got_v,&got_dist); 1172 ok( got_res == exp_res, "Expected result = %d, got %d\n",exp_res,got_res); 1173 1174 got_res = D3DXIntersectTri(&vertex[0], &vertex[1], &vertex[2], &position, &ray, NULL, NULL, NULL); 1175 ok(got_res == exp_res, "Expected result = %d, got %d\n", exp_res, got_res); 1176 } 1177 1178 static void D3DXCreateMeshTest(void) 1179 { 1180 HRESULT hr; 1181 IDirect3DDevice9 *device, *test_device; 1182 ID3DXMesh *d3dxmesh; 1183 int i, size; 1184 D3DVERTEXELEMENT9 test_decl[MAX_FVF_DECL_SIZE]; 1185 DWORD options; 1186 struct mesh mesh; 1187 struct test_context *test_context; 1188 1189 static const D3DVERTEXELEMENT9 decl1[] = 1190 { 1191 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 1192 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 1193 D3DDECL_END(), 1194 }; 1195 1196 static const D3DVERTEXELEMENT9 decl2[] = 1197 { 1198 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 1199 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 1200 {0, 24, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_PSIZE, 0}, 1201 {0, 28, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 1}, 1202 {0, 32, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 1203 /* 8 bytes padding */ 1204 {0, 44, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1}, 1205 D3DDECL_END(), 1206 }; 1207 1208 static const D3DVERTEXELEMENT9 decl3[] = 1209 { 1210 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 1211 {1, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 1212 D3DDECL_END(), 1213 }; 1214 1215 hr = D3DXCreateMesh(0, 0, 0, NULL, NULL, NULL); 1216 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 1217 1218 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl1, NULL, &d3dxmesh); 1219 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 1220 1221 test_context = new_test_context(); 1222 if (!test_context) 1223 { 1224 skip("Couldn't create test context\n"); 1225 return; 1226 } 1227 device = test_context->device; 1228 1229 hr = D3DXCreateMesh(0, 3, D3DXMESH_MANAGED, decl1, device, &d3dxmesh); 1230 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 1231 1232 hr = D3DXCreateMesh(1, 0, D3DXMESH_MANAGED, decl1, device, &d3dxmesh); 1233 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 1234 1235 hr = D3DXCreateMesh(1, 3, 0, decl1, device, &d3dxmesh); 1236 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK); 1237 1238 if (hr == D3D_OK) 1239 { 1240 d3dxmesh->lpVtbl->Release(d3dxmesh); 1241 } 1242 1243 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, 0, device, &d3dxmesh); 1244 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 1245 1246 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl1, device, NULL); 1247 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 1248 1249 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl1, device, &d3dxmesh); 1250 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); 1251 1252 if (hr == D3D_OK) 1253 { 1254 /* device */ 1255 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, NULL); 1256 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 1257 1258 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, &test_device); 1259 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK); 1260 ok(test_device == device, "Got result %p, expected %p\n", test_device, device); 1261 1262 if (hr == D3D_OK) 1263 { 1264 IDirect3DDevice9_Release(device); 1265 } 1266 1267 /* declaration */ 1268 hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, NULL); 1269 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 1270 1271 hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, test_decl); 1272 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); 1273 1274 if (hr == D3D_OK) 1275 { 1276 size = ARRAY_SIZE(decl1); 1277 for (i = 0; i < size - 1; i++) 1278 { 1279 ok(test_decl[i].Stream == decl1[i].Stream, "Returned stream %d, expected %d\n", test_decl[i].Stream, decl1[i].Stream); 1280 ok(test_decl[i].Type == decl1[i].Type, "Returned type %d, expected %d\n", test_decl[i].Type, decl1[i].Type); 1281 ok(test_decl[i].Method == decl1[i].Method, "Returned method %d, expected %d\n", test_decl[i].Method, decl1[i].Method); 1282 ok(test_decl[i].Usage == decl1[i].Usage, "Returned usage %d, expected %d\n", test_decl[i].Usage, decl1[i].Usage); 1283 ok(test_decl[i].UsageIndex == decl1[i].UsageIndex, "Returned usage index %d, expected %d\n", test_decl[i].UsageIndex, decl1[i].UsageIndex); 1284 ok(test_decl[i].Offset == decl1[i].Offset, "Returned offset %d, expected %d\n", test_decl[i].Offset, decl1[i].Offset); 1285 } 1286 ok(decl1[size-1].Stream == 0xFF, "Returned too long vertex declaration\n"); /* end element */ 1287 } 1288 1289 /* options */ 1290 options = d3dxmesh->lpVtbl->GetOptions(d3dxmesh); 1291 ok(options == D3DXMESH_MANAGED, "Got result %x, expected %x (D3DXMESH_MANAGED)\n", options, D3DXMESH_MANAGED); 1292 1293 /* rest */ 1294 if (!new_mesh(&mesh, 3, 1)) 1295 { 1296 skip("Couldn't create mesh\n"); 1297 } 1298 else 1299 { 1300 memset(mesh.vertices, 0, mesh.number_of_vertices * sizeof(*mesh.vertices)); 1301 memset(mesh.faces, 0, mesh.number_of_faces * sizeof(*mesh.faces)); 1302 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL; 1303 1304 compare_mesh("createmesh1", d3dxmesh, &mesh); 1305 1306 free_mesh(&mesh); 1307 } 1308 1309 d3dxmesh->lpVtbl->Release(d3dxmesh); 1310 } 1311 1312 /* Test a declaration that can't be converted to an FVF. */ 1313 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl2, device, &d3dxmesh); 1314 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); 1315 1316 if (hr == D3D_OK) 1317 { 1318 /* device */ 1319 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, NULL); 1320 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 1321 1322 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, &test_device); 1323 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK); 1324 ok(test_device == device, "Got result %p, expected %p\n", test_device, device); 1325 1326 if (hr == D3D_OK) 1327 { 1328 IDirect3DDevice9_Release(device); 1329 } 1330 1331 /* declaration */ 1332 hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, test_decl); 1333 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); 1334 1335 if (hr == D3D_OK) 1336 { 1337 size = ARRAY_SIZE(decl2); 1338 for (i = 0; i < size - 1; i++) 1339 { 1340 ok(test_decl[i].Stream == decl2[i].Stream, "Returned stream %d, expected %d\n", test_decl[i].Stream, decl2[i].Stream); 1341 ok(test_decl[i].Type == decl2[i].Type, "Returned type %d, expected %d\n", test_decl[i].Type, decl2[i].Type); 1342 ok(test_decl[i].Method == decl2[i].Method, "Returned method %d, expected %d\n", test_decl[i].Method, decl2[i].Method); 1343 ok(test_decl[i].Usage == decl2[i].Usage, "Returned usage %d, expected %d\n", test_decl[i].Usage, decl2[i].Usage); 1344 ok(test_decl[i].UsageIndex == decl2[i].UsageIndex, "Returned usage index %d, expected %d\n", test_decl[i].UsageIndex, decl2[i].UsageIndex); 1345 ok(test_decl[i].Offset == decl2[i].Offset, "Returned offset %d, expected %d\n", test_decl[i].Offset, decl2[i].Offset); 1346 } 1347 ok(decl2[size-1].Stream == 0xFF, "Returned too long vertex declaration\n"); /* end element */ 1348 } 1349 1350 /* options */ 1351 options = d3dxmesh->lpVtbl->GetOptions(d3dxmesh); 1352 ok(options == D3DXMESH_MANAGED, "Got result %x, expected %x (D3DXMESH_MANAGED)\n", options, D3DXMESH_MANAGED); 1353 1354 /* rest */ 1355 if (!new_mesh(&mesh, 3, 1)) 1356 { 1357 skip("Couldn't create mesh\n"); 1358 } 1359 else 1360 { 1361 memset(mesh.vertices, 0, mesh.number_of_vertices * sizeof(*mesh.vertices)); 1362 memset(mesh.faces, 0, mesh.number_of_faces * sizeof(*mesh.faces)); 1363 mesh.fvf = 0; 1364 mesh.vertex_size = 60; 1365 1366 compare_mesh("createmesh2", d3dxmesh, &mesh); 1367 1368 free_mesh(&mesh); 1369 } 1370 1371 mesh.vertex_size = d3dxmesh->lpVtbl->GetNumBytesPerVertex(d3dxmesh); 1372 ok(mesh.vertex_size == 60, "Got vertex size %u, expected %u\n", mesh.vertex_size, 60); 1373 1374 d3dxmesh->lpVtbl->Release(d3dxmesh); 1375 } 1376 1377 /* Test a declaration with multiple streams. */ 1378 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl3, device, &d3dxmesh); 1379 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 1380 1381 free_test_context(test_context); 1382 } 1383 1384 static void D3DXCreateMeshFVFTest(void) 1385 { 1386 HRESULT hr; 1387 IDirect3DDevice9 *device, *test_device; 1388 ID3DXMesh *d3dxmesh; 1389 int i, size; 1390 D3DVERTEXELEMENT9 test_decl[MAX_FVF_DECL_SIZE]; 1391 DWORD options; 1392 struct mesh mesh; 1393 struct test_context *test_context; 1394 1395 static const D3DVERTEXELEMENT9 decl[] = 1396 { 1397 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 1398 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 1399 D3DDECL_END(), 1400 }; 1401 1402 hr = D3DXCreateMeshFVF(0, 0, 0, 0, NULL, NULL); 1403 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 1404 1405 hr = D3DXCreateMeshFVF(1, 3, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, NULL, &d3dxmesh); 1406 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 1407 1408 test_context = new_test_context(); 1409 if (!test_context) 1410 { 1411 skip("Couldn't create test context\n"); 1412 return; 1413 } 1414 device = test_context->device; 1415 1416 hr = D3DXCreateMeshFVF(0, 3, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, device, &d3dxmesh); 1417 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 1418 1419 hr = D3DXCreateMeshFVF(1, 0, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, device, &d3dxmesh); 1420 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 1421 1422 hr = D3DXCreateMeshFVF(1, 3, 0, D3DFVF_XYZ | D3DFVF_NORMAL, device, &d3dxmesh); 1423 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK); 1424 1425 if (hr == D3D_OK) 1426 { 1427 d3dxmesh->lpVtbl->Release(d3dxmesh); 1428 } 1429 1430 hr = D3DXCreateMeshFVF(1, 3, D3DXMESH_MANAGED, 0xdeadbeef, device, &d3dxmesh); 1431 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 1432 1433 hr = D3DXCreateMeshFVF(1, 3, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, device, NULL); 1434 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 1435 1436 hr = D3DXCreateMeshFVF(1, 3, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, device, &d3dxmesh); 1437 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); 1438 1439 if (hr == D3D_OK) 1440 { 1441 /* device */ 1442 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, NULL); 1443 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 1444 1445 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, &test_device); 1446 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK); 1447 ok(test_device == device, "Got result %p, expected %p\n", test_device, device); 1448 1449 if (hr == D3D_OK) 1450 { 1451 IDirect3DDevice9_Release(device); 1452 } 1453 1454 /* declaration */ 1455 hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, NULL); 1456 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 1457 1458 hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, test_decl); 1459 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); 1460 1461 if (hr == D3D_OK) 1462 { 1463 size = ARRAY_SIZE(decl); 1464 for (i = 0; i < size - 1; i++) 1465 { 1466 ok(test_decl[i].Stream == decl[i].Stream, "Returned stream %d, expected %d\n", test_decl[i].Stream, decl[i].Stream); 1467 ok(test_decl[i].Type == decl[i].Type, "Returned type %d, expected %d\n", test_decl[i].Type, decl[i].Type); 1468 ok(test_decl[i].Method == decl[i].Method, "Returned method %d, expected %d\n", test_decl[i].Method, decl[i].Method); 1469 ok(test_decl[i].Usage == decl[i].Usage, "Returned usage %d, expected %d\n", test_decl[i].Usage, decl[i].Usage); 1470 ok(test_decl[i].UsageIndex == decl[i].UsageIndex, "Returned usage index %d, expected %d\n", 1471 test_decl[i].UsageIndex, decl[i].UsageIndex); 1472 ok(test_decl[i].Offset == decl[i].Offset, "Returned offset %d, expected %d\n", test_decl[i].Offset, decl[i].Offset); 1473 } 1474 ok(decl[size-1].Stream == 0xFF, "Returned too long vertex declaration\n"); /* end element */ 1475 } 1476 1477 /* options */ 1478 options = d3dxmesh->lpVtbl->GetOptions(d3dxmesh); 1479 ok(options == D3DXMESH_MANAGED, "Got result %x, expected %x (D3DXMESH_MANAGED)\n", options, D3DXMESH_MANAGED); 1480 1481 /* rest */ 1482 if (!new_mesh(&mesh, 3, 1)) 1483 { 1484 skip("Couldn't create mesh\n"); 1485 } 1486 else 1487 { 1488 memset(mesh.vertices, 0, mesh.number_of_vertices * sizeof(*mesh.vertices)); 1489 memset(mesh.faces, 0, mesh.number_of_faces * sizeof(*mesh.faces)); 1490 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL; 1491 1492 compare_mesh("createmeshfvf", d3dxmesh, &mesh); 1493 1494 free_mesh(&mesh); 1495 } 1496 1497 d3dxmesh->lpVtbl->Release(d3dxmesh); 1498 } 1499 1500 free_test_context(test_context); 1501 } 1502 1503 #define check_vertex_buffer(mesh, vertices, num_vertices, fvf) \ 1504 check_vertex_buffer_(__LINE__, mesh, vertices, num_vertices, fvf) 1505 static void check_vertex_buffer_(int line, ID3DXMesh *mesh, const void *vertices, DWORD num_vertices, DWORD fvf) 1506 { 1507 DWORD mesh_num_vertices = mesh->lpVtbl->GetNumVertices(mesh); 1508 DWORD mesh_fvf = mesh->lpVtbl->GetFVF(mesh); 1509 const void *mesh_vertices; 1510 HRESULT hr; 1511 1512 ok_(__FILE__,line)(fvf == mesh_fvf, "expected FVF %x, got %x\n", fvf, mesh_fvf); 1513 ok_(__FILE__,line)(num_vertices == mesh_num_vertices, 1514 "Expected %u vertices, got %u\n", num_vertices, mesh_num_vertices); 1515 1516 hr = mesh->lpVtbl->LockVertexBuffer(mesh, D3DLOCK_READONLY, (void**)&mesh_vertices); 1517 ok_(__FILE__,line)(hr == D3D_OK, "LockVertexBuffer returned %x, expected %x (D3D_OK)\n", hr, D3D_OK); 1518 if (FAILED(hr)) 1519 return; 1520 1521 if (mesh_fvf == fvf) { 1522 DWORD vertex_size = D3DXGetFVFVertexSize(fvf), i; 1523 1524 for (i = 0; i < min(num_vertices, mesh_num_vertices); i++) 1525 { 1526 const FLOAT *exp_float = vertices; 1527 const FLOAT *got_float = mesh_vertices; 1528 DWORD texcount; 1529 DWORD pos_dim = 0; 1530 int j; 1531 BOOL last_beta_dword = FALSE; 1532 char prefix[128]; 1533 1534 switch (fvf & D3DFVF_POSITION_MASK) { 1535 case D3DFVF_XYZ: pos_dim = 3; break; 1536 case D3DFVF_XYZRHW: pos_dim = 4; break; 1537 case D3DFVF_XYZB1: 1538 case D3DFVF_XYZB2: 1539 case D3DFVF_XYZB3: 1540 case D3DFVF_XYZB4: 1541 case D3DFVF_XYZB5: 1542 pos_dim = (fvf & D3DFVF_POSITION_MASK) - D3DFVF_XYZB1 + 1; 1543 if (fvf & (D3DFVF_LASTBETA_UBYTE4 | D3DFVF_LASTBETA_D3DCOLOR)) 1544 { 1545 pos_dim--; 1546 last_beta_dword = TRUE; 1547 } 1548 break; 1549 case D3DFVF_XYZW: pos_dim = 4; break; 1550 } 1551 sprintf(prefix, "vertex[%u] position, ", i); 1552 check_floats_(line, prefix, got_float, exp_float, pos_dim); 1553 exp_float += pos_dim; 1554 got_float += pos_dim; 1555 1556 if (last_beta_dword) { 1557 ok_(__FILE__,line)(*(DWORD*)exp_float == *(DWORD*)got_float, 1558 "Vertex[%u]: Expected last beta %08x, got %08x\n", i, *(DWORD*)exp_float, *(DWORD*)got_float); 1559 exp_float++; 1560 got_float++; 1561 } 1562 1563 if (fvf & D3DFVF_NORMAL) { 1564 sprintf(prefix, "vertex[%u] normal, ", i); 1565 check_floats_(line, prefix, got_float, exp_float, 3); 1566 exp_float += 3; 1567 got_float += 3; 1568 } 1569 if (fvf & D3DFVF_PSIZE) { 1570 ok_(__FILE__,line)(compare(*exp_float, *got_float), 1571 "Vertex[%u]: Expected psize %g, got %g\n", i, *exp_float, *got_float); 1572 exp_float++; 1573 got_float++; 1574 } 1575 if (fvf & D3DFVF_DIFFUSE) { 1576 ok_(__FILE__,line)(*(DWORD*)exp_float == *(DWORD*)got_float, 1577 "Vertex[%u]: Expected diffuse %08x, got %08x\n", i, *(DWORD*)exp_float, *(DWORD*)got_float); 1578 exp_float++; 1579 got_float++; 1580 } 1581 if (fvf & D3DFVF_SPECULAR) { 1582 ok_(__FILE__,line)(*(DWORD*)exp_float == *(DWORD*)got_float, 1583 "Vertex[%u]: Expected specular %08x, got %08x\n", i, *(DWORD*)exp_float, *(DWORD*)got_float); 1584 exp_float++; 1585 got_float++; 1586 } 1587 1588 texcount = (fvf & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT; 1589 for (j = 0; j < texcount; j++) { 1590 DWORD dim = (((fvf >> (16 + 2 * j)) + 1) & 0x03) + 1; 1591 sprintf(prefix, "vertex[%u] texture, ", i); 1592 check_floats_(line, prefix, got_float, exp_float, dim); 1593 exp_float += dim; 1594 got_float += dim; 1595 } 1596 1597 vertices = (BYTE*)vertices + vertex_size; 1598 mesh_vertices = (BYTE*)mesh_vertices + vertex_size; 1599 } 1600 } 1601 1602 mesh->lpVtbl->UnlockVertexBuffer(mesh); 1603 } 1604 1605 #define check_index_buffer(mesh, indices, num_indices, index_size) \ 1606 check_index_buffer_(__LINE__, mesh, indices, num_indices, index_size) 1607 static void check_index_buffer_(int line, ID3DXMesh *mesh, const void *indices, DWORD num_indices, DWORD index_size) 1608 { 1609 DWORD mesh_index_size = (mesh->lpVtbl->GetOptions(mesh) & D3DXMESH_32BIT) ? 4 : 2; 1610 DWORD mesh_num_indices = mesh->lpVtbl->GetNumFaces(mesh) * 3; 1611 const void *mesh_indices; 1612 HRESULT hr; 1613 DWORD i; 1614 1615 ok_(__FILE__,line)(index_size == mesh_index_size, 1616 "Expected index size %u, got %u\n", index_size, mesh_index_size); 1617 ok_(__FILE__,line)(num_indices == mesh_num_indices, 1618 "Expected %u indices, got %u\n", num_indices, mesh_num_indices); 1619 1620 hr = mesh->lpVtbl->LockIndexBuffer(mesh, D3DLOCK_READONLY, (void**)&mesh_indices); 1621 ok_(__FILE__,line)(hr == D3D_OK, "LockIndexBuffer returned %x, expected %x (D3D_OK)\n", hr, D3D_OK); 1622 if (FAILED(hr)) 1623 return; 1624 1625 if (mesh_index_size == index_size) { 1626 for (i = 0; i < min(num_indices, mesh_num_indices); i++) 1627 { 1628 if (index_size == 4) 1629 ok_(__FILE__,line)(*(DWORD*)indices == *(DWORD*)mesh_indices, 1630 "Index[%u]: expected %u, got %u\n", i, *(DWORD*)indices, *(DWORD*)mesh_indices); 1631 else 1632 ok_(__FILE__,line)(*(WORD*)indices == *(WORD*)mesh_indices, 1633 "Index[%u]: expected %u, got %u\n", i, *(WORD*)indices, *(WORD*)mesh_indices); 1634 indices = (BYTE*)indices + index_size; 1635 mesh_indices = (BYTE*)mesh_indices + index_size; 1636 } 1637 } 1638 mesh->lpVtbl->UnlockIndexBuffer(mesh); 1639 } 1640 1641 #define check_matrix(got, expected) check_matrix_(__LINE__, got, expected) 1642 static void check_matrix_(int line, const D3DXMATRIX *got, const D3DXMATRIX *expected) 1643 { 1644 int i, j; 1645 for (i = 0; i < 4; i++) { 1646 for (j = 0; j < 4; j++) { 1647 ok_(__FILE__,line)(compare(U(*expected).m[i][j], U(*got).m[i][j]), 1648 "matrix[%u][%u]: expected %g, got %g\n", 1649 i, j, U(*expected).m[i][j], U(*got).m[i][j]); 1650 } 1651 } 1652 } 1653 1654 static void check_colorvalue_(int line, const char *prefix, const D3DCOLORVALUE got, const D3DCOLORVALUE expected) 1655 { 1656 ok_(__FILE__,line)(expected.r == got.r && expected.g == got.g && expected.b == got.b && expected.a == got.a, 1657 "%sExpected (%g, %g, %g, %g), got (%g, %g, %g, %g)\n", prefix, 1658 expected.r, expected.g, expected.b, expected.a, got.r, got.g, got.b, got.a); 1659 } 1660 1661 #define check_materials(got, got_count, expected, expected_count) \ 1662 check_materials_(__LINE__, got, got_count, expected, expected_count) 1663 static void check_materials_(int line, const D3DXMATERIAL *got, DWORD got_count, const D3DXMATERIAL *expected, DWORD expected_count) 1664 { 1665 int i; 1666 ok_(__FILE__,line)(expected_count == got_count, "Expected %u materials, got %u\n", expected_count, got_count); 1667 if (!expected) { 1668 ok_(__FILE__,line)(got == NULL, "Expected NULL material ptr, got %p\n", got); 1669 return; 1670 } 1671 for (i = 0; i < min(expected_count, got_count); i++) 1672 { 1673 if (!expected[i].pTextureFilename) 1674 ok_(__FILE__,line)(got[i].pTextureFilename == NULL, 1675 "Expected NULL pTextureFilename, got %p\n", got[i].pTextureFilename); 1676 else 1677 ok_(__FILE__,line)(!strcmp(expected[i].pTextureFilename, got[i].pTextureFilename), 1678 "Expected '%s' for pTextureFilename, got '%s'\n", expected[i].pTextureFilename, got[i].pTextureFilename); 1679 check_colorvalue_(line, "Diffuse: ", got[i].MatD3D.Diffuse, expected[i].MatD3D.Diffuse); 1680 check_colorvalue_(line, "Ambient: ", got[i].MatD3D.Ambient, expected[i].MatD3D.Ambient); 1681 check_colorvalue_(line, "Specular: ", got[i].MatD3D.Specular, expected[i].MatD3D.Specular); 1682 check_colorvalue_(line, "Emissive: ", got[i].MatD3D.Emissive, expected[i].MatD3D.Emissive); 1683 ok_(__FILE__,line)(expected[i].MatD3D.Power == got[i].MatD3D.Power, 1684 "Power: Expected %g, got %g\n", expected[i].MatD3D.Power, got[i].MatD3D.Power); 1685 } 1686 } 1687 1688 #define check_generated_adjacency(mesh, got, epsilon) check_generated_adjacency_(__LINE__, mesh, got, epsilon) 1689 static void check_generated_adjacency_(int line, ID3DXMesh *mesh, const DWORD *got, FLOAT epsilon) 1690 { 1691 DWORD *expected; 1692 DWORD num_faces = mesh->lpVtbl->GetNumFaces(mesh); 1693 HRESULT hr; 1694 1695 expected = HeapAlloc(GetProcessHeap(), 0, num_faces * sizeof(DWORD) * 3); 1696 if (!expected) { 1697 skip_(__FILE__, line)("Out of memory\n"); 1698 return; 1699 } 1700 hr = mesh->lpVtbl->GenerateAdjacency(mesh, epsilon, expected); 1701 ok_(__FILE__, line)(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 1702 if (SUCCEEDED(hr)) 1703 { 1704 int i; 1705 for (i = 0; i < num_faces; i++) 1706 { 1707 ok_(__FILE__, line)(expected[i * 3] == got[i * 3] && 1708 expected[i * 3 + 1] == got[i * 3 + 1] && 1709 expected[i * 3 + 2] == got[i * 3 + 2], 1710 "Face %u adjacencies: Expected (%u, %u, %u), got (%u, %u, %u)\n", i, 1711 expected[i * 3], expected[i * 3 + 1], expected[i * 3 + 2], 1712 got[i * 3], got[i * 3 + 1], got[i * 3 + 2]); 1713 } 1714 } 1715 HeapFree(GetProcessHeap(), 0, expected); 1716 } 1717 1718 #define check_generated_effects(materials, num_materials, effects) \ 1719 check_generated_effects_(__LINE__, materials, num_materials, effects) 1720 static void check_generated_effects_(int line, const D3DXMATERIAL *materials, DWORD num_materials, const D3DXEFFECTINSTANCE *effects) 1721 { 1722 int i; 1723 static const struct { 1724 const char *name; 1725 DWORD name_size; 1726 DWORD num_bytes; 1727 DWORD value_offset; 1728 } params[] = { 1729 #define EFFECT_TABLE_ENTRY(str, field) \ 1730 {str, sizeof(str), sizeof(materials->MatD3D.field), offsetof(D3DXMATERIAL, MatD3D.field)} 1731 EFFECT_TABLE_ENTRY("Diffuse", Diffuse), 1732 EFFECT_TABLE_ENTRY("Power", Power), 1733 EFFECT_TABLE_ENTRY("Specular", Specular), 1734 EFFECT_TABLE_ENTRY("Emissive", Emissive), 1735 EFFECT_TABLE_ENTRY("Ambient", Ambient), 1736 #undef EFFECT_TABLE_ENTRY 1737 }; 1738 1739 if (!num_materials) { 1740 ok_(__FILE__, line)(effects == NULL, "Expected NULL effects, got %p\n", effects); 1741 return; 1742 } 1743 for (i = 0; i < num_materials; i++) 1744 { 1745 int j; 1746 DWORD expected_num_defaults = ARRAY_SIZE(params) + (materials[i].pTextureFilename ? 1 : 0); 1747 1748 ok_(__FILE__,line)(expected_num_defaults == effects[i].NumDefaults, 1749 "effect[%u] NumDefaults: Expected %u, got %u\n", i, 1750 expected_num_defaults, effects[i].NumDefaults); 1751 for (j = 0; j < min(ARRAY_SIZE(params), effects[i].NumDefaults); j++) 1752 { 1753 int k; 1754 D3DXEFFECTDEFAULT *got_param = &effects[i].pDefaults[j]; 1755 ok_(__FILE__,line)(!strcmp(params[j].name, got_param->pParamName), 1756 "effect[%u].pDefaults[%u].pParamName: Expected '%s', got '%s'\n", i, j, 1757 params[j].name, got_param->pParamName); 1758 ok_(__FILE__,line)(D3DXEDT_FLOATS == got_param->Type, 1759 "effect[%u].pDefaults[%u].Type: Expected %u, got %u\n", i, j, 1760 D3DXEDT_FLOATS, got_param->Type); 1761 ok_(__FILE__,line)(params[j].num_bytes == got_param->NumBytes, 1762 "effect[%u].pDefaults[%u].NumBytes: Expected %u, got %u\n", i, j, 1763 params[j].num_bytes, got_param->NumBytes); 1764 for (k = 0; k < min(params[j].num_bytes, got_param->NumBytes) / 4; k++) 1765 { 1766 FLOAT expected = ((FLOAT*)((BYTE*)&materials[i] + params[j].value_offset))[k]; 1767 FLOAT got = ((FLOAT*)got_param->pValue)[k]; 1768 ok_(__FILE__,line)(compare(expected, got), 1769 "effect[%u].pDefaults[%u] float value %u: Expected %g, got %g\n", i, j, k, expected, got); 1770 } 1771 } 1772 if (effects[i].NumDefaults > ARRAY_SIZE(params)) { 1773 D3DXEFFECTDEFAULT *got_param = &effects[i].pDefaults[j]; 1774 static const char *expected_name = "Texture0@Name"; 1775 1776 ok_(__FILE__,line)(!strcmp(expected_name, got_param->pParamName), 1777 "effect[%u].pDefaults[%u].pParamName: Expected '%s', got '%s'\n", i, j, 1778 expected_name, got_param->pParamName); 1779 ok_(__FILE__,line)(D3DXEDT_STRING == got_param->Type, 1780 "effect[%u].pDefaults[%u].Type: Expected %u, got %u\n", i, j, 1781 D3DXEDT_STRING, got_param->Type); 1782 if (materials[i].pTextureFilename) { 1783 ok_(__FILE__,line)(strlen(materials[i].pTextureFilename) + 1 == got_param->NumBytes, 1784 "effect[%u] texture filename length: Expected %u, got %u\n", i, 1785 (DWORD)strlen(materials[i].pTextureFilename) + 1, got_param->NumBytes); 1786 ok_(__FILE__,line)(!strcmp(materials[i].pTextureFilename, got_param->pValue), 1787 "effect[%u] texture filename: Expected '%s', got '%s'\n", i, 1788 materials[i].pTextureFilename, (char*)got_param->pValue); 1789 } 1790 } 1791 } 1792 } 1793 1794 static char *strdupA(const char *p) 1795 { 1796 char *ret; 1797 if (!p) return NULL; 1798 ret = HeapAlloc(GetProcessHeap(), 0, strlen(p) + 1); 1799 if (ret) strcpy(ret, p); 1800 return ret; 1801 } 1802 1803 static HRESULT CALLBACK ID3DXAllocateHierarchyImpl_DestroyFrame(ID3DXAllocateHierarchy *iface, LPD3DXFRAME frame) 1804 { 1805 TRACECALLBACK("ID3DXAllocateHierarchyImpl_DestroyFrame(%p, %p)\n", iface, frame); 1806 if (frame) { 1807 HeapFree(GetProcessHeap(), 0, frame->Name); 1808 HeapFree(GetProcessHeap(), 0, frame); 1809 } 1810 return D3D_OK; 1811 } 1812 1813 static HRESULT CALLBACK ID3DXAllocateHierarchyImpl_CreateFrame(ID3DXAllocateHierarchy *iface, 1814 const char *name, D3DXFRAME **new_frame) 1815 { 1816 D3DXFRAME *frame; 1817 1818 TRACECALLBACK("ID3DXAllocateHierarchyImpl_CreateFrame(%p, '%s', %p)\n", iface, name, new_frame); 1819 frame = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*frame)); 1820 if (!frame) 1821 return E_OUTOFMEMORY; 1822 if (name) { 1823 frame->Name = strdupA(name); 1824 if (!frame->Name) { 1825 HeapFree(GetProcessHeap(), 0, frame); 1826 return E_OUTOFMEMORY; 1827 } 1828 } 1829 *new_frame = frame; 1830 return D3D_OK; 1831 } 1832 1833 static HRESULT destroy_mesh_container(LPD3DXMESHCONTAINER mesh_container) 1834 { 1835 int i; 1836 1837 if (!mesh_container) 1838 return D3D_OK; 1839 HeapFree(GetProcessHeap(), 0, mesh_container->Name); 1840 if (U(mesh_container->MeshData).pMesh) 1841 IUnknown_Release(U(mesh_container->MeshData).pMesh); 1842 if (mesh_container->pMaterials) { 1843 for (i = 0; i < mesh_container->NumMaterials; i++) 1844 HeapFree(GetProcessHeap(), 0, mesh_container->pMaterials[i].pTextureFilename); 1845 HeapFree(GetProcessHeap(), 0, mesh_container->pMaterials); 1846 } 1847 if (mesh_container->pEffects) { 1848 for (i = 0; i < mesh_container->NumMaterials; i++) { 1849 HeapFree(GetProcessHeap(), 0, mesh_container->pEffects[i].pEffectFilename); 1850 if (mesh_container->pEffects[i].pDefaults) { 1851 int j; 1852 for (j = 0; j < mesh_container->pEffects[i].NumDefaults; j++) { 1853 HeapFree(GetProcessHeap(), 0, mesh_container->pEffects[i].pDefaults[j].pParamName); 1854 HeapFree(GetProcessHeap(), 0, mesh_container->pEffects[i].pDefaults[j].pValue); 1855 } 1856 HeapFree(GetProcessHeap(), 0, mesh_container->pEffects[i].pDefaults); 1857 } 1858 } 1859 HeapFree(GetProcessHeap(), 0, mesh_container->pEffects); 1860 } 1861 HeapFree(GetProcessHeap(), 0, mesh_container->pAdjacency); 1862 if (mesh_container->pSkinInfo) 1863 IUnknown_Release(mesh_container->pSkinInfo); 1864 HeapFree(GetProcessHeap(), 0, mesh_container); 1865 return D3D_OK; 1866 } 1867 1868 static HRESULT CALLBACK ID3DXAllocateHierarchyImpl_DestroyMeshContainer(ID3DXAllocateHierarchy *iface, LPD3DXMESHCONTAINER mesh_container) 1869 { 1870 TRACECALLBACK("ID3DXAllocateHierarchyImpl_DestroyMeshContainer(%p, %p)\n", iface, mesh_container); 1871 return destroy_mesh_container(mesh_container); 1872 } 1873 1874 static HRESULT CALLBACK ID3DXAllocateHierarchyImpl_CreateMeshContainer(ID3DXAllocateHierarchy *iface, 1875 const char *name, const D3DXMESHDATA *mesh_data, const D3DXMATERIAL *materials, 1876 const D3DXEFFECTINSTANCE *effects, DWORD num_materials, const DWORD *adjacency, 1877 ID3DXSkinInfo *skin_info, D3DXMESHCONTAINER **new_mesh_container) 1878 { 1879 LPD3DXMESHCONTAINER mesh_container = NULL; 1880 int i; 1881 1882 TRACECALLBACK("ID3DXAllocateHierarchyImpl_CreateMeshContainer(%p, '%s', %u, %p, %p, %p, %d, %p, %p, %p)\n", 1883 iface, name, mesh_data->Type, U(*mesh_data).pMesh, materials, effects, 1884 num_materials, adjacency, skin_info, *new_mesh_container); 1885 1886 mesh_container = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*mesh_container)); 1887 if (!mesh_container) 1888 return E_OUTOFMEMORY; 1889 1890 if (name) { 1891 mesh_container->Name = strdupA(name); 1892 if (!mesh_container->Name) 1893 goto error; 1894 } 1895 1896 mesh_container->NumMaterials = num_materials; 1897 if (num_materials) { 1898 mesh_container->pMaterials = HeapAlloc(GetProcessHeap(), 0, num_materials * sizeof(*materials)); 1899 if (!mesh_container->pMaterials) 1900 goto error; 1901 1902 memcpy(mesh_container->pMaterials, materials, num_materials * sizeof(*materials)); 1903 for (i = 0; i < num_materials; i++) 1904 mesh_container->pMaterials[i].pTextureFilename = NULL; 1905 for (i = 0; i < num_materials; i++) { 1906 if (materials[i].pTextureFilename) { 1907 mesh_container->pMaterials[i].pTextureFilename = strdupA(materials[i].pTextureFilename); 1908 if (!mesh_container->pMaterials[i].pTextureFilename) 1909 goto error; 1910 } 1911 } 1912 1913 mesh_container->pEffects = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, num_materials * sizeof(*effects)); 1914 if (!mesh_container->pEffects) 1915 goto error; 1916 for (i = 0; i < num_materials; i++) { 1917 int j; 1918 const D3DXEFFECTINSTANCE *effect_src = &effects[i]; 1919 D3DXEFFECTINSTANCE *effect_dest = &mesh_container->pEffects[i]; 1920 1921 if (effect_src->pEffectFilename) { 1922 effect_dest->pEffectFilename = strdupA(effect_src->pEffectFilename); 1923 if (!effect_dest->pEffectFilename) 1924 goto error; 1925 } 1926 effect_dest->pDefaults = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 1927 effect_src->NumDefaults * sizeof(*effect_src->pDefaults)); 1928 if (!effect_dest->pDefaults) 1929 goto error; 1930 effect_dest->NumDefaults = effect_src->NumDefaults; 1931 for (j = 0; j < effect_src->NumDefaults; j++) { 1932 const D3DXEFFECTDEFAULT *default_src = &effect_src->pDefaults[j]; 1933 D3DXEFFECTDEFAULT *default_dest = &effect_dest->pDefaults[j]; 1934 1935 if (default_src->pParamName) { 1936 default_dest->pParamName = strdupA(default_src->pParamName); 1937 if (!default_dest->pParamName) 1938 goto error; 1939 } 1940 default_dest->NumBytes = default_src->NumBytes; 1941 default_dest->Type = default_src->Type; 1942 default_dest->pValue = HeapAlloc(GetProcessHeap(), 0, default_src->NumBytes); 1943 memcpy(default_dest->pValue, default_src->pValue, default_src->NumBytes); 1944 } 1945 } 1946 } 1947 1948 ok(adjacency != NULL, "Expected non-NULL adjacency, got NULL\n"); 1949 if (adjacency) { 1950 if (mesh_data->Type == D3DXMESHTYPE_MESH || mesh_data->Type == D3DXMESHTYPE_PMESH) { 1951 ID3DXBaseMesh *basemesh = (ID3DXBaseMesh*)U(*mesh_data).pMesh; 1952 DWORD num_faces = basemesh->lpVtbl->GetNumFaces(basemesh); 1953 size_t size = num_faces * sizeof(DWORD) * 3; 1954 mesh_container->pAdjacency = HeapAlloc(GetProcessHeap(), 0, size); 1955 if (!mesh_container->pAdjacency) 1956 goto error; 1957 memcpy(mesh_container->pAdjacency, adjacency, size); 1958 } else { 1959 ok(mesh_data->Type == D3DXMESHTYPE_PATCHMESH, "Unknown mesh type %u\n", mesh_data->Type); 1960 if (mesh_data->Type == D3DXMESHTYPE_PATCHMESH) 1961 trace("FIXME: copying adjacency data for patch mesh not implemented\n"); 1962 } 1963 } 1964 1965 memcpy(&mesh_container->MeshData, mesh_data, sizeof(*mesh_data)); 1966 if (U(*mesh_data).pMesh) 1967 IUnknown_AddRef(U(*mesh_data).pMesh); 1968 if (skin_info) { 1969 mesh_container->pSkinInfo = skin_info; 1970 skin_info->lpVtbl->AddRef(skin_info); 1971 } 1972 *new_mesh_container = mesh_container; 1973 1974 return S_OK; 1975 error: 1976 destroy_mesh_container(mesh_container); 1977 return E_OUTOFMEMORY; 1978 } 1979 1980 static ID3DXAllocateHierarchyVtbl ID3DXAllocateHierarchyImpl_Vtbl = { 1981 ID3DXAllocateHierarchyImpl_CreateFrame, 1982 ID3DXAllocateHierarchyImpl_CreateMeshContainer, 1983 ID3DXAllocateHierarchyImpl_DestroyFrame, 1984 ID3DXAllocateHierarchyImpl_DestroyMeshContainer, 1985 }; 1986 static ID3DXAllocateHierarchy alloc_hier = { &ID3DXAllocateHierarchyImpl_Vtbl }; 1987 1988 #define test_LoadMeshFromX(device, xfile_str, vertex_array, fvf, index_array, materials_array, check_adjacency) \ 1989 test_LoadMeshFromX_(__LINE__, device, xfile_str, sizeof(xfile_str) - 1, vertex_array, ARRAY_SIZE(vertex_array), fvf, \ 1990 index_array, ARRAY_SIZE(index_array), sizeof(*index_array), materials_array, ARRAY_SIZE(materials_array), \ 1991 check_adjacency); 1992 static void test_LoadMeshFromX_(int line, IDirect3DDevice9 *device, const char *xfile_str, size_t xfile_strlen, 1993 const void *vertices, DWORD num_vertices, DWORD fvf, const void *indices, DWORD num_indices, size_t index_size, 1994 const D3DXMATERIAL *expected_materials, DWORD expected_num_materials, BOOL check_adjacency) 1995 { 1996 HRESULT hr; 1997 ID3DXBuffer *materials = NULL; 1998 ID3DXBuffer *effects = NULL; 1999 ID3DXBuffer *adjacency = NULL; 2000 ID3DXMesh *mesh = NULL; 2001 DWORD num_materials = 0; 2002 2003 /* Adjacency is not checked when the X file contains multiple meshes, 2004 * since calling GenerateAdjacency on the merged mesh is not equivalent 2005 * to calling GenerateAdjacency on the individual meshes and then merging 2006 * the adjacency data. */ 2007 hr = D3DXLoadMeshFromXInMemory(xfile_str, xfile_strlen, D3DXMESH_MANAGED, device, 2008 check_adjacency ? &adjacency : NULL, &materials, &effects, &num_materials, &mesh); 2009 ok_(__FILE__,line)(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 2010 if (SUCCEEDED(hr)) { 2011 D3DXMATERIAL *materials_ptr = materials ? ID3DXBuffer_GetBufferPointer(materials) : NULL; 2012 D3DXEFFECTINSTANCE *effects_ptr = effects ? ID3DXBuffer_GetBufferPointer(effects) : NULL; 2013 DWORD *adjacency_ptr = check_adjacency ? ID3DXBuffer_GetBufferPointer(adjacency) : NULL; 2014 2015 check_vertex_buffer_(line, mesh, vertices, num_vertices, fvf); 2016 check_index_buffer_(line, mesh, indices, num_indices, index_size); 2017 check_materials_(line, materials_ptr, num_materials, expected_materials, expected_num_materials); 2018 check_generated_effects_(line, materials_ptr, num_materials, effects_ptr); 2019 if (check_adjacency) 2020 check_generated_adjacency_(line, mesh, adjacency_ptr, 0.0f); 2021 2022 if (materials) ID3DXBuffer_Release(materials); 2023 if (effects) ID3DXBuffer_Release(effects); 2024 if (adjacency) ID3DXBuffer_Release(adjacency); 2025 IUnknown_Release(mesh); 2026 } 2027 } 2028 2029 static void D3DXLoadMeshTest(void) 2030 { 2031 static const char empty_xfile[] = "xof 0303txt 0032"; 2032 /*________________________*/ 2033 static const char simple_xfile[] = 2034 "xof 0303txt 0032" 2035 "Mesh {" 2036 "3;" 2037 "0.0; 0.0; 0.0;," 2038 "0.0; 1.0; 0.0;," 2039 "1.0; 1.0; 0.0;;" 2040 "1;" 2041 "3; 0, 1, 2;;" 2042 "}"; 2043 static const WORD simple_index_buffer[] = {0, 1, 2}; 2044 static const D3DXVECTOR3 simple_vertex_buffer[] = { 2045 {0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {1.0, 1.0, 0.0} 2046 }; 2047 const DWORD simple_fvf = D3DFVF_XYZ; 2048 static const char framed_xfile[] = 2049 "xof 0303txt 0032" 2050 "Frame {" 2051 "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;; }" 2052 "FrameTransformMatrix {" /* translation (0.0, 0.0, 2.0) */ 2053 "1.0, 0.0, 0.0, 0.0," 2054 "0.0, 1.0, 0.0, 0.0," 2055 "0.0, 0.0, 1.0, 0.0," 2056 "0.0, 0.0, 2.0, 1.0;;" 2057 "}" 2058 "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;; }" 2059 "FrameTransformMatrix {" /* translation (0.0, 0.0, 3.0) */ 2060 "1.0, 0.0, 0.0, 0.0," 2061 "0.0, 1.0, 0.0, 0.0," 2062 "0.0, 0.0, 1.0, 0.0," 2063 "0.0, 0.0, 3.0, 1.0;;" 2064 "}" 2065 "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;; }" 2066 "}"; 2067 static const WORD framed_index_buffer[] = { 0, 1, 2 }; 2068 static const D3DXVECTOR3 framed_vertex_buffers[3][3] = { 2069 {{0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {1.0, 1.0, 0.0}}, 2070 {{0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {2.0, 1.0, 0.0}}, 2071 {{0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {3.0, 1.0, 0.0}}, 2072 }; 2073 static const WORD merged_index_buffer[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 }; 2074 /* frame transforms accumulates for D3DXLoadMeshFromX */ 2075 static const D3DXVECTOR3 merged_vertex_buffer[] = { 2076 {0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {1.0, 1.0, 0.0}, 2077 {0.0, 0.0, 2.0}, {0.0, 1.0, 2.0}, {2.0, 1.0, 2.0}, 2078 {0.0, 0.0, 5.0}, {0.0, 1.0, 5.0}, {3.0, 1.0, 5.0}, 2079 }; 2080 const DWORD framed_fvf = D3DFVF_XYZ; 2081 /*________________________*/ 2082 static const char box_xfile[] = 2083 "xof 0303txt 0032" 2084 "Mesh {" 2085 "8;" /* DWORD nVertices; */ 2086 /* array Vector vertices[nVertices]; */ 2087 "0.0; 0.0; 0.0;," 2088 "0.0; 0.0; 1.0;," 2089 "0.0; 1.0; 0.0;," 2090 "0.0; 1.0; 1.0;," 2091 "1.0; 0.0; 0.0;," 2092 "1.0; 0.0; 1.0;," 2093 "1.0; 1.0; 0.0;," 2094 "1.0; 1.0; 1.0;;" 2095 "6;" /* DWORD nFaces; */ 2096 /* array MeshFace faces[nFaces]; */ 2097 "4; 0, 1, 3, 2;," /* (left side) */ 2098 "4; 2, 3, 7, 6;," /* (top side) */ 2099 "4; 6, 7, 5, 4;," /* (right side) */ 2100 "4; 1, 0, 4, 5;," /* (bottom side) */ 2101 "4; 1, 5, 7, 3;," /* (back side) */ 2102 "4; 0, 2, 6, 4;;" /* (front side) */ 2103 "MeshNormals {" 2104 "6;" /* DWORD nNormals; */ 2105 /* array Vector normals[nNormals]; */ 2106 "-1.0; 0.0; 0.0;," 2107 "0.0; 1.0; 0.0;," 2108 "1.0; 0.0; 0.0;," 2109 "0.0; -1.0; 0.0;," 2110 "0.0; 0.0; 1.0;," 2111 "0.0; 0.0; -1.0;;" 2112 "6;" /* DWORD nFaceNormals; */ 2113 /* array MeshFace faceNormals[nFaceNormals]; */ 2114 "4; 0, 0, 0, 0;," 2115 "4; 1, 1, 1, 1;," 2116 "4; 2, 2, 2, 2;," 2117 "4; 3, 3, 3, 3;," 2118 "4; 4, 4, 4, 4;," 2119 "4; 5, 5, 5, 5;;" 2120 "}" 2121 "MeshMaterialList materials {" 2122 "2;" /* DWORD nMaterials; */ 2123 "6;" /* DWORD nFaceIndexes; */ 2124 /* array DWORD faceIndexes[nFaceIndexes]; */ 2125 "0, 0, 0, 1, 1, 1;;" 2126 "Material {" 2127 /* ColorRGBA faceColor; */ 2128 "0.0; 0.0; 1.0; 1.0;;" 2129 /* FLOAT power; */ 2130 "0.5;" 2131 /* ColorRGB specularColor; */ 2132 "1.0; 1.0; 1.0;;" 2133 /* ColorRGB emissiveColor; */ 2134 "0.0; 0.0; 0.0;;" 2135 "}" 2136 "Material {" 2137 /* ColorRGBA faceColor; */ 2138 "1.0; 1.0; 1.0; 1.0;;" 2139 /* FLOAT power; */ 2140 "1.0;" 2141 /* ColorRGB specularColor; */ 2142 "1.0; 1.0; 1.0;;" 2143 /* ColorRGB emissiveColor; */ 2144 "0.0; 0.0; 0.0;;" 2145 "TextureFilename { \"texture.jpg\"; }" 2146 "}" 2147 "}" 2148 "MeshVertexColors {" 2149 "8;" /* DWORD nVertexColors; */ 2150 /* array IndexedColor vertexColors[nVertexColors]; */ 2151 "0; 0.0; 0.0; 0.0; 0.0;;" 2152 "1; 0.0; 0.0; 1.0; 0.1;;" 2153 "2; 0.0; 1.0; 0.0; 0.2;;" 2154 "3; 0.0; 1.0; 1.0; 0.3;;" 2155 "4; 1.0; 0.0; 0.0; 0.4;;" 2156 "5; 1.0; 0.0; 1.0; 0.5;;" 2157 "6; 1.0; 1.0; 0.0; 0.6;;" 2158 "7; 1.0; 1.0; 1.0; 0.7;;" 2159 "}" 2160 "MeshTextureCoords {" 2161 "8;" /* DWORD nTextureCoords; */ 2162 /* array Coords2d textureCoords[nTextureCoords]; */ 2163 "0.0; 1.0;," 2164 "1.0; 1.0;," 2165 "0.0; 0.0;," 2166 "1.0; 0.0;," 2167 "1.0; 1.0;," 2168 "0.0; 1.0;," 2169 "1.0; 0.0;," 2170 "0.0; 0.0;;" 2171 "}" 2172 "}"; 2173 static const WORD box_index_buffer[] = { 2174 0, 1, 3, 2175 0, 3, 2, 2176 8, 9, 7, 2177 8, 7, 6, 2178 10, 11, 5, 2179 10, 5, 4, 2180 12, 13, 14, 2181 12, 14, 15, 2182 16, 17, 18, 2183 16, 18, 19, 2184 20, 21, 22, 2185 20, 22, 23, 2186 }; 2187 static const struct { 2188 D3DXVECTOR3 position; 2189 D3DXVECTOR3 normal; 2190 D3DCOLOR diffuse; 2191 D3DXVECTOR2 tex_coords; 2192 } box_vertex_buffer[] = { 2193 {{0.0, 0.0, 0.0}, {-1.0, 0.0, 0.0}, 0x00000000, {0.0, 1.0}}, 2194 {{0.0, 0.0, 1.0}, {-1.0, 0.0, 0.0}, 0x1a0000ff, {1.0, 1.0}}, 2195 {{0.0, 1.0, 0.0}, {-1.0, 0.0, 0.0}, 0x3300ff00, {0.0, 0.0}}, 2196 {{0.0, 1.0, 1.0}, {-1.0, 0.0, 0.0}, 0x4d00ffff, {1.0, 0.0}}, 2197 {{1.0, 0.0, 0.0}, {1.0, 0.0, 0.0}, 0x66ff0000, {1.0, 1.0}}, 2198 {{1.0, 0.0, 1.0}, {1.0, 0.0, 0.0}, 0x80ff00ff, {0.0, 1.0}}, 2199 {{1.0, 1.0, 0.0}, {0.0, 1.0, 0.0}, 0x99ffff00, {1.0, 0.0}}, 2200 {{1.0, 1.0, 1.0}, {0.0, 1.0, 0.0}, 0xb3ffffff, {0.0, 0.0}}, 2201 {{0.0, 1.0, 0.0}, {0.0, 1.0, 0.0}, 0x3300ff00, {0.0, 0.0}}, 2202 {{0.0, 1.0, 1.0}, {0.0, 1.0, 0.0}, 0x4d00ffff, {1.0, 0.0}}, 2203 {{1.0, 1.0, 0.0}, {1.0, 0.0, 0.0}, 0x99ffff00, {1.0, 0.0}}, 2204 {{1.0, 1.0, 1.0}, {1.0, 0.0, 0.0}, 0xb3ffffff, {0.0, 0.0}}, 2205 {{0.0, 0.0, 1.0}, {0.0, -1.0, 0.0}, 0x1a0000ff, {1.0, 1.0}}, 2206 {{0.0, 0.0, 0.0}, {0.0, -1.0, 0.0}, 0x00000000, {0.0, 1.0}}, 2207 {{1.0, 0.0, 0.0}, {0.0, -1.0, 0.0}, 0x66ff0000, {1.0, 1.0}}, 2208 {{1.0, 0.0, 1.0}, {0.0, -1.0, 0.0}, 0x80ff00ff, {0.0, 1.0}}, 2209 {{0.0, 0.0, 1.0}, {0.0, 0.0, 1.0}, 0x1a0000ff, {1.0, 1.0}}, 2210 {{1.0, 0.0, 1.0}, {0.0, 0.0, 1.0}, 0x80ff00ff, {0.0, 1.0}}, 2211 {{1.0, 1.0, 1.0}, {0.0, 0.0, 1.0}, 0xb3ffffff, {0.0, 0.0}}, 2212 {{0.0, 1.0, 1.0}, {0.0, 0.0, 1.0}, 0x4d00ffff, {1.0, 0.0}}, 2213 {{0.0, 0.0, 0.0}, {0.0, 0.0, -1.0}, 0x00000000, {0.0, 1.0}}, 2214 {{0.0, 1.0, 0.0}, {0.0, 0.0, -1.0}, 0x3300ff00, {0.0, 0.0}}, 2215 {{1.0, 1.0, 0.0}, {0.0, 0.0, -1.0}, 0x99ffff00, {1.0, 0.0}}, 2216 {{1.0, 0.0, 0.0}, {0.0, 0.0, -1.0}, 0x66ff0000, {1.0, 1.0}}, 2217 }; 2218 static const D3DXMATERIAL box_materials[] = { 2219 { 2220 { 2221 {0.0, 0.0, 1.0, 1.0}, /* Diffuse */ 2222 {0.0, 0.0, 0.0, 1.0}, /* Ambient */ 2223 {1.0, 1.0, 1.0, 1.0}, /* Specular */ 2224 {0.0, 0.0, 0.0, 1.0}, /* Emissive */ 2225 0.5, /* Power */ 2226 }, 2227 NULL, /* pTextureFilename */ 2228 }, 2229 { 2230 { 2231 {1.0, 1.0, 1.0, 1.0}, /* Diffuse */ 2232 {0.0, 0.0, 0.0, 1.0}, /* Ambient */ 2233 {1.0, 1.0, 1.0, 1.0}, /* Specular */ 2234 {0.0, 0.0, 0.0, 1.0}, /* Emissive */ 2235 1.0, /* Power */ 2236 }, 2237 (char *)"texture.jpg", /* pTextureFilename */ 2238 }, 2239 }; 2240 static const char box_anim_xfile[] = 2241 "xof 0303txt 0032" 2242 "Mesh CubeMesh {" 2243 "8;" /* DWORD nVertices; */ 2244 /* array Vector vertices[nVertices]; */ 2245 "0.0; 0.0; 0.0;," 2246 "0.0; 0.0; 1.0;," 2247 "0.0; 1.0; 0.0;," 2248 "0.0; 1.0; 1.0;," 2249 "1.0; 0.0; 0.0;," 2250 "1.0; 0.0; 1.0;," 2251 "1.0; 1.0; 0.0;," 2252 "1.0; 1.0; 1.0;;" 2253 "6;" /* DWORD nFaces; */ 2254 /* array MeshFace faces[nFaces]; */ 2255 "4; 0, 1, 3, 2;," /* left side */ 2256 "4; 2, 3, 7, 6;," /* top side */ 2257 "4; 6, 7, 5, 4;," /* right side */ 2258 "4; 1, 0, 4, 5;," /* bottom side */ 2259 "4; 1, 5, 7, 3;," /* back side */ 2260 "4; 0, 2, 6, 4;;" /* front side */ 2261 "MeshNormals {" 2262 "6;" /* DWORD nNormals; */ 2263 /* array Vector normals[nNormals]; */ 2264 "-1.0; 0.0; 0.0;," 2265 "0.0; 1.0; 0.0;," 2266 "1.0; 0.0; 0.0;," 2267 "0.0; -1.0; 0.0;," 2268 "0.0; 0.0; 1.0;," 2269 "0.0; 0.0; -1.0;;" 2270 "6;" /* DWORD nFaceNormals; */ 2271 /* array MeshFace faceNormals[nFaceNormals]; */ 2272 "4; 0, 0, 0, 0;," 2273 "4; 1, 1, 1, 1;," 2274 "4; 2, 2, 2, 2;," 2275 "4; 3, 3, 3, 3;," 2276 "4; 4, 4, 4, 4;," 2277 "4; 5, 5, 5, 5;;" 2278 "}" 2279 "MeshMaterialList materials {" 2280 "2;" /* DWORD nMaterials; */ 2281 "6;" /* DWORD nFaceIndexes; */ 2282 /* array DWORD faceIndexes[nFaceIndexes]; */ 2283 "0, 0, 0, 1, 1, 1;;" 2284 "Material {" 2285 /* ColorRGBA faceColor; */ 2286 "0.0; 0.0; 1.0; 1.0;;" 2287 /* FLOAT power; */ 2288 "0.5;" 2289 /* ColorRGB specularColor; */ 2290 "1.0; 1.0; 1.0;;" 2291 /* ColorRGB emissiveColor; */ 2292 "0.0; 0.0; 0.0;;" 2293 "}" 2294 "Material {" 2295 /* ColorRGBA faceColor; */ 2296 "1.0; 1.0; 1.0; 1.0;;" 2297 /* FLOAT power; */ 2298 "1.0;" 2299 /* ColorRGB specularColor; */ 2300 "1.0; 1.0; 1.0;;" 2301 /* ColorRGB emissiveColor; */ 2302 "0.0; 0.0; 0.0;;" 2303 "TextureFilename { \"texture.jpg\"; }" 2304 "}" 2305 "}" 2306 "MeshVertexColors {" 2307 "8;" /* DWORD nVertexColors; */ 2308 /* array IndexedColor vertexColors[nVertexColors]; */ 2309 "0; 0.0; 0.0; 0.0; 0.0;;" 2310 "1; 0.0; 0.0; 1.0; 0.1;;" 2311 "2; 0.0; 1.0; 0.0; 0.2;;" 2312 "3; 0.0; 1.0; 1.0; 0.3;;" 2313 "4; 1.0; 0.0; 0.0; 0.4;;" 2314 "5; 1.0; 0.0; 1.0; 0.5;;" 2315 "6; 1.0; 1.0; 0.0; 0.6;;" 2316 "7; 1.0; 1.0; 1.0; 0.7;;" 2317 "}" 2318 "MeshTextureCoords {" 2319 "8;" /* DWORD nTextureCoords; */ 2320 /* array Coords2d textureCoords[nTextureCoords]; */ 2321 "0.0; 1.0;," 2322 "1.0; 1.0;," 2323 "0.0; 0.0;," 2324 "1.0; 0.0;," 2325 "1.0; 1.0;," 2326 "0.0; 1.0;," 2327 "1.0; 0.0;," 2328 "0.0; 0.0;;" 2329 "}" 2330 "}" 2331 "Frame CubeFrame {" 2332 "FrameTransformMatrix {" 2333 /* Matrix4x4 frameMatrix; */ 2334 "1.0, 0.0, 0.0, 0.0," 2335 "0.0, 1.0, 0.0, 0.0," 2336 "0.0, 0.0, 1.0, 0.0," 2337 "0.0, 0.0, 0.0, 1.0;;" 2338 "}" 2339 "{CubeMesh}" 2340 "}" 2341 "AnimationSet AnimationSet0 {" 2342 "Animation Animation0 {" 2343 "{CubeFrame}" 2344 "AnimationKey {" 2345 "2;" /* DWORD keyType; */ 2346 "9;" /* DWORD nKeys; */ 2347 /* array TimedFloatKeys keys[nKeys]; */ 2348 "10; 3; -100.0, 0.0, 0.0;;," 2349 "20; 3; -75.0, 0.0, 0.0;;," 2350 "30; 3; -50.0, 0.0, 0.0;;," 2351 "40; 3; -25.5, 0.0, 0.0;;," 2352 "50; 3; 0.0, 0.0, 0.0;;," 2353 "60; 3; 25.5, 0.0, 0.0;;," 2354 "70; 3; 50.0, 0.0, 0.0;;," 2355 "80; 3; 75.5, 0.0, 0.0;;," 2356 "90; 3; 100.0, 0.0, 0.0;;;" 2357 "}" 2358 "}" 2359 "}"; 2360 2361 const DWORD box_fvf = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_TEX1; 2362 /*________________________*/ 2363 static const D3DXMATERIAL default_materials[] = { 2364 { 2365 { 2366 {0.5, 0.5, 0.5, 0.0}, /* Diffuse */ 2367 {0.0, 0.0, 0.0, 0.0}, /* Ambient */ 2368 {0.5, 0.5, 0.5, 0.0}, /* Specular */ 2369 {0.0, 0.0, 0.0, 0.0}, /* Emissive */ 2370 0.0, /* Power */ 2371 }, 2372 NULL, /* pTextureFilename */ 2373 } 2374 }; 2375 HRESULT hr; 2376 IDirect3DDevice9 *device = NULL; 2377 ID3DXMesh *mesh = NULL; 2378 D3DXFRAME *frame_hier = NULL; 2379 D3DXMATRIX transform; 2380 struct test_context *test_context; 2381 ID3DXAnimationController *controller; 2382 2383 if (!(test_context = new_test_context())) 2384 { 2385 skip("Couldn't create test context\n"); 2386 return; 2387 } 2388 device = test_context->device; 2389 2390 hr = D3DXLoadMeshHierarchyFromXInMemory(NULL, sizeof(simple_xfile) - 1, 2391 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL); 2392 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 2393 2394 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, 0, 2395 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL); 2396 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 2397 2398 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1, 2399 D3DXMESH_MANAGED, NULL, &alloc_hier, NULL, &frame_hier, NULL); 2400 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 2401 2402 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1, 2403 D3DXMESH_MANAGED, device, NULL, NULL, &frame_hier, NULL); 2404 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 2405 2406 hr = D3DXLoadMeshHierarchyFromXInMemory(empty_xfile, sizeof(empty_xfile) - 1, 2407 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL); 2408 ok(hr == E_FAIL, "Expected E_FAIL, got %#x\n", hr); 2409 2410 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1, 2411 D3DXMESH_MANAGED, device, &alloc_hier, NULL, NULL, NULL); 2412 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 2413 2414 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1, 2415 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL); 2416 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 2417 if (SUCCEEDED(hr)) { 2418 D3DXMESHCONTAINER *container = frame_hier->pMeshContainer; 2419 2420 ok(frame_hier->Name == NULL, "Expected NULL, got '%s'\n", frame_hier->Name); 2421 D3DXMatrixIdentity(&transform); 2422 check_matrix(&frame_hier->TransformationMatrix, &transform); 2423 2424 ok(!strcmp(container->Name, ""), "Expected '', got '%s'\n", container->Name); 2425 ok(container->MeshData.Type == D3DXMESHTYPE_MESH, "Expected %d, got %d\n", 2426 D3DXMESHTYPE_MESH, container->MeshData.Type); 2427 mesh = U(container->MeshData).pMesh; 2428 check_vertex_buffer(mesh, simple_vertex_buffer, ARRAY_SIZE(simple_vertex_buffer), simple_fvf); 2429 check_index_buffer(mesh, simple_index_buffer, ARRAY_SIZE(simple_index_buffer), sizeof(*simple_index_buffer)); 2430 check_materials(container->pMaterials, container->NumMaterials, NULL, 0); 2431 check_generated_effects(container->pMaterials, container->NumMaterials, container->pEffects); 2432 check_generated_adjacency(mesh, container->pAdjacency, 0.0f); 2433 hr = D3DXFrameDestroy(frame_hier, &alloc_hier); 2434 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 2435 frame_hier = NULL; 2436 } 2437 2438 controller = (ID3DXAnimationController *)0xdeadbeef; 2439 hr = D3DXLoadMeshHierarchyFromXInMemory(box_anim_xfile, sizeof(box_anim_xfile) - 1, 2440 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, &controller); 2441 todo_wine ok(hr == D3D_OK, "Expected D3D_OK, got %#x.\n", hr); 2442 if (SUCCEEDED(hr)) 2443 { 2444 ok(controller != NULL, "Animation Controller NULL.\n"); 2445 2446 hr = D3DXFrameDestroy(frame_hier, &alloc_hier); 2447 ok(hr == D3D_OK, "Expected D3D_OK, got %#x.\n", hr); 2448 if (controller) 2449 controller->lpVtbl->Release(controller); 2450 2451 frame_hier = NULL; 2452 } 2453 2454 controller = (ID3DXAnimationController *)0xdeadbeef; 2455 hr = D3DXLoadMeshHierarchyFromXInMemory(box_xfile, sizeof(box_xfile) - 1, 2456 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, &controller); 2457 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 2458 if (SUCCEEDED(hr)) 2459 { 2460 D3DXMESHCONTAINER *container = frame_hier->pMeshContainer; 2461 2462 ok(!controller, "Animation Controller returned.\n"); 2463 ok(frame_hier->Name == NULL, "Expected NULL, got '%s'\n", frame_hier->Name); 2464 D3DXMatrixIdentity(&transform); 2465 check_matrix(&frame_hier->TransformationMatrix, &transform); 2466 2467 ok(!strcmp(container->Name, ""), "Expected '', got '%s'\n", container->Name); 2468 ok(container->MeshData.Type == D3DXMESHTYPE_MESH, "Expected %d, got %d\n", 2469 D3DXMESHTYPE_MESH, container->MeshData.Type); 2470 mesh = U(container->MeshData).pMesh; 2471 check_vertex_buffer(mesh, box_vertex_buffer, ARRAY_SIZE(box_vertex_buffer), box_fvf); 2472 check_index_buffer(mesh, box_index_buffer, ARRAY_SIZE(box_index_buffer), sizeof(*box_index_buffer)); 2473 check_materials(container->pMaterials, container->NumMaterials, box_materials, ARRAY_SIZE(box_materials)); 2474 check_generated_effects(container->pMaterials, container->NumMaterials, container->pEffects); 2475 check_generated_adjacency(mesh, container->pAdjacency, 0.0f); 2476 hr = D3DXFrameDestroy(frame_hier, &alloc_hier); 2477 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 2478 frame_hier = NULL; 2479 } 2480 2481 hr = D3DXLoadMeshHierarchyFromXInMemory(framed_xfile, sizeof(framed_xfile) - 1, 2482 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL); 2483 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 2484 if (SUCCEEDED(hr)) { 2485 D3DXMESHCONTAINER *container = frame_hier->pMeshContainer; 2486 int i; 2487 2488 ok(!strcmp(frame_hier->Name, ""), "Expected '', got '%s'\n", frame_hier->Name); 2489 /* last frame transform replaces the first */ 2490 D3DXMatrixIdentity(&transform); 2491 U(transform).m[3][2] = 3.0; 2492 check_matrix(&frame_hier->TransformationMatrix, &transform); 2493 2494 for (i = 0; i < 3; i++) { 2495 ok(!strcmp(container->Name, ""), "Expected '', got '%s'\n", container->Name); 2496 ok(container->MeshData.Type == D3DXMESHTYPE_MESH, "Expected %d, got %d\n", 2497 D3DXMESHTYPE_MESH, container->MeshData.Type); 2498 mesh = U(container->MeshData).pMesh; 2499 check_vertex_buffer(mesh, framed_vertex_buffers[i], ARRAY_SIZE(framed_vertex_buffers[0]), framed_fvf); 2500 check_index_buffer(mesh, framed_index_buffer, ARRAY_SIZE(framed_index_buffer), sizeof(*framed_index_buffer)); 2501 check_materials(container->pMaterials, container->NumMaterials, NULL, 0); 2502 check_generated_effects(container->pMaterials, container->NumMaterials, container->pEffects); 2503 check_generated_adjacency(mesh, container->pAdjacency, 0.0f); 2504 container = container->pNextMeshContainer; 2505 } 2506 ok(container == NULL, "Expected NULL, got %p\n", container); 2507 hr = D3DXFrameDestroy(frame_hier, &alloc_hier); 2508 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 2509 frame_hier = NULL; 2510 } 2511 2512 2513 hr = D3DXLoadMeshFromXInMemory(NULL, 0, D3DXMESH_MANAGED, 2514 device, NULL, NULL, NULL, NULL, &mesh); 2515 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 2516 2517 hr = D3DXLoadMeshFromXInMemory(NULL, sizeof(simple_xfile) - 1, D3DXMESH_MANAGED, 2518 device, NULL, NULL, NULL, NULL, &mesh); 2519 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 2520 2521 hr = D3DXLoadMeshFromXInMemory(simple_xfile, 0, D3DXMESH_MANAGED, 2522 device, NULL, NULL, NULL, NULL, &mesh); 2523 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 2524 2525 hr = D3DXLoadMeshFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1, D3DXMESH_MANAGED, 2526 device, NULL, NULL, NULL, NULL, NULL); 2527 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 2528 2529 hr = D3DXLoadMeshFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1, D3DXMESH_MANAGED, 2530 NULL, NULL, NULL, NULL, NULL, &mesh); 2531 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 2532 2533 hr = D3DXLoadMeshFromXInMemory(empty_xfile, sizeof(empty_xfile) - 1, D3DXMESH_MANAGED, 2534 device, NULL, NULL, NULL, NULL, &mesh); 2535 ok(hr == E_FAIL, "Expected E_FAIL, got %#x\n", hr); 2536 2537 hr = D3DXLoadMeshFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1, D3DXMESH_MANAGED, 2538 device, NULL, NULL, NULL, NULL, &mesh); 2539 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 2540 if (SUCCEEDED(hr)) 2541 IUnknown_Release(mesh); 2542 2543 test_LoadMeshFromX(device, simple_xfile, simple_vertex_buffer, simple_fvf, simple_index_buffer, default_materials, TRUE); 2544 test_LoadMeshFromX(device, box_xfile, box_vertex_buffer, box_fvf, box_index_buffer, box_materials, TRUE); 2545 test_LoadMeshFromX(device, framed_xfile, merged_vertex_buffer, framed_fvf, merged_index_buffer, default_materials, FALSE); 2546 2547 free_test_context(test_context); 2548 } 2549 2550 static ID3DXFileData *get_mesh_data(const char *memory, SIZE_T length) 2551 { 2552 D3DXF_FILELOADMEMORY source; 2553 ID3DXFileEnumObject *enumobj = NULL; 2554 ID3DXFileData *filedata = NULL; 2555 ID3DXFileData *ret = NULL; 2556 ID3DXFile *d3dxfile = NULL; 2557 SIZE_T i, nb_children; 2558 HRESULT hr; 2559 GUID guid; 2560 2561 hr = D3DXFileCreate(&d3dxfile); 2562 if (FAILED(hr)) return NULL; 2563 2564 hr = d3dxfile->lpVtbl->RegisterTemplates(d3dxfile, D3DRM_XTEMPLATES, D3DRM_XTEMPLATE_BYTES); 2565 if (FAILED(hr)) goto cleanup; 2566 2567 source.lpMemory = (void *)memory; 2568 source.dSize = length; 2569 2570 hr = d3dxfile->lpVtbl->CreateEnumObject(d3dxfile, &source, D3DXF_FILELOAD_FROMMEMORY, &enumobj); 2571 if (FAILED(hr)) goto cleanup; 2572 2573 hr = enumobj->lpVtbl->GetChildren(enumobj, &nb_children); 2574 if (FAILED(hr)) goto cleanup; 2575 2576 for (i = 0; i < nb_children; i++) 2577 { 2578 hr = enumobj->lpVtbl->GetChild(enumobj, i, &filedata); 2579 if (FAILED(hr)) goto cleanup; 2580 2581 hr = filedata->lpVtbl->GetType(filedata, &guid); 2582 if (SUCCEEDED(hr) && IsEqualGUID(&guid, &TID_D3DRMMesh)) 2583 { 2584 ret = filedata; 2585 break; 2586 } 2587 else 2588 filedata->lpVtbl->Release(filedata); 2589 } 2590 2591 cleanup: 2592 if (enumobj) enumobj->lpVtbl->Release(enumobj); 2593 if (d3dxfile) d3dxfile->lpVtbl->Release(d3dxfile); 2594 2595 return ret; 2596 } 2597 2598 static void D3DXLoadSkinMeshFromXofTest(void) 2599 { 2600 static const char simple_xfile[] = 2601 "xof 0303txt 0032" 2602 "Mesh {" 2603 "3;" 2604 "0.0; 0.0; 0.0;," 2605 "0.0; 1.0; 0.0;," 2606 "1.0; 1.0; 0.0;;" 2607 "1;" 2608 "3; 0, 1, 2;;" 2609 "}"; 2610 ID3DXBuffer *adjacency, *materials, *effects; 2611 D3DPRESENT_PARAMETERS d3dpp; 2612 IDirect3DDevice9 *device; 2613 ID3DXFileData *filedata; 2614 ID3DXSkinInfo *skininfo; 2615 ID3DXMesh *mesh; 2616 IDirect3D9 *d3d; 2617 DWORD mat_count; 2618 HRESULT hr; 2619 HWND hwnd; 2620 2621 if (!(hwnd = CreateWindowA("static", "d3dx9_test", WS_OVERLAPPEDWINDOW, 0, 0, 2622 640, 480, NULL, NULL, NULL, NULL))) 2623 { 2624 skip("Couldn't create application window\n"); 2625 return; 2626 } 2627 2628 d3d = Direct3DCreate9(D3D_SDK_VERSION); 2629 if (!d3d) 2630 { 2631 skip("Couldn't create IDirect3D9 object\n"); 2632 DestroyWindow(hwnd); 2633 return; 2634 } 2635 2636 ZeroMemory(&d3dpp, sizeof(d3dpp)); 2637 d3dpp.Windowed = TRUE; 2638 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; 2639 2640 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device); 2641 IDirect3D9_Release(d3d); 2642 if (FAILED(hr)) 2643 { 2644 skip("Failed to create IDirect3DDevice9 object %#x\n", hr); 2645 DestroyWindow(hwnd); 2646 return; 2647 } 2648 2649 filedata = get_mesh_data(simple_xfile, sizeof(simple_xfile) - 1); 2650 ok(filedata != NULL, "Failed to load mesh data\n"); 2651 2652 adjacency = materials = effects = NULL; 2653 skininfo = NULL; 2654 mesh = NULL; 2655 2656 hr = D3DXLoadSkinMeshFromXof(filedata, 0, device, &adjacency, &materials, &effects, &mat_count, &skininfo, &mesh); 2657 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); 2658 ok(skininfo != NULL, "Expected non-null skininfo\n"); 2659 2660 /* FIXME: Add additional tests for skininfo interface. */ 2661 2662 if (adjacency) adjacency->lpVtbl->Release(adjacency); 2663 if (materials) materials->lpVtbl->Release(materials); 2664 if (effects) effects->lpVtbl->Release(effects); 2665 if (skininfo) skininfo->lpVtbl->Release(skininfo); 2666 if (mesh) mesh->lpVtbl->Release(mesh); 2667 2668 filedata->lpVtbl->Release(filedata); 2669 IDirect3DDevice9_Release(device); 2670 DestroyWindow(hwnd); 2671 } 2672 2673 static BOOL compute_box(struct mesh *mesh, float width, float height, float depth) 2674 { 2675 unsigned int i, face; 2676 static const D3DXVECTOR3 unit_box[] = 2677 { 2678 {-1.0f, -1.0f, -1.0f}, {-1.0f, -1.0f, 1.0f}, {-1.0f, 1.0f, 1.0f}, {-1.0f, 1.0f, -1.0f}, 2679 {-1.0f, 1.0f, -1.0f}, {-1.0f, 1.0f, 1.0f}, { 1.0f, 1.0f, 1.0f}, { 1.0f, 1.0f, -1.0f}, 2680 { 1.0f, 1.0f, -1.0f}, { 1.0f, 1.0f, 1.0f}, { 1.0f, -1.0f, 1.0f}, { 1.0f, -1.0f, -1.0f}, 2681 {-1.0f, -1.0f, 1.0f}, {-1.0f, -1.0f, -1.0f}, { 1.0f, -1.0f, -1.0f}, { 1.0f, -1.0f, 1.0f}, 2682 {-1.0f, -1.0f, 1.0f}, { 1.0f, -1.0f, 1.0f}, { 1.0f, 1.0f, 1.0f}, {-1.0f, 1.0f, 1.0f}, 2683 {-1.0f, -1.0f, -1.0f}, {-1.0f, 1.0f, -1.0f}, { 1.0f, 1.0f, -1.0f}, { 1.0f, -1.0f, -1.0f} 2684 }; 2685 static const D3DXVECTOR3 normals[] = 2686 { 2687 {-1.0f, 0.0f, 0.0f}, { 0.0f, 1.0f, 0.0f}, { 1.0f, 0.0f, 0.0f}, 2688 { 0.0f, -1.0f, 0.0f}, { 0.0f, 0.0f, 1.0f}, { 0.0f, 0.0f, -1.0f} 2689 }; 2690 2691 if (!new_mesh(mesh, 24, 12)) 2692 { 2693 return FALSE; 2694 } 2695 2696 width /= 2.0f; 2697 height /= 2.0f; 2698 depth /= 2.0f; 2699 2700 for (i = 0; i < 24; i++) 2701 { 2702 mesh->vertices[i].position.x = width * unit_box[i].x; 2703 mesh->vertices[i].position.y = height * unit_box[i].y; 2704 mesh->vertices[i].position.z = depth * unit_box[i].z; 2705 mesh->vertices[i].normal.x = normals[i / 4].x; 2706 mesh->vertices[i].normal.y = normals[i / 4].y; 2707 mesh->vertices[i].normal.z = normals[i / 4].z; 2708 } 2709 2710 face = 0; 2711 for (i = 0; i < 12; i++) 2712 { 2713 mesh->faces[i][0] = face++; 2714 mesh->faces[i][1] = face++; 2715 mesh->faces[i][2] = (i % 2) ? face - 4 : face; 2716 } 2717 2718 return TRUE; 2719 } 2720 2721 static void test_box(IDirect3DDevice9 *device, float width, float height, float depth) 2722 { 2723 HRESULT hr; 2724 ID3DXMesh *box; 2725 struct mesh mesh; 2726 char name[256]; 2727 2728 hr = D3DXCreateBox(device, width, height, depth, &box, NULL); 2729 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); 2730 if (hr != D3D_OK) 2731 { 2732 skip("Couldn't create box\n"); 2733 return; 2734 } 2735 2736 if (!compute_box(&mesh, width, height, depth)) 2737 { 2738 skip("Couldn't create mesh\n"); 2739 box->lpVtbl->Release(box); 2740 return; 2741 } 2742 2743 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL; 2744 2745 sprintf(name, "box (%g, %g, %g)", width, height, depth); 2746 compare_mesh(name, box, &mesh); 2747 2748 free_mesh(&mesh); 2749 2750 box->lpVtbl->Release(box); 2751 } 2752 static void D3DXCreateBoxTest(void) 2753 { 2754 HRESULT hr; 2755 IDirect3DDevice9* device; 2756 ID3DXMesh* box; 2757 ID3DXBuffer* ppBuffer; 2758 DWORD *buffer; 2759 static const DWORD adjacency[36]= 2760 {6, 9, 1, 2, 10, 0, 2761 1, 9, 3, 4, 10, 2, 2762 3, 8, 5, 7, 11, 4, 2763 0, 11, 7, 5, 8, 6, 2764 7, 4, 9, 2, 0, 8, 2765 1, 3, 11, 5, 6, 10}; 2766 unsigned int i; 2767 struct test_context *test_context; 2768 2769 if (!(test_context = new_test_context())) 2770 { 2771 skip("Couldn't create test context\n"); 2772 return; 2773 } 2774 device = test_context->device; 2775 2776 hr = D3DXCreateBox(device,2.0f,20.0f,4.9f,NULL, &ppBuffer); 2777 ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr); 2778 2779 hr = D3DXCreateBox(NULL,22.0f,20.0f,4.9f,&box, &ppBuffer); 2780 ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr); 2781 2782 hr = D3DXCreateBox(device,-2.0f,20.0f,4.9f,&box, &ppBuffer); 2783 ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr); 2784 2785 hr = D3DXCreateBox(device,22.0f,-20.0f,4.9f,&box, &ppBuffer); 2786 ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr); 2787 2788 hr = D3DXCreateBox(device,22.0f,20.0f,-4.9f,&box, &ppBuffer); 2789 ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr); 2790 2791 ppBuffer = NULL; 2792 hr = D3DXCreateBox(device,10.9f,20.0f,4.9f,&box, &ppBuffer); 2793 ok(hr==D3D_OK, "Expected D3D_OK, received %#x\n", hr); 2794 2795 buffer = ID3DXBuffer_GetBufferPointer(ppBuffer); 2796 for(i=0; i<36; i++) 2797 ok(adjacency[i]==buffer[i], "expected adjacency %d: %#x, received %#x\n",i,adjacency[i], buffer[i]); 2798 2799 box->lpVtbl->Release(box); 2800 ID3DXBuffer_Release(ppBuffer); 2801 2802 test_box(device, 10.9f, 20.0f, 4.9f); 2803 2804 free_test_context(test_context); 2805 } 2806 2807 static BOOL compute_polygon(struct mesh *mesh, float length, unsigned int sides) 2808 { 2809 unsigned int i; 2810 float angle, scale; 2811 2812 if (!new_mesh(mesh, sides + 1, sides)) 2813 return FALSE; 2814 2815 angle = D3DX_PI / sides; 2816 scale = 0.5f * length / sinf(angle); 2817 angle *= 2.0f; 2818 2819 mesh->vertices[0].position.x = 0.0f; 2820 mesh->vertices[0].position.y = 0.0f; 2821 mesh->vertices[0].position.z = 0.0f; 2822 mesh->vertices[0].normal.x = 0.0f; 2823 mesh->vertices[0].normal.y = 0.0f; 2824 mesh->vertices[0].normal.z = 1.0f; 2825 2826 for (i = 0; i < sides; ++i) 2827 { 2828 mesh->vertices[i + 1].position.x = cosf(angle * i) * scale; 2829 mesh->vertices[i + 1].position.y = sinf(angle * i) * scale; 2830 mesh->vertices[i + 1].position.z = 0.0f; 2831 mesh->vertices[i + 1].normal.x = 0.0f; 2832 mesh->vertices[i + 1].normal.y = 0.0f; 2833 mesh->vertices[i + 1].normal.z = 1.0f; 2834 2835 mesh->faces[i][0] = 0; 2836 mesh->faces[i][1] = i + 1; 2837 mesh->faces[i][2] = i + 2; 2838 } 2839 2840 mesh->faces[sides - 1][2] = 1; 2841 2842 return TRUE; 2843 } 2844 2845 static void test_polygon(IDirect3DDevice9 *device, float length, unsigned int sides) 2846 { 2847 HRESULT hr; 2848 ID3DXMesh *polygon; 2849 struct mesh mesh; 2850 char name[64]; 2851 2852 hr = D3DXCreatePolygon(device, length, sides, &polygon, NULL); 2853 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); 2854 if (hr != D3D_OK) 2855 { 2856 skip("Couldn't create polygon\n"); 2857 return; 2858 } 2859 2860 if (!compute_polygon(&mesh, length, sides)) 2861 { 2862 skip("Couldn't create mesh\n"); 2863 polygon->lpVtbl->Release(polygon); 2864 return; 2865 } 2866 2867 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL; 2868 2869 sprintf(name, "polygon (%g, %u)", length, sides); 2870 compare_mesh(name, polygon, &mesh); 2871 2872 free_mesh(&mesh); 2873 2874 polygon->lpVtbl->Release(polygon); 2875 } 2876 2877 static void D3DXCreatePolygonTest(void) 2878 { 2879 HRESULT hr; 2880 IDirect3DDevice9 *device; 2881 ID3DXMesh *polygon; 2882 ID3DXBuffer *adjacency; 2883 DWORD (*buffer)[3], buffer_size; 2884 unsigned int i; 2885 struct test_context *test_context; 2886 2887 if (!(test_context = new_test_context())) 2888 { 2889 skip("Couldn't create test context\n"); 2890 return; 2891 } 2892 device = test_context->device; 2893 2894 hr = D3DXCreatePolygon(device, 2.0f, 11, NULL, &adjacency); 2895 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr); 2896 2897 hr = D3DXCreatePolygon(NULL, 2.0f, 11, &polygon, &adjacency); 2898 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr); 2899 2900 hr = D3DXCreatePolygon(device, -2.0f, 11, &polygon, &adjacency); 2901 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr); 2902 2903 polygon = (void *)0xdeadbeef; 2904 adjacency = (void *)0xdeadbeef; 2905 hr = D3DXCreatePolygon(device, 2.0f, 0, &polygon, &adjacency); 2906 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr); 2907 ok(polygon == (void *)0xdeadbeef, "Polygon was changed to %p\n", polygon); 2908 ok(adjacency == (void *)0xdeadbeef, "Adjacency was changed to %p\n", adjacency); 2909 2910 hr = D3DXCreatePolygon(device, 2.0f, 2, &polygon, &adjacency); 2911 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr); 2912 2913 adjacency = NULL; 2914 hr = D3DXCreatePolygon(device, 3.0f, 11, &polygon, &adjacency); 2915 ok(hr == D3D_OK, "Expected D3D_OK, received %#x\n", hr); 2916 2917 buffer_size = ID3DXBuffer_GetBufferSize(adjacency); 2918 ok(buffer_size == 33 * sizeof(DWORD), "Wrong adjacency buffer size %u\n", buffer_size); 2919 2920 buffer = ID3DXBuffer_GetBufferPointer(adjacency); 2921 for (i = 0; i < 11; ++i) 2922 { 2923 ok(buffer[i][0] == (i + 10) % 11, "Wrong adjacency[%d][0] = %u\n", i, buffer[i][0]); 2924 ok(buffer[i][1] == ~0U, "Wrong adjacency[%d][1] = %u\n", i, buffer[i][1]); 2925 ok(buffer[i][2] == (i + 1) % 11, "Wrong adjacency[%d][2] = %u\n", i, buffer[i][2]); 2926 } 2927 2928 polygon->lpVtbl->Release(polygon); 2929 ID3DXBuffer_Release(adjacency); 2930 2931 test_polygon(device, 2.0f, 3); 2932 test_polygon(device, 10.0f, 3); 2933 test_polygon(device, 10.0f, 5); 2934 test_polygon(device, 10.0f, 10); 2935 test_polygon(device, 20.0f, 10); 2936 test_polygon(device, 20.0f, 32000); 2937 2938 free_test_context(test_context); 2939 } 2940 2941 struct sincos_table 2942 { 2943 float *sin; 2944 float *cos; 2945 }; 2946 2947 static void free_sincos_table(struct sincos_table *sincos_table) 2948 { 2949 HeapFree(GetProcessHeap(), 0, sincos_table->cos); 2950 HeapFree(GetProcessHeap(), 0, sincos_table->sin); 2951 } 2952 2953 /* pre compute sine and cosine tables; caller must free */ 2954 static BOOL compute_sincos_table(struct sincos_table *sincos_table, float angle_start, float angle_step, int n) 2955 { 2956 float angle; 2957 int i; 2958 2959 sincos_table->sin = HeapAlloc(GetProcessHeap(), 0, n * sizeof(*sincos_table->sin)); 2960 if (!sincos_table->sin) 2961 { 2962 return FALSE; 2963 } 2964 sincos_table->cos = HeapAlloc(GetProcessHeap(), 0, n * sizeof(*sincos_table->cos)); 2965 if (!sincos_table->cos) 2966 { 2967 HeapFree(GetProcessHeap(), 0, sincos_table->sin); 2968 return FALSE; 2969 } 2970 2971 angle = angle_start; 2972 for (i = 0; i < n; i++) 2973 { 2974 sincos_table->sin[i] = sin(angle); 2975 sincos_table->cos[i] = cos(angle); 2976 angle += angle_step; 2977 } 2978 2979 return TRUE; 2980 } 2981 2982 static WORD vertex_index(UINT slices, int slice, int stack) 2983 { 2984 return stack*slices+slice+1; 2985 } 2986 2987 /* slices = subdivisions along xy plane, stacks = subdivisions along z axis */ 2988 static BOOL compute_sphere(struct mesh *mesh, FLOAT radius, UINT slices, UINT stacks) 2989 { 2990 float theta_step, theta_start; 2991 struct sincos_table theta; 2992 float phi_step, phi_start; 2993 struct sincos_table phi; 2994 DWORD number_of_vertices, number_of_faces; 2995 DWORD vertex, face; 2996 int slice, stack; 2997 2998 /* theta = angle on xy plane wrt x axis */ 2999 theta_step = D3DX_PI / stacks; 3000 theta_start = theta_step; 3001 3002 /* phi = angle on xz plane wrt z axis */ 3003 phi_step = -2 * D3DX_PI / slices; 3004 phi_start = D3DX_PI / 2; 3005 3006 if (!compute_sincos_table(&theta, theta_start, theta_step, stacks)) 3007 { 3008 return FALSE; 3009 } 3010 if (!compute_sincos_table(&phi, phi_start, phi_step, slices)) 3011 { 3012 free_sincos_table(&theta); 3013 return FALSE; 3014 } 3015 3016 number_of_vertices = 2 + slices * (stacks-1); 3017 number_of_faces = 2 * slices + (stacks - 2) * (2 * slices); 3018 3019 if (!new_mesh(mesh, number_of_vertices, number_of_faces)) 3020 { 3021 free_sincos_table(&phi); 3022 free_sincos_table(&theta); 3023 return FALSE; 3024 } 3025 3026 vertex = 0; 3027 face = 0; 3028 3029 mesh->vertices[vertex].normal.x = 0.0f; 3030 mesh->vertices[vertex].normal.y = 0.0f; 3031 mesh->vertices[vertex].normal.z = 1.0f; 3032 mesh->vertices[vertex].position.x = 0.0f; 3033 mesh->vertices[vertex].position.y = 0.0f; 3034 mesh->vertices[vertex].position.z = radius; 3035 vertex++; 3036 3037 for (stack = 0; stack < stacks - 1; stack++) 3038 { 3039 for (slice = 0; slice < slices; slice++) 3040 { 3041 mesh->vertices[vertex].normal.x = theta.sin[stack] * phi.cos[slice]; 3042 mesh->vertices[vertex].normal.y = theta.sin[stack] * phi.sin[slice]; 3043 mesh->vertices[vertex].normal.z = theta.cos[stack]; 3044 mesh->vertices[vertex].position.x = radius * theta.sin[stack] * phi.cos[slice]; 3045 mesh->vertices[vertex].position.y = radius * theta.sin[stack] * phi.sin[slice]; 3046 mesh->vertices[vertex].position.z = radius * theta.cos[stack]; 3047 vertex++; 3048 3049 if (slice > 0) 3050 { 3051 if (stack == 0) 3052 { 3053 /* top stack is triangle fan */ 3054 mesh->faces[face][0] = 0; 3055 mesh->faces[face][1] = slice + 1; 3056 mesh->faces[face][2] = slice; 3057 face++; 3058 } 3059 else 3060 { 3061 /* stacks in between top and bottom are quad strips */ 3062 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1); 3063 mesh->faces[face][1] = vertex_index(slices, slice, stack-1); 3064 mesh->faces[face][2] = vertex_index(slices, slice-1, stack); 3065 face++; 3066 3067 mesh->faces[face][0] = vertex_index(slices, slice, stack-1); 3068 mesh->faces[face][1] = vertex_index(slices, slice, stack); 3069 mesh->faces[face][2] = vertex_index(slices, slice-1, stack); 3070 face++; 3071 } 3072 } 3073 } 3074 3075 if (stack == 0) 3076 { 3077 mesh->faces[face][0] = 0; 3078 mesh->faces[face][1] = 1; 3079 mesh->faces[face][2] = slice; 3080 face++; 3081 } 3082 else 3083 { 3084 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1); 3085 mesh->faces[face][1] = vertex_index(slices, 0, stack-1); 3086 mesh->faces[face][2] = vertex_index(slices, slice-1, stack); 3087 face++; 3088 3089 mesh->faces[face][0] = vertex_index(slices, 0, stack-1); 3090 mesh->faces[face][1] = vertex_index(slices, 0, stack); 3091 mesh->faces[face][2] = vertex_index(slices, slice-1, stack); 3092 face++; 3093 } 3094 } 3095 3096 mesh->vertices[vertex].position.x = 0.0f; 3097 mesh->vertices[vertex].position.y = 0.0f; 3098 mesh->vertices[vertex].position.z = -radius; 3099 mesh->vertices[vertex].normal.x = 0.0f; 3100 mesh->vertices[vertex].normal.y = 0.0f; 3101 mesh->vertices[vertex].normal.z = -1.0f; 3102 3103 /* bottom stack is triangle fan */ 3104 for (slice = 1; slice < slices; slice++) 3105 { 3106 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1); 3107 mesh->faces[face][1] = vertex_index(slices, slice, stack-1); 3108 mesh->faces[face][2] = vertex; 3109 face++; 3110 } 3111 3112 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1); 3113 mesh->faces[face][1] = vertex_index(slices, 0, stack-1); 3114 mesh->faces[face][2] = vertex; 3115 3116 free_sincos_table(&phi); 3117 free_sincos_table(&theta); 3118 3119 return TRUE; 3120 } 3121 3122 static void test_sphere(IDirect3DDevice9 *device, FLOAT radius, UINT slices, UINT stacks) 3123 { 3124 HRESULT hr; 3125 ID3DXMesh *sphere; 3126 struct mesh mesh; 3127 char name[256]; 3128 3129 hr = D3DXCreateSphere(device, radius, slices, stacks, &sphere, NULL); 3130 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); 3131 if (hr != D3D_OK) 3132 { 3133 skip("Couldn't create sphere\n"); 3134 return; 3135 } 3136 3137 if (!compute_sphere(&mesh, radius, slices, stacks)) 3138 { 3139 skip("Couldn't create mesh\n"); 3140 sphere->lpVtbl->Release(sphere); 3141 return; 3142 } 3143 3144 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL; 3145 3146 sprintf(name, "sphere (%g, %u, %u)", radius, slices, stacks); 3147 compare_mesh(name, sphere, &mesh); 3148 3149 free_mesh(&mesh); 3150 3151 sphere->lpVtbl->Release(sphere); 3152 } 3153 3154 static void D3DXCreateSphereTest(void) 3155 { 3156 HRESULT hr; 3157 IDirect3DDevice9* device; 3158 ID3DXMesh* sphere = NULL; 3159 struct test_context *test_context; 3160 3161 hr = D3DXCreateSphere(NULL, 0.0f, 0, 0, NULL, NULL); 3162 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL); 3163 3164 hr = D3DXCreateSphere(NULL, 0.1f, 0, 0, NULL, NULL); 3165 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL); 3166 3167 hr = D3DXCreateSphere(NULL, 0.0f, 1, 0, NULL, NULL); 3168 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL); 3169 3170 hr = D3DXCreateSphere(NULL, 0.0f, 0, 1, NULL, NULL); 3171 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL); 3172 3173 if (!(test_context = new_test_context())) 3174 { 3175 skip("Couldn't create test context\n"); 3176 return; 3177 } 3178 device = test_context->device; 3179 3180 hr = D3DXCreateSphere(device, 1.0f, 1, 1, &sphere, NULL); 3181 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL); 3182 3183 hr = D3DXCreateSphere(device, 1.0f, 2, 1, &sphere, NULL); 3184 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 3185 3186 hr = D3DXCreateSphere(device, 1.0f, 1, 2, &sphere, NULL); 3187 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 3188 3189 hr = D3DXCreateSphere(device, -0.1f, 1, 2, &sphere, NULL); 3190 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 3191 3192 test_sphere(device, 0.0f, 2, 2); 3193 test_sphere(device, 1.0f, 2, 2); 3194 test_sphere(device, 1.0f, 3, 2); 3195 test_sphere(device, 1.0f, 4, 4); 3196 test_sphere(device, 1.0f, 3, 4); 3197 test_sphere(device, 5.0f, 6, 7); 3198 test_sphere(device, 10.0f, 11, 12); 3199 3200 free_test_context(test_context); 3201 } 3202 3203 static BOOL compute_cylinder(struct mesh *mesh, FLOAT radius1, FLOAT radius2, FLOAT length, UINT slices, UINT stacks) 3204 { 3205 float theta_step, theta_start; 3206 struct sincos_table theta; 3207 FLOAT delta_radius, radius, radius_step; 3208 FLOAT z, z_step, z_normal; 3209 DWORD number_of_vertices, number_of_faces; 3210 DWORD vertex, face; 3211 int slice, stack; 3212 3213 /* theta = angle on xy plane wrt x axis */ 3214 theta_step = -2 * D3DX_PI / slices; 3215 theta_start = D3DX_PI / 2; 3216 3217 if (!compute_sincos_table(&theta, theta_start, theta_step, slices)) 3218 { 3219 return FALSE; 3220 } 3221 3222 number_of_vertices = 2 + (slices * (3 + stacks)); 3223 number_of_faces = 2 * slices + stacks * (2 * slices); 3224 3225 if (!new_mesh(mesh, number_of_vertices, number_of_faces)) 3226 { 3227 free_sincos_table(&theta); 3228 return FALSE; 3229 } 3230 3231 vertex = 0; 3232 face = 0; 3233 3234 delta_radius = radius1 - radius2; 3235 radius = radius1; 3236 radius_step = delta_radius / stacks; 3237 3238 z = -length / 2; 3239 z_step = length / stacks; 3240 z_normal = delta_radius / length; 3241 if (isnan(z_normal)) 3242 { 3243 z_normal = 0.0f; 3244 } 3245 3246 mesh->vertices[vertex].normal.x = 0.0f; 3247 mesh->vertices[vertex].normal.y = 0.0f; 3248 mesh->vertices[vertex].normal.z = -1.0f; 3249 mesh->vertices[vertex].position.x = 0.0f; 3250 mesh->vertices[vertex].position.y = 0.0f; 3251 mesh->vertices[vertex++].position.z = z; 3252 3253 for (slice = 0; slice < slices; slice++, vertex++) 3254 { 3255 mesh->vertices[vertex].normal.x = 0.0f; 3256 mesh->vertices[vertex].normal.y = 0.0f; 3257 mesh->vertices[vertex].normal.z = -1.0f; 3258 mesh->vertices[vertex].position.x = radius * theta.cos[slice]; 3259 mesh->vertices[vertex].position.y = radius * theta.sin[slice]; 3260 mesh->vertices[vertex].position.z = z; 3261 3262 if (slice > 0) 3263 { 3264 mesh->faces[face][0] = 0; 3265 mesh->faces[face][1] = slice; 3266 mesh->faces[face++][2] = slice + 1; 3267 } 3268 } 3269 3270 mesh->faces[face][0] = 0; 3271 mesh->faces[face][1] = slice; 3272 mesh->faces[face++][2] = 1; 3273 3274 for (stack = 1; stack <= stacks+1; stack++) 3275 { 3276 for (slice = 0; slice < slices; slice++, vertex++) 3277 { 3278 mesh->vertices[vertex].normal.x = theta.cos[slice]; 3279 mesh->vertices[vertex].normal.y = theta.sin[slice]; 3280 mesh->vertices[vertex].normal.z = z_normal; 3281 D3DXVec3Normalize(&mesh->vertices[vertex].normal, &mesh->vertices[vertex].normal); 3282 mesh->vertices[vertex].position.x = radius * theta.cos[slice]; 3283 mesh->vertices[vertex].position.y = radius * theta.sin[slice]; 3284 mesh->vertices[vertex].position.z = z; 3285 3286 if (stack > 1 && slice > 0) 3287 { 3288 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1); 3289 mesh->faces[face][1] = vertex_index(slices, slice-1, stack); 3290 mesh->faces[face++][2] = vertex_index(slices, slice, stack-1); 3291 3292 mesh->faces[face][0] = vertex_index(slices, slice, stack-1); 3293 mesh->faces[face][1] = vertex_index(slices, slice-1, stack); 3294 mesh->faces[face++][2] = vertex_index(slices, slice, stack); 3295 } 3296 } 3297 3298 if (stack > 1) 3299 { 3300 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1); 3301 mesh->faces[face][1] = vertex_index(slices, slice-1, stack); 3302 mesh->faces[face++][2] = vertex_index(slices, 0, stack-1); 3303 3304 mesh->faces[face][0] = vertex_index(slices, 0, stack-1); 3305 mesh->faces[face][1] = vertex_index(slices, slice-1, stack); 3306 mesh->faces[face++][2] = vertex_index(slices, 0, stack); 3307 } 3308 3309 if (stack < stacks + 1) 3310 { 3311 z += z_step; 3312 radius -= radius_step; 3313 } 3314 } 3315 3316 for (slice = 0; slice < slices; slice++, vertex++) 3317 { 3318 mesh->vertices[vertex].normal.x = 0.0f; 3319 mesh->vertices[vertex].normal.y = 0.0f; 3320 mesh->vertices[vertex].normal.z = 1.0f; 3321 mesh->vertices[vertex].position.x = radius * theta.cos[slice]; 3322 mesh->vertices[vertex].position.y = radius * theta.sin[slice]; 3323 mesh->vertices[vertex].position.z = z; 3324 3325 if (slice > 0) 3326 { 3327 mesh->faces[face][0] = vertex_index(slices, slice-1, stack); 3328 mesh->faces[face][1] = number_of_vertices - 1; 3329 mesh->faces[face++][2] = vertex_index(slices, slice, stack); 3330 } 3331 } 3332 3333 mesh->vertices[vertex].position.x = 0.0f; 3334 mesh->vertices[vertex].position.y = 0.0f; 3335 mesh->vertices[vertex].position.z = z; 3336 mesh->vertices[vertex].normal.x = 0.0f; 3337 mesh->vertices[vertex].normal.y = 0.0f; 3338 mesh->vertices[vertex].normal.z = 1.0f; 3339 3340 mesh->faces[face][0] = vertex_index(slices, slice-1, stack); 3341 mesh->faces[face][1] = number_of_vertices - 1; 3342 mesh->faces[face][2] = vertex_index(slices, 0, stack); 3343 3344 free_sincos_table(&theta); 3345 3346 return TRUE; 3347 } 3348 3349 static void test_cylinder(IDirect3DDevice9 *device, FLOAT radius1, FLOAT radius2, FLOAT length, UINT slices, UINT stacks) 3350 { 3351 HRESULT hr; 3352 ID3DXMesh *cylinder; 3353 struct mesh mesh; 3354 char name[256]; 3355 3356 hr = D3DXCreateCylinder(device, radius1, radius2, length, slices, stacks, &cylinder, NULL); 3357 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); 3358 if (hr != D3D_OK) 3359 { 3360 skip("Couldn't create cylinder\n"); 3361 return; 3362 } 3363 3364 if (!compute_cylinder(&mesh, radius1, radius2, length, slices, stacks)) 3365 { 3366 skip("Couldn't create mesh\n"); 3367 cylinder->lpVtbl->Release(cylinder); 3368 return; 3369 } 3370 3371 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL; 3372 3373 sprintf(name, "cylinder (%g, %g, %g, %u, %u)", radius1, radius2, length, slices, stacks); 3374 compare_mesh(name, cylinder, &mesh); 3375 3376 free_mesh(&mesh); 3377 3378 cylinder->lpVtbl->Release(cylinder); 3379 } 3380 3381 static void D3DXCreateCylinderTest(void) 3382 { 3383 HRESULT hr; 3384 IDirect3DDevice9* device; 3385 ID3DXMesh* cylinder = NULL; 3386 struct test_context *test_context; 3387 3388 hr = D3DXCreateCylinder(NULL, 0.0f, 0.0f, 0.0f, 0, 0, NULL, NULL); 3389 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL); 3390 3391 hr = D3DXCreateCylinder(NULL, 1.0f, 1.0f, 1.0f, 2, 1, &cylinder, NULL); 3392 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL); 3393 3394 if (!(test_context = new_test_context())) 3395 { 3396 skip("Couldn't create test context\n"); 3397 return; 3398 } 3399 device = test_context->device; 3400 3401 hr = D3DXCreateCylinder(device, -0.1f, 1.0f, 1.0f, 2, 1, &cylinder, NULL); 3402 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL); 3403 3404 hr = D3DXCreateCylinder(device, 0.0f, 1.0f, 1.0f, 2, 1, &cylinder, NULL); 3405 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n",hr); 3406 3407 if (SUCCEEDED(hr) && cylinder) 3408 { 3409 cylinder->lpVtbl->Release(cylinder); 3410 } 3411 3412 hr = D3DXCreateCylinder(device, 1.0f, -0.1f, 1.0f, 2, 1, &cylinder, NULL); 3413 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL); 3414 3415 hr = D3DXCreateCylinder(device, 1.0f, 0.0f, 1.0f, 2, 1, &cylinder, NULL); 3416 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n",hr); 3417 3418 if (SUCCEEDED(hr) && cylinder) 3419 { 3420 cylinder->lpVtbl->Release(cylinder); 3421 } 3422 3423 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, -0.1f, 2, 1, &cylinder, NULL); 3424 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL); 3425 3426 /* Test with length == 0.0f succeeds */ 3427 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, 0.0f, 2, 1, &cylinder, NULL); 3428 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n",hr); 3429 3430 if (SUCCEEDED(hr) && cylinder) 3431 { 3432 cylinder->lpVtbl->Release(cylinder); 3433 } 3434 3435 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, 1.0f, 1, 1, &cylinder, NULL); 3436 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL); 3437 3438 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, 1.0f, 2, 0, &cylinder, NULL); 3439 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL); 3440 3441 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, 1.0f, 2, 1, NULL, NULL); 3442 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL); 3443 3444 test_cylinder(device, 0.0f, 0.0f, 0.0f, 2, 1); 3445 test_cylinder(device, 1.0f, 1.0f, 1.0f, 2, 1); 3446 test_cylinder(device, 1.0f, 1.0f, 2.0f, 3, 4); 3447 test_cylinder(device, 3.0f, 2.0f, 4.0f, 3, 4); 3448 test_cylinder(device, 2.0f, 3.0f, 4.0f, 3, 4); 3449 test_cylinder(device, 3.0f, 4.0f, 5.0f, 11, 20); 3450 3451 free_test_context(test_context); 3452 } 3453 3454 static BOOL compute_torus(struct mesh *mesh, float innerradius, float outerradius, UINT sides, UINT rings) 3455 { 3456 float phi, phi_step, sin_phi, cos_phi; 3457 float theta, theta_step, sin_theta, cos_theta; 3458 unsigned int numvert, numfaces, i, j; 3459 3460 numvert = sides * rings; 3461 numfaces = numvert * 2; 3462 3463 if (!new_mesh(mesh, numvert, numfaces)) 3464 return FALSE; 3465 3466 phi_step = D3DX_PI / sides * 2.0f; 3467 theta_step = D3DX_PI / rings * -2.0f; 3468 3469 theta = 0.0f; 3470 3471 for (i = 0; i < rings; ++i) 3472 { 3473 phi = 0.0f; 3474 3475 cos_theta = cosf(theta); 3476 sin_theta = sinf(theta); 3477 3478 for (j = 0; j < sides; ++j) 3479 { 3480 sin_phi = sinf(phi); 3481 cos_phi = cosf(phi); 3482 3483 mesh->vertices[i * sides + j].position.x = (innerradius * cos_phi + outerradius) * cos_theta; 3484 mesh->vertices[i * sides + j].position.y = (innerradius * cos_phi + outerradius) * sin_theta; 3485 mesh->vertices[i * sides + j].position.z = innerradius * sin_phi; 3486 mesh->vertices[i * sides + j].normal.x = cos_phi * cos_theta; 3487 mesh->vertices[i * sides + j].normal.y = cos_phi * sin_theta; 3488 mesh->vertices[i * sides + j].normal.z = sin_phi; 3489 3490 phi += phi_step; 3491 } 3492 3493 theta += theta_step; 3494 } 3495 3496 for (i = 0; i < numfaces - sides * 2; ++i) 3497 { 3498 mesh->faces[i][0] = i % 2 ? i / 2 + sides : i / 2; 3499 mesh->faces[i][1] = (i / 2 + 1) % sides ? i / 2 + 1 : i / 2 + 1 - sides; 3500 mesh->faces[i][2] = (i + 1) % (sides * 2) ? (i + 1) / 2 + sides : (i + 1) / 2; 3501 } 3502 3503 for (j = 0; i < numfaces; ++i, ++j) 3504 { 3505 mesh->faces[i][0] = i % 2 ? j / 2 : i / 2; 3506 mesh->faces[i][1] = (i / 2 + 1) % sides ? i / 2 + 1 : i / 2 + 1 - sides; 3507 mesh->faces[i][2] = i == numfaces - 1 ? 0 : (j + 1) / 2; 3508 } 3509 3510 return TRUE; 3511 } 3512 3513 static void test_torus(IDirect3DDevice9 *device, float innerradius, float outerradius, UINT sides, UINT rings) 3514 { 3515 HRESULT hr; 3516 ID3DXMesh *torus; 3517 struct mesh mesh; 3518 char name[256]; 3519 3520 hr = D3DXCreateTorus(device, innerradius, outerradius, sides, rings, &torus, NULL); 3521 ok(hr == D3D_OK, "Got result %#x, expected 0 (D3D_OK)\n", hr); 3522 if (hr != D3D_OK) 3523 { 3524 skip("Couldn't create torus\n"); 3525 return; 3526 } 3527 3528 if (!compute_torus(&mesh, innerradius, outerradius, sides, rings)) 3529 { 3530 skip("Couldn't create mesh\n"); 3531 torus->lpVtbl->Release(torus); 3532 return; 3533 } 3534 3535 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL; 3536 3537 sprintf(name, "torus (%g, %g, %u, %u)", innerradius, outerradius, sides, rings); 3538 compare_mesh(name, torus, &mesh); 3539 3540 free_mesh(&mesh); 3541 3542 torus->lpVtbl->Release(torus); 3543 } 3544 3545 static void D3DXCreateTorusTest(void) 3546 { 3547 HRESULT hr; 3548 IDirect3DDevice9* device; 3549 ID3DXMesh* torus = NULL; 3550 struct test_context *test_context; 3551 3552 if (!(test_context = new_test_context())) 3553 { 3554 skip("Couldn't create test context\n"); 3555 return; 3556 } 3557 device = test_context->device; 3558 3559 hr = D3DXCreateTorus(NULL, 0.0f, 0.0f, 3, 3, &torus, NULL); 3560 ok(hr == D3DERR_INVALIDCALL, "Got result %#x, expected %#x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 3561 3562 hr = D3DXCreateTorus(device, -1.0f, 0.0f, 3, 3, &torus, NULL); 3563 ok(hr == D3DERR_INVALIDCALL, "Got result %#x, expected %#x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 3564 3565 hr = D3DXCreateTorus(device, 0.0f, -1.0f, 3, 3, &torus, NULL); 3566 ok(hr == D3DERR_INVALIDCALL, "Got result %#x, expected %#x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 3567 3568 hr = D3DXCreateTorus(device, 0.0f, 0.0f, 2, 3, &torus, NULL); 3569 ok(hr == D3DERR_INVALIDCALL, "Got result %#x, expected %#x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 3570 3571 hr = D3DXCreateTorus(device, 0.0f, 0.0f, 3, 2, &torus, NULL); 3572 ok(hr == D3DERR_INVALIDCALL, "Got result %#x, expected %#x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 3573 3574 hr = D3DXCreateTorus(device, 0.0f, 0.0f, 3, 3, NULL, NULL); 3575 ok(hr == D3DERR_INVALIDCALL, "Got result %#x, expected %#x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 3576 3577 test_torus(device, 0.0f, 0.0f, 3, 3); 3578 test_torus(device, 1.0f, 1.0f, 3, 3); 3579 test_torus(device, 1.0f, 1.0f, 32, 64); 3580 test_torus(device, 0.0f, 1.0f, 5, 5); 3581 test_torus(device, 1.0f, 0.0f, 5, 5); 3582 test_torus(device, 5.0f, 0.2f, 8, 8); 3583 test_torus(device, 0.2f, 1.0f, 60, 3); 3584 test_torus(device, 0.2f, 1.0f, 8, 70); 3585 3586 free_test_context(test_context); 3587 } 3588 3589 struct dynamic_array 3590 { 3591 int count, capacity; 3592 void *items; 3593 }; 3594 3595 enum pointtype { 3596 POINTTYPE_CURVE = 0, 3597 POINTTYPE_CORNER, 3598 POINTTYPE_CURVE_START, 3599 POINTTYPE_CURVE_END, 3600 POINTTYPE_CURVE_MIDDLE, 3601 }; 3602 3603 struct point2d 3604 { 3605 D3DXVECTOR2 pos; 3606 enum pointtype corner; 3607 }; 3608 3609 /* is a dynamic_array */ 3610 struct outline 3611 { 3612 int count, capacity; 3613 struct point2d *items; 3614 }; 3615 3616 /* is a dynamic_array */ 3617 struct outline_array 3618 { 3619 int count, capacity; 3620 struct outline *items; 3621 }; 3622 3623 struct glyphinfo 3624 { 3625 struct outline_array outlines; 3626 float offset_x; 3627 }; 3628 3629 static BOOL reserve(struct dynamic_array *array, int count, int itemsize) 3630 { 3631 if (count > array->capacity) { 3632 void *new_buffer; 3633 int new_capacity; 3634 if (array->items && array->capacity) { 3635 new_capacity = max(array->capacity * 2, count); 3636 new_buffer = HeapReAlloc(GetProcessHeap(), 0, array->items, new_capacity * itemsize); 3637 } else { 3638 new_capacity = max(16, count); 3639 new_buffer = HeapAlloc(GetProcessHeap(), 0, new_capacity * itemsize); 3640 } 3641 if (!new_buffer) 3642 return FALSE; 3643 array->items = new_buffer; 3644 array->capacity = new_capacity; 3645 } 3646 return TRUE; 3647 } 3648 3649 static struct point2d *add_point(struct outline *array) 3650 { 3651 struct point2d *item; 3652 3653 if (!reserve((struct dynamic_array *)array, array->count + 1, sizeof(array->items[0]))) 3654 return NULL; 3655 3656 item = &array->items[array->count++]; 3657 ZeroMemory(item, sizeof(*item)); 3658 return item; 3659 } 3660 3661 static struct outline *add_outline(struct outline_array *array) 3662 { 3663 struct outline *item; 3664 3665 if (!reserve((struct dynamic_array *)array, array->count + 1, sizeof(array->items[0]))) 3666 return NULL; 3667 3668 item = &array->items[array->count++]; 3669 ZeroMemory(item, sizeof(*item)); 3670 return item; 3671 } 3672 3673 static inline D3DXVECTOR2 *convert_fixed_to_float(POINTFX *pt, int count, float emsquare) 3674 { 3675 D3DXVECTOR2 *ret = (D3DXVECTOR2*)pt; 3676 while (count--) { 3677 D3DXVECTOR2 *pt_flt = (D3DXVECTOR2*)pt; 3678 pt_flt->x = (pt->x.value + pt->x.fract / (float)0x10000) / emsquare; 3679 pt_flt->y = (pt->y.value + pt->y.fract / (float)0x10000) / emsquare; 3680 pt++; 3681 } 3682 return ret; 3683 } 3684 3685 static HRESULT add_bezier_points(struct outline *outline, const D3DXVECTOR2 *p1, 3686 const D3DXVECTOR2 *p2, const D3DXVECTOR2 *p3, 3687 float max_deviation) 3688 { 3689 D3DXVECTOR2 split1 = {0, 0}, split2 = {0, 0}, middle, vec; 3690 float deviation; 3691 3692 D3DXVec2Scale(&split1, D3DXVec2Add(&split1, p1, p2), 0.5f); 3693 D3DXVec2Scale(&split2, D3DXVec2Add(&split2, p2, p3), 0.5f); 3694 D3DXVec2Scale(&middle, D3DXVec2Add(&middle, &split1, &split2), 0.5f); 3695 3696 deviation = D3DXVec2Length(D3DXVec2Subtract(&vec, &middle, p2)); 3697 if (deviation < max_deviation) { 3698 struct point2d *pt = add_point(outline); 3699 if (!pt) return E_OUTOFMEMORY; 3700 pt->pos = *p2; 3701 pt->corner = POINTTYPE_CURVE; 3702 /* the end point is omitted because the end line merges into the next segment of 3703 * the split bezier curve, and the end of the split bezier curve is added outside 3704 * this recursive function. */ 3705 } else { 3706 HRESULT hr = add_bezier_points(outline, p1, &split1, &middle, max_deviation); 3707 if (hr != S_OK) return hr; 3708 hr = add_bezier_points(outline, &middle, &split2, p3, max_deviation); 3709 if (hr != S_OK) return hr; 3710 } 3711 3712 return S_OK; 3713 } 3714 3715 static inline BOOL is_direction_similar(D3DXVECTOR2 *dir1, D3DXVECTOR2 *dir2, float cos_theta) 3716 { 3717 /* dot product = cos(theta) */ 3718 return D3DXVec2Dot(dir1, dir2) > cos_theta; 3719 } 3720 3721 static inline D3DXVECTOR2 *unit_vec2(D3DXVECTOR2 *dir, const D3DXVECTOR2 *pt1, const D3DXVECTOR2 *pt2) 3722 { 3723 return D3DXVec2Normalize(D3DXVec2Subtract(dir, pt2, pt1), dir); 3724 } 3725 3726 static BOOL attempt_line_merge(struct outline *outline, 3727 int pt_index, 3728 const D3DXVECTOR2 *nextpt, 3729 BOOL to_curve) 3730 { 3731 D3DXVECTOR2 curdir, lastdir; 3732 struct point2d *prevpt, *pt; 3733 BOOL ret = FALSE; 3734 const float cos_half = cos(D3DXToRadian(0.5f)); 3735 3736 pt = &outline->items[pt_index]; 3737 pt_index = (pt_index - 1 + outline->count) % outline->count; 3738 prevpt = &outline->items[pt_index]; 3739 3740 if (to_curve) 3741 pt->corner = pt->corner != POINTTYPE_CORNER ? POINTTYPE_CURVE_MIDDLE : POINTTYPE_CURVE_START; 3742 3743 if (outline->count < 2) 3744 return FALSE; 3745 3746 /* remove last point if the next line continues the last line */ 3747 unit_vec2(&lastdir, &prevpt->pos, &pt->pos); 3748 unit_vec2(&curdir, &pt->pos, nextpt); 3749 if (is_direction_similar(&lastdir, &curdir, cos_half)) 3750 { 3751 outline->count--; 3752 if (pt->corner == POINTTYPE_CURVE_END) 3753 prevpt->corner = pt->corner; 3754 if (prevpt->corner == POINTTYPE_CURVE_END && to_curve) 3755 prevpt->corner = POINTTYPE_CURVE_MIDDLE; 3756 pt = prevpt; 3757 3758 ret = TRUE; 3759 if (outline->count < 2) 3760 return ret; 3761 3762 pt_index = (pt_index - 1 + outline->count) % outline->count; 3763 prevpt = &outline->items[pt_index]; 3764 unit_vec2(&lastdir, &prevpt->pos, &pt->pos); 3765 unit_vec2(&curdir, &pt->pos, nextpt); 3766 } 3767 return ret; 3768 } 3769 3770 static HRESULT create_outline(struct glyphinfo *glyph, void *raw_outline, int datasize, 3771 float max_deviation, float emsquare) 3772 { 3773 const float cos_45 = cos(D3DXToRadian(45.0f)); 3774 const float cos_90 = cos(D3DXToRadian(90.0f)); 3775 TTPOLYGONHEADER *header = (TTPOLYGONHEADER *)raw_outline; 3776 3777 while ((char *)header < (char *)raw_outline + datasize) 3778 { 3779 TTPOLYCURVE *curve = (TTPOLYCURVE *)(header + 1); 3780 struct point2d *lastpt, *pt; 3781 D3DXVECTOR2 lastdir; 3782 D3DXVECTOR2 *pt_flt; 3783 int j; 3784 struct outline *outline = add_outline(&glyph->outlines); 3785 3786 if (!outline) 3787 return E_OUTOFMEMORY; 3788 3789 pt = add_point(outline); 3790 if (!pt) 3791 return E_OUTOFMEMORY; 3792 pt_flt = convert_fixed_to_float(&header->pfxStart, 1, emsquare); 3793 pt->pos = *pt_flt; 3794 pt->corner = POINTTYPE_CORNER; 3795 3796 if (header->dwType != TT_POLYGON_TYPE) 3797 trace("Unknown header type %d\n", header->dwType); 3798 3799 while ((char *)curve < (char *)header + header->cb) 3800 { 3801 D3DXVECTOR2 bezier_start = outline->items[outline->count - 1].pos; 3802 BOOL to_curve = curve->wType != TT_PRIM_LINE && curve->cpfx > 1; 3803 3804 if (!curve->cpfx) { 3805 curve = (TTPOLYCURVE *)&curve->apfx[curve->cpfx]; 3806 continue; 3807 } 3808 3809 pt_flt = convert_fixed_to_float(curve->apfx, curve->cpfx, emsquare); 3810 3811 attempt_line_merge(outline, outline->count - 1, &pt_flt[0], to_curve); 3812 3813 if (to_curve) 3814 { 3815 HRESULT hr; 3816 int count = curve->cpfx; 3817 j = 0; 3818 3819 while (count > 2) 3820 { 3821 D3DXVECTOR2 bezier_end; 3822 3823 D3DXVec2Scale(&bezier_end, D3DXVec2Add(&bezier_end, &pt_flt[j], &pt_flt[j+1]), 0.5f); 3824 hr = add_bezier_points(outline, &bezier_start, &pt_flt[j], &bezier_end, max_deviation); 3825 if (hr != S_OK) 3826 return hr; 3827 bezier_start = bezier_end; 3828 count--; 3829 j++; 3830 } 3831 hr = add_bezier_points(outline, &bezier_start, &pt_flt[j], &pt_flt[j+1], max_deviation); 3832 if (hr != S_OK) 3833 return hr; 3834 3835 pt = add_point(outline); 3836 if (!pt) 3837 return E_OUTOFMEMORY; 3838 j++; 3839 pt->pos = pt_flt[j]; 3840 pt->corner = POINTTYPE_CURVE_END; 3841 } else { 3842 for (j = 0; j < curve->cpfx; j++) 3843 { 3844 pt = add_point(outline); 3845 if (!pt) 3846 return E_OUTOFMEMORY; 3847 pt->pos = pt_flt[j]; 3848 pt->corner = POINTTYPE_CORNER; 3849 } 3850 } 3851 3852 curve = (TTPOLYCURVE *)&curve->apfx[curve->cpfx]; 3853 } 3854 3855 /* remove last point if the next line continues the last line */ 3856 if (outline->count >= 3) { 3857 BOOL to_curve; 3858 3859 lastpt = &outline->items[outline->count - 1]; 3860 pt = &outline->items[0]; 3861 if (pt->pos.x == lastpt->pos.x && pt->pos.y == lastpt->pos.y) { 3862 if (lastpt->corner == POINTTYPE_CURVE_END) 3863 { 3864 if (pt->corner == POINTTYPE_CURVE_START) 3865 pt->corner = POINTTYPE_CURVE_MIDDLE; 3866 else 3867 pt->corner = POINTTYPE_CURVE_END; 3868 } 3869 outline->count--; 3870 } else { 3871 /* outline closed with a line from end to start point */ 3872 attempt_line_merge(outline, outline->count - 1, &pt->pos, FALSE); 3873 } 3874 lastpt = &outline->items[0]; 3875 to_curve = lastpt->corner != POINTTYPE_CORNER && lastpt->corner != POINTTYPE_CURVE_END; 3876 if (lastpt->corner == POINTTYPE_CURVE_START) 3877 lastpt->corner = POINTTYPE_CORNER; 3878 pt = &outline->items[1]; 3879 if (attempt_line_merge(outline, 0, &pt->pos, to_curve)) 3880 *lastpt = outline->items[outline->count]; 3881 } 3882 3883 lastpt = &outline->items[outline->count - 1]; 3884 pt = &outline->items[0]; 3885 unit_vec2(&lastdir, &lastpt->pos, &pt->pos); 3886 for (j = 0; j < outline->count; j++) 3887 { 3888 D3DXVECTOR2 curdir; 3889 3890 lastpt = pt; 3891 pt = &outline->items[(j + 1) % outline->count]; 3892 unit_vec2(&curdir, &lastpt->pos, &pt->pos); 3893 3894 switch (lastpt->corner) 3895 { 3896 case POINTTYPE_CURVE_START: 3897 case POINTTYPE_CURVE_END: 3898 if (!is_direction_similar(&lastdir, &curdir, cos_45)) 3899 lastpt->corner = POINTTYPE_CORNER; 3900 break; 3901 case POINTTYPE_CURVE_MIDDLE: 3902 if (!is_direction_similar(&lastdir, &curdir, cos_90)) 3903 lastpt->corner = POINTTYPE_CORNER; 3904 else 3905 lastpt->corner = POINTTYPE_CURVE; 3906 break; 3907 default: 3908 break; 3909 } 3910 lastdir = curdir; 3911 } 3912 3913 header = (TTPOLYGONHEADER *)((char *)header + header->cb); 3914 } 3915 return S_OK; 3916 } 3917 3918 static void free_outline(struct outline *outline) 3919 { 3920 HeapFree(GetProcessHeap(), 0, outline->items); 3921 } 3922 3923 static void free_glyphinfo(struct glyphinfo *glyph) 3924 { 3925 unsigned int i; 3926 3927 for (i = 0; i < glyph->outlines.count; ++i) 3928 free_outline(&glyph->outlines.items[i]); 3929 HeapFree(GetProcessHeap(), 0, glyph->outlines.items); 3930 } 3931 3932 static void compute_text_mesh(struct mesh *mesh, const char *text, 3933 float deviation, float extrusion, float otmEMSquare, const struct glyphinfo *glyphs) 3934 { 3935 DWORD nb_vertices, nb_faces; 3936 DWORD nb_corners, nb_outline_points; 3937 int textlen = 0; 3938 int i; 3939 struct vertex *vertex_ptr; 3940 face *face_ptr; 3941 3942 textlen = strlen(text); 3943 3944 /* corner points need an extra vertex for the different side faces normals */ 3945 nb_corners = 0; 3946 nb_outline_points = 0; 3947 for (i = 0; i < textlen; i++) 3948 { 3949 int j; 3950 for (j = 0; j < glyphs[i].outlines.count; j++) 3951 { 3952 int k; 3953 struct outline *outline = &glyphs[i].outlines.items[j]; 3954 nb_outline_points += outline->count; 3955 nb_corners++; /* first outline point always repeated as a corner */ 3956 for (k = 1; k < outline->count; k++) 3957 if (outline->items[k].corner) 3958 nb_corners++; 3959 } 3960 } 3961 3962 nb_vertices = (nb_outline_points + nb_corners) * 2 + textlen; 3963 nb_faces = nb_outline_points * 2; 3964 3965 ok(new_mesh(mesh, nb_vertices, nb_faces), "Failed to create reference text mesh.\n"); 3966 3967 /* convert 2D vertices and faces into 3D mesh */ 3968 vertex_ptr = mesh->vertices; 3969 face_ptr = mesh->faces; 3970 for (i = 0; i < textlen; i++) 3971 { 3972 int j; 3973 3974 /* side vertices and faces */ 3975 for (j = 0; j < glyphs[i].outlines.count; j++) 3976 { 3977 struct vertex *outline_vertices = vertex_ptr; 3978 struct outline *outline = &glyphs[i].outlines.items[j]; 3979 int k; 3980 struct point2d *prevpt = &outline->items[outline->count - 1]; 3981 struct point2d *pt = &outline->items[0]; 3982 3983 for (k = 1; k <= outline->count; k++) 3984 { 3985 struct vertex vtx; 3986 struct point2d *nextpt = &outline->items[k % outline->count]; 3987 WORD vtx_idx = vertex_ptr - mesh->vertices; 3988 D3DXVECTOR2 vec; 3989 3990 if (pt->corner == POINTTYPE_CURVE_START) 3991 D3DXVec2Subtract(&vec, &pt->pos, &prevpt->pos); 3992 else if (pt->corner) 3993 D3DXVec2Subtract(&vec, &nextpt->pos, &pt->pos); 3994 else 3995 D3DXVec2Subtract(&vec, &nextpt->pos, &prevpt->pos); 3996 D3DXVec2Normalize(&vec, &vec); 3997 vtx.normal.x = -vec.y; 3998 vtx.normal.y = vec.x; 3999 vtx.normal.z = 0; 4000 4001 vtx.position.x = pt->pos.x + glyphs[i].offset_x; 4002 vtx.position.y = pt->pos.y; 4003 vtx.position.z = 0; 4004 *vertex_ptr++ = vtx; 4005 4006 vtx.position.z = -extrusion; 4007 *vertex_ptr++ = vtx; 4008 4009 vtx.position.x = nextpt->pos.x + glyphs[i].offset_x; 4010 vtx.position.y = nextpt->pos.y; 4011 if (pt->corner && nextpt->corner && nextpt->corner != POINTTYPE_CURVE_END) { 4012 vtx.position.z = -extrusion; 4013 *vertex_ptr++ = vtx; 4014 vtx.position.z = 0; 4015 *vertex_ptr++ = vtx; 4016 4017 (*face_ptr)[0] = vtx_idx; 4018 (*face_ptr)[1] = vtx_idx + 2; 4019 (*face_ptr)[2] = vtx_idx + 1; 4020 face_ptr++; 4021 4022 (*face_ptr)[0] = vtx_idx; 4023 (*face_ptr)[1] = vtx_idx + 3; 4024 (*face_ptr)[2] = vtx_idx + 2; 4025 face_ptr++; 4026 } else { 4027 if (nextpt->corner) { 4028 if (nextpt->corner == POINTTYPE_CURVE_END) { 4029 struct point2d *nextpt2 = &outline->items[(k + 1) % outline->count]; 4030 D3DXVec2Subtract(&vec, &nextpt2->pos, &nextpt->pos); 4031 } else { 4032 D3DXVec2Subtract(&vec, &nextpt->pos, &pt->pos); 4033 } 4034 D3DXVec2Normalize(&vec, &vec); 4035 vtx.normal.x = -vec.y; 4036 vtx.normal.y = vec.x; 4037 4038 vtx.position.z = 0; 4039 *vertex_ptr++ = vtx; 4040 vtx.position.z = -extrusion; 4041 *vertex_ptr++ = vtx; 4042 } 4043 4044 (*face_ptr)[0] = vtx_idx; 4045 (*face_ptr)[1] = vtx_idx + 3; 4046 (*face_ptr)[2] = vtx_idx + 1; 4047 face_ptr++; 4048 4049 (*face_ptr)[0] = vtx_idx; 4050 (*face_ptr)[1] = vtx_idx + 2; 4051 (*face_ptr)[2] = vtx_idx + 3; 4052 face_ptr++; 4053 } 4054 4055 prevpt = pt; 4056 pt = nextpt; 4057 } 4058 if (!pt->corner) { 4059 *vertex_ptr++ = *outline_vertices++; 4060 *vertex_ptr++ = *outline_vertices++; 4061 } 4062 } 4063 4064 /* FIXME: compute expected faces */ 4065 /* Add placeholder to separate glyph outlines */ 4066 vertex_ptr->position.x = 0; 4067 vertex_ptr->position.y = 0; 4068 vertex_ptr->position.z = 0; 4069 vertex_ptr->normal.x = 0; 4070 vertex_ptr->normal.y = 0; 4071 vertex_ptr->normal.z = 1; 4072 vertex_ptr++; 4073 } 4074 } 4075 4076 static void compare_text_outline_mesh(const char *name, ID3DXMesh *d3dxmesh, struct mesh *mesh, 4077 size_t textlen, float extrusion, const struct glyphinfo *glyphs) 4078 { 4079 HRESULT hr; 4080 DWORD number_of_vertices, number_of_faces; 4081 IDirect3DVertexBuffer9 *vertex_buffer = NULL; 4082 IDirect3DIndexBuffer9 *index_buffer = NULL; 4083 D3DVERTEXBUFFER_DESC vertex_buffer_description; 4084 D3DINDEXBUFFER_DESC index_buffer_description; 4085 struct vertex *vertices = NULL; 4086 face *faces = NULL; 4087 int expected, i; 4088 int vtx_idx1, face_idx1, vtx_idx2, face_idx2; 4089 4090 number_of_vertices = d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh); 4091 number_of_faces = d3dxmesh->lpVtbl->GetNumFaces(d3dxmesh); 4092 4093 hr = d3dxmesh->lpVtbl->GetVertexBuffer(d3dxmesh, &vertex_buffer); 4094 ok(hr == D3D_OK, "Test %s, unexpected hr %#x.\n", name, hr); 4095 hr = IDirect3DVertexBuffer9_GetDesc(vertex_buffer, &vertex_buffer_description); 4096 ok(hr == D3D_OK, "Test %s, unexpected hr %#x.\n", name, hr); 4097 ok(vertex_buffer_description.Format == D3DFMT_VERTEXDATA, "Test %s, unexpected format %u.\n", 4098 name, vertex_buffer_description.Format); 4099 ok(vertex_buffer_description.Type == D3DRTYPE_VERTEXBUFFER, "Test %s, unexpected resource type %u.\n", 4100 name, vertex_buffer_description.Type); 4101 ok(!vertex_buffer_description.Usage, "Test %s, unexpected usage %#x.\n", name, vertex_buffer_description.Usage); 4102 ok(vertex_buffer_description.Pool == D3DPOOL_MANAGED, "Test %s, unexpected pool %u.\n", 4103 name, vertex_buffer_description.Pool); 4104 ok(vertex_buffer_description.FVF == mesh->fvf, "Test %s, unexpected FVF %#x (expected %#x).\n", 4105 name, vertex_buffer_description.FVF, mesh->fvf); 4106 if (!mesh->fvf) 4107 expected = number_of_vertices * mesh->vertex_size; 4108 else 4109 expected = number_of_vertices * D3DXGetFVFVertexSize(mesh->fvf); 4110 ok(vertex_buffer_description.Size == expected, "Test %s, unexpected size %u (expected %u).\n", 4111 name, vertex_buffer_description.Size, expected); 4112 4113 hr = d3dxmesh->lpVtbl->GetIndexBuffer(d3dxmesh, &index_buffer); 4114 ok(hr == D3D_OK, "Test %s, unexpected hr %#x.\n", name, hr); 4115 hr = IDirect3DIndexBuffer9_GetDesc(index_buffer, &index_buffer_description); 4116 ok(hr == D3D_OK, "Test %s, unexpected hr %#x.\n", name, hr); 4117 ok(index_buffer_description.Format == D3DFMT_INDEX16, "Test %s, unexpected format %u.\n", 4118 name, index_buffer_description.Format); 4119 ok(index_buffer_description.Type == D3DRTYPE_INDEXBUFFER, "Test %s, unexpected resource type %u.\n", 4120 name, index_buffer_description.Type); 4121 ok(!index_buffer_description.Usage, "Test %s, unexpected usage %#x.\n", 4122 name, index_buffer_description.Usage); 4123 ok(index_buffer_description.Pool == D3DPOOL_MANAGED, "Test %s, unexpected pool %u.\n", 4124 name, index_buffer_description.Pool); 4125 expected = number_of_faces * sizeof(WORD) * 3; 4126 ok(index_buffer_description.Size == expected, "Test %s, unexpected size %u.\n", 4127 name, index_buffer_description.Size); 4128 4129 hr = IDirect3DVertexBuffer9_Lock(vertex_buffer, 0, number_of_vertices * sizeof(D3DXVECTOR3) * 2, 4130 (void **)&vertices, D3DLOCK_DISCARD); 4131 ok(hr == D3D_OK, "Test %s, unexpected hr %#x.\n", name, hr); 4132 hr = IDirect3DIndexBuffer9_Lock(index_buffer, 0, number_of_faces * sizeof(WORD) * 3, 4133 (void **)&faces, D3DLOCK_DISCARD); 4134 ok(hr == D3D_OK, "Test %s, unexpected hr %#x.\n", name, hr); 4135 face_idx1 = 0; 4136 vtx_idx2 = 0; 4137 face_idx2 = 0; 4138 vtx_idx1 = 0; 4139 for (i = 0; i < textlen; i++) 4140 { 4141 int nb_outline_vertices1, nb_outline_faces1; 4142 int nb_outline_vertices2, nb_outline_faces2; 4143 int nb_back_vertices, nb_back_faces; 4144 int first_vtx1, first_vtx2; 4145 int first_face1, first_face2; 4146 int j; 4147 4148 first_vtx1 = vtx_idx1; 4149 first_vtx2 = vtx_idx2; 4150 /* Glyphs without outlines do not generate any vertices. */ 4151 if (glyphs[i].outlines.count > 0) 4152 { 4153 for (; vtx_idx1 < number_of_vertices; vtx_idx1++) 4154 { 4155 if (vertices[vtx_idx1].normal.z != 0) 4156 break; 4157 } 4158 4159 for (; vtx_idx2 < mesh->number_of_vertices; vtx_idx2++) 4160 { 4161 if (mesh->vertices[vtx_idx2].normal.z != 0) 4162 break; 4163 } 4164 } 4165 nb_outline_vertices1 = vtx_idx1 - first_vtx1; 4166 nb_outline_vertices2 = vtx_idx2 - first_vtx2; 4167 ok(nb_outline_vertices1 == nb_outline_vertices2, 4168 "Test %s, glyph %d, outline vertex count result %d, expected %d\n", name, i, 4169 nb_outline_vertices1, nb_outline_vertices2); 4170 4171 for (j = 0; j < min(nb_outline_vertices1, nb_outline_vertices2); j++) 4172 { 4173 vtx_idx1 = first_vtx1 + j; 4174 vtx_idx2 = first_vtx2 + j; 4175 ok(compare_vec3(vertices[vtx_idx1].position, mesh->vertices[vtx_idx2].position), 4176 "Test %s, glyph %d, vertex position %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1, 4177 vertices[vtx_idx1].position.x, vertices[vtx_idx1].position.y, vertices[vtx_idx1].position.z, 4178 mesh->vertices[vtx_idx2].position.x, mesh->vertices[vtx_idx2].position.y, mesh->vertices[vtx_idx2].position.z); 4179 ok(compare_vec3(vertices[vtx_idx1].normal, mesh->vertices[first_vtx2 + j].normal), 4180 "Test %s, glyph %d, vertex normal %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1, 4181 vertices[vtx_idx1].normal.x, vertices[vtx_idx1].normal.y, vertices[vtx_idx1].normal.z, 4182 mesh->vertices[vtx_idx2].normal.x, mesh->vertices[vtx_idx2].normal.y, mesh->vertices[vtx_idx2].normal.z); 4183 } 4184 vtx_idx1 = first_vtx1 + nb_outline_vertices1; 4185 vtx_idx2 = first_vtx2 + nb_outline_vertices2; 4186 4187 first_face1 = face_idx1; 4188 first_face2 = face_idx2; 4189 for (; face_idx1 < number_of_faces; face_idx1++) 4190 { 4191 if (faces[face_idx1][0] >= vtx_idx1 || 4192 faces[face_idx1][1] >= vtx_idx1 || 4193 faces[face_idx1][2] >= vtx_idx1) 4194 break; 4195 } 4196 for (; face_idx2 < mesh->number_of_faces; face_idx2++) 4197 { 4198 if (mesh->faces[face_idx2][0] >= vtx_idx2 || 4199 mesh->faces[face_idx2][1] >= vtx_idx2 || 4200 mesh->faces[face_idx2][2] >= vtx_idx2) 4201 break; 4202 } 4203 nb_outline_faces1 = face_idx1 - first_face1; 4204 nb_outline_faces2 = face_idx2 - first_face2; 4205 ok(nb_outline_faces1 == nb_outline_faces2, 4206 "Test %s, glyph %d, outline face count result %d, expected %d\n", name, i, 4207 nb_outline_faces1, nb_outline_faces2); 4208 4209 for (j = 0; j < min(nb_outline_faces1, nb_outline_faces2); j++) 4210 { 4211 face_idx1 = first_face1 + j; 4212 face_idx2 = first_face2 + j; 4213 ok(faces[face_idx1][0] - first_vtx1 == mesh->faces[face_idx2][0] - first_vtx2 && 4214 faces[face_idx1][1] - first_vtx1 == mesh->faces[face_idx2][1] - first_vtx2 && 4215 faces[face_idx1][2] - first_vtx1 == mesh->faces[face_idx2][2] - first_vtx2, 4216 "Test %s, glyph %d, face %d, result (%d, %d, %d), expected (%d, %d, %d)\n", name, i, face_idx1, 4217 faces[face_idx1][0], faces[face_idx1][1], faces[face_idx1][2], 4218 mesh->faces[face_idx2][0] - first_vtx2 + first_vtx1, 4219 mesh->faces[face_idx2][1] - first_vtx2 + first_vtx1, 4220 mesh->faces[face_idx2][2] - first_vtx2 + first_vtx1); 4221 } 4222 face_idx1 = first_face1 + nb_outline_faces1; 4223 face_idx2 = first_face2 + nb_outline_faces2; 4224 4225 /* partial test on back vertices and faces */ 4226 first_vtx1 = vtx_idx1; 4227 for (; vtx_idx1 < number_of_vertices; vtx_idx1++) { 4228 struct vertex vtx; 4229 4230 if (vertices[vtx_idx1].normal.z != 1.0f) 4231 break; 4232 4233 vtx.position.z = 0.0f; 4234 vtx.normal.x = 0.0f; 4235 vtx.normal.y = 0.0f; 4236 vtx.normal.z = 1.0f; 4237 ok(compare(vertices[vtx_idx1].position.z, vtx.position.z), 4238 "Test %s, glyph %d, vertex position.z %d, result %g, expected %g\n", name, i, vtx_idx1, 4239 vertices[vtx_idx1].position.z, vtx.position.z); 4240 ok(compare_vec3(vertices[vtx_idx1].normal, vtx.normal), 4241 "Test %s, glyph %d, vertex normal %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1, 4242 vertices[vtx_idx1].normal.x, vertices[vtx_idx1].normal.y, vertices[vtx_idx1].normal.z, 4243 vtx.normal.x, vtx.normal.y, vtx.normal.z); 4244 } 4245 nb_back_vertices = vtx_idx1 - first_vtx1; 4246 first_face1 = face_idx1; 4247 for (; face_idx1 < number_of_faces; face_idx1++) 4248 { 4249 const D3DXVECTOR3 *vtx1, *vtx2, *vtx3; 4250 D3DXVECTOR3 normal; 4251 D3DXVECTOR3 v1 = {0, 0, 0}; 4252 D3DXVECTOR3 v2 = {0, 0, 0}; 4253 D3DXVECTOR3 forward = {0.0f, 0.0f, 1.0f}; 4254 4255 if (faces[face_idx1][0] >= vtx_idx1 || 4256 faces[face_idx1][1] >= vtx_idx1 || 4257 faces[face_idx1][2] >= vtx_idx1) 4258 break; 4259 4260 vtx1 = &vertices[faces[face_idx1][0]].position; 4261 vtx2 = &vertices[faces[face_idx1][1]].position; 4262 vtx3 = &vertices[faces[face_idx1][2]].position; 4263 4264 D3DXVec3Subtract(&v1, vtx2, vtx1); 4265 D3DXVec3Subtract(&v2, vtx3, vtx2); 4266 D3DXVec3Cross(&normal, &v1, &v2); 4267 D3DXVec3Normalize(&normal, &normal); 4268 ok(!D3DXVec3Length(&normal) || compare_vec3(normal, forward), 4269 "Test %s, glyph %d, face %d normal, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, face_idx1, 4270 normal.x, normal.y, normal.z, forward.x, forward.y, forward.z); 4271 } 4272 nb_back_faces = face_idx1 - first_face1; 4273 4274 /* compare front and back faces & vertices */ 4275 if (extrusion == 0.0f) { 4276 /* Oddly there are only back faces in this case */ 4277 nb_back_vertices /= 2; 4278 nb_back_faces /= 2; 4279 face_idx1 -= nb_back_faces; 4280 vtx_idx1 -= nb_back_vertices; 4281 } 4282 for (j = 0; j < nb_back_vertices; j++) 4283 { 4284 struct vertex vtx = vertices[first_vtx1]; 4285 vtx.position.z = -extrusion; 4286 vtx.normal.x = 0.0f; 4287 vtx.normal.y = 0.0f; 4288 vtx.normal.z = extrusion == 0.0f ? 1.0f : -1.0f; 4289 ok(compare_vec3(vertices[vtx_idx1].position, vtx.position), 4290 "Test %s, glyph %d, vertex position %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1, 4291 vertices[vtx_idx1].position.x, vertices[vtx_idx1].position.y, vertices[vtx_idx1].position.z, 4292 vtx.position.x, vtx.position.y, vtx.position.z); 4293 ok(compare_vec3(vertices[vtx_idx1].normal, vtx.normal), 4294 "Test %s, glyph %d, vertex normal %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1, 4295 vertices[vtx_idx1].normal.x, vertices[vtx_idx1].normal.y, vertices[vtx_idx1].normal.z, 4296 vtx.normal.x, vtx.normal.y, vtx.normal.z); 4297 vtx_idx1++; 4298 first_vtx1++; 4299 } 4300 for (j = 0; j < nb_back_faces; j++) 4301 { 4302 int f1, f2; 4303 if (extrusion == 0.0f) { 4304 f1 = 1; 4305 f2 = 2; 4306 } else { 4307 f1 = 2; 4308 f2 = 1; 4309 } 4310 ok(faces[face_idx1][0] == faces[first_face1][0] + nb_back_vertices && 4311 faces[face_idx1][1] == faces[first_face1][f1] + nb_back_vertices && 4312 faces[face_idx1][2] == faces[first_face1][f2] + nb_back_vertices, 4313 "Test %s, glyph %d, face %d, result (%d, %d, %d), expected (%d, %d, %d)\n", name, i, face_idx1, 4314 faces[face_idx1][0], faces[face_idx1][1], faces[face_idx1][2], 4315 faces[first_face1][0] - nb_back_faces, 4316 faces[first_face1][f1] - nb_back_faces, 4317 faces[first_face1][f2] - nb_back_faces); 4318 first_face1++; 4319 face_idx1++; 4320 } 4321 4322 /* skip to the outline for the next glyph */ 4323 for (; vtx_idx2 < mesh->number_of_vertices; vtx_idx2++) { 4324 if (mesh->vertices[vtx_idx2].normal.z == 0) 4325 break; 4326 } 4327 for (; face_idx2 < mesh->number_of_faces; face_idx2++) 4328 { 4329 if (mesh->faces[face_idx2][0] >= vtx_idx2 || 4330 mesh->faces[face_idx2][1] >= vtx_idx2 || 4331 mesh->faces[face_idx2][2] >= vtx_idx2) break; 4332 } 4333 } 4334 4335 IDirect3DIndexBuffer9_Unlock(index_buffer); 4336 IDirect3DVertexBuffer9_Unlock(vertex_buffer); 4337 IDirect3DIndexBuffer9_Release(index_buffer); 4338 IDirect3DVertexBuffer9_Release(vertex_buffer); 4339 } 4340 4341 static void test_createtext(IDirect3DDevice9 *device, HDC hdc, const char *text, float deviation, float extrusion) 4342 { 4343 static const MAT2 identity = {{0, 1}, {0, 0}, {0, 0}, {0, 1}}; 4344 HRESULT hr; 4345 ID3DXMesh *d3dxmesh = NULL; 4346 struct mesh mesh = {0}; 4347 char name[256]; 4348 OUTLINETEXTMETRICA otm; 4349 GLYPHMETRICS gm; 4350 struct glyphinfo *glyphs; 4351 GLYPHMETRICSFLOAT *glyphmetrics_float = HeapAlloc(GetProcessHeap(), 0, sizeof(GLYPHMETRICSFLOAT) * strlen(text)); 4352 int i; 4353 LOGFONTA lf; 4354 float offset_x; 4355 size_t textlen; 4356 HFONT font = NULL, oldfont = NULL; 4357 char *raw_outline; 4358 4359 sprintf(name, "text ('%s', %f, %f)", text, deviation, extrusion); 4360 4361 hr = D3DXCreateTextA(device, hdc, text, deviation, extrusion, &d3dxmesh, NULL, glyphmetrics_float); 4362 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); 4363 4364 /* must select a modified font having lfHeight = otm.otmEMSquare before 4365 * calling GetGlyphOutline to get the expected values */ 4366 ok(GetObjectA(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf), "Failed to get current DC font.\n"); 4367 ok(GetOutlineTextMetricsA(hdc, sizeof(otm), &otm), "Failed to get DC font outline.\n"); 4368 lf.lfHeight = otm.otmEMSquare; 4369 lf.lfWidth = 0; 4370 ok(!!(font = CreateFontIndirectA(&lf)), "Failed to create font.\n"); 4371 4372 textlen = strlen(text); 4373 glyphs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, textlen * sizeof(*glyphs)); 4374 oldfont = SelectObject(hdc, font); 4375 4376 for (i = 0; i < textlen; i++) 4377 { 4378 GetGlyphOutlineA(hdc, text[i], GGO_NATIVE, &gm, 0, NULL, &identity); 4379 compare_float(glyphmetrics_float[i].gmfBlackBoxX, gm.gmBlackBoxX / (float)otm.otmEMSquare); 4380 compare_float(glyphmetrics_float[i].gmfBlackBoxY, gm.gmBlackBoxY / (float)otm.otmEMSquare); 4381 compare_float(glyphmetrics_float[i].gmfptGlyphOrigin.x, gm.gmptGlyphOrigin.x / (float)otm.otmEMSquare); 4382 compare_float(glyphmetrics_float[i].gmfptGlyphOrigin.y, gm.gmptGlyphOrigin.y / (float)otm.otmEMSquare); 4383 compare_float(glyphmetrics_float[i].gmfCellIncX, gm.gmCellIncX / (float)otm.otmEMSquare); 4384 compare_float(glyphmetrics_float[i].gmfCellIncY, gm.gmCellIncY / (float)otm.otmEMSquare); 4385 } 4386 4387 if (deviation == 0.0f) 4388 deviation = 1.0f / otm.otmEMSquare; 4389 4390 offset_x = 0.0f; 4391 for (i = 0; i < textlen; i++) 4392 { 4393 DWORD datasize; 4394 4395 glyphs[i].offset_x = offset_x; 4396 4397 datasize = GetGlyphOutlineA(hdc, text[i], GGO_NATIVE, &gm, 0, NULL, &identity); 4398 ok(datasize != GDI_ERROR, "Failed to retrieve GDI glyph outline size.\n"); 4399 raw_outline = HeapAlloc(GetProcessHeap(), 0, datasize); 4400 datasize = GetGlyphOutlineA(hdc, text[i], GGO_NATIVE, &gm, datasize, raw_outline, &identity); 4401 ok(datasize != GDI_ERROR, "Failed to retrieve GDI glyph outline.\n"); 4402 create_outline(&glyphs[i], raw_outline, datasize, deviation, otm.otmEMSquare); 4403 HeapFree(GetProcessHeap(), 0, raw_outline); 4404 4405 offset_x += gm.gmCellIncX / (float)otm.otmEMSquare; 4406 } 4407 4408 SelectObject(hdc, oldfont); 4409 4410 compute_text_mesh(&mesh, text, deviation, extrusion, otm.otmEMSquare, glyphs); 4411 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL; 4412 4413 compare_text_outline_mesh(name, d3dxmesh, &mesh, textlen, extrusion, glyphs); 4414 4415 free_mesh(&mesh); 4416 d3dxmesh->lpVtbl->Release(d3dxmesh); 4417 DeleteObject(font); 4418 HeapFree(GetProcessHeap(), 0, glyphmetrics_float); 4419 4420 for (i = 0; i < textlen; i++) 4421 free_glyphinfo(&glyphs[i]); 4422 HeapFree(GetProcessHeap(), 0, glyphs); 4423 } 4424 4425 static void D3DXCreateTextTest(void) 4426 { 4427 HRESULT hr; 4428 HDC hdc; 4429 IDirect3DDevice9* device; 4430 ID3DXMesh* d3dxmesh = NULL; 4431 HFONT hFont; 4432 OUTLINETEXTMETRICA otm; 4433 int number_of_vertices; 4434 int number_of_faces; 4435 struct test_context *test_context; 4436 4437 if (!(test_context = new_test_context())) 4438 { 4439 skip("Couldn't create test context\n"); 4440 return; 4441 } 4442 device = test_context->device; 4443 4444 hdc = CreateCompatibleDC(NULL); 4445 4446 hFont = CreateFontA(12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, 4447 CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, "Arial"); 4448 SelectObject(hdc, hFont); 4449 GetOutlineTextMetricsA(hdc, sizeof(otm), &otm); 4450 4451 hr = D3DXCreateTextA(device, hdc, "wine", 0.001f, 0.4f, NULL, NULL, NULL); 4452 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 4453 4454 /* D3DXCreateTextA page faults from passing NULL text */ 4455 4456 hr = D3DXCreateTextW(device, hdc, NULL, 0.001f, 0.4f, &d3dxmesh, NULL, NULL); 4457 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 4458 4459 hr = D3DXCreateTextA(device, hdc, "", 0.001f, 0.4f, &d3dxmesh, NULL, NULL); 4460 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 4461 4462 hr = D3DXCreateTextA(device, hdc, " ", 0.001f, 0.4f, &d3dxmesh, NULL, NULL); 4463 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 4464 4465 hr = D3DXCreateTextA(NULL, hdc, "wine", 0.001f, 0.4f, &d3dxmesh, NULL, NULL); 4466 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 4467 4468 hr = D3DXCreateTextA(device, NULL, "wine", 0.001f, 0.4f, &d3dxmesh, NULL, NULL); 4469 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 4470 4471 hr = D3DXCreateTextA(device, hdc, "wine", -FLT_MIN, 0.4f, &d3dxmesh, NULL, NULL); 4472 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 4473 4474 hr = D3DXCreateTextA(device, hdc, "wine", 0.001f, -FLT_MIN, &d3dxmesh, NULL, NULL); 4475 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 4476 4477 /* deviation = 0.0f treated as if deviation = 1.0f / otm.otmEMSquare */ 4478 hr = D3DXCreateTextA(device, hdc, "wine", 1.0f / otm.otmEMSquare, 0.4f, &d3dxmesh, NULL, NULL); 4479 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK); 4480 number_of_vertices = d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh); 4481 number_of_faces = d3dxmesh->lpVtbl->GetNumFaces(d3dxmesh); 4482 d3dxmesh->lpVtbl->Release(d3dxmesh); 4483 4484 hr = D3DXCreateTextA(device, hdc, "wine", 0.0f, 0.4f, &d3dxmesh, NULL, NULL); 4485 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK); 4486 ok(number_of_vertices == d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh), 4487 "Got %d vertices, expected %d\n", 4488 d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh), number_of_vertices); 4489 ok(number_of_faces == d3dxmesh->lpVtbl->GetNumFaces(d3dxmesh), 4490 "Got %d faces, expected %d\n", 4491 d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh), number_of_faces); 4492 d3dxmesh->lpVtbl->Release(d3dxmesh); 4493 4494 if (0) 4495 { 4496 /* too much detail requested, so will appear to hang */ 4497 trace("Waiting for D3DXCreateText to finish with deviation = FLT_MIN ...\n"); 4498 hr = D3DXCreateTextA(device, hdc, "wine", FLT_MIN, 0.4f, &d3dxmesh, NULL, NULL); 4499 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK); 4500 if (SUCCEEDED(hr) && d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh); 4501 trace("D3DXCreateText finish with deviation = FLT_MIN\n"); 4502 } 4503 4504 hr = D3DXCreateTextA(device, hdc, "wine", 0.001f, 0.4f, &d3dxmesh, NULL, NULL); 4505 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK); 4506 if (SUCCEEDED(hr) && d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh); 4507 4508 test_createtext(device, hdc, "wine", FLT_MAX, 0.4f); 4509 test_createtext(device, hdc, "wine", 0.001f, FLT_MIN); 4510 test_createtext(device, hdc, "wine", 0.001f, 0.0f); 4511 test_createtext(device, hdc, "wine", 0.001f, FLT_MAX); 4512 test_createtext(device, hdc, "wine", 0.0f, 1.0f); 4513 test_createtext(device, hdc, " wine", 1.0f, 0.0f); 4514 test_createtext(device, hdc, "wine ", 1.0f, 0.0f); 4515 test_createtext(device, hdc, "wi ne", 1.0f, 0.0f); 4516 4517 DeleteDC(hdc); 4518 DeleteObject(hFont); 4519 4520 free_test_context(test_context); 4521 } 4522 4523 static void test_get_decl_length(void) 4524 { 4525 static const D3DVERTEXELEMENT9 declaration1[] = 4526 { 4527 {0, 0, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4528 {1, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4529 {2, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4530 {3, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4531 {4, 0, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4532 {5, 0, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4533 {6, 0, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4534 {7, 0, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4535 {8, 0, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4536 {9, 0, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4537 {10, 0, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4538 {11, 0, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4539 {12, 0, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4540 {13, 0, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4541 {14, 0, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4542 D3DDECL_END(), 4543 }; 4544 static const D3DVERTEXELEMENT9 declaration2[] = 4545 { 4546 {0, 8, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4547 {1, 8, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4548 {2, 8, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4549 {3, 8, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4550 {4, 8, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4551 {5, 8, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4552 {6, 8, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4553 {7, 8, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4554 {0, 8, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4555 {1, 8, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4556 {2, 8, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4557 {3, 8, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4558 {4, 8, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4559 {5, 8, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4560 {6, 8, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4561 {7, 8, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4562 D3DDECL_END(), 4563 }; 4564 UINT size; 4565 4566 size = D3DXGetDeclLength(declaration1); 4567 ok(size == 15, "Got size %u, expected 15.\n", size); 4568 4569 size = D3DXGetDeclLength(declaration2); 4570 ok(size == 16, "Got size %u, expected 16.\n", size); 4571 } 4572 4573 static void test_get_decl_vertex_size(void) 4574 { 4575 static const D3DVERTEXELEMENT9 declaration1[] = 4576 { 4577 {0, 0, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4578 {1, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4579 {2, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4580 {3, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4581 {4, 0, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4582 {5, 0, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4583 {6, 0, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4584 {7, 0, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4585 {8, 0, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4586 {9, 0, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4587 {10, 0, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4588 {11, 0, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4589 {12, 0, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4590 {13, 0, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4591 {14, 0, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4592 D3DDECL_END(), 4593 }; 4594 static const D3DVERTEXELEMENT9 declaration2[] = 4595 { 4596 {0, 8, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4597 {1, 8, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4598 {2, 8, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4599 {3, 8, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4600 {4, 8, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4601 {5, 8, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4602 {6, 8, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4603 {7, 8, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4604 {0, 8, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4605 {1, 8, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4606 {2, 8, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4607 {3, 8, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4608 {4, 8, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4609 {5, 8, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4610 {6, 8, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4611 {7, 8, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4612 D3DDECL_END(), 4613 }; 4614 static const UINT sizes1[] = 4615 { 4616 4, 8, 12, 16, 4617 4, 4, 4, 8, 4618 4, 4, 8, 4, 4619 4, 4, 8, 0, 4620 }; 4621 static const UINT sizes2[] = 4622 { 4623 12, 16, 20, 24, 4624 12, 12, 16, 16, 4625 }; 4626 unsigned int i; 4627 UINT size; 4628 4629 size = D3DXGetDeclVertexSize(NULL, 0); 4630 ok(size == 0, "Got size %#x, expected 0.\n", size); 4631 4632 for (i = 0; i < 16; ++i) 4633 { 4634 size = D3DXGetDeclVertexSize(declaration1, i); 4635 ok(size == sizes1[i], "Got size %u for stream %u, expected %u.\n", size, i, sizes1[i]); 4636 } 4637 4638 for (i = 0; i < 8; ++i) 4639 { 4640 size = D3DXGetDeclVertexSize(declaration2, i); 4641 ok(size == sizes2[i], "Got size %u for stream %u, expected %u.\n", size, i, sizes2[i]); 4642 } 4643 } 4644 4645 static void D3DXGenerateAdjacencyTest(void) 4646 { 4647 HRESULT hr; 4648 IDirect3DDevice9 *device; 4649 ID3DXMesh *d3dxmesh = NULL; 4650 D3DXVECTOR3 *vertices = NULL; 4651 WORD *indices = NULL; 4652 int i; 4653 struct { 4654 DWORD num_vertices; 4655 D3DXVECTOR3 vertices[6]; 4656 DWORD num_faces; 4657 WORD indices[3 * 3]; 4658 FLOAT epsilon; 4659 DWORD adjacency[3 * 3]; 4660 } test_data[] = { 4661 { /* for epsilon < 0, indices must match for faces to be adjacent */ 4662 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}}, 4663 2, {0, 1, 2, 0, 2, 3}, 4664 -1.0, 4665 {-1, -1, 1, 0, -1, -1}, 4666 }, 4667 { 4668 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}}, 4669 2, {0, 1, 2, 3, 4, 5}, 4670 -1.0, 4671 {-1, -1, -1, -1, -1, -1}, 4672 }, 4673 { /* for epsilon == 0, indices or vertices must match for faces to be adjacent */ 4674 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}}, 4675 2, {0, 1, 2, 3, 4, 5}, 4676 0.0, 4677 {-1, -1, 1, 0, -1, -1}, 4678 }, 4679 { /* for epsilon > 0, vertices must be less than (but NOT equal to) epsilon distance away */ 4680 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}}, 4681 2, {0, 1, 2, 3, 4, 5}, 4682 0.25, 4683 {-1, -1, -1, -1, -1, -1}, 4684 }, 4685 { /* for epsilon > 0, vertices must be less than (but NOT equal to) epsilon distance away */ 4686 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}}, 4687 2, {0, 1, 2, 3, 4, 5}, 4688 0.250001, 4689 {-1, -1, 1, 0, -1, -1}, 4690 }, 4691 { /* length between vertices are compared to epsilon, not the individual dimension deltas */ 4692 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}}, 4693 2, {0, 1, 2, 3, 4, 5}, 4694 0.353, /* < sqrt(0.25*0.25 + 0.25*0.25) */ 4695 {-1, -1, -1, -1, -1, -1}, 4696 }, 4697 { 4698 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}}, 4699 2, {0, 1, 2, 3, 4, 5}, 4700 0.354, /* > sqrt(0.25*0.25 + 0.25*0.25) */ 4701 {-1, -1, 1, 0, -1, -1}, 4702 }, 4703 { /* adjacent faces must have opposite winding orders at the shared edge */ 4704 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}}, 4705 2, {0, 1, 2, 0, 3, 2}, 4706 0.0, 4707 {-1, -1, -1, -1, -1, -1}, 4708 }, 4709 }; 4710 struct test_context *test_context; 4711 4712 if (!(test_context = new_test_context())) 4713 { 4714 skip("Couldn't create test context\n"); 4715 return; 4716 } 4717 device = test_context->device; 4718 4719 for (i = 0; i < ARRAY_SIZE(test_data); i++) 4720 { 4721 DWORD adjacency[ARRAY_SIZE(test_data[0].adjacency)]; 4722 int j; 4723 4724 if (d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh); 4725 d3dxmesh = NULL; 4726 4727 hr = D3DXCreateMeshFVF(test_data[i].num_faces, test_data[i].num_vertices, 0, D3DFVF_XYZ, device, &d3dxmesh); 4728 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK); 4729 4730 hr = d3dxmesh->lpVtbl->LockVertexBuffer(d3dxmesh, D3DLOCK_DISCARD, (void**)&vertices); 4731 ok(hr == D3D_OK, "test %d: Got result %x, expected %x (D3D_OK)\n", i, hr, D3D_OK); 4732 if (FAILED(hr)) continue; 4733 CopyMemory(vertices, test_data[i].vertices, test_data[i].num_vertices * sizeof(test_data[0].vertices[0])); 4734 d3dxmesh->lpVtbl->UnlockVertexBuffer(d3dxmesh); 4735 4736 hr = d3dxmesh->lpVtbl->LockIndexBuffer(d3dxmesh, D3DLOCK_DISCARD, (void**)&indices); 4737 ok(hr == D3D_OK, "test %d: Got result %x, expected %x (D3D_OK)\n", i, hr, D3D_OK); 4738 if (FAILED(hr)) continue; 4739 CopyMemory(indices, test_data[i].indices, test_data[i].num_faces * 3 * sizeof(test_data[0].indices[0])); 4740 d3dxmesh->lpVtbl->UnlockIndexBuffer(d3dxmesh); 4741 4742 if (i == 0) { 4743 hr = d3dxmesh->lpVtbl->GenerateAdjacency(d3dxmesh, 0.0f, NULL); 4744 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 4745 } 4746 4747 hr = d3dxmesh->lpVtbl->GenerateAdjacency(d3dxmesh, test_data[i].epsilon, adjacency); 4748 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK); 4749 if (FAILED(hr)) continue; 4750 4751 for (j = 0; j < test_data[i].num_faces * 3; j++) 4752 ok(adjacency[j] == test_data[i].adjacency[j], 4753 "Test %d adjacency %d: Got result %u, expected %u\n", i, j, 4754 adjacency[j], test_data[i].adjacency[j]); 4755 } 4756 if (d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh); 4757 4758 free_test_context(test_context); 4759 } 4760 4761 static void test_update_semantics(void) 4762 { 4763 HRESULT hr; 4764 struct test_context *test_context = NULL; 4765 ID3DXMesh *mesh = NULL; 4766 D3DVERTEXELEMENT9 declaration0[] = 4767 { 4768 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4769 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 4770 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0}, 4771 D3DDECL_END() 4772 }; 4773 D3DVERTEXELEMENT9 declaration_pos_type_color[] = 4774 { 4775 {0, 0, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4776 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 4777 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0}, 4778 D3DDECL_END() 4779 }; 4780 D3DVERTEXELEMENT9 declaration_smaller[] = 4781 { 4782 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4783 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 4784 D3DDECL_END() 4785 }; 4786 D3DVERTEXELEMENT9 declaration_larger[] = 4787 { 4788 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4789 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 4790 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0}, 4791 {0, 40, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT, 0}, 4792 D3DDECL_END() 4793 }; 4794 D3DVERTEXELEMENT9 declaration_multiple_streams[] = 4795 { 4796 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4797 {1, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT, 0}, 4798 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 4799 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0}, 4800 4801 D3DDECL_END() 4802 }; 4803 D3DVERTEXELEMENT9 declaration_double_usage[] = 4804 { 4805 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4806 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4807 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 4808 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0}, 4809 D3DDECL_END() 4810 }; 4811 D3DVERTEXELEMENT9 declaration_undefined_type[] = 4812 { 4813 {0, 0, D3DDECLTYPE_UNUSED+1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4814 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 4815 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0}, 4816 D3DDECL_END() 4817 }; 4818 D3DVERTEXELEMENT9 declaration_not_4_byte_aligned_offset[] = 4819 { 4820 {0, 3, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4821 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 4822 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0}, 4823 D3DDECL_END() 4824 }; 4825 static const struct 4826 { 4827 D3DXVECTOR3 position0; 4828 D3DXVECTOR3 position1; 4829 D3DXVECTOR3 normal; 4830 DWORD color; 4831 } 4832 vertices[] = 4833 { 4834 { { 0.0f, 1.0f, 0.f}, { 1.0f, 0.0f, 0.f}, {0.0f, 0.0f, 1.0f}, 0xffff0000 }, 4835 { { 1.0f, -1.0f, 0.f}, {-1.0f, -1.0f, 0.f}, {0.0f, 0.0f, 1.0f}, 0xff00ff00 }, 4836 { {-1.0f, -1.0f, 0.f}, {-1.0f, 1.0f, 0.f}, {0.0f, 0.0f, 1.0f}, 0xff0000ff }, 4837 }; 4838 unsigned int faces[] = {0, 1, 2}; 4839 unsigned int attributes[] = {0}; 4840 unsigned int num_faces = ARRAY_SIZE(faces) / 3; 4841 unsigned int num_vertices = ARRAY_SIZE(vertices); 4842 int offset = sizeof(D3DXVECTOR3); 4843 DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM; 4844 void *vertex_buffer; 4845 void *index_buffer; 4846 DWORD *attributes_buffer; 4847 D3DVERTEXELEMENT9 declaration[MAX_FVF_DECL_SIZE]; 4848 D3DVERTEXELEMENT9 *decl_ptr; 4849 DWORD exp_vertex_size = sizeof(*vertices); 4850 DWORD vertex_size = 0; 4851 int equal; 4852 int i = 0; 4853 int *decl_mem; 4854 int filler_a = 0xaaaaaaaa; 4855 int filler_b = 0xbbbbbbbb; 4856 4857 test_context = new_test_context(); 4858 if (!test_context) 4859 { 4860 skip("Couldn't create a test_context\n"); 4861 goto cleanup; 4862 } 4863 4864 hr = D3DXCreateMesh(num_faces, num_vertices, options, declaration0, 4865 test_context->device, &mesh); 4866 if (FAILED(hr)) 4867 { 4868 skip("Couldn't create test mesh %#x\n", hr); 4869 goto cleanup; 4870 } 4871 4872 mesh->lpVtbl->LockVertexBuffer(mesh, 0, &vertex_buffer); 4873 memcpy(vertex_buffer, vertices, sizeof(vertices)); 4874 mesh->lpVtbl->UnlockVertexBuffer(mesh); 4875 4876 mesh->lpVtbl->LockIndexBuffer(mesh, 0, &index_buffer); 4877 memcpy(index_buffer, faces, sizeof(faces)); 4878 mesh->lpVtbl->UnlockIndexBuffer(mesh); 4879 4880 mesh->lpVtbl->LockAttributeBuffer(mesh, 0, &attributes_buffer); 4881 memcpy(attributes_buffer, attributes, sizeof(attributes)); 4882 mesh->lpVtbl->UnlockAttributeBuffer(mesh); 4883 4884 /* Get the declaration and try to change it */ 4885 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration); 4886 if (FAILED(hr)) 4887 { 4888 skip("Couldn't get vertex declaration %#x\n", hr); 4889 goto cleanup; 4890 } 4891 equal = memcmp(declaration, declaration0, sizeof(declaration0)); 4892 ok(equal == 0, "Vertex declarations were not equal\n"); 4893 4894 for (decl_ptr = declaration; decl_ptr->Stream != 0xFF; decl_ptr++) 4895 { 4896 if (decl_ptr->Usage == D3DDECLUSAGE_POSITION) 4897 { 4898 /* Use second vertex position instead of first */ 4899 decl_ptr->Offset = offset; 4900 } 4901 } 4902 4903 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration); 4904 ok(hr == D3D_OK, "Test UpdateSemantics, got %#x expected %#x\n", hr, D3D_OK); 4905 4906 /* Check that declaration was written by getting it again */ 4907 memset(declaration, 0, sizeof(declaration)); 4908 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration); 4909 if (FAILED(hr)) 4910 { 4911 skip("Couldn't get vertex declaration %#x\n", hr); 4912 goto cleanup; 4913 } 4914 4915 for (decl_ptr = declaration; decl_ptr->Stream != 0xFF; decl_ptr++) 4916 { 4917 if (decl_ptr->Usage == D3DDECLUSAGE_POSITION) 4918 { 4919 ok(decl_ptr->Offset == offset, "Test UpdateSemantics, got offset %d expected %d\n", 4920 decl_ptr->Offset, offset); 4921 } 4922 } 4923 4924 /* Check that GetDeclaration only writes up to the D3DDECL_END() marker and 4925 * not the full MAX_FVF_DECL_SIZE elements. 4926 */ 4927 memset(declaration, filler_a, sizeof(declaration)); 4928 memcpy(declaration, declaration0, sizeof(declaration0)); 4929 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration); 4930 ok(hr == D3D_OK, "Test UpdateSemantics, " 4931 "got %#x expected D3D_OK\n", hr); 4932 memset(declaration, filler_b, sizeof(declaration)); 4933 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration); 4934 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr); 4935 decl_mem = (int*)declaration; 4936 for (i = sizeof(declaration0)/sizeof(*decl_mem); i < sizeof(declaration)/sizeof(*decl_mem); i++) 4937 { 4938 equal = memcmp(&decl_mem[i], &filler_b, sizeof(filler_b)); 4939 ok(equal == 0, 4940 "GetDeclaration wrote past the D3DDECL_END() marker. " 4941 "Got %#x, expected %#x\n", decl_mem[i], filler_b); 4942 if (equal != 0) break; 4943 } 4944 4945 /* UpdateSemantics does not check for overlapping fields */ 4946 memset(declaration, 0, sizeof(declaration)); 4947 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration); 4948 if (FAILED(hr)) 4949 { 4950 skip("Couldn't get vertex declaration %#x\n", hr); 4951 goto cleanup; 4952 } 4953 4954 for (decl_ptr = declaration; decl_ptr->Stream != 0xFF; decl_ptr++) 4955 { 4956 if (decl_ptr->Type == D3DDECLTYPE_FLOAT3) 4957 { 4958 decl_ptr->Type = D3DDECLTYPE_FLOAT4; 4959 } 4960 } 4961 4962 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration); 4963 ok(hr == D3D_OK, "Test UpdateSemantics for overlapping fields, " 4964 "got %#x expected D3D_OK\n", hr); 4965 4966 /* Set the position type to color instead of float3 */ 4967 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_pos_type_color); 4968 ok(hr == D3D_OK, "Test UpdateSemantics position type color, " 4969 "got %#x expected D3D_OK\n", hr); 4970 4971 /* The following test cases show that NULL, smaller or larger declarations, 4972 * and declarations with non-zero Stream values are not accepted. 4973 * UpdateSemantics returns D3DERR_INVALIDCALL and the previously set 4974 * declaration will be used by DrawSubset, GetNumBytesPerVertex, and 4975 * GetDeclaration. 4976 */ 4977 4978 /* Null declaration (invalid declaration) */ 4979 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */ 4980 hr = mesh->lpVtbl->UpdateSemantics(mesh, NULL); 4981 ok(hr == D3DERR_INVALIDCALL, "Test UpdateSemantics null pointer declaration, " 4982 "got %#x expected D3DERR_INVALIDCALL\n", hr); 4983 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh); 4984 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n", 4985 vertex_size, exp_vertex_size); 4986 memset(declaration, 0, sizeof(declaration)); 4987 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration); 4988 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr); 4989 equal = memcmp(declaration, declaration0, sizeof(declaration0)); 4990 ok(equal == 0, "Vertex declarations were not equal\n"); 4991 4992 /* Smaller vertex declaration (invalid declaration) */ 4993 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */ 4994 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_smaller); 4995 ok(hr == D3DERR_INVALIDCALL, "Test UpdateSemantics for smaller vertex declaration, " 4996 "got %#x expected D3DERR_INVALIDCALL\n", hr); 4997 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh); 4998 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n", 4999 vertex_size, exp_vertex_size); 5000 memset(declaration, 0, sizeof(declaration)); 5001 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration); 5002 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr); 5003 equal = memcmp(declaration, declaration0, sizeof(declaration0)); 5004 ok(equal == 0, "Vertex declarations were not equal\n"); 5005 5006 /* Larger vertex declaration (invalid declaration) */ 5007 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */ 5008 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_larger); 5009 ok(hr == D3DERR_INVALIDCALL, "Test UpdateSemantics for larger vertex declaration, " 5010 "got %#x expected D3DERR_INVALIDCALL\n", hr); 5011 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh); 5012 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n", 5013 vertex_size, exp_vertex_size); 5014 memset(declaration, 0, sizeof(declaration)); 5015 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration); 5016 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr); 5017 equal = memcmp(declaration, declaration0, sizeof(declaration0)); 5018 ok(equal == 0, "Vertex declarations were not equal\n"); 5019 5020 /* Use multiple streams and keep the same vertex size (invalid declaration) */ 5021 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */ 5022 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_multiple_streams); 5023 ok(hr == D3DERR_INVALIDCALL, "Test UpdateSemantics using multiple streams, " 5024 "got %#x expected D3DERR_INVALIDCALL\n", hr); 5025 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh); 5026 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n", 5027 vertex_size, exp_vertex_size); 5028 memset(declaration, 0, sizeof(declaration)); 5029 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration); 5030 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr); 5031 equal = memcmp(declaration, declaration0, sizeof(declaration0)); 5032 ok(equal == 0, "Vertex declarations were not equal\n"); 5033 5034 /* The next following test cases show that some invalid declarations are 5035 * accepted with a D3D_OK. An access violation is thrown on Windows if 5036 * DrawSubset is called. The methods GetNumBytesPerVertex and GetDeclaration 5037 * are not affected, which indicates that the declaration is cached. 5038 */ 5039 5040 /* Double usage (invalid declaration) */ 5041 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */ 5042 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_double_usage); 5043 ok(hr == D3D_OK, "Test UpdateSemantics double usage, " 5044 "got %#x expected D3D_OK\n", hr); 5045 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh); 5046 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n", 5047 vertex_size, exp_vertex_size); 5048 memset(declaration, 0, sizeof(declaration)); 5049 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration); 5050 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr); 5051 equal = memcmp(declaration, declaration_double_usage, sizeof(declaration_double_usage)); 5052 ok(equal == 0, "Vertex declarations were not equal\n"); 5053 5054 /* Set the position to an undefined type (invalid declaration) */ 5055 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */ 5056 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_undefined_type); 5057 ok(hr == D3D_OK, "Test UpdateSemantics undefined type, " 5058 "got %#x expected D3D_OK\n", hr); 5059 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh); 5060 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n", 5061 vertex_size, exp_vertex_size); 5062 memset(declaration, 0, sizeof(declaration)); 5063 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration); 5064 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr); 5065 equal = memcmp(declaration, declaration_undefined_type, sizeof(declaration_undefined_type)); 5066 ok(equal == 0, "Vertex declarations were not equal\n"); 5067 5068 /* Use a not 4 byte aligned offset (invalid declaration) */ 5069 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */ 5070 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_not_4_byte_aligned_offset); 5071 ok(hr == D3D_OK, "Test UpdateSemantics not 4 byte aligned offset, " 5072 "got %#x expected D3D_OK\n", hr); 5073 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh); 5074 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n", 5075 vertex_size, exp_vertex_size); 5076 memset(declaration, 0, sizeof(declaration)); 5077 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration); 5078 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr); 5079 equal = memcmp(declaration, declaration_not_4_byte_aligned_offset, 5080 sizeof(declaration_not_4_byte_aligned_offset)); 5081 ok(equal == 0, "Vertex declarations were not equal\n"); 5082 5083 cleanup: 5084 if (mesh) 5085 mesh->lpVtbl->Release(mesh); 5086 5087 free_test_context(test_context); 5088 } 5089 5090 static void test_create_skin_info(void) 5091 { 5092 HRESULT hr; 5093 ID3DXSkinInfo *skininfo = NULL; 5094 D3DVERTEXELEMENT9 empty_declaration[] = { D3DDECL_END() }; 5095 D3DVERTEXELEMENT9 declaration_out[MAX_FVF_DECL_SIZE]; 5096 const D3DVERTEXELEMENT9 declaration_with_nonzero_stream[] = { 5097 {1, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 5098 D3DDECL_END() 5099 }; 5100 5101 hr = D3DXCreateSkinInfo(0, empty_declaration, 0, &skininfo); 5102 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 5103 if (skininfo) IUnknown_Release(skininfo); 5104 skininfo = NULL; 5105 5106 hr = D3DXCreateSkinInfo(1, NULL, 1, &skininfo); 5107 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 5108 5109 hr = D3DXCreateSkinInfo(1, declaration_with_nonzero_stream, 1, &skininfo); 5110 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 5111 5112 hr = D3DXCreateSkinInfoFVF(1, 0, 1, &skininfo); 5113 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 5114 if (skininfo) 5115 { 5116 DWORD dword_result; 5117 float flt_result; 5118 const char *string_result; 5119 D3DXMATRIX *transform; 5120 D3DXMATRIX identity_matrix; 5121 5122 /* test initial values */ 5123 hr = skininfo->lpVtbl->GetDeclaration(skininfo, declaration_out); 5124 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 5125 if (SUCCEEDED(hr)) 5126 compare_elements(declaration_out, empty_declaration, __LINE__, 0); 5127 5128 dword_result = skininfo->lpVtbl->GetNumBones(skininfo); 5129 ok(dword_result == 1, "Expected 1, got %u\n", dword_result); 5130 5131 flt_result = skininfo->lpVtbl->GetMinBoneInfluence(skininfo); 5132 ok(flt_result == 0.0f, "Expected 0.0, got %g\n", flt_result); 5133 5134 string_result = skininfo->lpVtbl->GetBoneName(skininfo, 0); 5135 ok(string_result == NULL, "Expected NULL, got %p\n", string_result); 5136 5137 dword_result = skininfo->lpVtbl->GetFVF(skininfo); 5138 ok(dword_result == 0, "Expected 0, got %u\n", dword_result); 5139 5140 dword_result = skininfo->lpVtbl->GetNumBoneInfluences(skininfo, 0); 5141 ok(dword_result == 0, "Expected 0, got %u\n", dword_result); 5142 5143 dword_result = skininfo->lpVtbl->GetNumBoneInfluences(skininfo, 1); 5144 ok(dword_result == 0, "Expected 0, got %u\n", dword_result); 5145 5146 transform = skininfo->lpVtbl->GetBoneOffsetMatrix(skininfo, -1); 5147 ok(transform == NULL, "Expected NULL, got %p\n", transform); 5148 5149 { 5150 /* test [GS]etBoneOffsetMatrix */ 5151 hr = skininfo->lpVtbl->SetBoneOffsetMatrix(skininfo, 1, &identity_matrix); 5152 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 5153 5154 hr = skininfo->lpVtbl->SetBoneOffsetMatrix(skininfo, 0, NULL); 5155 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 5156 5157 D3DXMatrixIdentity(&identity_matrix); 5158 hr = skininfo->lpVtbl->SetBoneOffsetMatrix(skininfo, 0, &identity_matrix); 5159 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 5160 5161 transform = skininfo->lpVtbl->GetBoneOffsetMatrix(skininfo, 0); 5162 check_matrix(transform, &identity_matrix); 5163 } 5164 5165 { 5166 /* test [GS]etBoneName */ 5167 const char *name_in = "testBoneName"; 5168 const char *string_result2; 5169 5170 hr = skininfo->lpVtbl->SetBoneName(skininfo, 1, name_in); 5171 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 5172 5173 hr = skininfo->lpVtbl->SetBoneName(skininfo, 0, NULL); 5174 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 5175 5176 hr = skininfo->lpVtbl->SetBoneName(skininfo, 0, name_in); 5177 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 5178 5179 string_result = skininfo->lpVtbl->GetBoneName(skininfo, 0); 5180 ok(string_result != NULL, "Expected non-NULL string, got %p\n", string_result); 5181 ok(!strcmp(string_result, name_in), "Expected '%s', got '%s'\n", name_in, string_result); 5182 5183 string_result2 = skininfo->lpVtbl->GetBoneName(skininfo, 0); 5184 ok(string_result == string_result2, "Expected %p, got %p\n", string_result, string_result2); 5185 5186 string_result = skininfo->lpVtbl->GetBoneName(skininfo, 1); 5187 ok(string_result == NULL, "Expected NULL, got %p\n", string_result); 5188 } 5189 5190 { 5191 /* test [GS]etBoneInfluence */ 5192 DWORD vertices[2]; 5193 FLOAT weights[2]; 5194 int i; 5195 DWORD num_influences; 5196 DWORD exp_vertices[2]; 5197 FLOAT exp_weights[2]; 5198 5199 /* vertex and weight arrays untouched when num_influences is 0 */ 5200 vertices[0] = 0xdeadbeef; 5201 weights[0] = FLT_MAX; 5202 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, vertices, weights); 5203 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 5204 ok(vertices[0] == 0xdeadbeef, "expected 0xdeadbeef, got %#x\n", vertices[0]); 5205 ok(weights[0] == FLT_MAX, "expected %g, got %g\n", FLT_MAX, weights[0]); 5206 5207 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 1, vertices, weights); 5208 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 5209 5210 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, NULL, NULL); 5211 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 5212 5213 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, vertices, NULL); 5214 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 5215 5216 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, NULL, weights); 5217 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 5218 5219 5220 /* no vertex or weight value checking */ 5221 exp_vertices[0] = 0; 5222 exp_vertices[1] = 0x87654321; 5223 exp_weights[0] = 0.5; 5224 exp_weights[1] = NAN; 5225 num_influences = 2; 5226 5227 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 1, num_influences, vertices, weights); 5228 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 5229 5230 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, num_influences, NULL, weights); 5231 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 5232 5233 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, num_influences, vertices, NULL); 5234 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 5235 5236 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, num_influences, NULL, NULL); 5237 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 5238 5239 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, num_influences, exp_vertices, exp_weights); 5240 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 5241 5242 memset(vertices, 0, sizeof(vertices)); 5243 memset(weights, 0, sizeof(weights)); 5244 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, vertices, weights); 5245 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 5246 for (i = 0; i < num_influences; i++) { 5247 ok(exp_vertices[i] == vertices[i], 5248 "influence[%d]: expected vertex %u, got %u\n", i, exp_vertices[i], vertices[i]); 5249 ok((isnan(exp_weights[i]) && isnan(weights[i])) || exp_weights[i] == weights[i], 5250 "influence[%d]: expected weights %g, got %g\n", i, exp_weights[i], weights[i]); 5251 } 5252 5253 /* vertices and weights aren't returned after setting num_influences to 0 */ 5254 memset(vertices, 0, sizeof(vertices)); 5255 memset(weights, 0, sizeof(weights)); 5256 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, 0, vertices, weights); 5257 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 5258 5259 vertices[0] = 0xdeadbeef; 5260 weights[0] = FLT_MAX; 5261 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, vertices, weights); 5262 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 5263 ok(vertices[0] == 0xdeadbeef, "expected vertex 0xdeadbeef, got %u\n", vertices[0]); 5264 ok(weights[0] == FLT_MAX, "expected weight %g, got %g\n", FLT_MAX, weights[0]); 5265 } 5266 5267 { 5268 /* test [GS]etFVF and [GS]etDeclaration */ 5269 D3DVERTEXELEMENT9 declaration_in[MAX_FVF_DECL_SIZE]; 5270 DWORD fvf = D3DFVF_XYZ; 5271 DWORD got_fvf; 5272 5273 hr = skininfo->lpVtbl->SetDeclaration(skininfo, NULL); 5274 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 5275 5276 hr = skininfo->lpVtbl->SetDeclaration(skininfo, declaration_with_nonzero_stream); 5277 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 5278 5279 hr = skininfo->lpVtbl->SetFVF(skininfo, 0); 5280 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 5281 5282 hr = D3DXDeclaratorFromFVF(fvf, declaration_in); 5283 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 5284 hr = skininfo->lpVtbl->SetDeclaration(skininfo, declaration_in); 5285 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 5286 got_fvf = skininfo->lpVtbl->GetFVF(skininfo); 5287 ok(fvf == got_fvf, "Expected %#x, got %#x\n", fvf, got_fvf); 5288 hr = skininfo->lpVtbl->GetDeclaration(skininfo, declaration_out); 5289 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 5290 compare_elements(declaration_out, declaration_in, __LINE__, 0); 5291 5292 hr = skininfo->lpVtbl->SetDeclaration(skininfo, empty_declaration); 5293 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 5294 got_fvf = skininfo->lpVtbl->GetFVF(skininfo); 5295 ok(got_fvf == 0, "Expected 0, got %#x\n", got_fvf); 5296 hr = skininfo->lpVtbl->GetDeclaration(skininfo, declaration_out); 5297 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 5298 compare_elements(declaration_out, empty_declaration, __LINE__, 0); 5299 5300 hr = skininfo->lpVtbl->SetFVF(skininfo, fvf); 5301 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 5302 got_fvf = skininfo->lpVtbl->GetFVF(skininfo); 5303 ok(fvf == got_fvf, "Expected %#x, got %#x\n", fvf, got_fvf); 5304 hr = skininfo->lpVtbl->GetDeclaration(skininfo, declaration_out); 5305 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 5306 compare_elements(declaration_out, declaration_in, __LINE__, 0); 5307 } 5308 } 5309 if (skininfo) IUnknown_Release(skininfo); 5310 skininfo = NULL; 5311 5312 hr = D3DXCreateSkinInfoFVF(1, D3DFVF_XYZ, 1, NULL); 5313 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 5314 5315 hr = D3DXCreateSkinInfo(1, NULL, 1, &skininfo); 5316 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 5317 } 5318 5319 static void test_update_skinned_mesh(void) 5320 { 5321 static DWORD bone0_vertices[2] = { 1, 3 }; 5322 static FLOAT bone0_weights[2] = { 1.0f, 0.5f }; 5323 static DWORD bone1_vertices[2] = { 2, 3 }; 5324 static FLOAT bone1_weights[2] = { 1.0f, 0.5f }; 5325 static D3DMATRIX bones_matrix[2] = 5326 { { { { 5327 1.0f, 0.0f, 0.0f, 0.0f, 5328 0.0f, 1.0f, 0.0f, 0.0f, 5329 0.0f, 0.0f, 1.0f, 0.0f, 5330 2.0f, 2.0f, 4.0f, 1.0f 5331 } } }, 5332 { { { 5333 1.0f, 0.0f, 0.0f, 0.0f, 5334 0.0f, 1.0f, 0.0f, 0.0f, 5335 0.0f, 0.0f, 1.0f, 0.0f, 5336 -4.0f, -4.0f, 4.0f, 1.0f 5337 } } } }; 5338 static D3DVECTOR vertices_src[] = {{ 1.0f, 1.0f, 1.0f }, 5339 { 1.0f, 0.0f, 0.0f }, 5340 { 1.0f, 1.0f, -1.0f }, 5341 { 0.0f, 1.0f, 0.0f }, 5342 { -1.0f, -1.0f, 1.0f }, 5343 { 0.0f, 0.0f, 1.0f }, 5344 { -1.0f, -1.0f, -1.0f }, 5345 { -1.0f, 0.0f, 0.0f }, 5346 }; 5347 static D3DVECTOR vertices_ref[] = {{ 0.0f, 0.0f, 0.0f }, 5348 { 0.0f, 0.0f, 0.0f }, 5349 { 3.0f, 3.0f, 3.0f }, 5350 { 0.0f, 1.0f, 0.0f }, 5351 { -5.0f, -5.0f, 5.0f }, 5352 { 0.0f, 0.0f, 1.0f }, 5353 { -2.0f, -2.0f, 3.0f }, 5354 { -1.0f, 0.0f, 0.0f }, 5355 }; 5356 D3DVECTOR vertices_dest[8]; 5357 HRESULT hr; 5358 ID3DXSkinInfo *skin_info; 5359 D3DXMATRIX matrix; 5360 int i; 5361 5362 D3DXMatrixIdentity(&matrix); 5363 for (i = 0; i < 8; i++) 5364 { 5365 vertices_dest[i].x = 10000.0f; 5366 vertices_dest[i].y = 10000.0f; 5367 vertices_dest[i].z = 10000.0f; 5368 } 5369 5370 hr = D3DXCreateSkinInfoFVF(4, D3DFVF_XYZ | D3DFVF_NORMAL, 2, &skin_info); 5371 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 5372 5373 skin_info->lpVtbl->SetBoneInfluence(skin_info, 0, 2, bone0_vertices, bone0_weights); 5374 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 5375 skin_info->lpVtbl->SetBoneOffsetMatrix(skin_info, 0, &matrix); 5376 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 5377 skin_info->lpVtbl->SetBoneInfluence(skin_info, 1, 2, bone1_vertices, bone1_weights); 5378 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 5379 skin_info->lpVtbl->SetBoneOffsetMatrix(skin_info, 1, &matrix); 5380 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 5381 skin_info->lpVtbl->UpdateSkinnedMesh(skin_info, bones_matrix, NULL, vertices_src, vertices_dest); 5382 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 5383 for (i = 0; i < 4; i++) 5384 { 5385 ok(compare(vertices_dest[i*2].x, vertices_ref[i*2].x), "Vertex[%d].position.x: got %g, expected %g\n", 5386 i, vertices_dest[i*2].x, vertices_ref[i*2].x); 5387 ok(compare(vertices_dest[i*2].y, vertices_ref[i*2].y), "Vertex[%d].position.y: got %g, expected %g\n", 5388 i, vertices_dest[i*2].y, vertices_ref[i*2].y); 5389 ok(compare(vertices_dest[i*2].z, vertices_ref[i*2].z), "Vertex[%d].position.z: got %g, expected %g\n", 5390 i, vertices_dest[i*2].z, vertices_ref[i*2].z); 5391 ok(compare(vertices_dest[i*2+1].x, vertices_ref[i*2+1].x), "Vertex[%d].normal.x: got %g, expected %g\n", 5392 i, vertices_dest[i*2+1].x, vertices_ref[i*2+1].x); 5393 ok(compare(vertices_dest[i*2+1].y, vertices_ref[i*2+1].y), "Vertex[%d].normal.y: got %g, expected %g\n", 5394 i, vertices_dest[i*2+1].y, vertices_ref[i*2+1].y); 5395 ok(compare(vertices_dest[i*2+1].z, vertices_ref[i*2+1].z), "Vertex[%d].normal.z: got %g, expected %g\n", 5396 i, vertices_dest[i*2+1].z, vertices_ref[i*2+1].z); 5397 } 5398 skin_info->lpVtbl->Release(skin_info); 5399 } 5400 5401 static void test_convert_adjacency_to_point_reps(void) 5402 { 5403 HRESULT hr; 5404 struct test_context *test_context = NULL; 5405 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM; 5406 const DWORD options_16bit = D3DXMESH_SYSTEMMEM; 5407 const D3DVERTEXELEMENT9 declaration[] = 5408 { 5409 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 5410 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 5411 {0, 24, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0}, 5412 D3DDECL_END() 5413 }; 5414 const unsigned int VERTS_PER_FACE = 3; 5415 void *vertex_buffer; 5416 void *index_buffer; 5417 DWORD *attributes_buffer; 5418 int i, j; 5419 enum color { RED = 0xffff0000, GREEN = 0xff00ff00, BLUE = 0xff0000ff}; 5420 struct vertex_pnc 5421 { 5422 D3DXVECTOR3 position; 5423 D3DXVECTOR3 normal; 5424 enum color color; /* In case of manual visual inspection */ 5425 }; 5426 #ifndef __REACTOS__ 5427 D3DXVECTOR3 up = {0.0f, 0.0f, 1.0f}; 5428 #else 5429 #define up {0.0f, 0.0f, 1.0f} 5430 #endif 5431 /* mesh0 (one face) 5432 * 5433 * 0--1 5434 * | / 5435 * |/ 5436 * 2 5437 */ 5438 const struct vertex_pnc vertices0[] = 5439 { 5440 {{ 0.0f, 3.0f, 0.f}, up, RED}, 5441 {{ 2.0f, 3.0f, 0.f}, up, GREEN}, 5442 {{ 0.0f, 0.0f, 0.f}, up, BLUE}, 5443 }; 5444 const DWORD indices0[] = {0, 1, 2}; 5445 const unsigned int num_vertices0 = ARRAY_SIZE(vertices0); 5446 const unsigned int num_faces0 = ARRAY_SIZE(indices0) / VERTS_PER_FACE; 5447 const DWORD adjacency0[] = {-1, -1, -1}; 5448 const DWORD exp_point_rep0[] = {0, 1, 2}; 5449 /* mesh1 (right) 5450 * 5451 * 0--1 3 5452 * | / /| 5453 * |/ / | 5454 * 2 5--4 5455 */ 5456 const struct vertex_pnc vertices1[] = 5457 { 5458 {{ 0.0f, 3.0f, 0.f}, up, RED}, 5459 {{ 2.0f, 3.0f, 0.f}, up, GREEN}, 5460 {{ 0.0f, 0.0f, 0.f}, up, BLUE}, 5461 5462 {{ 3.0f, 3.0f, 0.f}, up, GREEN}, 5463 {{ 3.0f, 0.0f, 0.f}, up, RED}, 5464 {{ 1.0f, 0.0f, 0.f}, up, BLUE}, 5465 }; 5466 const DWORD indices1[] = {0, 1, 2, 3, 4, 5}; 5467 const unsigned int num_vertices1 = ARRAY_SIZE(vertices1); 5468 const unsigned int num_faces1 = ARRAY_SIZE(indices1) / VERTS_PER_FACE; 5469 const DWORD adjacency1[] = {-1, 1, -1, -1, -1, 0}; 5470 const DWORD exp_point_rep1[] = {0, 1, 2, 1, 4, 2}; 5471 /* mesh2 (left) 5472 * 5473 * 3 0--1 5474 * /| | / 5475 * / | |/ 5476 * 5--4 2 5477 */ 5478 const struct vertex_pnc vertices2[] = 5479 { 5480 {{ 0.0f, 3.0f, 0.f}, up, RED}, 5481 {{ 2.0f, 3.0f, 0.f}, up, GREEN}, 5482 {{ 0.0f, 0.0f, 0.f}, up, BLUE}, 5483 5484 {{-1.0f, 3.0f, 0.f}, up, RED}, 5485 {{-1.0f, 0.0f, 0.f}, up, GREEN}, 5486 {{-3.0f, 0.0f, 0.f}, up, BLUE}, 5487 }; 5488 const DWORD indices2[] = {0, 1, 2, 3, 4, 5}; 5489 const unsigned int num_vertices2 = ARRAY_SIZE(vertices2); 5490 const unsigned int num_faces2 = ARRAY_SIZE(indices2) / VERTS_PER_FACE; 5491 const DWORD adjacency2[] = {-1, -1, 1, 0, -1, -1}; 5492 const DWORD exp_point_rep2[] = {0, 1, 2, 0, 2, 5}; 5493 /* mesh3 (above) 5494 * 5495 * 3 5496 * /| 5497 * / | 5498 * 5--4 5499 * 0--1 5500 * | / 5501 * |/ 5502 * 2 5503 */ 5504 struct vertex_pnc vertices3[] = 5505 { 5506 {{ 0.0f, 3.0f, 0.f}, up, RED}, 5507 {{ 2.0f, 3.0f, 0.f}, up, GREEN}, 5508 {{ 0.0f, 0.0f, 0.f}, up, BLUE}, 5509 5510 {{ 2.0f, 7.0f, 0.f}, up, BLUE}, 5511 {{ 2.0f, 4.0f, 0.f}, up, GREEN}, 5512 {{ 0.0f, 4.0f, 0.f}, up, RED}, 5513 }; 5514 const DWORD indices3[] = {0, 1, 2, 3, 4, 5}; 5515 const unsigned int num_vertices3 = ARRAY_SIZE(vertices3); 5516 const unsigned int num_faces3 = ARRAY_SIZE(indices3) / VERTS_PER_FACE; 5517 const DWORD adjacency3[] = {1, -1, -1, -1, 0, -1}; 5518 const DWORD exp_point_rep3[] = {0, 1, 2, 3, 1, 0}; 5519 /* mesh4 (below, tip against tip) 5520 * 5521 * 0--1 5522 * | / 5523 * |/ 5524 * 2 5525 * 3 5526 * |\ 5527 * | \ 5528 * 5--4 5529 */ 5530 struct vertex_pnc vertices4[] = 5531 { 5532 {{ 0.0f, 3.0f, 0.f}, up, RED}, 5533 {{ 2.0f, 3.0f, 0.f}, up, GREEN}, 5534 {{ 0.0f, 0.0f, 0.f}, up, BLUE}, 5535 5536 {{ 0.0f, -4.0f, 0.f}, up, BLUE}, 5537 {{ 2.0f, -7.0f, 0.f}, up, GREEN}, 5538 {{ 0.0f, -7.0f, 0.f}, up, RED}, 5539 }; 5540 const DWORD indices4[] = {0, 1, 2, 3, 4, 5}; 5541 const unsigned int num_vertices4 = ARRAY_SIZE(vertices4); 5542 const unsigned int num_faces4 = ARRAY_SIZE(indices4) / VERTS_PER_FACE; 5543 const DWORD adjacency4[] = {-1, -1, -1, -1, -1, -1}; 5544 const DWORD exp_point_rep4[] = {0, 1, 2, 3, 4, 5}; 5545 /* mesh5 (gap in mesh) 5546 * 5547 * 0 3-----4 15 5548 * / \ \ / / \ 5549 * / \ \ / / \ 5550 * 2-----1 5 17-----16 5551 * 6-----7 9 12-----13 5552 * \ / / \ \ / 5553 * \ / / \ \ / 5554 * 8 10-----11 14 5555 * 5556 */ 5557 const struct vertex_pnc vertices5[] = 5558 { 5559 {{ 0.0f, 1.0f, 0.f}, up, RED}, 5560 {{ 1.0f, -1.0f, 0.f}, up, GREEN}, 5561 {{-1.0f, -1.0f, 0.f}, up, BLUE}, 5562 5563 {{ 0.1f, 1.0f, 0.f}, up, RED}, 5564 {{ 2.1f, 1.0f, 0.f}, up, BLUE}, 5565 {{ 1.1f, -1.0f, 0.f}, up, GREEN}, 5566 5567 {{-1.0f, -1.1f, 0.f}, up, BLUE}, 5568 {{ 1.0f, -1.1f, 0.f}, up, GREEN}, 5569 {{ 0.0f, -3.1f, 0.f}, up, RED}, 5570 5571 {{ 1.1f, -1.1f, 0.f}, up, GREEN}, 5572 {{ 2.1f, -3.1f, 0.f}, up, BLUE}, 5573 {{ 0.1f, -3.1f, 0.f}, up, RED}, 5574 5575 {{ 1.2f, -1.1f, 0.f}, up, GREEN}, 5576 {{ 3.2f, -1.1f, 0.f}, up, RED}, 5577 {{ 2.2f, -3.1f, 0.f}, up, BLUE}, 5578 5579 {{ 2.2f, 1.0f, 0.f}, up, BLUE}, 5580 {{ 3.2f, -1.0f, 0.f}, up, RED}, 5581 {{ 1.2f, -1.0f, 0.f}, up, GREEN}, 5582 }; 5583 const DWORD indices5[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}; 5584 const unsigned int num_vertices5 = ARRAY_SIZE(vertices5); 5585 const unsigned int num_faces5 = ARRAY_SIZE(indices5) / VERTS_PER_FACE; 5586 const DWORD adjacency5[] = {-1, 2, -1, -1, 5, -1, 0, -1, -1, 4, -1, -1, 5, -1, 3, -1, 4, 1}; 5587 const DWORD exp_point_rep5[] = {0, 1, 2, 3, 4, 5, 2, 1, 8, 5, 10, 11, 5, 13, 10, 4, 13, 5}; 5588 const WORD indices5_16bit[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}; 5589 /* mesh6 (indices re-ordering) 5590 * 5591 * 0--1 6 3 5592 * | / /| |\ 5593 * |/ / | | \ 5594 * 2 8--7 5--4 5595 */ 5596 const struct vertex_pnc vertices6[] = 5597 { 5598 {{ 0.0f, 3.0f, 0.f}, up, RED}, 5599 {{ 2.0f, 3.0f, 0.f}, up, GREEN}, 5600 {{ 0.0f, 0.0f, 0.f}, up, BLUE}, 5601 5602 {{ 3.0f, 3.0f, 0.f}, up, GREEN}, 5603 {{ 3.0f, 0.0f, 0.f}, up, RED}, 5604 {{ 1.0f, 0.0f, 0.f}, up, BLUE}, 5605 5606 {{ 4.0f, 3.0f, 0.f}, up, GREEN}, 5607 {{ 6.0f, 0.0f, 0.f}, up, BLUE}, 5608 {{ 4.0f, 0.0f, 0.f}, up, RED}, 5609 }; 5610 const DWORD indices6[] = {0, 1, 2, 6, 7, 8, 3, 4, 5}; 5611 const unsigned int num_vertices6 = ARRAY_SIZE(vertices6); 5612 const unsigned int num_faces6 = ARRAY_SIZE(indices6) / VERTS_PER_FACE; 5613 const DWORD adjacency6[] = {-1, 1, -1, 2, -1, 0, -1, -1, 1}; 5614 const DWORD exp_point_rep6[] = {0, 1, 2, 1, 4, 5, 1, 5, 2}; 5615 /* mesh7 (expands collapsed triangle) 5616 * 5617 * 0--1 3 5618 * | / /| 5619 * |/ / | 5620 * 2 5--4 5621 */ 5622 const struct vertex_pnc vertices7[] = 5623 { 5624 {{ 0.0f, 3.0f, 0.f}, up, RED}, 5625 {{ 2.0f, 3.0f, 0.f}, up, GREEN}, 5626 {{ 0.0f, 0.0f, 0.f}, up, BLUE}, 5627 5628 {{ 3.0f, 3.0f, 0.f}, up, GREEN}, 5629 {{ 3.0f, 0.0f, 0.f}, up, RED}, 5630 {{ 1.0f, 0.0f, 0.f}, up, BLUE}, 5631 }; 5632 const DWORD indices7[] = {0, 1, 2, 3, 3, 3}; /* Face 1 is collapsed*/ 5633 const unsigned int num_vertices7 = ARRAY_SIZE(vertices7); 5634 const unsigned int num_faces7 = ARRAY_SIZE(indices7) / VERTS_PER_FACE; 5635 const DWORD adjacency7[] = {-1, -1, -1, -1, -1, -1}; 5636 const DWORD exp_point_rep7[] = {0, 1, 2, 3, 4, 5}; 5637 /* mesh8 (indices re-ordering and double replacement) 5638 * 5639 * 0--1 9 6 5640 * | / /| |\ 5641 * |/ / | | \ 5642 * 2 11-10 8--7 5643 * 3--4 5644 * | / 5645 * |/ 5646 * 5 5647 */ 5648 const struct vertex_pnc vertices8[] = 5649 { 5650 {{ 0.0f, 3.0f, 0.f}, up, RED}, 5651 {{ 2.0f, 3.0f, 0.f}, up, GREEN}, 5652 {{ 0.0f, 0.0f, 0.f}, up, BLUE}, 5653 5654 {{ 4.0, -4.0, 0.f}, up, RED}, 5655 {{ 6.0, -4.0, 0.f}, up, BLUE}, 5656 {{ 4.0, -7.0, 0.f}, up, GREEN}, 5657 5658 {{ 4.0f, 3.0f, 0.f}, up, GREEN}, 5659 {{ 6.0f, 0.0f, 0.f}, up, BLUE}, 5660 {{ 4.0f, 0.0f, 0.f}, up, RED}, 5661 5662 {{ 3.0f, 3.0f, 0.f}, up, GREEN}, 5663 {{ 3.0f, 0.0f, 0.f}, up, RED}, 5664 {{ 1.0f, 0.0f, 0.f}, up, BLUE}, 5665 }; 5666 const DWORD indices8[] = {0, 1, 2, 9, 10, 11, 6, 7, 8, 3, 4, 5}; 5667 const unsigned int num_vertices8 = ARRAY_SIZE(vertices8); 5668 const unsigned int num_faces8 = ARRAY_SIZE(indices8) / VERTS_PER_FACE; 5669 const DWORD adjacency8[] = {-1, 1, -1, 2, -1, 0, -1, 3, 1, 2, -1, -1}; 5670 const DWORD exp_point_rep8[] = {0, 1, 2, 3, 4, 5, 1, 4, 3, 1, 3, 2}; 5671 /* mesh9 (right, shared vertices) 5672 * 5673 * 0--1 5674 * | /| 5675 * |/ | 5676 * 2--3 5677 */ 5678 const struct vertex_pnc vertices9[] = 5679 { 5680 {{ 0.0f, 3.0f, 0.f}, up, RED}, 5681 {{ 2.0f, 3.0f, 0.f}, up, GREEN}, 5682 {{ 0.0f, 0.0f, 0.f}, up, BLUE}, 5683 5684 {{ 2.0f, 0.0f, 0.f}, up, RED}, 5685 }; 5686 const DWORD indices9[] = {0, 1, 2, 1, 3, 2}; 5687 const unsigned int num_vertices9 = ARRAY_SIZE(vertices9); 5688 const unsigned int num_faces9 = ARRAY_SIZE(indices9) / VERTS_PER_FACE; 5689 const DWORD adjacency9[] = {-1, 1, -1, -1, -1, 0}; 5690 const DWORD exp_point_rep9[] = {0, 1, 2, 3}; 5691 /* All mesh data */ 5692 ID3DXMesh *mesh = NULL; 5693 ID3DXMesh *mesh_null_check = NULL; 5694 unsigned int attributes[] = {0}; 5695 struct 5696 { 5697 const struct vertex_pnc *vertices; 5698 const DWORD *indices; 5699 const DWORD num_vertices; 5700 const DWORD num_faces; 5701 const DWORD *adjacency; 5702 const DWORD *exp_point_reps; 5703 const DWORD options; 5704 } 5705 tc[] = 5706 { 5707 { 5708 vertices0, 5709 indices0, 5710 num_vertices0, 5711 num_faces0, 5712 adjacency0, 5713 exp_point_rep0, 5714 options 5715 }, 5716 { 5717 vertices1, 5718 indices1, 5719 num_vertices1, 5720 num_faces1, 5721 adjacency1, 5722 exp_point_rep1, 5723 options 5724 }, 5725 { 5726 vertices2, 5727 indices2, 5728 num_vertices2, 5729 num_faces2, 5730 adjacency2, 5731 exp_point_rep2, 5732 options 5733 }, 5734 { 5735 vertices3, 5736 indices3, 5737 num_vertices3, 5738 num_faces3, 5739 adjacency3, 5740 exp_point_rep3, 5741 options 5742 }, 5743 { 5744 vertices4, 5745 indices4, 5746 num_vertices4, 5747 num_faces4, 5748 adjacency4, 5749 exp_point_rep4, 5750 options 5751 }, 5752 { 5753 vertices5, 5754 indices5, 5755 num_vertices5, 5756 num_faces5, 5757 adjacency5, 5758 exp_point_rep5, 5759 options 5760 }, 5761 { 5762 vertices6, 5763 indices6, 5764 num_vertices6, 5765 num_faces6, 5766 adjacency6, 5767 exp_point_rep6, 5768 options 5769 }, 5770 { 5771 vertices7, 5772 indices7, 5773 num_vertices7, 5774 num_faces7, 5775 adjacency7, 5776 exp_point_rep7, 5777 options 5778 }, 5779 { 5780 vertices8, 5781 indices8, 5782 num_vertices8, 5783 num_faces8, 5784 adjacency8, 5785 exp_point_rep8, 5786 options 5787 }, 5788 { 5789 vertices9, 5790 indices9, 5791 num_vertices9, 5792 num_faces9, 5793 adjacency9, 5794 exp_point_rep9, 5795 options 5796 }, 5797 { 5798 vertices5, 5799 (DWORD*)indices5_16bit, 5800 num_vertices5, 5801 num_faces5, 5802 adjacency5, 5803 exp_point_rep5, 5804 options_16bit 5805 }, 5806 }; 5807 DWORD *point_reps = NULL; 5808 5809 test_context = new_test_context(); 5810 if (!test_context) 5811 { 5812 skip("Couldn't create test context\n"); 5813 goto cleanup; 5814 } 5815 5816 for (i = 0; i < ARRAY_SIZE(tc); i++) 5817 { 5818 hr = D3DXCreateMesh(tc[i].num_faces, tc[i].num_vertices, tc[i].options, declaration, 5819 test_context->device, &mesh); 5820 if (FAILED(hr)) 5821 { 5822 skip("Couldn't create mesh %d. Got %x expected D3D_OK\n", i, hr); 5823 goto cleanup; 5824 } 5825 5826 if (i == 0) /* Save first mesh for later NULL checks */ 5827 mesh_null_check = mesh; 5828 5829 point_reps = HeapAlloc(GetProcessHeap(), 0, tc[i].num_vertices * sizeof(*point_reps)); 5830 if (!point_reps) 5831 { 5832 skip("Couldn't allocate point reps array.\n"); 5833 goto cleanup; 5834 } 5835 5836 hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, &vertex_buffer); 5837 if (FAILED(hr)) 5838 { 5839 skip("Couldn't lock vertex buffer.\n"); 5840 goto cleanup; 5841 } 5842 memcpy(vertex_buffer, tc[i].vertices, tc[i].num_vertices * sizeof(*tc[i].vertices)); 5843 hr = mesh->lpVtbl->UnlockVertexBuffer(mesh); 5844 if (FAILED(hr)) 5845 { 5846 skip("Couldn't unlock vertex buffer.\n"); 5847 goto cleanup; 5848 } 5849 5850 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, &index_buffer); 5851 if (FAILED(hr)) 5852 { 5853 skip("Couldn't lock index buffer.\n"); 5854 goto cleanup; 5855 } 5856 if (tc[i].options & D3DXMESH_32BIT) 5857 { 5858 memcpy(index_buffer, tc[i].indices, VERTS_PER_FACE * tc[i].num_faces * sizeof(DWORD)); 5859 } 5860 else 5861 { 5862 memcpy(index_buffer, tc[i].indices, VERTS_PER_FACE * tc[i].num_faces * sizeof(WORD)); 5863 } 5864 hr = mesh->lpVtbl->UnlockIndexBuffer(mesh); 5865 if (FAILED(hr)) { 5866 skip("Couldn't unlock index buffer.\n"); 5867 goto cleanup; 5868 } 5869 5870 hr = mesh->lpVtbl->LockAttributeBuffer(mesh, 0, &attributes_buffer); 5871 if (FAILED(hr)) 5872 { 5873 skip("Couldn't lock attributes buffer.\n"); 5874 goto cleanup; 5875 } 5876 memcpy(attributes_buffer, attributes, sizeof(attributes)); 5877 hr = mesh->lpVtbl->UnlockAttributeBuffer(mesh); 5878 if (FAILED(hr)) 5879 { 5880 skip("Couldn't unlock attributes buffer.\n"); 5881 goto cleanup; 5882 } 5883 5884 /* Convert adjacency to point representation */ 5885 for (j = 0; j < tc[i].num_vertices; j++) point_reps[j] = -1; 5886 hr = mesh->lpVtbl->ConvertAdjacencyToPointReps(mesh, tc[i].adjacency, point_reps); 5887 ok(hr == D3D_OK, "ConvertAdjacencyToPointReps failed case %d. " 5888 "Got %x expected D3D_OK\n", i, hr); 5889 5890 /* Check point representation */ 5891 for (j = 0; j < tc[i].num_vertices; j++) 5892 { 5893 ok(point_reps[j] == tc[i].exp_point_reps[j], 5894 "Unexpected point representation at (%d, %d)." 5895 " Got %d expected %d\n", 5896 i, j, point_reps[j], tc[i].exp_point_reps[j]); 5897 } 5898 5899 HeapFree(GetProcessHeap(), 0, point_reps); 5900 point_reps = NULL; 5901 5902 if (i != 0) /* First mesh will be freed during cleanup */ 5903 mesh->lpVtbl->Release(mesh); 5904 } 5905 5906 /* NULL checks */ 5907 hr = mesh_null_check->lpVtbl->ConvertAdjacencyToPointReps(mesh_null_check, tc[0].adjacency, NULL); 5908 ok(hr == D3DERR_INVALIDCALL, "ConvertAdjacencyToPointReps point_reps NULL. " 5909 "Got %x expected D3DERR_INVALIDCALL\n", hr); 5910 hr = mesh_null_check->lpVtbl->ConvertAdjacencyToPointReps(mesh_null_check, NULL, NULL); 5911 ok(hr == D3DERR_INVALIDCALL, "ConvertAdjacencyToPointReps adjacency and point_reps NULL. " 5912 "Got %x expected D3DERR_INVALIDCALL\n", hr); 5913 5914 cleanup: 5915 if (mesh_null_check) 5916 mesh_null_check->lpVtbl->Release(mesh_null_check); 5917 HeapFree(GetProcessHeap(), 0, point_reps); 5918 free_test_context(test_context); 5919 #ifdef __REACTOS__ 5920 #undef up 5921 #endif 5922 } 5923 5924 static void test_convert_point_reps_to_adjacency(void) 5925 { 5926 HRESULT hr; 5927 struct test_context *test_context = NULL; 5928 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM; 5929 const DWORD options_16bit = D3DXMESH_SYSTEMMEM; 5930 const D3DVERTEXELEMENT9 declaration[] = 5931 { 5932 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 5933 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 5934 {0, 24, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0}, 5935 D3DDECL_END() 5936 }; 5937 const unsigned int VERTS_PER_FACE = 3; 5938 void *vertex_buffer; 5939 void *index_buffer; 5940 DWORD *attributes_buffer; 5941 int i, j; 5942 enum color { RED = 0xffff0000, GREEN = 0xff00ff00, BLUE = 0xff0000ff}; 5943 struct vertex_pnc 5944 { 5945 D3DXVECTOR3 position; 5946 D3DXVECTOR3 normal; 5947 enum color color; /* In case of manual visual inspection */ 5948 }; 5949 #ifndef __REACTOS__ 5950 D3DXVECTOR3 up = {0.0f, 0.0f, 1.0f}; 5951 #else 5952 #define up {0.0f, 0.0f, 1.0f} 5953 #endif 5954 5955 /* mesh0 (one face) 5956 * 5957 * 0--1 5958 * | / 5959 * |/ 5960 * 2 5961 */ 5962 const struct vertex_pnc vertices0[] = 5963 { 5964 {{ 0.0f, 3.0f, 0.f}, up, RED}, 5965 {{ 2.0f, 3.0f, 0.f}, up, GREEN}, 5966 {{ 0.0f, 0.0f, 0.f}, up, BLUE}, 5967 }; 5968 const DWORD indices0[] = {0, 1, 2}; 5969 const unsigned int num_vertices0 = ARRAY_SIZE(vertices0); 5970 const unsigned int num_faces0 = num_vertices0 / VERTS_PER_FACE; 5971 const DWORD exp_adjacency0[] = {-1, -1, -1}; 5972 const DWORD exp_id_adjacency0[] = {-1, -1, -1}; 5973 const DWORD point_rep0[] = {0, 1, 2}; 5974 /* mesh1 (right) 5975 * 5976 * 0--1 3 5977 * | / /| 5978 * |/ / | 5979 * 2 5--4 5980 */ 5981 const struct vertex_pnc vertices1[] = 5982 { 5983 {{ 0.0f, 3.0f, 0.f}, up, RED}, 5984 {{ 2.0f, 3.0f, 0.f}, up, GREEN}, 5985 {{ 0.0f, 0.0f, 0.f}, up, BLUE}, 5986 5987 {{ 3.0f, 3.0f, 0.f}, up, GREEN}, 5988 {{ 3.0f, 0.0f, 0.f}, up, RED}, 5989 {{ 1.0f, 0.0f, 0.f}, up, BLUE}, 5990 }; 5991 const DWORD indices1[] = {0, 1, 2, 3, 4, 5}; 5992 const unsigned int num_vertices1 = ARRAY_SIZE(vertices1); 5993 const unsigned int num_faces1 = num_vertices1 / VERTS_PER_FACE; 5994 const DWORD exp_adjacency1[] = {-1, 1, -1, -1, -1, 0}; 5995 const DWORD exp_id_adjacency1[] = {-1, -1, -1, -1, -1, -1}; 5996 const DWORD point_rep1[] = {0, 1, 2, 1, 4, 2}; 5997 /* mesh2 (left) 5998 * 5999 * 3 0--1 6000 * /| | / 6001 * / | |/ 6002 * 5--4 2 6003 */ 6004 const struct vertex_pnc vertices2[] = 6005 { 6006 {{ 0.0f, 3.0f, 0.f}, up, RED}, 6007 {{ 2.0f, 3.0f, 0.f}, up, GREEN}, 6008 {{ 0.0f, 0.0f, 0.f}, up, BLUE}, 6009 6010 {{-1.0f, 3.0f, 0.f}, up, RED}, 6011 {{-1.0f, 0.0f, 0.f}, up, GREEN}, 6012 {{-3.0f, 0.0f, 0.f}, up, BLUE}, 6013 }; 6014 const DWORD indices2[] = {0, 1, 2, 3, 4, 5}; 6015 const unsigned int num_vertices2 = ARRAY_SIZE(vertices2); 6016 const unsigned int num_faces2 = num_vertices2 / VERTS_PER_FACE; 6017 const DWORD exp_adjacency2[] = {-1, -1, 1, 0, -1, -1}; 6018 const DWORD exp_id_adjacency2[] = {-1, -1, -1, -1, -1, -1}; 6019 const DWORD point_rep2[] = {0, 1, 2, 0, 2, 5}; 6020 /* mesh3 (above) 6021 * 6022 * 3 6023 * /| 6024 * / | 6025 * 5--4 6026 * 0--1 6027 * | / 6028 * |/ 6029 * 2 6030 */ 6031 struct vertex_pnc vertices3[] = 6032 { 6033 {{ 0.0f, 3.0f, 0.f}, up, RED}, 6034 {{ 2.0f, 3.0f, 0.f}, up, GREEN}, 6035 {{ 0.0f, 0.0f, 0.f}, up, BLUE}, 6036 6037 {{ 2.0f, 7.0f, 0.f}, up, BLUE}, 6038 {{ 2.0f, 4.0f, 0.f}, up, GREEN}, 6039 {{ 0.0f, 4.0f, 0.f}, up, RED}, 6040 }; 6041 const DWORD indices3[] = {0, 1, 2, 3, 4, 5}; 6042 const unsigned int num_vertices3 = ARRAY_SIZE(vertices3); 6043 const unsigned int num_faces3 = num_vertices3 / VERTS_PER_FACE; 6044 const DWORD exp_adjacency3[] = {1, -1, -1, -1, 0, -1}; 6045 const DWORD exp_id_adjacency3[] = {-1, -1, -1, -1, -1, -1}; 6046 const DWORD point_rep3[] = {0, 1, 2, 3, 1, 0}; 6047 /* mesh4 (below, tip against tip) 6048 * 6049 * 0--1 6050 * | / 6051 * |/ 6052 * 2 6053 * 3 6054 * |\ 6055 * | \ 6056 * 5--4 6057 */ 6058 struct vertex_pnc vertices4[] = 6059 { 6060 {{ 0.0f, 3.0f, 0.f}, up, RED}, 6061 {{ 2.0f, 3.0f, 0.f}, up, GREEN}, 6062 {{ 0.0f, 0.0f, 0.f}, up, BLUE}, 6063 6064 {{ 0.0f, -4.0f, 0.f}, up, BLUE}, 6065 {{ 2.0f, -7.0f, 0.f}, up, GREEN}, 6066 {{ 0.0f, -7.0f, 0.f}, up, RED}, 6067 }; 6068 const DWORD indices4[] = {0, 1, 2, 3, 4, 5}; 6069 const unsigned int num_vertices4 = ARRAY_SIZE(vertices4); 6070 const unsigned int num_faces4 = num_vertices4 / VERTS_PER_FACE; 6071 const DWORD exp_adjacency4[] = {-1, -1, -1, -1, -1, -1}; 6072 const DWORD exp_id_adjacency4[] = {-1, -1, -1, -1, -1, -1}; 6073 const DWORD point_rep4[] = {0, 1, 2, 3, 4, 5}; 6074 /* mesh5 (gap in mesh) 6075 * 6076 * 0 3-----4 15 6077 * / \ \ / / \ 6078 * / \ \ / / \ 6079 * 2-----1 5 17-----16 6080 * 6-----7 9 12-----13 6081 * \ / / \ \ / 6082 * \ / / \ \ / 6083 * 8 10-----11 14 6084 * 6085 */ 6086 const struct vertex_pnc vertices5[] = 6087 { 6088 {{ 0.0f, 1.0f, 0.f}, up, RED}, 6089 {{ 1.0f, -1.0f, 0.f}, up, GREEN}, 6090 {{-1.0f, -1.0f, 0.f}, up, BLUE}, 6091 6092 {{ 0.1f, 1.0f, 0.f}, up, RED}, 6093 {{ 2.1f, 1.0f, 0.f}, up, BLUE}, 6094 {{ 1.1f, -1.0f, 0.f}, up, GREEN}, 6095 6096 {{-1.0f, -1.1f, 0.f}, up, BLUE}, 6097 {{ 1.0f, -1.1f, 0.f}, up, GREEN}, 6098 {{ 0.0f, -3.1f, 0.f}, up, RED}, 6099 6100 {{ 1.1f, -1.1f, 0.f}, up, GREEN}, 6101 {{ 2.1f, -3.1f, 0.f}, up, BLUE}, 6102 {{ 0.1f, -3.1f, 0.f}, up, RED}, 6103 6104 {{ 1.2f, -1.1f, 0.f}, up, GREEN}, 6105 {{ 3.2f, -1.1f, 0.f}, up, RED}, 6106 {{ 2.2f, -3.1f, 0.f}, up, BLUE}, 6107 6108 {{ 2.2f, 1.0f, 0.f}, up, BLUE}, 6109 {{ 3.2f, -1.0f, 0.f}, up, RED}, 6110 {{ 1.2f, -1.0f, 0.f}, up, GREEN}, 6111 }; 6112 const DWORD indices5[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}; 6113 const unsigned int num_vertices5 = ARRAY_SIZE(vertices5); 6114 const unsigned int num_faces5 = num_vertices5 / VERTS_PER_FACE; 6115 const DWORD exp_adjacency5[] = {-1, 2, -1, -1, 5, -1, 0, -1, -1, 4, -1, -1, 5, -1, 3, -1, 4, 1}; 6116 const DWORD exp_id_adjacency5[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; 6117 const DWORD point_rep5[] = {0, 1, 2, 3, 4, 5, 2, 1, 8, 5, 10, 11, 5, 13, 10, 4, 13, 5}; 6118 /* mesh6 (indices re-ordering) 6119 * 6120 * 0--1 6 3 6121 * | / /| |\ 6122 * |/ / | | \ 6123 * 2 8--7 5--4 6124 */ 6125 const struct vertex_pnc vertices6[] = 6126 { 6127 {{ 0.0f, 3.0f, 0.f}, up, RED}, 6128 {{ 2.0f, 3.0f, 0.f}, up, GREEN}, 6129 {{ 0.0f, 0.0f, 0.f}, up, BLUE}, 6130 6131 {{ 3.0f, 3.0f, 0.f}, up, GREEN}, 6132 {{ 3.0f, 0.0f, 0.f}, up, RED}, 6133 {{ 1.0f, 0.0f, 0.f}, up, BLUE}, 6134 6135 {{ 4.0f, 3.0f, 0.f}, up, GREEN}, 6136 {{ 6.0f, 0.0f, 0.f}, up, BLUE}, 6137 {{ 4.0f, 0.0f, 0.f}, up, RED}, 6138 }; 6139 const DWORD indices6[] = {0, 1, 2, 6, 7, 8, 3, 4, 5}; 6140 const unsigned int num_vertices6 = ARRAY_SIZE(vertices6); 6141 const unsigned int num_faces6 = num_vertices6 / VERTS_PER_FACE; 6142 const DWORD exp_adjacency6[] = {-1, 1, -1, 2, -1, 0, -1, -1, 1}; 6143 const DWORD exp_id_adjacency6[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1}; 6144 const DWORD point_rep6[] = {0, 1, 2, 1, 4, 5, 1, 5, 2}; 6145 /* mesh7 (expands collapsed triangle) 6146 * 6147 * 0--1 3 6148 * | / /| 6149 * |/ / | 6150 * 2 5--4 6151 */ 6152 const struct vertex_pnc vertices7[] = 6153 { 6154 {{ 0.0f, 3.0f, 0.f}, up, RED}, 6155 {{ 2.0f, 3.0f, 0.f}, up, GREEN}, 6156 {{ 0.0f, 0.0f, 0.f}, up, BLUE}, 6157 6158 {{ 3.0f, 3.0f, 0.f}, up, GREEN}, 6159 {{ 3.0f, 0.0f, 0.f}, up, RED}, 6160 {{ 1.0f, 0.0f, 0.f}, up, BLUE}, 6161 }; 6162 const DWORD indices7[] = {0, 1, 2, 3, 3, 3}; /* Face 1 is collapsed*/ 6163 const unsigned int num_vertices7 = ARRAY_SIZE(vertices7); 6164 const unsigned int num_faces7 = num_vertices7 / VERTS_PER_FACE; 6165 const DWORD exp_adjacency7[] = {-1, -1, -1, -1, -1, -1}; 6166 const DWORD exp_id_adjacency7[] = {-1, -1, -1, -1, -1, -1}; 6167 const DWORD point_rep7[] = {0, 1, 2, 3, 4, 5}; 6168 /* mesh8 (indices re-ordering and double replacement) 6169 * 6170 * 0--1 9 6 6171 * | / /| |\ 6172 * |/ / | | \ 6173 * 2 11-10 8--7 6174 * 3--4 6175 * | / 6176 * |/ 6177 * 5 6178 */ 6179 const struct vertex_pnc vertices8[] = 6180 { 6181 {{ 0.0f, 3.0f, 0.f}, up, RED}, 6182 {{ 2.0f, 3.0f, 0.f}, up, GREEN}, 6183 {{ 0.0f, 0.0f, 0.f}, up, BLUE}, 6184 6185 {{ 4.0, -4.0, 0.f}, up, RED}, 6186 {{ 6.0, -4.0, 0.f}, up, BLUE}, 6187 {{ 4.0, -7.0, 0.f}, up, GREEN}, 6188 6189 {{ 4.0f, 3.0f, 0.f}, up, GREEN}, 6190 {{ 6.0f, 0.0f, 0.f}, up, BLUE}, 6191 {{ 4.0f, 0.0f, 0.f}, up, RED}, 6192 6193 {{ 3.0f, 3.0f, 0.f}, up, GREEN}, 6194 {{ 3.0f, 0.0f, 0.f}, up, RED}, 6195 {{ 1.0f, 0.0f, 0.f}, up, BLUE}, 6196 }; 6197 const DWORD indices8[] = {0, 1, 2, 9, 10, 11, 6, 7, 8, 3, 4, 5}; 6198 const WORD indices8_16bit[] = {0, 1, 2, 9, 10, 11, 6, 7, 8, 3, 4, 5}; 6199 const unsigned int num_vertices8 = ARRAY_SIZE(vertices8); 6200 const unsigned int num_faces8 = num_vertices8 / VERTS_PER_FACE; 6201 const DWORD exp_adjacency8[] = {-1, 1, -1, 2, -1, 0, -1, 3, 1, 2, -1, -1}; 6202 const DWORD exp_id_adjacency8[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; 6203 const DWORD point_rep8[] = {0, 1, 2, 3, 4, 5, 1, 4, 3, 1, 3, 2}; 6204 /* mesh9 (right, shared vertices) 6205 * 6206 * 0--1 6207 * | /| 6208 * |/ | 6209 * 2--3 6210 */ 6211 const struct vertex_pnc vertices9[] = 6212 { 6213 {{ 0.0f, 3.0f, 0.f}, up, RED}, 6214 {{ 2.0f, 3.0f, 0.f}, up, GREEN}, 6215 {{ 0.0f, 0.0f, 0.f}, up, BLUE}, 6216 6217 {{ 2.0f, 0.0f, 0.f}, up, RED}, 6218 }; 6219 const DWORD indices9[] = {0, 1, 2, 1, 3, 2}; 6220 const unsigned int num_vertices9 = ARRAY_SIZE(vertices9); 6221 const unsigned int num_faces9 = 2; 6222 const DWORD exp_adjacency9[] = {-1, 1, -1, -1, -1, 0}; 6223 const DWORD exp_id_adjacency9[] = {-1, 1, -1, -1, -1, 0}; 6224 const DWORD point_rep9[] = {0, 1, 2, 3}; 6225 /* All mesh data */ 6226 ID3DXMesh *mesh = NULL; 6227 ID3DXMesh *mesh_null_check = NULL; 6228 unsigned int attributes[] = {0}; 6229 struct 6230 { 6231 const struct vertex_pnc *vertices; 6232 const DWORD *indices; 6233 const DWORD num_vertices; 6234 const DWORD num_faces; 6235 const DWORD *point_reps; 6236 const DWORD *exp_adjacency; 6237 const DWORD *exp_id_adjacency; 6238 const DWORD options; 6239 } 6240 tc[] = 6241 { 6242 { 6243 vertices0, 6244 indices0, 6245 num_vertices0, 6246 num_faces0, 6247 point_rep0, 6248 exp_adjacency0, 6249 exp_id_adjacency0, 6250 options 6251 }, 6252 { 6253 vertices1, 6254 indices1, 6255 num_vertices1, 6256 num_faces1, 6257 point_rep1, 6258 exp_adjacency1, 6259 exp_id_adjacency1, 6260 options 6261 }, 6262 { 6263 vertices2, 6264 indices2, 6265 num_vertices2, 6266 num_faces2, 6267 point_rep2, 6268 exp_adjacency2, 6269 exp_id_adjacency2, 6270 options 6271 }, 6272 { 6273 vertices3, 6274 indices3, 6275 num_vertices3, 6276 num_faces3, 6277 point_rep3, 6278 exp_adjacency3, 6279 exp_id_adjacency3, 6280 options 6281 }, 6282 { 6283 vertices4, 6284 indices4, 6285 num_vertices4, 6286 num_faces4, 6287 point_rep4, 6288 exp_adjacency4, 6289 exp_id_adjacency4, 6290 options 6291 }, 6292 { 6293 vertices5, 6294 indices5, 6295 num_vertices5, 6296 num_faces5, 6297 point_rep5, 6298 exp_adjacency5, 6299 exp_id_adjacency5, 6300 options 6301 }, 6302 { 6303 vertices6, 6304 indices6, 6305 num_vertices6, 6306 num_faces6, 6307 point_rep6, 6308 exp_adjacency6, 6309 exp_id_adjacency6, 6310 options 6311 }, 6312 { 6313 vertices7, 6314 indices7, 6315 num_vertices7, 6316 num_faces7, 6317 point_rep7, 6318 exp_adjacency7, 6319 exp_id_adjacency7, 6320 options 6321 }, 6322 { 6323 vertices8, 6324 indices8, 6325 num_vertices8, 6326 num_faces8, 6327 point_rep8, 6328 exp_adjacency8, 6329 exp_id_adjacency8, 6330 options 6331 }, 6332 { 6333 vertices9, 6334 indices9, 6335 num_vertices9, 6336 num_faces9, 6337 point_rep9, 6338 exp_adjacency9, 6339 exp_id_adjacency9, 6340 options 6341 }, 6342 { 6343 vertices8, 6344 (DWORD*)indices8_16bit, 6345 num_vertices8, 6346 num_faces8, 6347 point_rep8, 6348 exp_adjacency8, 6349 exp_id_adjacency8, 6350 options_16bit 6351 }, 6352 }; 6353 DWORD *adjacency = NULL; 6354 #ifdef __REACTOS__ 6355 #undef up 6356 #endif 6357 6358 test_context = new_test_context(); 6359 if (!test_context) 6360 { 6361 skip("Couldn't create test context\n"); 6362 goto cleanup; 6363 } 6364 6365 for (i = 0; i < ARRAY_SIZE(tc); i++) 6366 { 6367 hr = D3DXCreateMesh(tc[i].num_faces, tc[i].num_vertices, tc[i].options, 6368 declaration, test_context->device, &mesh); 6369 if (FAILED(hr)) 6370 { 6371 skip("Couldn't create mesh %d. Got %x expected D3D_OK\n", i, hr); 6372 goto cleanup; 6373 } 6374 6375 if (i == 0) /* Save first mesh for later NULL checks */ 6376 mesh_null_check = mesh; 6377 6378 adjacency = HeapAlloc(GetProcessHeap(), 0, VERTS_PER_FACE * tc[i].num_faces * sizeof(*adjacency)); 6379 if (!adjacency) 6380 { 6381 skip("Couldn't allocate adjacency array.\n"); 6382 goto cleanup; 6383 } 6384 6385 hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, &vertex_buffer); 6386 if (FAILED(hr)) 6387 { 6388 skip("Couldn't lock vertex buffer.\n"); 6389 goto cleanup; 6390 } 6391 memcpy(vertex_buffer, tc[i].vertices, tc[i].num_vertices * sizeof(*tc[i].vertices)); 6392 hr = mesh->lpVtbl->UnlockVertexBuffer(mesh); 6393 if (FAILED(hr)) 6394 { 6395 skip("Couldn't unlock vertex buffer.\n"); 6396 goto cleanup; 6397 } 6398 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, &index_buffer); 6399 if (FAILED(hr)) 6400 { 6401 skip("Couldn't lock index buffer.\n"); 6402 goto cleanup; 6403 } 6404 if (tc[i].options & D3DXMESH_32BIT) 6405 { 6406 memcpy(index_buffer, tc[i].indices, VERTS_PER_FACE * tc[i].num_faces * sizeof(DWORD)); 6407 } 6408 else 6409 { 6410 memcpy(index_buffer, tc[i].indices, VERTS_PER_FACE * tc[i].num_faces * sizeof(WORD)); 6411 } 6412 hr = mesh->lpVtbl->UnlockIndexBuffer(mesh); 6413 if (FAILED(hr)) { 6414 skip("Couldn't unlock index buffer.\n"); 6415 goto cleanup; 6416 } 6417 6418 hr = mesh->lpVtbl->LockAttributeBuffer(mesh, 0, &attributes_buffer); 6419 if (FAILED(hr)) 6420 { 6421 skip("Couldn't lock attributes buffer.\n"); 6422 goto cleanup; 6423 } 6424 memcpy(attributes_buffer, attributes, sizeof(attributes)); 6425 hr = mesh->lpVtbl->UnlockAttributeBuffer(mesh); 6426 if (FAILED(hr)) 6427 { 6428 skip("Couldn't unlock attributes buffer.\n"); 6429 goto cleanup; 6430 } 6431 6432 /* Convert point representation to adjacency*/ 6433 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++) adjacency[j] = -2; 6434 6435 hr = mesh->lpVtbl->ConvertPointRepsToAdjacency(mesh, tc[i].point_reps, adjacency); 6436 ok(hr == D3D_OK, "ConvertPointRepsToAdjacency failed case %d. " 6437 "Got %x expected D3D_OK\n", i, hr); 6438 /* Check adjacency */ 6439 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++) 6440 { 6441 ok(adjacency[j] == tc[i].exp_adjacency[j], 6442 "Unexpected adjacency information at (%d, %d)." 6443 " Got %d expected %d\n", 6444 i, j, adjacency[j], tc[i].exp_adjacency[j]); 6445 } 6446 6447 /* NULL point representation is considered identity. */ 6448 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++) adjacency[j] = -2; 6449 hr = mesh_null_check->lpVtbl->ConvertPointRepsToAdjacency(mesh, NULL, adjacency); 6450 ok(hr == D3D_OK, "ConvertPointRepsToAdjacency NULL point_reps. " 6451 "Got %x expected D3D_OK\n", hr); 6452 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++) 6453 { 6454 ok(adjacency[j] == tc[i].exp_id_adjacency[j], 6455 "Unexpected adjacency information (id) at (%d, %d)." 6456 " Got %d expected %d\n", 6457 i, j, adjacency[j], tc[i].exp_id_adjacency[j]); 6458 } 6459 6460 HeapFree(GetProcessHeap(), 0, adjacency); 6461 adjacency = NULL; 6462 if (i != 0) /* First mesh will be freed during cleanup */ 6463 mesh->lpVtbl->Release(mesh); 6464 } 6465 6466 /* NULL checks */ 6467 hr = mesh_null_check->lpVtbl->ConvertPointRepsToAdjacency(mesh_null_check, tc[0].point_reps, NULL); 6468 ok(hr == D3DERR_INVALIDCALL, "ConvertPointRepsToAdjacency NULL adjacency. " 6469 "Got %x expected D3DERR_INVALIDCALL\n", hr); 6470 hr = mesh_null_check->lpVtbl->ConvertPointRepsToAdjacency(mesh_null_check, NULL, NULL); 6471 ok(hr == D3DERR_INVALIDCALL, "ConvertPointRepsToAdjacency NULL point_reps and adjacency. " 6472 "Got %x expected D3DERR_INVALIDCALL\n", hr); 6473 6474 cleanup: 6475 if (mesh_null_check) 6476 mesh_null_check->lpVtbl->Release(mesh_null_check); 6477 HeapFree(GetProcessHeap(), 0, adjacency); 6478 free_test_context(test_context); 6479 } 6480 6481 static HRESULT init_test_mesh(const DWORD num_faces, const DWORD num_vertices, 6482 const DWORD options, 6483 const D3DVERTEXELEMENT9 *declaration, 6484 IDirect3DDevice9 *device, ID3DXMesh **mesh_ptr, 6485 const void *vertices, const DWORD vertex_size, 6486 const DWORD *indices, const DWORD *attributes) 6487 { 6488 HRESULT hr; 6489 void *vertex_buffer; 6490 void *index_buffer; 6491 DWORD *attributes_buffer; 6492 ID3DXMesh *mesh = NULL; 6493 6494 hr = D3DXCreateMesh(num_faces, num_vertices, options, declaration, device, mesh_ptr); 6495 if (FAILED(hr)) 6496 { 6497 skip("Couldn't create mesh. Got %x expected D3D_OK\n", hr); 6498 goto cleanup; 6499 } 6500 mesh = *mesh_ptr; 6501 6502 hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, &vertex_buffer); 6503 if (FAILED(hr)) 6504 { 6505 skip("Couldn't lock vertex buffer.\n"); 6506 goto cleanup; 6507 } 6508 memcpy(vertex_buffer, vertices, num_vertices * vertex_size); 6509 hr = mesh->lpVtbl->UnlockVertexBuffer(mesh); 6510 if (FAILED(hr)) 6511 { 6512 skip("Couldn't unlock vertex buffer.\n"); 6513 goto cleanup; 6514 } 6515 6516 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, &index_buffer); 6517 if (FAILED(hr)) 6518 { 6519 skip("Couldn't lock index buffer.\n"); 6520 goto cleanup; 6521 } 6522 if (options & D3DXMESH_32BIT) 6523 { 6524 if (indices) 6525 memcpy(index_buffer, indices, 3 * num_faces * sizeof(DWORD)); 6526 else 6527 { 6528 /* Fill index buffer with 0, 1, 2, ...*/ 6529 DWORD *indices_32bit = (DWORD*)index_buffer; 6530 UINT i; 6531 for (i = 0; i < 3 * num_faces; i++) 6532 indices_32bit[i] = i; 6533 } 6534 } 6535 else 6536 { 6537 if (indices) 6538 memcpy(index_buffer, indices, 3 * num_faces * sizeof(WORD)); 6539 else 6540 { 6541 /* Fill index buffer with 0, 1, 2, ...*/ 6542 WORD *indices_16bit = (WORD*)index_buffer; 6543 UINT i; 6544 for (i = 0; i < 3 * num_faces; i++) 6545 indices_16bit[i] = i; 6546 } 6547 } 6548 hr = mesh->lpVtbl->UnlockIndexBuffer(mesh); 6549 if (FAILED(hr)) { 6550 skip("Couldn't unlock index buffer.\n"); 6551 goto cleanup; 6552 } 6553 6554 hr = mesh->lpVtbl->LockAttributeBuffer(mesh, 0, &attributes_buffer); 6555 if (FAILED(hr)) 6556 { 6557 skip("Couldn't lock attributes buffer.\n"); 6558 goto cleanup; 6559 } 6560 6561 if (attributes) 6562 memcpy(attributes_buffer, attributes, num_faces * sizeof(*attributes)); 6563 else 6564 memset(attributes_buffer, 0, num_faces * sizeof(*attributes)); 6565 6566 hr = mesh->lpVtbl->UnlockAttributeBuffer(mesh); 6567 if (FAILED(hr)) 6568 { 6569 skip("Couldn't unlock attributes buffer.\n"); 6570 goto cleanup; 6571 } 6572 6573 hr = D3D_OK; 6574 cleanup: 6575 return hr; 6576 } 6577 6578 /* Using structs instead of bit-fields in order to avoid compiler issues. */ 6579 struct udec3 6580 { 6581 UINT x; 6582 UINT y; 6583 UINT z; 6584 UINT w; 6585 }; 6586 6587 struct dec3n 6588 { 6589 INT x; 6590 INT y; 6591 INT z; 6592 INT w; 6593 }; 6594 6595 static DWORD init_udec3_dword(UINT x, UINT y, UINT z, UINT w) 6596 { 6597 DWORD d = 0; 6598 6599 d |= x & 0x3ff; 6600 d |= (y << 10) & 0xffc00; 6601 d |= (z << 20) & 0x3ff00000; 6602 d |= (w << 30) & 0xc0000000; 6603 6604 return d; 6605 } 6606 6607 static DWORD init_dec3n_dword(INT x, INT y, INT z, INT w) 6608 { 6609 DWORD d = 0; 6610 6611 d |= x & 0x3ff; 6612 d |= (y << 10) & 0xffc00; 6613 d |= (z << 20) & 0x3ff00000; 6614 d |= (w << 30) & 0xc0000000; 6615 6616 return d; 6617 } 6618 6619 static struct udec3 dword_to_udec3(DWORD d) 6620 { 6621 struct udec3 v; 6622 6623 v.x = d & 0x3ff; 6624 v.y = (d & 0xffc00) >> 10; 6625 v.z = (d & 0x3ff00000) >> 20; 6626 v.w = (d & 0xc0000000) >> 30; 6627 6628 return v; 6629 } 6630 6631 static struct dec3n dword_to_dec3n(DWORD d) 6632 { 6633 struct dec3n v; 6634 6635 v.x = d & 0x3ff; 6636 v.y = (d & 0xffc00) >> 10; 6637 v.z = (d & 0x3ff00000) >> 20; 6638 v.w = (d & 0xc0000000) >> 30; 6639 6640 return v; 6641 } 6642 6643 static void check_vertex_components(int line, int mesh_number, int vertex_number, BYTE *got_ptr, const BYTE *exp_ptr, D3DVERTEXELEMENT9 *declaration) 6644 { 6645 const char *usage_strings[] = 6646 { 6647 "position", 6648 "blend weight", 6649 "blend indices", 6650 "normal", 6651 "point size", 6652 "texture coordinates", 6653 "tangent", 6654 "binormal", 6655 "tessellation factor", 6656 "position transformed", 6657 "color", 6658 "fog", 6659 "depth", 6660 "sample" 6661 }; 6662 D3DVERTEXELEMENT9 *decl_ptr; 6663 const float PRECISION = 1e-5f; 6664 6665 for (decl_ptr = declaration; decl_ptr->Stream != 0xFF; decl_ptr++) 6666 { 6667 switch (decl_ptr->Type) 6668 { 6669 case D3DDECLTYPE_FLOAT1: 6670 { 6671 FLOAT *got = (FLOAT*)(got_ptr + decl_ptr->Offset); 6672 FLOAT *exp = (FLOAT*)(exp_ptr + decl_ptr->Offset); 6673 FLOAT diff = fabsf(*got - *exp); 6674 ok_(__FILE__,line)(diff <= PRECISION, "Mesh %d: Got %f for vertex %d %s, expected %f.\n", 6675 mesh_number, *got, vertex_number, usage_strings[decl_ptr->Usage], *exp); 6676 break; 6677 } 6678 case D3DDECLTYPE_FLOAT2: 6679 { 6680 D3DXVECTOR2 *got = (D3DXVECTOR2*)(got_ptr + decl_ptr->Offset); 6681 D3DXVECTOR2 *exp = (D3DXVECTOR2*)(exp_ptr + decl_ptr->Offset); 6682 FLOAT diff = max(fabsf(got->x - exp->x), fabsf(got->y - exp->y)); 6683 ok_(__FILE__,line)(diff <= PRECISION, "Mesh %d: Got (%f, %f) for vertex %d %s, expected (%f, %f).\n", 6684 mesh_number, got->x, got->y, vertex_number, usage_strings[decl_ptr->Usage], exp->x, exp->y); 6685 break; 6686 } 6687 case D3DDECLTYPE_FLOAT3: 6688 { 6689 D3DXVECTOR3 *got = (D3DXVECTOR3*)(got_ptr + decl_ptr->Offset); 6690 D3DXVECTOR3 *exp = (D3DXVECTOR3*)(exp_ptr + decl_ptr->Offset); 6691 FLOAT diff = max(fabsf(got->x - exp->x), fabsf(got->y - exp->y)); 6692 diff = max(diff, fabsf(got->z - exp->z)); 6693 ok_(__FILE__,line)(diff <= PRECISION, "Mesh %d: Got (%f, %f, %f) for vertex %d %s, expected (%f, %f, %f).\n", 6694 mesh_number, got->x, got->y, got->z, vertex_number, usage_strings[decl_ptr->Usage], exp->x, exp->y, exp->z); 6695 break; 6696 } 6697 case D3DDECLTYPE_FLOAT4: 6698 { 6699 D3DXVECTOR4 *got = (D3DXVECTOR4*)(got_ptr + decl_ptr->Offset); 6700 D3DXVECTOR4 *exp = (D3DXVECTOR4*)(exp_ptr + decl_ptr->Offset); 6701 FLOAT diff = max(fabsf(got->x - exp->x), fabsf(got->y - exp->y)); 6702 diff = max(diff, fabsf(got->z - exp->z)); 6703 diff = max(diff, fabsf(got->w - exp->w)); 6704 ok_(__FILE__,line)(diff <= PRECISION, "Mesh %d: Got (%f, %f, %f, %f) for vertex %d %s, expected (%f, %f, %f, %f).\n", 6705 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); 6706 break; 6707 } 6708 case D3DDECLTYPE_D3DCOLOR: 6709 { 6710 BYTE *got = got_ptr + decl_ptr->Offset; 6711 const BYTE *exp = exp_ptr + decl_ptr->Offset; 6712 BOOL same_color = got[0] == exp[0] && got[1] == exp[1] 6713 && got[2] == exp[2] && got[3] == exp[3]; 6714 const char *color_types[] = {"diffuse", "specular", "undefined color"}; 6715 BYTE usage_index = decl_ptr->UsageIndex; 6716 if (usage_index > 1) usage_index = 2; 6717 ok_(__FILE__,line)(same_color, "Mesh %d: Got (%u, %u, %u, %u) for vertex %d %s, expected (%u, %u, %u, %u).\n", 6718 mesh_number, got[0], got[1], got[2], got[3], vertex_number, color_types[usage_index], exp[0], exp[1], exp[2], exp[3]); 6719 break; 6720 } 6721 case D3DDECLTYPE_UBYTE4: 6722 case D3DDECLTYPE_UBYTE4N: 6723 { 6724 BYTE *got = got_ptr + decl_ptr->Offset; 6725 const BYTE *exp = exp_ptr + decl_ptr->Offset; 6726 BOOL same = got[0] == exp[0] && got[1] == exp[1] 6727 && got[2] == exp[2] && got[3] == exp[3]; 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[0], got[1], got[2], got[3], vertex_number, usage_strings[decl_ptr->Usage], exp[0], exp[1], exp[2], exp[3]); 6730 break; 6731 } 6732 case D3DDECLTYPE_SHORT2: 6733 case D3DDECLTYPE_SHORT2N: 6734 { 6735 SHORT *got = (SHORT*)(got_ptr + decl_ptr->Offset); 6736 SHORT *exp = (SHORT*)(exp_ptr + decl_ptr->Offset); 6737 BOOL same = got[0] == exp[0] && got[1] == exp[1]; 6738 ok_(__FILE__,line)(same, "Mesh %d: Got (%hd, %hd) for vertex %d %s, expected (%hd, %hd).\n", 6739 mesh_number, got[0], got[1], vertex_number, usage_strings[decl_ptr->Usage], exp[0], exp[1]); 6740 break; 6741 } 6742 case D3DDECLTYPE_SHORT4: 6743 case D3DDECLTYPE_SHORT4N: 6744 { 6745 SHORT *got = (SHORT*)(got_ptr + decl_ptr->Offset); 6746 SHORT *exp = (SHORT*)(exp_ptr + decl_ptr->Offset); 6747 BOOL same = got[0] == exp[0] && got[1] == exp[1] 6748 && got[2] == exp[2] && got[3] == exp[3]; 6749 ok_(__FILE__,line)(same, "Mesh %d: Got (%hd, %hd, %hd, %hd) for vertex %d %s, expected (%hd, %hd, %hd, %hd).\n", 6750 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]); 6751 break; 6752 } 6753 case D3DDECLTYPE_USHORT2N: 6754 { 6755 USHORT *got = (USHORT*)(got_ptr + decl_ptr->Offset); 6756 USHORT *exp = (USHORT*)(exp_ptr + decl_ptr->Offset); 6757 BOOL same = got[0] == exp[0] && got[1] == exp[1]; 6758 ok_(__FILE__,line)(same, "Mesh %d: Got (%hu, %hu) for vertex %d %s, expected (%hu, %hu).\n", 6759 mesh_number, got[0], got[1], vertex_number, usage_strings[decl_ptr->Usage], exp[0], exp[1]); 6760 break; 6761 } 6762 case D3DDECLTYPE_USHORT4N: 6763 { 6764 USHORT *got = (USHORT*)(got_ptr + decl_ptr->Offset); 6765 USHORT *exp = (USHORT*)(exp_ptr + decl_ptr->Offset); 6766 BOOL same = got[0] == exp[0] && got[1] == exp[1] 6767 && got[2] == exp[2] && got[3] == exp[3]; 6768 ok_(__FILE__,line)(same, "Mesh %d: Got (%hu, %hu, %hu, %hu) for vertex %d %s, expected (%hu, %hu, %hu, %hu).\n", 6769 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]); 6770 break; 6771 } 6772 case D3DDECLTYPE_UDEC3: 6773 { 6774 DWORD *got = (DWORD*)(got_ptr + decl_ptr->Offset); 6775 DWORD *exp = (DWORD*)(exp_ptr + decl_ptr->Offset); 6776 BOOL same = memcmp(got, exp, sizeof(*got)) == 0; 6777 struct udec3 got_udec3 = dword_to_udec3(*got); 6778 struct udec3 exp_udec3 = dword_to_udec3(*exp); 6779 ok_(__FILE__,line)(same, "Mesh %d: Got (%u, %u, %u, %u) for vertex %d %s, expected (%u, %u, %u, %u).\n", 6780 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); 6781 6782 break; 6783 } 6784 case D3DDECLTYPE_DEC3N: 6785 { 6786 DWORD *got = (DWORD*)(got_ptr + decl_ptr->Offset); 6787 DWORD *exp = (DWORD*)(exp_ptr + decl_ptr->Offset); 6788 BOOL same = memcmp(got, exp, sizeof(*got)) == 0; 6789 struct dec3n got_dec3n = dword_to_dec3n(*got); 6790 struct dec3n exp_dec3n = dword_to_dec3n(*exp); 6791 ok_(__FILE__,line)(same, "Mesh %d: Got (%d, %d, %d, %d) for vertex %d %s, expected (%d, %d, %d, %d).\n", 6792 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); 6793 break; 6794 } 6795 case D3DDECLTYPE_FLOAT16_2: 6796 { 6797 WORD *got = (WORD*)(got_ptr + decl_ptr->Offset); 6798 WORD *exp = (WORD*)(exp_ptr + decl_ptr->Offset); 6799 BOOL same = got[0] == exp[0] && got[1] == exp[1]; 6800 ok_(__FILE__,line)(same, "Mesh %d: Got (%hx, %hx) for vertex %d %s, expected (%hx, %hx).\n", 6801 mesh_number, got[0], got[1], vertex_number, usage_strings[decl_ptr->Usage], exp[0], exp[1]); 6802 break; 6803 } 6804 case D3DDECLTYPE_FLOAT16_4: 6805 { 6806 WORD *got = (WORD*)(got_ptr + decl_ptr->Offset); 6807 WORD *exp = (WORD*)(exp_ptr + decl_ptr->Offset); 6808 BOOL same = got[0] == exp[0] && got[1] == exp[1] 6809 && got[2] == exp[2] && got[3] == exp[3]; 6810 ok_(__FILE__,line)(same, "Mesh %d: Got (%hx, %hx, %hx, %hx) for vertex %d %s, expected (%hx, %hx, %hx, %hx).\n", 6811 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]); 6812 break; 6813 } 6814 default: 6815 break; 6816 } 6817 } 6818 } 6819 6820 static void test_weld_vertices(void) 6821 { 6822 HRESULT hr; 6823 struct test_context *test_context = NULL; 6824 DWORD i; 6825 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM; 6826 const DWORD options_16bit = D3DXMESH_SYSTEMMEM; 6827 BYTE *vertices = NULL; 6828 DWORD *indices = NULL; 6829 WORD *indices_16bit = NULL; 6830 const UINT VERTS_PER_FACE = 3; 6831 #ifndef __REACTOS__ 6832 const D3DXVECTOR3 up = {0.0f, 0.0f, 1.0f}; 6833 #else 6834 #define up {0.0f, 0.0f, 1.0f} 6835 #endif 6836 struct vertex_normal 6837 { 6838 D3DXVECTOR3 position; 6839 D3DXVECTOR3 normal; 6840 }; 6841 struct vertex_blendweight 6842 { 6843 D3DXVECTOR3 position; 6844 FLOAT blendweight; 6845 }; 6846 struct vertex_texcoord 6847 { 6848 D3DXVECTOR3 position; 6849 D3DXVECTOR2 texcoord; 6850 }; 6851 struct vertex_color 6852 { 6853 D3DXVECTOR3 position; 6854 DWORD color; 6855 }; 6856 struct vertex_color_ubyte4 6857 { 6858 D3DXVECTOR3 position; 6859 BYTE color[4]; 6860 }; 6861 struct vertex_texcoord_short2 6862 { 6863 D3DXVECTOR3 position; 6864 SHORT texcoord[2]; 6865 }; 6866 struct vertex_texcoord_ushort2n 6867 { 6868 D3DXVECTOR3 position; 6869 USHORT texcoord[2]; 6870 }; 6871 struct vertex_normal_short4 6872 { 6873 D3DXVECTOR3 position; 6874 SHORT normal[4]; 6875 }; 6876 struct vertex_texcoord_float16_2 6877 { 6878 D3DXVECTOR3 position; 6879 WORD texcoord[2]; 6880 }; 6881 struct vertex_texcoord_float16_4 6882 { 6883 D3DXVECTOR3 position; 6884 WORD texcoord[4]; 6885 }; 6886 struct vertex_normal_udec3 6887 { 6888 D3DXVECTOR3 position; 6889 DWORD normal; 6890 }; 6891 struct vertex_normal_dec3n 6892 { 6893 D3DXVECTOR3 position; 6894 DWORD normal; 6895 }; 6896 UINT vertex_size_normal = sizeof(struct vertex_normal); 6897 UINT vertex_size_blendweight = sizeof(struct vertex_blendweight); 6898 UINT vertex_size_texcoord = sizeof(struct vertex_texcoord); 6899 UINT vertex_size_color = sizeof(struct vertex_color); 6900 UINT vertex_size_color_ubyte4 = sizeof(struct vertex_color_ubyte4); 6901 UINT vertex_size_texcoord_short2 = sizeof(struct vertex_texcoord_short2); 6902 UINT vertex_size_normal_short4 = sizeof(struct vertex_normal_short4); 6903 UINT vertex_size_texcoord_float16_2 = sizeof(struct vertex_texcoord_float16_2); 6904 UINT vertex_size_texcoord_float16_4 = sizeof(struct vertex_texcoord_float16_4); 6905 UINT vertex_size_normal_udec3 = sizeof(struct vertex_normal_udec3); 6906 UINT vertex_size_normal_dec3n = sizeof(struct vertex_normal_dec3n); 6907 D3DVERTEXELEMENT9 declaration_normal[] = 6908 { 6909 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 6910 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 6911 D3DDECL_END() 6912 }; 6913 D3DVERTEXELEMENT9 declaration_normal3[] = 6914 { 6915 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 3}, 6916 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 6917 D3DDECL_END() 6918 }; 6919 D3DVERTEXELEMENT9 declaration_blendweight[] = 6920 { 6921 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 6922 {0, 12, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BLENDWEIGHT, 0}, 6923 D3DDECL_END() 6924 }; 6925 D3DVERTEXELEMENT9 declaration_texcoord[] = 6926 { 6927 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 6928 {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 6929 D3DDECL_END() 6930 }; 6931 D3DVERTEXELEMENT9 declaration_color[] = 6932 { 6933 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 6934 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0}, 6935 D3DDECL_END() 6936 }; 6937 D3DVERTEXELEMENT9 declaration_color_ubyte4n[] = 6938 { 6939 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 6940 {0, 12, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0}, 6941 D3DDECL_END() 6942 }; 6943 D3DVERTEXELEMENT9 declaration_color_ubyte4[] = 6944 { 6945 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 6946 {0, 12, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0}, 6947 D3DDECL_END() 6948 }; 6949 D3DVERTEXELEMENT9 declaration_texcoord_short2[] = 6950 { 6951 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 6952 {0, 12, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 6953 D3DDECL_END() 6954 }; 6955 D3DVERTEXELEMENT9 declaration_texcoord_short2n[] = 6956 { 6957 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 6958 {0, 12, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 6959 D3DDECL_END() 6960 }; 6961 D3DVERTEXELEMENT9 declaration_texcoord_ushort2n[] = 6962 { 6963 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 6964 {0, 12, D3DDECLTYPE_USHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 6965 D3DDECL_END() 6966 }; 6967 D3DVERTEXELEMENT9 declaration_normal_short4[] = 6968 { 6969 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 6970 {0, 12, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 6971 D3DDECL_END() 6972 }; 6973 D3DVERTEXELEMENT9 declaration_normal_short4n[] = 6974 { 6975 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 6976 {0, 12, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 6977 D3DDECL_END() 6978 }; 6979 D3DVERTEXELEMENT9 declaration_normal_ushort4n[] = 6980 { 6981 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 6982 {0, 12, D3DDECLTYPE_USHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 6983 D3DDECL_END() 6984 }; 6985 D3DVERTEXELEMENT9 declaration_texcoord10[] = 6986 { 6987 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 6988 {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 10}, 6989 D3DDECL_END() 6990 }; 6991 D3DVERTEXELEMENT9 declaration_color2[] = 6992 { 6993 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 6994 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 2}, 6995 D3DDECL_END() 6996 }; 6997 D3DVERTEXELEMENT9 declaration_color1[] = 6998 { 6999 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 7000 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 1}, 7001 D3DDECL_END() 7002 }; 7003 D3DVERTEXELEMENT9 declaration_texcoord_float16_2[] = 7004 { 7005 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 7006 {0, 12, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 7007 D3DDECL_END() 7008 }; 7009 D3DVERTEXELEMENT9 declaration_texcoord_float16_4[] = 7010 { 7011 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 7012 {0, 12, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 7013 D3DDECL_END() 7014 }; 7015 D3DVERTEXELEMENT9 declaration_normal_udec3[] = 7016 { 7017 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 7018 {0, 12, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 7019 D3DDECL_END() 7020 }; 7021 D3DVERTEXELEMENT9 declaration_normal_dec3n[] = 7022 { 7023 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 7024 {0, 12, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 7025 D3DDECL_END() 7026 }; 7027 /* Test 0. One face and no welding. 7028 * 7029 * 0--1 7030 * | / 7031 * |/ 7032 * 2 7033 */ 7034 const struct vertex vertices0[] = 7035 { 7036 {{ 0.0f, 3.0f, 0.f}, up}, 7037 {{ 2.0f, 3.0f, 0.f}, up}, 7038 {{ 0.0f, 0.0f, 0.f}, up}, 7039 }; 7040 const DWORD indices0[] = {0, 1, 2}; 7041 const DWORD attributes0[] = {0}; 7042 const DWORD exp_indices0[] = {0, 1, 2}; 7043 const UINT num_vertices0 = ARRAY_SIZE(vertices0); 7044 const UINT num_faces0 = ARRAY_SIZE(indices0) / VERTS_PER_FACE; 7045 const DWORD flags0 = D3DXWELDEPSILONS_WELDALL; 7046 /* epsilons0 is NULL */ 7047 const DWORD adjacency0[] = {-1, -1, -1}; 7048 const struct vertex exp_vertices0[] = 7049 { 7050 {{ 0.0f, 3.0f, 0.f}, up}, 7051 {{ 2.0f, 3.0f, 0.f}, up}, 7052 {{ 0.0f, 0.0f, 0.f}, up}, 7053 }; 7054 const DWORD exp_face_remap0[] = {0}; 7055 const DWORD exp_vertex_remap0[] = {0, 1, 2}; 7056 const DWORD exp_new_num_vertices0 = ARRAY_SIZE(exp_vertices0); 7057 /* Test 1. Two vertices should be removed without regard to epsilon. 7058 * 7059 * 0--1 3 7060 * | / /| 7061 * |/ / | 7062 * 2 5--4 7063 */ 7064 const struct vertex_normal vertices1[] = 7065 { 7066 {{ 0.0f, 3.0f, 0.f}, up}, 7067 {{ 2.0f, 3.0f, 0.f}, up}, 7068 {{ 0.0f, 0.0f, 0.f}, up}, 7069 7070 {{ 3.0f, 3.0f, 0.f}, up}, 7071 {{ 3.0f, 0.0f, 0.f}, up}, 7072 {{ 1.0f, 0.0f, 0.f}, up}, 7073 }; 7074 const DWORD indices1[] = {0, 1, 2, 3, 4, 5}; 7075 const DWORD attributes1[] = {0, 0}; 7076 const UINT num_vertices1 = ARRAY_SIZE(vertices1); 7077 const UINT num_faces1 = ARRAY_SIZE(indices1) / VERTS_PER_FACE; 7078 const DWORD flags1 = D3DXWELDEPSILONS_WELDALL; 7079 /* epsilons1 is NULL */ 7080 const DWORD adjacency1[] = {-1, 1, -1, -1, -1, 0}; 7081 const struct vertex_normal exp_vertices1[] = 7082 { 7083 {{ 0.0f, 3.0f, 0.f}, up}, 7084 {{ 2.0f, 3.0f, 0.f}, up}, 7085 {{ 0.0f, 0.0f, 0.f}, up}, 7086 7087 {{ 3.0f, 0.0f, 0.f}, up} 7088 }; 7089 const DWORD exp_indices1[] = {0, 1, 2, 1, 3, 2}; 7090 const DWORD exp_face_remap1[] = {0, 1}; 7091 const DWORD exp_vertex_remap1[] = {0, 1, 2, 4, -1, -1}; 7092 const DWORD exp_new_num_vertices1 = ARRAY_SIZE(exp_vertices1); 7093 /* Test 2. Two faces. No vertices should be removed because of normal 7094 * epsilon, but the positions should be replaced. */ 7095 const struct vertex_normal vertices2[] = 7096 { 7097 {{ 0.0f, 3.0f, 0.f}, up}, 7098 {{ 2.0f, 3.0f, 0.f}, up}, 7099 {{ 0.0f, 0.0f, 0.f}, up}, 7100 7101 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}}, 7102 {{ 3.0f, 0.0f, 0.f}, up}, 7103 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}}, 7104 }; 7105 const DWORD indices2[] = {0, 1, 2, 3, 4, 5}; 7106 const DWORD attributes2[] = {0, 0}; 7107 const UINT num_vertices2 = ARRAY_SIZE(vertices2); 7108 const UINT num_faces2 = ARRAY_SIZE(indices2) / VERTS_PER_FACE; 7109 DWORD flags2 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7110 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}; 7111 const DWORD adjacency2[] = {-1, 1, -1, -1, -1, 0}; 7112 const struct vertex_normal exp_vertices2[] = 7113 { 7114 {{ 0.0f, 3.0f, 0.f}, up}, 7115 {{ 2.0f, 3.0f, 0.f}, up}, 7116 {{ 0.0f, 0.0f, 0.f}, up}, 7117 7118 {{ 2.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}}, 7119 {{ 3.0f, 0.0f, 0.f}, up}, 7120 {{ 0.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}}, 7121 }; 7122 const DWORD exp_indices2[] = {0, 1, 2, 3, 4, 5}; 7123 const DWORD exp_face_remap2[] = {0, 1}; 7124 const DWORD exp_vertex_remap2[] = {0, 1, 2, 3, 4, 5}; 7125 const DWORD exp_new_num_vertices2 = ARRAY_SIZE(exp_vertices2); 7126 /* Test 3. Two faces. One vertex should be removed because of normal epsilon. */ 7127 const struct vertex_normal vertices3[] = 7128 { 7129 {{ 0.0f, 3.0f, 0.f}, up}, 7130 {{ 2.0f, 3.0f, 0.f}, up}, 7131 {{ 0.0f, 0.0f, 0.f}, up}, 7132 7133 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}}, 7134 {{ 3.0f, 0.0f, 0.f}, up}, 7135 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}}, 7136 }; 7137 const DWORD indices3[] = {0, 1, 2, 3, 4, 5}; 7138 const DWORD attributes3[] = {0, 0}; 7139 const UINT num_vertices3 = ARRAY_SIZE(vertices3); 7140 const UINT num_faces3 = ARRAY_SIZE(indices3) / VERTS_PER_FACE; 7141 DWORD flags3 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7142 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}; 7143 const DWORD adjacency3[] = {-1, 1, -1, -1, -1, 0}; 7144 const struct vertex_normal exp_vertices3[] = 7145 { 7146 {{ 0.0f, 3.0f, 0.f}, up}, 7147 {{ 2.0f, 3.0f, 0.f}, up}, 7148 {{ 0.0f, 0.0f, 0.f}, up}, 7149 7150 {{ 3.0f, 0.0f, 0.f}, up}, 7151 {{ 0.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}}, 7152 }; 7153 const DWORD exp_indices3[] = {0, 1, 2, 1, 3, 4}; 7154 const DWORD exp_face_remap3[] = {0, 1}; 7155 const DWORD exp_vertex_remap3[] = {0, 1, 2, 4, 5, -1}; 7156 const DWORD exp_new_num_vertices3 = ARRAY_SIZE(exp_vertices3); 7157 /* Test 4 Two faces. Two vertices should be removed. */ 7158 const struct vertex_normal vertices4[] = 7159 { 7160 {{ 0.0f, 3.0f, 0.f}, up}, 7161 {{ 2.0f, 3.0f, 0.f}, up}, 7162 {{ 0.0f, 0.0f, 0.f}, up}, 7163 7164 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}}, 7165 {{ 3.0f, 0.0f, 0.f}, up}, 7166 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}}, 7167 }; 7168 const DWORD indices4[] = {0, 1, 2, 3, 4, 5}; 7169 const DWORD attributes4[] = {0, 0}; 7170 const UINT num_vertices4 = ARRAY_SIZE(vertices4); 7171 const UINT num_faces4 = ARRAY_SIZE(indices4) / VERTS_PER_FACE; 7172 DWORD flags4 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7173 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}; 7174 const DWORD adjacency4[] = {-1, 1, -1, -1, -1, 0}; 7175 const struct vertex_normal exp_vertices4[] = 7176 { 7177 {{ 0.0f, 3.0f, 0.f}, up}, 7178 {{ 2.0f, 3.0f, 0.f}, up}, 7179 {{ 0.0f, 0.0f, 0.f}, up}, 7180 7181 {{ 3.0f, 0.0f, 0.f}, up}, 7182 }; 7183 const DWORD exp_indices4[] = {0, 1, 2, 1, 3, 2}; 7184 const DWORD exp_face_remap4[] = {0, 1}; 7185 const DWORD exp_vertex_remap4[] = {0, 1, 2, 4, -1, -1}; 7186 const DWORD exp_new_num_vertices4 = ARRAY_SIZE(exp_vertices4); 7187 /* Test 5. Odd face ordering. 7188 * 7189 * 0--1 6 3 7190 * | / /| |\ 7191 * |/ / | | \ 7192 * 2 8--7 5--4 7193 */ 7194 const struct vertex_normal vertices5[] = 7195 { 7196 {{ 0.0f, 3.0f, 0.f}, up}, 7197 {{ 2.0f, 3.0f, 0.f}, up}, 7198 {{ 0.0f, 0.0f, 0.f}, up}, 7199 7200 {{ 3.0f, 3.0f, 0.f}, up}, 7201 {{ 3.0f, 0.0f, 0.f}, up}, 7202 {{ 1.0f, 0.0f, 0.f}, up}, 7203 7204 {{ 4.0f, 3.0f, 0.f}, up}, 7205 {{ 6.0f, 0.0f, 0.f}, up}, 7206 {{ 4.0f, 0.0f, 0.f}, up}, 7207 }; 7208 const DWORD indices5[] = {0, 1, 2, 6, 7, 8, 3, 4, 5}; 7209 const DWORD exp_indices5[] = {0, 1, 2, 1, 4, 2, 1, 3, 4}; 7210 const DWORD attributes5[] = {0, 0, 0}; 7211 const UINT num_vertices5 = ARRAY_SIZE(vertices5); 7212 const UINT num_faces5 = ARRAY_SIZE(indices5) / VERTS_PER_FACE; 7213 DWORD flags5 = D3DXWELDEPSILONS_WELDALL; 7214 const DWORD adjacency5[] = {-1, 1, -1, 2, -1, 0, -1, -1, 1}; 7215 const struct vertex_normal exp_vertices5[] = 7216 { 7217 {{ 0.0f, 3.0f, 0.f}, up}, 7218 {{ 2.0f, 3.0f, 0.f}, up}, 7219 {{ 0.0f, 0.0f, 0.f}, up}, 7220 7221 {{ 3.0f, 0.0f, 0.f}, up}, 7222 {{ 1.0f, 0.0f, 0.f}, up}, 7223 }; 7224 const DWORD exp_face_remap5[] = {0, 1, 2}; 7225 const DWORD exp_vertex_remap5[] = {0, 1, 2, 4, 5, -1, -1, -1, -1}; 7226 const DWORD exp_new_num_vertices5 = ARRAY_SIZE(exp_vertices5); 7227 /* Test 6. Two faces. Do not remove flag is used, so no vertices should be 7228 * removed. */ 7229 const struct vertex_normal vertices6[] = 7230 { 7231 {{ 0.0f, 3.0f, 0.f}, up}, 7232 {{ 2.0f, 3.0f, 0.f}, up}, 7233 {{ 0.0f, 0.0f, 0.f}, up}, 7234 7235 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}}, 7236 {{ 3.0f, 0.0f, 0.f}, up}, 7237 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}}, 7238 }; 7239 const DWORD indices6[] = {0, 1, 2, 3, 4, 5}; 7240 const DWORD attributes6[] = {0, 0}; 7241 const UINT num_vertices6 = ARRAY_SIZE(vertices6); 7242 const UINT num_faces6 = ARRAY_SIZE(indices6) / VERTS_PER_FACE; 7243 DWORD flags6 = D3DXWELDEPSILONS_WELDPARTIALMATCHES | D3DXWELDEPSILONS_DONOTREMOVEVERTICES; 7244 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}; 7245 const DWORD adjacency6[] = {-1, 1, -1, -1, -1, 0}; 7246 const struct vertex_normal exp_vertices6[] = 7247 { 7248 {{ 0.0f, 3.0f, 0.f}, up}, 7249 {{ 2.0f, 3.0f, 0.f}, up}, 7250 {{ 0.0f, 0.0f, 0.f}, up}, 7251 7252 {{ 2.0f, 3.0f, 0.f}, up}, 7253 {{ 3.0f, 0.0f, 0.f}, up}, 7254 {{ 0.0f, 0.0f, 0.f}, up}, 7255 7256 }; 7257 const DWORD exp_indices6[] = {0, 1, 2, 3, 4, 5}; 7258 const DWORD exp_face_remap6[] = {0, 1}; 7259 const DWORD exp_vertex_remap6[] = {0, 1, 2, 3, 4, 5}; 7260 const DWORD exp_new_num_vertices6 = ARRAY_SIZE(exp_vertices6); 7261 /* Test 7. Same as test 6 but with 16 bit indices. */ 7262 const WORD indices6_16bit[] = {0, 1, 2, 3, 4, 5}; 7263 /* Test 8. No flags. Same result as D3DXWELDEPSILONS_WELDPARTIALMATCHES. */ 7264 const struct vertex_normal vertices8[] = 7265 { 7266 {{ 0.0f, 3.0f, 0.f}, up}, 7267 {{ 2.0f, 3.0f, 0.f}, up}, 7268 {{ 0.0f, 0.0f, 0.f}, up}, 7269 7270 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}}, 7271 {{ 3.0f, 0.0f, 0.f}, up}, 7272 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}}, 7273 }; 7274 const DWORD indices8[] = {0, 1, 2, 1, 3, 4}; 7275 const DWORD attributes8[] = {0, 0}; 7276 const UINT num_vertices8 = ARRAY_SIZE(vertices8); 7277 const UINT num_faces8 = ARRAY_SIZE(indices8) / VERTS_PER_FACE; 7278 DWORD flags8 = 0; 7279 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}; 7280 const DWORD adjacency8[] = {-1, 1, -1, -1, -1, 0}; 7281 const struct vertex_normal exp_vertices8[] = 7282 { 7283 {{ 0.0f, 3.0f, 0.f}, up}, 7284 {{ 2.0f, 3.0f, 0.f}, up}, 7285 {{ 0.0f, 0.0f, 0.f}, up}, 7286 7287 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}}, 7288 {{ 3.0f, 0.0f, 0.f}, up}, 7289 }; 7290 const DWORD exp_indices8[] = {0, 1, 2, 1, 3, 4}; 7291 const DWORD exp_face_remap8[] = {0, 1}; 7292 const DWORD exp_vertex_remap8[] = {0, 1, 2, 3, 4, -1}; 7293 const DWORD exp_new_num_vertices8 = ARRAY_SIZE(exp_vertices8); 7294 /* Test 9. Vertices are removed even though they belong to separate 7295 * attribute groups if D3DXWELDEPSILONS_DONOTSPLIT is set. */ 7296 const struct vertex_normal vertices9[] = 7297 { 7298 {{ 0.0f, 3.0f, 0.f}, up}, 7299 {{ 2.0f, 3.0f, 0.f}, up}, 7300 {{ 0.0f, 0.0f, 0.f}, up}, 7301 7302 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}}, 7303 {{ 3.0f, 0.0f, 0.f}, up}, 7304 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}}, 7305 }; 7306 const DWORD indices9[] = {0, 1, 2, 3, 4, 5}; 7307 const DWORD attributes9[] = {0, 1}; 7308 const UINT num_vertices9 = ARRAY_SIZE(vertices9); 7309 const UINT num_faces9 = ARRAY_SIZE(indices9) / VERTS_PER_FACE; 7310 DWORD flags9 = D3DXWELDEPSILONS_WELDPARTIALMATCHES | D3DXWELDEPSILONS_DONOTSPLIT; 7311 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}; 7312 const DWORD adjacency9[] = {-1, 1, -1, -1, -1, 0}; 7313 const struct vertex_normal exp_vertices9[] = 7314 { 7315 {{ 0.0f, 3.0f, 0.f}, up}, 7316 {{ 2.0f, 3.0f, 0.f}, up}, 7317 {{ 0.0f, 0.0f, 0.f}, up}, 7318 7319 {{ 3.0f, 0.0f, 0.f}, up}, 7320 }; 7321 const DWORD exp_indices9[] = {0, 1, 2, 1, 3, 2}; 7322 const DWORD exp_face_remap9[] = {0, 1}; 7323 const DWORD exp_vertex_remap9[] = {0, 1, 2, 4, -1, -1}; 7324 const DWORD exp_new_num_vertices9 = ARRAY_SIZE(exp_vertices9); 7325 /* Test 10. Weld blendweight (FLOAT1). */ 7326 const struct vertex_blendweight vertices10[] = 7327 { 7328 {{ 0.0f, 3.0f, 0.f}, 1.0f}, 7329 {{ 2.0f, 3.0f, 0.f}, 1.0f}, 7330 {{ 0.0f, 0.0f, 0.f}, 1.0f}, 7331 7332 {{ 3.0f, 3.0f, 0.f}, 0.9}, 7333 {{ 3.0f, 0.0f, 0.f}, 1.0}, 7334 {{ 1.0f, 0.0f, 0.f}, 0.4}, 7335 }; 7336 const DWORD indices10[] = {0, 1, 2, 3, 4, 5}; 7337 const DWORD attributes10[] = {0, 0}; 7338 const UINT num_vertices10 = ARRAY_SIZE(vertices10); 7339 const UINT num_faces10 = ARRAY_SIZE(indices10) / VERTS_PER_FACE; 7340 DWORD flags10 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7341 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}; 7342 const DWORD adjacency10[] = {-1, 1, -1, -1, -1, 0}; 7343 const struct vertex_blendweight exp_vertices10[] = 7344 { 7345 {{ 0.0f, 3.0f, 0.f}, 1.0f}, 7346 {{ 2.0f, 3.0f, 0.f}, 1.0f}, 7347 {{ 0.0f, 0.0f, 0.f}, 1.0f}, 7348 7349 {{ 3.0f, 0.0f, 0.f}, 1.0}, 7350 {{ 0.0f, 0.0f, 0.f}, 0.4}, 7351 }; 7352 const DWORD exp_indices10[] = {0, 1, 2, 1, 3, 4}; 7353 const DWORD exp_face_remap10[] = {0, 1}; 7354 const DWORD exp_vertex_remap10[] = {0, 1, 2, 4, 5, -1}; 7355 const DWORD exp_new_num_vertices10 = ARRAY_SIZE(exp_vertices10); 7356 /* Test 11. Weld texture coordinates. */ 7357 const struct vertex_texcoord vertices11[] = 7358 { 7359 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f}}, 7360 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.7f}}, 7361 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}}, 7362 7363 {{ 3.0f, 3.0f, 0.f}, {0.2f, 0.3f}}, 7364 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f}}, 7365 {{ 1.0f, 0.0f, 0.f}, {0.1f, 0.2f}} 7366 }; 7367 const DWORD indices11[] = {0, 1, 2, 3, 4, 5}; 7368 const DWORD attributes11[] = {0, 0}; 7369 const UINT num_vertices11 = ARRAY_SIZE(vertices11); 7370 const UINT num_faces11 = ARRAY_SIZE(indices11) / VERTS_PER_FACE; 7371 DWORD flags11 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7372 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}; 7373 const DWORD adjacency11[] = {-1, 1, -1, -1, -1, 0}; 7374 const struct vertex_texcoord exp_vertices11[] = 7375 { 7376 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f}}, 7377 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.7f}}, 7378 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}}, 7379 7380 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f}}, 7381 {{ 0.0f, 0.0f, 0.f}, {0.1f, 0.2f}}, 7382 }; 7383 const DWORD exp_indices11[] = {0, 1, 2, 1, 3, 4}; 7384 const DWORD exp_face_remap11[] = {0, 1}; 7385 const DWORD exp_vertex_remap11[] = {0, 1, 2, 4, 5, -1}; 7386 const DWORD exp_new_num_vertices11 = ARRAY_SIZE(exp_vertices11); 7387 /* Test 12. Weld with color. */ 7388 const struct vertex_color vertices12[] = 7389 { 7390 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF}, 7391 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF}, 7392 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF}, 7393 7394 {{ 3.0f, 3.0f, 0.f}, 0x00000000}, 7395 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF}, 7396 {{ 1.0f, 0.0f, 0.f}, 0x88888888}, 7397 }; 7398 const DWORD indices12[] = {0, 1, 2, 3, 4, 5}; 7399 const DWORD attributes12[] = {0, 0}; 7400 const UINT num_vertices12 = ARRAY_SIZE(vertices12); 7401 const UINT num_faces12 = ARRAY_SIZE(indices12) / VERTS_PER_FACE; 7402 DWORD flags12 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7403 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}; 7404 const DWORD adjacency12[] = {-1, 1, -1, -1, -1, 0}; 7405 const struct vertex_color exp_vertices12[] = 7406 { 7407 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF}, 7408 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF}, 7409 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF}, 7410 7411 {{ 2.0f, 3.0f, 0.f}, 0x00000000}, 7412 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF}, 7413 }; 7414 const DWORD exp_indices12[] = {0, 1, 2, 3, 4, 2}; 7415 const DWORD exp_face_remap12[] = {0, 1}; 7416 const DWORD exp_vertex_remap12[] = {0, 1, 2, 3, 4, -1}; 7417 const DWORD exp_new_num_vertices12 = ARRAY_SIZE(exp_vertices12); 7418 /* Test 13. Two faces. One vertex should be removed because of normal epsilon. 7419 * This is similar to test 3, but the declaration has been changed to NORMAL3. 7420 */ 7421 const struct vertex_normal vertices13[] = 7422 { 7423 {{ 0.0f, 3.0f, 0.f}, up}, 7424 {{ 2.0f, 3.0f, 0.f}, up}, 7425 {{ 0.0f, 0.0f, 0.f}, up}, 7426 7427 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}}, 7428 {{ 3.0f, 0.0f, 0.f}, up}, 7429 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}}, 7430 }; 7431 const DWORD indices13[] = {0, 1, 2, 3, 4, 5}; 7432 const DWORD attributes13[] = {0, 0}; 7433 const UINT num_vertices13 = ARRAY_SIZE(vertices3); 7434 const UINT num_faces13 = ARRAY_SIZE(indices3) / VERTS_PER_FACE; 7435 DWORD flags13 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7436 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}; 7437 const DWORD adjacency13[] = {-1, 1, -1, -1, -1, 0}; 7438 const struct vertex_normal exp_vertices13[] = 7439 { 7440 {{ 0.0f, 3.0f, 0.f}, up}, 7441 {{ 2.0f, 3.0f, 0.f}, up}, 7442 {{ 0.0f, 0.0f, 0.f}, up}, 7443 7444 {{ 3.0f, 0.0f, 0.f}, up}, 7445 {{ 0.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}}, 7446 }; 7447 const DWORD exp_indices13[] = {0, 1, 2, 1, 3, 4}; 7448 const DWORD exp_face_remap13[] = {0, 1}; 7449 const DWORD exp_vertex_remap13[] = {0, 1, 2, 4, 5, -1}; 7450 const DWORD exp_new_num_vertices13 = ARRAY_SIZE(exp_vertices13); 7451 /* Test 14. Another test for welding with color. */ 7452 const struct vertex_color vertices14[] = 7453 { 7454 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF}, 7455 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF}, 7456 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF}, 7457 7458 {{ 3.0f, 3.0f, 0.f}, 0x00000000}, 7459 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF}, 7460 {{ 1.0f, 0.0f, 0.f}, 0x01010101}, 7461 }; 7462 const DWORD indices14[] = {0, 1, 2, 3, 4, 5}; 7463 const DWORD attributes14[] = {0, 0}; 7464 const UINT num_vertices14 = ARRAY_SIZE(vertices14); 7465 const UINT num_faces14 = ARRAY_SIZE(indices14) / VERTS_PER_FACE; 7466 DWORD flags14 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7467 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}; 7468 const DWORD adjacency14[] = {-1, 1, -1, -1, -1, 0}; 7469 const struct vertex_color exp_vertices14[] = 7470 { 7471 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF}, 7472 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF}, 7473 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF}, 7474 7475 {{ 2.0f, 3.0f, 0.f}, 0x00000000}, 7476 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF}, 7477 }; 7478 const DWORD exp_indices14[] = {0, 1, 2, 3, 4, 2}; 7479 const DWORD exp_face_remap14[] = {0, 1}; 7480 const DWORD exp_vertex_remap14[] = {0, 1, 2, 3, 4, -1}; 7481 const DWORD exp_new_num_vertices14 = ARRAY_SIZE(exp_vertices14); 7482 /* Test 15. Weld with color, but as UBYTE4N instead of D3DCOLOR. It shows 7483 * that UBYTE4N and D3DCOLOR are compared the same way. 7484 */ 7485 const struct vertex_color_ubyte4 vertices15[] = 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 {{ 3.0f, 3.0f, 0.f}, { 0, 0, 0, 0}}, 7492 {{ 3.0f, 0.0f, 0.f}, {255, 255, 255, 255}}, 7493 {{ 1.0f, 0.0f, 0.f}, { 1, 1, 1, 1}}, 7494 }; 7495 const DWORD indices15[] = {0, 1, 2, 3, 4, 5}; 7496 const DWORD attributes15[] = {0, 0}; 7497 const UINT num_vertices15 = ARRAY_SIZE(vertices15); 7498 const UINT num_faces15 = ARRAY_SIZE(indices15) / VERTS_PER_FACE; 7499 DWORD flags15 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7500 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}; 7501 const DWORD adjacency15[] = {-1, 1, -1, -1, -1, 0}; 7502 const struct vertex_color_ubyte4 exp_vertices15[] = 7503 { 7504 {{ 0.0f, 3.0f, 0.f}, {255, 255, 255, 255}}, 7505 {{ 2.0f, 3.0f, 0.f}, {255, 255, 255, 255}}, 7506 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}}, 7507 7508 {{ 2.0f, 3.0f, 0.f}, { 0, 0, 0, 0}}, 7509 {{ 3.0f, 0.0f, 0.f}, {255, 255, 255, 255}}, 7510 }; 7511 const DWORD exp_indices15[] = {0, 1, 2, 3, 4, 2}; 7512 const DWORD exp_face_remap15[] = {0, 1}; 7513 const DWORD exp_vertex_remap15[] = {0, 1, 2, 3, 4, -1}; 7514 const DWORD exp_new_num_vertices15 = ARRAY_SIZE(exp_vertices15); 7515 /* Test 16. Weld with color, but as UBYTE4 instead of D3DCOLOR. It shows 7516 * that UBYTE4 is not normalized and that epsilon is truncated and compared 7517 * directly to each of the four bytes. 7518 */ 7519 const struct vertex_color_ubyte4 vertices16[] = 7520 { 7521 {{ 0.0f, 3.0f, 0.f}, {255, 255, 255, 255}}, 7522 {{ 2.0f, 3.0f, 0.f}, {255, 255, 255, 255}}, 7523 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}}, 7524 7525 {{ 3.0f, 3.0f, 0.f}, { 0, 0, 0, 0}}, 7526 {{ 3.0f, 0.0f, 0.f}, {255, 255, 255, 255}}, 7527 {{ 1.0f, 0.0f, 0.f}, { 1, 1, 1, 1}}, 7528 }; 7529 const DWORD indices16[] = {0, 1, 2, 3, 4, 5}; 7530 const DWORD attributes16[] = {0, 0}; 7531 const UINT num_vertices16 = ARRAY_SIZE(vertices16); 7532 const UINT num_faces16 = ARRAY_SIZE(indices16) / VERTS_PER_FACE; 7533 DWORD flags16 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7534 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}; 7535 const DWORD adjacency16[] = {-1, 1, -1, -1, -1, 0}; 7536 const struct vertex_color_ubyte4 exp_vertices16[] = 7537 { 7538 {{ 0.0f, 3.0f, 0.f}, {255, 255, 255, 255}}, 7539 {{ 2.0f, 3.0f, 0.f}, {255, 255, 255, 255}}, 7540 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}}, 7541 7542 {{ 2.0f, 3.0f, 0.f}, { 0, 0, 0, 0}}, 7543 {{ 3.0f, 0.0f, 0.f}, {255, 255, 255, 255}}, 7544 }; 7545 const DWORD exp_indices16[] = {0, 1, 2, 3, 4, 2}; 7546 const DWORD exp_face_remap16[] = {0, 1}; 7547 const DWORD exp_vertex_remap16[] = {0, 1, 2, 3, 4, -1}; 7548 const DWORD exp_new_num_vertices16 = ARRAY_SIZE(exp_vertices16); 7549 /* Test 17. Weld texture coordinates but as SHORT2 instead of D3DXVECTOR2.*/ 7550 const struct vertex_texcoord_short2 vertices17[] = 7551 { 7552 {{ 0.0f, 3.0f, 0.f}, { 0, 0}}, 7553 {{ 2.0f, 3.0f, 0.f}, { 0, 0}}, 7554 {{ 0.0f, 0.0f, 0.f}, { 0, 0}}, 7555 7556 {{ 3.0f, 3.0f, 0.f}, {32767, 32767}}, 7557 {{ 3.0f, 0.0f, 0.f}, {0, 0}}, 7558 {{ 1.0f, 0.0f, 0.f}, {32766, 32766}}, 7559 }; 7560 const DWORD indices17[] = {0, 1, 2, 3, 4, 5}; 7561 const DWORD attributes17[] = {0, 0}; 7562 const UINT num_vertices17 = ARRAY_SIZE(vertices17); 7563 const UINT num_faces17 = ARRAY_SIZE(indices17) / VERTS_PER_FACE; 7564 DWORD flags17 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7565 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}; 7566 const DWORD adjacency17[] = {-1, 1, -1, -1, -1, 0}; 7567 const struct vertex_texcoord_short2 exp_vertices17[] = 7568 { 7569 {{ 0.0f, 3.0f, 0.f}, { 0, 0}}, 7570 {{ 2.0f, 3.0f, 0.f}, { 0, 0}}, 7571 {{ 0.0f, 0.0f, 0.f}, { 0, 0}}, 7572 7573 {{ 2.0f, 3.0f, 0.f}, {32767, 32767}}, 7574 {{ 3.0f, 0.0f, 0.f}, {0, 0}}, 7575 }; 7576 const DWORD exp_indices17[] = {0, 1, 2, 3, 4, 2}; 7577 const DWORD exp_face_remap17[] = {0, 1}; 7578 const DWORD exp_vertex_remap17[] = {0, 1, 2, 3, 4, -1}; 7579 const DWORD exp_new_num_vertices17 = ARRAY_SIZE(exp_vertices17); 7580 /* Test 18. Weld texture coordinates but as SHORT2N instead of D3DXVECTOR2. */ 7581 const struct vertex_texcoord_short2 vertices18[] = 7582 { 7583 {{ 0.0f, 3.0f, 0.f}, { 0, 0}}, 7584 {{ 2.0f, 3.0f, 0.f}, { 0, 0}}, 7585 {{ 0.0f, 0.0f, 0.f}, { 0, 0}}, 7586 7587 {{ 3.0f, 3.0f, 0.f}, {32767, 32767}}, 7588 {{ 3.0f, 0.0f, 0.f}, {0, 0}}, 7589 {{ 1.0f, 0.0f, 0.f}, {32766, 32766}}, 7590 }; 7591 const DWORD indices18[] = {0, 1, 2, 3, 4, 5}; 7592 const DWORD attributes18[] = {0, 0}; 7593 const UINT num_vertices18 = ARRAY_SIZE(vertices18); 7594 const UINT num_faces18 = ARRAY_SIZE(indices18) / VERTS_PER_FACE; 7595 DWORD flags18 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7596 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}; 7597 const DWORD adjacency18[] = {-1, 1, -1, -1, -1, 0}; 7598 const struct vertex_texcoord_short2 exp_vertices18[] = 7599 { 7600 {{ 0.0f, 3.0f, 0.f}, { 0, 0}}, 7601 {{ 2.0f, 3.0f, 0.f}, { 0, 0}}, 7602 {{ 0.0f, 0.0f, 0.f}, { 0, 0}}, 7603 7604 {{ 2.0f, 3.0f, 0.f}, {32767, 32767}}, 7605 {{ 3.0f, 0.0f, 0.f}, {0, 0}}, 7606 }; 7607 const DWORD exp_indices18[] = {0, 1, 2, 3, 4, 2}; 7608 const DWORD exp_face_remap18[] = {0, 1}; 7609 const DWORD exp_vertex_remap18[] = {0, 1, 2, 3, 4, -1}; 7610 const DWORD exp_new_num_vertices18 = ARRAY_SIZE(exp_vertices18); 7611 /* Test 19. Weld texture coordinates but as USHORT2N instead of D3DXVECTOR2. */ 7612 const struct vertex_texcoord_ushort2n vertices19[] = 7613 { 7614 {{ 0.0f, 3.0f, 0.f}, { 0, 0}}, 7615 {{ 2.0f, 3.0f, 0.f}, { 0, 0}}, 7616 {{ 0.0f, 0.0f, 0.f}, { 0, 0}}, 7617 7618 {{ 3.0f, 3.0f, 0.f}, {65535, 65535}}, 7619 {{ 3.0f, 0.0f, 0.f}, {0, 0}}, 7620 {{ 1.0f, 0.0f, 0.f}, {65534, 65534}}, 7621 }; 7622 const DWORD indices19[] = {0, 1, 2, 3, 4, 5}; 7623 const DWORD attributes19[] = {0, 0}; 7624 const UINT num_vertices19 = ARRAY_SIZE(vertices19); 7625 const UINT num_faces19 = ARRAY_SIZE(indices19) / VERTS_PER_FACE; 7626 DWORD flags19 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7627 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}; 7628 const DWORD adjacency19[] = {-1, 1, -1, -1, -1, 0}; 7629 const struct vertex_texcoord_ushort2n exp_vertices19[] = 7630 { 7631 {{ 0.0f, 3.0f, 0.f}, { 0, 0}}, 7632 {{ 2.0f, 3.0f, 0.f}, { 0, 0}}, 7633 {{ 0.0f, 0.0f, 0.f}, { 0, 0}}, 7634 7635 {{ 2.0f, 3.0f, 0.f}, {65535, 65535}}, 7636 {{ 3.0f, 0.0f, 0.f}, {0, 0}}, 7637 }; 7638 const DWORD exp_indices19[] = {0, 1, 2, 3, 4, 2}; 7639 const DWORD exp_face_remap19[] = {0, 1}; 7640 const DWORD exp_vertex_remap19[] = {0, 1, 2, 3, 4, -1}; 7641 const DWORD exp_new_num_vertices19 = ARRAY_SIZE(exp_vertices19); 7642 /* Test 20. Weld normal as SHORT4 instead of D3DXVECTOR3. */ 7643 const struct vertex_normal_short4 vertices20[] = 7644 { 7645 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, 7646 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, 7647 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}}, 7648 7649 {{ 3.0f, 3.0f, 0.f}, {32767, 32767, 32767, 32767}}, 7650 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}}, 7651 {{ 1.0f, 0.0f, 0.f}, {32766, 32766, 32766, 32766}}, 7652 }; 7653 const DWORD indices20[] = {0, 1, 2, 3, 4, 5}; 7654 const DWORD attributes20[] = {0, 0}; 7655 const UINT num_vertices20 = ARRAY_SIZE(vertices20); 7656 const UINT num_faces20 = ARRAY_SIZE(indices20) / VERTS_PER_FACE; 7657 DWORD flags20 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7658 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}; 7659 const DWORD adjacency20[] = {-1, 1, -1, -1, -1, 0}; 7660 const struct vertex_normal_short4 exp_vertices20[] = 7661 { 7662 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, 7663 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, 7664 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}}, 7665 7666 {{ 2.0f, 3.0f, 0.f}, {32767, 32767, 32767, 32767}}, 7667 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}}, 7668 }; 7669 const DWORD exp_indices20[] = {0, 1, 2, 3, 4, 2}; 7670 const DWORD exp_face_remap20[] = {0, 1}; 7671 const DWORD exp_vertex_remap20[] = {0, 1, 2, 3, 4, -1}; 7672 const DWORD exp_new_num_vertices20 = ARRAY_SIZE(exp_vertices20); 7673 /* Test 21. Weld normal as SHORT4N instead of D3DXVECTOR3. */ 7674 const struct vertex_normal_short4 vertices21[] = 7675 { 7676 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, 7677 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, 7678 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}}, 7679 7680 {{ 3.0f, 3.0f, 0.f}, {32767, 32767, 32767, 32767}}, 7681 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}}, 7682 {{ 1.0f, 0.0f, 0.f}, {32766, 32766, 32766, 32766}}, 7683 }; 7684 const DWORD indices21[] = {0, 1, 2, 3, 4, 5}; 7685 const DWORD attributes21[] = {0, 0}; 7686 const UINT num_vertices21 = ARRAY_SIZE(vertices21); 7687 const UINT num_faces21 = ARRAY_SIZE(indices21) / VERTS_PER_FACE; 7688 DWORD flags21 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7689 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}; 7690 const DWORD adjacency21[] = {-1, 1, -1, -1, -1, 0}; 7691 const struct vertex_normal_short4 exp_vertices21[] = 7692 { 7693 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, 7694 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, 7695 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}}, 7696 7697 {{ 2.0f, 3.0f, 0.f}, {32767, 32767, 32767, 32767}}, 7698 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}}, 7699 }; 7700 const DWORD exp_indices21[] = {0, 1, 2, 3, 4, 2}; 7701 const DWORD exp_face_remap21[] = {0, 1}; 7702 const DWORD exp_vertex_remap21[] = {0, 1, 2, 3, 4, -1}; 7703 const DWORD exp_new_num_vertices21 = ARRAY_SIZE(exp_vertices21); 7704 /* Test 22. Weld normal as USHORT4N instead of D3DXVECTOR3. */ 7705 const struct vertex_normal_short4 vertices22[] = 7706 { 7707 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, 7708 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, 7709 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}}, 7710 7711 {{ 3.0f, 3.0f, 0.f}, {65535, 65535, 65535, 65535}}, 7712 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}}, 7713 {{ 1.0f, 0.0f, 0.f}, {65534, 65534, 65534, 65534}}, 7714 }; 7715 const DWORD indices22[] = {0, 1, 2, 3, 4, 5}; 7716 const DWORD attributes22[] = {0, 0}; 7717 const UINT num_vertices22 = ARRAY_SIZE(vertices22); 7718 const UINT num_faces22 = ARRAY_SIZE(indices22) / VERTS_PER_FACE; 7719 DWORD flags22 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7720 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}; 7721 const DWORD adjacency22[] = {-1, 1, -1, -1, -1, 0}; 7722 const struct vertex_normal_short4 exp_vertices22[] = 7723 { 7724 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, 7725 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, 7726 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}}, 7727 7728 {{ 2.0f, 3.0f, 0.f}, {65535, 65535, 65535, 65535}}, 7729 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}}, 7730 }; 7731 const DWORD exp_indices22[] = {0, 1, 2, 3, 4, 2}; 7732 const DWORD exp_face_remap22[] = {0, 1}; 7733 const DWORD exp_vertex_remap22[] = {0, 1, 2, 3, 4, -1}; 7734 const DWORD exp_new_num_vertices22 = ARRAY_SIZE(exp_vertices22); 7735 /* Test 23. Weld texture coordinates as FLOAT16_2. Similar to test 11, but 7736 * with texture coordinates converted to float16 in hex. */ 7737 const struct vertex_texcoord_float16_2 vertices23[] = 7738 { 7739 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */ 7740 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */ 7741 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */ 7742 7743 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd}}, /* {0.2f, 0.3f} */ 7744 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */ 7745 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */ 7746 }; 7747 const DWORD indices23[] = {0, 1, 2, 3, 4, 5}; 7748 const DWORD attributes23[] = {0, 0}; 7749 const UINT num_vertices23 = ARRAY_SIZE(vertices23); 7750 const UINT num_faces23 = ARRAY_SIZE(indices23) / VERTS_PER_FACE; 7751 DWORD flags23 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7752 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}; 7753 const DWORD adjacency23[] = {-1, 1, -1, -1, -1, 0}; 7754 const struct vertex_texcoord_float16_2 exp_vertices23[] = 7755 { 7756 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */ 7757 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */ 7758 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */ 7759 7760 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */ 7761 {{ 0.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */ 7762 }; 7763 const DWORD exp_indices23[] = {0, 1, 2, 1, 3, 4}; 7764 const DWORD exp_face_remap23[] = {0, 1}; 7765 const DWORD exp_vertex_remap23[] = {0, 1, 2, 4, 5, -1}; 7766 const DWORD exp_new_num_vertices23 = ARRAY_SIZE(exp_vertices23); 7767 /* Test 24. Weld texture coordinates as FLOAT16_4. Similar to test 24. */ 7768 const struct vertex_texcoord_float16_4 vertices24[] = 7769 { 7770 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}}, 7771 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a, 0x3800, 0x399a}}, 7772 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd, 0xb266, 0xb4cd}}, 7773 7774 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd, 0x3266, 0x34cd}}, 7775 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}}, 7776 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266, 0x2e66, 0x3266}}, 7777 }; 7778 const DWORD indices24[] = {0, 1, 2, 3, 4, 5}; 7779 const DWORD attributes24[] = {0, 0}; 7780 const UINT num_vertices24 = ARRAY_SIZE(vertices24); 7781 const UINT num_faces24 = ARRAY_SIZE(indices24) / VERTS_PER_FACE; 7782 DWORD flags24 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7783 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}; 7784 const DWORD adjacency24[] = {-1, 1, -1, -1, -1, 0}; 7785 const struct vertex_texcoord_float16_4 exp_vertices24[] = 7786 { 7787 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}}, 7788 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a, 0x3800, 0x399a}}, 7789 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd, 0xb266, 0xb4cd}}, 7790 7791 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}}, 7792 {{ 0.0f, 0.0f, 0.f}, {0x2e66, 0x3266, 0x2e66, 0x3266}}, 7793 }; 7794 const DWORD exp_indices24[] = {0, 1, 2, 1, 3, 4}; 7795 const DWORD exp_face_remap24[] = {0, 1}; 7796 const DWORD exp_vertex_remap24[] = {0, 1, 2, 4, 5, -1}; 7797 const DWORD exp_new_num_vertices24 = ARRAY_SIZE(exp_vertices24); 7798 /* Test 25. Weld texture coordinates with usage index 10 (TEXCOORD10). The 7799 * usage index is capped at 7, so the epsilon for TEXCOORD7 is used instead. 7800 */ 7801 const struct vertex_texcoord vertices25[] = 7802 { 7803 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f}}, 7804 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.7f}}, 7805 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}}, 7806 7807 {{ 3.0f, 3.0f, 0.f}, {0.2f, 0.3f}}, 7808 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f}}, 7809 {{ 1.0f, 0.0f, 0.f}, {0.1f, 0.2f}} 7810 }; 7811 const DWORD indices25[] = {0, 1, 2, 3, 4, 5}; 7812 const DWORD attributes25[] = {0, 0}; 7813 const UINT num_vertices25 = ARRAY_SIZE(vertices25); 7814 const UINT num_faces25 = ARRAY_SIZE(indices25) / VERTS_PER_FACE; 7815 DWORD flags25 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7816 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}; 7817 const DWORD adjacency25[] = {-1, 1, -1, -1, -1, 0}; 7818 const struct vertex_texcoord exp_vertices25[] = 7819 { 7820 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f}}, 7821 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.7f}}, 7822 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}}, 7823 7824 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f}}, 7825 {{ 0.0f, 0.0f, 0.f}, {0.1f, 0.2f}}, 7826 }; 7827 const DWORD exp_indices25[] = {0, 1, 2, 1, 3, 4}; 7828 const DWORD exp_face_remap25[] = {0, 1}; 7829 const DWORD exp_vertex_remap25[] = {0, 1, 2, 4, 5, -1}; 7830 const DWORD exp_new_num_vertices25 = ARRAY_SIZE(exp_vertices25); 7831 /* Test 26. Weld color with usage index larger than 1. Shows that none of 7832 * the epsilon values are used. */ 7833 const struct vertex_color vertices26[] = 7834 { 7835 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF}, 7836 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF}, 7837 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF}, 7838 7839 {{ 3.0f, 3.0f, 0.f}, 0x00000000}, 7840 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF}, 7841 {{ 1.0f, 0.0f, 0.f}, 0x01010101}, 7842 }; 7843 const DWORD indices26[] = {0, 1, 2, 3, 4, 5}; 7844 const DWORD attributes26[] = {0, 0}; 7845 const UINT num_vertices26 = ARRAY_SIZE(vertices26); 7846 const UINT num_faces26 = ARRAY_SIZE(indices26) / VERTS_PER_FACE; 7847 DWORD flags26 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7848 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}; 7849 const DWORD adjacency26[] = {-1, 1, -1, -1, -1, 0}; 7850 const struct vertex_color exp_vertices26[] = 7851 { 7852 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF}, 7853 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF}, 7854 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF}, 7855 7856 {{ 2.0f, 3.0f, 0.f}, 0x00000000}, 7857 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF}, 7858 {{ 0.0f, 0.0f, 0.f}, 0x01010101}, 7859 }; 7860 const DWORD exp_indices26[] = {0, 1, 2, 3, 4, 5}; 7861 const DWORD exp_face_remap26[] = {0, 1}; 7862 const DWORD exp_vertex_remap26[] = {0, 1, 2, 3, 4, 5}; 7863 const DWORD exp_new_num_vertices26 = ARRAY_SIZE(exp_vertices26); 7864 /* Test 27. Weld color with usage index 1 (specular). */ 7865 /* Previously this test used float color values and index > 1 but that case 7866 * appears to be effectively unhandled in native so the test gave 7867 * inconsistent results. */ 7868 const struct vertex_color vertices27[] = 7869 { 7870 {{ 0.0f, 3.0f, 0.0f}, 0x00000000}, 7871 {{ 2.0f, 3.0f, 0.0f}, 0x10203040}, 7872 {{ 0.0f, 0.0f, 0.0f}, 0x50607080}, 7873 7874 {{ 3.0f, 3.0f, 0.0f}, 0x11213141}, 7875 {{ 3.0f, 0.0f, 0.0f}, 0xffffffff}, 7876 {{ 1.0f, 0.0f, 0.0f}, 0x51617181}, 7877 }; 7878 const DWORD indices27[] = {0, 1, 2, 3, 4, 5}; 7879 const DWORD attributes27[] = {0, 0}; 7880 const UINT num_vertices27 = ARRAY_SIZE(vertices27); 7881 const UINT num_faces27 = ARRAY_SIZE(indices27) / VERTS_PER_FACE; 7882 DWORD flags27 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7883 const D3DXWELDEPSILONS epsilons27 = 7884 { 7885 1.1f, 0.0f, 0.0f, 0.0f, 2.0f / 255.0f, 0.0f, 7886 {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, 0.0f, 0.0f, 0.0f 7887 }; 7888 const DWORD adjacency27[] = {-1, 1, -1, -1, -1, 0}; 7889 const struct vertex_color exp_vertices27[] = 7890 { 7891 {{ 0.0f, 3.0f, 0.0f}, 0x00000000}, 7892 {{ 2.0f, 3.0f, 0.0f}, 0x10203040}, 7893 {{ 0.0f, 0.0f, 0.0f}, 0x50607080}, 7894 7895 {{ 3.0f, 0.0f, 0.0f}, 0xffffffff}, 7896 }; 7897 const DWORD exp_indices27[] = {0, 1, 2, 1, 3, 2}; 7898 const DWORD exp_face_remap27[] = {0, 1}; 7899 const DWORD exp_vertex_remap27[] = {0, 1, 2, 4, -1, -1}; 7900 const DWORD exp_new_num_vertices27 = ARRAY_SIZE(exp_vertices27); 7901 /* Test 28. Weld one normal with UDEC3. */ 7902 const DWORD dword_udec3_zero = init_udec3_dword(0, 0, 0, 1); 7903 const DWORD dword_udec3_1023 = init_udec3_dword(1023, 1023, 1023, 1); 7904 const DWORD dword_udec3_1022 = init_udec3_dword(1022, 1022, 1022, 1); 7905 const struct vertex_normal_udec3 vertices28[] = 7906 { 7907 {{ 0.0f, 3.0f, 0.f}, dword_udec3_zero}, 7908 {{ 2.0f, 3.0f, 0.f}, dword_udec3_zero}, 7909 {{ 0.0f, 0.0f, 0.f}, dword_udec3_zero}, 7910 7911 {{ 3.0f, 3.0f, 0.f}, dword_udec3_1023}, 7912 {{ 3.0f, 0.0f, 0.f}, dword_udec3_zero}, 7913 {{ 1.0f, 0.0f, 0.f}, dword_udec3_1022}, 7914 }; 7915 const DWORD indices28[] = {0, 1, 2, 3, 4, 5}; 7916 const DWORD attributes28[] = {0, 0}; 7917 const UINT num_vertices28 = ARRAY_SIZE(vertices28); 7918 const UINT num_faces28 = ARRAY_SIZE(indices28) / VERTS_PER_FACE; 7919 DWORD flags28 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7920 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}; 7921 const DWORD adjacency28[] = {-1, 1, -1, -1, -1, 0}; 7922 const struct vertex_normal_udec3 exp_vertices28[] = 7923 { 7924 {{ 0.0f, 3.0f, 0.f}, dword_udec3_zero}, 7925 {{ 2.0f, 3.0f, 0.f}, dword_udec3_zero}, 7926 {{ 0.0f, 0.0f, 0.f}, dword_udec3_zero}, 7927 7928 {{ 2.0f, 3.0f, 0.f}, dword_udec3_1023}, 7929 {{ 3.0f, 0.0f, 0.f}, dword_udec3_zero}, 7930 }; 7931 const DWORD exp_indices28[] = {0, 1, 2, 3, 4, 2}; 7932 const DWORD exp_face_remap28[] = {0, 1}; 7933 const DWORD exp_vertex_remap28[] = {0, 1, 2, 3, 4, -1}; 7934 const DWORD exp_new_num_vertices28 = ARRAY_SIZE(exp_vertices28); 7935 /* Test 29. Weld one normal with DEC3N. */ 7936 const DWORD dword_dec3n_zero = init_dec3n_dword(0, 0, 0, 1); 7937 const DWORD dword_dec3n_511 = init_dec3n_dword(511, 511, 511, 1); 7938 const DWORD dword_dec3n_510 = init_dec3n_dword(510, 510, 510, 1); 7939 const struct vertex_normal_dec3n vertices29[] = 7940 { 7941 {{ 0.0f, 3.0f, 0.f}, dword_dec3n_zero}, 7942 {{ 2.0f, 3.0f, 0.f}, dword_dec3n_zero}, 7943 {{ 0.0f, 0.0f, 0.f}, dword_dec3n_zero}, 7944 7945 {{ 3.0f, 3.0f, 0.f}, dword_dec3n_511}, 7946 {{ 3.0f, 0.0f, 0.f}, dword_dec3n_zero}, 7947 {{ 1.0f, 0.0f, 0.f}, dword_dec3n_510}, 7948 }; 7949 const DWORD indices29[] = {0, 1, 2, 3, 4, 5}; 7950 const DWORD attributes29[] = {0, 0}; 7951 const UINT num_vertices29 = ARRAY_SIZE(vertices29); 7952 const UINT num_faces29 = ARRAY_SIZE(indices29) / VERTS_PER_FACE; 7953 DWORD flags29 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7954 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}; 7955 const DWORD adjacency29[] = {-1, 1, -1, -1, -1, 0}; 7956 const struct vertex_normal_dec3n exp_vertices29[] = 7957 { 7958 {{ 0.0f, 3.0f, 0.f}, dword_dec3n_zero}, 7959 {{ 2.0f, 3.0f, 0.f}, dword_dec3n_zero}, 7960 {{ 0.0f, 0.0f, 0.f}, dword_dec3n_zero}, 7961 7962 {{ 2.0f, 3.0f, 0.f}, dword_dec3n_511}, 7963 {{ 3.0f, 0.0f, 0.f}, dword_dec3n_zero}, 7964 }; 7965 const DWORD exp_indices29[] = {0, 1, 2, 3, 4, 2}; 7966 const DWORD exp_face_remap29[] = {0, 1}; 7967 const DWORD exp_vertex_remap29[] = {0, 1, 2, 3, 4, -1}; 7968 const DWORD exp_new_num_vertices29 = ARRAY_SIZE(exp_vertices29); 7969 /* All mesh data */ 7970 DWORD *adjacency_out = NULL; 7971 DWORD *face_remap = NULL; 7972 ID3DXMesh *mesh = NULL; 7973 ID3DXBuffer *vertex_remap = NULL; 7974 struct 7975 { 7976 const BYTE *vertices; 7977 const DWORD *indices; 7978 const DWORD *attributes; 7979 const DWORD num_vertices; 7980 const DWORD num_faces; 7981 const DWORD options; 7982 D3DVERTEXELEMENT9 *declaration; 7983 const UINT vertex_size; 7984 const DWORD flags; 7985 const D3DXWELDEPSILONS *epsilons; 7986 const DWORD *adjacency; 7987 const BYTE *exp_vertices; 7988 const DWORD *exp_indices; 7989 const DWORD *exp_face_remap; 7990 const DWORD *exp_vertex_remap; 7991 const DWORD exp_new_num_vertices; 7992 } 7993 tc[] = 7994 { 7995 { 7996 (BYTE*)vertices0, 7997 indices0, 7998 attributes0, 7999 num_vertices0, 8000 num_faces0, 8001 options, 8002 declaration_normal, 8003 vertex_size_normal, 8004 flags0, 8005 NULL, 8006 adjacency0, 8007 (BYTE*)exp_vertices0, 8008 exp_indices0, 8009 exp_face_remap0, 8010 exp_vertex_remap0, 8011 exp_new_num_vertices0 8012 }, 8013 { 8014 (BYTE*)vertices1, 8015 indices1, 8016 attributes1, 8017 num_vertices1, 8018 num_faces1, 8019 options, 8020 declaration_normal, 8021 vertex_size_normal, 8022 flags1, 8023 NULL, 8024 adjacency1, 8025 (BYTE*)exp_vertices1, 8026 exp_indices1, 8027 exp_face_remap1, 8028 exp_vertex_remap1, 8029 exp_new_num_vertices1 8030 }, 8031 { 8032 (BYTE*)vertices2, 8033 indices2, 8034 attributes2, 8035 num_vertices2, 8036 num_faces2, 8037 options, 8038 declaration_normal, 8039 vertex_size_normal, 8040 flags2, 8041 &epsilons2, 8042 adjacency2, 8043 (BYTE*)exp_vertices2, 8044 exp_indices2, 8045 exp_face_remap2, 8046 exp_vertex_remap2, 8047 exp_new_num_vertices2 8048 }, 8049 { 8050 (BYTE*)vertices3, 8051 indices3, 8052 attributes3, 8053 num_vertices3, 8054 num_faces3, 8055 options, 8056 declaration_normal, 8057 vertex_size_normal, 8058 flags3, 8059 &epsilons3, 8060 adjacency3, 8061 (BYTE*)exp_vertices3, 8062 exp_indices3, 8063 exp_face_remap3, 8064 exp_vertex_remap3, 8065 exp_new_num_vertices3 8066 }, 8067 { 8068 (BYTE*)vertices4, 8069 indices4, 8070 attributes4, 8071 num_vertices4, 8072 num_faces4, 8073 options, 8074 declaration_normal, 8075 vertex_size_normal, 8076 flags4, 8077 &epsilons4, 8078 adjacency4, 8079 (BYTE*)exp_vertices4, 8080 exp_indices4, 8081 exp_face_remap4, 8082 exp_vertex_remap4, 8083 exp_new_num_vertices4 8084 }, 8085 /* Unusual ordering. */ 8086 { 8087 (BYTE*)vertices5, 8088 indices5, 8089 attributes5, 8090 num_vertices5, 8091 num_faces5, 8092 options, 8093 declaration_normal, 8094 vertex_size_normal, 8095 flags5, 8096 NULL, 8097 adjacency5, 8098 (BYTE*)exp_vertices5, 8099 exp_indices5, 8100 exp_face_remap5, 8101 exp_vertex_remap5, 8102 exp_new_num_vertices5 8103 }, 8104 { 8105 (BYTE*)vertices6, 8106 indices6, 8107 attributes6, 8108 num_vertices6, 8109 num_faces6, 8110 options, 8111 declaration_normal, 8112 vertex_size_normal, 8113 flags6, 8114 &epsilons6, 8115 adjacency6, 8116 (BYTE*)exp_vertices6, 8117 exp_indices6, 8118 exp_face_remap6, 8119 exp_vertex_remap6, 8120 exp_new_num_vertices6 8121 }, 8122 { 8123 (BYTE*)vertices6, 8124 (DWORD*)indices6_16bit, 8125 attributes6, 8126 num_vertices6, 8127 num_faces6, 8128 options_16bit, 8129 declaration_normal, 8130 vertex_size_normal, 8131 flags6, 8132 &epsilons6, 8133 adjacency6, 8134 (BYTE*)exp_vertices6, 8135 exp_indices6, 8136 exp_face_remap6, 8137 exp_vertex_remap6, 8138 exp_new_num_vertices6 8139 }, 8140 { 8141 (BYTE*)vertices8, 8142 indices8, 8143 attributes8, 8144 num_vertices8, 8145 num_faces8, 8146 options, 8147 declaration_normal, 8148 vertex_size_normal, 8149 flags8, 8150 &epsilons8, 8151 adjacency8, 8152 (BYTE*)exp_vertices8, 8153 exp_indices8, 8154 exp_face_remap8, 8155 exp_vertex_remap8, 8156 exp_new_num_vertices8 8157 }, 8158 { 8159 (BYTE*)vertices9, 8160 indices9, 8161 attributes9, 8162 num_vertices9, 8163 num_faces9, 8164 options, 8165 declaration_normal, 8166 vertex_size_normal, 8167 flags9, 8168 &epsilons9, 8169 adjacency9, 8170 (BYTE*)exp_vertices9, 8171 exp_indices9, 8172 exp_face_remap9, 8173 exp_vertex_remap9, 8174 exp_new_num_vertices9 8175 }, 8176 { 8177 (BYTE*)vertices10, 8178 indices10, 8179 attributes10, 8180 num_vertices10, 8181 num_faces10, 8182 options, 8183 declaration_blendweight, 8184 vertex_size_blendweight, 8185 flags10, 8186 &epsilons10, 8187 adjacency10, 8188 (BYTE*)exp_vertices10, 8189 exp_indices10, 8190 exp_face_remap10, 8191 exp_vertex_remap10, 8192 exp_new_num_vertices10 8193 }, 8194 { 8195 (BYTE*)vertices11, 8196 indices11, 8197 attributes11, 8198 num_vertices11, 8199 num_faces11, 8200 options, 8201 declaration_texcoord, 8202 vertex_size_texcoord, 8203 flags11, 8204 &epsilons11, 8205 adjacency11, 8206 (BYTE*)exp_vertices11, 8207 exp_indices11, 8208 exp_face_remap11, 8209 exp_vertex_remap11, 8210 exp_new_num_vertices11 8211 }, 8212 { 8213 (BYTE*)vertices12, 8214 indices12, 8215 attributes12, 8216 num_vertices12, 8217 num_faces12, 8218 options, 8219 declaration_color, 8220 vertex_size_color, 8221 flags12, 8222 &epsilons12, 8223 adjacency12, 8224 (BYTE*)exp_vertices12, 8225 exp_indices12, 8226 exp_face_remap12, 8227 exp_vertex_remap12, 8228 exp_new_num_vertices12 8229 }, 8230 { 8231 (BYTE*)vertices13, 8232 indices13, 8233 attributes13, 8234 num_vertices13, 8235 num_faces13, 8236 options, 8237 declaration_normal3, 8238 vertex_size_normal, 8239 flags13, 8240 &epsilons13, 8241 adjacency13, 8242 (BYTE*)exp_vertices13, 8243 exp_indices13, 8244 exp_face_remap13, 8245 exp_vertex_remap13, 8246 exp_new_num_vertices13 8247 }, 8248 { 8249 (BYTE*)vertices14, 8250 indices14, 8251 attributes14, 8252 num_vertices14, 8253 num_faces14, 8254 options, 8255 declaration_color, 8256 vertex_size_color, 8257 flags14, 8258 &epsilons14, 8259 adjacency14, 8260 (BYTE*)exp_vertices14, 8261 exp_indices14, 8262 exp_face_remap14, 8263 exp_vertex_remap14, 8264 exp_new_num_vertices14 8265 }, 8266 { 8267 (BYTE*)vertices15, 8268 indices15, 8269 attributes15, 8270 num_vertices15, 8271 num_faces15, 8272 options, 8273 declaration_color_ubyte4n, 8274 vertex_size_color_ubyte4, /* UBYTE4 same size as UBYTE4N */ 8275 flags15, 8276 &epsilons15, 8277 adjacency15, 8278 (BYTE*)exp_vertices15, 8279 exp_indices15, 8280 exp_face_remap15, 8281 exp_vertex_remap15, 8282 exp_new_num_vertices15 8283 }, 8284 { 8285 (BYTE*)vertices16, 8286 indices16, 8287 attributes16, 8288 num_vertices16, 8289 num_faces16, 8290 options, 8291 declaration_color_ubyte4, 8292 vertex_size_color_ubyte4, 8293 flags16, 8294 &epsilons16, 8295 adjacency16, 8296 (BYTE*)exp_vertices16, 8297 exp_indices16, 8298 exp_face_remap16, 8299 exp_vertex_remap16, 8300 exp_new_num_vertices16 8301 }, 8302 { 8303 (BYTE*)vertices17, 8304 indices17, 8305 attributes17, 8306 num_vertices17, 8307 num_faces17, 8308 options, 8309 declaration_texcoord_short2, 8310 vertex_size_texcoord_short2, 8311 flags17, 8312 &epsilons17, 8313 adjacency17, 8314 (BYTE*)exp_vertices17, 8315 exp_indices17, 8316 exp_face_remap17, 8317 exp_vertex_remap17, 8318 exp_new_num_vertices17 8319 }, 8320 { 8321 (BYTE*)vertices18, 8322 indices18, 8323 attributes18, 8324 num_vertices18, 8325 num_faces18, 8326 options, 8327 declaration_texcoord_short2n, 8328 vertex_size_texcoord_short2, /* SHORT2 same size as SHORT2N */ 8329 flags18, 8330 &epsilons18, 8331 adjacency18, 8332 (BYTE*)exp_vertices18, 8333 exp_indices18, 8334 exp_face_remap18, 8335 exp_vertex_remap18, 8336 exp_new_num_vertices18 8337 }, 8338 { 8339 (BYTE*)vertices19, 8340 indices19, 8341 attributes19, 8342 num_vertices19, 8343 num_faces19, 8344 options, 8345 declaration_texcoord_ushort2n, 8346 vertex_size_texcoord_short2, /* SHORT2 same size as USHORT2N */ 8347 flags19, 8348 &epsilons19, 8349 adjacency19, 8350 (BYTE*)exp_vertices19, 8351 exp_indices19, 8352 exp_face_remap19, 8353 exp_vertex_remap19, 8354 exp_new_num_vertices19 8355 }, 8356 { 8357 (BYTE*)vertices20, 8358 indices20, 8359 attributes20, 8360 num_vertices20, 8361 num_faces20, 8362 options, 8363 declaration_normal_short4, 8364 vertex_size_normal_short4, 8365 flags20, 8366 &epsilons20, 8367 adjacency20, 8368 (BYTE*)exp_vertices20, 8369 exp_indices20, 8370 exp_face_remap20, 8371 exp_vertex_remap20, 8372 exp_new_num_vertices20 8373 }, 8374 { 8375 (BYTE*)vertices21, 8376 indices21, 8377 attributes21, 8378 num_vertices21, 8379 num_faces21, 8380 options, 8381 declaration_normal_short4n, 8382 vertex_size_normal_short4, /* SHORT4 same size as SHORT4N */ 8383 flags21, 8384 &epsilons21, 8385 adjacency21, 8386 (BYTE*)exp_vertices21, 8387 exp_indices21, 8388 exp_face_remap21, 8389 exp_vertex_remap21, 8390 exp_new_num_vertices21 8391 }, 8392 { 8393 (BYTE*)vertices22, 8394 indices22, 8395 attributes22, 8396 num_vertices22, 8397 num_faces22, 8398 options, 8399 declaration_normal_ushort4n, 8400 vertex_size_normal_short4, /* SHORT4 same size as USHORT4N */ 8401 flags22, 8402 &epsilons22, 8403 adjacency22, 8404 (BYTE*)exp_vertices22, 8405 exp_indices22, 8406 exp_face_remap22, 8407 exp_vertex_remap22, 8408 exp_new_num_vertices22 8409 }, 8410 { 8411 (BYTE*)vertices23, 8412 indices23, 8413 attributes23, 8414 num_vertices23, 8415 num_faces23, 8416 options, 8417 declaration_texcoord_float16_2, 8418 vertex_size_texcoord_float16_2, 8419 flags23, 8420 &epsilons23, 8421 adjacency23, 8422 (BYTE*)exp_vertices23, 8423 exp_indices23, 8424 exp_face_remap23, 8425 exp_vertex_remap23, 8426 exp_new_num_vertices23 8427 }, 8428 { 8429 (BYTE*)vertices24, 8430 indices24, 8431 attributes24, 8432 num_vertices24, 8433 num_faces24, 8434 options, 8435 declaration_texcoord_float16_4, 8436 vertex_size_texcoord_float16_4, 8437 flags24, 8438 &epsilons24, 8439 adjacency24, 8440 (BYTE*)exp_vertices24, 8441 exp_indices24, 8442 exp_face_remap24, 8443 exp_vertex_remap24, 8444 exp_new_num_vertices24 8445 }, 8446 { 8447 (BYTE*)vertices25, 8448 indices25, 8449 attributes25, 8450 num_vertices25, 8451 num_faces25, 8452 options, 8453 declaration_texcoord10, 8454 vertex_size_texcoord, 8455 flags25, 8456 &epsilons25, 8457 adjacency25, 8458 (BYTE*)exp_vertices25, 8459 exp_indices25, 8460 exp_face_remap25, 8461 exp_vertex_remap25, 8462 exp_new_num_vertices25 8463 }, 8464 { 8465 (BYTE*)vertices26, 8466 indices26, 8467 attributes26, 8468 num_vertices26, 8469 num_faces26, 8470 options, 8471 declaration_color2, 8472 vertex_size_color, 8473 flags26, 8474 &epsilons26, 8475 adjacency26, 8476 (BYTE*)exp_vertices26, 8477 exp_indices26, 8478 exp_face_remap26, 8479 exp_vertex_remap26, 8480 exp_new_num_vertices26 8481 }, 8482 { 8483 (BYTE*)vertices27, 8484 indices27, 8485 attributes27, 8486 num_vertices27, 8487 num_faces27, 8488 options, 8489 declaration_color1, 8490 vertex_size_color, 8491 flags27, 8492 &epsilons27, 8493 adjacency27, 8494 (BYTE*)exp_vertices27, 8495 exp_indices27, 8496 exp_face_remap27, 8497 exp_vertex_remap27, 8498 exp_new_num_vertices27 8499 }, 8500 { 8501 (BYTE*)vertices28, 8502 indices28, 8503 attributes28, 8504 num_vertices28, 8505 num_faces28, 8506 options, 8507 declaration_normal_udec3, 8508 vertex_size_normal_udec3, 8509 flags28, 8510 &epsilons28, 8511 adjacency28, 8512 (BYTE*)exp_vertices28, 8513 exp_indices28, 8514 exp_face_remap28, 8515 exp_vertex_remap28, 8516 exp_new_num_vertices28 8517 }, 8518 { 8519 (BYTE*)vertices29, 8520 indices29, 8521 attributes29, 8522 num_vertices29, 8523 num_faces29, 8524 options, 8525 declaration_normal_dec3n, 8526 vertex_size_normal_dec3n, 8527 flags29, 8528 &epsilons29, 8529 adjacency29, 8530 (BYTE*)exp_vertices29, 8531 exp_indices29, 8532 exp_face_remap29, 8533 exp_vertex_remap29, 8534 exp_new_num_vertices29 8535 } 8536 }; 8537 #ifdef __REACTOS__ 8538 #undef up 8539 #endif 8540 8541 test_context = new_test_context(); 8542 if (!test_context) 8543 { 8544 skip("Couldn't create test context\n"); 8545 goto cleanup; 8546 } 8547 8548 for (i = 0; i < ARRAY_SIZE(tc); i++) 8549 { 8550 DWORD j; 8551 DWORD *vertex_remap_ptr; 8552 DWORD new_num_vertices; 8553 8554 hr = init_test_mesh(tc[i].num_faces, tc[i].num_vertices, tc[i].options, 8555 tc[i].declaration, test_context->device, &mesh, 8556 tc[i].vertices, tc[i].vertex_size, 8557 tc[i].indices, tc[i].attributes); 8558 if (FAILED(hr)) 8559 { 8560 skip("Couldn't initialize test mesh %d.\n", i); 8561 goto cleanup; 8562 } 8563 8564 /* Allocate out parameters */ 8565 adjacency_out = HeapAlloc(GetProcessHeap(), 0, VERTS_PER_FACE * tc[i].num_faces * sizeof(*adjacency_out)); 8566 if (!adjacency_out) 8567 { 8568 skip("Couldn't allocate adjacency_out array.\n"); 8569 goto cleanup; 8570 } 8571 face_remap = HeapAlloc(GetProcessHeap(), 0, tc[i].num_faces * sizeof(*face_remap)); 8572 if (!face_remap) 8573 { 8574 skip("Couldn't allocate face_remap array.\n"); 8575 goto cleanup; 8576 } 8577 8578 hr = D3DXWeldVertices(mesh, tc[i].flags, tc[i].epsilons, tc[i].adjacency, 8579 adjacency_out, face_remap, &vertex_remap); 8580 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 8581 /* Check number of vertices*/ 8582 new_num_vertices = mesh->lpVtbl->GetNumVertices(mesh); 8583 ok(new_num_vertices == tc[i].exp_new_num_vertices, 8584 "Mesh %d: new_num_vertices == %d, expected %d.\n", 8585 i, new_num_vertices, tc[i].exp_new_num_vertices); 8586 /* Check index buffer */ 8587 if (tc[i].options & D3DXMESH_32BIT) 8588 { 8589 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, (void**)&indices); 8590 if (FAILED(hr)) 8591 { 8592 skip("Couldn't lock index buffer.\n"); 8593 goto cleanup; 8594 } 8595 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++) 8596 { 8597 ok(indices[j] == tc[i].exp_indices[j], 8598 "Mesh %d: indices[%d] == %d, expected %d\n", 8599 i, j, indices[j], tc[i].exp_indices[j]); 8600 } 8601 } 8602 else 8603 { 8604 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, (void**)&indices_16bit); 8605 if (FAILED(hr)) 8606 { 8607 skip("Couldn't lock index buffer.\n"); 8608 goto cleanup; 8609 } 8610 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++) 8611 { 8612 ok(indices_16bit[j] == tc[i].exp_indices[j], 8613 "Mesh %d: indices_16bit[%d] == %d, expected %d\n", 8614 i, j, indices_16bit[j], tc[i].exp_indices[j]); 8615 } 8616 } 8617 mesh->lpVtbl->UnlockIndexBuffer(mesh); 8618 indices = NULL; 8619 indices_16bit = NULL; 8620 /* Check adjacency_out */ 8621 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++) 8622 { 8623 ok(adjacency_out[j] == tc[i].adjacency[j], 8624 "Mesh %d: adjacency_out[%d] == %d, expected %d\n", 8625 i, j, adjacency_out[j], tc[i].adjacency[j]); 8626 } 8627 /* Check face_remap */ 8628 for (j = 0; j < tc[i].num_faces; j++) 8629 { 8630 ok(face_remap[j] == tc[i].exp_face_remap[j], 8631 "Mesh %d: face_remap[%d] == %d, expected %d\n", 8632 i, j, face_remap[j], tc[i].exp_face_remap[j]); 8633 } 8634 /* Check vertex_remap */ 8635 vertex_remap_ptr = vertex_remap->lpVtbl->GetBufferPointer(vertex_remap); 8636 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++) 8637 { 8638 ok(vertex_remap_ptr[j] == tc[i].exp_vertex_remap[j], 8639 "Mesh %d: vertex_remap_ptr[%d] == %d, expected %d\n", 8640 i, j, vertex_remap_ptr[j], tc[i].exp_vertex_remap[j]); 8641 } 8642 /* Check vertex buffer */ 8643 hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, (void*)&vertices); 8644 if (FAILED(hr)) 8645 { 8646 skip("Couldn't lock vertex buffer.\n"); 8647 goto cleanup; 8648 } 8649 /* Check contents of re-ordered vertex buffer */ 8650 for (j = 0; j < tc[i].exp_new_num_vertices; j++) 8651 { 8652 int index = tc[i].vertex_size*j; 8653 check_vertex_components(__LINE__, i, j, &vertices[index], &tc[i].exp_vertices[index], tc[i].declaration); 8654 } 8655 mesh->lpVtbl->UnlockVertexBuffer(mesh); 8656 vertices = NULL; 8657 8658 /* Free mesh and output data */ 8659 HeapFree(GetProcessHeap(), 0, adjacency_out); 8660 adjacency_out = NULL; 8661 HeapFree(GetProcessHeap(), 0, face_remap); 8662 face_remap = NULL; 8663 vertex_remap->lpVtbl->Release(vertex_remap); 8664 vertex_remap = NULL; 8665 mesh->lpVtbl->Release(mesh); 8666 mesh = NULL; 8667 } 8668 8669 cleanup: 8670 HeapFree(GetProcessHeap(), 0, adjacency_out); 8671 HeapFree(GetProcessHeap(), 0, face_remap); 8672 if (indices) mesh->lpVtbl->UnlockIndexBuffer(mesh); 8673 if (indices_16bit) mesh->lpVtbl->UnlockIndexBuffer(mesh); 8674 if (mesh) mesh->lpVtbl->Release(mesh); 8675 if (vertex_remap) vertex_remap->lpVtbl->Release(vertex_remap); 8676 if (vertices) mesh->lpVtbl->UnlockVertexBuffer(mesh); 8677 free_test_context(test_context); 8678 } 8679 8680 static void test_clone_mesh(void) 8681 { 8682 HRESULT hr; 8683 struct test_context *test_context = NULL; 8684 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM; 8685 D3DVERTEXELEMENT9 declaration_pn[] = 8686 { 8687 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8688 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 8689 D3DDECL_END() 8690 }; 8691 D3DVERTEXELEMENT9 declaration_pntc[] = 8692 { 8693 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8694 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 8695 {0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 8696 D3DDECL_END() 8697 }; 8698 D3DVERTEXELEMENT9 declaration_ptcn[] = 8699 { 8700 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8701 {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 8702 {0, 20, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 8703 D3DDECL_END() 8704 }; 8705 D3DVERTEXELEMENT9 declaration_ptc[] = 8706 { 8707 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8708 {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 8709 D3DDECL_END() 8710 }; 8711 D3DVERTEXELEMENT9 declaration_ptc_float16_2[] = 8712 { 8713 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8714 {0, 12, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 8715 D3DDECL_END() 8716 }; 8717 D3DVERTEXELEMENT9 declaration_ptc_float16_4[] = 8718 { 8719 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8720 {0, 12, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 8721 D3DDECL_END() 8722 }; 8723 D3DVERTEXELEMENT9 declaration_ptc_float1[] = 8724 { 8725 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8726 {0, 12, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 8727 D3DDECL_END() 8728 }; 8729 D3DVERTEXELEMENT9 declaration_ptc_float3[] = 8730 { 8731 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8732 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 8733 D3DDECL_END() 8734 }; 8735 D3DVERTEXELEMENT9 declaration_ptc_float4[] = 8736 { 8737 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8738 {0, 12, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 8739 D3DDECL_END() 8740 }; 8741 D3DVERTEXELEMENT9 declaration_ptc_d3dcolor[] = 8742 { 8743 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8744 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 8745 D3DDECL_END() 8746 }; 8747 D3DVERTEXELEMENT9 declaration_ptc_ubyte4[] = 8748 { 8749 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8750 {0, 12, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 8751 D3DDECL_END() 8752 }; 8753 D3DVERTEXELEMENT9 declaration_ptc_ubyte4n[] = 8754 { 8755 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8756 {0, 12, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 8757 D3DDECL_END() 8758 }; 8759 D3DVERTEXELEMENT9 declaration_ptc_short2[] = 8760 { 8761 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8762 {0, 12, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 8763 D3DDECL_END() 8764 }; 8765 D3DVERTEXELEMENT9 declaration_ptc_short4[] = 8766 { 8767 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8768 {0, 12, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 8769 D3DDECL_END() 8770 }; 8771 D3DVERTEXELEMENT9 declaration_ptc_short2n[] = 8772 { 8773 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8774 {0, 12, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 8775 D3DDECL_END() 8776 }; 8777 D3DVERTEXELEMENT9 declaration_ptc_short4n[] = 8778 { 8779 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8780 {0, 12, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 8781 D3DDECL_END() 8782 }; 8783 D3DVERTEXELEMENT9 declaration_ptc_ushort2n[] = 8784 { 8785 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8786 {0, 12, D3DDECLTYPE_USHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 8787 D3DDECL_END() 8788 }; 8789 D3DVERTEXELEMENT9 declaration_ptc_ushort4n[] = 8790 { 8791 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8792 {0, 12, D3DDECLTYPE_USHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 8793 D3DDECL_END() 8794 }; 8795 D3DVERTEXELEMENT9 declaration_ptc_float16_2_partialu[] = 8796 { 8797 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8798 {0, 12, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_PARTIALU, D3DDECLUSAGE_TEXCOORD, 0}, 8799 D3DDECL_END() 8800 }; 8801 D3DVERTEXELEMENT9 declaration_pntc1[] = 8802 { 8803 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8804 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 8805 {0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1}, 8806 D3DDECL_END() 8807 }; 8808 const unsigned int VERTS_PER_FACE = 3; 8809 BYTE *vertices = NULL; 8810 INT i; 8811 struct vertex_pn 8812 { 8813 D3DXVECTOR3 position; 8814 D3DXVECTOR3 normal; 8815 }; 8816 struct vertex_pntc 8817 { 8818 D3DXVECTOR3 position; 8819 D3DXVECTOR3 normal; 8820 D3DXVECTOR2 texcoords; 8821 }; 8822 struct vertex_ptcn 8823 { 8824 D3DXVECTOR3 position; 8825 D3DXVECTOR2 texcoords; 8826 D3DXVECTOR3 normal; 8827 }; 8828 struct vertex_ptc 8829 { 8830 D3DXVECTOR3 position; 8831 D3DXVECTOR2 texcoords; 8832 }; 8833 struct vertex_ptc_float16_2 8834 { 8835 D3DXVECTOR3 position; 8836 WORD texcoords[2]; /* float16_2 */ 8837 }; 8838 struct vertex_ptc_float16_4 8839 { 8840 D3DXVECTOR3 position; 8841 WORD texcoords[4]; /* float16_4 */ 8842 }; 8843 struct vertex_ptc_float1 8844 { 8845 D3DXVECTOR3 position; 8846 FLOAT texcoords; 8847 }; 8848 struct vertex_ptc_float3 8849 { 8850 D3DXVECTOR3 position; 8851 FLOAT texcoords[3]; 8852 }; 8853 struct vertex_ptc_float4 8854 { 8855 D3DXVECTOR3 position; 8856 FLOAT texcoords[4]; 8857 }; 8858 struct vertex_ptc_d3dcolor 8859 { 8860 D3DXVECTOR3 position; 8861 BYTE texcoords[4]; 8862 }; 8863 struct vertex_ptc_ubyte4 8864 { 8865 D3DXVECTOR3 position; 8866 BYTE texcoords[4]; 8867 }; 8868 struct vertex_ptc_ubyte4n 8869 { 8870 D3DXVECTOR3 position; 8871 BYTE texcoords[4]; 8872 }; 8873 struct vertex_ptc_short2 8874 { 8875 D3DXVECTOR3 position; 8876 SHORT texcoords[2]; 8877 }; 8878 struct vertex_ptc_short4 8879 { 8880 D3DXVECTOR3 position; 8881 SHORT texcoords[4]; 8882 }; 8883 struct vertex_ptc_ushort2n 8884 { 8885 D3DXVECTOR3 position; 8886 USHORT texcoords[2]; 8887 }; 8888 struct vertex_ptc_ushort4n 8889 { 8890 D3DXVECTOR3 position; 8891 USHORT texcoords[4]; 8892 }; 8893 struct vertex_ptc_udec3 8894 { 8895 D3DXVECTOR3 position; 8896 DWORD texcoords; 8897 }; 8898 struct vertex_ptc_dec3n 8899 { 8900 D3DXVECTOR3 position; 8901 DWORD texcoords; 8902 }; 8903 #ifndef __REACTOS__ 8904 D3DXVECTOR3 up = {0.0f, 0.0f, 1.0f}; 8905 D3DXVECTOR2 zero_vec2 = {0.0f, 0.0f}; 8906 #else 8907 #define up {0.0f, 0.0f, 1.0f} 8908 #define zero_vec2 {0.0f, 0.0f} 8909 #endif 8910 /* Test 0. Check that a mesh can be cloned if the new declaration is the 8911 * same as the one used to create the mesh. 8912 * 8913 * 0--1 3 8914 * | / /| 8915 * |/ / | 8916 * 2 5--4 8917 */ 8918 const struct vertex_pn vertices0[] = 8919 { 8920 {{ 0.0f, 3.0f, 0.f}, up}, 8921 {{ 2.0f, 3.0f, 0.f}, up}, 8922 {{ 0.0f, 0.0f, 0.f}, up}, 8923 8924 {{ 3.0f, 3.0f, 0.f}, up}, 8925 {{ 3.0f, 0.0f, 0.f}, up}, 8926 {{ 1.0f, 0.0f, 0.f}, up}, 8927 }; 8928 const UINT num_vertices0 = ARRAY_SIZE(vertices0); 8929 const UINT num_faces0 = ARRAY_SIZE(vertices0) / VERTS_PER_FACE; 8930 const UINT vertex_size0 = sizeof(*vertices0); 8931 /* Test 1. Check that 16-bit indices are handled. */ 8932 const DWORD options_16bit = D3DXMESH_SYSTEMMEM; 8933 /* Test 2. Check that the size of each vertex is increased and the data 8934 * moved if the new declaration adds an element after the original elements. 8935 */ 8936 const struct vertex_pntc exp_vertices2[] = 8937 { 8938 {{ 0.0f, 3.0f, 0.f}, up, zero_vec2}, 8939 {{ 2.0f, 3.0f, 0.f}, up, zero_vec2}, 8940 {{ 0.0f, 0.0f, 0.f}, up, zero_vec2}, 8941 8942 {{ 3.0f, 3.0f, 0.f}, up, zero_vec2}, 8943 {{ 3.0f, 0.0f, 0.f}, up, zero_vec2}, 8944 {{ 1.0f, 0.0f, 0.f}, up, zero_vec2}, 8945 }; 8946 const UINT exp_vertex_size2 = sizeof(*exp_vertices2); 8947 /* Test 3. Check that the size of each vertex is increased and the data 8948 * moved if the new declaration adds an element between the original 8949 * elements. 8950 */ 8951 const struct vertex_ptcn exp_vertices3[] = 8952 { 8953 {{ 0.0f, 3.0f, 0.f}, zero_vec2, up}, 8954 {{ 2.0f, 3.0f, 0.f}, zero_vec2, up}, 8955 {{ 0.0f, 0.0f, 0.f}, zero_vec2, up}, 8956 8957 {{ 3.0f, 3.0f, 0.f}, zero_vec2, up}, 8958 {{ 3.0f, 0.0f, 0.f}, zero_vec2, up}, 8959 {{ 1.0f, 0.0f, 0.f}, zero_vec2, up}, 8960 }; 8961 const UINT exp_vertex_size3 = sizeof(*exp_vertices3); 8962 /* Test 4. Test that data types can be converted, e.g. FLOAT2 to FLOAT16_2. */ 8963 const struct vertex_ptc vertices4[] = 8964 { 8965 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}}, 8966 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}}, 8967 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}}, 8968 8969 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}}, 8970 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}}, 8971 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}}, 8972 }; 8973 const UINT num_vertices4 = ARRAY_SIZE(vertices4); 8974 const UINT num_faces4 = ARRAY_SIZE(vertices4) / VERTS_PER_FACE; 8975 const UINT vertex_size4 = sizeof(*vertices4); 8976 const struct vertex_ptc_float16_2 exp_vertices4[] = 8977 { 8978 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */ 8979 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */ 8980 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */ 8981 8982 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd}}, /* {0.2f, 0.3f} */ 8983 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */ 8984 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */ 8985 }; 8986 const UINT exp_vertex_size4 = sizeof(*exp_vertices4); 8987 /* Test 5. Convert FLOAT2 to FLOAT16_4. */ 8988 const struct vertex_ptc vertices5[] = 8989 { 8990 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}}, 8991 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}}, 8992 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}}, 8993 8994 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}}, 8995 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}}, 8996 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}}, 8997 }; 8998 const UINT num_vertices5 = ARRAY_SIZE(vertices5); 8999 const UINT num_faces5 = ARRAY_SIZE(vertices5) / VERTS_PER_FACE; 9000 const UINT vertex_size5 = sizeof(*vertices5); 9001 const struct vertex_ptc_float16_4 exp_vertices5[] = 9002 { 9003 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00, 0, 0x3c00}}, /* {1.0f, 1.0f, 0.0f, 1.0f} */ 9004 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a, 0, 0x3c00}}, /* {0.5f, 0.7f, 0.0f, 1.0f} */ 9005 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd, 0, 0x3c00}}, /* {-0.2f, -0.3f, 0.0f, 1.0f} */ 9006 9007 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd, 0, 0x3c00}}, /* {0.2f, 0.3f, 0.0f, 1.0f} */ 9008 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00, 0, 0x3c00}}, /* {1.0f, 1.0f, 0.0f, 1.0f} */ 9009 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266, 0, 0x3c00}}, /* {0.1f, 0.2f, 0.0f, 1.0f} */ 9010 }; 9011 const UINT exp_vertex_size5 = sizeof(*exp_vertices5); 9012 /* Test 6. Convert FLOAT2 to FLOAT1. */ 9013 const struct vertex_ptc vertices6[] = 9014 { 9015 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}}, 9016 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}}, 9017 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}}, 9018 9019 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}}, 9020 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}}, 9021 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}}, 9022 }; 9023 const UINT num_vertices6 = ARRAY_SIZE(vertices6); 9024 const UINT num_faces6 = ARRAY_SIZE(vertices6) / VERTS_PER_FACE; 9025 const UINT vertex_size6 = sizeof(*vertices6); 9026 const struct vertex_ptc_float1 exp_vertices6[] = 9027 { 9028 {{ 0.0f, 3.0f, 0.f}, 1.0f}, 9029 {{ 2.0f, 3.0f, 0.f}, 0.5f}, 9030 {{ 0.0f, 0.0f, 0.f}, -0.2f}, 9031 9032 {{ 3.0f, 3.0f, 0.f}, 0.2f}, 9033 {{ 3.0f, 0.0f, 0.f}, 1.0f}, 9034 {{ 1.0f, 0.0f, 0.f}, 0.1f}, 9035 }; 9036 const UINT exp_vertex_size6 = sizeof(*exp_vertices6); 9037 /* Test 7. Convert FLOAT2 to FLOAT3. */ 9038 const struct vertex_ptc vertices7[] = 9039 { 9040 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}}, 9041 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}}, 9042 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}}, 9043 9044 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}}, 9045 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}}, 9046 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}}, 9047 }; 9048 const UINT num_vertices7 = ARRAY_SIZE(vertices7); 9049 const UINT num_faces7 = ARRAY_SIZE(vertices7) / VERTS_PER_FACE; 9050 const UINT vertex_size7 = sizeof(*vertices7); 9051 const struct vertex_ptc_float3 exp_vertices7[] = 9052 { 9053 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f, 0.0f}}, 9054 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f, 0.0f}}, 9055 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f, 0.0f}}, 9056 9057 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f, 0.0f}}, 9058 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f, 0.0f}}, 9059 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f, 0.0f}}, 9060 }; 9061 const UINT exp_vertex_size7 = sizeof(*exp_vertices7); 9062 /* Test 8. Convert FLOAT2 to FLOAT4. */ 9063 const struct vertex_ptc vertices8[] = 9064 { 9065 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}}, 9066 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}}, 9067 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}}, 9068 9069 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}}, 9070 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}}, 9071 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}}, 9072 }; 9073 const UINT num_vertices8 = ARRAY_SIZE(vertices8); 9074 const UINT num_faces8 = ARRAY_SIZE(vertices8) / VERTS_PER_FACE; 9075 const UINT vertex_size8 = sizeof(*vertices8); 9076 const struct vertex_ptc_float4 exp_vertices8[] = 9077 { 9078 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f, 0.0f, 1.0f}}, 9079 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f, 0.0f, 1.0f}}, 9080 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f, 0.0f, 1.0f}}, 9081 9082 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f, 0.0f, 1.0f}}, 9083 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f, 0.0f, 1.0f}}, 9084 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f, 0.0f, 1.0f}}, 9085 }; 9086 const UINT exp_vertex_size8 = sizeof(*exp_vertices8); 9087 /* Test 9. Convert FLOAT2 to D3DCOLOR. */ 9088 const struct vertex_ptc vertices9[] = 9089 { 9090 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}}, 9091 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}}, 9092 {{ 0.0f, 0.0f, 0.f}, {-0.4f, -0.6f}}, 9093 9094 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}}, 9095 {{ 3.0f, 0.0f, 0.f}, { 2.0f, 256.0f}}, 9096 {{ 1.0f, 0.0f, 0.f}, { 0.11f, 0.2f}}, 9097 }; 9098 const UINT num_vertices9 = ARRAY_SIZE(vertices9); 9099 const UINT num_faces9 = ARRAY_SIZE(vertices9) / VERTS_PER_FACE; 9100 const UINT vertex_size9 = sizeof(*vertices9); 9101 const struct vertex_ptc_d3dcolor exp_vertices9[] = 9102 { 9103 {{ 0.0f, 3.0f, 0.f}, {0, 255, 255, 255}}, 9104 {{ 2.0f, 3.0f, 0.f}, {0, 179, 128, 255}}, 9105 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 255}}, 9106 9107 {{ 3.0f, 3.0f, 0.f}, {0, 77, 51, 255}}, 9108 {{ 3.0f, 0.0f, 0.f}, {0, 255, 255, 255}}, 9109 {{ 1.0f, 0.0f, 0.f}, {0, 51, 28, 255}}, 9110 }; 9111 const UINT exp_vertex_size9 = sizeof(*exp_vertices9); 9112 /* Test 10. Convert FLOAT2 to UBYTE4. */ 9113 const struct vertex_ptc vertices10[] = 9114 { 9115 {{ 0.0f, 3.0f, 0.f}, { 0.0f, 1.0f}}, 9116 {{ 2.0f, 3.0f, 0.f}, { 2.0f, 3.0f}}, 9117 {{ 0.0f, 0.0f, 0.f}, { 254.0f, 255.0f}}, 9118 9119 {{ 3.0f, 3.0f, 0.f}, { 256.0f, 257.0f}}, 9120 {{ 3.0f, 0.0f, 0.f}, { 1.4f, 1.5f}}, 9121 {{ 1.0f, 0.0f, 0.f}, {-4.0f, -5.0f}}, 9122 }; 9123 const UINT num_vertices10 = ARRAY_SIZE(vertices10); 9124 const UINT num_faces10 = ARRAY_SIZE(vertices10) / VERTS_PER_FACE; 9125 const UINT vertex_size10 = sizeof(*vertices10); 9126 const struct vertex_ptc_ubyte4 exp_vertices10[] = 9127 { 9128 {{ 0.0f, 3.0f, 0.f}, {0, 1, 0, 1}}, 9129 {{ 2.0f, 3.0f, 0.f}, {2, 3, 0, 1}}, 9130 {{ 0.0f, 0.0f, 0.f}, {254, 255, 0, 1}}, 9131 9132 {{ 3.0f, 3.0f, 0.f}, {0, 1, 0, 1}}, 9133 {{ 3.0f, 0.0f, 0.f}, {1, 2, 0, 1}}, 9134 {{ 1.0f, 0.0f, 0.f}, {0, 0, 0, 1}}, 9135 }; 9136 const UINT exp_vertex_size10 = sizeof(*exp_vertices10); 9137 /* Test 11. Convert FLOAT2 to SHORT2. */ 9138 const struct vertex_ptc vertices11[] = 9139 { 9140 {{ 0.0f, 3.0f, 0.f}, { 1.0f, -1.0f}}, 9141 {{ 2.0f, 3.0f, 0.f}, { 0.4f, 0.5f}}, 9142 {{ 0.0f, 0.0f, 0.f}, {-0.5f, -5.0f}}, 9143 9144 {{ 3.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MIN}}, 9145 {{ 3.0f, 0.0f, 0.f}, {SHRT_MAX + 1.0f, SHRT_MIN - 1.0f}}, 9146 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX + 2.0f, SHRT_MIN - 2.0f}}, 9147 9148 {{ 4.0f, 3.0f, 0.f}, {2 * SHRT_MAX, 2 * SHRT_MIN}}, 9149 {{ 6.0f, 0.0f, 0.f}, {3 * SHRT_MAX, 3 * SHRT_MIN}}, 9150 {{ 4.0f, 0.0f, 0.f}, {4 * SHRT_MAX, 4 * SHRT_MIN}}, 9151 }; 9152 const UINT num_vertices11 = ARRAY_SIZE(vertices11); 9153 const UINT num_faces11 = ARRAY_SIZE(vertices11) / VERTS_PER_FACE; 9154 const UINT vertex_size11 = sizeof(*vertices11); 9155 const struct vertex_ptc_short2 exp_vertices11[] = 9156 { 9157 {{ 0.0f, 3.0f, 0.f}, {1, 0}}, 9158 {{ 2.0f, 3.0f, 0.f}, {0, 1}}, 9159 {{ 0.0f, 0.0f, 0.f}, {0, -4}}, 9160 9161 {{ 3.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MIN + 1}}, 9162 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MIN}}, 9163 {{ 1.0f, 0.0f, 0.f}, {SHRT_MIN + 1, SHRT_MAX}}, 9164 9165 {{ 4.0f, 3.0f, 0.f}, {-2, 1}}, 9166 {{ 6.0f, 0.0f, 0.f}, {32765, -32767}}, 9167 {{ 4.0f, 0.0f, 0.f}, {-4, 1}}, 9168 }; 9169 const UINT exp_vertex_size11 = sizeof(*exp_vertices11); 9170 /* Test 12. Convert FLOAT2 to SHORT4. */ 9171 const struct vertex_ptc vertices12[] = 9172 { 9173 {{ 0.0f, 3.0f, 0.f}, { 1.0f, -1.0f}}, 9174 {{ 2.0f, 3.0f, 0.f}, { 0.4f, 0.5f}}, 9175 {{ 0.0f, 0.0f, 0.f}, {-0.5f, -5.0f}}, 9176 9177 {{ 3.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MIN}}, 9178 {{ 3.0f, 0.0f, 0.f}, {SHRT_MAX + 1.0f, SHRT_MIN - 1.0f}}, 9179 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX + 2.0f, SHRT_MIN - 2.0f}}, 9180 9181 {{ 4.0f, 3.0f, 0.f}, {2 * SHRT_MAX, 2 * SHRT_MIN}}, 9182 {{ 6.0f, 0.0f, 0.f}, {3 * SHRT_MAX, 3 * SHRT_MIN}}, 9183 {{ 4.0f, 0.0f, 0.f}, {4 * SHRT_MAX, 4 * SHRT_MIN}}, 9184 }; 9185 const UINT num_vertices12 = ARRAY_SIZE(vertices12); 9186 const UINT num_faces12 = ARRAY_SIZE(vertices12) / VERTS_PER_FACE; 9187 const UINT vertex_size12 = sizeof(*vertices12); 9188 const struct vertex_ptc_short4 exp_vertices12[] = 9189 { 9190 {{ 0.0f, 3.0f, 0.f}, {1, 0, 0, 1}}, 9191 {{ 2.0f, 3.0f, 0.f}, {0, 1, 0, 1}}, 9192 {{ 0.0f, 0.0f, 0.f}, {0, -4, 0, 1}}, 9193 9194 {{ 3.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MIN + 1, 0, 1}}, 9195 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MIN, 0, 1}}, 9196 {{ 1.0f, 0.0f, 0.f}, {SHRT_MIN + 1, SHRT_MAX, 0, 1}}, 9197 9198 {{ 4.0f, 3.0f, 0.f}, {-2, 1, 0, 1}}, 9199 {{ 6.0f, 0.0f, 0.f}, {32765, -32767, 0, 1}}, 9200 {{ 4.0f, 0.0f, 0.f}, {-4, 1, 0, 1}}, 9201 }; 9202 const UINT exp_vertex_size12 = sizeof(*exp_vertices12); 9203 /* Test 13. Convert FLOAT2 to UBYTE4N. */ 9204 const struct vertex_ptc vertices13[] = 9205 { 9206 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 2.0f}}, 9207 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}}, 9208 {{ 0.0f, 0.0f, 0.f}, {-0.4f, -0.5f}}, 9209 9210 {{ 3.0f, 3.0f, 0.f}, {-0.6f, -1.0f}}, 9211 {{ 3.0f, 0.0f, 0.f}, {UCHAR_MAX, UCHAR_MAX + 1}}, 9212 {{ 1.0f, 0.0f, 0.f}, {2 * UCHAR_MAX, -UCHAR_MAX}}, 9213 }; 9214 const UINT num_vertices13 = ARRAY_SIZE(vertices13); 9215 const UINT num_faces13 = ARRAY_SIZE(vertices13) / VERTS_PER_FACE; 9216 const UINT vertex_size13 = sizeof(*vertices13); 9217 const struct vertex_ptc_ubyte4n exp_vertices13[] = 9218 { 9219 {{ 0.0f, 3.0f, 0.f}, {255, 255, 0, 255}}, 9220 {{ 2.0f, 3.0f, 0.f}, {128, 179, 0, 255}}, 9221 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 255}}, 9222 9223 {{ 3.0f, 3.0f, 0.f}, {0, 0, 0, 255}}, 9224 {{ 3.0f, 0.0f, 0.f}, {255, 255, 0, 255}}, 9225 {{ 1.0f, 0.0f, 0.f}, {255, 0, 0, 255}}, 9226 }; 9227 const UINT exp_vertex_size13 = sizeof(*exp_vertices13); 9228 /* Test 14. Convert FLOAT2 to SHORT2N. */ 9229 const struct vertex_ptc vertices14[] = 9230 { 9231 {{ 0.0f, 3.0f, 0.f}, {1.0f, 2.0f}}, 9232 {{ 2.0f, 3.0f, 0.f}, {0.4f, 0.5f}}, 9233 {{ 0.0f, 0.0f, 0.f}, {0.6f, -1.0f}}, 9234 9235 {{ 3.0f, 3.0f, 0.f}, {-0.4f, -0.5f}}, 9236 {{ 3.0f, 0.0f, 0.f}, {-0.9f, -0.99997}}, 9237 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX, SHRT_MIN}}, 9238 }; 9239 const UINT num_vertices14 = ARRAY_SIZE(vertices14); 9240 const UINT num_faces14 = ARRAY_SIZE(vertices14) / VERTS_PER_FACE; 9241 const UINT vertex_size14 = sizeof(*vertices14); 9242 const struct vertex_ptc_short2 exp_vertices14[] = 9243 { 9244 {{ 0.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MAX}}, 9245 {{ 2.0f, 3.0f, 0.f}, {13107, 16384}}, 9246 {{ 0.0f, 0.0f, 0.f}, {19660, SHRT_MIN + 2}}, 9247 9248 {{ 3.0f, 3.0f, 0.f}, {-13106, -16383}}, 9249 {{ 3.0f, 0.0f, 0.f}, {-29489, SHRT_MIN + 3}}, 9250 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX, SHRT_MIN + 2}}, 9251 }; 9252 const UINT exp_vertex_size14 = sizeof(*exp_vertices14); 9253 /* Test 15. Convert FLOAT2 to SHORT4N. */ 9254 const struct vertex_ptc vertices15[] = 9255 { 9256 {{ 0.0f, 3.0f, 0.f}, {1.0f, 2.0f}}, 9257 {{ 2.0f, 3.0f, 0.f}, {0.4f, 0.5f}}, 9258 {{ 0.0f, 0.0f, 0.f}, {0.6f, -1.0f}}, 9259 9260 {{ 3.0f, 3.0f, 0.f}, {-0.4f, -0.5f}}, 9261 {{ 3.0f, 0.0f, 0.f}, {-0.9f, -0.99997}}, 9262 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX, SHRT_MIN}}, 9263 }; 9264 const UINT num_vertices15 = ARRAY_SIZE(vertices15); 9265 const UINT num_faces15 = ARRAY_SIZE(vertices15) / VERTS_PER_FACE; 9266 const UINT vertex_size15 = sizeof(*vertices15); 9267 const struct vertex_ptc_short4 exp_vertices15[] = 9268 { 9269 {{ 0.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MAX, 0, SHRT_MAX}}, 9270 {{ 2.0f, 3.0f, 0.f}, {13107, 16384, 0, SHRT_MAX}}, 9271 {{ 0.0f, 0.0f, 0.f}, {19660, SHRT_MIN + 2, 0, SHRT_MAX}}, 9272 9273 {{ 3.0f, 3.0f, 0.f}, {-13106, -16383, 0, SHRT_MAX}}, 9274 {{ 3.0f, 0.0f, 0.f}, {-29489, SHRT_MIN + 3, 0, SHRT_MAX}}, 9275 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX, SHRT_MIN + 2, 0, SHRT_MAX}}, 9276 }; 9277 const UINT exp_vertex_size15 = sizeof(*exp_vertices15); 9278 /* Test 16. Convert FLOAT2 to USHORT2N. */ 9279 const struct vertex_ptc vertices16[] = 9280 { 9281 {{ 0.0f, 3.0f, 0.f}, {1.0f, 2.0f}}, 9282 {{ 2.0f, 3.0f, 0.f}, {0.4f, 0.5f}}, 9283 {{ 0.0f, 0.0f, 0.f}, {0.6f, -1.0f}}, 9284 9285 {{ 3.0f, 3.0f, 0.f}, {-0.4f, -0.5f}}, 9286 {{ 3.0f, 0.0f, 0.f}, {-0.9f, 0.99998f}}, 9287 {{ 1.0f, 0.0f, 0.f}, {USHRT_MAX, 0.0f}}, 9288 }; 9289 const UINT num_vertices16 = ARRAY_SIZE(vertices16); 9290 const UINT num_faces16 = ARRAY_SIZE(vertices16) / VERTS_PER_FACE; 9291 const UINT vertex_size16 = sizeof(*vertices16); 9292 const struct vertex_ptc_ushort2n exp_vertices16[] = 9293 { 9294 {{ 0.0f, 3.0f, 0.f}, {USHRT_MAX, USHRT_MAX}}, 9295 {{ 2.0f, 3.0f, 0.f}, {26214, 32768}}, 9296 {{ 0.0f, 0.0f, 0.f}, {39321, 0}}, 9297 9298 {{ 3.0f, 3.0f, 0.f}, {0, 0}}, 9299 {{ 3.0f, 0.0f, 0.f}, {0, USHRT_MAX - 1}}, 9300 {{ 1.0f, 0.0f, 0.f}, {USHRT_MAX, 0}}, 9301 }; 9302 const UINT exp_vertex_size16 = sizeof(*exp_vertices16); 9303 /* Test 17. Convert FLOAT2 to USHORT4N. */ 9304 const struct vertex_ptc vertices17[] = 9305 { 9306 {{ 0.0f, 3.0f, 0.f}, {1.0f, 2.0f}}, 9307 {{ 2.0f, 3.0f, 0.f}, {0.4f, 0.5f}}, 9308 {{ 0.0f, 0.0f, 0.f}, {0.6f, -1.0f}}, 9309 9310 {{ 3.0f, 3.0f, 0.f}, {-0.4f, -0.5f}}, 9311 {{ 3.0f, 0.0f, 0.f}, {-0.9f, 0.99998f}}, 9312 {{ 1.0f, 0.0f, 0.f}, {USHRT_MAX, 0.0f}}, 9313 }; 9314 const UINT num_vertices17 = ARRAY_SIZE(vertices17); 9315 const UINT num_faces17 = ARRAY_SIZE(vertices17) / VERTS_PER_FACE; 9316 const UINT vertex_size17 = sizeof(*vertices17); 9317 const struct vertex_ptc_ushort4n exp_vertices17[] = 9318 { 9319 {{ 0.0f, 3.0f, 0.f}, {USHRT_MAX, USHRT_MAX, 0, USHRT_MAX}}, 9320 {{ 2.0f, 3.0f, 0.f}, {26214, 32768, 0, USHRT_MAX}}, 9321 {{ 0.0f, 0.0f, 0.f}, {39321, 0, 0, USHRT_MAX}}, 9322 9323 {{ 3.0f, 3.0f, 0.f}, {0, 0, 0, USHRT_MAX}}, 9324 {{ 3.0f, 0.0f, 0.f}, {0, USHRT_MAX - 1, 0, USHRT_MAX}}, 9325 {{ 1.0f, 0.0f, 0.f}, {USHRT_MAX, 0, 0, USHRT_MAX}}, 9326 }; 9327 const UINT exp_vertex_size17 = sizeof(*exp_vertices17); 9328 /* Test 18. Test that the method field is compared by converting a FLOAT2 to 9329 * FLOAT16_2. where the method field has been change from 9330 * D3DDECLMETHOD_DEFAULT to D3DDECLMETHOD_PARTIALU. */ 9331 const struct vertex_ptc vertices18[] = 9332 { 9333 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}}, 9334 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}}, 9335 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}}, 9336 9337 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}}, 9338 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}}, 9339 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}}, 9340 }; 9341 const UINT num_vertices18 = ARRAY_SIZE(vertices18); 9342 const UINT num_faces18 = ARRAY_SIZE(vertices18) / VERTS_PER_FACE; 9343 const UINT vertex_size18 = sizeof(*vertices18); 9344 const struct vertex_ptc_float16_2 exp_vertices18[] = 9345 { 9346 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */ 9347 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */ 9348 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */ 9349 9350 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd}}, /* {0.2f, 0.3f} */ 9351 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */ 9352 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */ 9353 }; 9354 const UINT exp_vertex_size18 = sizeof(*exp_vertices18); 9355 /* Test 19. Test that data is lost if usage index changes, e.g. TEXCOORD0 9356 * TEXCOORD1. */ 9357 const struct vertex_pntc vertices19[] = 9358 { 9359 {{ 0.0f, 3.0f, 0.f}, up, { 1.0f, 1.0f}}, 9360 {{ 2.0f, 3.0f, 0.f}, up, { 0.5f, 0.7f}}, 9361 {{ 0.0f, 0.0f, 0.f}, up, {-0.2f, -0.3f}}, 9362 9363 {{ 3.0f, 3.0f, 0.f}, up, { 0.2f, 0.3f}}, 9364 {{ 3.0f, 0.0f, 0.f}, up, { 1.0f, 1.0f}}, 9365 {{ 1.0f, 0.0f, 0.f}, up, { 0.1f, 0.2f}}, 9366 }; 9367 const UINT num_vertices19 = ARRAY_SIZE(vertices19); 9368 const UINT num_faces19 = ARRAY_SIZE(vertices19) / VERTS_PER_FACE; 9369 const UINT vertex_size19 = sizeof(*vertices19); 9370 const struct vertex_pntc exp_vertices19[] = 9371 { 9372 {{ 0.0f, 3.0f, 0.f}, up, zero_vec2}, 9373 {{ 2.0f, 3.0f, 0.f}, up, zero_vec2}, 9374 {{ 0.0f, 0.0f, 0.f}, up, zero_vec2}, 9375 9376 {{ 3.0f, 3.0f, 0.f}, up, zero_vec2}, 9377 {{ 3.0f, 0.0f, 0.f}, up, zero_vec2}, 9378 {{ 1.0f, 0.0f, 0.f}, up, zero_vec2}, 9379 }; 9380 const UINT exp_vertex_size19 = sizeof(*exp_vertices19); 9381 /* Test 20. Another test that data is lost if usage index changes, e.g. 9382 * TEXCOORD1 to TEXCOORD0. */ 9383 const struct vertex_pntc vertices20[] = 9384 { 9385 {{ 0.0f, 3.0f, 0.f}, up, { 1.0f, 1.0f}}, 9386 {{ 2.0f, 3.0f, 0.f}, up, { 0.5f, 0.7f}}, 9387 {{ 0.0f, 0.0f, 0.f}, up, {-0.2f, -0.3f}}, 9388 9389 {{ 3.0f, 3.0f, 0.f}, up, { 0.2f, 0.3f}}, 9390 {{ 3.0f, 0.0f, 0.f}, up, { 1.0f, 1.0f}}, 9391 {{ 1.0f, 0.0f, 0.f}, up, { 0.1f, 0.2f}}, 9392 }; 9393 const UINT num_vertices20 = ARRAY_SIZE(vertices20); 9394 const UINT num_faces20 = ARRAY_SIZE(vertices20) / VERTS_PER_FACE; 9395 const UINT vertex_size20 = sizeof(*vertices20); 9396 const struct vertex_pntc exp_vertices20[] = 9397 { 9398 {{ 0.0f, 3.0f, 0.f}, up, zero_vec2}, 9399 {{ 2.0f, 3.0f, 0.f}, up, zero_vec2}, 9400 {{ 0.0f, 0.0f, 0.f}, up, zero_vec2}, 9401 9402 {{ 3.0f, 3.0f, 0.f}, up, zero_vec2}, 9403 {{ 3.0f, 0.0f, 0.f}, up, zero_vec2}, 9404 {{ 1.0f, 0.0f, 0.f}, up, zero_vec2}, 9405 }; 9406 const UINT exp_vertex_size20 = sizeof(*exp_vertices20); 9407 /* Test 21. Convert FLOAT1 to FLOAT2. */ 9408 const struct vertex_ptc_float1 vertices21[] = 9409 { 9410 {{ 0.0f, 3.0f, 0.f}, 1.0f}, 9411 {{ 2.0f, 3.0f, 0.f}, 0.5f}, 9412 {{ 0.0f, 0.0f, 0.f}, -0.2f}, 9413 9414 {{ 3.0f, 3.0f, 0.f}, 0.2f}, 9415 {{ 3.0f, 0.0f, 0.f}, 1.0f}, 9416 {{ 1.0f, 0.0f, 0.f}, 0.1f}, 9417 }; 9418 const UINT num_vertices21 = ARRAY_SIZE(vertices21); 9419 const UINT num_faces21 = ARRAY_SIZE(vertices21) / VERTS_PER_FACE; 9420 const UINT vertex_size21 = sizeof(*vertices21); 9421 const struct vertex_ptc exp_vertices21[] = 9422 { 9423 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 0.0f}}, 9424 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.0f}}, 9425 {{ 0.0f, 0.0f, 0.f}, {-0.2f, 0.0f}}, 9426 9427 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.0f}}, 9428 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 0.0f}}, 9429 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.0f}}, 9430 }; 9431 const UINT exp_vertex_size21 = sizeof(*exp_vertices21); 9432 /* Test 22. Convert FLOAT1 to FLOAT3. */ 9433 const struct vertex_ptc_float1 vertices22[] = 9434 { 9435 {{ 0.0f, 3.0f, 0.f}, 1.0f}, 9436 {{ 2.0f, 3.0f, 0.f}, 0.5f}, 9437 {{ 0.0f, 0.0f, 0.f}, -0.2f}, 9438 9439 {{ 3.0f, 3.0f, 0.f}, 0.2f}, 9440 {{ 3.0f, 0.0f, 0.f}, 1.0f}, 9441 {{ 1.0f, 0.0f, 0.f}, 0.1f}, 9442 }; 9443 const UINT num_vertices22 = ARRAY_SIZE(vertices22); 9444 const UINT num_faces22 = ARRAY_SIZE(vertices22) / VERTS_PER_FACE; 9445 const UINT vertex_size22 = sizeof(*vertices22); 9446 const struct vertex_ptc_float3 exp_vertices22[] = 9447 { 9448 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 0.0f, 0.0f}}, 9449 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.0f, 0.0f}}, 9450 {{ 0.0f, 0.0f, 0.f}, {-0.2f, 0.0f, 0.0f}}, 9451 9452 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.0f, 0.0f}}, 9453 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 0.0f, 0.0f}}, 9454 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.0f, 0.0f}}, 9455 }; 9456 const UINT exp_vertex_size22 = sizeof(*exp_vertices22); 9457 /* Test 23. Convert FLOAT1 to FLOAT4. */ 9458 const struct vertex_ptc_float1 vertices23[] = 9459 { 9460 {{ 0.0f, 3.0f, 0.f}, 1.0f}, 9461 {{ 2.0f, 3.0f, 0.f}, 0.5f}, 9462 {{ 0.0f, 0.0f, 0.f}, -0.2f}, 9463 9464 {{ 3.0f, 3.0f, 0.f}, 0.2f}, 9465 {{ 3.0f, 0.0f, 0.f}, 1.0f}, 9466 {{ 1.0f, 0.0f, 0.f}, 0.1f}, 9467 }; 9468 const UINT num_vertices23 = ARRAY_SIZE(vertices23); 9469 const UINT num_faces23 = ARRAY_SIZE(vertices23) / VERTS_PER_FACE; 9470 const UINT vertex_size23 = sizeof(*vertices23); 9471 const struct vertex_ptc_float4 exp_vertices23[] = 9472 { 9473 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 0.0f, 0.0f, 1.0f}}, 9474 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.0f, 0.0f, 1.0f}}, 9475 {{ 0.0f, 0.0f, 0.f}, {-0.2f, 0.0f, 0.0f, 1.0f}}, 9476 9477 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.0f, 0.0f, 1.0f}}, 9478 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 0.0f, 0.0f, 1.0f}}, 9479 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.0f, 0.0f, 1.0f}}, 9480 }; 9481 const UINT exp_vertex_size23 = sizeof(*exp_vertices23); 9482 /* Test 24. Convert FLOAT1 to D3DCOLOR. */ 9483 const struct vertex_ptc_float1 vertices24[] = 9484 { 9485 {{ 0.0f, 3.0f, 0.f}, 1.0f}, 9486 {{ 2.0f, 3.0f, 0.f}, 0.5f}, 9487 {{ 0.0f, 0.0f, 0.f}, -0.2f}, 9488 9489 {{ 3.0f, 3.0f, 0.f}, 0.2f}, 9490 {{ 3.0f, 0.0f, 0.f}, 1.0f}, 9491 {{ 1.0f, 0.0f, 0.f}, 0.11f}, 9492 }; 9493 const UINT num_vertices24 = ARRAY_SIZE(vertices24); 9494 const UINT num_faces24 = ARRAY_SIZE(vertices24) / VERTS_PER_FACE; 9495 const UINT vertex_size24 = sizeof(*vertices24); 9496 const struct vertex_ptc_d3dcolor exp_vertices24[] = 9497 { 9498 {{ 0.0f, 3.0f, 0.f}, {0, 0, 255, 255}}, 9499 {{ 2.0f, 3.0f, 0.f}, {0, 0, 128, 255}}, 9500 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 255}}, 9501 9502 {{ 3.0f, 3.0f, 0.f}, {0, 0, 51, 255}}, 9503 {{ 3.0f, 0.0f, 0.f}, {0, 0, 255, 255}}, 9504 {{ 1.0f, 0.0f, 0.f}, {0, 0, 28, 255}}, 9505 }; 9506 const UINT exp_vertex_size24 = sizeof(*exp_vertices24); 9507 /* Test 25. Convert FLOAT1 to ubyte4. */ 9508 const struct vertex_ptc_float1 vertices25[] = 9509 { 9510 {{ 0.0f, 3.0f, 0.f}, 0.0f}, 9511 {{ 2.0f, 3.0f, 0.f}, 1.4f}, 9512 {{ 0.0f, 0.0f, 0.f}, 1.5f}, 9513 9514 {{ 3.0f, 3.0f, 0.f}, 255.0f}, 9515 {{ 3.0f, 0.0f, 0.f}, 256.0f}, 9516 {{ 1.0f, 0.0f, 0.f}, -1.0f}, 9517 }; 9518 const UINT num_vertices25 = ARRAY_SIZE(vertices25); 9519 const UINT num_faces25 = ARRAY_SIZE(vertices25) / VERTS_PER_FACE; 9520 const UINT vertex_size25 = sizeof(*vertices25); 9521 const struct vertex_ptc_ubyte4 exp_vertices25[] = 9522 { 9523 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 1}}, 9524 {{ 2.0f, 3.0f, 0.f}, {1, 0, 0, 1}}, 9525 {{ 0.0f, 0.0f, 0.f}, {2, 0, 0, 1}}, 9526 9527 {{ 3.0f, 3.0f, 0.f}, {255, 0, 0, 1}}, 9528 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 1}}, 9529 {{ 1.0f, 0.0f, 0.f}, {0, 0, 0, 1}}, 9530 }; 9531 const UINT exp_vertex_size25 = sizeof(*exp_vertices25); 9532 /* Test 26. Convert FLOAT4 to D3DCOLOR. */ 9533 const struct vertex_ptc_float4 vertices26[] = 9534 { 9535 {{ 0.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.4f, 0.5f}}, 9536 {{ 2.0f, 3.0f, 0.f}, {-0.4f, -0.5f, -1.0f, -2.0f}}, 9537 {{ 0.0f, 0.0f, 0.f}, {254.0f, 255.0f, 256.0f, 257.0f}}, 9538 9539 {{ 3.0f, 3.0f, 0.f}, {0.1f, 0.2f, 0.3f, 0.4f}}, 9540 {{ 3.0f, 0.0f, 0.f}, {0.5f, 0.6f, 0.7f, 0.8f}}, 9541 {{ 1.0f, 0.0f, 0.f}, {0.9f, 0.99f, 0.995f, 0.999f}}, 9542 }; 9543 const UINT num_vertices26 = ARRAY_SIZE(vertices26); 9544 const UINT num_faces26 = ARRAY_SIZE(vertices26) / VERTS_PER_FACE; 9545 const UINT vertex_size26 = sizeof(*vertices26); 9546 const struct vertex_ptc_d3dcolor exp_vertices26[] = 9547 { 9548 {{ 0.0f, 3.0f, 0.f}, {102, 255, 0, 128}}, 9549 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, 9550 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}}, 9551 9552 {{ 3.0f, 3.0f, 0.f}, {77, 51, 26, 102}}, 9553 {{ 3.0f, 0.0f, 0.f}, {179, 153, 128, 204}}, 9554 {{ 1.0f, 0.0f, 0.f}, {254, 252, 230, 255}}, 9555 }; 9556 const UINT exp_vertex_size26 = sizeof(*exp_vertices26); 9557 /* Test 27. Convert D3DCOLOR to FLOAT4. */ 9558 const struct vertex_ptc_d3dcolor vertices27[] = 9559 { 9560 {{ 0.0f, 3.0f, 0.f}, {102, 255, 0, 128}}, 9561 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, 9562 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}}, 9563 9564 {{ 3.0f, 3.0f, 0.f}, {77, 51, 26, 102}}, 9565 {{ 3.0f, 0.0f, 0.f}, {179, 153, 128, 204}}, 9566 {{ 1.0f, 0.0f, 0.f}, {254, 252, 230, 255}}, 9567 }; 9568 const UINT num_vertices27 = ARRAY_SIZE(vertices27); 9569 const UINT num_faces27 = ARRAY_SIZE(vertices27) / VERTS_PER_FACE; 9570 const UINT vertex_size27 = sizeof(*vertices27); 9571 const struct vertex_ptc_float4 exp_vertices27[] = 9572 { 9573 {{ 0.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.4f, 0.501961f}}, 9574 {{ 2.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}}, 9575 {{ 0.0f, 0.0f, 0.f}, {1.0f, 1.0f, 1.0f, 1.0f}}, 9576 9577 {{ 3.0f, 3.0f, 0.f}, {0.101961f, 0.2f, 0.301961f, 0.4f}}, 9578 {{ 3.0f, 0.0f, 0.f}, {0.501961f, 0.6f, 0.701961f, 0.8f}}, 9579 {{ 1.0f, 0.0f, 0.f}, {0.901961f, 0.988235f, 0.996078f, 1.0f}}, 9580 }; 9581 const UINT exp_vertex_size27 = sizeof(*exp_vertices27); 9582 /* Test 28. Convert UBYTE4 to FLOAT4. */ 9583 const struct vertex_ptc_ubyte4 vertices28[] = 9584 { 9585 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, 9586 {{ 2.0f, 3.0f, 0.f}, {1, 1, 1, 1}}, 9587 {{ 0.0f, 0.0f, 0.f}, {1, 0, 1, 0}}, 9588 9589 {{ 3.0f, 3.0f, 0.f}, {0, 1, 0, 1}}, 9590 {{ 3.0f, 0.0f, 0.f}, {10, 20, 30, 40}}, 9591 {{ 1.0f, 0.0f, 0.f}, {50, 60, 127, 255}}, 9592 }; 9593 const UINT num_vertices28 = ARRAY_SIZE(vertices28); 9594 const UINT num_faces28 = ARRAY_SIZE(vertices28) / VERTS_PER_FACE; 9595 const UINT vertex_size28 = sizeof(*vertices28); 9596 const struct vertex_ptc_float4 exp_vertices28[] = 9597 { 9598 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}}, 9599 {{ 2.0f, 3.0f, 0.f}, {1.0f, 1.0f, 1.0f, 1.0f}}, 9600 {{ 0.0f, 0.0f, 0.f}, {1.0f, 0.0f, 1.0f, 0.0f}}, 9601 9602 {{ 3.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.0f, 1.0f}}, 9603 {{ 3.0f, 0.0f, 0.f}, {10.0f, 20.0f, 30.0f, 40.0f}}, 9604 {{ 1.0f, 0.0f, 0.f}, {50.0f, 60.0f, 127.0f, 255.0f}}, 9605 }; 9606 const UINT exp_vertex_size28 = sizeof(*exp_vertices28); 9607 /* Test 29. Convert SHORT2 to FLOAT4. */ 9608 const struct vertex_ptc_short2 vertices29[] = 9609 { 9610 {{ 0.0f, 3.0f, 0.f}, {0, 0}}, 9611 {{ 2.0f, 3.0f, 0.f}, {0, 1}}, 9612 {{ 0.0f, 0.0f, 0.f}, {1, 0}}, 9613 9614 {{ 3.0f, 3.0f, 0.f}, {1, 1}}, 9615 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MAX}}, 9616 {{ 1.0f, 0.0f, 0.f}, {-42, 42}}, 9617 }; 9618 const UINT num_vertices29 = ARRAY_SIZE(vertices29); 9619 const UINT num_faces29 = ARRAY_SIZE(vertices29) / VERTS_PER_FACE; 9620 const UINT vertex_size29 = sizeof(*vertices29); 9621 const struct vertex_ptc_float4 exp_vertices29[] = 9622 { 9623 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 1.0f}}, 9624 {{ 2.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.0f, 1.0f }}, 9625 {{ 0.0f, 0.0f, 0.f}, {1.0f, 0.0f, 0.0f, 1.0f}}, 9626 9627 {{ 3.0f, 3.0f, 0.f}, {1.0f, 1.0f, 0.0f, 1.0f}}, 9628 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MAX, 0.0f, 1.0f}}, 9629 {{ 1.0f, 0.0f, 0.f}, {-42.0f, 42.0f, 0.0f, 1.0f}}, 9630 }; 9631 const UINT exp_vertex_size29 = sizeof(*exp_vertices29); 9632 /* Test 29. Convert SHORT4 to FLOAT4. */ 9633 const struct vertex_ptc_short4 vertices30[] = 9634 { 9635 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, 9636 {{ 2.0f, 3.0f, 0.f}, {0, 1, 0, 1}}, 9637 {{ 0.0f, 0.0f, 0.f}, {1, 0, 1, 0}}, 9638 9639 {{ 3.0f, 3.0f, 0.f}, {1, 1, 1, 1}}, 9640 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MAX, 1, 0}}, 9641 {{ 1.0f, 0.0f, 0.f}, {-42, 42, SHRT_MAX, SHRT_MIN}}, 9642 }; 9643 const UINT num_vertices30 = ARRAY_SIZE(vertices30); 9644 const UINT num_faces30 = ARRAY_SIZE(vertices30) / VERTS_PER_FACE; 9645 const UINT vertex_size30 = sizeof(*vertices30); 9646 const struct vertex_ptc_float4 exp_vertices30[] = 9647 { 9648 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}}, 9649 {{ 2.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.0f, 1.0f }}, 9650 {{ 0.0f, 0.0f, 0.f}, {1.0f, 0.0f, 1.0f, 0.0f}}, 9651 9652 {{ 3.0f, 3.0f, 0.f}, {1.0f, 1.0f, 1.0f, 1.0f}}, 9653 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MAX, 1.0f, 0.0f}}, 9654 {{ 1.0f, 0.0f, 0.f}, {-42.0f, 42.0f, SHRT_MAX, SHRT_MIN}}, 9655 }; 9656 const UINT exp_vertex_size30 = sizeof(*exp_vertices30); 9657 /* Test 31. Convert UBYTE4N to FLOAT4. */ 9658 const struct vertex_ptc_ubyte4n vertices31[] = 9659 { 9660 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, 9661 {{ 2.0f, 3.0f, 0.f}, {1, 1, 1, 1}}, 9662 {{ 0.0f, 0.0f, 0.f}, {1, 0, 1, 0}}, 9663 9664 {{ 3.0f, 3.0f, 0.f}, {0, 1, 0, 1}}, 9665 {{ 3.0f, 0.0f, 0.f}, {10, 20, 30, 40}}, 9666 {{ 1.0f, 0.0f, 0.f}, {50, 60, 70, UCHAR_MAX}}, 9667 }; 9668 const UINT num_vertices31 = ARRAY_SIZE(vertices31); 9669 const UINT num_faces31 = ARRAY_SIZE(vertices31) / VERTS_PER_FACE; 9670 const UINT vertex_size31 = sizeof(*vertices31); 9671 const struct vertex_ptc_float4 exp_vertices31[] = 9672 { 9673 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}}, 9674 {{ 2.0f, 3.0f, 0.f}, {(FLOAT)1/UCHAR_MAX, (FLOAT)1/UCHAR_MAX, (FLOAT)1/UCHAR_MAX, (FLOAT)1/UCHAR_MAX}}, 9675 {{ 0.0f, 0.0f, 0.f}, {(FLOAT)1/UCHAR_MAX, 0.0f, (FLOAT)1/UCHAR_MAX, 0.0f}}, 9676 9677 {{ 3.0f, 3.0f, 0.f}, {0.0f, (FLOAT)1/UCHAR_MAX, 0.0f, (FLOAT)1/UCHAR_MAX}}, 9678 {{ 3.0f, 0.0f, 0.f}, {(FLOAT)10/UCHAR_MAX, (FLOAT)20/UCHAR_MAX, (FLOAT)30/UCHAR_MAX, (FLOAT)40/UCHAR_MAX}}, 9679 {{ 1.0f, 0.0f, 0.f}, {(FLOAT)50/UCHAR_MAX, (FLOAT)60/UCHAR_MAX, (FLOAT)70/UCHAR_MAX, 1.0f}}, 9680 }; 9681 const UINT exp_vertex_size31 = sizeof(*exp_vertices31); 9682 /* Test 32. Convert SHORT2N to FLOAT4. */ 9683 const struct vertex_ptc_short2 vertices32[] = 9684 { 9685 {{ 0.0f, 3.0f, 0.f}, {0, 0}}, 9686 {{ 2.0f, 3.0f, 0.f}, {0, 1}}, 9687 {{ 0.0f, 0.0f, 0.f}, {1, 0}}, 9688 9689 {{ 3.0f, 3.0f, 0.f}, {1, 1}}, 9690 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN + 1, SHRT_MAX}}, 9691 {{ 1.0f, 0.0f, 0.f}, {-42, 42}}, 9692 }; 9693 const UINT num_vertices32 = ARRAY_SIZE(vertices32); 9694 const UINT num_faces32 = ARRAY_SIZE(vertices32) / VERTS_PER_FACE; 9695 const UINT vertex_size32 = sizeof(*vertices32); 9696 const struct vertex_ptc_float4 exp_vertices32[] = 9697 { 9698 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 1.0f}}, 9699 {{ 2.0f, 3.0f, 0.f}, {0.0f, 1.0f/SHRT_MAX, 0.0f, 1.0f}}, 9700 {{ 0.0f, 0.0f, 0.f}, {1.0f/SHRT_MAX, 0.0f, 0.0f, 1.0f}}, 9701 9702 {{ 3.0f, 3.0f, 0.f}, {1.0f/SHRT_MAX, 1.0f/SHRT_MAX, 0.0f, 1.0f}}, 9703 {{ 3.0f, 0.0f, 0.f}, {-1.0f, 1.0f, 0.0f, 1.0f}}, 9704 {{ 1.0f, 0.0f, 0.f}, {-42.0f/SHRT_MAX, 42.0f/SHRT_MAX, 0.0f, 1.0f}}, 9705 }; 9706 const UINT exp_vertex_size32 = sizeof(*exp_vertices32); 9707 /* Test 33. Convert SHORT4N to FLOAT4. */ 9708 const struct vertex_ptc_short4 vertices33[] = 9709 { 9710 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, 9711 {{ 2.0f, 3.0f, 0.f}, {0, 1, 0, 1}}, 9712 {{ 0.0f, 0.0f, 0.f}, {1, 0, 1, 0}}, 9713 9714 {{ 3.0f, 3.0f, 0.f}, {1, 1, 1, 1}}, 9715 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN + 1, SHRT_MAX, SHRT_MIN + 1, SHRT_MAX}}, 9716 {{ 1.0f, 0.0f, 0.f}, {-42, 42, 1, 1}}, 9717 }; 9718 const UINT num_vertices33 = ARRAY_SIZE(vertices33); 9719 const UINT num_faces33 = ARRAY_SIZE(vertices33) / VERTS_PER_FACE; 9720 const UINT vertex_size33 = sizeof(*vertices33); 9721 const struct vertex_ptc_float4 exp_vertices33[] = 9722 { 9723 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}}, 9724 {{ 2.0f, 3.0f, 0.f}, {0.0f, 1.0f/SHRT_MAX, 0.0f, 1.0f/SHRT_MAX}}, 9725 {{ 0.0f, 0.0f, 0.f}, {1.0f/SHRT_MAX, 0.0f, 1.0f/SHRT_MAX, 0.0f}}, 9726 9727 {{ 3.0f, 3.0f, 0.f}, {1.0f/SHRT_MAX, 1.0f/SHRT_MAX, 1.0f/SHRT_MAX, 1.0f/SHRT_MAX}}, 9728 {{ 3.0f, 0.0f, 0.f}, {-1.0f, 1.0f, -1.0f, 1.0f}}, 9729 {{ 1.0f, 0.0f, 0.f}, {-42.0f/SHRT_MAX, 42.0f/SHRT_MAX, 1.0f/SHRT_MAX, 1.0f/SHRT_MAX}}, 9730 }; 9731 const UINT exp_vertex_size33 = sizeof(*exp_vertices33); 9732 /* Test 34. Convert FLOAT16_2 to FLOAT4. */ 9733 const struct vertex_ptc_float16_2 vertices34[] = 9734 { 9735 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */ 9736 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */ 9737 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */ 9738 9739 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd}}, /* {0.2f, 0.3f} */ 9740 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */ 9741 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */ 9742 }; 9743 const UINT num_vertices34 = ARRAY_SIZE(vertices34); 9744 const UINT num_faces34 = ARRAY_SIZE(vertices34) / VERTS_PER_FACE; 9745 const UINT vertex_size34 = sizeof(*vertices34); 9746 const struct vertex_ptc_float4 exp_vertices34[] = 9747 { 9748 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f, 0.0f, 1.0f}}, 9749 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.700195f, 0.0f, 1.0f}}, 9750 {{ 0.0f, 0.0f, 0.f}, {-0.199951f, -0.300049f, 0.0f, 1.0f}}, 9751 9752 {{ 3.0f, 3.0f, 0.f}, {0.199951f, 0.300049f, 0.0f, 1.0f}}, 9753 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f, 0.0f, 1.0f}}, 9754 {{ 1.0f, 0.0f, 0.f}, {0.099976f, 0.199951f, 0.0f, 1.0f}}, 9755 }; 9756 const UINT exp_vertex_size34 = sizeof(*exp_vertices34); 9757 /* Test 35. Convert FLOAT16_4 to FLOAT4. */ 9758 const struct vertex_ptc_float16_4 vertices35[] = 9759 { 9760 {{ 0.0f, 3.0f, 0.f}, {0x0000, 0x0000, 0x0000, 0x0000}}, 9761 {{ 2.0f, 3.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}}, 9762 {{ 0.0f, 0.0f, 0.f}, {0x3c00, 0x0000, 0x3c00, 0x0000}}, 9763 9764 {{ 3.0f, 3.0f, 0.f}, {0x0000, 0x3c00, 0x0000, 0x3c00}}, 9765 {{ 3.0f, 0.0f, 0.f}, {0x3800, 0x399a, 0xb266, 0xb4cd}}, 9766 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266, 0x2e66, 0x3266}}, 9767 }; 9768 const UINT num_vertices35 = ARRAY_SIZE(vertices35); 9769 const UINT num_faces35 = ARRAY_SIZE(vertices35) / VERTS_PER_FACE; 9770 const UINT vertex_size35 = sizeof(*vertices35); 9771 const struct vertex_ptc_float4 exp_vertices35[] = 9772 { 9773 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}}, 9774 {{ 2.0f, 3.0f, 0.f}, {1.0f, 1.0f, 1.0f, 1.0f}}, 9775 {{ 0.0f, 0.0f, 0.f}, {1.0f, 0.0f, 1.0f, 0.0f}}, 9776 9777 {{ 3.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.0f, 1.0f}}, 9778 {{ 3.0f, 0.0f, 0.f}, {0.5f, 0.700195f, -0.199951f, -0.300049f}}, 9779 {{ 1.0f, 0.0f, 0.f}, {0.099976f, 0.199951f, 0.099976f, 0.199951f}}, 9780 }; 9781 const UINT exp_vertex_size35 = sizeof(*exp_vertices35); 9782 /* Test 36. Check that vertex buffer sharing is ok. */ 9783 const struct vertex_pn vertices36[] = 9784 { 9785 {{ 0.0f, 3.0f, 0.f}, up}, 9786 {{ 2.0f, 3.0f, 0.f}, up}, 9787 {{ 0.0f, 0.0f, 0.f}, up}, 9788 }; 9789 const UINT num_vertices36 = ARRAY_SIZE(vertices36); 9790 const UINT num_faces36 = ARRAY_SIZE(vertices36) / VERTS_PER_FACE; 9791 const UINT vertex_size36 = sizeof(*vertices36); 9792 const DWORD clone_options36 = options | D3DXMESH_VB_SHARE; 9793 /* Common mesh data */ 9794 ID3DXMesh *mesh = NULL; 9795 ID3DXMesh *mesh_clone = NULL; 9796 struct 9797 { 9798 const BYTE *vertices; 9799 const DWORD *indices; 9800 const DWORD *attributes; 9801 const UINT num_vertices; 9802 const UINT num_faces; 9803 const UINT vertex_size; 9804 const DWORD create_options; 9805 const DWORD clone_options; 9806 D3DVERTEXELEMENT9 *declaration; 9807 D3DVERTEXELEMENT9 *new_declaration; 9808 const BYTE *exp_vertices; 9809 const UINT exp_vertex_size; 9810 } 9811 tc[] = 9812 { 9813 { 9814 (BYTE*)vertices0, 9815 NULL, 9816 NULL, 9817 num_vertices0, 9818 num_faces0, 9819 vertex_size0, 9820 options, 9821 options, 9822 declaration_pn, 9823 declaration_pn, 9824 (BYTE*)vertices0, 9825 vertex_size0 9826 }, 9827 { 9828 (BYTE*)vertices0, 9829 NULL, 9830 NULL, 9831 num_vertices0, 9832 num_faces0, 9833 vertex_size0, 9834 options_16bit, 9835 options_16bit, 9836 declaration_pn, 9837 declaration_pn, 9838 (BYTE*)vertices0, 9839 vertex_size0 9840 }, 9841 { 9842 (BYTE*)vertices0, 9843 NULL, 9844 NULL, 9845 num_vertices0, 9846 num_faces0, 9847 vertex_size0, 9848 options, 9849 options, 9850 declaration_pn, 9851 declaration_pntc, 9852 (BYTE*)exp_vertices2, 9853 exp_vertex_size2 9854 }, 9855 { 9856 (BYTE*)vertices0, 9857 NULL, 9858 NULL, 9859 num_vertices0, 9860 num_faces0, 9861 vertex_size0, 9862 options, 9863 options, 9864 declaration_pn, 9865 declaration_ptcn, 9866 (BYTE*)exp_vertices3, 9867 exp_vertex_size3 9868 }, 9869 { 9870 (BYTE*)vertices4, 9871 NULL, 9872 NULL, 9873 num_vertices4, 9874 num_faces4, 9875 vertex_size4, 9876 options, 9877 options, 9878 declaration_ptc, 9879 declaration_ptc_float16_2, 9880 (BYTE*)exp_vertices4, 9881 exp_vertex_size4 9882 }, 9883 { 9884 (BYTE*)vertices5, 9885 NULL, 9886 NULL, 9887 num_vertices5, 9888 num_faces5, 9889 vertex_size5, 9890 options, 9891 options, 9892 declaration_ptc, 9893 declaration_ptc_float16_4, 9894 (BYTE*)exp_vertices5, 9895 exp_vertex_size5 9896 }, 9897 { 9898 (BYTE*)vertices6, 9899 NULL, 9900 NULL, 9901 num_vertices6, 9902 num_faces6, 9903 vertex_size6, 9904 options, 9905 options, 9906 declaration_ptc, 9907 declaration_ptc_float1, 9908 (BYTE*)exp_vertices6, 9909 exp_vertex_size6 9910 }, 9911 { 9912 (BYTE*)vertices7, 9913 NULL, 9914 NULL, 9915 num_vertices7, 9916 num_faces7, 9917 vertex_size7, 9918 options, 9919 options, 9920 declaration_ptc, 9921 declaration_ptc_float3, 9922 (BYTE*)exp_vertices7, 9923 exp_vertex_size7 9924 }, 9925 { 9926 (BYTE*)vertices8, 9927 NULL, 9928 NULL, 9929 num_vertices8, 9930 num_faces8, 9931 vertex_size8, 9932 options, 9933 options, 9934 declaration_ptc, 9935 declaration_ptc_float4, 9936 (BYTE*)exp_vertices8, 9937 exp_vertex_size8 9938 }, 9939 { 9940 (BYTE*)vertices9, 9941 NULL, 9942 NULL, 9943 num_vertices9, 9944 num_faces9, 9945 vertex_size9, 9946 options, 9947 options, 9948 declaration_ptc, 9949 declaration_ptc_d3dcolor, 9950 (BYTE*)exp_vertices9, 9951 exp_vertex_size9 9952 }, 9953 { 9954 (BYTE*)vertices10, 9955 NULL, 9956 NULL, 9957 num_vertices10, 9958 num_faces10, 9959 vertex_size10, 9960 options, 9961 options, 9962 declaration_ptc, 9963 declaration_ptc_ubyte4, 9964 (BYTE*)exp_vertices10, 9965 exp_vertex_size10 9966 }, 9967 { 9968 (BYTE*)vertices11, 9969 NULL, 9970 NULL, 9971 num_vertices11, 9972 num_faces11, 9973 vertex_size11, 9974 options, 9975 options, 9976 declaration_ptc, 9977 declaration_ptc_short2, 9978 (BYTE*)exp_vertices11, 9979 exp_vertex_size11 9980 }, 9981 { 9982 (BYTE*)vertices12, 9983 NULL, 9984 NULL, 9985 num_vertices12, 9986 num_faces12, 9987 vertex_size12, 9988 options, 9989 options, 9990 declaration_ptc, 9991 declaration_ptc_short4, 9992 (BYTE*)exp_vertices12, 9993 exp_vertex_size12 9994 }, 9995 { 9996 (BYTE*)vertices13, 9997 NULL, 9998 NULL, 9999 num_vertices13, 10000 num_faces13, 10001 vertex_size13, 10002 options, 10003 options, 10004 declaration_ptc, 10005 declaration_ptc_ubyte4n, 10006 (BYTE*)exp_vertices13, 10007 exp_vertex_size13 10008 }, 10009 { 10010 (BYTE*)vertices14, 10011 NULL, 10012 NULL, 10013 num_vertices14, 10014 num_faces14, 10015 vertex_size14, 10016 options, 10017 options, 10018 declaration_ptc, 10019 declaration_ptc_short2n, 10020 (BYTE*)exp_vertices14, 10021 exp_vertex_size14 10022 }, 10023 { 10024 (BYTE*)vertices15, 10025 NULL, 10026 NULL, 10027 num_vertices15, 10028 num_faces15, 10029 vertex_size15, 10030 options, 10031 options, 10032 declaration_ptc, 10033 declaration_ptc_short4n, 10034 (BYTE*)exp_vertices15, 10035 exp_vertex_size15 10036 }, 10037 { 10038 (BYTE*)vertices16, 10039 NULL, 10040 NULL, 10041 num_vertices16, 10042 num_faces16, 10043 vertex_size16, 10044 options, 10045 options, 10046 declaration_ptc, 10047 declaration_ptc_ushort2n, 10048 (BYTE*)exp_vertices16, 10049 exp_vertex_size16 10050 }, 10051 { 10052 (BYTE*)vertices17, 10053 NULL, 10054 NULL, 10055 num_vertices17, 10056 num_faces17, 10057 vertex_size17, 10058 options, 10059 options, 10060 declaration_ptc, 10061 declaration_ptc_ushort4n, 10062 (BYTE*)exp_vertices17, 10063 exp_vertex_size17 10064 }, 10065 { 10066 (BYTE*)vertices18, 10067 NULL, 10068 NULL, 10069 num_vertices18, 10070 num_faces18, 10071 vertex_size18, 10072 options, 10073 options, 10074 declaration_ptc, 10075 declaration_ptc_float16_2_partialu, 10076 (BYTE*)exp_vertices18, 10077 exp_vertex_size18 10078 }, 10079 { 10080 (BYTE*)vertices19, 10081 NULL, 10082 NULL, 10083 num_vertices19, 10084 num_faces19, 10085 vertex_size19, 10086 options, 10087 options, 10088 declaration_pntc, 10089 declaration_pntc1, 10090 (BYTE*)exp_vertices19, 10091 exp_vertex_size19 10092 }, 10093 { 10094 (BYTE*)vertices20, 10095 NULL, 10096 NULL, 10097 num_vertices20, 10098 num_faces20, 10099 vertex_size20, 10100 options, 10101 options, 10102 declaration_pntc1, 10103 declaration_pntc, 10104 (BYTE*)exp_vertices20, 10105 exp_vertex_size20 10106 }, 10107 { 10108 (BYTE*)vertices21, 10109 NULL, 10110 NULL, 10111 num_vertices21, 10112 num_faces21, 10113 vertex_size21, 10114 options, 10115 options, 10116 declaration_ptc_float1, 10117 declaration_ptc, 10118 (BYTE*)exp_vertices21, 10119 exp_vertex_size21 10120 }, 10121 { 10122 (BYTE*)vertices22, 10123 NULL, 10124 NULL, 10125 num_vertices22, 10126 num_faces22, 10127 vertex_size22, 10128 options, 10129 options, 10130 declaration_ptc_float1, 10131 declaration_ptc_float3, 10132 (BYTE*)exp_vertices22, 10133 exp_vertex_size22 10134 }, 10135 { 10136 (BYTE*)vertices23, 10137 NULL, 10138 NULL, 10139 num_vertices23, 10140 num_faces23, 10141 vertex_size23, 10142 options, 10143 options, 10144 declaration_ptc_float1, 10145 declaration_ptc_float4, 10146 (BYTE*)exp_vertices23, 10147 exp_vertex_size23 10148 }, 10149 { 10150 (BYTE*)vertices24, 10151 NULL, 10152 NULL, 10153 num_vertices24, 10154 num_faces24, 10155 vertex_size24, 10156 options, 10157 options, 10158 declaration_ptc_float1, 10159 declaration_ptc_d3dcolor, 10160 (BYTE*)exp_vertices24, 10161 exp_vertex_size24 10162 }, 10163 { 10164 (BYTE*)vertices25, 10165 NULL, 10166 NULL, 10167 num_vertices25, 10168 num_faces25, 10169 vertex_size25, 10170 options, 10171 options, 10172 declaration_ptc_float1, 10173 declaration_ptc_ubyte4, 10174 (BYTE*)exp_vertices25, 10175 exp_vertex_size25 10176 }, 10177 { 10178 (BYTE*)vertices26, 10179 NULL, 10180 NULL, 10181 num_vertices26, 10182 num_faces26, 10183 vertex_size26, 10184 options, 10185 options, 10186 declaration_ptc_float4, 10187 declaration_ptc_d3dcolor, 10188 (BYTE*)exp_vertices26, 10189 exp_vertex_size26 10190 }, 10191 { 10192 (BYTE*)vertices27, 10193 NULL, 10194 NULL, 10195 num_vertices27, 10196 num_faces27, 10197 vertex_size27, 10198 options, 10199 options, 10200 declaration_ptc_d3dcolor, 10201 declaration_ptc_float4, 10202 (BYTE*)exp_vertices27, 10203 exp_vertex_size27 10204 }, 10205 { 10206 (BYTE*)vertices28, 10207 NULL, 10208 NULL, 10209 num_vertices28, 10210 num_faces28, 10211 vertex_size28, 10212 options, 10213 options, 10214 declaration_ptc_ubyte4, 10215 declaration_ptc_float4, 10216 (BYTE*)exp_vertices28, 10217 exp_vertex_size28 10218 }, 10219 { 10220 (BYTE*)vertices29, 10221 NULL, 10222 NULL, 10223 num_vertices29, 10224 num_faces29, 10225 vertex_size29, 10226 options, 10227 options, 10228 declaration_ptc_short2, 10229 declaration_ptc_float4, 10230 (BYTE*)exp_vertices29, 10231 exp_vertex_size29 10232 }, 10233 { 10234 (BYTE*)vertices30, 10235 NULL, 10236 NULL, 10237 num_vertices30, 10238 num_faces30, 10239 vertex_size30, 10240 options, 10241 options, 10242 declaration_ptc_short4, 10243 declaration_ptc_float4, 10244 (BYTE*)exp_vertices30, 10245 exp_vertex_size30 10246 }, 10247 { 10248 (BYTE*)vertices31, 10249 NULL, 10250 NULL, 10251 num_vertices31, 10252 num_faces31, 10253 vertex_size31, 10254 options, 10255 options, 10256 declaration_ptc_ubyte4n, 10257 declaration_ptc_float4, 10258 (BYTE*)exp_vertices31, 10259 exp_vertex_size31 10260 }, 10261 { 10262 (BYTE*)vertices32, 10263 NULL, 10264 NULL, 10265 num_vertices32, 10266 num_faces32, 10267 vertex_size32, 10268 options, 10269 options, 10270 declaration_ptc_short2n, 10271 declaration_ptc_float4, 10272 (BYTE*)exp_vertices32, 10273 exp_vertex_size32 10274 }, 10275 { 10276 (BYTE*)vertices33, 10277 NULL, 10278 NULL, 10279 num_vertices33, 10280 num_faces33, 10281 vertex_size33, 10282 options, 10283 options, 10284 declaration_ptc_short4n, 10285 declaration_ptc_float4, 10286 (BYTE*)exp_vertices33, 10287 exp_vertex_size33 10288 }, 10289 { 10290 (BYTE*)vertices34, 10291 NULL, 10292 NULL, 10293 num_vertices34, 10294 num_faces34, 10295 vertex_size34, 10296 options, 10297 options, 10298 declaration_ptc_float16_2, 10299 declaration_ptc_float4, 10300 (BYTE*)exp_vertices34, 10301 exp_vertex_size34 10302 }, 10303 { 10304 (BYTE*)vertices35, 10305 NULL, 10306 NULL, 10307 num_vertices35, 10308 num_faces35, 10309 vertex_size35, 10310 options, 10311 options, 10312 declaration_ptc_float16_4, 10313 declaration_ptc_float4, 10314 (BYTE*)exp_vertices35, 10315 exp_vertex_size35 10316 }, 10317 { 10318 (BYTE*)vertices36, 10319 NULL, 10320 NULL, 10321 num_vertices36, 10322 num_faces36, 10323 vertex_size36, 10324 options, 10325 clone_options36, 10326 declaration_pn, 10327 declaration_pn, 10328 (BYTE*)vertices36, 10329 vertex_size36 10330 }, 10331 }; 10332 #ifdef __REACTOS__ 10333 #undef up 10334 #undef zero_vec2 10335 #endif 10336 10337 test_context = new_test_context(); 10338 if (!test_context) 10339 { 10340 skip("Couldn't create test context\n"); 10341 goto cleanup; 10342 } 10343 10344 for (i = 0; i < ARRAY_SIZE(tc); i++) 10345 { 10346 UINT j; 10347 D3DVERTEXELEMENT9 new_declaration[MAX_FVF_DECL_SIZE]; 10348 UINT exp_new_decl_length, new_decl_length; 10349 UINT exp_new_decl_size, new_decl_size; 10350 10351 hr = init_test_mesh(tc[i].num_faces, tc[i].num_vertices, 10352 tc[i].create_options, 10353 tc[i].declaration, 10354 test_context->device, &mesh, 10355 tc[i].vertices, tc[i].vertex_size, 10356 tc[i].indices, tc[i].attributes); 10357 if (FAILED(hr)) 10358 { 10359 skip("Couldn't initialize test mesh %d. Got %x expected D3D_OK\n", i, hr); 10360 goto cleanup; 10361 } 10362 10363 hr = mesh->lpVtbl->CloneMesh(mesh, tc[i].clone_options, tc[i].new_declaration, 10364 test_context->device, &mesh_clone); 10365 ok(hr == D3D_OK, "CloneMesh test case %d failed. Got %x, expected D3D_OK.\n", i, hr); 10366 10367 hr = mesh_clone->lpVtbl->GetDeclaration(mesh_clone, new_declaration); 10368 ok(hr == D3D_OK, "GetDeclaration test case %d failed. Got %x, expected D3D_OK.\n", i, hr); 10369 /* Check declaration elements */ 10370 for (j = 0; tc[i].new_declaration[j].Stream != 0xFF; j++) 10371 { 10372 ok(memcmp(&tc[i].new_declaration[j], &new_declaration[j], sizeof(*new_declaration)) == 0, 10373 "Test case %d failed. Declaration element %d did not match.\n", i, j); 10374 } 10375 10376 /* Check declaration length */ 10377 exp_new_decl_length = D3DXGetDeclLength(tc[i].new_declaration); 10378 new_decl_length = D3DXGetDeclLength(new_declaration); 10379 ok(new_decl_length == exp_new_decl_length, 10380 "Test case %d failed. Got new declaration length %d, expected %d\n", 10381 i, new_decl_length, exp_new_decl_length); 10382 10383 /* Check declaration size */ 10384 exp_new_decl_size = D3DXGetDeclVertexSize(tc[i].new_declaration, 0); 10385 new_decl_size = D3DXGetDeclVertexSize(new_declaration, 0); 10386 ok(new_decl_size == exp_new_decl_size, 10387 "Test case %d failed. Got new declaration size %d, expected %d\n", 10388 i, new_decl_size, exp_new_decl_size); 10389 10390 /* Check vertex data in cloned mesh */ 10391 hr = mesh_clone->lpVtbl->LockVertexBuffer(mesh_clone, 0, (void**)&vertices); 10392 if (FAILED(hr)) 10393 { 10394 skip("Couldn't lock cloned vertex buffer.\n"); 10395 goto cleanup; 10396 } 10397 for (j = 0; j < tc[i].num_vertices; j++) 10398 { 10399 UINT index = tc[i].exp_vertex_size * j; 10400 check_vertex_components(__LINE__, i, j, &vertices[index], &tc[i].exp_vertices[index], tc[i].new_declaration); 10401 } 10402 hr = mesh_clone->lpVtbl->UnlockVertexBuffer(mesh_clone); 10403 if (FAILED(hr)) 10404 { 10405 skip("Couldn't unlock vertex buffer.\n"); 10406 goto cleanup; 10407 } 10408 vertices = NULL; 10409 mesh->lpVtbl->Release(mesh); 10410 mesh = NULL; 10411 mesh_clone->lpVtbl->Release(mesh_clone); 10412 mesh_clone = NULL; 10413 } 10414 10415 /* The following test shows that it is not possible to share a vertex buffer 10416 * with D3DXMESH_VB_SHARE and change the vertex declaration at the same 10417 * time. It reuses the test data from test 2. 10418 */ 10419 hr = init_test_mesh(tc[2].num_faces, tc[2].num_vertices, 10420 tc[2].create_options, 10421 tc[2].declaration, 10422 test_context->device, &mesh, 10423 tc[2].vertices, tc[2].vertex_size, 10424 tc[2].indices, tc[2].attributes); 10425 if (FAILED(hr)) 10426 { 10427 skip("Couldn't initialize test mesh for D3DXMESH_VB_SHARE case." 10428 " Got %x expected D3D_OK\n", hr); 10429 goto cleanup; 10430 } 10431 10432 hr = mesh->lpVtbl->CloneMesh(mesh, tc[2].create_options | D3DXMESH_VB_SHARE, 10433 tc[2].new_declaration, test_context->device, 10434 &mesh_clone); 10435 ok(hr == D3DERR_INVALIDCALL, "CloneMesh D3DXMESH_VB_SHARE with new" 10436 " declaration. Got %x, expected D3DERR_INVALIDCALL\n", 10437 hr); 10438 mesh->lpVtbl->Release(mesh); 10439 mesh = NULL; 10440 mesh_clone = NULL; 10441 10442 cleanup: 10443 if (vertices) mesh->lpVtbl->UnlockVertexBuffer(mesh); 10444 if (mesh) mesh->lpVtbl->Release(mesh); 10445 if (mesh_clone) mesh_clone->lpVtbl->Release(mesh_clone); 10446 free_test_context(test_context); 10447 } 10448 10449 static void test_valid_mesh(void) 10450 { 10451 HRESULT hr; 10452 struct test_context *test_context = NULL; 10453 UINT i; 10454 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM; 10455 const D3DVERTEXELEMENT9 declaration[] = 10456 { 10457 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 10458 D3DDECL_END() 10459 }; 10460 const unsigned int VERTS_PER_FACE = 3; 10461 /* mesh0 (one face) 10462 * 10463 * 0--1 10464 * | / 10465 * |/ 10466 * 2 10467 */ 10468 const D3DXVECTOR3 vertices0[] = 10469 { 10470 { 0.0f, 3.0f, 0.f}, 10471 { 2.0f, 3.0f, 0.f}, 10472 { 0.0f, 0.0f, 0.f}, 10473 }; 10474 const DWORD indices0[] = {0, 1, 2}; 10475 const unsigned int num_vertices0 = ARRAY_SIZE(vertices0); 10476 const unsigned int num_faces0 = ARRAY_SIZE(indices0) / VERTS_PER_FACE; 10477 const DWORD adjacency0[] = {-1, -1, -1}; 10478 const HRESULT exp_hr0 = D3D_OK; 10479 /* mesh1 (Simple bow-tie) 10480 * 10481 * 0--1 1--3 10482 * | / \ | 10483 * |/ \| 10484 * 2 4 10485 */ 10486 const D3DXVECTOR3 vertices1[] = 10487 { 10488 { 0.0f, 3.0f, 0.f}, 10489 { 2.0f, 3.0f, 0.f}, 10490 { 0.0f, 0.0f, 0.f}, 10491 10492 { 4.0f, 3.0f, 0.f}, 10493 { 4.0f, 0.0f, 0.f}, 10494 }; 10495 const DWORD indices1[] = {0, 1, 2, 1, 3, 4}; 10496 const unsigned int num_vertices1 = ARRAY_SIZE(vertices1); 10497 const unsigned int num_faces1 = ARRAY_SIZE(indices1) / VERTS_PER_FACE; 10498 const DWORD adjacency1[] = {-1, -1, -1, -1, -1, -1}; 10499 const HRESULT exp_hr1 = D3DXERR_INVALIDMESH; 10500 /* Common mesh data */ 10501 ID3DXMesh *mesh = NULL; 10502 UINT vertex_size = sizeof(D3DXVECTOR3); 10503 ID3DXBuffer *errors_and_warnings = NULL; 10504 struct 10505 { 10506 const D3DXVECTOR3 *vertices; 10507 const DWORD *indices; 10508 const UINT num_vertices; 10509 const UINT num_faces; 10510 const DWORD *adjacency; 10511 const HRESULT exp_hr; 10512 } 10513 tc[] = 10514 { 10515 { 10516 vertices0, 10517 indices0, 10518 num_vertices0, 10519 num_faces0, 10520 adjacency0, 10521 exp_hr0, 10522 }, 10523 { 10524 vertices1, 10525 indices1, 10526 num_vertices1, 10527 num_faces1, 10528 adjacency1, 10529 exp_hr1, 10530 }, 10531 }; 10532 10533 test_context = new_test_context(); 10534 if (!test_context) 10535 { 10536 skip("Couldn't create test context\n"); 10537 goto cleanup; 10538 } 10539 10540 for (i = 0; i < ARRAY_SIZE(tc); i++) 10541 { 10542 hr = init_test_mesh(tc[i].num_faces, tc[i].num_vertices, 10543 options, declaration, 10544 test_context->device, &mesh, 10545 tc[i].vertices, vertex_size, 10546 tc[i].indices, NULL); 10547 if (FAILED(hr)) 10548 { 10549 skip("Couldn't initialize test mesh %d. Got %x expected D3D_OK\n", i, hr); 10550 goto cleanup; 10551 } 10552 10553 hr = D3DXValidMesh(mesh, tc[i].adjacency, &errors_and_warnings); 10554 todo_wine ok(hr == tc[i].exp_hr, "D3DXValidMesh test case %d failed. " 10555 "Got %x, expected %x.\n", i, hr, tc[i].exp_hr); 10556 10557 /* Note errors_and_warnings is deliberately not checked because that 10558 * would require copying wast amounts of the text output. */ 10559 if (errors_and_warnings) 10560 { 10561 ID3DXBuffer_Release(errors_and_warnings); 10562 errors_and_warnings = NULL; 10563 } 10564 mesh->lpVtbl->Release(mesh); 10565 mesh = NULL; 10566 } 10567 10568 cleanup: 10569 if (mesh) mesh->lpVtbl->Release(mesh); 10570 free_test_context(test_context); 10571 } 10572 10573 static void test_optimize_vertices(void) 10574 { 10575 HRESULT hr; 10576 DWORD vertex_remap[3]; 10577 const DWORD indices[] = {0, 1, 2}; 10578 const UINT num_faces = 1; 10579 const UINT num_vertices = 3; 10580 10581 hr = D3DXOptimizeVertices(indices, num_faces, 10582 num_vertices, FALSE, 10583 vertex_remap); 10584 ok(hr == D3D_OK, "D3DXOptimizeVertices failed. Got %x, expected D3D_OK.\n", hr); 10585 10586 /* vertex_remap must not be NULL */ 10587 hr = D3DXOptimizeVertices(indices, num_faces, 10588 num_vertices, FALSE, 10589 NULL); 10590 ok(hr == D3DERR_INVALIDCALL, "D3DXOptimizeVertices passed NULL vertex_remap " 10591 "pointer. Got %x, expected D3DERR_INVALIDCALL.\n", hr); 10592 } 10593 10594 static void test_optimize_faces(void) 10595 { 10596 HRESULT hr; 10597 UINT i; 10598 DWORD smallest_face_remap; 10599 /* mesh0 10600 * 10601 * 0--1 10602 * | / 10603 * |/ 10604 * 2 10605 */ 10606 const DWORD indices0[] = {0, 1, 2}; 10607 const UINT num_faces0 = 1; 10608 const UINT num_vertices0 = 3; 10609 const DWORD exp_face_remap0[] = {0}; 10610 /* mesh1 10611 * 10612 * 0--1 3 10613 * | / /| 10614 * |/ / | 10615 * 2 5--4 10616 */ 10617 const DWORD indices1[] = {0, 1, 2, 3, 4, 5}; 10618 const UINT num_faces1 = 2; 10619 const UINT num_vertices1 = 6; 10620 const DWORD exp_face_remap1[] = {1, 0}; 10621 /* mesh2 10622 * 10623 * 0--1 10624 * | /| 10625 * |/ | 10626 * 2--3 10627 */ 10628 const DWORD indices2[] = {0, 1, 2, 1, 3, 2}; 10629 const UINT num_faces2 = 2; 10630 const UINT num_vertices2 = 4; 10631 const DWORD exp_face_remap2[] = {1, 0}; 10632 /* mesh3 10633 * 10634 * 0--1 10635 * | /| 10636 * |/ | 10637 * 2--3 10638 * | /| 10639 * |/ | 10640 * 4--5 10641 */ 10642 const DWORD indices3[] = {0, 1, 2, 1, 3, 2, 2, 3, 4, 3, 4, 5}; 10643 const UINT num_faces3 = 4; 10644 const UINT num_vertices3 = 6; 10645 const DWORD exp_face_remap3[] = {3, 2, 1, 0}; 10646 /* mesh4 10647 * 10648 * 0--1 10649 * | /| 10650 * |/ | 10651 * 2--3 10652 * | /| 10653 * |/ | 10654 * 4--5 10655 */ 10656 const WORD indices4[] = {0, 1, 2, 1, 3, 2, 2, 3, 4, 3, 4, 5}; 10657 const UINT num_faces4 = 4; 10658 const UINT num_vertices4 = 6; 10659 const DWORD exp_face_remap4[] = {3, 2, 1, 0}; 10660 /* Test cases are stored in the tc array */ 10661 struct 10662 { 10663 const VOID *indices; 10664 const UINT num_faces; 10665 const UINT num_vertices; 10666 const BOOL indices_are_32bit; 10667 const DWORD *exp_face_remap; 10668 } 10669 tc[] = 10670 { 10671 { 10672 indices0, 10673 num_faces0, 10674 num_vertices0, 10675 TRUE, 10676 exp_face_remap0 10677 }, 10678 { 10679 indices1, 10680 num_faces1, 10681 num_vertices1, 10682 TRUE, 10683 exp_face_remap1 10684 }, 10685 { 10686 indices2, 10687 num_faces2, 10688 num_vertices2, 10689 TRUE, 10690 exp_face_remap2 10691 }, 10692 { 10693 indices3, 10694 num_faces3, 10695 num_vertices3, 10696 TRUE, 10697 exp_face_remap3 10698 }, 10699 { 10700 indices4, 10701 num_faces4, 10702 num_vertices4, 10703 FALSE, 10704 exp_face_remap4 10705 }, 10706 }; 10707 10708 /* Go through all test cases */ 10709 for (i = 0; i < ARRAY_SIZE(tc); i++) 10710 { 10711 DWORD j; 10712 DWORD *face_remap; 10713 face_remap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 10714 tc[i].num_faces*sizeof(*face_remap)); 10715 10716 hr = D3DXOptimizeFaces(tc[i].indices, tc[i].num_faces, 10717 tc[i].num_vertices, tc[i].indices_are_32bit, 10718 face_remap); 10719 ok(hr == D3D_OK, "D3DXOptimizeFaces test case %d failed. " 10720 "Got %x, expected D3D_OK.\n", i, hr); 10721 10722 /* Compare face remap with expected face remap */ 10723 for (j = 0; j < tc[i].num_faces; j++) 10724 { 10725 ok(tc[i].exp_face_remap[j] == face_remap[j], 10726 "Test case %d: Got face %d at %d, expected %d\n", i, 10727 face_remap[j], j, tc[i].exp_face_remap[j]); 10728 } 10729 10730 HeapFree(GetProcessHeap(), 0, face_remap); 10731 } 10732 10733 /* face_remap must not be NULL */ 10734 hr = D3DXOptimizeFaces(tc[0].indices, tc[0].num_faces, 10735 tc[0].num_vertices, tc[0].indices_are_32bit, 10736 NULL); 10737 ok(hr == D3DERR_INVALIDCALL, "D3DXOptimizeFaces passed NULL face_remap " 10738 "pointer. Got %x, expected D3DERR_INVALIDCALL.\n", hr); 10739 10740 /* Number of faces must be smaller than 2^15 */ 10741 hr = D3DXOptimizeFaces(tc[0].indices, 2 << 15, 10742 tc[0].num_vertices, FALSE, 10743 &smallest_face_remap); 10744 ok(hr == D3DERR_INVALIDCALL, "D3DXOptimizeFaces should not accept 2^15 " 10745 "faces when using 16-bit indices. Got %x, expected D3DERR_INVALIDCALL.\n", hr); 10746 } 10747 10748 static HRESULT clear_normals(ID3DXMesh *mesh) 10749 { 10750 HRESULT hr; 10751 BYTE *vertices; 10752 size_t normal_size; 10753 DWORD i, num_vertices, vertex_stride; 10754 const D3DXVECTOR4 normal = {NAN, NAN, NAN, NAN}; 10755 D3DVERTEXELEMENT9 *normal_declaration = NULL; 10756 D3DVERTEXELEMENT9 declaration[MAX_FVF_DECL_SIZE] = {D3DDECL_END()}; 10757 10758 if (FAILED(hr = mesh->lpVtbl->GetDeclaration(mesh, declaration))) 10759 return hr; 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 return D3DERR_INVALIDCALL; 10772 10773 if (normal_declaration->Type == D3DDECLTYPE_FLOAT3) 10774 { 10775 normal_size = sizeof(D3DXVECTOR3); 10776 } 10777 else if (normal_declaration->Type == D3DDECLTYPE_FLOAT4) 10778 { 10779 normal_size = sizeof(D3DXVECTOR4); 10780 } 10781 else 10782 { 10783 trace("Cannot clear normals\n"); 10784 return E_NOTIMPL; 10785 } 10786 10787 num_vertices = mesh->lpVtbl->GetNumVertices(mesh); 10788 vertex_stride = mesh->lpVtbl->GetNumBytesPerVertex(mesh); 10789 10790 if (FAILED(hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, (void **)&vertices))) 10791 return hr; 10792 10793 vertices += normal_declaration->Offset; 10794 10795 for (i = 0; i < num_vertices; i++, vertices += vertex_stride) 10796 memcpy(vertices, &normal, normal_size); 10797 10798 return mesh->lpVtbl->UnlockVertexBuffer(mesh); 10799 } 10800 10801 static void compare_normals(unsigned int line, const char *test_name, 10802 ID3DXMesh *mesh, const D3DXVECTOR3 *normals, unsigned int num_normals) 10803 { 10804 unsigned int i; 10805 BYTE *vertices; 10806 DWORD num_vertices, vertex_stride; 10807 D3DVERTEXELEMENT9 *normal_declaration = NULL; 10808 D3DVERTEXELEMENT9 declaration[MAX_FVF_DECL_SIZE] = {D3DDECL_END()}; 10809 10810 if (FAILED(mesh->lpVtbl->GetDeclaration(mesh, declaration))) 10811 { 10812 ok_(__FILE__, line)(0, "%s: Failed to get declaration\n", test_name); 10813 return; 10814 } 10815 10816 for (i = 0; declaration[i].Stream != 0xff; i++) 10817 { 10818 if (declaration[i].Usage == D3DDECLUSAGE_NORMAL && !declaration[i].UsageIndex) 10819 { 10820 normal_declaration = &declaration[i]; 10821 break; 10822 } 10823 } 10824 10825 if (!normal_declaration) 10826 { 10827 ok_(__FILE__, line)(0, "%s: Mesh has no normals\n", test_name); 10828 return; 10829 } 10830 10831 if (normal_declaration->Type != D3DDECLTYPE_FLOAT3 && normal_declaration->Type != D3DDECLTYPE_FLOAT4) 10832 { 10833 ok_(__FILE__, line)(0, "%s: Mesh has invalid normals type\n", test_name); 10834 return; 10835 } 10836 10837 num_vertices = mesh->lpVtbl->GetNumVertices(mesh); 10838 vertex_stride = mesh->lpVtbl->GetNumBytesPerVertex(mesh); 10839 10840 ok_(__FILE__, line)(num_vertices == num_normals, "%s: Expected %u vertices, got %u\n", test_name, 10841 num_normals, num_vertices); 10842 10843 if (FAILED(mesh->lpVtbl->LockVertexBuffer(mesh, 0, (void **)&vertices))) 10844 { 10845 ok_(__FILE__, line)(0, "%s: Failed to compare normals\n", test_name); 10846 return; 10847 } 10848 10849 vertices += normal_declaration->Offset; 10850 10851 for (i = 0; i < min(num_vertices, num_normals); i++, vertices += vertex_stride) 10852 { 10853 if (normal_declaration->Type == D3DDECLTYPE_FLOAT3) 10854 { 10855 const D3DXVECTOR3 *n = (D3DXVECTOR3 *)vertices; 10856 ok_(__FILE__, line)(compare_vec3(*n, normals[i]), 10857 "%s: normal %2u, expected (%f, %f, %f), got (%f, %f, %f)\n", 10858 test_name, i, normals[i].x, normals[i].y, normals[i].z, n->x, n->y, n->z); 10859 } 10860 else 10861 { 10862 const D3DXVECTOR4 *n = (D3DXVECTOR4 *)vertices; 10863 const D3DXVECTOR4 normal = {normals[i].x, normals[i].y, normals[i].z, 1.0f}; 10864 ok_(__FILE__, line)(compare_vec4(*n, normal), 10865 "%s: normal %2u, expected (%f, %f, %f, %f), got (%f, %f, %f, %f)\n", 10866 test_name, i, normals[i].x, normals[i].y, normals[i].z, 1.0f, 10867 n->x, n->y, n->z, n->w); 10868 } 10869 } 10870 10871 mesh->lpVtbl->UnlockVertexBuffer(mesh); 10872 } 10873 10874 static HRESULT compute_normals_D3DXComputeNormals(ID3DXMesh *mesh, const DWORD *adjacency) 10875 { 10876 return D3DXComputeNormals((ID3DXBaseMesh *)mesh, adjacency); 10877 } 10878 10879 static HRESULT compute_normals_D3DXComputeTangentFrameEx(ID3DXMesh *mesh, const DWORD *adjacency) 10880 { 10881 return D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, 10882 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS, 10883 adjacency, -1.01f, -0.01f, -1.01f, NULL, NULL); 10884 } 10885 10886 static void test_compute_normals(void) 10887 { 10888 HRESULT hr; 10889 ULONG refcount; 10890 ID3DXMesh *mesh, *cloned_mesh; 10891 ID3DXBuffer *adjacency; 10892 IDirect3DDevice9 *device; 10893 struct test_context *test_context; 10894 unsigned int i; 10895 10896 static const struct compute_normals_func 10897 { 10898 const char *name; 10899 HRESULT (*apply)(ID3DXMesh *mesh, const DWORD *adjacency); 10900 } 10901 compute_normals_funcs[] = 10902 { 10903 {"D3DXComputeNormals", compute_normals_D3DXComputeNormals }, 10904 {"D3DXComputeTangentFrameEx", compute_normals_D3DXComputeTangentFrameEx} 10905 }; 10906 10907 static const D3DXVECTOR3 box_normals[24] = 10908 { 10909 {-1.0f, 0.0f, 0.0f}, {-1.0f, 0.0f, 0.0f}, {-1.0f, 0.0f, 0.0f}, {-1.0f, 0.0f, 0.0f}, 10910 { 0.0f, 1.0f, 0.0f}, { 0.0f, 1.0f, 0.0f}, { 0.0f, 1.0f, 0.0f}, { 0.0f, 1.0f, 0.0f}, 10911 { 1.0f, 0.0f, 0.0f}, { 1.0f, 0.0f, 0.0f}, { 1.0f, 0.0f, 0.0f}, { 1.0f, 0.0f, 0.0f}, 10912 { 0.0f,-1.0f, 0.0f}, { 0.0f,-1.0f, 0.0f}, { 0.0f,-1.0f, 0.0f}, { 0.0f,-1.0f, 0.0f}, 10913 { 0.0f, 0.0f, 1.0f}, { 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}, { 0.0f, 0.0f,-1.0f} 10915 }; 10916 const float box_normal_component = 1.0f / sqrtf(3.0f); 10917 const D3DXVECTOR3 box_normals_adjacency[24] = 10918 { 10919 {-box_normal_component, -box_normal_component, -box_normal_component}, 10920 {-box_normal_component, -box_normal_component, box_normal_component}, 10921 {-box_normal_component, box_normal_component, box_normal_component}, 10922 {-box_normal_component, box_normal_component, -box_normal_component}, 10923 {-box_normal_component, box_normal_component, -box_normal_component}, 10924 {-box_normal_component, box_normal_component, box_normal_component}, 10925 { box_normal_component, box_normal_component, box_normal_component}, 10926 { box_normal_component, box_normal_component, -box_normal_component}, 10927 { box_normal_component, box_normal_component, -box_normal_component}, 10928 { box_normal_component, box_normal_component, box_normal_component}, 10929 { box_normal_component, -box_normal_component, box_normal_component}, 10930 { box_normal_component, -box_normal_component, -box_normal_component}, 10931 {-box_normal_component, -box_normal_component, box_normal_component}, 10932 {-box_normal_component, -box_normal_component, -box_normal_component}, 10933 { box_normal_component, -box_normal_component, -box_normal_component}, 10934 { box_normal_component, -box_normal_component, box_normal_component}, 10935 {-box_normal_component, -box_normal_component, box_normal_component}, 10936 { box_normal_component, -box_normal_component, box_normal_component}, 10937 { box_normal_component, box_normal_component, box_normal_component}, 10938 {-box_normal_component, box_normal_component, box_normal_component}, 10939 {-box_normal_component, -box_normal_component, -box_normal_component}, 10940 {-box_normal_component, box_normal_component, -box_normal_component}, 10941 { box_normal_component, box_normal_component, -box_normal_component}, 10942 { box_normal_component, -box_normal_component, -box_normal_component} 10943 }; 10944 static const D3DXVECTOR3 box_normals_adjacency_area[24] = 10945 { 10946 {-0.666667f, -0.333333f, -0.666667f}, {-0.333333f, -0.666667f, 0.666667f}, 10947 {-0.816496f, 0.408248f, 0.408248f}, {-0.408248f, 0.816496f, -0.408248f}, 10948 {-0.408248f, 0.816496f, -0.408248f}, {-0.816496f, 0.408248f, 0.408248f}, 10949 { 0.333333f, 0.666667f, 0.666667f}, { 0.666667f, 0.333333f, -0.666667f}, 10950 { 0.666667f, 0.333333f, -0.666667f}, { 0.333333f, 0.666667f, 0.666667f}, 10951 { 0.816496f, -0.408248f, 0.408248f}, { 0.408248f, -0.816496f, -0.408248f}, 10952 {-0.333333f, -0.666667f, 0.666667f}, {-0.666667f, -0.333333f, -0.666667f}, 10953 { 0.408248f, -0.816496f, -0.408248f}, { 0.816496f, -0.408248f, 0.408248f}, 10954 {-0.333333f, -0.666667f, 0.666667f}, { 0.816497f, -0.408248f, 0.408248f}, 10955 { 0.333333f, 0.666667f, 0.666667f}, {-0.816497f, 0.408248f, 0.408248f}, 10956 {-0.666667f, -0.333333f, -0.666667f}, {-0.408248f, 0.816497f, -0.408248f}, 10957 { 0.666667f, 0.333333f, -0.666667f}, { 0.408248f, -0.816496f, -0.408248f} 10958 }; 10959 static const D3DXVECTOR3 box_normals_position1f[24] = {{0}}; 10960 static const D3DXVECTOR3 box_normals_position2f[24] = 10961 { 10962 {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f}, 10963 {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, 1.0f}, 10964 {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, -1.0f}, 10965 {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}, 10966 {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, -1.0f}, 10967 {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f}, 10968 {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}, 10969 {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, -1.0f} 10970 }; 10971 10972 static const D3DXVECTOR3 sphere_normals[22] = 10973 { 10974 { 0.000000f, -0.000000f, 1.000000f}, { 0.000000f, 0.582244f, 0.813014f}, 10975 { 0.582244f, -0.000000f, 0.813014f}, {-0.000000f, -0.582244f, 0.813014f}, 10976 {-0.582244f, 0.000000f, 0.813014f}, {-0.000000f, 0.890608f, 0.454772f}, 10977 { 0.890608f, 0.000000f, 0.454772f}, { 0.000000f, -0.890608f, 0.454772f}, 10978 {-0.890608f, -0.000000f, 0.454772f}, { 0.000000f, 1.000000f, -0.000000f}, 10979 { 1.000000f, -0.000000f, -0.000000f}, {-0.000000f, -1.000000f, -0.000000f}, 10980 {-1.000000f, 0.000000f, -0.000000f}, { 0.000000f, 0.890608f, -0.454773f}, 10981 { 0.890608f, -0.000000f, -0.454772f}, {-0.000000f, -0.890608f, -0.454773f}, 10982 {-0.890608f, 0.000000f, -0.454773f}, { 0.000000f, 0.582244f, -0.813015f}, 10983 { 0.582244f, -0.000000f, -0.813015f}, { 0.000000f, -0.582244f, -0.813015f}, 10984 {-0.582243f, 0.000000f, -0.813015f}, { 0.000000f, 0.000000f, -1.000000f} 10985 }; 10986 static const D3DXVECTOR3 sphere_normals_area[22] = 10987 { 10988 { 0.000000f, -0.000000f, 1.000000f}, {-0.215311f, 0.554931f, 0.803550f}, 10989 { 0.554931f, 0.215311f, 0.803550f}, { 0.215311f, -0.554931f, 0.803550f}, 10990 {-0.554931f, -0.215311f, 0.803550f}, {-0.126638f, 0.872121f, 0.472618f}, 10991 { 0.872121f, 0.126638f, 0.472618f}, { 0.126638f, -0.872121f, 0.472618f}, 10992 {-0.872121f, -0.126637f, 0.472618f}, { 0.000000f, 1.000000f, -0.000000f}, 10993 { 1.000000f, -0.000000f, -0.000000f}, {-0.000000f, -1.000000f, -0.000000f}, 10994 {-1.000000f, 0.000000f, -0.000000f}, { 0.126638f, 0.872121f, -0.472618f}, 10995 { 0.872121f, -0.126638f, -0.472618f}, {-0.126638f, -0.872121f, -0.472618f}, 10996 {-0.872121f, 0.126638f, -0.472618f}, { 0.215311f, 0.554931f, -0.803550f}, 10997 { 0.554931f, -0.215311f, -0.803550f}, {-0.215311f, -0.554931f, -0.803550f}, 10998 {-0.554931f, 0.215311f, -0.803550f}, { 0.000000f, 0.000000f, -1.000000f} 10999 }; 11000 static const D3DXVECTOR3 sphere_normals_equal[22] = 11001 { 11002 { 0.000000f, -0.000000f, 1.000000f}, {-0.134974f, 0.522078f, 0.842150f}, 11003 { 0.522078f, 0.134974f, 0.842150f}, { 0.134974f, -0.522078f, 0.842150f}, 11004 {-0.522078f, -0.134974f, 0.842150f}, {-0.026367f, 0.857121f, 0.514440f}, 11005 { 0.857121f, 0.026367f, 0.514440f}, { 0.026367f, -0.857121f, 0.514440f}, 11006 {-0.857121f, -0.026367f, 0.514440f}, { 0.000000f, 1.000000f, -0.000000f}, 11007 { 1.000000f, -0.000000f, -0.000000f}, {-0.000000f, -1.000000f, -0.000000f}, 11008 {-1.000000f, 0.000000f, -0.000000f}, { 0.026367f, 0.857121f, -0.514440f}, 11009 { 0.857121f, -0.026367f, -0.514440f}, {-0.026367f, -0.857121f, -0.514440f}, 11010 {-0.857121f, 0.026367f, -0.514440f}, { 0.134975f, 0.522078f, -0.842150f}, 11011 { 0.522078f, -0.134975f, -0.842150f}, {-0.134974f, -0.522078f, -0.842150f}, 11012 {-0.522078f, 0.134974f, -0.842150f}, { 0.000000f, 0.000000f, -1.000000f} 11013 }; 11014 11015 static const D3DVERTEXELEMENT9 position3f_normal1f_declaration[] = 11016 { 11017 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 11018 {0, sizeof(D3DXVECTOR3), D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 11019 D3DDECL_END() 11020 }; 11021 static const D3DVERTEXELEMENT9 position3f_normal2f_declaration[] = 11022 { 11023 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 11024 {0, sizeof(D3DXVECTOR3), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 11025 D3DDECL_END() 11026 }; 11027 static const D3DVERTEXELEMENT9 normal4f_position3f_declaration[] = 11028 { 11029 {0, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 11030 {0, sizeof(D3DXVECTOR4), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 11031 D3DDECL_END() 11032 }; 11033 static const D3DVERTEXELEMENT9 position1f_normal3f_declaration[] = 11034 { 11035 {0, 0, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 11036 {0, sizeof(float), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 11037 D3DDECL_END() 11038 }; 11039 static const D3DVERTEXELEMENT9 position2f_normal3f_declaration[] = 11040 { 11041 {0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 11042 {0, sizeof(D3DXVECTOR2), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 11043 D3DDECL_END() 11044 }; 11045 static const D3DVERTEXELEMENT9 position4f_normal3f_declaration[] = 11046 { 11047 {0, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 11048 {0, sizeof(D3DXVECTOR4), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 11049 D3DDECL_END() 11050 }; 11051 11052 for (i = 0; i < ARRAY_SIZE(compute_normals_funcs); i++) 11053 { 11054 hr = compute_normals_funcs[i].apply(NULL, NULL); 11055 ok(hr == D3DERR_INVALIDCALL, "%s returned %#x, expected D3DERR_INVALIDCALL\n", compute_normals_funcs[i].name, hr); 11056 } 11057 11058 if (!(test_context = new_test_context())) 11059 { 11060 skip("Couldn't create test context\n"); 11061 return; 11062 } 11063 device = test_context->device; 11064 11065 hr = D3DXCreateBox(device, 1.0f, 1.0f, 1.0f, &mesh, &adjacency); 11066 ok(SUCCEEDED(hr), "D3DXCreateBox failed %#x\n", hr); 11067 11068 /* Check wrong input */ 11069 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, 11070 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE, NULL, -1.01f, -0.01f, -1.01f, NULL, NULL); 11071 todo_wine ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr); 11072 11073 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DDECLUSAGE_NORMAL, 0, 11074 D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_BY_AREA | D3DXTANGENT_WEIGHT_EQUAL, 11075 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL); 11076 ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr); 11077 11078 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, 11079 D3DDECLUSAGE_NORMAL, 0, 0, NULL, -1.01f, -0.01f, -1.01f, NULL, NULL); 11080 todo_wine ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr); 11081 11082 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, 11083 D3DDECLUSAGE_NORMAL, 1, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS, 11084 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL); 11085 ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr); 11086 11087 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, 11088 D3DX_DEFAULT, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS, 11089 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL); 11090 ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr); 11091 11092 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, 11093 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_CALCULATE_NORMALS, 11094 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL); 11095 todo_wine ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr); 11096 11097 for (i = 0; i < ARRAY_SIZE(compute_normals_funcs); i++) 11098 { 11099 const struct compute_normals_func *func = &compute_normals_funcs[i]; 11100 11101 /* Mesh without normals */ 11102 hr = mesh->lpVtbl->CloneMeshFVF(mesh, 0, D3DFVF_XYZ, device, &cloned_mesh); 11103 ok(SUCCEEDED(hr), "CloneMeshFVF failed %#x\n", hr); 11104 11105 hr = func->apply(cloned_mesh, NULL); 11106 ok(hr == D3DERR_INVALIDCALL, "%s returned %#x, expected D3DERR_INVALIDCALL\n", func->name, hr); 11107 11108 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh); 11109 ok(!refcount, "Mesh has %u references left\n", refcount); 11110 11111 /* Mesh without positions */ 11112 hr = mesh->lpVtbl->CloneMeshFVF(mesh, 0, D3DFVF_NORMAL, device, &cloned_mesh); 11113 ok(SUCCEEDED(hr), "CloneMeshFVF failed %#x\n", hr); 11114 11115 hr = func->apply(cloned_mesh, NULL); 11116 ok(hr == D3DERR_INVALIDCALL, "%s returned %#x, expected D3DERR_INVALIDCALL\n", func->name, hr); 11117 11118 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh); 11119 ok(!refcount, "Mesh has %u references left\n", refcount); 11120 11121 /* Mesh with D3DDECLTYPE_FLOAT1 normals */ 11122 hr = mesh->lpVtbl->CloneMesh(mesh, 0, position3f_normal1f_declaration, device, &cloned_mesh); 11123 ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr); 11124 11125 hr = func->apply(cloned_mesh, NULL); 11126 ok(hr == D3DERR_INVALIDCALL, "%s returned %#x, expected D3DERR_INVALIDCALL\n", func->name, hr); 11127 11128 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh); 11129 ok(!refcount, "Mesh has %u references left\n", refcount); 11130 11131 /* Mesh with D3DDECLTYPE_FLOAT2 normals */ 11132 hr = mesh->lpVtbl->CloneMesh(mesh, 0, position3f_normal2f_declaration, device, &cloned_mesh); 11133 ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr); 11134 11135 hr = func->apply(cloned_mesh, NULL); 11136 ok(hr == D3DERR_INVALIDCALL, "%s returned %#x, expected D3DERR_INVALIDCALL\n", func->name, hr); 11137 11138 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh); 11139 ok(!refcount, "Mesh has %u references left\n", refcount); 11140 11141 /* Mesh without adjacency data */ 11142 hr = clear_normals(mesh); 11143 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr); 11144 11145 hr = func->apply(mesh, NULL); 11146 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr); 11147 11148 compare_normals(__LINE__, func->name, mesh, box_normals, ARRAY_SIZE(box_normals)); 11149 11150 /* Mesh with adjacency data */ 11151 hr = clear_normals(mesh); 11152 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr); 11153 11154 hr = func->apply(mesh, ID3DXBuffer_GetBufferPointer(adjacency)); 11155 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr); 11156 11157 compare_normals(__LINE__, func->name, mesh, box_normals_adjacency, ARRAY_SIZE(box_normals_adjacency)); 11158 11159 /* Mesh with custom vertex format, D3DDECLTYPE_FLOAT4 normals and adjacency */ 11160 hr = mesh->lpVtbl->CloneMesh(mesh, 0, normal4f_position3f_declaration, device, &cloned_mesh); 11161 ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr); 11162 11163 hr = clear_normals(cloned_mesh); 11164 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr); 11165 11166 hr = func->apply(cloned_mesh, ID3DXBuffer_GetBufferPointer(adjacency)); 11167 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr); 11168 11169 compare_normals(__LINE__, func->name, cloned_mesh, box_normals_adjacency, ARRAY_SIZE(box_normals_adjacency)); 11170 11171 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh); 11172 ok(!refcount, "Mesh has %u references left\n", refcount); 11173 11174 /* Mesh with D3DDECLTYPE_FLOAT1 positions and D3DDECLTYPE_FLOAT3 normals */ 11175 hr = mesh->lpVtbl->CloneMesh(mesh, 0, position1f_normal3f_declaration, device, &cloned_mesh); 11176 ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr); 11177 11178 hr = clear_normals(cloned_mesh); 11179 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr); 11180 11181 hr = func->apply(cloned_mesh, ID3DXBuffer_GetBufferPointer(adjacency)); 11182 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr); 11183 11184 compare_normals(__LINE__, func->name, cloned_mesh, box_normals_position1f, ARRAY_SIZE(box_normals_position1f)); 11185 11186 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh); 11187 ok(!refcount, "Mesh has %u references left\n", refcount); 11188 11189 /* Mesh with D3DDECLTYPE_FLOAT2 positions and D3DDECLTYPE_FLOAT3 normals */ 11190 hr = mesh->lpVtbl->CloneMesh(mesh, 0, position2f_normal3f_declaration, device, &cloned_mesh); 11191 ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr); 11192 11193 hr = clear_normals(cloned_mesh); 11194 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr); 11195 11196 hr = func->apply(cloned_mesh, ID3DXBuffer_GetBufferPointer(adjacency)); 11197 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr); 11198 11199 compare_normals(__LINE__, func->name, cloned_mesh, box_normals_position2f, ARRAY_SIZE(box_normals_position2f)); 11200 11201 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh); 11202 ok(!refcount, "Mesh has %u references left\n", refcount); 11203 11204 /* Mesh with D3DDECLTYPE_FLOAT4 positions and D3DDECLTYPE_FLOAT3 normals */ 11205 hr = mesh->lpVtbl->CloneMesh(mesh, 0, position4f_normal3f_declaration, device, &cloned_mesh); 11206 ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr); 11207 11208 hr = clear_normals(cloned_mesh); 11209 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr); 11210 11211 hr = func->apply(cloned_mesh, ID3DXBuffer_GetBufferPointer(adjacency)); 11212 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr); 11213 11214 compare_normals(__LINE__, func->name, cloned_mesh, box_normals_adjacency, ARRAY_SIZE(box_normals_adjacency)); 11215 11216 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh); 11217 ok(!refcount, "Mesh has %u references left\n", refcount); 11218 } 11219 11220 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, 11221 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_BY_AREA, 11222 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL); 11223 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr); 11224 11225 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, box_normals, ARRAY_SIZE(box_normals)); 11226 11227 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, 11228 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_BY_AREA, 11229 ID3DXBuffer_GetBufferPointer(adjacency), -1.01f, -0.01f, -1.01f, NULL, NULL); 11230 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr); 11231 11232 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, box_normals_adjacency_area, ARRAY_SIZE(box_normals_adjacency_area)); 11233 11234 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, 11235 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_EQUAL, 11236 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL); 11237 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr); 11238 11239 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, box_normals, ARRAY_SIZE(box_normals)); 11240 11241 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, 11242 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_EQUAL, 11243 ID3DXBuffer_GetBufferPointer(adjacency), -1.01f, -0.01f, -1.01f, NULL, NULL); 11244 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr); 11245 11246 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, box_normals_adjacency_area, ARRAY_SIZE(box_normals_adjacency_area)); 11247 11248 refcount = mesh->lpVtbl->Release(mesh); 11249 ok(!refcount, "Mesh has %u references left\n", refcount); 11250 refcount = ID3DXBuffer_Release(adjacency); 11251 ok(!refcount, "Buffer has %u references left\n", refcount); 11252 11253 hr = D3DXCreateSphere(device, 1.0f, 4, 6, &mesh, &adjacency); 11254 ok(SUCCEEDED(hr), "D3DXCreateSphere failed %#x\n", hr); 11255 11256 for (i = 0; i < ARRAY_SIZE(compute_normals_funcs); i++) 11257 { 11258 const struct compute_normals_func *func = &compute_normals_funcs[i]; 11259 11260 /* Sphere without adjacency data */ 11261 hr = clear_normals(mesh); 11262 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr); 11263 11264 hr = func->apply(mesh, NULL); 11265 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr); 11266 11267 compare_normals(__LINE__, func->name, mesh, sphere_normals, ARRAY_SIZE(sphere_normals)); 11268 11269 /* Sphere with adjacency data */ 11270 hr = clear_normals(mesh); 11271 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr); 11272 11273 hr = func->apply(mesh, ID3DXBuffer_GetBufferPointer(adjacency)); 11274 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr); 11275 11276 compare_normals(__LINE__, func->name, mesh, sphere_normals, ARRAY_SIZE(sphere_normals)); 11277 } 11278 11279 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, 11280 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_BY_AREA, 11281 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL); 11282 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr); 11283 11284 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, sphere_normals_area, ARRAY_SIZE(sphere_normals_area)); 11285 11286 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, 11287 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_BY_AREA, 11288 ID3DXBuffer_GetBufferPointer(adjacency), -1.01f, -0.01f, -1.01f, NULL, NULL); 11289 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr); 11290 11291 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, sphere_normals_area, ARRAY_SIZE(sphere_normals_area)); 11292 11293 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, 11294 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_EQUAL, 11295 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL); 11296 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr); 11297 11298 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, sphere_normals_equal, ARRAY_SIZE(sphere_normals_equal)); 11299 11300 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, 11301 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_EQUAL, 11302 ID3DXBuffer_GetBufferPointer(adjacency), -1.01f, -0.01f, -1.01f, NULL, NULL); 11303 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr); 11304 11305 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, sphere_normals_equal, ARRAY_SIZE(sphere_normals_equal)); 11306 11307 refcount = mesh->lpVtbl->Release(mesh); 11308 ok(!refcount, "Mesh has %u references left\n", refcount); 11309 refcount = ID3DXBuffer_Release(adjacency); 11310 ok(!refcount, "Buffer has %u references left\n", refcount); 11311 11312 free_test_context(test_context); 11313 } 11314 11315 static void D3DXCreateAnimationControllerTest(void) 11316 { 11317 HRESULT hr; 11318 ID3DXAnimationController *animation; 11319 UINT value; 11320 11321 hr = D3DXCreateAnimationController(0, 0, 0, 0, NULL); 11322 ok(hr == D3D_OK, "Got unexpected hr returned %#x.\n", hr); 11323 11324 animation = (void*)0xdeadbeef; 11325 hr = D3DXCreateAnimationController(0, 1, 1, 1, &animation); 11326 ok(hr == D3D_OK, "Got unexpected hr returned %#x.\n", hr); 11327 ok(animation == (void*)0xdeadbeef, "Got unexpected animation %p.\n", animation); 11328 11329 animation = (void*)0xdeadbeef; 11330 hr = D3DXCreateAnimationController(1, 0, 1, 1, &animation); 11331 ok(hr == D3D_OK, "Got unexpected hr returned %#x.\n", hr); 11332 ok(animation == (void*)0xdeadbeef, "Got unexpected animation %p.\n", animation); 11333 11334 animation = (void*)0xdeadbeef; 11335 hr = D3DXCreateAnimationController(1, 1, 0, 1, &animation); 11336 ok(hr == D3D_OK, "Got unexpected hr returned %#x.\n", hr); 11337 ok(animation == (void*)0xdeadbeef, "Got unexpected animation %p.\n", animation); 11338 11339 animation = (void*)0xdeadbeef; 11340 hr = D3DXCreateAnimationController(1, 1, 1, 0, &animation); 11341 ok(hr == D3D_OK, "Got unexpected hr returned %#x.\n", hr); 11342 ok(animation == (void*)0xdeadbeef, "Got unexpected animation %p.\n", animation); 11343 11344 hr = D3DXCreateAnimationController(1, 1, 1, 1, &animation); 11345 ok(hr == D3D_OK, "Got unexpected hr returned %#x.\n", hr); 11346 11347 value = animation->lpVtbl->GetMaxNumAnimationOutputs(animation); 11348 ok(value == 1, "Got unexpected value %u.\n", value); 11349 11350 value = animation->lpVtbl->GetMaxNumAnimationSets(animation); 11351 ok(value == 1, "Got unexpected value %u.\n", value); 11352 11353 value = animation->lpVtbl->GetMaxNumTracks(animation); 11354 ok(value == 1, "Got unexpected value %u.\n", value); 11355 11356 value = animation->lpVtbl->GetMaxNumEvents(animation); 11357 ok(value == 1, "Got unexpected value %u.\n", value); 11358 11359 animation->lpVtbl->Release(animation); 11360 11361 hr = D3DXCreateAnimationController(100, 101, 102, 103, &animation); 11362 ok(hr == D3D_OK, "Got unexpected hr returned %#x.\n", hr); 11363 11364 value = animation->lpVtbl->GetMaxNumAnimationOutputs(animation); 11365 ok(value == 100, "Got unexpected value %u.\n", value); 11366 11367 value = animation->lpVtbl->GetMaxNumAnimationSets(animation); 11368 ok(value == 101, "Got unexpected value %u.\n", value); 11369 11370 value = animation->lpVtbl->GetMaxNumTracks(animation); 11371 ok(value == 102, "Got unexpected value %u.\n", value); 11372 11373 value = animation->lpVtbl->GetMaxNumEvents(animation); 11374 ok(value == 103, "Got unexpected value %u.\n", value); 11375 11376 animation->lpVtbl->Release(animation); 11377 } 11378 11379 static void test_D3DXFrameFind(void) 11380 { 11381 static char n1[] = "name1"; 11382 static char n2[] = "name2"; 11383 static char n3[] = "name3"; 11384 static char n4[] = "name4"; 11385 static char n5[] = "name5"; 11386 static char n6[] = "name6"; 11387 static char N1[] = "Name1"; 11388 D3DXFRAME root, sibling, sibling2, child, *ret; 11389 D3DXFRAME child2, child3; 11390 11391 ret = D3DXFrameFind(NULL, NULL); 11392 ok(ret == NULL, "Unexpected frame, %p.\n", ret); 11393 11394 ret = D3DXFrameFind(NULL, "test"); 11395 ok(ret == NULL, "Unexpected frame, %p.\n", ret); 11396 11397 memset(&root, 0, sizeof(root)); 11398 11399 ret = D3DXFrameFind(&root, NULL); 11400 ok(ret == &root, "Unexpected frame, %p.\n", ret); 11401 11402 root.Name = n1; 11403 ret = D3DXFrameFind(&root, NULL); 11404 ok(ret == NULL, "Unexpected frame, %p.\n", ret); 11405 11406 ret = D3DXFrameFind(&root, n1); 11407 ok(ret == &root, "Unexpected frame, %p.\n", ret); 11408 11409 ret = D3DXFrameFind(&root, N1); 11410 ok(ret == NULL, "Unexpected frame, %p.\n", ret); 11411 11412 /* Test siblings order traversal. */ 11413 memset(&sibling, 0, sizeof(sibling)); 11414 sibling.Name = n2; 11415 root.pFrameSibling = &sibling; 11416 ret = D3DXFrameFind(&root, n2); 11417 ok(ret == &sibling, "Unexpected frame, %p.\n", ret); 11418 11419 memset(&sibling2, 0, sizeof(sibling2)); 11420 sibling2.Name = n2; 11421 sibling.pFrameSibling = &sibling2; 11422 ret = D3DXFrameFind(&root, n2); 11423 ok(ret == &sibling, "Unexpected frame, %p.\n", ret); 11424 11425 sibling2.Name = n3; 11426 ret = D3DXFrameFind(&root, n3); 11427 ok(ret == &sibling2, "Unexpected frame, %p.\n", ret); 11428 11429 /* Siblings first. */ 11430 memset(&child, 0, sizeof(child)); 11431 child.Name = n2; 11432 root.pFrameFirstChild = &child; 11433 ret = D3DXFrameFind(&root, n2); 11434 ok(ret == &sibling, "Unexpected frame, %p.\n", ret); 11435 11436 child.Name = n4; 11437 ret = D3DXFrameFind(&root, n4); 11438 ok(ret == &child, "Unexpected frame, %p.\n", ret); 11439 11440 /* Link a grandchild and another one for sibling. */ 11441 memset(&child2, 0, sizeof(child2)); 11442 memset(&child3, 0, sizeof(child3)); 11443 child2.Name = child3.Name = n5; 11444 sibling.pFrameFirstChild = &child2; 11445 child.pFrameFirstChild = &child3; 11446 ret = D3DXFrameFind(&root, n5); 11447 ok(ret == &child2, "Unexpected frame, %p.\n", ret); 11448 11449 child3.Name = n6; 11450 ret = D3DXFrameFind(&root, n6); 11451 ok(ret == &child3, "Unexpected frame, %p.\n", ret); 11452 } 11453 11454 START_TEST(mesh) 11455 { 11456 D3DXBoundProbeTest(); 11457 D3DXComputeBoundingBoxTest(); 11458 D3DXComputeBoundingSphereTest(); 11459 D3DXGetFVFVertexSizeTest(); 11460 D3DXIntersectTriTest(); 11461 D3DXCreateMeshTest(); 11462 D3DXCreateMeshFVFTest(); 11463 D3DXLoadMeshTest(); 11464 D3DXLoadSkinMeshFromXofTest(); 11465 D3DXCreateBoxTest(); 11466 D3DXCreatePolygonTest(); 11467 D3DXCreateSphereTest(); 11468 D3DXCreateCylinderTest(); 11469 D3DXCreateTextTest(); 11470 D3DXCreateTorusTest(); 11471 D3DXCreateAnimationControllerTest(); 11472 test_get_decl_length(); 11473 test_get_decl_vertex_size(); 11474 test_fvf_decl_conversion(); 11475 D3DXGenerateAdjacencyTest(); 11476 test_update_semantics(); 11477 test_create_skin_info(); 11478 test_update_skinned_mesh(); 11479 test_convert_adjacency_to_point_reps(); 11480 test_convert_point_reps_to_adjacency(); 11481 test_weld_vertices(); 11482 test_clone_mesh(); 11483 test_valid_mesh(); 11484 test_optimize_vertices(); 11485 test_optimize_faces(); 11486 test_compute_normals(); 11487 test_D3DXFrameFind(); 11488 } 11489