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_convert_adjacency_to_point_reps(void) 5320 { 5321 HRESULT hr; 5322 struct test_context *test_context = NULL; 5323 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM; 5324 const DWORD options_16bit = D3DXMESH_SYSTEMMEM; 5325 const D3DVERTEXELEMENT9 declaration[] = 5326 { 5327 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 5328 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 5329 {0, 24, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0}, 5330 D3DDECL_END() 5331 }; 5332 const unsigned int VERTS_PER_FACE = 3; 5333 void *vertex_buffer; 5334 void *index_buffer; 5335 DWORD *attributes_buffer; 5336 int i, j; 5337 enum color { RED = 0xffff0000, GREEN = 0xff00ff00, BLUE = 0xff0000ff}; 5338 struct vertex_pnc 5339 { 5340 D3DXVECTOR3 position; 5341 D3DXVECTOR3 normal; 5342 enum color color; /* In case of manual visual inspection */ 5343 }; 5344 #ifndef __REACTOS__ 5345 D3DXVECTOR3 up = {0.0f, 0.0f, 1.0f}; 5346 #else 5347 #define up {0.0f, 0.0f, 1.0f} 5348 #endif 5349 /* mesh0 (one face) 5350 * 5351 * 0--1 5352 * | / 5353 * |/ 5354 * 2 5355 */ 5356 const struct vertex_pnc vertices0[] = 5357 { 5358 {{ 0.0f, 3.0f, 0.f}, up, RED}, 5359 {{ 2.0f, 3.0f, 0.f}, up, GREEN}, 5360 {{ 0.0f, 0.0f, 0.f}, up, BLUE}, 5361 }; 5362 const DWORD indices0[] = {0, 1, 2}; 5363 const unsigned int num_vertices0 = ARRAY_SIZE(vertices0); 5364 const unsigned int num_faces0 = ARRAY_SIZE(indices0) / VERTS_PER_FACE; 5365 const DWORD adjacency0[] = {-1, -1, -1}; 5366 const DWORD exp_point_rep0[] = {0, 1, 2}; 5367 /* mesh1 (right) 5368 * 5369 * 0--1 3 5370 * | / /| 5371 * |/ / | 5372 * 2 5--4 5373 */ 5374 const struct vertex_pnc vertices1[] = 5375 { 5376 {{ 0.0f, 3.0f, 0.f}, up, RED}, 5377 {{ 2.0f, 3.0f, 0.f}, up, GREEN}, 5378 {{ 0.0f, 0.0f, 0.f}, up, BLUE}, 5379 5380 {{ 3.0f, 3.0f, 0.f}, up, GREEN}, 5381 {{ 3.0f, 0.0f, 0.f}, up, RED}, 5382 {{ 1.0f, 0.0f, 0.f}, up, BLUE}, 5383 }; 5384 const DWORD indices1[] = {0, 1, 2, 3, 4, 5}; 5385 const unsigned int num_vertices1 = ARRAY_SIZE(vertices1); 5386 const unsigned int num_faces1 = ARRAY_SIZE(indices1) / VERTS_PER_FACE; 5387 const DWORD adjacency1[] = {-1, 1, -1, -1, -1, 0}; 5388 const DWORD exp_point_rep1[] = {0, 1, 2, 1, 4, 2}; 5389 /* mesh2 (left) 5390 * 5391 * 3 0--1 5392 * /| | / 5393 * / | |/ 5394 * 5--4 2 5395 */ 5396 const struct vertex_pnc vertices2[] = 5397 { 5398 {{ 0.0f, 3.0f, 0.f}, up, RED}, 5399 {{ 2.0f, 3.0f, 0.f}, up, GREEN}, 5400 {{ 0.0f, 0.0f, 0.f}, up, BLUE}, 5401 5402 {{-1.0f, 3.0f, 0.f}, up, RED}, 5403 {{-1.0f, 0.0f, 0.f}, up, GREEN}, 5404 {{-3.0f, 0.0f, 0.f}, up, BLUE}, 5405 }; 5406 const DWORD indices2[] = {0, 1, 2, 3, 4, 5}; 5407 const unsigned int num_vertices2 = ARRAY_SIZE(vertices2); 5408 const unsigned int num_faces2 = ARRAY_SIZE(indices2) / VERTS_PER_FACE; 5409 const DWORD adjacency2[] = {-1, -1, 1, 0, -1, -1}; 5410 const DWORD exp_point_rep2[] = {0, 1, 2, 0, 2, 5}; 5411 /* mesh3 (above) 5412 * 5413 * 3 5414 * /| 5415 * / | 5416 * 5--4 5417 * 0--1 5418 * | / 5419 * |/ 5420 * 2 5421 */ 5422 struct vertex_pnc vertices3[] = 5423 { 5424 {{ 0.0f, 3.0f, 0.f}, up, RED}, 5425 {{ 2.0f, 3.0f, 0.f}, up, GREEN}, 5426 {{ 0.0f, 0.0f, 0.f}, up, BLUE}, 5427 5428 {{ 2.0f, 7.0f, 0.f}, up, BLUE}, 5429 {{ 2.0f, 4.0f, 0.f}, up, GREEN}, 5430 {{ 0.0f, 4.0f, 0.f}, up, RED}, 5431 }; 5432 const DWORD indices3[] = {0, 1, 2, 3, 4, 5}; 5433 const unsigned int num_vertices3 = ARRAY_SIZE(vertices3); 5434 const unsigned int num_faces3 = ARRAY_SIZE(indices3) / VERTS_PER_FACE; 5435 const DWORD adjacency3[] = {1, -1, -1, -1, 0, -1}; 5436 const DWORD exp_point_rep3[] = {0, 1, 2, 3, 1, 0}; 5437 /* mesh4 (below, tip against tip) 5438 * 5439 * 0--1 5440 * | / 5441 * |/ 5442 * 2 5443 * 3 5444 * |\ 5445 * | \ 5446 * 5--4 5447 */ 5448 struct vertex_pnc vertices4[] = 5449 { 5450 {{ 0.0f, 3.0f, 0.f}, up, RED}, 5451 {{ 2.0f, 3.0f, 0.f}, up, GREEN}, 5452 {{ 0.0f, 0.0f, 0.f}, up, BLUE}, 5453 5454 {{ 0.0f, -4.0f, 0.f}, up, BLUE}, 5455 {{ 2.0f, -7.0f, 0.f}, up, GREEN}, 5456 {{ 0.0f, -7.0f, 0.f}, up, RED}, 5457 }; 5458 const DWORD indices4[] = {0, 1, 2, 3, 4, 5}; 5459 const unsigned int num_vertices4 = ARRAY_SIZE(vertices4); 5460 const unsigned int num_faces4 = ARRAY_SIZE(indices4) / VERTS_PER_FACE; 5461 const DWORD adjacency4[] = {-1, -1, -1, -1, -1, -1}; 5462 const DWORD exp_point_rep4[] = {0, 1, 2, 3, 4, 5}; 5463 /* mesh5 (gap in mesh) 5464 * 5465 * 0 3-----4 15 5466 * / \ \ / / \ 5467 * / \ \ / / \ 5468 * 2-----1 5 17-----16 5469 * 6-----7 9 12-----13 5470 * \ / / \ \ / 5471 * \ / / \ \ / 5472 * 8 10-----11 14 5473 * 5474 */ 5475 const struct vertex_pnc vertices5[] = 5476 { 5477 {{ 0.0f, 1.0f, 0.f}, up, RED}, 5478 {{ 1.0f, -1.0f, 0.f}, up, GREEN}, 5479 {{-1.0f, -1.0f, 0.f}, up, BLUE}, 5480 5481 {{ 0.1f, 1.0f, 0.f}, up, RED}, 5482 {{ 2.1f, 1.0f, 0.f}, up, BLUE}, 5483 {{ 1.1f, -1.0f, 0.f}, up, GREEN}, 5484 5485 {{-1.0f, -1.1f, 0.f}, up, BLUE}, 5486 {{ 1.0f, -1.1f, 0.f}, up, GREEN}, 5487 {{ 0.0f, -3.1f, 0.f}, up, RED}, 5488 5489 {{ 1.1f, -1.1f, 0.f}, up, GREEN}, 5490 {{ 2.1f, -3.1f, 0.f}, up, BLUE}, 5491 {{ 0.1f, -3.1f, 0.f}, up, RED}, 5492 5493 {{ 1.2f, -1.1f, 0.f}, up, GREEN}, 5494 {{ 3.2f, -1.1f, 0.f}, up, RED}, 5495 {{ 2.2f, -3.1f, 0.f}, up, BLUE}, 5496 5497 {{ 2.2f, 1.0f, 0.f}, up, BLUE}, 5498 {{ 3.2f, -1.0f, 0.f}, up, RED}, 5499 {{ 1.2f, -1.0f, 0.f}, up, GREEN}, 5500 }; 5501 const DWORD indices5[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}; 5502 const unsigned int num_vertices5 = ARRAY_SIZE(vertices5); 5503 const unsigned int num_faces5 = ARRAY_SIZE(indices5) / VERTS_PER_FACE; 5504 const DWORD adjacency5[] = {-1, 2, -1, -1, 5, -1, 0, -1, -1, 4, -1, -1, 5, -1, 3, -1, 4, 1}; 5505 const DWORD exp_point_rep5[] = {0, 1, 2, 3, 4, 5, 2, 1, 8, 5, 10, 11, 5, 13, 10, 4, 13, 5}; 5506 const WORD indices5_16bit[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}; 5507 /* mesh6 (indices re-ordering) 5508 * 5509 * 0--1 6 3 5510 * | / /| |\ 5511 * |/ / | | \ 5512 * 2 8--7 5--4 5513 */ 5514 const struct vertex_pnc vertices6[] = 5515 { 5516 {{ 0.0f, 3.0f, 0.f}, up, RED}, 5517 {{ 2.0f, 3.0f, 0.f}, up, GREEN}, 5518 {{ 0.0f, 0.0f, 0.f}, up, BLUE}, 5519 5520 {{ 3.0f, 3.0f, 0.f}, up, GREEN}, 5521 {{ 3.0f, 0.0f, 0.f}, up, RED}, 5522 {{ 1.0f, 0.0f, 0.f}, up, BLUE}, 5523 5524 {{ 4.0f, 3.0f, 0.f}, up, GREEN}, 5525 {{ 6.0f, 0.0f, 0.f}, up, BLUE}, 5526 {{ 4.0f, 0.0f, 0.f}, up, RED}, 5527 }; 5528 const DWORD indices6[] = {0, 1, 2, 6, 7, 8, 3, 4, 5}; 5529 const unsigned int num_vertices6 = ARRAY_SIZE(vertices6); 5530 const unsigned int num_faces6 = ARRAY_SIZE(indices6) / VERTS_PER_FACE; 5531 const DWORD adjacency6[] = {-1, 1, -1, 2, -1, 0, -1, -1, 1}; 5532 const DWORD exp_point_rep6[] = {0, 1, 2, 1, 4, 5, 1, 5, 2}; 5533 /* mesh7 (expands collapsed triangle) 5534 * 5535 * 0--1 3 5536 * | / /| 5537 * |/ / | 5538 * 2 5--4 5539 */ 5540 const struct vertex_pnc vertices7[] = 5541 { 5542 {{ 0.0f, 3.0f, 0.f}, up, RED}, 5543 {{ 2.0f, 3.0f, 0.f}, up, GREEN}, 5544 {{ 0.0f, 0.0f, 0.f}, up, BLUE}, 5545 5546 {{ 3.0f, 3.0f, 0.f}, up, GREEN}, 5547 {{ 3.0f, 0.0f, 0.f}, up, RED}, 5548 {{ 1.0f, 0.0f, 0.f}, up, BLUE}, 5549 }; 5550 const DWORD indices7[] = {0, 1, 2, 3, 3, 3}; /* Face 1 is collapsed*/ 5551 const unsigned int num_vertices7 = ARRAY_SIZE(vertices7); 5552 const unsigned int num_faces7 = ARRAY_SIZE(indices7) / VERTS_PER_FACE; 5553 const DWORD adjacency7[] = {-1, -1, -1, -1, -1, -1}; 5554 const DWORD exp_point_rep7[] = {0, 1, 2, 3, 4, 5}; 5555 /* mesh8 (indices re-ordering and double replacement) 5556 * 5557 * 0--1 9 6 5558 * | / /| |\ 5559 * |/ / | | \ 5560 * 2 11-10 8--7 5561 * 3--4 5562 * | / 5563 * |/ 5564 * 5 5565 */ 5566 const struct vertex_pnc vertices8[] = 5567 { 5568 {{ 0.0f, 3.0f, 0.f}, up, RED}, 5569 {{ 2.0f, 3.0f, 0.f}, up, GREEN}, 5570 {{ 0.0f, 0.0f, 0.f}, up, BLUE}, 5571 5572 {{ 4.0, -4.0, 0.f}, up, RED}, 5573 {{ 6.0, -4.0, 0.f}, up, BLUE}, 5574 {{ 4.0, -7.0, 0.f}, up, GREEN}, 5575 5576 {{ 4.0f, 3.0f, 0.f}, up, GREEN}, 5577 {{ 6.0f, 0.0f, 0.f}, up, BLUE}, 5578 {{ 4.0f, 0.0f, 0.f}, up, RED}, 5579 5580 {{ 3.0f, 3.0f, 0.f}, up, GREEN}, 5581 {{ 3.0f, 0.0f, 0.f}, up, RED}, 5582 {{ 1.0f, 0.0f, 0.f}, up, BLUE}, 5583 }; 5584 const DWORD indices8[] = {0, 1, 2, 9, 10, 11, 6, 7, 8, 3, 4, 5}; 5585 const unsigned int num_vertices8 = ARRAY_SIZE(vertices8); 5586 const unsigned int num_faces8 = ARRAY_SIZE(indices8) / VERTS_PER_FACE; 5587 const DWORD adjacency8[] = {-1, 1, -1, 2, -1, 0, -1, 3, 1, 2, -1, -1}; 5588 const DWORD exp_point_rep8[] = {0, 1, 2, 3, 4, 5, 1, 4, 3, 1, 3, 2}; 5589 /* mesh9 (right, shared vertices) 5590 * 5591 * 0--1 5592 * | /| 5593 * |/ | 5594 * 2--3 5595 */ 5596 const struct vertex_pnc vertices9[] = 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 {{ 2.0f, 0.0f, 0.f}, up, RED}, 5603 }; 5604 const DWORD indices9[] = {0, 1, 2, 1, 3, 2}; 5605 const unsigned int num_vertices9 = ARRAY_SIZE(vertices9); 5606 const unsigned int num_faces9 = ARRAY_SIZE(indices9) / VERTS_PER_FACE; 5607 const DWORD adjacency9[] = {-1, 1, -1, -1, -1, 0}; 5608 const DWORD exp_point_rep9[] = {0, 1, 2, 3}; 5609 /* All mesh data */ 5610 ID3DXMesh *mesh = NULL; 5611 ID3DXMesh *mesh_null_check = NULL; 5612 unsigned int attributes[] = {0}; 5613 struct 5614 { 5615 const struct vertex_pnc *vertices; 5616 const DWORD *indices; 5617 const DWORD num_vertices; 5618 const DWORD num_faces; 5619 const DWORD *adjacency; 5620 const DWORD *exp_point_reps; 5621 const DWORD options; 5622 } 5623 tc[] = 5624 { 5625 { 5626 vertices0, 5627 indices0, 5628 num_vertices0, 5629 num_faces0, 5630 adjacency0, 5631 exp_point_rep0, 5632 options 5633 }, 5634 { 5635 vertices1, 5636 indices1, 5637 num_vertices1, 5638 num_faces1, 5639 adjacency1, 5640 exp_point_rep1, 5641 options 5642 }, 5643 { 5644 vertices2, 5645 indices2, 5646 num_vertices2, 5647 num_faces2, 5648 adjacency2, 5649 exp_point_rep2, 5650 options 5651 }, 5652 { 5653 vertices3, 5654 indices3, 5655 num_vertices3, 5656 num_faces3, 5657 adjacency3, 5658 exp_point_rep3, 5659 options 5660 }, 5661 { 5662 vertices4, 5663 indices4, 5664 num_vertices4, 5665 num_faces4, 5666 adjacency4, 5667 exp_point_rep4, 5668 options 5669 }, 5670 { 5671 vertices5, 5672 indices5, 5673 num_vertices5, 5674 num_faces5, 5675 adjacency5, 5676 exp_point_rep5, 5677 options 5678 }, 5679 { 5680 vertices6, 5681 indices6, 5682 num_vertices6, 5683 num_faces6, 5684 adjacency6, 5685 exp_point_rep6, 5686 options 5687 }, 5688 { 5689 vertices7, 5690 indices7, 5691 num_vertices7, 5692 num_faces7, 5693 adjacency7, 5694 exp_point_rep7, 5695 options 5696 }, 5697 { 5698 vertices8, 5699 indices8, 5700 num_vertices8, 5701 num_faces8, 5702 adjacency8, 5703 exp_point_rep8, 5704 options 5705 }, 5706 { 5707 vertices9, 5708 indices9, 5709 num_vertices9, 5710 num_faces9, 5711 adjacency9, 5712 exp_point_rep9, 5713 options 5714 }, 5715 { 5716 vertices5, 5717 (DWORD*)indices5_16bit, 5718 num_vertices5, 5719 num_faces5, 5720 adjacency5, 5721 exp_point_rep5, 5722 options_16bit 5723 }, 5724 }; 5725 DWORD *point_reps = NULL; 5726 5727 test_context = new_test_context(); 5728 if (!test_context) 5729 { 5730 skip("Couldn't create test context\n"); 5731 goto cleanup; 5732 } 5733 5734 for (i = 0; i < ARRAY_SIZE(tc); i++) 5735 { 5736 hr = D3DXCreateMesh(tc[i].num_faces, tc[i].num_vertices, tc[i].options, declaration, 5737 test_context->device, &mesh); 5738 if (FAILED(hr)) 5739 { 5740 skip("Couldn't create mesh %d. Got %x expected D3D_OK\n", i, hr); 5741 goto cleanup; 5742 } 5743 5744 if (i == 0) /* Save first mesh for later NULL checks */ 5745 mesh_null_check = mesh; 5746 5747 point_reps = HeapAlloc(GetProcessHeap(), 0, tc[i].num_vertices * sizeof(*point_reps)); 5748 if (!point_reps) 5749 { 5750 skip("Couldn't allocate point reps array.\n"); 5751 goto cleanup; 5752 } 5753 5754 hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, &vertex_buffer); 5755 if (FAILED(hr)) 5756 { 5757 skip("Couldn't lock vertex buffer.\n"); 5758 goto cleanup; 5759 } 5760 memcpy(vertex_buffer, tc[i].vertices, tc[i].num_vertices * sizeof(*tc[i].vertices)); 5761 hr = mesh->lpVtbl->UnlockVertexBuffer(mesh); 5762 if (FAILED(hr)) 5763 { 5764 skip("Couldn't unlock vertex buffer.\n"); 5765 goto cleanup; 5766 } 5767 5768 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, &index_buffer); 5769 if (FAILED(hr)) 5770 { 5771 skip("Couldn't lock index buffer.\n"); 5772 goto cleanup; 5773 } 5774 if (tc[i].options & D3DXMESH_32BIT) 5775 { 5776 memcpy(index_buffer, tc[i].indices, VERTS_PER_FACE * tc[i].num_faces * sizeof(DWORD)); 5777 } 5778 else 5779 { 5780 memcpy(index_buffer, tc[i].indices, VERTS_PER_FACE * tc[i].num_faces * sizeof(WORD)); 5781 } 5782 hr = mesh->lpVtbl->UnlockIndexBuffer(mesh); 5783 if (FAILED(hr)) { 5784 skip("Couldn't unlock index buffer.\n"); 5785 goto cleanup; 5786 } 5787 5788 hr = mesh->lpVtbl->LockAttributeBuffer(mesh, 0, &attributes_buffer); 5789 if (FAILED(hr)) 5790 { 5791 skip("Couldn't lock attributes buffer.\n"); 5792 goto cleanup; 5793 } 5794 memcpy(attributes_buffer, attributes, sizeof(attributes)); 5795 hr = mesh->lpVtbl->UnlockAttributeBuffer(mesh); 5796 if (FAILED(hr)) 5797 { 5798 skip("Couldn't unlock attributes buffer.\n"); 5799 goto cleanup; 5800 } 5801 5802 /* Convert adjacency to point representation */ 5803 for (j = 0; j < tc[i].num_vertices; j++) point_reps[j] = -1; 5804 hr = mesh->lpVtbl->ConvertAdjacencyToPointReps(mesh, tc[i].adjacency, point_reps); 5805 ok(hr == D3D_OK, "ConvertAdjacencyToPointReps failed case %d. " 5806 "Got %x expected D3D_OK\n", i, hr); 5807 5808 /* Check point representation */ 5809 for (j = 0; j < tc[i].num_vertices; j++) 5810 { 5811 ok(point_reps[j] == tc[i].exp_point_reps[j], 5812 "Unexpected point representation at (%d, %d)." 5813 " Got %d expected %d\n", 5814 i, j, point_reps[j], tc[i].exp_point_reps[j]); 5815 } 5816 5817 HeapFree(GetProcessHeap(), 0, point_reps); 5818 point_reps = NULL; 5819 5820 if (i != 0) /* First mesh will be freed during cleanup */ 5821 mesh->lpVtbl->Release(mesh); 5822 } 5823 5824 /* NULL checks */ 5825 hr = mesh_null_check->lpVtbl->ConvertAdjacencyToPointReps(mesh_null_check, tc[0].adjacency, NULL); 5826 ok(hr == D3DERR_INVALIDCALL, "ConvertAdjacencyToPointReps point_reps NULL. " 5827 "Got %x expected D3DERR_INVALIDCALL\n", hr); 5828 hr = mesh_null_check->lpVtbl->ConvertAdjacencyToPointReps(mesh_null_check, NULL, NULL); 5829 ok(hr == D3DERR_INVALIDCALL, "ConvertAdjacencyToPointReps adjacency and point_reps NULL. " 5830 "Got %x expected D3DERR_INVALIDCALL\n", hr); 5831 5832 cleanup: 5833 if (mesh_null_check) 5834 mesh_null_check->lpVtbl->Release(mesh_null_check); 5835 HeapFree(GetProcessHeap(), 0, point_reps); 5836 free_test_context(test_context); 5837 #ifdef __REACTOS__ 5838 #undef up 5839 #endif 5840 } 5841 5842 static void test_convert_point_reps_to_adjacency(void) 5843 { 5844 HRESULT hr; 5845 struct test_context *test_context = NULL; 5846 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM; 5847 const DWORD options_16bit = D3DXMESH_SYSTEMMEM; 5848 const D3DVERTEXELEMENT9 declaration[] = 5849 { 5850 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 5851 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 5852 {0, 24, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0}, 5853 D3DDECL_END() 5854 }; 5855 const unsigned int VERTS_PER_FACE = 3; 5856 void *vertex_buffer; 5857 void *index_buffer; 5858 DWORD *attributes_buffer; 5859 int i, j; 5860 enum color { RED = 0xffff0000, GREEN = 0xff00ff00, BLUE = 0xff0000ff}; 5861 struct vertex_pnc 5862 { 5863 D3DXVECTOR3 position; 5864 D3DXVECTOR3 normal; 5865 enum color color; /* In case of manual visual inspection */ 5866 }; 5867 #ifndef __REACTOS__ 5868 D3DXVECTOR3 up = {0.0f, 0.0f, 1.0f}; 5869 #else 5870 #define up {0.0f, 0.0f, 1.0f} 5871 #endif 5872 5873 /* mesh0 (one face) 5874 * 5875 * 0--1 5876 * | / 5877 * |/ 5878 * 2 5879 */ 5880 const struct vertex_pnc vertices0[] = 5881 { 5882 {{ 0.0f, 3.0f, 0.f}, up, RED}, 5883 {{ 2.0f, 3.0f, 0.f}, up, GREEN}, 5884 {{ 0.0f, 0.0f, 0.f}, up, BLUE}, 5885 }; 5886 const DWORD indices0[] = {0, 1, 2}; 5887 const unsigned int num_vertices0 = ARRAY_SIZE(vertices0); 5888 const unsigned int num_faces0 = num_vertices0 / VERTS_PER_FACE; 5889 const DWORD exp_adjacency0[] = {-1, -1, -1}; 5890 const DWORD exp_id_adjacency0[] = {-1, -1, -1}; 5891 const DWORD point_rep0[] = {0, 1, 2}; 5892 /* mesh1 (right) 5893 * 5894 * 0--1 3 5895 * | / /| 5896 * |/ / | 5897 * 2 5--4 5898 */ 5899 const struct vertex_pnc vertices1[] = 5900 { 5901 {{ 0.0f, 3.0f, 0.f}, up, RED}, 5902 {{ 2.0f, 3.0f, 0.f}, up, GREEN}, 5903 {{ 0.0f, 0.0f, 0.f}, up, BLUE}, 5904 5905 {{ 3.0f, 3.0f, 0.f}, up, GREEN}, 5906 {{ 3.0f, 0.0f, 0.f}, up, RED}, 5907 {{ 1.0f, 0.0f, 0.f}, up, BLUE}, 5908 }; 5909 const DWORD indices1[] = {0, 1, 2, 3, 4, 5}; 5910 const unsigned int num_vertices1 = ARRAY_SIZE(vertices1); 5911 const unsigned int num_faces1 = num_vertices1 / VERTS_PER_FACE; 5912 const DWORD exp_adjacency1[] = {-1, 1, -1, -1, -1, 0}; 5913 const DWORD exp_id_adjacency1[] = {-1, -1, -1, -1, -1, -1}; 5914 const DWORD point_rep1[] = {0, 1, 2, 1, 4, 2}; 5915 /* mesh2 (left) 5916 * 5917 * 3 0--1 5918 * /| | / 5919 * / | |/ 5920 * 5--4 2 5921 */ 5922 const struct vertex_pnc vertices2[] = 5923 { 5924 {{ 0.0f, 3.0f, 0.f}, up, RED}, 5925 {{ 2.0f, 3.0f, 0.f}, up, GREEN}, 5926 {{ 0.0f, 0.0f, 0.f}, up, BLUE}, 5927 5928 {{-1.0f, 3.0f, 0.f}, up, RED}, 5929 {{-1.0f, 0.0f, 0.f}, up, GREEN}, 5930 {{-3.0f, 0.0f, 0.f}, up, BLUE}, 5931 }; 5932 const DWORD indices2[] = {0, 1, 2, 3, 4, 5}; 5933 const unsigned int num_vertices2 = ARRAY_SIZE(vertices2); 5934 const unsigned int num_faces2 = num_vertices2 / VERTS_PER_FACE; 5935 const DWORD exp_adjacency2[] = {-1, -1, 1, 0, -1, -1}; 5936 const DWORD exp_id_adjacency2[] = {-1, -1, -1, -1, -1, -1}; 5937 const DWORD point_rep2[] = {0, 1, 2, 0, 2, 5}; 5938 /* mesh3 (above) 5939 * 5940 * 3 5941 * /| 5942 * / | 5943 * 5--4 5944 * 0--1 5945 * | / 5946 * |/ 5947 * 2 5948 */ 5949 struct vertex_pnc vertices3[] = 5950 { 5951 {{ 0.0f, 3.0f, 0.f}, up, RED}, 5952 {{ 2.0f, 3.0f, 0.f}, up, GREEN}, 5953 {{ 0.0f, 0.0f, 0.f}, up, BLUE}, 5954 5955 {{ 2.0f, 7.0f, 0.f}, up, BLUE}, 5956 {{ 2.0f, 4.0f, 0.f}, up, GREEN}, 5957 {{ 0.0f, 4.0f, 0.f}, up, RED}, 5958 }; 5959 const DWORD indices3[] = {0, 1, 2, 3, 4, 5}; 5960 const unsigned int num_vertices3 = ARRAY_SIZE(vertices3); 5961 const unsigned int num_faces3 = num_vertices3 / VERTS_PER_FACE; 5962 const DWORD exp_adjacency3[] = {1, -1, -1, -1, 0, -1}; 5963 const DWORD exp_id_adjacency3[] = {-1, -1, -1, -1, -1, -1}; 5964 const DWORD point_rep3[] = {0, 1, 2, 3, 1, 0}; 5965 /* mesh4 (below, tip against tip) 5966 * 5967 * 0--1 5968 * | / 5969 * |/ 5970 * 2 5971 * 3 5972 * |\ 5973 * | \ 5974 * 5--4 5975 */ 5976 struct vertex_pnc vertices4[] = 5977 { 5978 {{ 0.0f, 3.0f, 0.f}, up, RED}, 5979 {{ 2.0f, 3.0f, 0.f}, up, GREEN}, 5980 {{ 0.0f, 0.0f, 0.f}, up, BLUE}, 5981 5982 {{ 0.0f, -4.0f, 0.f}, up, BLUE}, 5983 {{ 2.0f, -7.0f, 0.f}, up, GREEN}, 5984 {{ 0.0f, -7.0f, 0.f}, up, RED}, 5985 }; 5986 const DWORD indices4[] = {0, 1, 2, 3, 4, 5}; 5987 const unsigned int num_vertices4 = ARRAY_SIZE(vertices4); 5988 const unsigned int num_faces4 = num_vertices4 / VERTS_PER_FACE; 5989 const DWORD exp_adjacency4[] = {-1, -1, -1, -1, -1, -1}; 5990 const DWORD exp_id_adjacency4[] = {-1, -1, -1, -1, -1, -1}; 5991 const DWORD point_rep4[] = {0, 1, 2, 3, 4, 5}; 5992 /* mesh5 (gap in mesh) 5993 * 5994 * 0 3-----4 15 5995 * / \ \ / / \ 5996 * / \ \ / / \ 5997 * 2-----1 5 17-----16 5998 * 6-----7 9 12-----13 5999 * \ / / \ \ / 6000 * \ / / \ \ / 6001 * 8 10-----11 14 6002 * 6003 */ 6004 const struct vertex_pnc vertices5[] = 6005 { 6006 {{ 0.0f, 1.0f, 0.f}, up, RED}, 6007 {{ 1.0f, -1.0f, 0.f}, up, GREEN}, 6008 {{-1.0f, -1.0f, 0.f}, up, BLUE}, 6009 6010 {{ 0.1f, 1.0f, 0.f}, up, RED}, 6011 {{ 2.1f, 1.0f, 0.f}, up, BLUE}, 6012 {{ 1.1f, -1.0f, 0.f}, up, GREEN}, 6013 6014 {{-1.0f, -1.1f, 0.f}, up, BLUE}, 6015 {{ 1.0f, -1.1f, 0.f}, up, GREEN}, 6016 {{ 0.0f, -3.1f, 0.f}, up, RED}, 6017 6018 {{ 1.1f, -1.1f, 0.f}, up, GREEN}, 6019 {{ 2.1f, -3.1f, 0.f}, up, BLUE}, 6020 {{ 0.1f, -3.1f, 0.f}, up, RED}, 6021 6022 {{ 1.2f, -1.1f, 0.f}, up, GREEN}, 6023 {{ 3.2f, -1.1f, 0.f}, up, RED}, 6024 {{ 2.2f, -3.1f, 0.f}, up, BLUE}, 6025 6026 {{ 2.2f, 1.0f, 0.f}, up, BLUE}, 6027 {{ 3.2f, -1.0f, 0.f}, up, RED}, 6028 {{ 1.2f, -1.0f, 0.f}, up, GREEN}, 6029 }; 6030 const DWORD indices5[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}; 6031 const unsigned int num_vertices5 = ARRAY_SIZE(vertices5); 6032 const unsigned int num_faces5 = num_vertices5 / VERTS_PER_FACE; 6033 const DWORD exp_adjacency5[] = {-1, 2, -1, -1, 5, -1, 0, -1, -1, 4, -1, -1, 5, -1, 3, -1, 4, 1}; 6034 const DWORD exp_id_adjacency5[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; 6035 const DWORD point_rep5[] = {0, 1, 2, 3, 4, 5, 2, 1, 8, 5, 10, 11, 5, 13, 10, 4, 13, 5}; 6036 /* mesh6 (indices re-ordering) 6037 * 6038 * 0--1 6 3 6039 * | / /| |\ 6040 * |/ / | | \ 6041 * 2 8--7 5--4 6042 */ 6043 const struct vertex_pnc vertices6[] = 6044 { 6045 {{ 0.0f, 3.0f, 0.f}, up, RED}, 6046 {{ 2.0f, 3.0f, 0.f}, up, GREEN}, 6047 {{ 0.0f, 0.0f, 0.f}, up, BLUE}, 6048 6049 {{ 3.0f, 3.0f, 0.f}, up, GREEN}, 6050 {{ 3.0f, 0.0f, 0.f}, up, RED}, 6051 {{ 1.0f, 0.0f, 0.f}, up, BLUE}, 6052 6053 {{ 4.0f, 3.0f, 0.f}, up, GREEN}, 6054 {{ 6.0f, 0.0f, 0.f}, up, BLUE}, 6055 {{ 4.0f, 0.0f, 0.f}, up, RED}, 6056 }; 6057 const DWORD indices6[] = {0, 1, 2, 6, 7, 8, 3, 4, 5}; 6058 const unsigned int num_vertices6 = ARRAY_SIZE(vertices6); 6059 const unsigned int num_faces6 = num_vertices6 / VERTS_PER_FACE; 6060 const DWORD exp_adjacency6[] = {-1, 1, -1, 2, -1, 0, -1, -1, 1}; 6061 const DWORD exp_id_adjacency6[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1}; 6062 const DWORD point_rep6[] = {0, 1, 2, 1, 4, 5, 1, 5, 2}; 6063 /* mesh7 (expands collapsed triangle) 6064 * 6065 * 0--1 3 6066 * | / /| 6067 * |/ / | 6068 * 2 5--4 6069 */ 6070 const struct vertex_pnc vertices7[] = 6071 { 6072 {{ 0.0f, 3.0f, 0.f}, up, RED}, 6073 {{ 2.0f, 3.0f, 0.f}, up, GREEN}, 6074 {{ 0.0f, 0.0f, 0.f}, up, BLUE}, 6075 6076 {{ 3.0f, 3.0f, 0.f}, up, GREEN}, 6077 {{ 3.0f, 0.0f, 0.f}, up, RED}, 6078 {{ 1.0f, 0.0f, 0.f}, up, BLUE}, 6079 }; 6080 const DWORD indices7[] = {0, 1, 2, 3, 3, 3}; /* Face 1 is collapsed*/ 6081 const unsigned int num_vertices7 = ARRAY_SIZE(vertices7); 6082 const unsigned int num_faces7 = num_vertices7 / VERTS_PER_FACE; 6083 const DWORD exp_adjacency7[] = {-1, -1, -1, -1, -1, -1}; 6084 const DWORD exp_id_adjacency7[] = {-1, -1, -1, -1, -1, -1}; 6085 const DWORD point_rep7[] = {0, 1, 2, 3, 4, 5}; 6086 /* mesh8 (indices re-ordering and double replacement) 6087 * 6088 * 0--1 9 6 6089 * | / /| |\ 6090 * |/ / | | \ 6091 * 2 11-10 8--7 6092 * 3--4 6093 * | / 6094 * |/ 6095 * 5 6096 */ 6097 const struct vertex_pnc vertices8[] = 6098 { 6099 {{ 0.0f, 3.0f, 0.f}, up, RED}, 6100 {{ 2.0f, 3.0f, 0.f}, up, GREEN}, 6101 {{ 0.0f, 0.0f, 0.f}, up, BLUE}, 6102 6103 {{ 4.0, -4.0, 0.f}, up, RED}, 6104 {{ 6.0, -4.0, 0.f}, up, BLUE}, 6105 {{ 4.0, -7.0, 0.f}, up, GREEN}, 6106 6107 {{ 4.0f, 3.0f, 0.f}, up, GREEN}, 6108 {{ 6.0f, 0.0f, 0.f}, up, BLUE}, 6109 {{ 4.0f, 0.0f, 0.f}, up, RED}, 6110 6111 {{ 3.0f, 3.0f, 0.f}, up, GREEN}, 6112 {{ 3.0f, 0.0f, 0.f}, up, RED}, 6113 {{ 1.0f, 0.0f, 0.f}, up, BLUE}, 6114 }; 6115 const DWORD indices8[] = {0, 1, 2, 9, 10, 11, 6, 7, 8, 3, 4, 5}; 6116 const WORD indices8_16bit[] = {0, 1, 2, 9, 10, 11, 6, 7, 8, 3, 4, 5}; 6117 const unsigned int num_vertices8 = ARRAY_SIZE(vertices8); 6118 const unsigned int num_faces8 = num_vertices8 / VERTS_PER_FACE; 6119 const DWORD exp_adjacency8[] = {-1, 1, -1, 2, -1, 0, -1, 3, 1, 2, -1, -1}; 6120 const DWORD exp_id_adjacency8[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; 6121 const DWORD point_rep8[] = {0, 1, 2, 3, 4, 5, 1, 4, 3, 1, 3, 2}; 6122 /* mesh9 (right, shared vertices) 6123 * 6124 * 0--1 6125 * | /| 6126 * |/ | 6127 * 2--3 6128 */ 6129 const struct vertex_pnc vertices9[] = 6130 { 6131 {{ 0.0f, 3.0f, 0.f}, up, RED}, 6132 {{ 2.0f, 3.0f, 0.f}, up, GREEN}, 6133 {{ 0.0f, 0.0f, 0.f}, up, BLUE}, 6134 6135 {{ 2.0f, 0.0f, 0.f}, up, RED}, 6136 }; 6137 const DWORD indices9[] = {0, 1, 2, 1, 3, 2}; 6138 const unsigned int num_vertices9 = ARRAY_SIZE(vertices9); 6139 const unsigned int num_faces9 = 2; 6140 const DWORD exp_adjacency9[] = {-1, 1, -1, -1, -1, 0}; 6141 const DWORD exp_id_adjacency9[] = {-1, 1, -1, -1, -1, 0}; 6142 const DWORD point_rep9[] = {0, 1, 2, 3}; 6143 /* All mesh data */ 6144 ID3DXMesh *mesh = NULL; 6145 ID3DXMesh *mesh_null_check = NULL; 6146 unsigned int attributes[] = {0}; 6147 struct 6148 { 6149 const struct vertex_pnc *vertices; 6150 const DWORD *indices; 6151 const DWORD num_vertices; 6152 const DWORD num_faces; 6153 const DWORD *point_reps; 6154 const DWORD *exp_adjacency; 6155 const DWORD *exp_id_adjacency; 6156 const DWORD options; 6157 } 6158 tc[] = 6159 { 6160 { 6161 vertices0, 6162 indices0, 6163 num_vertices0, 6164 num_faces0, 6165 point_rep0, 6166 exp_adjacency0, 6167 exp_id_adjacency0, 6168 options 6169 }, 6170 { 6171 vertices1, 6172 indices1, 6173 num_vertices1, 6174 num_faces1, 6175 point_rep1, 6176 exp_adjacency1, 6177 exp_id_adjacency1, 6178 options 6179 }, 6180 { 6181 vertices2, 6182 indices2, 6183 num_vertices2, 6184 num_faces2, 6185 point_rep2, 6186 exp_adjacency2, 6187 exp_id_adjacency2, 6188 options 6189 }, 6190 { 6191 vertices3, 6192 indices3, 6193 num_vertices3, 6194 num_faces3, 6195 point_rep3, 6196 exp_adjacency3, 6197 exp_id_adjacency3, 6198 options 6199 }, 6200 { 6201 vertices4, 6202 indices4, 6203 num_vertices4, 6204 num_faces4, 6205 point_rep4, 6206 exp_adjacency4, 6207 exp_id_adjacency4, 6208 options 6209 }, 6210 { 6211 vertices5, 6212 indices5, 6213 num_vertices5, 6214 num_faces5, 6215 point_rep5, 6216 exp_adjacency5, 6217 exp_id_adjacency5, 6218 options 6219 }, 6220 { 6221 vertices6, 6222 indices6, 6223 num_vertices6, 6224 num_faces6, 6225 point_rep6, 6226 exp_adjacency6, 6227 exp_id_adjacency6, 6228 options 6229 }, 6230 { 6231 vertices7, 6232 indices7, 6233 num_vertices7, 6234 num_faces7, 6235 point_rep7, 6236 exp_adjacency7, 6237 exp_id_adjacency7, 6238 options 6239 }, 6240 { 6241 vertices8, 6242 indices8, 6243 num_vertices8, 6244 num_faces8, 6245 point_rep8, 6246 exp_adjacency8, 6247 exp_id_adjacency8, 6248 options 6249 }, 6250 { 6251 vertices9, 6252 indices9, 6253 num_vertices9, 6254 num_faces9, 6255 point_rep9, 6256 exp_adjacency9, 6257 exp_id_adjacency9, 6258 options 6259 }, 6260 { 6261 vertices8, 6262 (DWORD*)indices8_16bit, 6263 num_vertices8, 6264 num_faces8, 6265 point_rep8, 6266 exp_adjacency8, 6267 exp_id_adjacency8, 6268 options_16bit 6269 }, 6270 }; 6271 DWORD *adjacency = NULL; 6272 #ifdef __REACTOS__ 6273 #undef up 6274 #endif 6275 6276 test_context = new_test_context(); 6277 if (!test_context) 6278 { 6279 skip("Couldn't create test context\n"); 6280 goto cleanup; 6281 } 6282 6283 for (i = 0; i < ARRAY_SIZE(tc); i++) 6284 { 6285 hr = D3DXCreateMesh(tc[i].num_faces, tc[i].num_vertices, tc[i].options, 6286 declaration, test_context->device, &mesh); 6287 if (FAILED(hr)) 6288 { 6289 skip("Couldn't create mesh %d. Got %x expected D3D_OK\n", i, hr); 6290 goto cleanup; 6291 } 6292 6293 if (i == 0) /* Save first mesh for later NULL checks */ 6294 mesh_null_check = mesh; 6295 6296 adjacency = HeapAlloc(GetProcessHeap(), 0, VERTS_PER_FACE * tc[i].num_faces * sizeof(*adjacency)); 6297 if (!adjacency) 6298 { 6299 skip("Couldn't allocate adjacency array.\n"); 6300 goto cleanup; 6301 } 6302 6303 hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, &vertex_buffer); 6304 if (FAILED(hr)) 6305 { 6306 skip("Couldn't lock vertex buffer.\n"); 6307 goto cleanup; 6308 } 6309 memcpy(vertex_buffer, tc[i].vertices, tc[i].num_vertices * sizeof(*tc[i].vertices)); 6310 hr = mesh->lpVtbl->UnlockVertexBuffer(mesh); 6311 if (FAILED(hr)) 6312 { 6313 skip("Couldn't unlock vertex buffer.\n"); 6314 goto cleanup; 6315 } 6316 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, &index_buffer); 6317 if (FAILED(hr)) 6318 { 6319 skip("Couldn't lock index buffer.\n"); 6320 goto cleanup; 6321 } 6322 if (tc[i].options & D3DXMESH_32BIT) 6323 { 6324 memcpy(index_buffer, tc[i].indices, VERTS_PER_FACE * tc[i].num_faces * sizeof(DWORD)); 6325 } 6326 else 6327 { 6328 memcpy(index_buffer, tc[i].indices, VERTS_PER_FACE * tc[i].num_faces * sizeof(WORD)); 6329 } 6330 hr = mesh->lpVtbl->UnlockIndexBuffer(mesh); 6331 if (FAILED(hr)) { 6332 skip("Couldn't unlock index buffer.\n"); 6333 goto cleanup; 6334 } 6335 6336 hr = mesh->lpVtbl->LockAttributeBuffer(mesh, 0, &attributes_buffer); 6337 if (FAILED(hr)) 6338 { 6339 skip("Couldn't lock attributes buffer.\n"); 6340 goto cleanup; 6341 } 6342 memcpy(attributes_buffer, attributes, sizeof(attributes)); 6343 hr = mesh->lpVtbl->UnlockAttributeBuffer(mesh); 6344 if (FAILED(hr)) 6345 { 6346 skip("Couldn't unlock attributes buffer.\n"); 6347 goto cleanup; 6348 } 6349 6350 /* Convert point representation to adjacency*/ 6351 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++) adjacency[j] = -2; 6352 6353 hr = mesh->lpVtbl->ConvertPointRepsToAdjacency(mesh, tc[i].point_reps, adjacency); 6354 ok(hr == D3D_OK, "ConvertPointRepsToAdjacency failed case %d. " 6355 "Got %x expected D3D_OK\n", i, hr); 6356 /* Check adjacency */ 6357 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++) 6358 { 6359 ok(adjacency[j] == tc[i].exp_adjacency[j], 6360 "Unexpected adjacency information at (%d, %d)." 6361 " Got %d expected %d\n", 6362 i, j, adjacency[j], tc[i].exp_adjacency[j]); 6363 } 6364 6365 /* NULL point representation is considered identity. */ 6366 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++) adjacency[j] = -2; 6367 hr = mesh_null_check->lpVtbl->ConvertPointRepsToAdjacency(mesh, NULL, adjacency); 6368 ok(hr == D3D_OK, "ConvertPointRepsToAdjacency NULL point_reps. " 6369 "Got %x expected D3D_OK\n", hr); 6370 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++) 6371 { 6372 ok(adjacency[j] == tc[i].exp_id_adjacency[j], 6373 "Unexpected adjacency information (id) at (%d, %d)." 6374 " Got %d expected %d\n", 6375 i, j, adjacency[j], tc[i].exp_id_adjacency[j]); 6376 } 6377 6378 HeapFree(GetProcessHeap(), 0, adjacency); 6379 adjacency = NULL; 6380 if (i != 0) /* First mesh will be freed during cleanup */ 6381 mesh->lpVtbl->Release(mesh); 6382 } 6383 6384 /* NULL checks */ 6385 hr = mesh_null_check->lpVtbl->ConvertPointRepsToAdjacency(mesh_null_check, tc[0].point_reps, NULL); 6386 ok(hr == D3DERR_INVALIDCALL, "ConvertPointRepsToAdjacency NULL adjacency. " 6387 "Got %x expected D3DERR_INVALIDCALL\n", hr); 6388 hr = mesh_null_check->lpVtbl->ConvertPointRepsToAdjacency(mesh_null_check, NULL, NULL); 6389 ok(hr == D3DERR_INVALIDCALL, "ConvertPointRepsToAdjacency NULL point_reps and adjacency. " 6390 "Got %x expected D3DERR_INVALIDCALL\n", hr); 6391 6392 cleanup: 6393 if (mesh_null_check) 6394 mesh_null_check->lpVtbl->Release(mesh_null_check); 6395 HeapFree(GetProcessHeap(), 0, adjacency); 6396 free_test_context(test_context); 6397 } 6398 6399 static HRESULT init_test_mesh(const DWORD num_faces, const DWORD num_vertices, 6400 const DWORD options, 6401 const D3DVERTEXELEMENT9 *declaration, 6402 IDirect3DDevice9 *device, ID3DXMesh **mesh_ptr, 6403 const void *vertices, const DWORD vertex_size, 6404 const DWORD *indices, const DWORD *attributes) 6405 { 6406 HRESULT hr; 6407 void *vertex_buffer; 6408 void *index_buffer; 6409 DWORD *attributes_buffer; 6410 ID3DXMesh *mesh = NULL; 6411 6412 hr = D3DXCreateMesh(num_faces, num_vertices, options, declaration, device, mesh_ptr); 6413 if (FAILED(hr)) 6414 { 6415 skip("Couldn't create mesh. Got %x expected D3D_OK\n", hr); 6416 goto cleanup; 6417 } 6418 mesh = *mesh_ptr; 6419 6420 hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, &vertex_buffer); 6421 if (FAILED(hr)) 6422 { 6423 skip("Couldn't lock vertex buffer.\n"); 6424 goto cleanup; 6425 } 6426 memcpy(vertex_buffer, vertices, num_vertices * vertex_size); 6427 hr = mesh->lpVtbl->UnlockVertexBuffer(mesh); 6428 if (FAILED(hr)) 6429 { 6430 skip("Couldn't unlock vertex buffer.\n"); 6431 goto cleanup; 6432 } 6433 6434 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, &index_buffer); 6435 if (FAILED(hr)) 6436 { 6437 skip("Couldn't lock index buffer.\n"); 6438 goto cleanup; 6439 } 6440 if (options & D3DXMESH_32BIT) 6441 { 6442 if (indices) 6443 memcpy(index_buffer, indices, 3 * num_faces * sizeof(DWORD)); 6444 else 6445 { 6446 /* Fill index buffer with 0, 1, 2, ...*/ 6447 DWORD *indices_32bit = (DWORD*)index_buffer; 6448 UINT i; 6449 for (i = 0; i < 3 * num_faces; i++) 6450 indices_32bit[i] = i; 6451 } 6452 } 6453 else 6454 { 6455 if (indices) 6456 memcpy(index_buffer, indices, 3 * num_faces * sizeof(WORD)); 6457 else 6458 { 6459 /* Fill index buffer with 0, 1, 2, ...*/ 6460 WORD *indices_16bit = (WORD*)index_buffer; 6461 UINT i; 6462 for (i = 0; i < 3 * num_faces; i++) 6463 indices_16bit[i] = i; 6464 } 6465 } 6466 hr = mesh->lpVtbl->UnlockIndexBuffer(mesh); 6467 if (FAILED(hr)) { 6468 skip("Couldn't unlock index buffer.\n"); 6469 goto cleanup; 6470 } 6471 6472 hr = mesh->lpVtbl->LockAttributeBuffer(mesh, 0, &attributes_buffer); 6473 if (FAILED(hr)) 6474 { 6475 skip("Couldn't lock attributes buffer.\n"); 6476 goto cleanup; 6477 } 6478 6479 if (attributes) 6480 memcpy(attributes_buffer, attributes, num_faces * sizeof(*attributes)); 6481 else 6482 memset(attributes_buffer, 0, num_faces * sizeof(*attributes)); 6483 6484 hr = mesh->lpVtbl->UnlockAttributeBuffer(mesh); 6485 if (FAILED(hr)) 6486 { 6487 skip("Couldn't unlock attributes buffer.\n"); 6488 goto cleanup; 6489 } 6490 6491 hr = D3D_OK; 6492 cleanup: 6493 return hr; 6494 } 6495 6496 /* Using structs instead of bit-fields in order to avoid compiler issues. */ 6497 struct udec3 6498 { 6499 UINT x; 6500 UINT y; 6501 UINT z; 6502 UINT w; 6503 }; 6504 6505 struct dec3n 6506 { 6507 INT x; 6508 INT y; 6509 INT z; 6510 INT w; 6511 }; 6512 6513 static DWORD init_udec3_dword(UINT x, UINT y, UINT z, UINT w) 6514 { 6515 DWORD d = 0; 6516 6517 d |= x & 0x3ff; 6518 d |= (y << 10) & 0xffc00; 6519 d |= (z << 20) & 0x3ff00000; 6520 d |= (w << 30) & 0xc0000000; 6521 6522 return d; 6523 } 6524 6525 static DWORD init_dec3n_dword(INT x, INT y, INT z, INT w) 6526 { 6527 DWORD d = 0; 6528 6529 d |= x & 0x3ff; 6530 d |= (y << 10) & 0xffc00; 6531 d |= (z << 20) & 0x3ff00000; 6532 d |= (w << 30) & 0xc0000000; 6533 6534 return d; 6535 } 6536 6537 static struct udec3 dword_to_udec3(DWORD d) 6538 { 6539 struct udec3 v; 6540 6541 v.x = d & 0x3ff; 6542 v.y = (d & 0xffc00) >> 10; 6543 v.z = (d & 0x3ff00000) >> 20; 6544 v.w = (d & 0xc0000000) >> 30; 6545 6546 return v; 6547 } 6548 6549 static struct dec3n dword_to_dec3n(DWORD d) 6550 { 6551 struct dec3n v; 6552 6553 v.x = d & 0x3ff; 6554 v.y = (d & 0xffc00) >> 10; 6555 v.z = (d & 0x3ff00000) >> 20; 6556 v.w = (d & 0xc0000000) >> 30; 6557 6558 return v; 6559 } 6560 6561 static void check_vertex_components(int line, int mesh_number, int vertex_number, BYTE *got_ptr, const BYTE *exp_ptr, D3DVERTEXELEMENT9 *declaration) 6562 { 6563 const char *usage_strings[] = 6564 { 6565 "position", 6566 "blend weight", 6567 "blend indices", 6568 "normal", 6569 "point size", 6570 "texture coordinates", 6571 "tangent", 6572 "binormal", 6573 "tessellation factor", 6574 "position transformed", 6575 "color", 6576 "fog", 6577 "depth", 6578 "sample" 6579 }; 6580 D3DVERTEXELEMENT9 *decl_ptr; 6581 const float PRECISION = 1e-5f; 6582 6583 for (decl_ptr = declaration; decl_ptr->Stream != 0xFF; decl_ptr++) 6584 { 6585 switch (decl_ptr->Type) 6586 { 6587 case D3DDECLTYPE_FLOAT1: 6588 { 6589 FLOAT *got = (FLOAT*)(got_ptr + decl_ptr->Offset); 6590 FLOAT *exp = (FLOAT*)(exp_ptr + decl_ptr->Offset); 6591 FLOAT diff = fabsf(*got - *exp); 6592 ok_(__FILE__,line)(diff <= PRECISION, "Mesh %d: Got %f for vertex %d %s, expected %f.\n", 6593 mesh_number, *got, vertex_number, usage_strings[decl_ptr->Usage], *exp); 6594 break; 6595 } 6596 case D3DDECLTYPE_FLOAT2: 6597 { 6598 D3DXVECTOR2 *got = (D3DXVECTOR2*)(got_ptr + decl_ptr->Offset); 6599 D3DXVECTOR2 *exp = (D3DXVECTOR2*)(exp_ptr + decl_ptr->Offset); 6600 FLOAT diff = max(fabsf(got->x - exp->x), fabsf(got->y - exp->y)); 6601 ok_(__FILE__,line)(diff <= PRECISION, "Mesh %d: Got (%f, %f) for vertex %d %s, expected (%f, %f).\n", 6602 mesh_number, got->x, got->y, vertex_number, usage_strings[decl_ptr->Usage], exp->x, exp->y); 6603 break; 6604 } 6605 case D3DDECLTYPE_FLOAT3: 6606 { 6607 D3DXVECTOR3 *got = (D3DXVECTOR3*)(got_ptr + decl_ptr->Offset); 6608 D3DXVECTOR3 *exp = (D3DXVECTOR3*)(exp_ptr + decl_ptr->Offset); 6609 FLOAT diff = max(fabsf(got->x - exp->x), fabsf(got->y - exp->y)); 6610 diff = max(diff, fabsf(got->z - exp->z)); 6611 ok_(__FILE__,line)(diff <= PRECISION, "Mesh %d: Got (%f, %f, %f) for vertex %d %s, expected (%f, %f, %f).\n", 6612 mesh_number, got->x, got->y, got->z, vertex_number, usage_strings[decl_ptr->Usage], exp->x, exp->y, exp->z); 6613 break; 6614 } 6615 case D3DDECLTYPE_FLOAT4: 6616 { 6617 D3DXVECTOR4 *got = (D3DXVECTOR4*)(got_ptr + decl_ptr->Offset); 6618 D3DXVECTOR4 *exp = (D3DXVECTOR4*)(exp_ptr + decl_ptr->Offset); 6619 FLOAT diff = max(fabsf(got->x - exp->x), fabsf(got->y - exp->y)); 6620 diff = max(diff, fabsf(got->z - exp->z)); 6621 diff = max(diff, fabsf(got->w - exp->w)); 6622 ok_(__FILE__,line)(diff <= PRECISION, "Mesh %d: Got (%f, %f, %f, %f) for vertex %d %s, expected (%f, %f, %f, %f).\n", 6623 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); 6624 break; 6625 } 6626 case D3DDECLTYPE_D3DCOLOR: 6627 { 6628 BYTE *got = got_ptr + decl_ptr->Offset; 6629 const BYTE *exp = exp_ptr + decl_ptr->Offset; 6630 BOOL same_color = got[0] == exp[0] && got[1] == exp[1] 6631 && got[2] == exp[2] && got[3] == exp[3]; 6632 const char *color_types[] = {"diffuse", "specular", "undefined color"}; 6633 BYTE usage_index = decl_ptr->UsageIndex; 6634 if (usage_index > 1) usage_index = 2; 6635 ok_(__FILE__,line)(same_color, "Mesh %d: Got (%u, %u, %u, %u) for vertex %d %s, expected (%u, %u, %u, %u).\n", 6636 mesh_number, got[0], got[1], got[2], got[3], vertex_number, color_types[usage_index], exp[0], exp[1], exp[2], exp[3]); 6637 break; 6638 } 6639 case D3DDECLTYPE_UBYTE4: 6640 case D3DDECLTYPE_UBYTE4N: 6641 { 6642 BYTE *got = got_ptr + decl_ptr->Offset; 6643 const BYTE *exp = exp_ptr + decl_ptr->Offset; 6644 BOOL same = got[0] == exp[0] && got[1] == exp[1] 6645 && got[2] == exp[2] && got[3] == exp[3]; 6646 ok_(__FILE__,line)(same, "Mesh %d: Got (%u, %u, %u, %u) for vertex %d %s, expected (%u, %u, %u, %u).\n", 6647 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]); 6648 break; 6649 } 6650 case D3DDECLTYPE_SHORT2: 6651 case D3DDECLTYPE_SHORT2N: 6652 { 6653 SHORT *got = (SHORT*)(got_ptr + decl_ptr->Offset); 6654 SHORT *exp = (SHORT*)(exp_ptr + decl_ptr->Offset); 6655 BOOL same = got[0] == exp[0] && got[1] == exp[1]; 6656 ok_(__FILE__,line)(same, "Mesh %d: Got (%hd, %hd) for vertex %d %s, expected (%hd, %hd).\n", 6657 mesh_number, got[0], got[1], vertex_number, usage_strings[decl_ptr->Usage], exp[0], exp[1]); 6658 break; 6659 } 6660 case D3DDECLTYPE_SHORT4: 6661 case D3DDECLTYPE_SHORT4N: 6662 { 6663 SHORT *got = (SHORT*)(got_ptr + decl_ptr->Offset); 6664 SHORT *exp = (SHORT*)(exp_ptr + decl_ptr->Offset); 6665 BOOL same = got[0] == exp[0] && got[1] == exp[1] 6666 && got[2] == exp[2] && got[3] == exp[3]; 6667 ok_(__FILE__,line)(same, "Mesh %d: Got (%hd, %hd, %hd, %hd) for vertex %d %s, expected (%hd, %hd, %hd, %hd).\n", 6668 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]); 6669 break; 6670 } 6671 case D3DDECLTYPE_USHORT2N: 6672 { 6673 USHORT *got = (USHORT*)(got_ptr + decl_ptr->Offset); 6674 USHORT *exp = (USHORT*)(exp_ptr + decl_ptr->Offset); 6675 BOOL same = got[0] == exp[0] && got[1] == exp[1]; 6676 ok_(__FILE__,line)(same, "Mesh %d: Got (%hu, %hu) for vertex %d %s, expected (%hu, %hu).\n", 6677 mesh_number, got[0], got[1], vertex_number, usage_strings[decl_ptr->Usage], exp[0], exp[1]); 6678 break; 6679 } 6680 case D3DDECLTYPE_USHORT4N: 6681 { 6682 USHORT *got = (USHORT*)(got_ptr + decl_ptr->Offset); 6683 USHORT *exp = (USHORT*)(exp_ptr + decl_ptr->Offset); 6684 BOOL same = got[0] == exp[0] && got[1] == exp[1] 6685 && got[2] == exp[2] && got[3] == exp[3]; 6686 ok_(__FILE__,line)(same, "Mesh %d: Got (%hu, %hu, %hu, %hu) for vertex %d %s, expected (%hu, %hu, %hu, %hu).\n", 6687 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]); 6688 break; 6689 } 6690 case D3DDECLTYPE_UDEC3: 6691 { 6692 DWORD *got = (DWORD*)(got_ptr + decl_ptr->Offset); 6693 DWORD *exp = (DWORD*)(exp_ptr + decl_ptr->Offset); 6694 BOOL same = memcmp(got, exp, sizeof(*got)) == 0; 6695 struct udec3 got_udec3 = dword_to_udec3(*got); 6696 struct udec3 exp_udec3 = dword_to_udec3(*exp); 6697 ok_(__FILE__,line)(same, "Mesh %d: Got (%u, %u, %u, %u) for vertex %d %s, expected (%u, %u, %u, %u).\n", 6698 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); 6699 6700 break; 6701 } 6702 case D3DDECLTYPE_DEC3N: 6703 { 6704 DWORD *got = (DWORD*)(got_ptr + decl_ptr->Offset); 6705 DWORD *exp = (DWORD*)(exp_ptr + decl_ptr->Offset); 6706 BOOL same = memcmp(got, exp, sizeof(*got)) == 0; 6707 struct dec3n got_dec3n = dword_to_dec3n(*got); 6708 struct dec3n exp_dec3n = dword_to_dec3n(*exp); 6709 ok_(__FILE__,line)(same, "Mesh %d: Got (%d, %d, %d, %d) for vertex %d %s, expected (%d, %d, %d, %d).\n", 6710 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); 6711 break; 6712 } 6713 case D3DDECLTYPE_FLOAT16_2: 6714 { 6715 WORD *got = (WORD*)(got_ptr + decl_ptr->Offset); 6716 WORD *exp = (WORD*)(exp_ptr + decl_ptr->Offset); 6717 BOOL same = got[0] == exp[0] && got[1] == exp[1]; 6718 ok_(__FILE__,line)(same, "Mesh %d: Got (%hx, %hx) for vertex %d %s, expected (%hx, %hx).\n", 6719 mesh_number, got[0], got[1], vertex_number, usage_strings[decl_ptr->Usage], exp[0], exp[1]); 6720 break; 6721 } 6722 case D3DDECLTYPE_FLOAT16_4: 6723 { 6724 WORD *got = (WORD*)(got_ptr + decl_ptr->Offset); 6725 WORD *exp = (WORD*)(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 (%hx, %hx, %hx, %hx) for vertex %d %s, expected (%hx, %hx, %hx, %hx).\n", 6729 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]); 6730 break; 6731 } 6732 default: 6733 break; 6734 } 6735 } 6736 } 6737 6738 static void test_weld_vertices(void) 6739 { 6740 HRESULT hr; 6741 struct test_context *test_context = NULL; 6742 DWORD i; 6743 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM; 6744 const DWORD options_16bit = D3DXMESH_SYSTEMMEM; 6745 BYTE *vertices = NULL; 6746 DWORD *indices = NULL; 6747 WORD *indices_16bit = NULL; 6748 const UINT VERTS_PER_FACE = 3; 6749 #ifndef __REACTOS__ 6750 const D3DXVECTOR3 up = {0.0f, 0.0f, 1.0f}; 6751 #else 6752 #define up {0.0f, 0.0f, 1.0f} 6753 #endif 6754 struct vertex_normal 6755 { 6756 D3DXVECTOR3 position; 6757 D3DXVECTOR3 normal; 6758 }; 6759 struct vertex_blendweight 6760 { 6761 D3DXVECTOR3 position; 6762 FLOAT blendweight; 6763 }; 6764 struct vertex_texcoord 6765 { 6766 D3DXVECTOR3 position; 6767 D3DXVECTOR2 texcoord; 6768 }; 6769 struct vertex_color 6770 { 6771 D3DXVECTOR3 position; 6772 DWORD color; 6773 }; 6774 struct vertex_color_ubyte4 6775 { 6776 D3DXVECTOR3 position; 6777 BYTE color[4]; 6778 }; 6779 struct vertex_texcoord_short2 6780 { 6781 D3DXVECTOR3 position; 6782 SHORT texcoord[2]; 6783 }; 6784 struct vertex_texcoord_ushort2n 6785 { 6786 D3DXVECTOR3 position; 6787 USHORT texcoord[2]; 6788 }; 6789 struct vertex_normal_short4 6790 { 6791 D3DXVECTOR3 position; 6792 SHORT normal[4]; 6793 }; 6794 struct vertex_texcoord_float16_2 6795 { 6796 D3DXVECTOR3 position; 6797 WORD texcoord[2]; 6798 }; 6799 struct vertex_texcoord_float16_4 6800 { 6801 D3DXVECTOR3 position; 6802 WORD texcoord[4]; 6803 }; 6804 struct vertex_normal_udec3 6805 { 6806 D3DXVECTOR3 position; 6807 DWORD normal; 6808 }; 6809 struct vertex_normal_dec3n 6810 { 6811 D3DXVECTOR3 position; 6812 DWORD normal; 6813 }; 6814 UINT vertex_size_normal = sizeof(struct vertex_normal); 6815 UINT vertex_size_blendweight = sizeof(struct vertex_blendweight); 6816 UINT vertex_size_texcoord = sizeof(struct vertex_texcoord); 6817 UINT vertex_size_color = sizeof(struct vertex_color); 6818 UINT vertex_size_color_ubyte4 = sizeof(struct vertex_color_ubyte4); 6819 UINT vertex_size_texcoord_short2 = sizeof(struct vertex_texcoord_short2); 6820 UINT vertex_size_normal_short4 = sizeof(struct vertex_normal_short4); 6821 UINT vertex_size_texcoord_float16_2 = sizeof(struct vertex_texcoord_float16_2); 6822 UINT vertex_size_texcoord_float16_4 = sizeof(struct vertex_texcoord_float16_4); 6823 UINT vertex_size_normal_udec3 = sizeof(struct vertex_normal_udec3); 6824 UINT vertex_size_normal_dec3n = sizeof(struct vertex_normal_dec3n); 6825 D3DVERTEXELEMENT9 declaration_normal[] = 6826 { 6827 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 6828 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 6829 D3DDECL_END() 6830 }; 6831 D3DVERTEXELEMENT9 declaration_normal3[] = 6832 { 6833 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 3}, 6834 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 6835 D3DDECL_END() 6836 }; 6837 D3DVERTEXELEMENT9 declaration_blendweight[] = 6838 { 6839 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 6840 {0, 12, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BLENDWEIGHT, 0}, 6841 D3DDECL_END() 6842 }; 6843 D3DVERTEXELEMENT9 declaration_texcoord[] = 6844 { 6845 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 6846 {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 6847 D3DDECL_END() 6848 }; 6849 D3DVERTEXELEMENT9 declaration_color[] = 6850 { 6851 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 6852 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0}, 6853 D3DDECL_END() 6854 }; 6855 D3DVERTEXELEMENT9 declaration_color_ubyte4n[] = 6856 { 6857 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 6858 {0, 12, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0}, 6859 D3DDECL_END() 6860 }; 6861 D3DVERTEXELEMENT9 declaration_color_ubyte4[] = 6862 { 6863 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 6864 {0, 12, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0}, 6865 D3DDECL_END() 6866 }; 6867 D3DVERTEXELEMENT9 declaration_texcoord_short2[] = 6868 { 6869 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 6870 {0, 12, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 6871 D3DDECL_END() 6872 }; 6873 D3DVERTEXELEMENT9 declaration_texcoord_short2n[] = 6874 { 6875 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 6876 {0, 12, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 6877 D3DDECL_END() 6878 }; 6879 D3DVERTEXELEMENT9 declaration_texcoord_ushort2n[] = 6880 { 6881 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 6882 {0, 12, D3DDECLTYPE_USHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 6883 D3DDECL_END() 6884 }; 6885 D3DVERTEXELEMENT9 declaration_normal_short4[] = 6886 { 6887 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 6888 {0, 12, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 6889 D3DDECL_END() 6890 }; 6891 D3DVERTEXELEMENT9 declaration_normal_short4n[] = 6892 { 6893 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 6894 {0, 12, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 6895 D3DDECL_END() 6896 }; 6897 D3DVERTEXELEMENT9 declaration_normal_ushort4n[] = 6898 { 6899 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 6900 {0, 12, D3DDECLTYPE_USHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 6901 D3DDECL_END() 6902 }; 6903 D3DVERTEXELEMENT9 declaration_texcoord10[] = 6904 { 6905 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 6906 {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 10}, 6907 D3DDECL_END() 6908 }; 6909 D3DVERTEXELEMENT9 declaration_color2[] = 6910 { 6911 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 6912 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 2}, 6913 D3DDECL_END() 6914 }; 6915 D3DVERTEXELEMENT9 declaration_color1[] = 6916 { 6917 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 6918 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 1}, 6919 D3DDECL_END() 6920 }; 6921 D3DVERTEXELEMENT9 declaration_texcoord_float16_2[] = 6922 { 6923 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 6924 {0, 12, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 6925 D3DDECL_END() 6926 }; 6927 D3DVERTEXELEMENT9 declaration_texcoord_float16_4[] = 6928 { 6929 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 6930 {0, 12, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 6931 D3DDECL_END() 6932 }; 6933 D3DVERTEXELEMENT9 declaration_normal_udec3[] = 6934 { 6935 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 6936 {0, 12, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 6937 D3DDECL_END() 6938 }; 6939 D3DVERTEXELEMENT9 declaration_normal_dec3n[] = 6940 { 6941 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 6942 {0, 12, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 6943 D3DDECL_END() 6944 }; 6945 /* Test 0. One face and no welding. 6946 * 6947 * 0--1 6948 * | / 6949 * |/ 6950 * 2 6951 */ 6952 const struct vertex vertices0[] = 6953 { 6954 {{ 0.0f, 3.0f, 0.f}, up}, 6955 {{ 2.0f, 3.0f, 0.f}, up}, 6956 {{ 0.0f, 0.0f, 0.f}, up}, 6957 }; 6958 const DWORD indices0[] = {0, 1, 2}; 6959 const DWORD attributes0[] = {0}; 6960 const DWORD exp_indices0[] = {0, 1, 2}; 6961 const UINT num_vertices0 = ARRAY_SIZE(vertices0); 6962 const UINT num_faces0 = ARRAY_SIZE(indices0) / VERTS_PER_FACE; 6963 const DWORD flags0 = D3DXWELDEPSILONS_WELDALL; 6964 /* epsilons0 is NULL */ 6965 const DWORD adjacency0[] = {-1, -1, -1}; 6966 const struct vertex exp_vertices0[] = 6967 { 6968 {{ 0.0f, 3.0f, 0.f}, up}, 6969 {{ 2.0f, 3.0f, 0.f}, up}, 6970 {{ 0.0f, 0.0f, 0.f}, up}, 6971 }; 6972 const DWORD exp_face_remap0[] = {0}; 6973 const DWORD exp_vertex_remap0[] = {0, 1, 2}; 6974 const DWORD exp_new_num_vertices0 = ARRAY_SIZE(exp_vertices0); 6975 /* Test 1. Two vertices should be removed without regard to epsilon. 6976 * 6977 * 0--1 3 6978 * | / /| 6979 * |/ / | 6980 * 2 5--4 6981 */ 6982 const struct vertex_normal vertices1[] = 6983 { 6984 {{ 0.0f, 3.0f, 0.f}, up}, 6985 {{ 2.0f, 3.0f, 0.f}, up}, 6986 {{ 0.0f, 0.0f, 0.f}, up}, 6987 6988 {{ 3.0f, 3.0f, 0.f}, up}, 6989 {{ 3.0f, 0.0f, 0.f}, up}, 6990 {{ 1.0f, 0.0f, 0.f}, up}, 6991 }; 6992 const DWORD indices1[] = {0, 1, 2, 3, 4, 5}; 6993 const DWORD attributes1[] = {0, 0}; 6994 const UINT num_vertices1 = ARRAY_SIZE(vertices1); 6995 const UINT num_faces1 = ARRAY_SIZE(indices1) / VERTS_PER_FACE; 6996 const DWORD flags1 = D3DXWELDEPSILONS_WELDALL; 6997 /* epsilons1 is NULL */ 6998 const DWORD adjacency1[] = {-1, 1, -1, -1, -1, 0}; 6999 const struct vertex_normal exp_vertices1[] = 7000 { 7001 {{ 0.0f, 3.0f, 0.f}, up}, 7002 {{ 2.0f, 3.0f, 0.f}, up}, 7003 {{ 0.0f, 0.0f, 0.f}, up}, 7004 7005 {{ 3.0f, 0.0f, 0.f}, up} 7006 }; 7007 const DWORD exp_indices1[] = {0, 1, 2, 1, 3, 2}; 7008 const DWORD exp_face_remap1[] = {0, 1}; 7009 const DWORD exp_vertex_remap1[] = {0, 1, 2, 4, -1, -1}; 7010 const DWORD exp_new_num_vertices1 = ARRAY_SIZE(exp_vertices1); 7011 /* Test 2. Two faces. No vertices should be removed because of normal 7012 * epsilon, but the positions should be replaced. */ 7013 const struct vertex_normal vertices2[] = 7014 { 7015 {{ 0.0f, 3.0f, 0.f}, up}, 7016 {{ 2.0f, 3.0f, 0.f}, up}, 7017 {{ 0.0f, 0.0f, 0.f}, up}, 7018 7019 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}}, 7020 {{ 3.0f, 0.0f, 0.f}, up}, 7021 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}}, 7022 }; 7023 const DWORD indices2[] = {0, 1, 2, 3, 4, 5}; 7024 const DWORD attributes2[] = {0, 0}; 7025 const UINT num_vertices2 = ARRAY_SIZE(vertices2); 7026 const UINT num_faces2 = ARRAY_SIZE(indices2) / VERTS_PER_FACE; 7027 DWORD flags2 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7028 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}; 7029 const DWORD adjacency2[] = {-1, 1, -1, -1, -1, 0}; 7030 const struct vertex_normal exp_vertices2[] = 7031 { 7032 {{ 0.0f, 3.0f, 0.f}, up}, 7033 {{ 2.0f, 3.0f, 0.f}, up}, 7034 {{ 0.0f, 0.0f, 0.f}, up}, 7035 7036 {{ 2.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}}, 7037 {{ 3.0f, 0.0f, 0.f}, up}, 7038 {{ 0.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}}, 7039 }; 7040 const DWORD exp_indices2[] = {0, 1, 2, 3, 4, 5}; 7041 const DWORD exp_face_remap2[] = {0, 1}; 7042 const DWORD exp_vertex_remap2[] = {0, 1, 2, 3, 4, 5}; 7043 const DWORD exp_new_num_vertices2 = ARRAY_SIZE(exp_vertices2); 7044 /* Test 3. Two faces. One vertex should be removed because of normal epsilon. */ 7045 const struct vertex_normal vertices3[] = 7046 { 7047 {{ 0.0f, 3.0f, 0.f}, up}, 7048 {{ 2.0f, 3.0f, 0.f}, up}, 7049 {{ 0.0f, 0.0f, 0.f}, up}, 7050 7051 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}}, 7052 {{ 3.0f, 0.0f, 0.f}, up}, 7053 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}}, 7054 }; 7055 const DWORD indices3[] = {0, 1, 2, 3, 4, 5}; 7056 const DWORD attributes3[] = {0, 0}; 7057 const UINT num_vertices3 = ARRAY_SIZE(vertices3); 7058 const UINT num_faces3 = ARRAY_SIZE(indices3) / VERTS_PER_FACE; 7059 DWORD flags3 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7060 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}; 7061 const DWORD adjacency3[] = {-1, 1, -1, -1, -1, 0}; 7062 const struct vertex_normal exp_vertices3[] = 7063 { 7064 {{ 0.0f, 3.0f, 0.f}, up}, 7065 {{ 2.0f, 3.0f, 0.f}, up}, 7066 {{ 0.0f, 0.0f, 0.f}, up}, 7067 7068 {{ 3.0f, 0.0f, 0.f}, up}, 7069 {{ 0.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}}, 7070 }; 7071 const DWORD exp_indices3[] = {0, 1, 2, 1, 3, 4}; 7072 const DWORD exp_face_remap3[] = {0, 1}; 7073 const DWORD exp_vertex_remap3[] = {0, 1, 2, 4, 5, -1}; 7074 const DWORD exp_new_num_vertices3 = ARRAY_SIZE(exp_vertices3); 7075 /* Test 4 Two faces. Two vertices should be removed. */ 7076 const struct vertex_normal vertices4[] = 7077 { 7078 {{ 0.0f, 3.0f, 0.f}, up}, 7079 {{ 2.0f, 3.0f, 0.f}, up}, 7080 {{ 0.0f, 0.0f, 0.f}, up}, 7081 7082 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}}, 7083 {{ 3.0f, 0.0f, 0.f}, up}, 7084 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}}, 7085 }; 7086 const DWORD indices4[] = {0, 1, 2, 3, 4, 5}; 7087 const DWORD attributes4[] = {0, 0}; 7088 const UINT num_vertices4 = ARRAY_SIZE(vertices4); 7089 const UINT num_faces4 = ARRAY_SIZE(indices4) / VERTS_PER_FACE; 7090 DWORD flags4 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7091 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}; 7092 const DWORD adjacency4[] = {-1, 1, -1, -1, -1, 0}; 7093 const struct vertex_normal exp_vertices4[] = 7094 { 7095 {{ 0.0f, 3.0f, 0.f}, up}, 7096 {{ 2.0f, 3.0f, 0.f}, up}, 7097 {{ 0.0f, 0.0f, 0.f}, up}, 7098 7099 {{ 3.0f, 0.0f, 0.f}, up}, 7100 }; 7101 const DWORD exp_indices4[] = {0, 1, 2, 1, 3, 2}; 7102 const DWORD exp_face_remap4[] = {0, 1}; 7103 const DWORD exp_vertex_remap4[] = {0, 1, 2, 4, -1, -1}; 7104 const DWORD exp_new_num_vertices4 = ARRAY_SIZE(exp_vertices4); 7105 /* Test 5. Odd face ordering. 7106 * 7107 * 0--1 6 3 7108 * | / /| |\ 7109 * |/ / | | \ 7110 * 2 8--7 5--4 7111 */ 7112 const struct vertex_normal vertices5[] = 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 {{ 3.0f, 3.0f, 0.f}, up}, 7119 {{ 3.0f, 0.0f, 0.f}, up}, 7120 {{ 1.0f, 0.0f, 0.f}, up}, 7121 7122 {{ 4.0f, 3.0f, 0.f}, up}, 7123 {{ 6.0f, 0.0f, 0.f}, up}, 7124 {{ 4.0f, 0.0f, 0.f}, up}, 7125 }; 7126 const DWORD indices5[] = {0, 1, 2, 6, 7, 8, 3, 4, 5}; 7127 const DWORD exp_indices5[] = {0, 1, 2, 1, 4, 2, 1, 3, 4}; 7128 const DWORD attributes5[] = {0, 0, 0}; 7129 const UINT num_vertices5 = ARRAY_SIZE(vertices5); 7130 const UINT num_faces5 = ARRAY_SIZE(indices5) / VERTS_PER_FACE; 7131 DWORD flags5 = D3DXWELDEPSILONS_WELDALL; 7132 const DWORD adjacency5[] = {-1, 1, -1, 2, -1, 0, -1, -1, 1}; 7133 const struct vertex_normal exp_vertices5[] = 7134 { 7135 {{ 0.0f, 3.0f, 0.f}, up}, 7136 {{ 2.0f, 3.0f, 0.f}, up}, 7137 {{ 0.0f, 0.0f, 0.f}, up}, 7138 7139 {{ 3.0f, 0.0f, 0.f}, up}, 7140 {{ 1.0f, 0.0f, 0.f}, up}, 7141 }; 7142 const DWORD exp_face_remap5[] = {0, 1, 2}; 7143 const DWORD exp_vertex_remap5[] = {0, 1, 2, 4, 5, -1, -1, -1, -1}; 7144 const DWORD exp_new_num_vertices5 = ARRAY_SIZE(exp_vertices5); 7145 /* Test 6. Two faces. Do not remove flag is used, so no vertices should be 7146 * removed. */ 7147 const struct vertex_normal vertices6[] = 7148 { 7149 {{ 0.0f, 3.0f, 0.f}, up}, 7150 {{ 2.0f, 3.0f, 0.f}, up}, 7151 {{ 0.0f, 0.0f, 0.f}, up}, 7152 7153 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}}, 7154 {{ 3.0f, 0.0f, 0.f}, up}, 7155 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}}, 7156 }; 7157 const DWORD indices6[] = {0, 1, 2, 3, 4, 5}; 7158 const DWORD attributes6[] = {0, 0}; 7159 const UINT num_vertices6 = ARRAY_SIZE(vertices6); 7160 const UINT num_faces6 = ARRAY_SIZE(indices6) / VERTS_PER_FACE; 7161 DWORD flags6 = D3DXWELDEPSILONS_WELDPARTIALMATCHES | D3DXWELDEPSILONS_DONOTREMOVEVERTICES; 7162 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}; 7163 const DWORD adjacency6[] = {-1, 1, -1, -1, -1, 0}; 7164 const struct vertex_normal exp_vertices6[] = 7165 { 7166 {{ 0.0f, 3.0f, 0.f}, up}, 7167 {{ 2.0f, 3.0f, 0.f}, up}, 7168 {{ 0.0f, 0.0f, 0.f}, up}, 7169 7170 {{ 2.0f, 3.0f, 0.f}, up}, 7171 {{ 3.0f, 0.0f, 0.f}, up}, 7172 {{ 0.0f, 0.0f, 0.f}, up}, 7173 7174 }; 7175 const DWORD exp_indices6[] = {0, 1, 2, 3, 4, 5}; 7176 const DWORD exp_face_remap6[] = {0, 1}; 7177 const DWORD exp_vertex_remap6[] = {0, 1, 2, 3, 4, 5}; 7178 const DWORD exp_new_num_vertices6 = ARRAY_SIZE(exp_vertices6); 7179 /* Test 7. Same as test 6 but with 16 bit indices. */ 7180 const WORD indices6_16bit[] = {0, 1, 2, 3, 4, 5}; 7181 /* Test 8. No flags. Same result as D3DXWELDEPSILONS_WELDPARTIALMATCHES. */ 7182 const struct vertex_normal vertices8[] = 7183 { 7184 {{ 0.0f, 3.0f, 0.f}, up}, 7185 {{ 2.0f, 3.0f, 0.f}, up}, 7186 {{ 0.0f, 0.0f, 0.f}, up}, 7187 7188 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}}, 7189 {{ 3.0f, 0.0f, 0.f}, up}, 7190 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}}, 7191 }; 7192 const DWORD indices8[] = {0, 1, 2, 1, 3, 4}; 7193 const DWORD attributes8[] = {0, 0}; 7194 const UINT num_vertices8 = ARRAY_SIZE(vertices8); 7195 const UINT num_faces8 = ARRAY_SIZE(indices8) / VERTS_PER_FACE; 7196 DWORD flags8 = 0; 7197 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}; 7198 const DWORD adjacency8[] = {-1, 1, -1, -1, -1, 0}; 7199 const struct vertex_normal exp_vertices8[] = 7200 { 7201 {{ 0.0f, 3.0f, 0.f}, up}, 7202 {{ 2.0f, 3.0f, 0.f}, up}, 7203 {{ 0.0f, 0.0f, 0.f}, up}, 7204 7205 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}}, 7206 {{ 3.0f, 0.0f, 0.f}, up}, 7207 }; 7208 const DWORD exp_indices8[] = {0, 1, 2, 1, 3, 4}; 7209 const DWORD exp_face_remap8[] = {0, 1}; 7210 const DWORD exp_vertex_remap8[] = {0, 1, 2, 3, 4, -1}; 7211 const DWORD exp_new_num_vertices8 = ARRAY_SIZE(exp_vertices8); 7212 /* Test 9. Vertices are removed even though they belong to separate 7213 * attribute groups if D3DXWELDEPSILONS_DONOTSPLIT is set. */ 7214 const struct vertex_normal vertices9[] = 7215 { 7216 {{ 0.0f, 3.0f, 0.f}, up}, 7217 {{ 2.0f, 3.0f, 0.f}, up}, 7218 {{ 0.0f, 0.0f, 0.f}, up}, 7219 7220 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}}, 7221 {{ 3.0f, 0.0f, 0.f}, up}, 7222 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}}, 7223 }; 7224 const DWORD indices9[] = {0, 1, 2, 3, 4, 5}; 7225 const DWORD attributes9[] = {0, 1}; 7226 const UINT num_vertices9 = ARRAY_SIZE(vertices9); 7227 const UINT num_faces9 = ARRAY_SIZE(indices9) / VERTS_PER_FACE; 7228 DWORD flags9 = D3DXWELDEPSILONS_WELDPARTIALMATCHES | D3DXWELDEPSILONS_DONOTSPLIT; 7229 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}; 7230 const DWORD adjacency9[] = {-1, 1, -1, -1, -1, 0}; 7231 const struct vertex_normal exp_vertices9[] = 7232 { 7233 {{ 0.0f, 3.0f, 0.f}, up}, 7234 {{ 2.0f, 3.0f, 0.f}, up}, 7235 {{ 0.0f, 0.0f, 0.f}, up}, 7236 7237 {{ 3.0f, 0.0f, 0.f}, up}, 7238 }; 7239 const DWORD exp_indices9[] = {0, 1, 2, 1, 3, 2}; 7240 const DWORD exp_face_remap9[] = {0, 1}; 7241 const DWORD exp_vertex_remap9[] = {0, 1, 2, 4, -1, -1}; 7242 const DWORD exp_new_num_vertices9 = ARRAY_SIZE(exp_vertices9); 7243 /* Test 10. Weld blendweight (FLOAT1). */ 7244 const struct vertex_blendweight vertices10[] = 7245 { 7246 {{ 0.0f, 3.0f, 0.f}, 1.0f}, 7247 {{ 2.0f, 3.0f, 0.f}, 1.0f}, 7248 {{ 0.0f, 0.0f, 0.f}, 1.0f}, 7249 7250 {{ 3.0f, 3.0f, 0.f}, 0.9}, 7251 {{ 3.0f, 0.0f, 0.f}, 1.0}, 7252 {{ 1.0f, 0.0f, 0.f}, 0.4}, 7253 }; 7254 const DWORD indices10[] = {0, 1, 2, 3, 4, 5}; 7255 const DWORD attributes10[] = {0, 0}; 7256 const UINT num_vertices10 = ARRAY_SIZE(vertices10); 7257 const UINT num_faces10 = ARRAY_SIZE(indices10) / VERTS_PER_FACE; 7258 DWORD flags10 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7259 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}; 7260 const DWORD adjacency10[] = {-1, 1, -1, -1, -1, 0}; 7261 const struct vertex_blendweight exp_vertices10[] = 7262 { 7263 {{ 0.0f, 3.0f, 0.f}, 1.0f}, 7264 {{ 2.0f, 3.0f, 0.f}, 1.0f}, 7265 {{ 0.0f, 0.0f, 0.f}, 1.0f}, 7266 7267 {{ 3.0f, 0.0f, 0.f}, 1.0}, 7268 {{ 0.0f, 0.0f, 0.f}, 0.4}, 7269 }; 7270 const DWORD exp_indices10[] = {0, 1, 2, 1, 3, 4}; 7271 const DWORD exp_face_remap10[] = {0, 1}; 7272 const DWORD exp_vertex_remap10[] = {0, 1, 2, 4, 5, -1}; 7273 const DWORD exp_new_num_vertices10 = ARRAY_SIZE(exp_vertices10); 7274 /* Test 11. Weld texture coordinates. */ 7275 const struct vertex_texcoord vertices11[] = 7276 { 7277 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f}}, 7278 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.7f}}, 7279 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}}, 7280 7281 {{ 3.0f, 3.0f, 0.f}, {0.2f, 0.3f}}, 7282 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f}}, 7283 {{ 1.0f, 0.0f, 0.f}, {0.1f, 0.2f}} 7284 }; 7285 const DWORD indices11[] = {0, 1, 2, 3, 4, 5}; 7286 const DWORD attributes11[] = {0, 0}; 7287 const UINT num_vertices11 = ARRAY_SIZE(vertices11); 7288 const UINT num_faces11 = ARRAY_SIZE(indices11) / VERTS_PER_FACE; 7289 DWORD flags11 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7290 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}; 7291 const DWORD adjacency11[] = {-1, 1, -1, -1, -1, 0}; 7292 const struct vertex_texcoord exp_vertices11[] = 7293 { 7294 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f}}, 7295 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.7f}}, 7296 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}}, 7297 7298 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f}}, 7299 {{ 0.0f, 0.0f, 0.f}, {0.1f, 0.2f}}, 7300 }; 7301 const DWORD exp_indices11[] = {0, 1, 2, 1, 3, 4}; 7302 const DWORD exp_face_remap11[] = {0, 1}; 7303 const DWORD exp_vertex_remap11[] = {0, 1, 2, 4, 5, -1}; 7304 const DWORD exp_new_num_vertices11 = ARRAY_SIZE(exp_vertices11); 7305 /* Test 12. Weld with color. */ 7306 const struct vertex_color vertices12[] = 7307 { 7308 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF}, 7309 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF}, 7310 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF}, 7311 7312 {{ 3.0f, 3.0f, 0.f}, 0x00000000}, 7313 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF}, 7314 {{ 1.0f, 0.0f, 0.f}, 0x88888888}, 7315 }; 7316 const DWORD indices12[] = {0, 1, 2, 3, 4, 5}; 7317 const DWORD attributes12[] = {0, 0}; 7318 const UINT num_vertices12 = ARRAY_SIZE(vertices12); 7319 const UINT num_faces12 = ARRAY_SIZE(indices12) / VERTS_PER_FACE; 7320 DWORD flags12 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7321 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}; 7322 const DWORD adjacency12[] = {-1, 1, -1, -1, -1, 0}; 7323 const struct vertex_color exp_vertices12[] = 7324 { 7325 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF}, 7326 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF}, 7327 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF}, 7328 7329 {{ 2.0f, 3.0f, 0.f}, 0x00000000}, 7330 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF}, 7331 }; 7332 const DWORD exp_indices12[] = {0, 1, 2, 3, 4, 2}; 7333 const DWORD exp_face_remap12[] = {0, 1}; 7334 const DWORD exp_vertex_remap12[] = {0, 1, 2, 3, 4, -1}; 7335 const DWORD exp_new_num_vertices12 = ARRAY_SIZE(exp_vertices12); 7336 /* Test 13. Two faces. One vertex should be removed because of normal epsilon. 7337 * This is similar to test 3, but the declaration has been changed to NORMAL3. 7338 */ 7339 const struct vertex_normal vertices13[] = 7340 { 7341 {{ 0.0f, 3.0f, 0.f}, up}, 7342 {{ 2.0f, 3.0f, 0.f}, up}, 7343 {{ 0.0f, 0.0f, 0.f}, up}, 7344 7345 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}}, 7346 {{ 3.0f, 0.0f, 0.f}, up}, 7347 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}}, 7348 }; 7349 const DWORD indices13[] = {0, 1, 2, 3, 4, 5}; 7350 const DWORD attributes13[] = {0, 0}; 7351 const UINT num_vertices13 = ARRAY_SIZE(vertices3); 7352 const UINT num_faces13 = ARRAY_SIZE(indices3) / VERTS_PER_FACE; 7353 DWORD flags13 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7354 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}; 7355 const DWORD adjacency13[] = {-1, 1, -1, -1, -1, 0}; 7356 const struct vertex_normal exp_vertices13[] = 7357 { 7358 {{ 0.0f, 3.0f, 0.f}, up}, 7359 {{ 2.0f, 3.0f, 0.f}, up}, 7360 {{ 0.0f, 0.0f, 0.f}, up}, 7361 7362 {{ 3.0f, 0.0f, 0.f}, up}, 7363 {{ 0.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}}, 7364 }; 7365 const DWORD exp_indices13[] = {0, 1, 2, 1, 3, 4}; 7366 const DWORD exp_face_remap13[] = {0, 1}; 7367 const DWORD exp_vertex_remap13[] = {0, 1, 2, 4, 5, -1}; 7368 const DWORD exp_new_num_vertices13 = ARRAY_SIZE(exp_vertices13); 7369 /* Test 14. Another test for welding with color. */ 7370 const struct vertex_color vertices14[] = 7371 { 7372 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF}, 7373 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF}, 7374 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF}, 7375 7376 {{ 3.0f, 3.0f, 0.f}, 0x00000000}, 7377 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF}, 7378 {{ 1.0f, 0.0f, 0.f}, 0x01010101}, 7379 }; 7380 const DWORD indices14[] = {0, 1, 2, 3, 4, 5}; 7381 const DWORD attributes14[] = {0, 0}; 7382 const UINT num_vertices14 = ARRAY_SIZE(vertices14); 7383 const UINT num_faces14 = ARRAY_SIZE(indices14) / VERTS_PER_FACE; 7384 DWORD flags14 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7385 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}; 7386 const DWORD adjacency14[] = {-1, 1, -1, -1, -1, 0}; 7387 const struct vertex_color exp_vertices14[] = 7388 { 7389 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF}, 7390 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF}, 7391 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF}, 7392 7393 {{ 2.0f, 3.0f, 0.f}, 0x00000000}, 7394 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF}, 7395 }; 7396 const DWORD exp_indices14[] = {0, 1, 2, 3, 4, 2}; 7397 const DWORD exp_face_remap14[] = {0, 1}; 7398 const DWORD exp_vertex_remap14[] = {0, 1, 2, 3, 4, -1}; 7399 const DWORD exp_new_num_vertices14 = ARRAY_SIZE(exp_vertices14); 7400 /* Test 15. Weld with color, but as UBYTE4N instead of D3DCOLOR. It shows 7401 * that UBYTE4N and D3DCOLOR are compared the same way. 7402 */ 7403 const struct vertex_color_ubyte4 vertices15[] = 7404 { 7405 {{ 0.0f, 3.0f, 0.f}, {255, 255, 255, 255}}, 7406 {{ 2.0f, 3.0f, 0.f}, {255, 255, 255, 255}}, 7407 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}}, 7408 7409 {{ 3.0f, 3.0f, 0.f}, { 0, 0, 0, 0}}, 7410 {{ 3.0f, 0.0f, 0.f}, {255, 255, 255, 255}}, 7411 {{ 1.0f, 0.0f, 0.f}, { 1, 1, 1, 1}}, 7412 }; 7413 const DWORD indices15[] = {0, 1, 2, 3, 4, 5}; 7414 const DWORD attributes15[] = {0, 0}; 7415 const UINT num_vertices15 = ARRAY_SIZE(vertices15); 7416 const UINT num_faces15 = ARRAY_SIZE(indices15) / VERTS_PER_FACE; 7417 DWORD flags15 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7418 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}; 7419 const DWORD adjacency15[] = {-1, 1, -1, -1, -1, 0}; 7420 const struct vertex_color_ubyte4 exp_vertices15[] = 7421 { 7422 {{ 0.0f, 3.0f, 0.f}, {255, 255, 255, 255}}, 7423 {{ 2.0f, 3.0f, 0.f}, {255, 255, 255, 255}}, 7424 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}}, 7425 7426 {{ 2.0f, 3.0f, 0.f}, { 0, 0, 0, 0}}, 7427 {{ 3.0f, 0.0f, 0.f}, {255, 255, 255, 255}}, 7428 }; 7429 const DWORD exp_indices15[] = {0, 1, 2, 3, 4, 2}; 7430 const DWORD exp_face_remap15[] = {0, 1}; 7431 const DWORD exp_vertex_remap15[] = {0, 1, 2, 3, 4, -1}; 7432 const DWORD exp_new_num_vertices15 = ARRAY_SIZE(exp_vertices15); 7433 /* Test 16. Weld with color, but as UBYTE4 instead of D3DCOLOR. It shows 7434 * that UBYTE4 is not normalized and that epsilon is truncated and compared 7435 * directly to each of the four bytes. 7436 */ 7437 const struct vertex_color_ubyte4 vertices16[] = 7438 { 7439 {{ 0.0f, 3.0f, 0.f}, {255, 255, 255, 255}}, 7440 {{ 2.0f, 3.0f, 0.f}, {255, 255, 255, 255}}, 7441 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}}, 7442 7443 {{ 3.0f, 3.0f, 0.f}, { 0, 0, 0, 0}}, 7444 {{ 3.0f, 0.0f, 0.f}, {255, 255, 255, 255}}, 7445 {{ 1.0f, 0.0f, 0.f}, { 1, 1, 1, 1}}, 7446 }; 7447 const DWORD indices16[] = {0, 1, 2, 3, 4, 5}; 7448 const DWORD attributes16[] = {0, 0}; 7449 const UINT num_vertices16 = ARRAY_SIZE(vertices16); 7450 const UINT num_faces16 = ARRAY_SIZE(indices16) / VERTS_PER_FACE; 7451 DWORD flags16 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7452 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}; 7453 const DWORD adjacency16[] = {-1, 1, -1, -1, -1, 0}; 7454 const struct vertex_color_ubyte4 exp_vertices16[] = 7455 { 7456 {{ 0.0f, 3.0f, 0.f}, {255, 255, 255, 255}}, 7457 {{ 2.0f, 3.0f, 0.f}, {255, 255, 255, 255}}, 7458 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}}, 7459 7460 {{ 2.0f, 3.0f, 0.f}, { 0, 0, 0, 0}}, 7461 {{ 3.0f, 0.0f, 0.f}, {255, 255, 255, 255}}, 7462 }; 7463 const DWORD exp_indices16[] = {0, 1, 2, 3, 4, 2}; 7464 const DWORD exp_face_remap16[] = {0, 1}; 7465 const DWORD exp_vertex_remap16[] = {0, 1, 2, 3, 4, -1}; 7466 const DWORD exp_new_num_vertices16 = ARRAY_SIZE(exp_vertices16); 7467 /* Test 17. Weld texture coordinates but as SHORT2 instead of D3DXVECTOR2.*/ 7468 const struct vertex_texcoord_short2 vertices17[] = 7469 { 7470 {{ 0.0f, 3.0f, 0.f}, { 0, 0}}, 7471 {{ 2.0f, 3.0f, 0.f}, { 0, 0}}, 7472 {{ 0.0f, 0.0f, 0.f}, { 0, 0}}, 7473 7474 {{ 3.0f, 3.0f, 0.f}, {32767, 32767}}, 7475 {{ 3.0f, 0.0f, 0.f}, {0, 0}}, 7476 {{ 1.0f, 0.0f, 0.f}, {32766, 32766}}, 7477 }; 7478 const DWORD indices17[] = {0, 1, 2, 3, 4, 5}; 7479 const DWORD attributes17[] = {0, 0}; 7480 const UINT num_vertices17 = ARRAY_SIZE(vertices17); 7481 const UINT num_faces17 = ARRAY_SIZE(indices17) / VERTS_PER_FACE; 7482 DWORD flags17 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7483 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}; 7484 const DWORD adjacency17[] = {-1, 1, -1, -1, -1, 0}; 7485 const struct vertex_texcoord_short2 exp_vertices17[] = 7486 { 7487 {{ 0.0f, 3.0f, 0.f}, { 0, 0}}, 7488 {{ 2.0f, 3.0f, 0.f}, { 0, 0}}, 7489 {{ 0.0f, 0.0f, 0.f}, { 0, 0}}, 7490 7491 {{ 2.0f, 3.0f, 0.f}, {32767, 32767}}, 7492 {{ 3.0f, 0.0f, 0.f}, {0, 0}}, 7493 }; 7494 const DWORD exp_indices17[] = {0, 1, 2, 3, 4, 2}; 7495 const DWORD exp_face_remap17[] = {0, 1}; 7496 const DWORD exp_vertex_remap17[] = {0, 1, 2, 3, 4, -1}; 7497 const DWORD exp_new_num_vertices17 = ARRAY_SIZE(exp_vertices17); 7498 /* Test 18. Weld texture coordinates but as SHORT2N instead of D3DXVECTOR2. */ 7499 const struct vertex_texcoord_short2 vertices18[] = 7500 { 7501 {{ 0.0f, 3.0f, 0.f}, { 0, 0}}, 7502 {{ 2.0f, 3.0f, 0.f}, { 0, 0}}, 7503 {{ 0.0f, 0.0f, 0.f}, { 0, 0}}, 7504 7505 {{ 3.0f, 3.0f, 0.f}, {32767, 32767}}, 7506 {{ 3.0f, 0.0f, 0.f}, {0, 0}}, 7507 {{ 1.0f, 0.0f, 0.f}, {32766, 32766}}, 7508 }; 7509 const DWORD indices18[] = {0, 1, 2, 3, 4, 5}; 7510 const DWORD attributes18[] = {0, 0}; 7511 const UINT num_vertices18 = ARRAY_SIZE(vertices18); 7512 const UINT num_faces18 = ARRAY_SIZE(indices18) / VERTS_PER_FACE; 7513 DWORD flags18 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7514 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}; 7515 const DWORD adjacency18[] = {-1, 1, -1, -1, -1, 0}; 7516 const struct vertex_texcoord_short2 exp_vertices18[] = 7517 { 7518 {{ 0.0f, 3.0f, 0.f}, { 0, 0}}, 7519 {{ 2.0f, 3.0f, 0.f}, { 0, 0}}, 7520 {{ 0.0f, 0.0f, 0.f}, { 0, 0}}, 7521 7522 {{ 2.0f, 3.0f, 0.f}, {32767, 32767}}, 7523 {{ 3.0f, 0.0f, 0.f}, {0, 0}}, 7524 }; 7525 const DWORD exp_indices18[] = {0, 1, 2, 3, 4, 2}; 7526 const DWORD exp_face_remap18[] = {0, 1}; 7527 const DWORD exp_vertex_remap18[] = {0, 1, 2, 3, 4, -1}; 7528 const DWORD exp_new_num_vertices18 = ARRAY_SIZE(exp_vertices18); 7529 /* Test 19. Weld texture coordinates but as USHORT2N instead of D3DXVECTOR2. */ 7530 const struct vertex_texcoord_ushort2n vertices19[] = 7531 { 7532 {{ 0.0f, 3.0f, 0.f}, { 0, 0}}, 7533 {{ 2.0f, 3.0f, 0.f}, { 0, 0}}, 7534 {{ 0.0f, 0.0f, 0.f}, { 0, 0}}, 7535 7536 {{ 3.0f, 3.0f, 0.f}, {65535, 65535}}, 7537 {{ 3.0f, 0.0f, 0.f}, {0, 0}}, 7538 {{ 1.0f, 0.0f, 0.f}, {65534, 65534}}, 7539 }; 7540 const DWORD indices19[] = {0, 1, 2, 3, 4, 5}; 7541 const DWORD attributes19[] = {0, 0}; 7542 const UINT num_vertices19 = ARRAY_SIZE(vertices19); 7543 const UINT num_faces19 = ARRAY_SIZE(indices19) / VERTS_PER_FACE; 7544 DWORD flags19 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7545 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}; 7546 const DWORD adjacency19[] = {-1, 1, -1, -1, -1, 0}; 7547 const struct vertex_texcoord_ushort2n exp_vertices19[] = 7548 { 7549 {{ 0.0f, 3.0f, 0.f}, { 0, 0}}, 7550 {{ 2.0f, 3.0f, 0.f}, { 0, 0}}, 7551 {{ 0.0f, 0.0f, 0.f}, { 0, 0}}, 7552 7553 {{ 2.0f, 3.0f, 0.f}, {65535, 65535}}, 7554 {{ 3.0f, 0.0f, 0.f}, {0, 0}}, 7555 }; 7556 const DWORD exp_indices19[] = {0, 1, 2, 3, 4, 2}; 7557 const DWORD exp_face_remap19[] = {0, 1}; 7558 const DWORD exp_vertex_remap19[] = {0, 1, 2, 3, 4, -1}; 7559 const DWORD exp_new_num_vertices19 = ARRAY_SIZE(exp_vertices19); 7560 /* Test 20. Weld normal as SHORT4 instead of D3DXVECTOR3. */ 7561 const struct vertex_normal_short4 vertices20[] = 7562 { 7563 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, 7564 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, 7565 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}}, 7566 7567 {{ 3.0f, 3.0f, 0.f}, {32767, 32767, 32767, 32767}}, 7568 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}}, 7569 {{ 1.0f, 0.0f, 0.f}, {32766, 32766, 32766, 32766}}, 7570 }; 7571 const DWORD indices20[] = {0, 1, 2, 3, 4, 5}; 7572 const DWORD attributes20[] = {0, 0}; 7573 const UINT num_vertices20 = ARRAY_SIZE(vertices20); 7574 const UINT num_faces20 = ARRAY_SIZE(indices20) / VERTS_PER_FACE; 7575 DWORD flags20 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7576 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}; 7577 const DWORD adjacency20[] = {-1, 1, -1, -1, -1, 0}; 7578 const struct vertex_normal_short4 exp_vertices20[] = 7579 { 7580 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, 7581 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, 7582 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}}, 7583 7584 {{ 2.0f, 3.0f, 0.f}, {32767, 32767, 32767, 32767}}, 7585 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}}, 7586 }; 7587 const DWORD exp_indices20[] = {0, 1, 2, 3, 4, 2}; 7588 const DWORD exp_face_remap20[] = {0, 1}; 7589 const DWORD exp_vertex_remap20[] = {0, 1, 2, 3, 4, -1}; 7590 const DWORD exp_new_num_vertices20 = ARRAY_SIZE(exp_vertices20); 7591 /* Test 21. Weld normal as SHORT4N instead of D3DXVECTOR3. */ 7592 const struct vertex_normal_short4 vertices21[] = 7593 { 7594 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, 7595 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, 7596 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}}, 7597 7598 {{ 3.0f, 3.0f, 0.f}, {32767, 32767, 32767, 32767}}, 7599 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}}, 7600 {{ 1.0f, 0.0f, 0.f}, {32766, 32766, 32766, 32766}}, 7601 }; 7602 const DWORD indices21[] = {0, 1, 2, 3, 4, 5}; 7603 const DWORD attributes21[] = {0, 0}; 7604 const UINT num_vertices21 = ARRAY_SIZE(vertices21); 7605 const UINT num_faces21 = ARRAY_SIZE(indices21) / VERTS_PER_FACE; 7606 DWORD flags21 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7607 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}; 7608 const DWORD adjacency21[] = {-1, 1, -1, -1, -1, 0}; 7609 const struct vertex_normal_short4 exp_vertices21[] = 7610 { 7611 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, 7612 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, 7613 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}}, 7614 7615 {{ 2.0f, 3.0f, 0.f}, {32767, 32767, 32767, 32767}}, 7616 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}}, 7617 }; 7618 const DWORD exp_indices21[] = {0, 1, 2, 3, 4, 2}; 7619 const DWORD exp_face_remap21[] = {0, 1}; 7620 const DWORD exp_vertex_remap21[] = {0, 1, 2, 3, 4, -1}; 7621 const DWORD exp_new_num_vertices21 = ARRAY_SIZE(exp_vertices21); 7622 /* Test 22. Weld normal as USHORT4N instead of D3DXVECTOR3. */ 7623 const struct vertex_normal_short4 vertices22[] = 7624 { 7625 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, 7626 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, 7627 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}}, 7628 7629 {{ 3.0f, 3.0f, 0.f}, {65535, 65535, 65535, 65535}}, 7630 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}}, 7631 {{ 1.0f, 0.0f, 0.f}, {65534, 65534, 65534, 65534}}, 7632 }; 7633 const DWORD indices22[] = {0, 1, 2, 3, 4, 5}; 7634 const DWORD attributes22[] = {0, 0}; 7635 const UINT num_vertices22 = ARRAY_SIZE(vertices22); 7636 const UINT num_faces22 = ARRAY_SIZE(indices22) / VERTS_PER_FACE; 7637 DWORD flags22 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7638 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}; 7639 const DWORD adjacency22[] = {-1, 1, -1, -1, -1, 0}; 7640 const struct vertex_normal_short4 exp_vertices22[] = 7641 { 7642 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, 7643 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, 7644 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}}, 7645 7646 {{ 2.0f, 3.0f, 0.f}, {65535, 65535, 65535, 65535}}, 7647 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}}, 7648 }; 7649 const DWORD exp_indices22[] = {0, 1, 2, 3, 4, 2}; 7650 const DWORD exp_face_remap22[] = {0, 1}; 7651 const DWORD exp_vertex_remap22[] = {0, 1, 2, 3, 4, -1}; 7652 const DWORD exp_new_num_vertices22 = ARRAY_SIZE(exp_vertices22); 7653 /* Test 23. Weld texture coordinates as FLOAT16_2. Similar to test 11, but 7654 * with texture coordinates converted to float16 in hex. */ 7655 const struct vertex_texcoord_float16_2 vertices23[] = 7656 { 7657 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */ 7658 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */ 7659 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */ 7660 7661 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd}}, /* {0.2f, 0.3f} */ 7662 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */ 7663 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */ 7664 }; 7665 const DWORD indices23[] = {0, 1, 2, 3, 4, 5}; 7666 const DWORD attributes23[] = {0, 0}; 7667 const UINT num_vertices23 = ARRAY_SIZE(vertices23); 7668 const UINT num_faces23 = ARRAY_SIZE(indices23) / VERTS_PER_FACE; 7669 DWORD flags23 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7670 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}; 7671 const DWORD adjacency23[] = {-1, 1, -1, -1, -1, 0}; 7672 const struct vertex_texcoord_float16_2 exp_vertices23[] = 7673 { 7674 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */ 7675 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */ 7676 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */ 7677 7678 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */ 7679 {{ 0.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */ 7680 }; 7681 const DWORD exp_indices23[] = {0, 1, 2, 1, 3, 4}; 7682 const DWORD exp_face_remap23[] = {0, 1}; 7683 const DWORD exp_vertex_remap23[] = {0, 1, 2, 4, 5, -1}; 7684 const DWORD exp_new_num_vertices23 = ARRAY_SIZE(exp_vertices23); 7685 /* Test 24. Weld texture coordinates as FLOAT16_4. Similar to test 24. */ 7686 const struct vertex_texcoord_float16_4 vertices24[] = 7687 { 7688 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}}, 7689 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a, 0x3800, 0x399a}}, 7690 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd, 0xb266, 0xb4cd}}, 7691 7692 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd, 0x3266, 0x34cd}}, 7693 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}}, 7694 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266, 0x2e66, 0x3266}}, 7695 }; 7696 const DWORD indices24[] = {0, 1, 2, 3, 4, 5}; 7697 const DWORD attributes24[] = {0, 0}; 7698 const UINT num_vertices24 = ARRAY_SIZE(vertices24); 7699 const UINT num_faces24 = ARRAY_SIZE(indices24) / VERTS_PER_FACE; 7700 DWORD flags24 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7701 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}; 7702 const DWORD adjacency24[] = {-1, 1, -1, -1, -1, 0}; 7703 const struct vertex_texcoord_float16_4 exp_vertices24[] = 7704 { 7705 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}}, 7706 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a, 0x3800, 0x399a}}, 7707 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd, 0xb266, 0xb4cd}}, 7708 7709 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}}, 7710 {{ 0.0f, 0.0f, 0.f}, {0x2e66, 0x3266, 0x2e66, 0x3266}}, 7711 }; 7712 const DWORD exp_indices24[] = {0, 1, 2, 1, 3, 4}; 7713 const DWORD exp_face_remap24[] = {0, 1}; 7714 const DWORD exp_vertex_remap24[] = {0, 1, 2, 4, 5, -1}; 7715 const DWORD exp_new_num_vertices24 = ARRAY_SIZE(exp_vertices24); 7716 /* Test 25. Weld texture coordinates with usage index 10 (TEXCOORD10). The 7717 * usage index is capped at 7, so the epsilon for TEXCOORD7 is used instead. 7718 */ 7719 const struct vertex_texcoord vertices25[] = 7720 { 7721 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f}}, 7722 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.7f}}, 7723 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}}, 7724 7725 {{ 3.0f, 3.0f, 0.f}, {0.2f, 0.3f}}, 7726 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f}}, 7727 {{ 1.0f, 0.0f, 0.f}, {0.1f, 0.2f}} 7728 }; 7729 const DWORD indices25[] = {0, 1, 2, 3, 4, 5}; 7730 const DWORD attributes25[] = {0, 0}; 7731 const UINT num_vertices25 = ARRAY_SIZE(vertices25); 7732 const UINT num_faces25 = ARRAY_SIZE(indices25) / VERTS_PER_FACE; 7733 DWORD flags25 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7734 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}; 7735 const DWORD adjacency25[] = {-1, 1, -1, -1, -1, 0}; 7736 const struct vertex_texcoord exp_vertices25[] = 7737 { 7738 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f}}, 7739 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.7f}}, 7740 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}}, 7741 7742 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f}}, 7743 {{ 0.0f, 0.0f, 0.f}, {0.1f, 0.2f}}, 7744 }; 7745 const DWORD exp_indices25[] = {0, 1, 2, 1, 3, 4}; 7746 const DWORD exp_face_remap25[] = {0, 1}; 7747 const DWORD exp_vertex_remap25[] = {0, 1, 2, 4, 5, -1}; 7748 const DWORD exp_new_num_vertices25 = ARRAY_SIZE(exp_vertices25); 7749 /* Test 26. Weld color with usage index larger than 1. Shows that none of 7750 * the epsilon values are used. */ 7751 const struct vertex_color vertices26[] = 7752 { 7753 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF}, 7754 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF}, 7755 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF}, 7756 7757 {{ 3.0f, 3.0f, 0.f}, 0x00000000}, 7758 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF}, 7759 {{ 1.0f, 0.0f, 0.f}, 0x01010101}, 7760 }; 7761 const DWORD indices26[] = {0, 1, 2, 3, 4, 5}; 7762 const DWORD attributes26[] = {0, 0}; 7763 const UINT num_vertices26 = ARRAY_SIZE(vertices26); 7764 const UINT num_faces26 = ARRAY_SIZE(indices26) / VERTS_PER_FACE; 7765 DWORD flags26 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7766 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}; 7767 const DWORD adjacency26[] = {-1, 1, -1, -1, -1, 0}; 7768 const struct vertex_color exp_vertices26[] = 7769 { 7770 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF}, 7771 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF}, 7772 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF}, 7773 7774 {{ 2.0f, 3.0f, 0.f}, 0x00000000}, 7775 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF}, 7776 {{ 0.0f, 0.0f, 0.f}, 0x01010101}, 7777 }; 7778 const DWORD exp_indices26[] = {0, 1, 2, 3, 4, 5}; 7779 const DWORD exp_face_remap26[] = {0, 1}; 7780 const DWORD exp_vertex_remap26[] = {0, 1, 2, 3, 4, 5}; 7781 const DWORD exp_new_num_vertices26 = ARRAY_SIZE(exp_vertices26); 7782 /* Test 27. Weld color with usage index 1 (specular). */ 7783 /* Previously this test used float color values and index > 1 but that case 7784 * appears to be effectively unhandled in native so the test gave 7785 * inconsistent results. */ 7786 const struct vertex_color vertices27[] = 7787 { 7788 {{ 0.0f, 3.0f, 0.0f}, 0x00000000}, 7789 {{ 2.0f, 3.0f, 0.0f}, 0x10203040}, 7790 {{ 0.0f, 0.0f, 0.0f}, 0x50607080}, 7791 7792 {{ 3.0f, 3.0f, 0.0f}, 0x11213141}, 7793 {{ 3.0f, 0.0f, 0.0f}, 0xffffffff}, 7794 {{ 1.0f, 0.0f, 0.0f}, 0x51617181}, 7795 }; 7796 const DWORD indices27[] = {0, 1, 2, 3, 4, 5}; 7797 const DWORD attributes27[] = {0, 0}; 7798 const UINT num_vertices27 = ARRAY_SIZE(vertices27); 7799 const UINT num_faces27 = ARRAY_SIZE(indices27) / VERTS_PER_FACE; 7800 DWORD flags27 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7801 const D3DXWELDEPSILONS epsilons27 = 7802 { 7803 1.1f, 0.0f, 0.0f, 0.0f, 2.0f / 255.0f, 0.0f, 7804 {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, 0.0f, 0.0f, 0.0f 7805 }; 7806 const DWORD adjacency27[] = {-1, 1, -1, -1, -1, 0}; 7807 const struct vertex_color exp_vertices27[] = 7808 { 7809 {{ 0.0f, 3.0f, 0.0f}, 0x00000000}, 7810 {{ 2.0f, 3.0f, 0.0f}, 0x10203040}, 7811 {{ 0.0f, 0.0f, 0.0f}, 0x50607080}, 7812 7813 {{ 3.0f, 0.0f, 0.0f}, 0xffffffff}, 7814 }; 7815 const DWORD exp_indices27[] = {0, 1, 2, 1, 3, 2}; 7816 const DWORD exp_face_remap27[] = {0, 1}; 7817 const DWORD exp_vertex_remap27[] = {0, 1, 2, 4, -1, -1}; 7818 const DWORD exp_new_num_vertices27 = ARRAY_SIZE(exp_vertices27); 7819 /* Test 28. Weld one normal with UDEC3. */ 7820 const DWORD dword_udec3_zero = init_udec3_dword(0, 0, 0, 1); 7821 const DWORD dword_udec3_1023 = init_udec3_dword(1023, 1023, 1023, 1); 7822 const DWORD dword_udec3_1022 = init_udec3_dword(1022, 1022, 1022, 1); 7823 const struct vertex_normal_udec3 vertices28[] = 7824 { 7825 {{ 0.0f, 3.0f, 0.f}, dword_udec3_zero}, 7826 {{ 2.0f, 3.0f, 0.f}, dword_udec3_zero}, 7827 {{ 0.0f, 0.0f, 0.f}, dword_udec3_zero}, 7828 7829 {{ 3.0f, 3.0f, 0.f}, dword_udec3_1023}, 7830 {{ 3.0f, 0.0f, 0.f}, dword_udec3_zero}, 7831 {{ 1.0f, 0.0f, 0.f}, dword_udec3_1022}, 7832 }; 7833 const DWORD indices28[] = {0, 1, 2, 3, 4, 5}; 7834 const DWORD attributes28[] = {0, 0}; 7835 const UINT num_vertices28 = ARRAY_SIZE(vertices28); 7836 const UINT num_faces28 = ARRAY_SIZE(indices28) / VERTS_PER_FACE; 7837 DWORD flags28 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7838 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}; 7839 const DWORD adjacency28[] = {-1, 1, -1, -1, -1, 0}; 7840 const struct vertex_normal_udec3 exp_vertices28[] = 7841 { 7842 {{ 0.0f, 3.0f, 0.f}, dword_udec3_zero}, 7843 {{ 2.0f, 3.0f, 0.f}, dword_udec3_zero}, 7844 {{ 0.0f, 0.0f, 0.f}, dword_udec3_zero}, 7845 7846 {{ 2.0f, 3.0f, 0.f}, dword_udec3_1023}, 7847 {{ 3.0f, 0.0f, 0.f}, dword_udec3_zero}, 7848 }; 7849 const DWORD exp_indices28[] = {0, 1, 2, 3, 4, 2}; 7850 const DWORD exp_face_remap28[] = {0, 1}; 7851 const DWORD exp_vertex_remap28[] = {0, 1, 2, 3, 4, -1}; 7852 const DWORD exp_new_num_vertices28 = ARRAY_SIZE(exp_vertices28); 7853 /* Test 29. Weld one normal with DEC3N. */ 7854 const DWORD dword_dec3n_zero = init_dec3n_dword(0, 0, 0, 1); 7855 const DWORD dword_dec3n_511 = init_dec3n_dword(511, 511, 511, 1); 7856 const DWORD dword_dec3n_510 = init_dec3n_dword(510, 510, 510, 1); 7857 const struct vertex_normal_dec3n vertices29[] = 7858 { 7859 {{ 0.0f, 3.0f, 0.f}, dword_dec3n_zero}, 7860 {{ 2.0f, 3.0f, 0.f}, dword_dec3n_zero}, 7861 {{ 0.0f, 0.0f, 0.f}, dword_dec3n_zero}, 7862 7863 {{ 3.0f, 3.0f, 0.f}, dword_dec3n_511}, 7864 {{ 3.0f, 0.0f, 0.f}, dword_dec3n_zero}, 7865 {{ 1.0f, 0.0f, 0.f}, dword_dec3n_510}, 7866 }; 7867 const DWORD indices29[] = {0, 1, 2, 3, 4, 5}; 7868 const DWORD attributes29[] = {0, 0}; 7869 const UINT num_vertices29 = ARRAY_SIZE(vertices29); 7870 const UINT num_faces29 = ARRAY_SIZE(indices29) / VERTS_PER_FACE; 7871 DWORD flags29 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7872 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}; 7873 const DWORD adjacency29[] = {-1, 1, -1, -1, -1, 0}; 7874 const struct vertex_normal_dec3n exp_vertices29[] = 7875 { 7876 {{ 0.0f, 3.0f, 0.f}, dword_dec3n_zero}, 7877 {{ 2.0f, 3.0f, 0.f}, dword_dec3n_zero}, 7878 {{ 0.0f, 0.0f, 0.f}, dword_dec3n_zero}, 7879 7880 {{ 2.0f, 3.0f, 0.f}, dword_dec3n_511}, 7881 {{ 3.0f, 0.0f, 0.f}, dword_dec3n_zero}, 7882 }; 7883 const DWORD exp_indices29[] = {0, 1, 2, 3, 4, 2}; 7884 const DWORD exp_face_remap29[] = {0, 1}; 7885 const DWORD exp_vertex_remap29[] = {0, 1, 2, 3, 4, -1}; 7886 const DWORD exp_new_num_vertices29 = ARRAY_SIZE(exp_vertices29); 7887 /* All mesh data */ 7888 DWORD *adjacency_out = NULL; 7889 DWORD *face_remap = NULL; 7890 ID3DXMesh *mesh = NULL; 7891 ID3DXBuffer *vertex_remap = NULL; 7892 struct 7893 { 7894 const BYTE *vertices; 7895 const DWORD *indices; 7896 const DWORD *attributes; 7897 const DWORD num_vertices; 7898 const DWORD num_faces; 7899 const DWORD options; 7900 D3DVERTEXELEMENT9 *declaration; 7901 const UINT vertex_size; 7902 const DWORD flags; 7903 const D3DXWELDEPSILONS *epsilons; 7904 const DWORD *adjacency; 7905 const BYTE *exp_vertices; 7906 const DWORD *exp_indices; 7907 const DWORD *exp_face_remap; 7908 const DWORD *exp_vertex_remap; 7909 const DWORD exp_new_num_vertices; 7910 } 7911 tc[] = 7912 { 7913 { 7914 (BYTE*)vertices0, 7915 indices0, 7916 attributes0, 7917 num_vertices0, 7918 num_faces0, 7919 options, 7920 declaration_normal, 7921 vertex_size_normal, 7922 flags0, 7923 NULL, 7924 adjacency0, 7925 (BYTE*)exp_vertices0, 7926 exp_indices0, 7927 exp_face_remap0, 7928 exp_vertex_remap0, 7929 exp_new_num_vertices0 7930 }, 7931 { 7932 (BYTE*)vertices1, 7933 indices1, 7934 attributes1, 7935 num_vertices1, 7936 num_faces1, 7937 options, 7938 declaration_normal, 7939 vertex_size_normal, 7940 flags1, 7941 NULL, 7942 adjacency1, 7943 (BYTE*)exp_vertices1, 7944 exp_indices1, 7945 exp_face_remap1, 7946 exp_vertex_remap1, 7947 exp_new_num_vertices1 7948 }, 7949 { 7950 (BYTE*)vertices2, 7951 indices2, 7952 attributes2, 7953 num_vertices2, 7954 num_faces2, 7955 options, 7956 declaration_normal, 7957 vertex_size_normal, 7958 flags2, 7959 &epsilons2, 7960 adjacency2, 7961 (BYTE*)exp_vertices2, 7962 exp_indices2, 7963 exp_face_remap2, 7964 exp_vertex_remap2, 7965 exp_new_num_vertices2 7966 }, 7967 { 7968 (BYTE*)vertices3, 7969 indices3, 7970 attributes3, 7971 num_vertices3, 7972 num_faces3, 7973 options, 7974 declaration_normal, 7975 vertex_size_normal, 7976 flags3, 7977 &epsilons3, 7978 adjacency3, 7979 (BYTE*)exp_vertices3, 7980 exp_indices3, 7981 exp_face_remap3, 7982 exp_vertex_remap3, 7983 exp_new_num_vertices3 7984 }, 7985 { 7986 (BYTE*)vertices4, 7987 indices4, 7988 attributes4, 7989 num_vertices4, 7990 num_faces4, 7991 options, 7992 declaration_normal, 7993 vertex_size_normal, 7994 flags4, 7995 &epsilons4, 7996 adjacency4, 7997 (BYTE*)exp_vertices4, 7998 exp_indices4, 7999 exp_face_remap4, 8000 exp_vertex_remap4, 8001 exp_new_num_vertices4 8002 }, 8003 /* Unusual ordering. */ 8004 { 8005 (BYTE*)vertices5, 8006 indices5, 8007 attributes5, 8008 num_vertices5, 8009 num_faces5, 8010 options, 8011 declaration_normal, 8012 vertex_size_normal, 8013 flags5, 8014 NULL, 8015 adjacency5, 8016 (BYTE*)exp_vertices5, 8017 exp_indices5, 8018 exp_face_remap5, 8019 exp_vertex_remap5, 8020 exp_new_num_vertices5 8021 }, 8022 { 8023 (BYTE*)vertices6, 8024 indices6, 8025 attributes6, 8026 num_vertices6, 8027 num_faces6, 8028 options, 8029 declaration_normal, 8030 vertex_size_normal, 8031 flags6, 8032 &epsilons6, 8033 adjacency6, 8034 (BYTE*)exp_vertices6, 8035 exp_indices6, 8036 exp_face_remap6, 8037 exp_vertex_remap6, 8038 exp_new_num_vertices6 8039 }, 8040 { 8041 (BYTE*)vertices6, 8042 (DWORD*)indices6_16bit, 8043 attributes6, 8044 num_vertices6, 8045 num_faces6, 8046 options_16bit, 8047 declaration_normal, 8048 vertex_size_normal, 8049 flags6, 8050 &epsilons6, 8051 adjacency6, 8052 (BYTE*)exp_vertices6, 8053 exp_indices6, 8054 exp_face_remap6, 8055 exp_vertex_remap6, 8056 exp_new_num_vertices6 8057 }, 8058 { 8059 (BYTE*)vertices8, 8060 indices8, 8061 attributes8, 8062 num_vertices8, 8063 num_faces8, 8064 options, 8065 declaration_normal, 8066 vertex_size_normal, 8067 flags8, 8068 &epsilons8, 8069 adjacency8, 8070 (BYTE*)exp_vertices8, 8071 exp_indices8, 8072 exp_face_remap8, 8073 exp_vertex_remap8, 8074 exp_new_num_vertices8 8075 }, 8076 { 8077 (BYTE*)vertices9, 8078 indices9, 8079 attributes9, 8080 num_vertices9, 8081 num_faces9, 8082 options, 8083 declaration_normal, 8084 vertex_size_normal, 8085 flags9, 8086 &epsilons9, 8087 adjacency9, 8088 (BYTE*)exp_vertices9, 8089 exp_indices9, 8090 exp_face_remap9, 8091 exp_vertex_remap9, 8092 exp_new_num_vertices9 8093 }, 8094 { 8095 (BYTE*)vertices10, 8096 indices10, 8097 attributes10, 8098 num_vertices10, 8099 num_faces10, 8100 options, 8101 declaration_blendweight, 8102 vertex_size_blendweight, 8103 flags10, 8104 &epsilons10, 8105 adjacency10, 8106 (BYTE*)exp_vertices10, 8107 exp_indices10, 8108 exp_face_remap10, 8109 exp_vertex_remap10, 8110 exp_new_num_vertices10 8111 }, 8112 { 8113 (BYTE*)vertices11, 8114 indices11, 8115 attributes11, 8116 num_vertices11, 8117 num_faces11, 8118 options, 8119 declaration_texcoord, 8120 vertex_size_texcoord, 8121 flags11, 8122 &epsilons11, 8123 adjacency11, 8124 (BYTE*)exp_vertices11, 8125 exp_indices11, 8126 exp_face_remap11, 8127 exp_vertex_remap11, 8128 exp_new_num_vertices11 8129 }, 8130 { 8131 (BYTE*)vertices12, 8132 indices12, 8133 attributes12, 8134 num_vertices12, 8135 num_faces12, 8136 options, 8137 declaration_color, 8138 vertex_size_color, 8139 flags12, 8140 &epsilons12, 8141 adjacency12, 8142 (BYTE*)exp_vertices12, 8143 exp_indices12, 8144 exp_face_remap12, 8145 exp_vertex_remap12, 8146 exp_new_num_vertices12 8147 }, 8148 { 8149 (BYTE*)vertices13, 8150 indices13, 8151 attributes13, 8152 num_vertices13, 8153 num_faces13, 8154 options, 8155 declaration_normal3, 8156 vertex_size_normal, 8157 flags13, 8158 &epsilons13, 8159 adjacency13, 8160 (BYTE*)exp_vertices13, 8161 exp_indices13, 8162 exp_face_remap13, 8163 exp_vertex_remap13, 8164 exp_new_num_vertices13 8165 }, 8166 { 8167 (BYTE*)vertices14, 8168 indices14, 8169 attributes14, 8170 num_vertices14, 8171 num_faces14, 8172 options, 8173 declaration_color, 8174 vertex_size_color, 8175 flags14, 8176 &epsilons14, 8177 adjacency14, 8178 (BYTE*)exp_vertices14, 8179 exp_indices14, 8180 exp_face_remap14, 8181 exp_vertex_remap14, 8182 exp_new_num_vertices14 8183 }, 8184 { 8185 (BYTE*)vertices15, 8186 indices15, 8187 attributes15, 8188 num_vertices15, 8189 num_faces15, 8190 options, 8191 declaration_color_ubyte4n, 8192 vertex_size_color_ubyte4, /* UBYTE4 same size as UBYTE4N */ 8193 flags15, 8194 &epsilons15, 8195 adjacency15, 8196 (BYTE*)exp_vertices15, 8197 exp_indices15, 8198 exp_face_remap15, 8199 exp_vertex_remap15, 8200 exp_new_num_vertices15 8201 }, 8202 { 8203 (BYTE*)vertices16, 8204 indices16, 8205 attributes16, 8206 num_vertices16, 8207 num_faces16, 8208 options, 8209 declaration_color_ubyte4, 8210 vertex_size_color_ubyte4, 8211 flags16, 8212 &epsilons16, 8213 adjacency16, 8214 (BYTE*)exp_vertices16, 8215 exp_indices16, 8216 exp_face_remap16, 8217 exp_vertex_remap16, 8218 exp_new_num_vertices16 8219 }, 8220 { 8221 (BYTE*)vertices17, 8222 indices17, 8223 attributes17, 8224 num_vertices17, 8225 num_faces17, 8226 options, 8227 declaration_texcoord_short2, 8228 vertex_size_texcoord_short2, 8229 flags17, 8230 &epsilons17, 8231 adjacency17, 8232 (BYTE*)exp_vertices17, 8233 exp_indices17, 8234 exp_face_remap17, 8235 exp_vertex_remap17, 8236 exp_new_num_vertices17 8237 }, 8238 { 8239 (BYTE*)vertices18, 8240 indices18, 8241 attributes18, 8242 num_vertices18, 8243 num_faces18, 8244 options, 8245 declaration_texcoord_short2n, 8246 vertex_size_texcoord_short2, /* SHORT2 same size as SHORT2N */ 8247 flags18, 8248 &epsilons18, 8249 adjacency18, 8250 (BYTE*)exp_vertices18, 8251 exp_indices18, 8252 exp_face_remap18, 8253 exp_vertex_remap18, 8254 exp_new_num_vertices18 8255 }, 8256 { 8257 (BYTE*)vertices19, 8258 indices19, 8259 attributes19, 8260 num_vertices19, 8261 num_faces19, 8262 options, 8263 declaration_texcoord_ushort2n, 8264 vertex_size_texcoord_short2, /* SHORT2 same size as USHORT2N */ 8265 flags19, 8266 &epsilons19, 8267 adjacency19, 8268 (BYTE*)exp_vertices19, 8269 exp_indices19, 8270 exp_face_remap19, 8271 exp_vertex_remap19, 8272 exp_new_num_vertices19 8273 }, 8274 { 8275 (BYTE*)vertices20, 8276 indices20, 8277 attributes20, 8278 num_vertices20, 8279 num_faces20, 8280 options, 8281 declaration_normal_short4, 8282 vertex_size_normal_short4, 8283 flags20, 8284 &epsilons20, 8285 adjacency20, 8286 (BYTE*)exp_vertices20, 8287 exp_indices20, 8288 exp_face_remap20, 8289 exp_vertex_remap20, 8290 exp_new_num_vertices20 8291 }, 8292 { 8293 (BYTE*)vertices21, 8294 indices21, 8295 attributes21, 8296 num_vertices21, 8297 num_faces21, 8298 options, 8299 declaration_normal_short4n, 8300 vertex_size_normal_short4, /* SHORT4 same size as SHORT4N */ 8301 flags21, 8302 &epsilons21, 8303 adjacency21, 8304 (BYTE*)exp_vertices21, 8305 exp_indices21, 8306 exp_face_remap21, 8307 exp_vertex_remap21, 8308 exp_new_num_vertices21 8309 }, 8310 { 8311 (BYTE*)vertices22, 8312 indices22, 8313 attributes22, 8314 num_vertices22, 8315 num_faces22, 8316 options, 8317 declaration_normal_ushort4n, 8318 vertex_size_normal_short4, /* SHORT4 same size as USHORT4N */ 8319 flags22, 8320 &epsilons22, 8321 adjacency22, 8322 (BYTE*)exp_vertices22, 8323 exp_indices22, 8324 exp_face_remap22, 8325 exp_vertex_remap22, 8326 exp_new_num_vertices22 8327 }, 8328 { 8329 (BYTE*)vertices23, 8330 indices23, 8331 attributes23, 8332 num_vertices23, 8333 num_faces23, 8334 options, 8335 declaration_texcoord_float16_2, 8336 vertex_size_texcoord_float16_2, 8337 flags23, 8338 &epsilons23, 8339 adjacency23, 8340 (BYTE*)exp_vertices23, 8341 exp_indices23, 8342 exp_face_remap23, 8343 exp_vertex_remap23, 8344 exp_new_num_vertices23 8345 }, 8346 { 8347 (BYTE*)vertices24, 8348 indices24, 8349 attributes24, 8350 num_vertices24, 8351 num_faces24, 8352 options, 8353 declaration_texcoord_float16_4, 8354 vertex_size_texcoord_float16_4, 8355 flags24, 8356 &epsilons24, 8357 adjacency24, 8358 (BYTE*)exp_vertices24, 8359 exp_indices24, 8360 exp_face_remap24, 8361 exp_vertex_remap24, 8362 exp_new_num_vertices24 8363 }, 8364 { 8365 (BYTE*)vertices25, 8366 indices25, 8367 attributes25, 8368 num_vertices25, 8369 num_faces25, 8370 options, 8371 declaration_texcoord10, 8372 vertex_size_texcoord, 8373 flags25, 8374 &epsilons25, 8375 adjacency25, 8376 (BYTE*)exp_vertices25, 8377 exp_indices25, 8378 exp_face_remap25, 8379 exp_vertex_remap25, 8380 exp_new_num_vertices25 8381 }, 8382 { 8383 (BYTE*)vertices26, 8384 indices26, 8385 attributes26, 8386 num_vertices26, 8387 num_faces26, 8388 options, 8389 declaration_color2, 8390 vertex_size_color, 8391 flags26, 8392 &epsilons26, 8393 adjacency26, 8394 (BYTE*)exp_vertices26, 8395 exp_indices26, 8396 exp_face_remap26, 8397 exp_vertex_remap26, 8398 exp_new_num_vertices26 8399 }, 8400 { 8401 (BYTE*)vertices27, 8402 indices27, 8403 attributes27, 8404 num_vertices27, 8405 num_faces27, 8406 options, 8407 declaration_color1, 8408 vertex_size_color, 8409 flags27, 8410 &epsilons27, 8411 adjacency27, 8412 (BYTE*)exp_vertices27, 8413 exp_indices27, 8414 exp_face_remap27, 8415 exp_vertex_remap27, 8416 exp_new_num_vertices27 8417 }, 8418 { 8419 (BYTE*)vertices28, 8420 indices28, 8421 attributes28, 8422 num_vertices28, 8423 num_faces28, 8424 options, 8425 declaration_normal_udec3, 8426 vertex_size_normal_udec3, 8427 flags28, 8428 &epsilons28, 8429 adjacency28, 8430 (BYTE*)exp_vertices28, 8431 exp_indices28, 8432 exp_face_remap28, 8433 exp_vertex_remap28, 8434 exp_new_num_vertices28 8435 }, 8436 { 8437 (BYTE*)vertices29, 8438 indices29, 8439 attributes29, 8440 num_vertices29, 8441 num_faces29, 8442 options, 8443 declaration_normal_dec3n, 8444 vertex_size_normal_dec3n, 8445 flags29, 8446 &epsilons29, 8447 adjacency29, 8448 (BYTE*)exp_vertices29, 8449 exp_indices29, 8450 exp_face_remap29, 8451 exp_vertex_remap29, 8452 exp_new_num_vertices29 8453 } 8454 }; 8455 #ifdef __REACTOS__ 8456 #undef up 8457 #endif 8458 8459 test_context = new_test_context(); 8460 if (!test_context) 8461 { 8462 skip("Couldn't create test context\n"); 8463 goto cleanup; 8464 } 8465 8466 for (i = 0; i < ARRAY_SIZE(tc); i++) 8467 { 8468 DWORD j; 8469 DWORD *vertex_remap_ptr; 8470 DWORD new_num_vertices; 8471 8472 hr = init_test_mesh(tc[i].num_faces, tc[i].num_vertices, tc[i].options, 8473 tc[i].declaration, test_context->device, &mesh, 8474 tc[i].vertices, tc[i].vertex_size, 8475 tc[i].indices, tc[i].attributes); 8476 if (FAILED(hr)) 8477 { 8478 skip("Couldn't initialize test mesh %d.\n", i); 8479 goto cleanup; 8480 } 8481 8482 /* Allocate out parameters */ 8483 adjacency_out = HeapAlloc(GetProcessHeap(), 0, VERTS_PER_FACE * tc[i].num_faces * sizeof(*adjacency_out)); 8484 if (!adjacency_out) 8485 { 8486 skip("Couldn't allocate adjacency_out array.\n"); 8487 goto cleanup; 8488 } 8489 face_remap = HeapAlloc(GetProcessHeap(), 0, tc[i].num_faces * sizeof(*face_remap)); 8490 if (!face_remap) 8491 { 8492 skip("Couldn't allocate face_remap array.\n"); 8493 goto cleanup; 8494 } 8495 8496 hr = D3DXWeldVertices(mesh, tc[i].flags, tc[i].epsilons, tc[i].adjacency, 8497 adjacency_out, face_remap, &vertex_remap); 8498 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 8499 /* Check number of vertices*/ 8500 new_num_vertices = mesh->lpVtbl->GetNumVertices(mesh); 8501 ok(new_num_vertices == tc[i].exp_new_num_vertices, 8502 "Mesh %d: new_num_vertices == %d, expected %d.\n", 8503 i, new_num_vertices, tc[i].exp_new_num_vertices); 8504 /* Check index buffer */ 8505 if (tc[i].options & D3DXMESH_32BIT) 8506 { 8507 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, (void**)&indices); 8508 if (FAILED(hr)) 8509 { 8510 skip("Couldn't lock index buffer.\n"); 8511 goto cleanup; 8512 } 8513 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++) 8514 { 8515 ok(indices[j] == tc[i].exp_indices[j], 8516 "Mesh %d: indices[%d] == %d, expected %d\n", 8517 i, j, indices[j], tc[i].exp_indices[j]); 8518 } 8519 } 8520 else 8521 { 8522 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, (void**)&indices_16bit); 8523 if (FAILED(hr)) 8524 { 8525 skip("Couldn't lock index buffer.\n"); 8526 goto cleanup; 8527 } 8528 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++) 8529 { 8530 ok(indices_16bit[j] == tc[i].exp_indices[j], 8531 "Mesh %d: indices_16bit[%d] == %d, expected %d\n", 8532 i, j, indices_16bit[j], tc[i].exp_indices[j]); 8533 } 8534 } 8535 mesh->lpVtbl->UnlockIndexBuffer(mesh); 8536 indices = NULL; 8537 indices_16bit = NULL; 8538 /* Check adjacency_out */ 8539 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++) 8540 { 8541 ok(adjacency_out[j] == tc[i].adjacency[j], 8542 "Mesh %d: adjacency_out[%d] == %d, expected %d\n", 8543 i, j, adjacency_out[j], tc[i].adjacency[j]); 8544 } 8545 /* Check face_remap */ 8546 for (j = 0; j < tc[i].num_faces; j++) 8547 { 8548 ok(face_remap[j] == tc[i].exp_face_remap[j], 8549 "Mesh %d: face_remap[%d] == %d, expected %d\n", 8550 i, j, face_remap[j], tc[i].exp_face_remap[j]); 8551 } 8552 /* Check vertex_remap */ 8553 vertex_remap_ptr = vertex_remap->lpVtbl->GetBufferPointer(vertex_remap); 8554 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++) 8555 { 8556 ok(vertex_remap_ptr[j] == tc[i].exp_vertex_remap[j], 8557 "Mesh %d: vertex_remap_ptr[%d] == %d, expected %d\n", 8558 i, j, vertex_remap_ptr[j], tc[i].exp_vertex_remap[j]); 8559 } 8560 /* Check vertex buffer */ 8561 hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, (void*)&vertices); 8562 if (FAILED(hr)) 8563 { 8564 skip("Couldn't lock vertex buffer.\n"); 8565 goto cleanup; 8566 } 8567 /* Check contents of re-ordered vertex buffer */ 8568 for (j = 0; j < tc[i].exp_new_num_vertices; j++) 8569 { 8570 int index = tc[i].vertex_size*j; 8571 check_vertex_components(__LINE__, i, j, &vertices[index], &tc[i].exp_vertices[index], tc[i].declaration); 8572 } 8573 mesh->lpVtbl->UnlockVertexBuffer(mesh); 8574 vertices = NULL; 8575 8576 /* Free mesh and output data */ 8577 HeapFree(GetProcessHeap(), 0, adjacency_out); 8578 adjacency_out = NULL; 8579 HeapFree(GetProcessHeap(), 0, face_remap); 8580 face_remap = NULL; 8581 vertex_remap->lpVtbl->Release(vertex_remap); 8582 vertex_remap = NULL; 8583 mesh->lpVtbl->Release(mesh); 8584 mesh = NULL; 8585 } 8586 8587 cleanup: 8588 HeapFree(GetProcessHeap(), 0, adjacency_out); 8589 HeapFree(GetProcessHeap(), 0, face_remap); 8590 if (indices) mesh->lpVtbl->UnlockIndexBuffer(mesh); 8591 if (indices_16bit) mesh->lpVtbl->UnlockIndexBuffer(mesh); 8592 if (mesh) mesh->lpVtbl->Release(mesh); 8593 if (vertex_remap) vertex_remap->lpVtbl->Release(vertex_remap); 8594 if (vertices) mesh->lpVtbl->UnlockVertexBuffer(mesh); 8595 free_test_context(test_context); 8596 } 8597 8598 static void test_clone_mesh(void) 8599 { 8600 HRESULT hr; 8601 struct test_context *test_context = NULL; 8602 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM; 8603 D3DVERTEXELEMENT9 declaration_pn[] = 8604 { 8605 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8606 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 8607 D3DDECL_END() 8608 }; 8609 D3DVERTEXELEMENT9 declaration_pntc[] = 8610 { 8611 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8612 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 8613 {0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 8614 D3DDECL_END() 8615 }; 8616 D3DVERTEXELEMENT9 declaration_ptcn[] = 8617 { 8618 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8619 {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 8620 {0, 20, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 8621 D3DDECL_END() 8622 }; 8623 D3DVERTEXELEMENT9 declaration_ptc[] = 8624 { 8625 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8626 {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 8627 D3DDECL_END() 8628 }; 8629 D3DVERTEXELEMENT9 declaration_ptc_float16_2[] = 8630 { 8631 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8632 {0, 12, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 8633 D3DDECL_END() 8634 }; 8635 D3DVERTEXELEMENT9 declaration_ptc_float16_4[] = 8636 { 8637 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8638 {0, 12, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 8639 D3DDECL_END() 8640 }; 8641 D3DVERTEXELEMENT9 declaration_ptc_float1[] = 8642 { 8643 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8644 {0, 12, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 8645 D3DDECL_END() 8646 }; 8647 D3DVERTEXELEMENT9 declaration_ptc_float3[] = 8648 { 8649 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8650 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 8651 D3DDECL_END() 8652 }; 8653 D3DVERTEXELEMENT9 declaration_ptc_float4[] = 8654 { 8655 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8656 {0, 12, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 8657 D3DDECL_END() 8658 }; 8659 D3DVERTEXELEMENT9 declaration_ptc_d3dcolor[] = 8660 { 8661 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8662 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 8663 D3DDECL_END() 8664 }; 8665 D3DVERTEXELEMENT9 declaration_ptc_ubyte4[] = 8666 { 8667 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8668 {0, 12, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 8669 D3DDECL_END() 8670 }; 8671 D3DVERTEXELEMENT9 declaration_ptc_ubyte4n[] = 8672 { 8673 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8674 {0, 12, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 8675 D3DDECL_END() 8676 }; 8677 D3DVERTEXELEMENT9 declaration_ptc_short2[] = 8678 { 8679 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8680 {0, 12, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 8681 D3DDECL_END() 8682 }; 8683 D3DVERTEXELEMENT9 declaration_ptc_short4[] = 8684 { 8685 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8686 {0, 12, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 8687 D3DDECL_END() 8688 }; 8689 D3DVERTEXELEMENT9 declaration_ptc_short2n[] = 8690 { 8691 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8692 {0, 12, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 8693 D3DDECL_END() 8694 }; 8695 D3DVERTEXELEMENT9 declaration_ptc_short4n[] = 8696 { 8697 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8698 {0, 12, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 8699 D3DDECL_END() 8700 }; 8701 D3DVERTEXELEMENT9 declaration_ptc_ushort2n[] = 8702 { 8703 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8704 {0, 12, D3DDECLTYPE_USHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 8705 D3DDECL_END() 8706 }; 8707 D3DVERTEXELEMENT9 declaration_ptc_ushort4n[] = 8708 { 8709 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8710 {0, 12, D3DDECLTYPE_USHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 8711 D3DDECL_END() 8712 }; 8713 D3DVERTEXELEMENT9 declaration_ptc_float16_2_partialu[] = 8714 { 8715 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8716 {0, 12, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_PARTIALU, D3DDECLUSAGE_TEXCOORD, 0}, 8717 D3DDECL_END() 8718 }; 8719 D3DVERTEXELEMENT9 declaration_pntc1[] = 8720 { 8721 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8722 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 8723 {0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1}, 8724 D3DDECL_END() 8725 }; 8726 const unsigned int VERTS_PER_FACE = 3; 8727 BYTE *vertices = NULL; 8728 INT i; 8729 struct vertex_pn 8730 { 8731 D3DXVECTOR3 position; 8732 D3DXVECTOR3 normal; 8733 }; 8734 struct vertex_pntc 8735 { 8736 D3DXVECTOR3 position; 8737 D3DXVECTOR3 normal; 8738 D3DXVECTOR2 texcoords; 8739 }; 8740 struct vertex_ptcn 8741 { 8742 D3DXVECTOR3 position; 8743 D3DXVECTOR2 texcoords; 8744 D3DXVECTOR3 normal; 8745 }; 8746 struct vertex_ptc 8747 { 8748 D3DXVECTOR3 position; 8749 D3DXVECTOR2 texcoords; 8750 }; 8751 struct vertex_ptc_float16_2 8752 { 8753 D3DXVECTOR3 position; 8754 WORD texcoords[2]; /* float16_2 */ 8755 }; 8756 struct vertex_ptc_float16_4 8757 { 8758 D3DXVECTOR3 position; 8759 WORD texcoords[4]; /* float16_4 */ 8760 }; 8761 struct vertex_ptc_float1 8762 { 8763 D3DXVECTOR3 position; 8764 FLOAT texcoords; 8765 }; 8766 struct vertex_ptc_float3 8767 { 8768 D3DXVECTOR3 position; 8769 FLOAT texcoords[3]; 8770 }; 8771 struct vertex_ptc_float4 8772 { 8773 D3DXVECTOR3 position; 8774 FLOAT texcoords[4]; 8775 }; 8776 struct vertex_ptc_d3dcolor 8777 { 8778 D3DXVECTOR3 position; 8779 BYTE texcoords[4]; 8780 }; 8781 struct vertex_ptc_ubyte4 8782 { 8783 D3DXVECTOR3 position; 8784 BYTE texcoords[4]; 8785 }; 8786 struct vertex_ptc_ubyte4n 8787 { 8788 D3DXVECTOR3 position; 8789 BYTE texcoords[4]; 8790 }; 8791 struct vertex_ptc_short2 8792 { 8793 D3DXVECTOR3 position; 8794 SHORT texcoords[2]; 8795 }; 8796 struct vertex_ptc_short4 8797 { 8798 D3DXVECTOR3 position; 8799 SHORT texcoords[4]; 8800 }; 8801 struct vertex_ptc_ushort2n 8802 { 8803 D3DXVECTOR3 position; 8804 USHORT texcoords[2]; 8805 }; 8806 struct vertex_ptc_ushort4n 8807 { 8808 D3DXVECTOR3 position; 8809 USHORT texcoords[4]; 8810 }; 8811 struct vertex_ptc_udec3 8812 { 8813 D3DXVECTOR3 position; 8814 DWORD texcoords; 8815 }; 8816 struct vertex_ptc_dec3n 8817 { 8818 D3DXVECTOR3 position; 8819 DWORD texcoords; 8820 }; 8821 #ifndef __REACTOS__ 8822 D3DXVECTOR3 up = {0.0f, 0.0f, 1.0f}; 8823 D3DXVECTOR2 zero_vec2 = {0.0f, 0.0f}; 8824 #else 8825 #define up {0.0f, 0.0f, 1.0f} 8826 #define zero_vec2 {0.0f, 0.0f} 8827 #endif 8828 /* Test 0. Check that a mesh can be cloned if the new declaration is the 8829 * same as the one used to create the mesh. 8830 * 8831 * 0--1 3 8832 * | / /| 8833 * |/ / | 8834 * 2 5--4 8835 */ 8836 const struct vertex_pn vertices0[] = 8837 { 8838 {{ 0.0f, 3.0f, 0.f}, up}, 8839 {{ 2.0f, 3.0f, 0.f}, up}, 8840 {{ 0.0f, 0.0f, 0.f}, up}, 8841 8842 {{ 3.0f, 3.0f, 0.f}, up}, 8843 {{ 3.0f, 0.0f, 0.f}, up}, 8844 {{ 1.0f, 0.0f, 0.f}, up}, 8845 }; 8846 const UINT num_vertices0 = ARRAY_SIZE(vertices0); 8847 const UINT num_faces0 = ARRAY_SIZE(vertices0) / VERTS_PER_FACE; 8848 const UINT vertex_size0 = sizeof(*vertices0); 8849 /* Test 1. Check that 16-bit indices are handled. */ 8850 const DWORD options_16bit = D3DXMESH_SYSTEMMEM; 8851 /* Test 2. Check that the size of each vertex is increased and the data 8852 * moved if the new declaration adds an element after the original elements. 8853 */ 8854 const struct vertex_pntc exp_vertices2[] = 8855 { 8856 {{ 0.0f, 3.0f, 0.f}, up, zero_vec2}, 8857 {{ 2.0f, 3.0f, 0.f}, up, zero_vec2}, 8858 {{ 0.0f, 0.0f, 0.f}, up, zero_vec2}, 8859 8860 {{ 3.0f, 3.0f, 0.f}, up, zero_vec2}, 8861 {{ 3.0f, 0.0f, 0.f}, up, zero_vec2}, 8862 {{ 1.0f, 0.0f, 0.f}, up, zero_vec2}, 8863 }; 8864 const UINT exp_vertex_size2 = sizeof(*exp_vertices2); 8865 /* Test 3. Check that the size of each vertex is increased and the data 8866 * moved if the new declaration adds an element between the original 8867 * elements. 8868 */ 8869 const struct vertex_ptcn exp_vertices3[] = 8870 { 8871 {{ 0.0f, 3.0f, 0.f}, zero_vec2, up}, 8872 {{ 2.0f, 3.0f, 0.f}, zero_vec2, up}, 8873 {{ 0.0f, 0.0f, 0.f}, zero_vec2, up}, 8874 8875 {{ 3.0f, 3.0f, 0.f}, zero_vec2, up}, 8876 {{ 3.0f, 0.0f, 0.f}, zero_vec2, up}, 8877 {{ 1.0f, 0.0f, 0.f}, zero_vec2, up}, 8878 }; 8879 const UINT exp_vertex_size3 = sizeof(*exp_vertices3); 8880 /* Test 4. Test that data types can be converted, e.g. FLOAT2 to FLOAT16_2. */ 8881 const struct vertex_ptc vertices4[] = 8882 { 8883 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}}, 8884 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}}, 8885 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}}, 8886 8887 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}}, 8888 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}}, 8889 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}}, 8890 }; 8891 const UINT num_vertices4 = ARRAY_SIZE(vertices4); 8892 const UINT num_faces4 = ARRAY_SIZE(vertices4) / VERTS_PER_FACE; 8893 const UINT vertex_size4 = sizeof(*vertices4); 8894 const struct vertex_ptc_float16_2 exp_vertices4[] = 8895 { 8896 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */ 8897 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */ 8898 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */ 8899 8900 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd}}, /* {0.2f, 0.3f} */ 8901 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */ 8902 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */ 8903 }; 8904 const UINT exp_vertex_size4 = sizeof(*exp_vertices4); 8905 /* Test 5. Convert FLOAT2 to FLOAT16_4. */ 8906 const struct vertex_ptc vertices5[] = 8907 { 8908 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}}, 8909 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}}, 8910 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}}, 8911 8912 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}}, 8913 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}}, 8914 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}}, 8915 }; 8916 const UINT num_vertices5 = ARRAY_SIZE(vertices5); 8917 const UINT num_faces5 = ARRAY_SIZE(vertices5) / VERTS_PER_FACE; 8918 const UINT vertex_size5 = sizeof(*vertices5); 8919 const struct vertex_ptc_float16_4 exp_vertices5[] = 8920 { 8921 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00, 0, 0x3c00}}, /* {1.0f, 1.0f, 0.0f, 1.0f} */ 8922 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a, 0, 0x3c00}}, /* {0.5f, 0.7f, 0.0f, 1.0f} */ 8923 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd, 0, 0x3c00}}, /* {-0.2f, -0.3f, 0.0f, 1.0f} */ 8924 8925 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd, 0, 0x3c00}}, /* {0.2f, 0.3f, 0.0f, 1.0f} */ 8926 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00, 0, 0x3c00}}, /* {1.0f, 1.0f, 0.0f, 1.0f} */ 8927 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266, 0, 0x3c00}}, /* {0.1f, 0.2f, 0.0f, 1.0f} */ 8928 }; 8929 const UINT exp_vertex_size5 = sizeof(*exp_vertices5); 8930 /* Test 6. Convert FLOAT2 to FLOAT1. */ 8931 const struct vertex_ptc vertices6[] = 8932 { 8933 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}}, 8934 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}}, 8935 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}}, 8936 8937 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}}, 8938 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}}, 8939 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}}, 8940 }; 8941 const UINT num_vertices6 = ARRAY_SIZE(vertices6); 8942 const UINT num_faces6 = ARRAY_SIZE(vertices6) / VERTS_PER_FACE; 8943 const UINT vertex_size6 = sizeof(*vertices6); 8944 const struct vertex_ptc_float1 exp_vertices6[] = 8945 { 8946 {{ 0.0f, 3.0f, 0.f}, 1.0f}, 8947 {{ 2.0f, 3.0f, 0.f}, 0.5f}, 8948 {{ 0.0f, 0.0f, 0.f}, -0.2f}, 8949 8950 {{ 3.0f, 3.0f, 0.f}, 0.2f}, 8951 {{ 3.0f, 0.0f, 0.f}, 1.0f}, 8952 {{ 1.0f, 0.0f, 0.f}, 0.1f}, 8953 }; 8954 const UINT exp_vertex_size6 = sizeof(*exp_vertices6); 8955 /* Test 7. Convert FLOAT2 to FLOAT3. */ 8956 const struct vertex_ptc vertices7[] = 8957 { 8958 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}}, 8959 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}}, 8960 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}}, 8961 8962 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}}, 8963 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}}, 8964 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}}, 8965 }; 8966 const UINT num_vertices7 = ARRAY_SIZE(vertices7); 8967 const UINT num_faces7 = ARRAY_SIZE(vertices7) / VERTS_PER_FACE; 8968 const UINT vertex_size7 = sizeof(*vertices7); 8969 const struct vertex_ptc_float3 exp_vertices7[] = 8970 { 8971 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f, 0.0f}}, 8972 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f, 0.0f}}, 8973 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f, 0.0f}}, 8974 8975 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f, 0.0f}}, 8976 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f, 0.0f}}, 8977 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f, 0.0f}}, 8978 }; 8979 const UINT exp_vertex_size7 = sizeof(*exp_vertices7); 8980 /* Test 8. Convert FLOAT2 to FLOAT4. */ 8981 const struct vertex_ptc vertices8[] = 8982 { 8983 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}}, 8984 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}}, 8985 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}}, 8986 8987 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}}, 8988 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}}, 8989 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}}, 8990 }; 8991 const UINT num_vertices8 = ARRAY_SIZE(vertices8); 8992 const UINT num_faces8 = ARRAY_SIZE(vertices8) / VERTS_PER_FACE; 8993 const UINT vertex_size8 = sizeof(*vertices8); 8994 const struct vertex_ptc_float4 exp_vertices8[] = 8995 { 8996 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f, 0.0f, 1.0f}}, 8997 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f, 0.0f, 1.0f}}, 8998 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f, 0.0f, 1.0f}}, 8999 9000 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f, 0.0f, 1.0f}}, 9001 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f, 0.0f, 1.0f}}, 9002 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f, 0.0f, 1.0f}}, 9003 }; 9004 const UINT exp_vertex_size8 = sizeof(*exp_vertices8); 9005 /* Test 9. Convert FLOAT2 to D3DCOLOR. */ 9006 const struct vertex_ptc vertices9[] = 9007 { 9008 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}}, 9009 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}}, 9010 {{ 0.0f, 0.0f, 0.f}, {-0.4f, -0.6f}}, 9011 9012 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}}, 9013 {{ 3.0f, 0.0f, 0.f}, { 2.0f, 256.0f}}, 9014 {{ 1.0f, 0.0f, 0.f}, { 0.11f, 0.2f}}, 9015 }; 9016 const UINT num_vertices9 = ARRAY_SIZE(vertices9); 9017 const UINT num_faces9 = ARRAY_SIZE(vertices9) / VERTS_PER_FACE; 9018 const UINT vertex_size9 = sizeof(*vertices9); 9019 const struct vertex_ptc_d3dcolor exp_vertices9[] = 9020 { 9021 {{ 0.0f, 3.0f, 0.f}, {0, 255, 255, 255}}, 9022 {{ 2.0f, 3.0f, 0.f}, {0, 179, 128, 255}}, 9023 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 255}}, 9024 9025 {{ 3.0f, 3.0f, 0.f}, {0, 77, 51, 255}}, 9026 {{ 3.0f, 0.0f, 0.f}, {0, 255, 255, 255}}, 9027 {{ 1.0f, 0.0f, 0.f}, {0, 51, 28, 255}}, 9028 }; 9029 const UINT exp_vertex_size9 = sizeof(*exp_vertices9); 9030 /* Test 10. Convert FLOAT2 to UBYTE4. */ 9031 const struct vertex_ptc vertices10[] = 9032 { 9033 {{ 0.0f, 3.0f, 0.f}, { 0.0f, 1.0f}}, 9034 {{ 2.0f, 3.0f, 0.f}, { 2.0f, 3.0f}}, 9035 {{ 0.0f, 0.0f, 0.f}, { 254.0f, 255.0f}}, 9036 9037 {{ 3.0f, 3.0f, 0.f}, { 256.0f, 257.0f}}, 9038 {{ 3.0f, 0.0f, 0.f}, { 1.4f, 1.5f}}, 9039 {{ 1.0f, 0.0f, 0.f}, {-4.0f, -5.0f}}, 9040 }; 9041 const UINT num_vertices10 = ARRAY_SIZE(vertices10); 9042 const UINT num_faces10 = ARRAY_SIZE(vertices10) / VERTS_PER_FACE; 9043 const UINT vertex_size10 = sizeof(*vertices10); 9044 const struct vertex_ptc_ubyte4 exp_vertices10[] = 9045 { 9046 {{ 0.0f, 3.0f, 0.f}, {0, 1, 0, 1}}, 9047 {{ 2.0f, 3.0f, 0.f}, {2, 3, 0, 1}}, 9048 {{ 0.0f, 0.0f, 0.f}, {254, 255, 0, 1}}, 9049 9050 {{ 3.0f, 3.0f, 0.f}, {0, 1, 0, 1}}, 9051 {{ 3.0f, 0.0f, 0.f}, {1, 2, 0, 1}}, 9052 {{ 1.0f, 0.0f, 0.f}, {0, 0, 0, 1}}, 9053 }; 9054 const UINT exp_vertex_size10 = sizeof(*exp_vertices10); 9055 /* Test 11. Convert FLOAT2 to SHORT2. */ 9056 const struct vertex_ptc vertices11[] = 9057 { 9058 {{ 0.0f, 3.0f, 0.f}, { 1.0f, -1.0f}}, 9059 {{ 2.0f, 3.0f, 0.f}, { 0.4f, 0.5f}}, 9060 {{ 0.0f, 0.0f, 0.f}, {-0.5f, -5.0f}}, 9061 9062 {{ 3.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MIN}}, 9063 {{ 3.0f, 0.0f, 0.f}, {SHRT_MAX + 1.0f, SHRT_MIN - 1.0f}}, 9064 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX + 2.0f, SHRT_MIN - 2.0f}}, 9065 9066 {{ 4.0f, 3.0f, 0.f}, {2 * SHRT_MAX, 2 * SHRT_MIN}}, 9067 {{ 6.0f, 0.0f, 0.f}, {3 * SHRT_MAX, 3 * SHRT_MIN}}, 9068 {{ 4.0f, 0.0f, 0.f}, {4 * SHRT_MAX, 4 * SHRT_MIN}}, 9069 }; 9070 const UINT num_vertices11 = ARRAY_SIZE(vertices11); 9071 const UINT num_faces11 = ARRAY_SIZE(vertices11) / VERTS_PER_FACE; 9072 const UINT vertex_size11 = sizeof(*vertices11); 9073 const struct vertex_ptc_short2 exp_vertices11[] = 9074 { 9075 {{ 0.0f, 3.0f, 0.f}, {1, 0}}, 9076 {{ 2.0f, 3.0f, 0.f}, {0, 1}}, 9077 {{ 0.0f, 0.0f, 0.f}, {0, -4}}, 9078 9079 {{ 3.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MIN + 1}}, 9080 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MIN}}, 9081 {{ 1.0f, 0.0f, 0.f}, {SHRT_MIN + 1, SHRT_MAX}}, 9082 9083 {{ 4.0f, 3.0f, 0.f}, {-2, 1}}, 9084 {{ 6.0f, 0.0f, 0.f}, {32765, -32767}}, 9085 {{ 4.0f, 0.0f, 0.f}, {-4, 1}}, 9086 }; 9087 const UINT exp_vertex_size11 = sizeof(*exp_vertices11); 9088 /* Test 12. Convert FLOAT2 to SHORT4. */ 9089 const struct vertex_ptc vertices12[] = 9090 { 9091 {{ 0.0f, 3.0f, 0.f}, { 1.0f, -1.0f}}, 9092 {{ 2.0f, 3.0f, 0.f}, { 0.4f, 0.5f}}, 9093 {{ 0.0f, 0.0f, 0.f}, {-0.5f, -5.0f}}, 9094 9095 {{ 3.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MIN}}, 9096 {{ 3.0f, 0.0f, 0.f}, {SHRT_MAX + 1.0f, SHRT_MIN - 1.0f}}, 9097 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX + 2.0f, SHRT_MIN - 2.0f}}, 9098 9099 {{ 4.0f, 3.0f, 0.f}, {2 * SHRT_MAX, 2 * SHRT_MIN}}, 9100 {{ 6.0f, 0.0f, 0.f}, {3 * SHRT_MAX, 3 * SHRT_MIN}}, 9101 {{ 4.0f, 0.0f, 0.f}, {4 * SHRT_MAX, 4 * SHRT_MIN}}, 9102 }; 9103 const UINT num_vertices12 = ARRAY_SIZE(vertices12); 9104 const UINT num_faces12 = ARRAY_SIZE(vertices12) / VERTS_PER_FACE; 9105 const UINT vertex_size12 = sizeof(*vertices12); 9106 const struct vertex_ptc_short4 exp_vertices12[] = 9107 { 9108 {{ 0.0f, 3.0f, 0.f}, {1, 0, 0, 1}}, 9109 {{ 2.0f, 3.0f, 0.f}, {0, 1, 0, 1}}, 9110 {{ 0.0f, 0.0f, 0.f}, {0, -4, 0, 1}}, 9111 9112 {{ 3.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MIN + 1, 0, 1}}, 9113 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MIN, 0, 1}}, 9114 {{ 1.0f, 0.0f, 0.f}, {SHRT_MIN + 1, SHRT_MAX, 0, 1}}, 9115 9116 {{ 4.0f, 3.0f, 0.f}, {-2, 1, 0, 1}}, 9117 {{ 6.0f, 0.0f, 0.f}, {32765, -32767, 0, 1}}, 9118 {{ 4.0f, 0.0f, 0.f}, {-4, 1, 0, 1}}, 9119 }; 9120 const UINT exp_vertex_size12 = sizeof(*exp_vertices12); 9121 /* Test 13. Convert FLOAT2 to UBYTE4N. */ 9122 const struct vertex_ptc vertices13[] = 9123 { 9124 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 2.0f}}, 9125 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}}, 9126 {{ 0.0f, 0.0f, 0.f}, {-0.4f, -0.5f}}, 9127 9128 {{ 3.0f, 3.0f, 0.f}, {-0.6f, -1.0f}}, 9129 {{ 3.0f, 0.0f, 0.f}, {UCHAR_MAX, UCHAR_MAX + 1}}, 9130 {{ 1.0f, 0.0f, 0.f}, {2 * UCHAR_MAX, -UCHAR_MAX}}, 9131 }; 9132 const UINT num_vertices13 = ARRAY_SIZE(vertices13); 9133 const UINT num_faces13 = ARRAY_SIZE(vertices13) / VERTS_PER_FACE; 9134 const UINT vertex_size13 = sizeof(*vertices13); 9135 const struct vertex_ptc_ubyte4n exp_vertices13[] = 9136 { 9137 {{ 0.0f, 3.0f, 0.f}, {255, 255, 0, 255}}, 9138 {{ 2.0f, 3.0f, 0.f}, {128, 179, 0, 255}}, 9139 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 255}}, 9140 9141 {{ 3.0f, 3.0f, 0.f}, {0, 0, 0, 255}}, 9142 {{ 3.0f, 0.0f, 0.f}, {255, 255, 0, 255}}, 9143 {{ 1.0f, 0.0f, 0.f}, {255, 0, 0, 255}}, 9144 }; 9145 const UINT exp_vertex_size13 = sizeof(*exp_vertices13); 9146 /* Test 14. Convert FLOAT2 to SHORT2N. */ 9147 const struct vertex_ptc vertices14[] = 9148 { 9149 {{ 0.0f, 3.0f, 0.f}, {1.0f, 2.0f}}, 9150 {{ 2.0f, 3.0f, 0.f}, {0.4f, 0.5f}}, 9151 {{ 0.0f, 0.0f, 0.f}, {0.6f, -1.0f}}, 9152 9153 {{ 3.0f, 3.0f, 0.f}, {-0.4f, -0.5f}}, 9154 {{ 3.0f, 0.0f, 0.f}, {-0.9f, -0.99997}}, 9155 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX, SHRT_MIN}}, 9156 }; 9157 const UINT num_vertices14 = ARRAY_SIZE(vertices14); 9158 const UINT num_faces14 = ARRAY_SIZE(vertices14) / VERTS_PER_FACE; 9159 const UINT vertex_size14 = sizeof(*vertices14); 9160 const struct vertex_ptc_short2 exp_vertices14[] = 9161 { 9162 {{ 0.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MAX}}, 9163 {{ 2.0f, 3.0f, 0.f}, {13107, 16384}}, 9164 {{ 0.0f, 0.0f, 0.f}, {19660, SHRT_MIN + 2}}, 9165 9166 {{ 3.0f, 3.0f, 0.f}, {-13106, -16383}}, 9167 {{ 3.0f, 0.0f, 0.f}, {-29489, SHRT_MIN + 3}}, 9168 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX, SHRT_MIN + 2}}, 9169 }; 9170 const UINT exp_vertex_size14 = sizeof(*exp_vertices14); 9171 /* Test 15. Convert FLOAT2 to SHORT4N. */ 9172 const struct vertex_ptc vertices15[] = 9173 { 9174 {{ 0.0f, 3.0f, 0.f}, {1.0f, 2.0f}}, 9175 {{ 2.0f, 3.0f, 0.f}, {0.4f, 0.5f}}, 9176 {{ 0.0f, 0.0f, 0.f}, {0.6f, -1.0f}}, 9177 9178 {{ 3.0f, 3.0f, 0.f}, {-0.4f, -0.5f}}, 9179 {{ 3.0f, 0.0f, 0.f}, {-0.9f, -0.99997}}, 9180 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX, SHRT_MIN}}, 9181 }; 9182 const UINT num_vertices15 = ARRAY_SIZE(vertices15); 9183 const UINT num_faces15 = ARRAY_SIZE(vertices15) / VERTS_PER_FACE; 9184 const UINT vertex_size15 = sizeof(*vertices15); 9185 const struct vertex_ptc_short4 exp_vertices15[] = 9186 { 9187 {{ 0.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MAX, 0, SHRT_MAX}}, 9188 {{ 2.0f, 3.0f, 0.f}, {13107, 16384, 0, SHRT_MAX}}, 9189 {{ 0.0f, 0.0f, 0.f}, {19660, SHRT_MIN + 2, 0, SHRT_MAX}}, 9190 9191 {{ 3.0f, 3.0f, 0.f}, {-13106, -16383, 0, SHRT_MAX}}, 9192 {{ 3.0f, 0.0f, 0.f}, {-29489, SHRT_MIN + 3, 0, SHRT_MAX}}, 9193 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX, SHRT_MIN + 2, 0, SHRT_MAX}}, 9194 }; 9195 const UINT exp_vertex_size15 = sizeof(*exp_vertices15); 9196 /* Test 16. Convert FLOAT2 to USHORT2N. */ 9197 const struct vertex_ptc vertices16[] = 9198 { 9199 {{ 0.0f, 3.0f, 0.f}, {1.0f, 2.0f}}, 9200 {{ 2.0f, 3.0f, 0.f}, {0.4f, 0.5f}}, 9201 {{ 0.0f, 0.0f, 0.f}, {0.6f, -1.0f}}, 9202 9203 {{ 3.0f, 3.0f, 0.f}, {-0.4f, -0.5f}}, 9204 {{ 3.0f, 0.0f, 0.f}, {-0.9f, 0.99998f}}, 9205 {{ 1.0f, 0.0f, 0.f}, {USHRT_MAX, 0.0f}}, 9206 }; 9207 const UINT num_vertices16 = ARRAY_SIZE(vertices16); 9208 const UINT num_faces16 = ARRAY_SIZE(vertices16) / VERTS_PER_FACE; 9209 const UINT vertex_size16 = sizeof(*vertices16); 9210 const struct vertex_ptc_ushort2n exp_vertices16[] = 9211 { 9212 {{ 0.0f, 3.0f, 0.f}, {USHRT_MAX, USHRT_MAX}}, 9213 {{ 2.0f, 3.0f, 0.f}, {26214, 32768}}, 9214 {{ 0.0f, 0.0f, 0.f}, {39321, 0}}, 9215 9216 {{ 3.0f, 3.0f, 0.f}, {0, 0}}, 9217 {{ 3.0f, 0.0f, 0.f}, {0, USHRT_MAX - 1}}, 9218 {{ 1.0f, 0.0f, 0.f}, {USHRT_MAX, 0}}, 9219 }; 9220 const UINT exp_vertex_size16 = sizeof(*exp_vertices16); 9221 /* Test 17. Convert FLOAT2 to USHORT4N. */ 9222 const struct vertex_ptc vertices17[] = 9223 { 9224 {{ 0.0f, 3.0f, 0.f}, {1.0f, 2.0f}}, 9225 {{ 2.0f, 3.0f, 0.f}, {0.4f, 0.5f}}, 9226 {{ 0.0f, 0.0f, 0.f}, {0.6f, -1.0f}}, 9227 9228 {{ 3.0f, 3.0f, 0.f}, {-0.4f, -0.5f}}, 9229 {{ 3.0f, 0.0f, 0.f}, {-0.9f, 0.99998f}}, 9230 {{ 1.0f, 0.0f, 0.f}, {USHRT_MAX, 0.0f}}, 9231 }; 9232 const UINT num_vertices17 = ARRAY_SIZE(vertices17); 9233 const UINT num_faces17 = ARRAY_SIZE(vertices17) / VERTS_PER_FACE; 9234 const UINT vertex_size17 = sizeof(*vertices17); 9235 const struct vertex_ptc_ushort4n exp_vertices17[] = 9236 { 9237 {{ 0.0f, 3.0f, 0.f}, {USHRT_MAX, USHRT_MAX, 0, USHRT_MAX}}, 9238 {{ 2.0f, 3.0f, 0.f}, {26214, 32768, 0, USHRT_MAX}}, 9239 {{ 0.0f, 0.0f, 0.f}, {39321, 0, 0, USHRT_MAX}}, 9240 9241 {{ 3.0f, 3.0f, 0.f}, {0, 0, 0, USHRT_MAX}}, 9242 {{ 3.0f, 0.0f, 0.f}, {0, USHRT_MAX - 1, 0, USHRT_MAX}}, 9243 {{ 1.0f, 0.0f, 0.f}, {USHRT_MAX, 0, 0, USHRT_MAX}}, 9244 }; 9245 const UINT exp_vertex_size17 = sizeof(*exp_vertices17); 9246 /* Test 18. Test that the method field is compared by converting a FLOAT2 to 9247 * FLOAT16_2. where the method field has been change from 9248 * D3DDECLMETHOD_DEFAULT to D3DDECLMETHOD_PARTIALU. */ 9249 const struct vertex_ptc vertices18[] = 9250 { 9251 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}}, 9252 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}}, 9253 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}}, 9254 9255 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}}, 9256 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}}, 9257 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}}, 9258 }; 9259 const UINT num_vertices18 = ARRAY_SIZE(vertices18); 9260 const UINT num_faces18 = ARRAY_SIZE(vertices18) / VERTS_PER_FACE; 9261 const UINT vertex_size18 = sizeof(*vertices18); 9262 const struct vertex_ptc_float16_2 exp_vertices18[] = 9263 { 9264 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */ 9265 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */ 9266 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */ 9267 9268 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd}}, /* {0.2f, 0.3f} */ 9269 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */ 9270 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */ 9271 }; 9272 const UINT exp_vertex_size18 = sizeof(*exp_vertices18); 9273 /* Test 19. Test that data is lost if usage index changes, e.g. TEXCOORD0 9274 * TEXCOORD1. */ 9275 const struct vertex_pntc vertices19[] = 9276 { 9277 {{ 0.0f, 3.0f, 0.f}, up, { 1.0f, 1.0f}}, 9278 {{ 2.0f, 3.0f, 0.f}, up, { 0.5f, 0.7f}}, 9279 {{ 0.0f, 0.0f, 0.f}, up, {-0.2f, -0.3f}}, 9280 9281 {{ 3.0f, 3.0f, 0.f}, up, { 0.2f, 0.3f}}, 9282 {{ 3.0f, 0.0f, 0.f}, up, { 1.0f, 1.0f}}, 9283 {{ 1.0f, 0.0f, 0.f}, up, { 0.1f, 0.2f}}, 9284 }; 9285 const UINT num_vertices19 = ARRAY_SIZE(vertices19); 9286 const UINT num_faces19 = ARRAY_SIZE(vertices19) / VERTS_PER_FACE; 9287 const UINT vertex_size19 = sizeof(*vertices19); 9288 const struct vertex_pntc exp_vertices19[] = 9289 { 9290 {{ 0.0f, 3.0f, 0.f}, up, zero_vec2}, 9291 {{ 2.0f, 3.0f, 0.f}, up, zero_vec2}, 9292 {{ 0.0f, 0.0f, 0.f}, up, zero_vec2}, 9293 9294 {{ 3.0f, 3.0f, 0.f}, up, zero_vec2}, 9295 {{ 3.0f, 0.0f, 0.f}, up, zero_vec2}, 9296 {{ 1.0f, 0.0f, 0.f}, up, zero_vec2}, 9297 }; 9298 const UINT exp_vertex_size19 = sizeof(*exp_vertices19); 9299 /* Test 20. Another test that data is lost if usage index changes, e.g. 9300 * TEXCOORD1 to TEXCOORD0. */ 9301 const struct vertex_pntc vertices20[] = 9302 { 9303 {{ 0.0f, 3.0f, 0.f}, up, { 1.0f, 1.0f}}, 9304 {{ 2.0f, 3.0f, 0.f}, up, { 0.5f, 0.7f}}, 9305 {{ 0.0f, 0.0f, 0.f}, up, {-0.2f, -0.3f}}, 9306 9307 {{ 3.0f, 3.0f, 0.f}, up, { 0.2f, 0.3f}}, 9308 {{ 3.0f, 0.0f, 0.f}, up, { 1.0f, 1.0f}}, 9309 {{ 1.0f, 0.0f, 0.f}, up, { 0.1f, 0.2f}}, 9310 }; 9311 const UINT num_vertices20 = ARRAY_SIZE(vertices20); 9312 const UINT num_faces20 = ARRAY_SIZE(vertices20) / VERTS_PER_FACE; 9313 const UINT vertex_size20 = sizeof(*vertices20); 9314 const struct vertex_pntc exp_vertices20[] = 9315 { 9316 {{ 0.0f, 3.0f, 0.f}, up, zero_vec2}, 9317 {{ 2.0f, 3.0f, 0.f}, up, zero_vec2}, 9318 {{ 0.0f, 0.0f, 0.f}, up, zero_vec2}, 9319 9320 {{ 3.0f, 3.0f, 0.f}, up, zero_vec2}, 9321 {{ 3.0f, 0.0f, 0.f}, up, zero_vec2}, 9322 {{ 1.0f, 0.0f, 0.f}, up, zero_vec2}, 9323 }; 9324 const UINT exp_vertex_size20 = sizeof(*exp_vertices20); 9325 /* Test 21. Convert FLOAT1 to FLOAT2. */ 9326 const struct vertex_ptc_float1 vertices21[] = 9327 { 9328 {{ 0.0f, 3.0f, 0.f}, 1.0f}, 9329 {{ 2.0f, 3.0f, 0.f}, 0.5f}, 9330 {{ 0.0f, 0.0f, 0.f}, -0.2f}, 9331 9332 {{ 3.0f, 3.0f, 0.f}, 0.2f}, 9333 {{ 3.0f, 0.0f, 0.f}, 1.0f}, 9334 {{ 1.0f, 0.0f, 0.f}, 0.1f}, 9335 }; 9336 const UINT num_vertices21 = ARRAY_SIZE(vertices21); 9337 const UINT num_faces21 = ARRAY_SIZE(vertices21) / VERTS_PER_FACE; 9338 const UINT vertex_size21 = sizeof(*vertices21); 9339 const struct vertex_ptc exp_vertices21[] = 9340 { 9341 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 0.0f}}, 9342 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.0f}}, 9343 {{ 0.0f, 0.0f, 0.f}, {-0.2f, 0.0f}}, 9344 9345 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.0f}}, 9346 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 0.0f}}, 9347 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.0f}}, 9348 }; 9349 const UINT exp_vertex_size21 = sizeof(*exp_vertices21); 9350 /* Test 22. Convert FLOAT1 to FLOAT3. */ 9351 const struct vertex_ptc_float1 vertices22[] = 9352 { 9353 {{ 0.0f, 3.0f, 0.f}, 1.0f}, 9354 {{ 2.0f, 3.0f, 0.f}, 0.5f}, 9355 {{ 0.0f, 0.0f, 0.f}, -0.2f}, 9356 9357 {{ 3.0f, 3.0f, 0.f}, 0.2f}, 9358 {{ 3.0f, 0.0f, 0.f}, 1.0f}, 9359 {{ 1.0f, 0.0f, 0.f}, 0.1f}, 9360 }; 9361 const UINT num_vertices22 = ARRAY_SIZE(vertices22); 9362 const UINT num_faces22 = ARRAY_SIZE(vertices22) / VERTS_PER_FACE; 9363 const UINT vertex_size22 = sizeof(*vertices22); 9364 const struct vertex_ptc_float3 exp_vertices22[] = 9365 { 9366 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 0.0f, 0.0f}}, 9367 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.0f, 0.0f}}, 9368 {{ 0.0f, 0.0f, 0.f}, {-0.2f, 0.0f, 0.0f}}, 9369 9370 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.0f, 0.0f}}, 9371 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 0.0f, 0.0f}}, 9372 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.0f, 0.0f}}, 9373 }; 9374 const UINT exp_vertex_size22 = sizeof(*exp_vertices22); 9375 /* Test 23. Convert FLOAT1 to FLOAT4. */ 9376 const struct vertex_ptc_float1 vertices23[] = 9377 { 9378 {{ 0.0f, 3.0f, 0.f}, 1.0f}, 9379 {{ 2.0f, 3.0f, 0.f}, 0.5f}, 9380 {{ 0.0f, 0.0f, 0.f}, -0.2f}, 9381 9382 {{ 3.0f, 3.0f, 0.f}, 0.2f}, 9383 {{ 3.0f, 0.0f, 0.f}, 1.0f}, 9384 {{ 1.0f, 0.0f, 0.f}, 0.1f}, 9385 }; 9386 const UINT num_vertices23 = ARRAY_SIZE(vertices23); 9387 const UINT num_faces23 = ARRAY_SIZE(vertices23) / VERTS_PER_FACE; 9388 const UINT vertex_size23 = sizeof(*vertices23); 9389 const struct vertex_ptc_float4 exp_vertices23[] = 9390 { 9391 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 0.0f, 0.0f, 1.0f}}, 9392 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.0f, 0.0f, 1.0f}}, 9393 {{ 0.0f, 0.0f, 0.f}, {-0.2f, 0.0f, 0.0f, 1.0f}}, 9394 9395 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.0f, 0.0f, 1.0f}}, 9396 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 0.0f, 0.0f, 1.0f}}, 9397 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.0f, 0.0f, 1.0f}}, 9398 }; 9399 const UINT exp_vertex_size23 = sizeof(*exp_vertices23); 9400 /* Test 24. Convert FLOAT1 to D3DCOLOR. */ 9401 const struct vertex_ptc_float1 vertices24[] = 9402 { 9403 {{ 0.0f, 3.0f, 0.f}, 1.0f}, 9404 {{ 2.0f, 3.0f, 0.f}, 0.5f}, 9405 {{ 0.0f, 0.0f, 0.f}, -0.2f}, 9406 9407 {{ 3.0f, 3.0f, 0.f}, 0.2f}, 9408 {{ 3.0f, 0.0f, 0.f}, 1.0f}, 9409 {{ 1.0f, 0.0f, 0.f}, 0.11f}, 9410 }; 9411 const UINT num_vertices24 = ARRAY_SIZE(vertices24); 9412 const UINT num_faces24 = ARRAY_SIZE(vertices24) / VERTS_PER_FACE; 9413 const UINT vertex_size24 = sizeof(*vertices24); 9414 const struct vertex_ptc_d3dcolor exp_vertices24[] = 9415 { 9416 {{ 0.0f, 3.0f, 0.f}, {0, 0, 255, 255}}, 9417 {{ 2.0f, 3.0f, 0.f}, {0, 0, 128, 255}}, 9418 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 255}}, 9419 9420 {{ 3.0f, 3.0f, 0.f}, {0, 0, 51, 255}}, 9421 {{ 3.0f, 0.0f, 0.f}, {0, 0, 255, 255}}, 9422 {{ 1.0f, 0.0f, 0.f}, {0, 0, 28, 255}}, 9423 }; 9424 const UINT exp_vertex_size24 = sizeof(*exp_vertices24); 9425 /* Test 25. Convert FLOAT1 to ubyte4. */ 9426 const struct vertex_ptc_float1 vertices25[] = 9427 { 9428 {{ 0.0f, 3.0f, 0.f}, 0.0f}, 9429 {{ 2.0f, 3.0f, 0.f}, 1.4f}, 9430 {{ 0.0f, 0.0f, 0.f}, 1.5f}, 9431 9432 {{ 3.0f, 3.0f, 0.f}, 255.0f}, 9433 {{ 3.0f, 0.0f, 0.f}, 256.0f}, 9434 {{ 1.0f, 0.0f, 0.f}, -1.0f}, 9435 }; 9436 const UINT num_vertices25 = ARRAY_SIZE(vertices25); 9437 const UINT num_faces25 = ARRAY_SIZE(vertices25) / VERTS_PER_FACE; 9438 const UINT vertex_size25 = sizeof(*vertices25); 9439 const struct vertex_ptc_ubyte4 exp_vertices25[] = 9440 { 9441 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 1}}, 9442 {{ 2.0f, 3.0f, 0.f}, {1, 0, 0, 1}}, 9443 {{ 0.0f, 0.0f, 0.f}, {2, 0, 0, 1}}, 9444 9445 {{ 3.0f, 3.0f, 0.f}, {255, 0, 0, 1}}, 9446 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 1}}, 9447 {{ 1.0f, 0.0f, 0.f}, {0, 0, 0, 1}}, 9448 }; 9449 const UINT exp_vertex_size25 = sizeof(*exp_vertices25); 9450 /* Test 26. Convert FLOAT4 to D3DCOLOR. */ 9451 const struct vertex_ptc_float4 vertices26[] = 9452 { 9453 {{ 0.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.4f, 0.5f}}, 9454 {{ 2.0f, 3.0f, 0.f}, {-0.4f, -0.5f, -1.0f, -2.0f}}, 9455 {{ 0.0f, 0.0f, 0.f}, {254.0f, 255.0f, 256.0f, 257.0f}}, 9456 9457 {{ 3.0f, 3.0f, 0.f}, {0.1f, 0.2f, 0.3f, 0.4f}}, 9458 {{ 3.0f, 0.0f, 0.f}, {0.5f, 0.6f, 0.7f, 0.8f}}, 9459 {{ 1.0f, 0.0f, 0.f}, {0.9f, 0.99f, 0.995f, 0.999f}}, 9460 }; 9461 const UINT num_vertices26 = ARRAY_SIZE(vertices26); 9462 const UINT num_faces26 = ARRAY_SIZE(vertices26) / VERTS_PER_FACE; 9463 const UINT vertex_size26 = sizeof(*vertices26); 9464 const struct vertex_ptc_d3dcolor exp_vertices26[] = 9465 { 9466 {{ 0.0f, 3.0f, 0.f}, {102, 255, 0, 128}}, 9467 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, 9468 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}}, 9469 9470 {{ 3.0f, 3.0f, 0.f}, {77, 51, 26, 102}}, 9471 {{ 3.0f, 0.0f, 0.f}, {179, 153, 128, 204}}, 9472 {{ 1.0f, 0.0f, 0.f}, {254, 252, 230, 255}}, 9473 }; 9474 const UINT exp_vertex_size26 = sizeof(*exp_vertices26); 9475 /* Test 27. Convert D3DCOLOR to FLOAT4. */ 9476 const struct vertex_ptc_d3dcolor vertices27[] = 9477 { 9478 {{ 0.0f, 3.0f, 0.f}, {102, 255, 0, 128}}, 9479 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, 9480 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}}, 9481 9482 {{ 3.0f, 3.0f, 0.f}, {77, 51, 26, 102}}, 9483 {{ 3.0f, 0.0f, 0.f}, {179, 153, 128, 204}}, 9484 {{ 1.0f, 0.0f, 0.f}, {254, 252, 230, 255}}, 9485 }; 9486 const UINT num_vertices27 = ARRAY_SIZE(vertices27); 9487 const UINT num_faces27 = ARRAY_SIZE(vertices27) / VERTS_PER_FACE; 9488 const UINT vertex_size27 = sizeof(*vertices27); 9489 const struct vertex_ptc_float4 exp_vertices27[] = 9490 { 9491 {{ 0.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.4f, 0.501961f}}, 9492 {{ 2.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}}, 9493 {{ 0.0f, 0.0f, 0.f}, {1.0f, 1.0f, 1.0f, 1.0f}}, 9494 9495 {{ 3.0f, 3.0f, 0.f}, {0.101961f, 0.2f, 0.301961f, 0.4f}}, 9496 {{ 3.0f, 0.0f, 0.f}, {0.501961f, 0.6f, 0.701961f, 0.8f}}, 9497 {{ 1.0f, 0.0f, 0.f}, {0.901961f, 0.988235f, 0.996078f, 1.0f}}, 9498 }; 9499 const UINT exp_vertex_size27 = sizeof(*exp_vertices27); 9500 /* Test 28. Convert UBYTE4 to FLOAT4. */ 9501 const struct vertex_ptc_ubyte4 vertices28[] = 9502 { 9503 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, 9504 {{ 2.0f, 3.0f, 0.f}, {1, 1, 1, 1}}, 9505 {{ 0.0f, 0.0f, 0.f}, {1, 0, 1, 0}}, 9506 9507 {{ 3.0f, 3.0f, 0.f}, {0, 1, 0, 1}}, 9508 {{ 3.0f, 0.0f, 0.f}, {10, 20, 30, 40}}, 9509 {{ 1.0f, 0.0f, 0.f}, {50, 60, 127, 255}}, 9510 }; 9511 const UINT num_vertices28 = ARRAY_SIZE(vertices28); 9512 const UINT num_faces28 = ARRAY_SIZE(vertices28) / VERTS_PER_FACE; 9513 const UINT vertex_size28 = sizeof(*vertices28); 9514 const struct vertex_ptc_float4 exp_vertices28[] = 9515 { 9516 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}}, 9517 {{ 2.0f, 3.0f, 0.f}, {1.0f, 1.0f, 1.0f, 1.0f}}, 9518 {{ 0.0f, 0.0f, 0.f}, {1.0f, 0.0f, 1.0f, 0.0f}}, 9519 9520 {{ 3.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.0f, 1.0f}}, 9521 {{ 3.0f, 0.0f, 0.f}, {10.0f, 20.0f, 30.0f, 40.0f}}, 9522 {{ 1.0f, 0.0f, 0.f}, {50.0f, 60.0f, 127.0f, 255.0f}}, 9523 }; 9524 const UINT exp_vertex_size28 = sizeof(*exp_vertices28); 9525 /* Test 29. Convert SHORT2 to FLOAT4. */ 9526 const struct vertex_ptc_short2 vertices29[] = 9527 { 9528 {{ 0.0f, 3.0f, 0.f}, {0, 0}}, 9529 {{ 2.0f, 3.0f, 0.f}, {0, 1}}, 9530 {{ 0.0f, 0.0f, 0.f}, {1, 0}}, 9531 9532 {{ 3.0f, 3.0f, 0.f}, {1, 1}}, 9533 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MAX}}, 9534 {{ 1.0f, 0.0f, 0.f}, {-42, 42}}, 9535 }; 9536 const UINT num_vertices29 = ARRAY_SIZE(vertices29); 9537 const UINT num_faces29 = ARRAY_SIZE(vertices29) / VERTS_PER_FACE; 9538 const UINT vertex_size29 = sizeof(*vertices29); 9539 const struct vertex_ptc_float4 exp_vertices29[] = 9540 { 9541 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 1.0f}}, 9542 {{ 2.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.0f, 1.0f }}, 9543 {{ 0.0f, 0.0f, 0.f}, {1.0f, 0.0f, 0.0f, 1.0f}}, 9544 9545 {{ 3.0f, 3.0f, 0.f}, {1.0f, 1.0f, 0.0f, 1.0f}}, 9546 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MAX, 0.0f, 1.0f}}, 9547 {{ 1.0f, 0.0f, 0.f}, {-42.0f, 42.0f, 0.0f, 1.0f}}, 9548 }; 9549 const UINT exp_vertex_size29 = sizeof(*exp_vertices29); 9550 /* Test 29. Convert SHORT4 to FLOAT4. */ 9551 const struct vertex_ptc_short4 vertices30[] = 9552 { 9553 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, 9554 {{ 2.0f, 3.0f, 0.f}, {0, 1, 0, 1}}, 9555 {{ 0.0f, 0.0f, 0.f}, {1, 0, 1, 0}}, 9556 9557 {{ 3.0f, 3.0f, 0.f}, {1, 1, 1, 1}}, 9558 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MAX, 1, 0}}, 9559 {{ 1.0f, 0.0f, 0.f}, {-42, 42, SHRT_MAX, SHRT_MIN}}, 9560 }; 9561 const UINT num_vertices30 = ARRAY_SIZE(vertices30); 9562 const UINT num_faces30 = ARRAY_SIZE(vertices30) / VERTS_PER_FACE; 9563 const UINT vertex_size30 = sizeof(*vertices30); 9564 const struct vertex_ptc_float4 exp_vertices30[] = 9565 { 9566 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}}, 9567 {{ 2.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.0f, 1.0f }}, 9568 {{ 0.0f, 0.0f, 0.f}, {1.0f, 0.0f, 1.0f, 0.0f}}, 9569 9570 {{ 3.0f, 3.0f, 0.f}, {1.0f, 1.0f, 1.0f, 1.0f}}, 9571 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MAX, 1.0f, 0.0f}}, 9572 {{ 1.0f, 0.0f, 0.f}, {-42.0f, 42.0f, SHRT_MAX, SHRT_MIN}}, 9573 }; 9574 const UINT exp_vertex_size30 = sizeof(*exp_vertices30); 9575 /* Test 31. Convert UBYTE4N to FLOAT4. */ 9576 const struct vertex_ptc_ubyte4n vertices31[] = 9577 { 9578 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, 9579 {{ 2.0f, 3.0f, 0.f}, {1, 1, 1, 1}}, 9580 {{ 0.0f, 0.0f, 0.f}, {1, 0, 1, 0}}, 9581 9582 {{ 3.0f, 3.0f, 0.f}, {0, 1, 0, 1}}, 9583 {{ 3.0f, 0.0f, 0.f}, {10, 20, 30, 40}}, 9584 {{ 1.0f, 0.0f, 0.f}, {50, 60, 70, UCHAR_MAX}}, 9585 }; 9586 const UINT num_vertices31 = ARRAY_SIZE(vertices31); 9587 const UINT num_faces31 = ARRAY_SIZE(vertices31) / VERTS_PER_FACE; 9588 const UINT vertex_size31 = sizeof(*vertices31); 9589 const struct vertex_ptc_float4 exp_vertices31[] = 9590 { 9591 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}}, 9592 {{ 2.0f, 3.0f, 0.f}, {(FLOAT)1/UCHAR_MAX, (FLOAT)1/UCHAR_MAX, (FLOAT)1/UCHAR_MAX, (FLOAT)1/UCHAR_MAX}}, 9593 {{ 0.0f, 0.0f, 0.f}, {(FLOAT)1/UCHAR_MAX, 0.0f, (FLOAT)1/UCHAR_MAX, 0.0f}}, 9594 9595 {{ 3.0f, 3.0f, 0.f}, {0.0f, (FLOAT)1/UCHAR_MAX, 0.0f, (FLOAT)1/UCHAR_MAX}}, 9596 {{ 3.0f, 0.0f, 0.f}, {(FLOAT)10/UCHAR_MAX, (FLOAT)20/UCHAR_MAX, (FLOAT)30/UCHAR_MAX, (FLOAT)40/UCHAR_MAX}}, 9597 {{ 1.0f, 0.0f, 0.f}, {(FLOAT)50/UCHAR_MAX, (FLOAT)60/UCHAR_MAX, (FLOAT)70/UCHAR_MAX, 1.0f}}, 9598 }; 9599 const UINT exp_vertex_size31 = sizeof(*exp_vertices31); 9600 /* Test 32. Convert SHORT2N to FLOAT4. */ 9601 const struct vertex_ptc_short2 vertices32[] = 9602 { 9603 {{ 0.0f, 3.0f, 0.f}, {0, 0}}, 9604 {{ 2.0f, 3.0f, 0.f}, {0, 1}}, 9605 {{ 0.0f, 0.0f, 0.f}, {1, 0}}, 9606 9607 {{ 3.0f, 3.0f, 0.f}, {1, 1}}, 9608 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN + 1, SHRT_MAX}}, 9609 {{ 1.0f, 0.0f, 0.f}, {-42, 42}}, 9610 }; 9611 const UINT num_vertices32 = ARRAY_SIZE(vertices32); 9612 const UINT num_faces32 = ARRAY_SIZE(vertices32) / VERTS_PER_FACE; 9613 const UINT vertex_size32 = sizeof(*vertices32); 9614 const struct vertex_ptc_float4 exp_vertices32[] = 9615 { 9616 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 1.0f}}, 9617 {{ 2.0f, 3.0f, 0.f}, {0.0f, 1.0f/SHRT_MAX, 0.0f, 1.0f}}, 9618 {{ 0.0f, 0.0f, 0.f}, {1.0f/SHRT_MAX, 0.0f, 0.0f, 1.0f}}, 9619 9620 {{ 3.0f, 3.0f, 0.f}, {1.0f/SHRT_MAX, 1.0f/SHRT_MAX, 0.0f, 1.0f}}, 9621 {{ 3.0f, 0.0f, 0.f}, {-1.0f, 1.0f, 0.0f, 1.0f}}, 9622 {{ 1.0f, 0.0f, 0.f}, {-42.0f/SHRT_MAX, 42.0f/SHRT_MAX, 0.0f, 1.0f}}, 9623 }; 9624 const UINT exp_vertex_size32 = sizeof(*exp_vertices32); 9625 /* Test 33. Convert SHORT4N to FLOAT4. */ 9626 const struct vertex_ptc_short4 vertices33[] = 9627 { 9628 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, 9629 {{ 2.0f, 3.0f, 0.f}, {0, 1, 0, 1}}, 9630 {{ 0.0f, 0.0f, 0.f}, {1, 0, 1, 0}}, 9631 9632 {{ 3.0f, 3.0f, 0.f}, {1, 1, 1, 1}}, 9633 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN + 1, SHRT_MAX, SHRT_MIN + 1, SHRT_MAX}}, 9634 {{ 1.0f, 0.0f, 0.f}, {-42, 42, 1, 1}}, 9635 }; 9636 const UINT num_vertices33 = ARRAY_SIZE(vertices33); 9637 const UINT num_faces33 = ARRAY_SIZE(vertices33) / VERTS_PER_FACE; 9638 const UINT vertex_size33 = sizeof(*vertices33); 9639 const struct vertex_ptc_float4 exp_vertices33[] = 9640 { 9641 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}}, 9642 {{ 2.0f, 3.0f, 0.f}, {0.0f, 1.0f/SHRT_MAX, 0.0f, 1.0f/SHRT_MAX}}, 9643 {{ 0.0f, 0.0f, 0.f}, {1.0f/SHRT_MAX, 0.0f, 1.0f/SHRT_MAX, 0.0f}}, 9644 9645 {{ 3.0f, 3.0f, 0.f}, {1.0f/SHRT_MAX, 1.0f/SHRT_MAX, 1.0f/SHRT_MAX, 1.0f/SHRT_MAX}}, 9646 {{ 3.0f, 0.0f, 0.f}, {-1.0f, 1.0f, -1.0f, 1.0f}}, 9647 {{ 1.0f, 0.0f, 0.f}, {-42.0f/SHRT_MAX, 42.0f/SHRT_MAX, 1.0f/SHRT_MAX, 1.0f/SHRT_MAX}}, 9648 }; 9649 const UINT exp_vertex_size33 = sizeof(*exp_vertices33); 9650 /* Test 34. Convert FLOAT16_2 to FLOAT4. */ 9651 const struct vertex_ptc_float16_2 vertices34[] = 9652 { 9653 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */ 9654 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */ 9655 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */ 9656 9657 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd}}, /* {0.2f, 0.3f} */ 9658 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */ 9659 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */ 9660 }; 9661 const UINT num_vertices34 = ARRAY_SIZE(vertices34); 9662 const UINT num_faces34 = ARRAY_SIZE(vertices34) / VERTS_PER_FACE; 9663 const UINT vertex_size34 = sizeof(*vertices34); 9664 const struct vertex_ptc_float4 exp_vertices34[] = 9665 { 9666 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f, 0.0f, 1.0f}}, 9667 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.700195f, 0.0f, 1.0f}}, 9668 {{ 0.0f, 0.0f, 0.f}, {-0.199951f, -0.300049f, 0.0f, 1.0f}}, 9669 9670 {{ 3.0f, 3.0f, 0.f}, {0.199951f, 0.300049f, 0.0f, 1.0f}}, 9671 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f, 0.0f, 1.0f}}, 9672 {{ 1.0f, 0.0f, 0.f}, {0.099976f, 0.199951f, 0.0f, 1.0f}}, 9673 }; 9674 const UINT exp_vertex_size34 = sizeof(*exp_vertices34); 9675 /* Test 35. Convert FLOAT16_4 to FLOAT4. */ 9676 const struct vertex_ptc_float16_4 vertices35[] = 9677 { 9678 {{ 0.0f, 3.0f, 0.f}, {0x0000, 0x0000, 0x0000, 0x0000}}, 9679 {{ 2.0f, 3.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}}, 9680 {{ 0.0f, 0.0f, 0.f}, {0x3c00, 0x0000, 0x3c00, 0x0000}}, 9681 9682 {{ 3.0f, 3.0f, 0.f}, {0x0000, 0x3c00, 0x0000, 0x3c00}}, 9683 {{ 3.0f, 0.0f, 0.f}, {0x3800, 0x399a, 0xb266, 0xb4cd}}, 9684 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266, 0x2e66, 0x3266}}, 9685 }; 9686 const UINT num_vertices35 = ARRAY_SIZE(vertices35); 9687 const UINT num_faces35 = ARRAY_SIZE(vertices35) / VERTS_PER_FACE; 9688 const UINT vertex_size35 = sizeof(*vertices35); 9689 const struct vertex_ptc_float4 exp_vertices35[] = 9690 { 9691 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}}, 9692 {{ 2.0f, 3.0f, 0.f}, {1.0f, 1.0f, 1.0f, 1.0f}}, 9693 {{ 0.0f, 0.0f, 0.f}, {1.0f, 0.0f, 1.0f, 0.0f}}, 9694 9695 {{ 3.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.0f, 1.0f}}, 9696 {{ 3.0f, 0.0f, 0.f}, {0.5f, 0.700195f, -0.199951f, -0.300049f}}, 9697 {{ 1.0f, 0.0f, 0.f}, {0.099976f, 0.199951f, 0.099976f, 0.199951f}}, 9698 }; 9699 const UINT exp_vertex_size35 = sizeof(*exp_vertices35); 9700 /* Test 36. Check that vertex buffer sharing is ok. */ 9701 const struct vertex_pn vertices36[] = 9702 { 9703 {{ 0.0f, 3.0f, 0.f}, up}, 9704 {{ 2.0f, 3.0f, 0.f}, up}, 9705 {{ 0.0f, 0.0f, 0.f}, up}, 9706 }; 9707 const UINT num_vertices36 = ARRAY_SIZE(vertices36); 9708 const UINT num_faces36 = ARRAY_SIZE(vertices36) / VERTS_PER_FACE; 9709 const UINT vertex_size36 = sizeof(*vertices36); 9710 const DWORD clone_options36 = options | D3DXMESH_VB_SHARE; 9711 /* Common mesh data */ 9712 ID3DXMesh *mesh = NULL; 9713 ID3DXMesh *mesh_clone = NULL; 9714 struct 9715 { 9716 const BYTE *vertices; 9717 const DWORD *indices; 9718 const DWORD *attributes; 9719 const UINT num_vertices; 9720 const UINT num_faces; 9721 const UINT vertex_size; 9722 const DWORD create_options; 9723 const DWORD clone_options; 9724 D3DVERTEXELEMENT9 *declaration; 9725 D3DVERTEXELEMENT9 *new_declaration; 9726 const BYTE *exp_vertices; 9727 const UINT exp_vertex_size; 9728 } 9729 tc[] = 9730 { 9731 { 9732 (BYTE*)vertices0, 9733 NULL, 9734 NULL, 9735 num_vertices0, 9736 num_faces0, 9737 vertex_size0, 9738 options, 9739 options, 9740 declaration_pn, 9741 declaration_pn, 9742 (BYTE*)vertices0, 9743 vertex_size0 9744 }, 9745 { 9746 (BYTE*)vertices0, 9747 NULL, 9748 NULL, 9749 num_vertices0, 9750 num_faces0, 9751 vertex_size0, 9752 options_16bit, 9753 options_16bit, 9754 declaration_pn, 9755 declaration_pn, 9756 (BYTE*)vertices0, 9757 vertex_size0 9758 }, 9759 { 9760 (BYTE*)vertices0, 9761 NULL, 9762 NULL, 9763 num_vertices0, 9764 num_faces0, 9765 vertex_size0, 9766 options, 9767 options, 9768 declaration_pn, 9769 declaration_pntc, 9770 (BYTE*)exp_vertices2, 9771 exp_vertex_size2 9772 }, 9773 { 9774 (BYTE*)vertices0, 9775 NULL, 9776 NULL, 9777 num_vertices0, 9778 num_faces0, 9779 vertex_size0, 9780 options, 9781 options, 9782 declaration_pn, 9783 declaration_ptcn, 9784 (BYTE*)exp_vertices3, 9785 exp_vertex_size3 9786 }, 9787 { 9788 (BYTE*)vertices4, 9789 NULL, 9790 NULL, 9791 num_vertices4, 9792 num_faces4, 9793 vertex_size4, 9794 options, 9795 options, 9796 declaration_ptc, 9797 declaration_ptc_float16_2, 9798 (BYTE*)exp_vertices4, 9799 exp_vertex_size4 9800 }, 9801 { 9802 (BYTE*)vertices5, 9803 NULL, 9804 NULL, 9805 num_vertices5, 9806 num_faces5, 9807 vertex_size5, 9808 options, 9809 options, 9810 declaration_ptc, 9811 declaration_ptc_float16_4, 9812 (BYTE*)exp_vertices5, 9813 exp_vertex_size5 9814 }, 9815 { 9816 (BYTE*)vertices6, 9817 NULL, 9818 NULL, 9819 num_vertices6, 9820 num_faces6, 9821 vertex_size6, 9822 options, 9823 options, 9824 declaration_ptc, 9825 declaration_ptc_float1, 9826 (BYTE*)exp_vertices6, 9827 exp_vertex_size6 9828 }, 9829 { 9830 (BYTE*)vertices7, 9831 NULL, 9832 NULL, 9833 num_vertices7, 9834 num_faces7, 9835 vertex_size7, 9836 options, 9837 options, 9838 declaration_ptc, 9839 declaration_ptc_float3, 9840 (BYTE*)exp_vertices7, 9841 exp_vertex_size7 9842 }, 9843 { 9844 (BYTE*)vertices8, 9845 NULL, 9846 NULL, 9847 num_vertices8, 9848 num_faces8, 9849 vertex_size8, 9850 options, 9851 options, 9852 declaration_ptc, 9853 declaration_ptc_float4, 9854 (BYTE*)exp_vertices8, 9855 exp_vertex_size8 9856 }, 9857 { 9858 (BYTE*)vertices9, 9859 NULL, 9860 NULL, 9861 num_vertices9, 9862 num_faces9, 9863 vertex_size9, 9864 options, 9865 options, 9866 declaration_ptc, 9867 declaration_ptc_d3dcolor, 9868 (BYTE*)exp_vertices9, 9869 exp_vertex_size9 9870 }, 9871 { 9872 (BYTE*)vertices10, 9873 NULL, 9874 NULL, 9875 num_vertices10, 9876 num_faces10, 9877 vertex_size10, 9878 options, 9879 options, 9880 declaration_ptc, 9881 declaration_ptc_ubyte4, 9882 (BYTE*)exp_vertices10, 9883 exp_vertex_size10 9884 }, 9885 { 9886 (BYTE*)vertices11, 9887 NULL, 9888 NULL, 9889 num_vertices11, 9890 num_faces11, 9891 vertex_size11, 9892 options, 9893 options, 9894 declaration_ptc, 9895 declaration_ptc_short2, 9896 (BYTE*)exp_vertices11, 9897 exp_vertex_size11 9898 }, 9899 { 9900 (BYTE*)vertices12, 9901 NULL, 9902 NULL, 9903 num_vertices12, 9904 num_faces12, 9905 vertex_size12, 9906 options, 9907 options, 9908 declaration_ptc, 9909 declaration_ptc_short4, 9910 (BYTE*)exp_vertices12, 9911 exp_vertex_size12 9912 }, 9913 { 9914 (BYTE*)vertices13, 9915 NULL, 9916 NULL, 9917 num_vertices13, 9918 num_faces13, 9919 vertex_size13, 9920 options, 9921 options, 9922 declaration_ptc, 9923 declaration_ptc_ubyte4n, 9924 (BYTE*)exp_vertices13, 9925 exp_vertex_size13 9926 }, 9927 { 9928 (BYTE*)vertices14, 9929 NULL, 9930 NULL, 9931 num_vertices14, 9932 num_faces14, 9933 vertex_size14, 9934 options, 9935 options, 9936 declaration_ptc, 9937 declaration_ptc_short2n, 9938 (BYTE*)exp_vertices14, 9939 exp_vertex_size14 9940 }, 9941 { 9942 (BYTE*)vertices15, 9943 NULL, 9944 NULL, 9945 num_vertices15, 9946 num_faces15, 9947 vertex_size15, 9948 options, 9949 options, 9950 declaration_ptc, 9951 declaration_ptc_short4n, 9952 (BYTE*)exp_vertices15, 9953 exp_vertex_size15 9954 }, 9955 { 9956 (BYTE*)vertices16, 9957 NULL, 9958 NULL, 9959 num_vertices16, 9960 num_faces16, 9961 vertex_size16, 9962 options, 9963 options, 9964 declaration_ptc, 9965 declaration_ptc_ushort2n, 9966 (BYTE*)exp_vertices16, 9967 exp_vertex_size16 9968 }, 9969 { 9970 (BYTE*)vertices17, 9971 NULL, 9972 NULL, 9973 num_vertices17, 9974 num_faces17, 9975 vertex_size17, 9976 options, 9977 options, 9978 declaration_ptc, 9979 declaration_ptc_ushort4n, 9980 (BYTE*)exp_vertices17, 9981 exp_vertex_size17 9982 }, 9983 { 9984 (BYTE*)vertices18, 9985 NULL, 9986 NULL, 9987 num_vertices18, 9988 num_faces18, 9989 vertex_size18, 9990 options, 9991 options, 9992 declaration_ptc, 9993 declaration_ptc_float16_2_partialu, 9994 (BYTE*)exp_vertices18, 9995 exp_vertex_size18 9996 }, 9997 { 9998 (BYTE*)vertices19, 9999 NULL, 10000 NULL, 10001 num_vertices19, 10002 num_faces19, 10003 vertex_size19, 10004 options, 10005 options, 10006 declaration_pntc, 10007 declaration_pntc1, 10008 (BYTE*)exp_vertices19, 10009 exp_vertex_size19 10010 }, 10011 { 10012 (BYTE*)vertices20, 10013 NULL, 10014 NULL, 10015 num_vertices20, 10016 num_faces20, 10017 vertex_size20, 10018 options, 10019 options, 10020 declaration_pntc1, 10021 declaration_pntc, 10022 (BYTE*)exp_vertices20, 10023 exp_vertex_size20 10024 }, 10025 { 10026 (BYTE*)vertices21, 10027 NULL, 10028 NULL, 10029 num_vertices21, 10030 num_faces21, 10031 vertex_size21, 10032 options, 10033 options, 10034 declaration_ptc_float1, 10035 declaration_ptc, 10036 (BYTE*)exp_vertices21, 10037 exp_vertex_size21 10038 }, 10039 { 10040 (BYTE*)vertices22, 10041 NULL, 10042 NULL, 10043 num_vertices22, 10044 num_faces22, 10045 vertex_size22, 10046 options, 10047 options, 10048 declaration_ptc_float1, 10049 declaration_ptc_float3, 10050 (BYTE*)exp_vertices22, 10051 exp_vertex_size22 10052 }, 10053 { 10054 (BYTE*)vertices23, 10055 NULL, 10056 NULL, 10057 num_vertices23, 10058 num_faces23, 10059 vertex_size23, 10060 options, 10061 options, 10062 declaration_ptc_float1, 10063 declaration_ptc_float4, 10064 (BYTE*)exp_vertices23, 10065 exp_vertex_size23 10066 }, 10067 { 10068 (BYTE*)vertices24, 10069 NULL, 10070 NULL, 10071 num_vertices24, 10072 num_faces24, 10073 vertex_size24, 10074 options, 10075 options, 10076 declaration_ptc_float1, 10077 declaration_ptc_d3dcolor, 10078 (BYTE*)exp_vertices24, 10079 exp_vertex_size24 10080 }, 10081 { 10082 (BYTE*)vertices25, 10083 NULL, 10084 NULL, 10085 num_vertices25, 10086 num_faces25, 10087 vertex_size25, 10088 options, 10089 options, 10090 declaration_ptc_float1, 10091 declaration_ptc_ubyte4, 10092 (BYTE*)exp_vertices25, 10093 exp_vertex_size25 10094 }, 10095 { 10096 (BYTE*)vertices26, 10097 NULL, 10098 NULL, 10099 num_vertices26, 10100 num_faces26, 10101 vertex_size26, 10102 options, 10103 options, 10104 declaration_ptc_float4, 10105 declaration_ptc_d3dcolor, 10106 (BYTE*)exp_vertices26, 10107 exp_vertex_size26 10108 }, 10109 { 10110 (BYTE*)vertices27, 10111 NULL, 10112 NULL, 10113 num_vertices27, 10114 num_faces27, 10115 vertex_size27, 10116 options, 10117 options, 10118 declaration_ptc_d3dcolor, 10119 declaration_ptc_float4, 10120 (BYTE*)exp_vertices27, 10121 exp_vertex_size27 10122 }, 10123 { 10124 (BYTE*)vertices28, 10125 NULL, 10126 NULL, 10127 num_vertices28, 10128 num_faces28, 10129 vertex_size28, 10130 options, 10131 options, 10132 declaration_ptc_ubyte4, 10133 declaration_ptc_float4, 10134 (BYTE*)exp_vertices28, 10135 exp_vertex_size28 10136 }, 10137 { 10138 (BYTE*)vertices29, 10139 NULL, 10140 NULL, 10141 num_vertices29, 10142 num_faces29, 10143 vertex_size29, 10144 options, 10145 options, 10146 declaration_ptc_short2, 10147 declaration_ptc_float4, 10148 (BYTE*)exp_vertices29, 10149 exp_vertex_size29 10150 }, 10151 { 10152 (BYTE*)vertices30, 10153 NULL, 10154 NULL, 10155 num_vertices30, 10156 num_faces30, 10157 vertex_size30, 10158 options, 10159 options, 10160 declaration_ptc_short4, 10161 declaration_ptc_float4, 10162 (BYTE*)exp_vertices30, 10163 exp_vertex_size30 10164 }, 10165 { 10166 (BYTE*)vertices31, 10167 NULL, 10168 NULL, 10169 num_vertices31, 10170 num_faces31, 10171 vertex_size31, 10172 options, 10173 options, 10174 declaration_ptc_ubyte4n, 10175 declaration_ptc_float4, 10176 (BYTE*)exp_vertices31, 10177 exp_vertex_size31 10178 }, 10179 { 10180 (BYTE*)vertices32, 10181 NULL, 10182 NULL, 10183 num_vertices32, 10184 num_faces32, 10185 vertex_size32, 10186 options, 10187 options, 10188 declaration_ptc_short2n, 10189 declaration_ptc_float4, 10190 (BYTE*)exp_vertices32, 10191 exp_vertex_size32 10192 }, 10193 { 10194 (BYTE*)vertices33, 10195 NULL, 10196 NULL, 10197 num_vertices33, 10198 num_faces33, 10199 vertex_size33, 10200 options, 10201 options, 10202 declaration_ptc_short4n, 10203 declaration_ptc_float4, 10204 (BYTE*)exp_vertices33, 10205 exp_vertex_size33 10206 }, 10207 { 10208 (BYTE*)vertices34, 10209 NULL, 10210 NULL, 10211 num_vertices34, 10212 num_faces34, 10213 vertex_size34, 10214 options, 10215 options, 10216 declaration_ptc_float16_2, 10217 declaration_ptc_float4, 10218 (BYTE*)exp_vertices34, 10219 exp_vertex_size34 10220 }, 10221 { 10222 (BYTE*)vertices35, 10223 NULL, 10224 NULL, 10225 num_vertices35, 10226 num_faces35, 10227 vertex_size35, 10228 options, 10229 options, 10230 declaration_ptc_float16_4, 10231 declaration_ptc_float4, 10232 (BYTE*)exp_vertices35, 10233 exp_vertex_size35 10234 }, 10235 { 10236 (BYTE*)vertices36, 10237 NULL, 10238 NULL, 10239 num_vertices36, 10240 num_faces36, 10241 vertex_size36, 10242 options, 10243 clone_options36, 10244 declaration_pn, 10245 declaration_pn, 10246 (BYTE*)vertices36, 10247 vertex_size36 10248 }, 10249 }; 10250 #ifdef __REACTOS__ 10251 #undef up 10252 #undef zero_vec2 10253 #endif 10254 10255 test_context = new_test_context(); 10256 if (!test_context) 10257 { 10258 skip("Couldn't create test context\n"); 10259 goto cleanup; 10260 } 10261 10262 for (i = 0; i < ARRAY_SIZE(tc); i++) 10263 { 10264 UINT j; 10265 D3DVERTEXELEMENT9 new_declaration[MAX_FVF_DECL_SIZE]; 10266 UINT exp_new_decl_length, new_decl_length; 10267 UINT exp_new_decl_size, new_decl_size; 10268 10269 hr = init_test_mesh(tc[i].num_faces, tc[i].num_vertices, 10270 tc[i].create_options, 10271 tc[i].declaration, 10272 test_context->device, &mesh, 10273 tc[i].vertices, tc[i].vertex_size, 10274 tc[i].indices, tc[i].attributes); 10275 if (FAILED(hr)) 10276 { 10277 skip("Couldn't initialize test mesh %d. Got %x expected D3D_OK\n", i, hr); 10278 goto cleanup; 10279 } 10280 10281 hr = mesh->lpVtbl->CloneMesh(mesh, tc[i].clone_options, tc[i].new_declaration, 10282 test_context->device, &mesh_clone); 10283 ok(hr == D3D_OK, "CloneMesh test case %d failed. Got %x, expected D3D_OK.\n", i, hr); 10284 10285 hr = mesh_clone->lpVtbl->GetDeclaration(mesh_clone, new_declaration); 10286 ok(hr == D3D_OK, "GetDeclaration test case %d failed. Got %x, expected D3D_OK.\n", i, hr); 10287 /* Check declaration elements */ 10288 for (j = 0; tc[i].new_declaration[j].Stream != 0xFF; j++) 10289 { 10290 ok(memcmp(&tc[i].new_declaration[j], &new_declaration[j], sizeof(*new_declaration)) == 0, 10291 "Test case %d failed. Declaration element %d did not match.\n", i, j); 10292 } 10293 10294 /* Check declaration length */ 10295 exp_new_decl_length = D3DXGetDeclLength(tc[i].new_declaration); 10296 new_decl_length = D3DXGetDeclLength(new_declaration); 10297 ok(new_decl_length == exp_new_decl_length, 10298 "Test case %d failed. Got new declaration length %d, expected %d\n", 10299 i, new_decl_length, exp_new_decl_length); 10300 10301 /* Check declaration size */ 10302 exp_new_decl_size = D3DXGetDeclVertexSize(tc[i].new_declaration, 0); 10303 new_decl_size = D3DXGetDeclVertexSize(new_declaration, 0); 10304 ok(new_decl_size == exp_new_decl_size, 10305 "Test case %d failed. Got new declaration size %d, expected %d\n", 10306 i, new_decl_size, exp_new_decl_size); 10307 10308 /* Check vertex data in cloned mesh */ 10309 hr = mesh_clone->lpVtbl->LockVertexBuffer(mesh_clone, 0, (void**)&vertices); 10310 if (FAILED(hr)) 10311 { 10312 skip("Couldn't lock cloned vertex buffer.\n"); 10313 goto cleanup; 10314 } 10315 for (j = 0; j < tc[i].num_vertices; j++) 10316 { 10317 UINT index = tc[i].exp_vertex_size * j; 10318 check_vertex_components(__LINE__, i, j, &vertices[index], &tc[i].exp_vertices[index], tc[i].new_declaration); 10319 } 10320 hr = mesh_clone->lpVtbl->UnlockVertexBuffer(mesh_clone); 10321 if (FAILED(hr)) 10322 { 10323 skip("Couldn't unlock vertex buffer.\n"); 10324 goto cleanup; 10325 } 10326 vertices = NULL; 10327 mesh->lpVtbl->Release(mesh); 10328 mesh = NULL; 10329 mesh_clone->lpVtbl->Release(mesh_clone); 10330 mesh_clone = NULL; 10331 } 10332 10333 /* The following test shows that it is not possible to share a vertex buffer 10334 * with D3DXMESH_VB_SHARE and change the vertex declaration at the same 10335 * time. It reuses the test data from test 2. 10336 */ 10337 hr = init_test_mesh(tc[2].num_faces, tc[2].num_vertices, 10338 tc[2].create_options, 10339 tc[2].declaration, 10340 test_context->device, &mesh, 10341 tc[2].vertices, tc[2].vertex_size, 10342 tc[2].indices, tc[2].attributes); 10343 if (FAILED(hr)) 10344 { 10345 skip("Couldn't initialize test mesh for D3DXMESH_VB_SHARE case." 10346 " Got %x expected D3D_OK\n", hr); 10347 goto cleanup; 10348 } 10349 10350 hr = mesh->lpVtbl->CloneMesh(mesh, tc[2].create_options | D3DXMESH_VB_SHARE, 10351 tc[2].new_declaration, test_context->device, 10352 &mesh_clone); 10353 ok(hr == D3DERR_INVALIDCALL, "CloneMesh D3DXMESH_VB_SHARE with new" 10354 " declaration. Got %x, expected D3DERR_INVALIDCALL\n", 10355 hr); 10356 mesh->lpVtbl->Release(mesh); 10357 mesh = NULL; 10358 mesh_clone = NULL; 10359 10360 cleanup: 10361 if (vertices) mesh->lpVtbl->UnlockVertexBuffer(mesh); 10362 if (mesh) mesh->lpVtbl->Release(mesh); 10363 if (mesh_clone) mesh_clone->lpVtbl->Release(mesh_clone); 10364 free_test_context(test_context); 10365 } 10366 10367 static void test_valid_mesh(void) 10368 { 10369 HRESULT hr; 10370 struct test_context *test_context = NULL; 10371 UINT i; 10372 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM; 10373 const D3DVERTEXELEMENT9 declaration[] = 10374 { 10375 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 10376 D3DDECL_END() 10377 }; 10378 const unsigned int VERTS_PER_FACE = 3; 10379 /* mesh0 (one face) 10380 * 10381 * 0--1 10382 * | / 10383 * |/ 10384 * 2 10385 */ 10386 const D3DXVECTOR3 vertices0[] = 10387 { 10388 { 0.0f, 3.0f, 0.f}, 10389 { 2.0f, 3.0f, 0.f}, 10390 { 0.0f, 0.0f, 0.f}, 10391 }; 10392 const DWORD indices0[] = {0, 1, 2}; 10393 const unsigned int num_vertices0 = ARRAY_SIZE(vertices0); 10394 const unsigned int num_faces0 = ARRAY_SIZE(indices0) / VERTS_PER_FACE; 10395 const DWORD adjacency0[] = {-1, -1, -1}; 10396 const HRESULT exp_hr0 = D3D_OK; 10397 /* mesh1 (Simple bow-tie) 10398 * 10399 * 0--1 1--3 10400 * | / \ | 10401 * |/ \| 10402 * 2 4 10403 */ 10404 const D3DXVECTOR3 vertices1[] = 10405 { 10406 { 0.0f, 3.0f, 0.f}, 10407 { 2.0f, 3.0f, 0.f}, 10408 { 0.0f, 0.0f, 0.f}, 10409 10410 { 4.0f, 3.0f, 0.f}, 10411 { 4.0f, 0.0f, 0.f}, 10412 }; 10413 const DWORD indices1[] = {0, 1, 2, 1, 3, 4}; 10414 const unsigned int num_vertices1 = ARRAY_SIZE(vertices1); 10415 const unsigned int num_faces1 = ARRAY_SIZE(indices1) / VERTS_PER_FACE; 10416 const DWORD adjacency1[] = {-1, -1, -1, -1, -1, -1}; 10417 const HRESULT exp_hr1 = D3DXERR_INVALIDMESH; 10418 /* Common mesh data */ 10419 ID3DXMesh *mesh = NULL; 10420 UINT vertex_size = sizeof(D3DXVECTOR3); 10421 ID3DXBuffer *errors_and_warnings = NULL; 10422 struct 10423 { 10424 const D3DXVECTOR3 *vertices; 10425 const DWORD *indices; 10426 const UINT num_vertices; 10427 const UINT num_faces; 10428 const DWORD *adjacency; 10429 const HRESULT exp_hr; 10430 } 10431 tc[] = 10432 { 10433 { 10434 vertices0, 10435 indices0, 10436 num_vertices0, 10437 num_faces0, 10438 adjacency0, 10439 exp_hr0, 10440 }, 10441 { 10442 vertices1, 10443 indices1, 10444 num_vertices1, 10445 num_faces1, 10446 adjacency1, 10447 exp_hr1, 10448 }, 10449 }; 10450 10451 test_context = new_test_context(); 10452 if (!test_context) 10453 { 10454 skip("Couldn't create test context\n"); 10455 goto cleanup; 10456 } 10457 10458 for (i = 0; i < ARRAY_SIZE(tc); i++) 10459 { 10460 hr = init_test_mesh(tc[i].num_faces, tc[i].num_vertices, 10461 options, declaration, 10462 test_context->device, &mesh, 10463 tc[i].vertices, vertex_size, 10464 tc[i].indices, NULL); 10465 if (FAILED(hr)) 10466 { 10467 skip("Couldn't initialize test mesh %d. Got %x expected D3D_OK\n", i, hr); 10468 goto cleanup; 10469 } 10470 10471 hr = D3DXValidMesh(mesh, tc[i].adjacency, &errors_and_warnings); 10472 todo_wine ok(hr == tc[i].exp_hr, "D3DXValidMesh test case %d failed. " 10473 "Got %x, expected %x.\n", i, hr, tc[i].exp_hr); 10474 10475 /* Note errors_and_warnings is deliberately not checked because that 10476 * would require copying wast amounts of the text output. */ 10477 if (errors_and_warnings) 10478 { 10479 ID3DXBuffer_Release(errors_and_warnings); 10480 errors_and_warnings = NULL; 10481 } 10482 mesh->lpVtbl->Release(mesh); 10483 mesh = NULL; 10484 } 10485 10486 cleanup: 10487 if (mesh) mesh->lpVtbl->Release(mesh); 10488 free_test_context(test_context); 10489 } 10490 10491 static void test_optimize_vertices(void) 10492 { 10493 HRESULT hr; 10494 DWORD vertex_remap[3]; 10495 const DWORD indices[] = {0, 1, 2}; 10496 const UINT num_faces = 1; 10497 const UINT num_vertices = 3; 10498 10499 hr = D3DXOptimizeVertices(indices, num_faces, 10500 num_vertices, FALSE, 10501 vertex_remap); 10502 ok(hr == D3D_OK, "D3DXOptimizeVertices failed. Got %x, expected D3D_OK.\n", hr); 10503 10504 /* vertex_remap must not be NULL */ 10505 hr = D3DXOptimizeVertices(indices, num_faces, 10506 num_vertices, FALSE, 10507 NULL); 10508 ok(hr == D3DERR_INVALIDCALL, "D3DXOptimizeVertices passed NULL vertex_remap " 10509 "pointer. Got %x, expected D3DERR_INVALIDCALL.\n", hr); 10510 } 10511 10512 static void test_optimize_faces(void) 10513 { 10514 HRESULT hr; 10515 UINT i; 10516 DWORD smallest_face_remap; 10517 /* mesh0 10518 * 10519 * 0--1 10520 * | / 10521 * |/ 10522 * 2 10523 */ 10524 const DWORD indices0[] = {0, 1, 2}; 10525 const UINT num_faces0 = 1; 10526 const UINT num_vertices0 = 3; 10527 const DWORD exp_face_remap0[] = {0}; 10528 /* mesh1 10529 * 10530 * 0--1 3 10531 * | / /| 10532 * |/ / | 10533 * 2 5--4 10534 */ 10535 const DWORD indices1[] = {0, 1, 2, 3, 4, 5}; 10536 const UINT num_faces1 = 2; 10537 const UINT num_vertices1 = 6; 10538 const DWORD exp_face_remap1[] = {1, 0}; 10539 /* mesh2 10540 * 10541 * 0--1 10542 * | /| 10543 * |/ | 10544 * 2--3 10545 */ 10546 const DWORD indices2[] = {0, 1, 2, 1, 3, 2}; 10547 const UINT num_faces2 = 2; 10548 const UINT num_vertices2 = 4; 10549 const DWORD exp_face_remap2[] = {1, 0}; 10550 /* mesh3 10551 * 10552 * 0--1 10553 * | /| 10554 * |/ | 10555 * 2--3 10556 * | /| 10557 * |/ | 10558 * 4--5 10559 */ 10560 const DWORD indices3[] = {0, 1, 2, 1, 3, 2, 2, 3, 4, 3, 4, 5}; 10561 const UINT num_faces3 = 4; 10562 const UINT num_vertices3 = 6; 10563 const DWORD exp_face_remap3[] = {3, 2, 1, 0}; 10564 /* mesh4 10565 * 10566 * 0--1 10567 * | /| 10568 * |/ | 10569 * 2--3 10570 * | /| 10571 * |/ | 10572 * 4--5 10573 */ 10574 const WORD indices4[] = {0, 1, 2, 1, 3, 2, 2, 3, 4, 3, 4, 5}; 10575 const UINT num_faces4 = 4; 10576 const UINT num_vertices4 = 6; 10577 const DWORD exp_face_remap4[] = {3, 2, 1, 0}; 10578 /* Test cases are stored in the tc array */ 10579 struct 10580 { 10581 const VOID *indices; 10582 const UINT num_faces; 10583 const UINT num_vertices; 10584 const BOOL indices_are_32bit; 10585 const DWORD *exp_face_remap; 10586 } 10587 tc[] = 10588 { 10589 { 10590 indices0, 10591 num_faces0, 10592 num_vertices0, 10593 TRUE, 10594 exp_face_remap0 10595 }, 10596 { 10597 indices1, 10598 num_faces1, 10599 num_vertices1, 10600 TRUE, 10601 exp_face_remap1 10602 }, 10603 { 10604 indices2, 10605 num_faces2, 10606 num_vertices2, 10607 TRUE, 10608 exp_face_remap2 10609 }, 10610 { 10611 indices3, 10612 num_faces3, 10613 num_vertices3, 10614 TRUE, 10615 exp_face_remap3 10616 }, 10617 { 10618 indices4, 10619 num_faces4, 10620 num_vertices4, 10621 FALSE, 10622 exp_face_remap4 10623 }, 10624 }; 10625 10626 /* Go through all test cases */ 10627 for (i = 0; i < ARRAY_SIZE(tc); i++) 10628 { 10629 DWORD j; 10630 DWORD *face_remap; 10631 face_remap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 10632 tc[i].num_faces*sizeof(*face_remap)); 10633 10634 hr = D3DXOptimizeFaces(tc[i].indices, tc[i].num_faces, 10635 tc[i].num_vertices, tc[i].indices_are_32bit, 10636 face_remap); 10637 ok(hr == D3D_OK, "D3DXOptimizeFaces test case %d failed. " 10638 "Got %x, expected D3D_OK.\n", i, hr); 10639 10640 /* Compare face remap with expected face remap */ 10641 for (j = 0; j < tc[i].num_faces; j++) 10642 { 10643 ok(tc[i].exp_face_remap[j] == face_remap[j], 10644 "Test case %d: Got face %d at %d, expected %d\n", i, 10645 face_remap[j], j, tc[i].exp_face_remap[j]); 10646 } 10647 10648 HeapFree(GetProcessHeap(), 0, face_remap); 10649 } 10650 10651 /* face_remap must not be NULL */ 10652 hr = D3DXOptimizeFaces(tc[0].indices, tc[0].num_faces, 10653 tc[0].num_vertices, tc[0].indices_are_32bit, 10654 NULL); 10655 ok(hr == D3DERR_INVALIDCALL, "D3DXOptimizeFaces passed NULL face_remap " 10656 "pointer. Got %x, expected D3DERR_INVALIDCALL.\n", hr); 10657 10658 /* Number of faces must be smaller than 2^15 */ 10659 hr = D3DXOptimizeFaces(tc[0].indices, 2 << 15, 10660 tc[0].num_vertices, FALSE, 10661 &smallest_face_remap); 10662 ok(hr == D3DERR_INVALIDCALL, "D3DXOptimizeFaces should not accept 2^15 " 10663 "faces when using 16-bit indices. Got %x, expected D3DERR_INVALIDCALL.\n", hr); 10664 } 10665 10666 static HRESULT clear_normals(ID3DXMesh *mesh) 10667 { 10668 HRESULT hr; 10669 BYTE *vertices; 10670 size_t normal_size; 10671 DWORD i, num_vertices, vertex_stride; 10672 const D3DXVECTOR4 normal = {NAN, NAN, NAN, NAN}; 10673 D3DVERTEXELEMENT9 *normal_declaration = NULL; 10674 D3DVERTEXELEMENT9 declaration[MAX_FVF_DECL_SIZE] = {D3DDECL_END()}; 10675 10676 if (FAILED(hr = mesh->lpVtbl->GetDeclaration(mesh, declaration))) 10677 return hr; 10678 10679 for (i = 0; declaration[i].Stream != 0xff; i++) 10680 { 10681 if (declaration[i].Usage == D3DDECLUSAGE_NORMAL && !declaration[i].UsageIndex) 10682 { 10683 normal_declaration = &declaration[i]; 10684 break; 10685 } 10686 } 10687 10688 if (!normal_declaration) 10689 return D3DERR_INVALIDCALL; 10690 10691 if (normal_declaration->Type == D3DDECLTYPE_FLOAT3) 10692 { 10693 normal_size = sizeof(D3DXVECTOR3); 10694 } 10695 else if (normal_declaration->Type == D3DDECLTYPE_FLOAT4) 10696 { 10697 normal_size = sizeof(D3DXVECTOR4); 10698 } 10699 else 10700 { 10701 trace("Cannot clear normals\n"); 10702 return E_NOTIMPL; 10703 } 10704 10705 num_vertices = mesh->lpVtbl->GetNumVertices(mesh); 10706 vertex_stride = mesh->lpVtbl->GetNumBytesPerVertex(mesh); 10707 10708 if (FAILED(hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, (void **)&vertices))) 10709 return hr; 10710 10711 vertices += normal_declaration->Offset; 10712 10713 for (i = 0; i < num_vertices; i++, vertices += vertex_stride) 10714 memcpy(vertices, &normal, normal_size); 10715 10716 return mesh->lpVtbl->UnlockVertexBuffer(mesh); 10717 } 10718 10719 static void compare_normals(unsigned int line, const char *test_name, 10720 ID3DXMesh *mesh, const D3DXVECTOR3 *normals, unsigned int num_normals) 10721 { 10722 unsigned int i; 10723 BYTE *vertices; 10724 DWORD num_vertices, vertex_stride; 10725 D3DVERTEXELEMENT9 *normal_declaration = NULL; 10726 D3DVERTEXELEMENT9 declaration[MAX_FVF_DECL_SIZE] = {D3DDECL_END()}; 10727 10728 if (FAILED(mesh->lpVtbl->GetDeclaration(mesh, declaration))) 10729 { 10730 ok_(__FILE__, line)(0, "%s: Failed to get declaration\n", test_name); 10731 return; 10732 } 10733 10734 for (i = 0; declaration[i].Stream != 0xff; i++) 10735 { 10736 if (declaration[i].Usage == D3DDECLUSAGE_NORMAL && !declaration[i].UsageIndex) 10737 { 10738 normal_declaration = &declaration[i]; 10739 break; 10740 } 10741 } 10742 10743 if (!normal_declaration) 10744 { 10745 ok_(__FILE__, line)(0, "%s: Mesh has no normals\n", test_name); 10746 return; 10747 } 10748 10749 if (normal_declaration->Type != D3DDECLTYPE_FLOAT3 && normal_declaration->Type != D3DDECLTYPE_FLOAT4) 10750 { 10751 ok_(__FILE__, line)(0, "%s: Mesh has invalid normals type\n", test_name); 10752 return; 10753 } 10754 10755 num_vertices = mesh->lpVtbl->GetNumVertices(mesh); 10756 vertex_stride = mesh->lpVtbl->GetNumBytesPerVertex(mesh); 10757 10758 ok_(__FILE__, line)(num_vertices == num_normals, "%s: Expected %u vertices, got %u\n", test_name, 10759 num_normals, num_vertices); 10760 10761 if (FAILED(mesh->lpVtbl->LockVertexBuffer(mesh, 0, (void **)&vertices))) 10762 { 10763 ok_(__FILE__, line)(0, "%s: Failed to compare normals\n", test_name); 10764 return; 10765 } 10766 10767 vertices += normal_declaration->Offset; 10768 10769 for (i = 0; i < min(num_vertices, num_normals); i++, vertices += vertex_stride) 10770 { 10771 if (normal_declaration->Type == D3DDECLTYPE_FLOAT3) 10772 { 10773 const D3DXVECTOR3 *n = (D3DXVECTOR3 *)vertices; 10774 ok_(__FILE__, line)(compare_vec3(*n, normals[i]), 10775 "%s: normal %2u, expected (%f, %f, %f), got (%f, %f, %f)\n", 10776 test_name, i, normals[i].x, normals[i].y, normals[i].z, n->x, n->y, n->z); 10777 } 10778 else 10779 { 10780 const D3DXVECTOR4 *n = (D3DXVECTOR4 *)vertices; 10781 const D3DXVECTOR4 normal = {normals[i].x, normals[i].y, normals[i].z, 1.0f}; 10782 ok_(__FILE__, line)(compare_vec4(*n, normal), 10783 "%s: normal %2u, expected (%f, %f, %f, %f), got (%f, %f, %f, %f)\n", 10784 test_name, i, normals[i].x, normals[i].y, normals[i].z, 1.0f, 10785 n->x, n->y, n->z, n->w); 10786 } 10787 } 10788 10789 mesh->lpVtbl->UnlockVertexBuffer(mesh); 10790 } 10791 10792 static HRESULT compute_normals_D3DXComputeNormals(ID3DXMesh *mesh, const DWORD *adjacency) 10793 { 10794 return D3DXComputeNormals((ID3DXBaseMesh *)mesh, adjacency); 10795 } 10796 10797 static HRESULT compute_normals_D3DXComputeTangentFrameEx(ID3DXMesh *mesh, const DWORD *adjacency) 10798 { 10799 return D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, 10800 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS, 10801 adjacency, -1.01f, -0.01f, -1.01f, NULL, NULL); 10802 } 10803 10804 static void test_compute_normals(void) 10805 { 10806 HRESULT hr; 10807 ULONG refcount; 10808 ID3DXMesh *mesh, *cloned_mesh; 10809 ID3DXBuffer *adjacency; 10810 IDirect3DDevice9 *device; 10811 struct test_context *test_context; 10812 unsigned int i; 10813 10814 static const struct compute_normals_func 10815 { 10816 const char *name; 10817 HRESULT (*apply)(ID3DXMesh *mesh, const DWORD *adjacency); 10818 } 10819 compute_normals_funcs[] = 10820 { 10821 {"D3DXComputeNormals", compute_normals_D3DXComputeNormals }, 10822 {"D3DXComputeTangentFrameEx", compute_normals_D3DXComputeTangentFrameEx} 10823 }; 10824 10825 static const D3DXVECTOR3 box_normals[24] = 10826 { 10827 {-1.0f, 0.0f, 0.0f}, {-1.0f, 0.0f, 0.0f}, {-1.0f, 0.0f, 0.0f}, {-1.0f, 0.0f, 0.0f}, 10828 { 0.0f, 1.0f, 0.0f}, { 0.0f, 1.0f, 0.0f}, { 0.0f, 1.0f, 0.0f}, { 0.0f, 1.0f, 0.0f}, 10829 { 1.0f, 0.0f, 0.0f}, { 1.0f, 0.0f, 0.0f}, { 1.0f, 0.0f, 0.0f}, { 1.0f, 0.0f, 0.0f}, 10830 { 0.0f,-1.0f, 0.0f}, { 0.0f,-1.0f, 0.0f}, { 0.0f,-1.0f, 0.0f}, { 0.0f,-1.0f, 0.0f}, 10831 { 0.0f, 0.0f, 1.0f}, { 0.0f, 0.0f, 1.0f}, { 0.0f, 0.0f, 1.0f}, { 0.0f, 0.0f, 1.0f}, 10832 { 0.0f, 0.0f,-1.0f}, { 0.0f, 0.0f,-1.0f}, { 0.0f, 0.0f,-1.0f}, { 0.0f, 0.0f,-1.0f} 10833 }; 10834 const float box_normal_component = 1.0f / sqrtf(3.0f); 10835 const D3DXVECTOR3 box_normals_adjacency[24] = 10836 { 10837 {-box_normal_component, -box_normal_component, -box_normal_component}, 10838 {-box_normal_component, -box_normal_component, box_normal_component}, 10839 {-box_normal_component, box_normal_component, box_normal_component}, 10840 {-box_normal_component, box_normal_component, -box_normal_component}, 10841 {-box_normal_component, box_normal_component, -box_normal_component}, 10842 {-box_normal_component, box_normal_component, box_normal_component}, 10843 { box_normal_component, box_normal_component, box_normal_component}, 10844 { box_normal_component, box_normal_component, -box_normal_component}, 10845 { box_normal_component, box_normal_component, -box_normal_component}, 10846 { box_normal_component, box_normal_component, box_normal_component}, 10847 { box_normal_component, -box_normal_component, box_normal_component}, 10848 { box_normal_component, -box_normal_component, -box_normal_component}, 10849 {-box_normal_component, -box_normal_component, box_normal_component}, 10850 {-box_normal_component, -box_normal_component, -box_normal_component}, 10851 { box_normal_component, -box_normal_component, -box_normal_component}, 10852 { box_normal_component, -box_normal_component, box_normal_component}, 10853 {-box_normal_component, -box_normal_component, box_normal_component}, 10854 { box_normal_component, -box_normal_component, box_normal_component}, 10855 { box_normal_component, box_normal_component, box_normal_component}, 10856 {-box_normal_component, box_normal_component, box_normal_component}, 10857 {-box_normal_component, -box_normal_component, -box_normal_component}, 10858 {-box_normal_component, box_normal_component, -box_normal_component}, 10859 { box_normal_component, box_normal_component, -box_normal_component}, 10860 { box_normal_component, -box_normal_component, -box_normal_component} 10861 }; 10862 static const D3DXVECTOR3 box_normals_adjacency_area[24] = 10863 { 10864 {-0.666667f, -0.333333f, -0.666667f}, {-0.333333f, -0.666667f, 0.666667f}, 10865 {-0.816496f, 0.408248f, 0.408248f}, {-0.408248f, 0.816496f, -0.408248f}, 10866 {-0.408248f, 0.816496f, -0.408248f}, {-0.816496f, 0.408248f, 0.408248f}, 10867 { 0.333333f, 0.666667f, 0.666667f}, { 0.666667f, 0.333333f, -0.666667f}, 10868 { 0.666667f, 0.333333f, -0.666667f}, { 0.333333f, 0.666667f, 0.666667f}, 10869 { 0.816496f, -0.408248f, 0.408248f}, { 0.408248f, -0.816496f, -0.408248f}, 10870 {-0.333333f, -0.666667f, 0.666667f}, {-0.666667f, -0.333333f, -0.666667f}, 10871 { 0.408248f, -0.816496f, -0.408248f}, { 0.816496f, -0.408248f, 0.408248f}, 10872 {-0.333333f, -0.666667f, 0.666667f}, { 0.816497f, -0.408248f, 0.408248f}, 10873 { 0.333333f, 0.666667f, 0.666667f}, {-0.816497f, 0.408248f, 0.408248f}, 10874 {-0.666667f, -0.333333f, -0.666667f}, {-0.408248f, 0.816497f, -0.408248f}, 10875 { 0.666667f, 0.333333f, -0.666667f}, { 0.408248f, -0.816496f, -0.408248f} 10876 }; 10877 static const D3DXVECTOR3 box_normals_position1f[24] = {{0}}; 10878 static const D3DXVECTOR3 box_normals_position2f[24] = 10879 { 10880 {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f}, 10881 {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, 1.0f}, 10882 {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, -1.0f}, 10883 {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}, 10884 {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, -1.0f}, 10885 {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f}, 10886 {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}, 10887 {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, -1.0f} 10888 }; 10889 10890 static const D3DXVECTOR3 sphere_normals[22] = 10891 { 10892 { 0.000000f, -0.000000f, 1.000000f}, { 0.000000f, 0.582244f, 0.813014f}, 10893 { 0.582244f, -0.000000f, 0.813014f}, {-0.000000f, -0.582244f, 0.813014f}, 10894 {-0.582244f, 0.000000f, 0.813014f}, {-0.000000f, 0.890608f, 0.454772f}, 10895 { 0.890608f, 0.000000f, 0.454772f}, { 0.000000f, -0.890608f, 0.454772f}, 10896 {-0.890608f, -0.000000f, 0.454772f}, { 0.000000f, 1.000000f, -0.000000f}, 10897 { 1.000000f, -0.000000f, -0.000000f}, {-0.000000f, -1.000000f, -0.000000f}, 10898 {-1.000000f, 0.000000f, -0.000000f}, { 0.000000f, 0.890608f, -0.454773f}, 10899 { 0.890608f, -0.000000f, -0.454772f}, {-0.000000f, -0.890608f, -0.454773f}, 10900 {-0.890608f, 0.000000f, -0.454773f}, { 0.000000f, 0.582244f, -0.813015f}, 10901 { 0.582244f, -0.000000f, -0.813015f}, { 0.000000f, -0.582244f, -0.813015f}, 10902 {-0.582243f, 0.000000f, -0.813015f}, { 0.000000f, 0.000000f, -1.000000f} 10903 }; 10904 static const D3DXVECTOR3 sphere_normals_area[22] = 10905 { 10906 { 0.000000f, -0.000000f, 1.000000f}, {-0.215311f, 0.554931f, 0.803550f}, 10907 { 0.554931f, 0.215311f, 0.803550f}, { 0.215311f, -0.554931f, 0.803550f}, 10908 {-0.554931f, -0.215311f, 0.803550f}, {-0.126638f, 0.872121f, 0.472618f}, 10909 { 0.872121f, 0.126638f, 0.472618f}, { 0.126638f, -0.872121f, 0.472618f}, 10910 {-0.872121f, -0.126637f, 0.472618f}, { 0.000000f, 1.000000f, -0.000000f}, 10911 { 1.000000f, -0.000000f, -0.000000f}, {-0.000000f, -1.000000f, -0.000000f}, 10912 {-1.000000f, 0.000000f, -0.000000f}, { 0.126638f, 0.872121f, -0.472618f}, 10913 { 0.872121f, -0.126638f, -0.472618f}, {-0.126638f, -0.872121f, -0.472618f}, 10914 {-0.872121f, 0.126638f, -0.472618f}, { 0.215311f, 0.554931f, -0.803550f}, 10915 { 0.554931f, -0.215311f, -0.803550f}, {-0.215311f, -0.554931f, -0.803550f}, 10916 {-0.554931f, 0.215311f, -0.803550f}, { 0.000000f, 0.000000f, -1.000000f} 10917 }; 10918 static const D3DXVECTOR3 sphere_normals_equal[22] = 10919 { 10920 { 0.000000f, -0.000000f, 1.000000f}, {-0.134974f, 0.522078f, 0.842150f}, 10921 { 0.522078f, 0.134974f, 0.842150f}, { 0.134974f, -0.522078f, 0.842150f}, 10922 {-0.522078f, -0.134974f, 0.842150f}, {-0.026367f, 0.857121f, 0.514440f}, 10923 { 0.857121f, 0.026367f, 0.514440f}, { 0.026367f, -0.857121f, 0.514440f}, 10924 {-0.857121f, -0.026367f, 0.514440f}, { 0.000000f, 1.000000f, -0.000000f}, 10925 { 1.000000f, -0.000000f, -0.000000f}, {-0.000000f, -1.000000f, -0.000000f}, 10926 {-1.000000f, 0.000000f, -0.000000f}, { 0.026367f, 0.857121f, -0.514440f}, 10927 { 0.857121f, -0.026367f, -0.514440f}, {-0.026367f, -0.857121f, -0.514440f}, 10928 {-0.857121f, 0.026367f, -0.514440f}, { 0.134975f, 0.522078f, -0.842150f}, 10929 { 0.522078f, -0.134975f, -0.842150f}, {-0.134974f, -0.522078f, -0.842150f}, 10930 {-0.522078f, 0.134974f, -0.842150f}, { 0.000000f, 0.000000f, -1.000000f} 10931 }; 10932 10933 static const D3DVERTEXELEMENT9 position3f_normal1f_declaration[] = 10934 { 10935 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 10936 {0, sizeof(D3DXVECTOR3), D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 10937 D3DDECL_END() 10938 }; 10939 static const D3DVERTEXELEMENT9 position3f_normal2f_declaration[] = 10940 { 10941 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 10942 {0, sizeof(D3DXVECTOR3), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 10943 D3DDECL_END() 10944 }; 10945 static const D3DVERTEXELEMENT9 normal4f_position3f_declaration[] = 10946 { 10947 {0, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 10948 {0, sizeof(D3DXVECTOR4), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 10949 D3DDECL_END() 10950 }; 10951 static const D3DVERTEXELEMENT9 position1f_normal3f_declaration[] = 10952 { 10953 {0, 0, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 10954 {0, sizeof(float), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 10955 D3DDECL_END() 10956 }; 10957 static const D3DVERTEXELEMENT9 position2f_normal3f_declaration[] = 10958 { 10959 {0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 10960 {0, sizeof(D3DXVECTOR2), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 10961 D3DDECL_END() 10962 }; 10963 static const D3DVERTEXELEMENT9 position4f_normal3f_declaration[] = 10964 { 10965 {0, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 10966 {0, sizeof(D3DXVECTOR4), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 10967 D3DDECL_END() 10968 }; 10969 10970 for (i = 0; i < ARRAY_SIZE(compute_normals_funcs); i++) 10971 { 10972 hr = compute_normals_funcs[i].apply(NULL, NULL); 10973 ok(hr == D3DERR_INVALIDCALL, "%s returned %#x, expected D3DERR_INVALIDCALL\n", compute_normals_funcs[i].name, hr); 10974 } 10975 10976 if (!(test_context = new_test_context())) 10977 { 10978 skip("Couldn't create test context\n"); 10979 return; 10980 } 10981 device = test_context->device; 10982 10983 hr = D3DXCreateBox(device, 1.0f, 1.0f, 1.0f, &mesh, &adjacency); 10984 ok(SUCCEEDED(hr), "D3DXCreateBox failed %#x\n", hr); 10985 10986 /* Check wrong input */ 10987 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, 10988 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE, NULL, -1.01f, -0.01f, -1.01f, NULL, NULL); 10989 todo_wine ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr); 10990 10991 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DDECLUSAGE_NORMAL, 0, 10992 D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_BY_AREA | D3DXTANGENT_WEIGHT_EQUAL, 10993 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL); 10994 ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr); 10995 10996 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, 10997 D3DDECLUSAGE_NORMAL, 0, 0, NULL, -1.01f, -0.01f, -1.01f, NULL, NULL); 10998 todo_wine ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr); 10999 11000 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, 11001 D3DDECLUSAGE_NORMAL, 1, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS, 11002 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL); 11003 ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr); 11004 11005 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, 11006 D3DX_DEFAULT, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS, 11007 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL); 11008 ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr); 11009 11010 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, 11011 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_CALCULATE_NORMALS, 11012 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL); 11013 todo_wine ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr); 11014 11015 for (i = 0; i < ARRAY_SIZE(compute_normals_funcs); i++) 11016 { 11017 const struct compute_normals_func *func = &compute_normals_funcs[i]; 11018 11019 /* Mesh without normals */ 11020 hr = mesh->lpVtbl->CloneMeshFVF(mesh, 0, D3DFVF_XYZ, device, &cloned_mesh); 11021 ok(SUCCEEDED(hr), "CloneMeshFVF failed %#x\n", hr); 11022 11023 hr = func->apply(cloned_mesh, NULL); 11024 ok(hr == D3DERR_INVALIDCALL, "%s returned %#x, expected D3DERR_INVALIDCALL\n", func->name, hr); 11025 11026 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh); 11027 ok(!refcount, "Mesh has %u references left\n", refcount); 11028 11029 /* Mesh without positions */ 11030 hr = mesh->lpVtbl->CloneMeshFVF(mesh, 0, D3DFVF_NORMAL, device, &cloned_mesh); 11031 ok(SUCCEEDED(hr), "CloneMeshFVF failed %#x\n", hr); 11032 11033 hr = func->apply(cloned_mesh, NULL); 11034 ok(hr == D3DERR_INVALIDCALL, "%s returned %#x, expected D3DERR_INVALIDCALL\n", func->name, hr); 11035 11036 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh); 11037 ok(!refcount, "Mesh has %u references left\n", refcount); 11038 11039 /* Mesh with D3DDECLTYPE_FLOAT1 normals */ 11040 hr = mesh->lpVtbl->CloneMesh(mesh, 0, position3f_normal1f_declaration, device, &cloned_mesh); 11041 ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr); 11042 11043 hr = func->apply(cloned_mesh, NULL); 11044 ok(hr == D3DERR_INVALIDCALL, "%s returned %#x, expected D3DERR_INVALIDCALL\n", func->name, hr); 11045 11046 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh); 11047 ok(!refcount, "Mesh has %u references left\n", refcount); 11048 11049 /* Mesh with D3DDECLTYPE_FLOAT2 normals */ 11050 hr = mesh->lpVtbl->CloneMesh(mesh, 0, position3f_normal2f_declaration, device, &cloned_mesh); 11051 ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr); 11052 11053 hr = func->apply(cloned_mesh, NULL); 11054 ok(hr == D3DERR_INVALIDCALL, "%s returned %#x, expected D3DERR_INVALIDCALL\n", func->name, hr); 11055 11056 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh); 11057 ok(!refcount, "Mesh has %u references left\n", refcount); 11058 11059 /* Mesh without adjacency data */ 11060 hr = clear_normals(mesh); 11061 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr); 11062 11063 hr = func->apply(mesh, NULL); 11064 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr); 11065 11066 compare_normals(__LINE__, func->name, mesh, box_normals, ARRAY_SIZE(box_normals)); 11067 11068 /* Mesh with adjacency data */ 11069 hr = clear_normals(mesh); 11070 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr); 11071 11072 hr = func->apply(mesh, ID3DXBuffer_GetBufferPointer(adjacency)); 11073 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr); 11074 11075 compare_normals(__LINE__, func->name, mesh, box_normals_adjacency, ARRAY_SIZE(box_normals_adjacency)); 11076 11077 /* Mesh with custom vertex format, D3DDECLTYPE_FLOAT4 normals and adjacency */ 11078 hr = mesh->lpVtbl->CloneMesh(mesh, 0, normal4f_position3f_declaration, device, &cloned_mesh); 11079 ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr); 11080 11081 hr = clear_normals(cloned_mesh); 11082 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr); 11083 11084 hr = func->apply(cloned_mesh, ID3DXBuffer_GetBufferPointer(adjacency)); 11085 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr); 11086 11087 compare_normals(__LINE__, func->name, cloned_mesh, box_normals_adjacency, ARRAY_SIZE(box_normals_adjacency)); 11088 11089 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh); 11090 ok(!refcount, "Mesh has %u references left\n", refcount); 11091 11092 /* Mesh with D3DDECLTYPE_FLOAT1 positions and D3DDECLTYPE_FLOAT3 normals */ 11093 hr = mesh->lpVtbl->CloneMesh(mesh, 0, position1f_normal3f_declaration, device, &cloned_mesh); 11094 ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr); 11095 11096 hr = clear_normals(cloned_mesh); 11097 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr); 11098 11099 hr = func->apply(cloned_mesh, ID3DXBuffer_GetBufferPointer(adjacency)); 11100 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr); 11101 11102 compare_normals(__LINE__, func->name, cloned_mesh, box_normals_position1f, ARRAY_SIZE(box_normals_position1f)); 11103 11104 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh); 11105 ok(!refcount, "Mesh has %u references left\n", refcount); 11106 11107 /* Mesh with D3DDECLTYPE_FLOAT2 positions and D3DDECLTYPE_FLOAT3 normals */ 11108 hr = mesh->lpVtbl->CloneMesh(mesh, 0, position2f_normal3f_declaration, device, &cloned_mesh); 11109 ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr); 11110 11111 hr = clear_normals(cloned_mesh); 11112 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr); 11113 11114 hr = func->apply(cloned_mesh, ID3DXBuffer_GetBufferPointer(adjacency)); 11115 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr); 11116 11117 compare_normals(__LINE__, func->name, cloned_mesh, box_normals_position2f, ARRAY_SIZE(box_normals_position2f)); 11118 11119 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh); 11120 ok(!refcount, "Mesh has %u references left\n", refcount); 11121 11122 /* Mesh with D3DDECLTYPE_FLOAT4 positions and D3DDECLTYPE_FLOAT3 normals */ 11123 hr = mesh->lpVtbl->CloneMesh(mesh, 0, position4f_normal3f_declaration, device, &cloned_mesh); 11124 ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr); 11125 11126 hr = clear_normals(cloned_mesh); 11127 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr); 11128 11129 hr = func->apply(cloned_mesh, ID3DXBuffer_GetBufferPointer(adjacency)); 11130 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr); 11131 11132 compare_normals(__LINE__, func->name, cloned_mesh, box_normals_adjacency, ARRAY_SIZE(box_normals_adjacency)); 11133 11134 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh); 11135 ok(!refcount, "Mesh has %u references left\n", refcount); 11136 } 11137 11138 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, 11139 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_BY_AREA, 11140 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL); 11141 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr); 11142 11143 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, box_normals, ARRAY_SIZE(box_normals)); 11144 11145 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, 11146 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_BY_AREA, 11147 ID3DXBuffer_GetBufferPointer(adjacency), -1.01f, -0.01f, -1.01f, NULL, NULL); 11148 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr); 11149 11150 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, box_normals_adjacency_area, ARRAY_SIZE(box_normals_adjacency_area)); 11151 11152 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, 11153 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_EQUAL, 11154 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL); 11155 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr); 11156 11157 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, box_normals, ARRAY_SIZE(box_normals)); 11158 11159 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, 11160 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_EQUAL, 11161 ID3DXBuffer_GetBufferPointer(adjacency), -1.01f, -0.01f, -1.01f, NULL, NULL); 11162 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr); 11163 11164 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, box_normals_adjacency_area, ARRAY_SIZE(box_normals_adjacency_area)); 11165 11166 refcount = mesh->lpVtbl->Release(mesh); 11167 ok(!refcount, "Mesh has %u references left\n", refcount); 11168 refcount = ID3DXBuffer_Release(adjacency); 11169 ok(!refcount, "Buffer has %u references left\n", refcount); 11170 11171 hr = D3DXCreateSphere(device, 1.0f, 4, 6, &mesh, &adjacency); 11172 ok(SUCCEEDED(hr), "D3DXCreateSphere failed %#x\n", hr); 11173 11174 for (i = 0; i < ARRAY_SIZE(compute_normals_funcs); i++) 11175 { 11176 const struct compute_normals_func *func = &compute_normals_funcs[i]; 11177 11178 /* Sphere without adjacency data */ 11179 hr = clear_normals(mesh); 11180 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr); 11181 11182 hr = func->apply(mesh, NULL); 11183 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr); 11184 11185 compare_normals(__LINE__, func->name, mesh, sphere_normals, ARRAY_SIZE(sphere_normals)); 11186 11187 /* Sphere with adjacency data */ 11188 hr = clear_normals(mesh); 11189 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr); 11190 11191 hr = func->apply(mesh, ID3DXBuffer_GetBufferPointer(adjacency)); 11192 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr); 11193 11194 compare_normals(__LINE__, func->name, mesh, sphere_normals, ARRAY_SIZE(sphere_normals)); 11195 } 11196 11197 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, 11198 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_BY_AREA, 11199 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL); 11200 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr); 11201 11202 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, sphere_normals_area, ARRAY_SIZE(sphere_normals_area)); 11203 11204 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, 11205 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_BY_AREA, 11206 ID3DXBuffer_GetBufferPointer(adjacency), -1.01f, -0.01f, -1.01f, NULL, NULL); 11207 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr); 11208 11209 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, sphere_normals_area, ARRAY_SIZE(sphere_normals_area)); 11210 11211 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, 11212 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_EQUAL, 11213 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL); 11214 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr); 11215 11216 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, sphere_normals_equal, ARRAY_SIZE(sphere_normals_equal)); 11217 11218 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, 11219 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_EQUAL, 11220 ID3DXBuffer_GetBufferPointer(adjacency), -1.01f, -0.01f, -1.01f, NULL, NULL); 11221 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr); 11222 11223 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, sphere_normals_equal, ARRAY_SIZE(sphere_normals_equal)); 11224 11225 refcount = mesh->lpVtbl->Release(mesh); 11226 ok(!refcount, "Mesh has %u references left\n", refcount); 11227 refcount = ID3DXBuffer_Release(adjacency); 11228 ok(!refcount, "Buffer has %u references left\n", refcount); 11229 11230 free_test_context(test_context); 11231 } 11232 11233 static void D3DXCreateAnimationControllerTest(void) 11234 { 11235 HRESULT hr; 11236 ID3DXAnimationController *animation; 11237 UINT value; 11238 11239 hr = D3DXCreateAnimationController(0, 0, 0, 0, NULL); 11240 ok(hr == D3D_OK, "Got unexpected hr returned %#x.\n", hr); 11241 11242 animation = (void*)0xdeadbeef; 11243 hr = D3DXCreateAnimationController(0, 1, 1, 1, &animation); 11244 ok(hr == D3D_OK, "Got unexpected hr returned %#x.\n", hr); 11245 ok(animation == (void*)0xdeadbeef, "Got unexpected animation %p.\n", animation); 11246 11247 animation = (void*)0xdeadbeef; 11248 hr = D3DXCreateAnimationController(1, 0, 1, 1, &animation); 11249 ok(hr == D3D_OK, "Got unexpected hr returned %#x.\n", hr); 11250 ok(animation == (void*)0xdeadbeef, "Got unexpected animation %p.\n", animation); 11251 11252 animation = (void*)0xdeadbeef; 11253 hr = D3DXCreateAnimationController(1, 1, 0, 1, &animation); 11254 ok(hr == D3D_OK, "Got unexpected hr returned %#x.\n", hr); 11255 ok(animation == (void*)0xdeadbeef, "Got unexpected animation %p.\n", animation); 11256 11257 animation = (void*)0xdeadbeef; 11258 hr = D3DXCreateAnimationController(1, 1, 1, 0, &animation); 11259 ok(hr == D3D_OK, "Got unexpected hr returned %#x.\n", hr); 11260 ok(animation == (void*)0xdeadbeef, "Got unexpected animation %p.\n", animation); 11261 11262 hr = D3DXCreateAnimationController(1, 1, 1, 1, &animation); 11263 ok(hr == D3D_OK, "Got unexpected hr returned %#x.\n", hr); 11264 11265 value = animation->lpVtbl->GetMaxNumAnimationOutputs(animation); 11266 ok(value == 1, "Got unexpected value %u.\n", value); 11267 11268 value = animation->lpVtbl->GetMaxNumAnimationSets(animation); 11269 ok(value == 1, "Got unexpected value %u.\n", value); 11270 11271 value = animation->lpVtbl->GetMaxNumTracks(animation); 11272 ok(value == 1, "Got unexpected value %u.\n", value); 11273 11274 value = animation->lpVtbl->GetMaxNumEvents(animation); 11275 ok(value == 1, "Got unexpected value %u.\n", value); 11276 11277 animation->lpVtbl->Release(animation); 11278 11279 hr = D3DXCreateAnimationController(100, 101, 102, 103, &animation); 11280 ok(hr == D3D_OK, "Got unexpected hr returned %#x.\n", hr); 11281 11282 value = animation->lpVtbl->GetMaxNumAnimationOutputs(animation); 11283 ok(value == 100, "Got unexpected value %u.\n", value); 11284 11285 value = animation->lpVtbl->GetMaxNumAnimationSets(animation); 11286 ok(value == 101, "Got unexpected value %u.\n", value); 11287 11288 value = animation->lpVtbl->GetMaxNumTracks(animation); 11289 ok(value == 102, "Got unexpected value %u.\n", value); 11290 11291 value = animation->lpVtbl->GetMaxNumEvents(animation); 11292 ok(value == 103, "Got unexpected value %u.\n", value); 11293 11294 animation->lpVtbl->Release(animation); 11295 } 11296 11297 static void test_D3DXFrameFind(void) 11298 { 11299 static char n1[] = "name1"; 11300 static char n2[] = "name2"; 11301 static char n3[] = "name3"; 11302 static char n4[] = "name4"; 11303 static char n5[] = "name5"; 11304 static char n6[] = "name6"; 11305 static char N1[] = "Name1"; 11306 D3DXFRAME root, sibling, sibling2, child, *ret; 11307 D3DXFRAME child2, child3; 11308 11309 ret = D3DXFrameFind(NULL, NULL); 11310 ok(ret == NULL, "Unexpected frame, %p.\n", ret); 11311 11312 ret = D3DXFrameFind(NULL, "test"); 11313 ok(ret == NULL, "Unexpected frame, %p.\n", ret); 11314 11315 memset(&root, 0, sizeof(root)); 11316 11317 ret = D3DXFrameFind(&root, NULL); 11318 ok(ret == &root, "Unexpected frame, %p.\n", ret); 11319 11320 root.Name = n1; 11321 ret = D3DXFrameFind(&root, NULL); 11322 ok(ret == NULL, "Unexpected frame, %p.\n", ret); 11323 11324 ret = D3DXFrameFind(&root, n1); 11325 ok(ret == &root, "Unexpected frame, %p.\n", ret); 11326 11327 ret = D3DXFrameFind(&root, N1); 11328 ok(ret == NULL, "Unexpected frame, %p.\n", ret); 11329 11330 /* Test siblings order traversal. */ 11331 memset(&sibling, 0, sizeof(sibling)); 11332 sibling.Name = n2; 11333 root.pFrameSibling = &sibling; 11334 ret = D3DXFrameFind(&root, n2); 11335 ok(ret == &sibling, "Unexpected frame, %p.\n", ret); 11336 11337 memset(&sibling2, 0, sizeof(sibling2)); 11338 sibling2.Name = n2; 11339 sibling.pFrameSibling = &sibling2; 11340 ret = D3DXFrameFind(&root, n2); 11341 ok(ret == &sibling, "Unexpected frame, %p.\n", ret); 11342 11343 sibling2.Name = n3; 11344 ret = D3DXFrameFind(&root, n3); 11345 ok(ret == &sibling2, "Unexpected frame, %p.\n", ret); 11346 11347 /* Siblings first. */ 11348 memset(&child, 0, sizeof(child)); 11349 child.Name = n2; 11350 root.pFrameFirstChild = &child; 11351 ret = D3DXFrameFind(&root, n2); 11352 ok(ret == &sibling, "Unexpected frame, %p.\n", ret); 11353 11354 child.Name = n4; 11355 ret = D3DXFrameFind(&root, n4); 11356 ok(ret == &child, "Unexpected frame, %p.\n", ret); 11357 11358 /* Link a grandchild and another one for sibling. */ 11359 memset(&child2, 0, sizeof(child2)); 11360 memset(&child3, 0, sizeof(child3)); 11361 child2.Name = child3.Name = n5; 11362 sibling.pFrameFirstChild = &child2; 11363 child.pFrameFirstChild = &child3; 11364 ret = D3DXFrameFind(&root, n5); 11365 ok(ret == &child2, "Unexpected frame, %p.\n", ret); 11366 11367 child3.Name = n6; 11368 ret = D3DXFrameFind(&root, n6); 11369 ok(ret == &child3, "Unexpected frame, %p.\n", ret); 11370 } 11371 11372 START_TEST(mesh) 11373 { 11374 D3DXBoundProbeTest(); 11375 D3DXComputeBoundingBoxTest(); 11376 D3DXComputeBoundingSphereTest(); 11377 D3DXGetFVFVertexSizeTest(); 11378 D3DXIntersectTriTest(); 11379 D3DXCreateMeshTest(); 11380 D3DXCreateMeshFVFTest(); 11381 D3DXLoadMeshTest(); 11382 D3DXLoadSkinMeshFromXofTest(); 11383 D3DXCreateBoxTest(); 11384 D3DXCreatePolygonTest(); 11385 D3DXCreateSphereTest(); 11386 D3DXCreateCylinderTest(); 11387 D3DXCreateTextTest(); 11388 D3DXCreateTorusTest(); 11389 D3DXCreateAnimationControllerTest(); 11390 test_get_decl_length(); 11391 test_get_decl_vertex_size(); 11392 test_fvf_decl_conversion(); 11393 D3DXGenerateAdjacencyTest(); 11394 test_update_semantics(); 11395 test_create_skin_info(); 11396 test_convert_adjacency_to_point_reps(); 11397 test_convert_point_reps_to_adjacency(); 11398 test_weld_vertices(); 11399 test_clone_mesh(); 11400 test_valid_mesh(); 11401 test_optimize_vertices(); 11402 test_optimize_faces(); 11403 test_compute_normals(); 11404 test_D3DXFrameFind(); 11405 } 11406