1 /* 2 * Copyright 2008 David Adam 3 * Copyright 2008 Luis Busquets 4 * Copyright 2009 Henri Verbeet for CodeWeavers 5 * Copyright 2011 Michael Mc Donnell 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 20 */ 21 22 #define COBJMACROS 23 #include <stdio.h> 24 #include <float.h> 25 #include <limits.h> 26 #include "wine/test.h" 27 #include "d3dx9.h" 28 29 #ifndef NAN 30 /* From wine/port.h */ 31 static inline float __port_nan(void) 32 { 33 static const unsigned __nan_bytes = 0x7fc00000; 34 return *(const float *)&__nan_bytes; 35 } 36 #define NAN __port_nan() 37 #endif 38 39 /* Set the WINETEST_DEBUG environment variable to be greater than 1 for verbose 40 * function call traces of ID3DXAllocateHierarchy callbacks. */ 41 #define TRACECALLBACK if(winetest_debug > 1) trace 42 43 #define admitted_error 0.0001f 44 45 #define compare_vertex_sizes(type, exp) \ 46 got=D3DXGetFVFVertexSize(type); \ 47 ok(got==exp, "Expected: %d, Got: %d\n", exp, got); 48 49 #define compare_float(got, exp) \ 50 do { \ 51 float _got = (got); \ 52 float _exp = (exp); \ 53 ok(_got == _exp, "Expected: %g, Got: %g\n", _exp, _got); \ 54 } while (0) 55 56 static BOOL compare(FLOAT u, FLOAT v) 57 { 58 return (fabs(u-v) < admitted_error); 59 } 60 61 static BOOL compare_vec3(D3DXVECTOR3 u, D3DXVECTOR3 v) 62 { 63 return ( compare(u.x, v.x) && compare(u.y, v.y) && compare(u.z, v.z) ); 64 } 65 66 static BOOL compare_vec4(D3DXVECTOR4 u, D3DXVECTOR4 v) 67 { 68 return compare(u.x, v.x) && compare(u.y, v.y) && compare(u.z, v.z) && compare(u.w, v.w); 69 } 70 71 #define check_floats(got, exp, dim) check_floats_(__LINE__, "", got, exp, dim) 72 static void check_floats_(int line, const char *prefix, const float *got, const float *exp, int dim) 73 { 74 int i; 75 char exp_buffer[256] = ""; 76 char got_buffer[256] = ""; 77 char *exp_buffer_ptr = exp_buffer; 78 char *got_buffer_ptr = got_buffer; 79 BOOL equal = TRUE; 80 81 for (i = 0; i < dim; i++) { 82 if (i) { 83 exp_buffer_ptr += sprintf(exp_buffer_ptr, ", "); 84 got_buffer_ptr += sprintf(got_buffer_ptr, ", "); 85 } 86 equal = equal && compare(*exp, *got); 87 exp_buffer_ptr += sprintf(exp_buffer_ptr, "%g", *exp); 88 got_buffer_ptr += sprintf(got_buffer_ptr, "%g", *got); 89 exp++, got++; 90 } 91 ok_(__FILE__,line)(equal, "%sExpected (%s), got (%s)", prefix, exp_buffer, got_buffer); 92 } 93 94 struct vertex 95 { 96 D3DXVECTOR3 position; 97 D3DXVECTOR3 normal; 98 }; 99 100 typedef WORD face[3]; 101 102 static BOOL compare_face(face a, face b) 103 { 104 return (a[0]==b[0] && a[1] == b[1] && a[2] == b[2]); 105 } 106 107 struct test_context 108 { 109 HWND hwnd; 110 IDirect3D9 *d3d; 111 IDirect3DDevice9 *device; 112 }; 113 114 /* Initializes a test context struct. Use it to initialize DirectX. 115 * 116 * Returns NULL if an error occurred. 117 */ 118 static struct test_context *new_test_context(void) 119 { 120 HRESULT hr; 121 HWND hwnd = NULL; 122 IDirect3D9 *d3d = NULL; 123 IDirect3DDevice9 *device = NULL; 124 D3DPRESENT_PARAMETERS d3dpp = {0}; 125 struct test_context *test_context; 126 127 if (!(hwnd = CreateWindowA("static", "d3dx9_test", WS_OVERLAPPEDWINDOW, 0, 0, 128 640, 480, NULL, NULL, NULL, NULL))) 129 { 130 skip("Couldn't create application window\n"); 131 goto error; 132 } 133 134 d3d = Direct3DCreate9(D3D_SDK_VERSION); 135 if (!d3d) 136 { 137 skip("Couldn't create IDirect3D9 object\n"); 138 goto error; 139 } 140 141 memset(&d3dpp, 0, sizeof(d3dpp)); 142 d3dpp.Windowed = TRUE; 143 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; 144 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd, 145 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device); 146 if (FAILED(hr)) 147 { 148 skip("Couldn't create IDirect3DDevice9 object %#x\n", hr); 149 goto error; 150 } 151 152 test_context = HeapAlloc(GetProcessHeap(), 0, sizeof(*test_context)); 153 if (!test_context) 154 { 155 skip("Couldn't allocate memory for test_context\n"); 156 goto error; 157 } 158 test_context->hwnd = hwnd; 159 test_context->d3d = d3d; 160 test_context->device = device; 161 162 return test_context; 163 164 error: 165 if (device) 166 IDirect3DDevice9_Release(device); 167 168 if (d3d) 169 IDirect3D9_Release(d3d); 170 171 if (hwnd) 172 DestroyWindow(hwnd); 173 174 return NULL; 175 } 176 177 static void free_test_context(struct test_context *test_context) 178 { 179 if (!test_context) 180 return; 181 182 if (test_context->device) 183 IDirect3DDevice9_Release(test_context->device); 184 185 if (test_context->d3d) 186 IDirect3D9_Release(test_context->d3d); 187 188 if (test_context->hwnd) 189 DestroyWindow(test_context->hwnd); 190 191 HeapFree(GetProcessHeap(), 0, test_context); 192 } 193 194 struct mesh 195 { 196 DWORD number_of_vertices; 197 struct vertex *vertices; 198 199 DWORD number_of_faces; 200 face *faces; 201 202 DWORD fvf; 203 UINT vertex_size; 204 }; 205 206 static void free_mesh(struct mesh *mesh) 207 { 208 HeapFree(GetProcessHeap(), 0, mesh->faces); 209 HeapFree(GetProcessHeap(), 0, mesh->vertices); 210 } 211 212 static BOOL new_mesh(struct mesh *mesh, DWORD number_of_vertices, DWORD number_of_faces) 213 { 214 mesh->vertices = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, number_of_vertices * sizeof(*mesh->vertices)); 215 if (!mesh->vertices) 216 { 217 return FALSE; 218 } 219 mesh->number_of_vertices = number_of_vertices; 220 221 mesh->faces = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, number_of_faces * sizeof(*mesh->faces)); 222 if (!mesh->faces) 223 { 224 HeapFree(GetProcessHeap(), 0, mesh->vertices); 225 return FALSE; 226 } 227 mesh->number_of_faces = number_of_faces; 228 229 return TRUE; 230 } 231 232 static void compare_mesh(const char *name, ID3DXMesh *d3dxmesh, struct mesh *mesh) 233 { 234 HRESULT hr; 235 DWORD number_of_vertices, number_of_faces; 236 IDirect3DVertexBuffer9 *vertex_buffer; 237 IDirect3DIndexBuffer9 *index_buffer; 238 D3DVERTEXBUFFER_DESC vertex_buffer_description; 239 D3DINDEXBUFFER_DESC index_buffer_description; 240 struct vertex *vertices; 241 face *faces; 242 int expected, i; 243 244 number_of_vertices = d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh); 245 ok(number_of_vertices == mesh->number_of_vertices, "Test %s, result %u, expected %d\n", 246 name, number_of_vertices, mesh->number_of_vertices); 247 248 number_of_faces = d3dxmesh->lpVtbl->GetNumFaces(d3dxmesh); 249 ok(number_of_faces == mesh->number_of_faces, "Test %s, result %u, expected %d\n", 250 name, number_of_faces, mesh->number_of_faces); 251 252 /* vertex buffer */ 253 hr = d3dxmesh->lpVtbl->GetVertexBuffer(d3dxmesh, &vertex_buffer); 254 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr); 255 256 if (hr != D3D_OK) 257 { 258 skip("Couldn't get vertex buffer\n"); 259 } 260 else 261 { 262 hr = IDirect3DVertexBuffer9_GetDesc(vertex_buffer, &vertex_buffer_description); 263 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr); 264 265 if (hr != D3D_OK) 266 { 267 skip("Couldn't get vertex buffer description\n"); 268 } 269 else 270 { 271 ok(vertex_buffer_description.Format == D3DFMT_VERTEXDATA, "Test %s, result %x, expected %x (D3DFMT_VERTEXDATA)\n", 272 name, vertex_buffer_description.Format, D3DFMT_VERTEXDATA); 273 ok(vertex_buffer_description.Type == D3DRTYPE_VERTEXBUFFER, "Test %s, result %x, expected %x (D3DRTYPE_VERTEXBUFFER)\n", 274 name, vertex_buffer_description.Type, D3DRTYPE_VERTEXBUFFER); 275 ok(vertex_buffer_description.Usage == 0, "Test %s, result %x, expected %x\n", name, vertex_buffer_description.Usage, 0); 276 ok(vertex_buffer_description.Pool == D3DPOOL_MANAGED, "Test %s, result %x, expected %x (D3DPOOL_MANAGED)\n", 277 name, vertex_buffer_description.Pool, D3DPOOL_MANAGED); 278 ok(vertex_buffer_description.FVF == mesh->fvf, "Test %s, result %x, expected %x\n", 279 name, vertex_buffer_description.FVF, mesh->fvf); 280 if (mesh->fvf == 0) 281 { 282 expected = number_of_vertices * mesh->vertex_size; 283 } 284 else 285 { 286 expected = number_of_vertices * D3DXGetFVFVertexSize(mesh->fvf); 287 } 288 ok(vertex_buffer_description.Size == expected, "Test %s, result %x, expected %x\n", 289 name, vertex_buffer_description.Size, expected); 290 } 291 292 /* specify offset and size to avoid potential overruns */ 293 hr = IDirect3DVertexBuffer9_Lock(vertex_buffer, 0, number_of_vertices * sizeof(D3DXVECTOR3) * 2, 294 (void **)&vertices, D3DLOCK_DISCARD); 295 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr); 296 297 if (hr != D3D_OK) 298 { 299 skip("Couldn't lock vertex buffer\n"); 300 } 301 else 302 { 303 for (i = 0; i < number_of_vertices; i++) 304 { 305 ok(compare_vec3(vertices[i].position, mesh->vertices[i].position), 306 "Test %s, vertex position %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, 307 vertices[i].position.x, vertices[i].position.y, vertices[i].position.z, 308 mesh->vertices[i].position.x, mesh->vertices[i].position.y, mesh->vertices[i].position.z); 309 ok(compare_vec3(vertices[i].normal, mesh->vertices[i].normal), 310 "Test %s, vertex normal %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, 311 vertices[i].normal.x, vertices[i].normal.y, vertices[i].normal.z, 312 mesh->vertices[i].normal.x, mesh->vertices[i].normal.y, mesh->vertices[i].normal.z); 313 } 314 315 IDirect3DVertexBuffer9_Unlock(vertex_buffer); 316 } 317 318 IDirect3DVertexBuffer9_Release(vertex_buffer); 319 } 320 321 /* index buffer */ 322 hr = d3dxmesh->lpVtbl->GetIndexBuffer(d3dxmesh, &index_buffer); 323 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr); 324 325 if (!index_buffer) 326 { 327 skip("Couldn't get index buffer\n"); 328 } 329 else 330 { 331 hr = IDirect3DIndexBuffer9_GetDesc(index_buffer, &index_buffer_description); 332 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr); 333 334 if (hr != D3D_OK) 335 { 336 skip("Couldn't get index buffer description\n"); 337 } 338 else 339 { 340 ok(index_buffer_description.Format == D3DFMT_INDEX16, "Test %s, result %x, expected %x (D3DFMT_INDEX16)\n", 341 name, index_buffer_description.Format, D3DFMT_INDEX16); 342 ok(index_buffer_description.Type == D3DRTYPE_INDEXBUFFER, "Test %s, result %x, expected %x (D3DRTYPE_INDEXBUFFER)\n", 343 name, index_buffer_description.Type, D3DRTYPE_INDEXBUFFER); 344 ok(index_buffer_description.Usage == 0, "Test %s, result %#x, expected %#x.\n", 345 name, index_buffer_description.Usage, 0); 346 ok(index_buffer_description.Pool == D3DPOOL_MANAGED, "Test %s, result %x, expected %x (D3DPOOL_MANAGED)\n", 347 name, index_buffer_description.Pool, D3DPOOL_MANAGED); 348 expected = number_of_faces * sizeof(WORD) * 3; 349 ok(index_buffer_description.Size == expected, "Test %s, result %x, expected %x\n", 350 name, index_buffer_description.Size, expected); 351 } 352 353 /* specify offset and size to avoid potential overruns */ 354 hr = IDirect3DIndexBuffer9_Lock(index_buffer, 0, number_of_faces * sizeof(WORD) * 3, 355 (void **)&faces, D3DLOCK_DISCARD); 356 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr); 357 358 if (hr != D3D_OK) 359 { 360 skip("Couldn't lock index buffer\n"); 361 } 362 else 363 { 364 for (i = 0; i < number_of_faces; i++) 365 { 366 ok(compare_face(faces[i], mesh->faces[i]), 367 "Test %s, face %d, result (%u, %u, %u), expected (%u, %u, %u)\n", name, i, 368 faces[i][0], faces[i][1], faces[i][2], 369 mesh->faces[i][0], mesh->faces[i][1], mesh->faces[i][2]); 370 } 371 372 IDirect3DIndexBuffer9_Unlock(index_buffer); 373 } 374 375 IDirect3DIndexBuffer9_Release(index_buffer); 376 } 377 } 378 379 static void D3DXBoundProbeTest(void) 380 { 381 BOOL result; 382 D3DXVECTOR3 bottom_point, center, top_point, raydirection, rayposition; 383 FLOAT radius; 384 385 /*____________Test the Box case___________________________*/ 386 bottom_point.x = -3.0f; bottom_point.y = -2.0f; bottom_point.z = -1.0f; 387 top_point.x = 7.0f; top_point.y = 8.0f; top_point.z = 9.0f; 388 389 raydirection.x = -4.0f; raydirection.y = -5.0f; raydirection.z = -6.0f; 390 rayposition.x = 5.0f; rayposition.y = 5.0f; rayposition.z = 11.0f; 391 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection); 392 ok(result == TRUE, "expected TRUE, received FALSE\n"); 393 394 raydirection.x = 4.0f; raydirection.y = 5.0f; raydirection.z = 6.0f; 395 rayposition.x = 5.0f; rayposition.y = 5.0f; rayposition.z = 11.0f; 396 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection); 397 ok(result == FALSE, "expected FALSE, received TRUE\n"); 398 399 rayposition.x = -4.0f; rayposition.y = 1.0f; rayposition.z = -2.0f; 400 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection); 401 ok(result == TRUE, "expected TRUE, received FALSE\n"); 402 403 bottom_point.x = 1.0f; bottom_point.y = 0.0f; bottom_point.z = 0.0f; 404 top_point.x = 1.0f; top_point.y = 0.0f; top_point.z = 0.0f; 405 rayposition.x = 0.0f; rayposition.y = 1.0f; rayposition.z = 0.0f; 406 raydirection.x = 0.0f; raydirection.y = 3.0f; raydirection.z = 0.0f; 407 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection); 408 ok(result == FALSE, "expected FALSE, received TRUE\n"); 409 410 bottom_point.x = 1.0f; bottom_point.y = 2.0f; bottom_point.z = 3.0f; 411 top_point.x = 10.0f; top_point.y = 15.0f; top_point.z = 20.0f; 412 413 raydirection.x = 7.0f; raydirection.y = 8.0f; raydirection.z = 9.0f; 414 rayposition.x = 3.0f; rayposition.y = 7.0f; rayposition.z = -6.0f; 415 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection); 416 ok(result == TRUE, "expected TRUE, received FALSE\n"); 417 418 bottom_point.x = 0.0f; bottom_point.y = 0.0f; bottom_point.z = 0.0f; 419 top_point.x = 1.0f; top_point.y = 1.0f; top_point.z = 1.0f; 420 421 raydirection.x = 0.0f; raydirection.y = 1.0f; raydirection.z = .0f; 422 rayposition.x = -3.0f; rayposition.y = 0.0f; rayposition.z = 0.0f; 423 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection); 424 ok(result == FALSE, "expected FALSE, received TRUE\n"); 425 426 raydirection.x = 1.0f; raydirection.y = 0.0f; raydirection.z = .0f; 427 rayposition.x = -3.0f; rayposition.y = 0.0f; rayposition.z = 0.0f; 428 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection); 429 ok(result == TRUE, "expected TRUE, received FALSE\n"); 430 431 /*____________Test the Sphere case________________________*/ 432 radius = sqrt(77.0f); 433 center.x = 1.0f; center.y = 2.0f; center.z = 3.0f; 434 raydirection.x = 2.0f; raydirection.y = -4.0f; raydirection.z = 2.0f; 435 436 rayposition.x = 5.0f; rayposition.y = 5.0f; rayposition.z = 9.0f; 437 result = D3DXSphereBoundProbe(¢er, radius, &rayposition, &raydirection); 438 ok(result == TRUE, "expected TRUE, received FALSE\n"); 439 440 rayposition.x = 45.0f; rayposition.y = -75.0f; rayposition.z = 49.0f; 441 result = D3DXSphereBoundProbe(¢er, radius, &rayposition, &raydirection); 442 ok(result == FALSE, "expected FALSE, received TRUE\n"); 443 444 rayposition.x = 5.0f; rayposition.y = 11.0f; rayposition.z = 9.0f; 445 result = D3DXSphereBoundProbe(¢er, radius, &rayposition, &raydirection); 446 ok(result == FALSE, "expected FALSE, received TRUE\n"); 447 } 448 449 static void D3DXComputeBoundingBoxTest(void) 450 { 451 D3DXVECTOR3 exp_max, exp_min, got_max, got_min, vertex[5]; 452 HRESULT hr; 453 454 vertex[0].x = 1.0f; vertex[0].y = 1.0f; vertex[0].z = 1.0f; 455 vertex[1].x = 1.0f; vertex[1].y = 1.0f; vertex[1].z = 1.0f; 456 vertex[2].x = 1.0f; vertex[2].y = 1.0f; vertex[2].z = 1.0f; 457 vertex[3].x = 1.0f; vertex[3].y = 1.0f; vertex[3].z = 1.0f; 458 vertex[4].x = 9.0f; vertex[4].y = 9.0f; vertex[4].z = 9.0f; 459 460 exp_min.x = 1.0f; exp_min.y = 1.0f; exp_min.z = 1.0f; 461 exp_max.x = 9.0f; exp_max.y = 9.0f; exp_max.z = 9.0f; 462 463 hr = D3DXComputeBoundingBox(&vertex[3],2,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_min,&got_max); 464 465 ok( hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 466 ok( compare_vec3(exp_min,got_min), "Expected min: (%f, %f, %f), got: (%f, %f, %f)\n", exp_min.x,exp_min.y,exp_min.z,got_min.x,got_min.y,got_min.z); 467 ok( compare_vec3(exp_max,got_max), "Expected max: (%f, %f, %f), got: (%f, %f, %f)\n", exp_max.x,exp_max.y,exp_max.z,got_max.x,got_max.y,got_max.z); 468 469 /*________________________*/ 470 471 vertex[0].x = 2.0f; vertex[0].y = 5.9f; vertex[0].z = -1.2f; 472 vertex[1].x = -1.87f; vertex[1].y = 7.9f; vertex[1].z = 7.4f; 473 vertex[2].x = 7.43f; vertex[2].y = -0.9f; vertex[2].z = 11.9f; 474 vertex[3].x = -6.92f; vertex[3].y = 6.3f; vertex[3].z = -3.8f; 475 vertex[4].x = 11.4f; vertex[4].y = -8.1f; vertex[4].z = 4.5f; 476 477 exp_min.x = -6.92f; exp_min.y = -8.1f; exp_min.z = -3.80f; 478 exp_max.x = 11.4f; exp_max.y = 7.90f; exp_max.z = 11.9f; 479 480 hr = D3DXComputeBoundingBox(&vertex[0],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_min,&got_max); 481 482 ok( hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 483 ok( compare_vec3(exp_min,got_min), "Expected min: (%f, %f, %f), got: (%f, %f, %f)\n", exp_min.x,exp_min.y,exp_min.z,got_min.x,got_min.y,got_min.z); 484 ok( compare_vec3(exp_max,got_max), "Expected max: (%f, %f, %f), got: (%f, %f, %f)\n", exp_max.x,exp_max.y,exp_max.z,got_max.x,got_max.y,got_max.z); 485 486 /*________________________*/ 487 488 vertex[0].x = 2.0f; vertex[0].y = 5.9f; vertex[0].z = -1.2f; 489 vertex[1].x = -1.87f; vertex[1].y = 7.9f; vertex[1].z = 7.4f; 490 vertex[2].x = 7.43f; vertex[2].y = -0.9f; vertex[2].z = 11.9f; 491 vertex[3].x = -6.92f; vertex[3].y = 6.3f; vertex[3].z = -3.8f; 492 vertex[4].x = 11.4f; vertex[4].y = -8.1f; vertex[4].z = 4.5f; 493 494 exp_min.x = -6.92f; exp_min.y = -0.9f; exp_min.z = -3.8f; 495 exp_max.x = 7.43f; exp_max.y = 7.90f; exp_max.z = 11.9f; 496 497 hr = D3DXComputeBoundingBox(&vertex[0],4,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_min,&got_max); 498 499 ok( hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 500 ok( compare_vec3(exp_min,got_min), "Expected min: (%f, %f, %f), got: (%f, %f, %f)\n", exp_min.x,exp_min.y,exp_min.z,got_min.x,got_min.y,got_min.z); 501 ok( compare_vec3(exp_max,got_max), "Expected max: (%f, %f, %f), got: (%f, %f, %f)\n", exp_max.x,exp_max.y,exp_max.z,got_max.x,got_max.y,got_max.z); 502 503 /*________________________*/ 504 hr = D3DXComputeBoundingBox(NULL,5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_min,&got_max); 505 ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 506 507 /*________________________*/ 508 hr = D3DXComputeBoundingBox(&vertex[3],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),NULL,&got_max); 509 ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 510 511 /*________________________*/ 512 hr = D3DXComputeBoundingBox(&vertex[3],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_min,NULL); 513 ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 514 } 515 516 static void D3DXComputeBoundingSphereTest(void) 517 { 518 D3DXVECTOR3 exp_cen, got_cen, vertex[5]; 519 FLOAT exp_rad, got_rad; 520 HRESULT hr; 521 522 vertex[0].x = 1.0f; vertex[0].y = 1.0f; vertex[0].z = 1.0f; 523 vertex[1].x = 1.0f; vertex[1].y = 1.0f; vertex[1].z = 1.0f; 524 vertex[2].x = 1.0f; vertex[2].y = 1.0f; vertex[2].z = 1.0f; 525 vertex[3].x = 1.0f; vertex[3].y = 1.0f; vertex[3].z = 1.0f; 526 vertex[4].x = 9.0f; vertex[4].y = 9.0f; vertex[4].z = 9.0f; 527 528 exp_rad = 6.928203f; 529 exp_cen.x = 5.0; exp_cen.y = 5.0; exp_cen.z = 5.0; 530 531 hr = D3DXComputeBoundingSphere(&vertex[3],2,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_cen,&got_rad); 532 533 ok( hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 534 ok( compare(exp_rad, got_rad), "Expected radius: %f, got radius: %f\n", exp_rad, got_rad); 535 ok( compare_vec3(exp_cen,got_cen), "Expected center: (%f, %f, %f), got center: (%f, %f, %f)\n", exp_cen.x,exp_cen.y,exp_cen.z,got_cen.x,got_cen.y,got_cen.z); 536 537 /*________________________*/ 538 539 vertex[0].x = 2.0f; vertex[0].y = 5.9f; vertex[0].z = -1.2f; 540 vertex[1].x = -1.87f; vertex[1].y = 7.9f; vertex[1].z = 7.4f; 541 vertex[2].x = 7.43f; vertex[2].y = -0.9f; vertex[2].z = 11.9f; 542 vertex[3].x = -6.92f; vertex[3].y = 6.3f; vertex[3].z = -3.8f; 543 vertex[4].x = 11.4f; vertex[4].y = -8.1f; vertex[4].z = 4.5f; 544 545 exp_rad = 13.707883f; 546 exp_cen.x = 2.408f; exp_cen.y = 2.22f; exp_cen.z = 3.76f; 547 548 hr = D3DXComputeBoundingSphere(&vertex[0],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_cen,&got_rad); 549 550 ok( hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 551 ok( compare(exp_rad, got_rad), "Expected radius: %f, got radius: %f\n", exp_rad, got_rad); 552 ok( compare_vec3(exp_cen,got_cen), "Expected center: (%f, %f, %f), got center: (%f, %f, %f)\n", exp_cen.x,exp_cen.y,exp_cen.z,got_cen.x,got_cen.y,got_cen.z); 553 554 /*________________________*/ 555 hr = D3DXComputeBoundingSphere(NULL,5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_cen,&got_rad); 556 ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 557 558 /*________________________*/ 559 hr = D3DXComputeBoundingSphere(&vertex[3],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),NULL,&got_rad); 560 ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 561 562 /*________________________*/ 563 hr = D3DXComputeBoundingSphere(&vertex[3],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_cen,NULL); 564 ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 565 } 566 567 static void print_elements(const D3DVERTEXELEMENT9 *elements) 568 { 569 D3DVERTEXELEMENT9 last = D3DDECL_END(); 570 const D3DVERTEXELEMENT9 *ptr = elements; 571 int count = 0; 572 573 while (memcmp(ptr, &last, sizeof(D3DVERTEXELEMENT9))) 574 { 575 trace( 576 "[Element %d] Stream = %d, Offset = %d, Type = %d, Method = %d, Usage = %d, UsageIndex = %d\n", 577 count, ptr->Stream, ptr->Offset, ptr->Type, ptr->Method, ptr->Usage, ptr->UsageIndex); 578 ptr++; 579 count++; 580 } 581 } 582 583 static void compare_elements(const D3DVERTEXELEMENT9 *elements, const D3DVERTEXELEMENT9 *expected_elements, 584 unsigned int line, unsigned int test_id) 585 { 586 D3DVERTEXELEMENT9 last = D3DDECL_END(); 587 unsigned int i; 588 589 for (i = 0; i < MAX_FVF_DECL_SIZE; i++) 590 { 591 int end1 = memcmp(&elements[i], &last, sizeof(last)); 592 int end2 = memcmp(&expected_elements[i], &last, sizeof(last)); 593 int status; 594 595 if (!end1 && !end2) break; 596 597 status = !end1 ^ !end2; 598 ok(!status, "Line %u, test %u: Mismatch in size, test declaration is %s than expected.\n", 599 line, test_id, end1 ? "shorter" : "longer"); 600 if (status) 601 { 602 print_elements(elements); 603 break; 604 } 605 606 status = memcmp(&elements[i], &expected_elements[i], sizeof(D3DVERTEXELEMENT9)); 607 ok(!status, "Line %u, test %u: Mismatch in element %u.\n", line, test_id, i); 608 if (status) 609 { 610 print_elements(elements); 611 break; 612 } 613 } 614 } 615 616 static void test_fvf_to_decl(DWORD test_fvf, const D3DVERTEXELEMENT9 expected_elements[], 617 HRESULT expected_hr, unsigned int line, unsigned int test_id) 618 { 619 HRESULT hr; 620 D3DVERTEXELEMENT9 decl[MAX_FVF_DECL_SIZE]; 621 622 hr = D3DXDeclaratorFromFVF(test_fvf, decl); 623 ok(hr == expected_hr, 624 "Line %u, test %u: D3DXDeclaratorFromFVF returned %#x, expected %#x.\n", 625 line, test_id, hr, expected_hr); 626 if (SUCCEEDED(hr)) compare_elements(decl, expected_elements, line, test_id); 627 } 628 629 static void test_decl_to_fvf(const D3DVERTEXELEMENT9 *decl, DWORD expected_fvf, 630 HRESULT expected_hr, unsigned int line, unsigned int test_id) 631 { 632 HRESULT hr; 633 DWORD result_fvf = 0xdeadbeef; 634 635 hr = D3DXFVFFromDeclarator(decl, &result_fvf); 636 ok(hr == expected_hr, 637 "Line %u, test %u: D3DXFVFFromDeclarator returned %#x, expected %#x.\n", 638 line, test_id, hr, expected_hr); 639 if (SUCCEEDED(hr)) 640 { 641 ok(expected_fvf == result_fvf, "Line %u, test %u: Got FVF %#x, expected %#x.\n", 642 line, test_id, result_fvf, expected_fvf); 643 } 644 } 645 646 static void test_fvf_decl_conversion(void) 647 { 648 static const struct 649 { 650 D3DVERTEXELEMENT9 decl[MAXD3DDECLLENGTH + 1]; 651 DWORD fvf; 652 } 653 test_data[] = 654 { 655 {{ 656 D3DDECL_END(), 657 }, 0}, 658 {{ 659 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 660 D3DDECL_END(), 661 }, D3DFVF_XYZ}, 662 {{ 663 {0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITIONT, 0}, 664 D3DDECL_END(), 665 }, D3DFVF_XYZRHW}, 666 {{ 667 {0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITIONT, 0}, 668 D3DDECL_END(), 669 }, D3DFVF_XYZRHW}, 670 {{ 671 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 672 {0, 12, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, 673 D3DDECL_END(), 674 }, D3DFVF_XYZB1}, 675 {{ 676 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 677 {0, 12, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0}, 678 D3DDECL_END(), 679 }, D3DFVF_XYZB1 | D3DFVF_LASTBETA_UBYTE4}, 680 {{ 681 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 682 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0}, 683 D3DDECL_END(), 684 }, D3DFVF_XYZB1 | D3DFVF_LASTBETA_D3DCOLOR}, 685 {{ 686 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 687 {0, 12, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, 688 D3DDECL_END(), 689 }, D3DFVF_XYZB2}, 690 {{ 691 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 692 {0, 12, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, 693 {0, 16, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0}, 694 D3DDECL_END(), 695 }, D3DFVF_XYZB2 | D3DFVF_LASTBETA_UBYTE4}, 696 {{ 697 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 698 {0, 12, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, 699 {0, 16, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0}, 700 D3DDECL_END(), 701 }, D3DFVF_XYZB2 | D3DFVF_LASTBETA_D3DCOLOR}, 702 {{ 703 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 704 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, 705 D3DDECL_END(), 706 }, D3DFVF_XYZB3}, 707 {{ 708 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 709 {0, 12, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, 710 {0, 20, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0}, 711 D3DDECL_END(), 712 }, D3DFVF_XYZB3 | D3DFVF_LASTBETA_UBYTE4}, 713 {{ 714 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 715 {0, 12, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, 716 {0, 20, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0}, 717 D3DDECL_END(), 718 }, D3DFVF_XYZB3 | D3DFVF_LASTBETA_D3DCOLOR}, 719 {{ 720 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 721 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, 722 D3DDECL_END(), 723 }, D3DFVF_XYZB4}, 724 {{ 725 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 726 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, 727 {0, 24, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0}, 728 D3DDECL_END(), 729 }, D3DFVF_XYZB4 | D3DFVF_LASTBETA_UBYTE4}, 730 {{ 731 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 732 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, 733 {0, 24, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0}, 734 D3DDECL_END(), 735 }, D3DFVF_XYZB4 | D3DFVF_LASTBETA_D3DCOLOR}, 736 {{ 737 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 738 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, 739 {0, 28, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0}, 740 D3DDECL_END(), 741 }, D3DFVF_XYZB5 | D3DFVF_LASTBETA_UBYTE4}, 742 {{ 743 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 744 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, 745 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0}, 746 D3DDECL_END(), 747 }, D3DFVF_XYZB5 | D3DFVF_LASTBETA_D3DCOLOR}, 748 {{ 749 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0}, 750 D3DDECL_END(), 751 }, D3DFVF_NORMAL}, 752 {{ 753 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0}, 754 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0}, 755 D3DDECL_END(), 756 }, D3DFVF_NORMAL | D3DFVF_DIFFUSE}, 757 {{ 758 {0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_PSIZE, 0}, 759 D3DDECL_END(), 760 }, D3DFVF_PSIZE}, 761 {{ 762 {0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0}, 763 D3DDECL_END(), 764 }, D3DFVF_DIFFUSE}, 765 {{ 766 {0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1}, 767 D3DDECL_END(), 768 }, D3DFVF_SPECULAR}, 769 /* Make sure textures of different sizes work. */ 770 {{ 771 {0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0}, 772 D3DDECL_END(), 773 }, D3DFVF_TEXCOORDSIZE1(0) | D3DFVF_TEX1}, 774 {{ 775 {0, 0, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 0}, 776 D3DDECL_END(), 777 }, D3DFVF_TEXCOORDSIZE2(0) | D3DFVF_TEX1}, 778 {{ 779 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 0}, 780 D3DDECL_END(), 781 }, D3DFVF_TEXCOORDSIZE3(0) | D3DFVF_TEX1}, 782 {{ 783 {0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 0}, 784 D3DDECL_END(), 785 }, D3DFVF_TEXCOORDSIZE4(0) | D3DFVF_TEX1}, 786 /* Make sure the TEXCOORD index works correctly - try several textures. */ 787 {{ 788 {0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0}, 789 {0, 4, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 1}, 790 {0, 16, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 2}, 791 {0, 24, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 3}, 792 D3DDECL_END(), 793 }, D3DFVF_TEX4 | D3DFVF_TEXCOORDSIZE1(0) | D3DFVF_TEXCOORDSIZE3(1) 794 | D3DFVF_TEXCOORDSIZE2(2) | D3DFVF_TEXCOORDSIZE4(3)}, 795 /* Now try some combination tests. */ 796 {{ 797 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 798 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, 799 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0}, 800 {0, 32, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1}, 801 {0, 36, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 0}, 802 {0, 44, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 1}, 803 D3DDECL_END(), 804 }, D3DFVF_XYZB4 | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_TEX2 805 | D3DFVF_TEXCOORDSIZE2(0) | D3DFVF_TEXCOORDSIZE3(1)}, 806 {{ 807 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 808 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0}, 809 {0, 24, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_PSIZE, 0}, 810 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1}, 811 {0, 32, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0}, 812 {0, 36, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 1}, 813 D3DDECL_END(), 814 }, D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_PSIZE | D3DFVF_SPECULAR | D3DFVF_TEX2 815 | D3DFVF_TEXCOORDSIZE1(0) | D3DFVF_TEXCOORDSIZE4(1)}, 816 }; 817 unsigned int i; 818 819 for (i = 0; i < ARRAY_SIZE(test_data); ++i) 820 { 821 test_decl_to_fvf(test_data[i].decl, test_data[i].fvf, D3D_OK, __LINE__, i); 822 test_fvf_to_decl(test_data[i].fvf, test_data[i].decl, D3D_OK, __LINE__, i); 823 } 824 825 /* Usage indices for position and normal are apparently ignored. */ 826 { 827 const D3DVERTEXELEMENT9 decl[] = 828 { 829 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 1}, 830 D3DDECL_END(), 831 }; 832 test_decl_to_fvf(decl, D3DFVF_XYZ, D3D_OK, __LINE__, 0); 833 } 834 { 835 const D3DVERTEXELEMENT9 decl[] = 836 { 837 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 1}, 838 D3DDECL_END(), 839 }; 840 test_decl_to_fvf(decl, D3DFVF_NORMAL, D3D_OK, __LINE__, 0); 841 } 842 /* D3DFVF_LASTBETA_UBYTE4 and D3DFVF_LASTBETA_D3DCOLOR are ignored if 843 * there are no blend matrices. */ 844 { 845 const D3DVERTEXELEMENT9 decl[] = 846 { 847 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 848 D3DDECL_END(), 849 }; 850 test_fvf_to_decl(D3DFVF_XYZ | D3DFVF_LASTBETA_UBYTE4, decl, D3D_OK, __LINE__, 0); 851 } 852 { 853 const D3DVERTEXELEMENT9 decl[] = 854 { 855 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 856 D3DDECL_END(), 857 }; 858 test_fvf_to_decl(D3DFVF_XYZ | D3DFVF_LASTBETA_D3DCOLOR, decl, D3D_OK, __LINE__, 0); 859 } 860 /* D3DFVF_LASTBETA_UBYTE4 takes precedence over D3DFVF_LASTBETA_D3DCOLOR. */ 861 { 862 const D3DVERTEXELEMENT9 decl[] = 863 { 864 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 865 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, 866 {0, 28, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0}, 867 D3DDECL_END(), 868 }; 869 test_fvf_to_decl(D3DFVF_XYZB5 | D3DFVF_LASTBETA_D3DCOLOR | D3DFVF_LASTBETA_UBYTE4, 870 decl, D3D_OK, __LINE__, 0); 871 } 872 /* These are supposed to fail, both ways. */ 873 { 874 const D3DVERTEXELEMENT9 decl[] = 875 { 876 {0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITION, 0}, 877 D3DDECL_END(), 878 }; 879 test_decl_to_fvf(decl, D3DFVF_XYZW, D3DERR_INVALIDCALL, __LINE__, 0); 880 test_fvf_to_decl(D3DFVF_XYZW, decl, D3DERR_INVALIDCALL, __LINE__, 0); 881 } 882 { 883 const D3DVERTEXELEMENT9 decl[] = 884 { 885 {0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITION, 0}, 886 {0, 16, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0}, 887 D3DDECL_END(), 888 }; 889 test_decl_to_fvf(decl, D3DFVF_XYZW | D3DFVF_NORMAL, D3DERR_INVALIDCALL, __LINE__, 0); 890 test_fvf_to_decl(D3DFVF_XYZW | D3DFVF_NORMAL, decl, D3DERR_INVALIDCALL, __LINE__, 0); 891 } 892 { 893 const D3DVERTEXELEMENT9 decl[] = 894 { 895 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 896 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, 897 {0, 28, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDINDICES, 0}, 898 D3DDECL_END(), 899 }; 900 test_decl_to_fvf(decl, D3DFVF_XYZB5, D3DERR_INVALIDCALL, __LINE__, 0); 901 test_fvf_to_decl(D3DFVF_XYZB5, decl, D3DERR_INVALIDCALL, __LINE__, 0); 902 } 903 /* Test a declaration that can't be converted to an FVF. */ 904 { 905 const D3DVERTEXELEMENT9 decl[] = 906 { 907 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 908 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0}, 909 {0, 24, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_PSIZE, 0}, 910 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1}, 911 {0, 32, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0}, 912 /* 8 bytes padding */ 913 {0, 44, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 1}, 914 D3DDECL_END(), 915 }; 916 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0); 917 } 918 /* Elements must be ordered by offset. */ 919 { 920 const D3DVERTEXELEMENT9 decl[] = 921 { 922 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0}, 923 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 924 D3DDECL_END(), 925 }; 926 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0); 927 } 928 /* Basic tests for element order. */ 929 { 930 const D3DVERTEXELEMENT9 decl[] = 931 { 932 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 933 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0}, 934 {0, 16, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0}, 935 D3DDECL_END(), 936 }; 937 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0); 938 } 939 { 940 const D3DVERTEXELEMENT9 decl[] = 941 { 942 {0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0}, 943 {0, 4, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 944 D3DDECL_END(), 945 }; 946 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0); 947 } 948 { 949 const D3DVERTEXELEMENT9 decl[] = 950 { 951 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0}, 952 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 953 D3DDECL_END(), 954 }; 955 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0); 956 } 957 /* Textures must be ordered by texcoords. */ 958 { 959 const D3DVERTEXELEMENT9 decl[] = 960 { 961 {0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0}, 962 {0, 4, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 2}, 963 {0, 16, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 1}, 964 {0, 24, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 3}, 965 D3DDECL_END(), 966 }; 967 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0); 968 } 969 /* Duplicate elements are not allowed. */ 970 { 971 const D3DVERTEXELEMENT9 decl[] = 972 { 973 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 974 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0}, 975 {0, 16, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0}, 976 D3DDECL_END(), 977 }; 978 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0); 979 } 980 /* Invalid FVFs cannot be converted to a declarator. */ 981 test_fvf_to_decl(0xdeadbeef, NULL, D3DERR_INVALIDCALL, __LINE__, 0); 982 } 983 984 static void D3DXGetFVFVertexSizeTest(void) 985 { 986 UINT got; 987 988 compare_vertex_sizes (D3DFVF_XYZ, 12); 989 990 compare_vertex_sizes (D3DFVF_XYZB3, 24); 991 992 compare_vertex_sizes (D3DFVF_XYZB5, 32); 993 994 compare_vertex_sizes (D3DFVF_XYZ | D3DFVF_NORMAL, 24); 995 996 compare_vertex_sizes (D3DFVF_XYZ | D3DFVF_DIFFUSE, 16); 997 998 compare_vertex_sizes ( 999 D3DFVF_XYZ | 1000 D3DFVF_TEX1 | 1001 D3DFVF_TEXCOORDSIZE1(0), 16); 1002 compare_vertex_sizes ( 1003 D3DFVF_XYZ | 1004 D3DFVF_TEX2 | 1005 D3DFVF_TEXCOORDSIZE1(0) | 1006 D3DFVF_TEXCOORDSIZE1(1), 20); 1007 1008 compare_vertex_sizes ( 1009 D3DFVF_XYZ | 1010 D3DFVF_TEX1 | 1011 D3DFVF_TEXCOORDSIZE2(0), 20); 1012 1013 compare_vertex_sizes ( 1014 D3DFVF_XYZ | 1015 D3DFVF_TEX2 | 1016 D3DFVF_TEXCOORDSIZE2(0) | 1017 D3DFVF_TEXCOORDSIZE2(1), 28); 1018 1019 compare_vertex_sizes ( 1020 D3DFVF_XYZ | 1021 D3DFVF_TEX6 | 1022 D3DFVF_TEXCOORDSIZE2(0) | 1023 D3DFVF_TEXCOORDSIZE2(1) | 1024 D3DFVF_TEXCOORDSIZE2(2) | 1025 D3DFVF_TEXCOORDSIZE2(3) | 1026 D3DFVF_TEXCOORDSIZE2(4) | 1027 D3DFVF_TEXCOORDSIZE2(5), 60); 1028 1029 compare_vertex_sizes ( 1030 D3DFVF_XYZ | 1031 D3DFVF_TEX8 | 1032 D3DFVF_TEXCOORDSIZE2(0) | 1033 D3DFVF_TEXCOORDSIZE2(1) | 1034 D3DFVF_TEXCOORDSIZE2(2) | 1035 D3DFVF_TEXCOORDSIZE2(3) | 1036 D3DFVF_TEXCOORDSIZE2(4) | 1037 D3DFVF_TEXCOORDSIZE2(5) | 1038 D3DFVF_TEXCOORDSIZE2(6) | 1039 D3DFVF_TEXCOORDSIZE2(7), 76); 1040 1041 compare_vertex_sizes ( 1042 D3DFVF_XYZ | 1043 D3DFVF_TEX1 | 1044 D3DFVF_TEXCOORDSIZE3(0), 24); 1045 1046 compare_vertex_sizes ( 1047 D3DFVF_XYZ | 1048 D3DFVF_TEX4 | 1049 D3DFVF_TEXCOORDSIZE3(0) | 1050 D3DFVF_TEXCOORDSIZE3(1) | 1051 D3DFVF_TEXCOORDSIZE3(2) | 1052 D3DFVF_TEXCOORDSIZE3(3), 60); 1053 1054 compare_vertex_sizes ( 1055 D3DFVF_XYZ | 1056 D3DFVF_TEX1 | 1057 D3DFVF_TEXCOORDSIZE4(0), 28); 1058 1059 compare_vertex_sizes ( 1060 D3DFVF_XYZ | 1061 D3DFVF_TEX2 | 1062 D3DFVF_TEXCOORDSIZE4(0) | 1063 D3DFVF_TEXCOORDSIZE4(1), 44); 1064 1065 compare_vertex_sizes ( 1066 D3DFVF_XYZ | 1067 D3DFVF_TEX3 | 1068 D3DFVF_TEXCOORDSIZE4(0) | 1069 D3DFVF_TEXCOORDSIZE4(1) | 1070 D3DFVF_TEXCOORDSIZE4(2), 60); 1071 1072 compare_vertex_sizes ( 1073 D3DFVF_XYZB5 | 1074 D3DFVF_NORMAL | 1075 D3DFVF_DIFFUSE | 1076 D3DFVF_SPECULAR | 1077 D3DFVF_TEX8 | 1078 D3DFVF_TEXCOORDSIZE4(0) | 1079 D3DFVF_TEXCOORDSIZE4(1) | 1080 D3DFVF_TEXCOORDSIZE4(2) | 1081 D3DFVF_TEXCOORDSIZE4(3) | 1082 D3DFVF_TEXCOORDSIZE4(4) | 1083 D3DFVF_TEXCOORDSIZE4(5) | 1084 D3DFVF_TEXCOORDSIZE4(6) | 1085 D3DFVF_TEXCOORDSIZE4(7), 180); 1086 } 1087 1088 static void D3DXIntersectTriTest(void) 1089 { 1090 BOOL exp_res, got_res; 1091 D3DXVECTOR3 position, ray, vertex[3]; 1092 FLOAT exp_dist, got_dist, exp_u, got_u, exp_v, got_v; 1093 1094 vertex[0].x = 1.0f; vertex[0].y = 0.0f; vertex[0].z = 0.0f; 1095 vertex[1].x = 2.0f; vertex[1].y = 0.0f; vertex[1].z = 0.0f; 1096 vertex[2].x = 1.0f; vertex[2].y = 1.0f; vertex[2].z = 0.0f; 1097 1098 position.x = -14.5f; position.y = -23.75f; position.z = -32.0f; 1099 1100 ray.x = 2.0f; ray.y = 3.0f; ray.z = 4.0f; 1101 1102 exp_res = TRUE; exp_u = 0.5f; exp_v = 0.25f; exp_dist = 8.0f; 1103 1104 got_res = D3DXIntersectTri(&vertex[0], &vertex[1], &vertex[2], &position, &ray, &got_u, &got_v, &got_dist); 1105 ok(got_res == exp_res, "Expected result %d, got %d.\n", exp_res, got_res); 1106 ok(compare(exp_u, got_u), "Expected u %f, got %f.\n", exp_u, got_u); 1107 ok(compare(exp_v, got_v), "Expected v %f, got %f.\n", exp_v, got_v); 1108 ok(compare(exp_dist, got_dist), "Expected distance %f, got %f.\n", exp_dist, got_dist); 1109 1110 got_res = D3DXIntersectTri(&vertex[0], &vertex[1], &vertex[2], &position, &ray, NULL, NULL, NULL); 1111 ok(got_res == exp_res, "Expected result %d, got %d.\n", exp_res, got_res); 1112 1113 vertex[2].x = 1.0f; vertex[2].y = 0.0f; vertex[2].z = 0.0f; 1114 vertex[1].x = 2.0f; vertex[1].y = 0.0f; vertex[1].z = 0.0f; 1115 vertex[0].x = 1.0f; vertex[0].y = 1.0f; vertex[0].z = 0.0f; 1116 1117 got_u = got_v = got_dist = 0.0f; 1118 got_res = D3DXIntersectTri(&vertex[0], &vertex[1], &vertex[2], &position, &ray, &got_u, &got_v, &got_dist); 1119 ok(got_res == exp_res, "Expected result %d, got %d.\n", exp_res, got_res); 1120 ok(compare(exp_u, got_u), "Expected u %f, got %f.\n", exp_u, got_u); 1121 ok(compare(exp_v, got_v), "Expected v %f, got %f.\n", exp_v, got_v); 1122 ok(compare(exp_dist, got_dist), "Expected distance %f, got %f.\n", exp_dist, got_dist); 1123 1124 vertex[2].x = 1.0f; vertex[2].y = 0.0f; vertex[2].z = 0.0f; 1125 vertex[1].x = 2.0f; vertex[1].y = 0.0f; vertex[1].z = -0.5f; 1126 vertex[0].x = 1.0f; vertex[0].y = 1.0f; vertex[0].z = -1.0f; 1127 exp_u = 0.375f; 1128 exp_v = 0.5625f; 1129 exp_dist = 7.9375f; 1130 got_u = got_v = got_dist = 0.0f; 1131 got_res = D3DXIntersectTri(&vertex[0], &vertex[1], &vertex[2], &position, &ray, &got_u, &got_v, &got_dist); 1132 ok(got_res == exp_res, "Expected result %d, got %d.\n", exp_res, got_res); 1133 ok(compare(exp_u, got_u), "Expected u %f, got %f.\n", exp_u, got_u); 1134 ok(compare(exp_v, got_v), "Expected v %f, got %f.\n", exp_v, got_v); 1135 ok(compare(exp_dist, got_dist), "Expected distance %f, got %f.\n", exp_dist, got_dist); 1136 1137 1138 /*Only positive ray is taken in account*/ 1139 1140 vertex[0].x = 1.0f; vertex[0].y = 0.0f; vertex[0].z = 0.0f; 1141 vertex[1].x = 2.0f; vertex[1].y = 0.0f; vertex[1].z = 0.0f; 1142 vertex[2].x = 1.0f; vertex[2].y = 1.0f; vertex[2].z = 0.0f; 1143 1144 position.x = 17.5f; position.y = 24.25f; position.z = 32.0f; 1145 1146 ray.x = 2.0f; ray.y = 3.0f; ray.z = 4.0f; 1147 1148 exp_res = FALSE; 1149 1150 got_res = D3DXIntersectTri(&vertex[0],&vertex[1],&vertex[2],&position,&ray,&got_u,&got_v,&got_dist); 1151 ok( got_res == exp_res, "Expected result = %d, got %d\n",exp_res,got_res); 1152 1153 got_res = D3DXIntersectTri(&vertex[0], &vertex[1], &vertex[2], &position, &ray, NULL, NULL, NULL); 1154 ok(got_res == exp_res, "Expected result = %d, got %d\n", exp_res, got_res); 1155 1156 /*Intersection between ray and triangle in a same plane is considered as empty*/ 1157 1158 vertex[0].x = 4.0f; vertex[0].y = 0.0f; vertex[0].z = 0.0f; 1159 vertex[1].x = 6.0f; vertex[1].y = 0.0f; vertex[1].z = 0.0f; 1160 vertex[2].x = 4.0f; vertex[2].y = 2.0f; vertex[2].z = 0.0f; 1161 1162 position.x = 1.0f; position.y = 1.0f; position.z = 0.0f; 1163 1164 ray.x = 1.0f; ray.y = 0.0f; ray.z = 0.0f; 1165 1166 exp_res = FALSE; 1167 1168 got_res = D3DXIntersectTri(&vertex[0],&vertex[1],&vertex[2],&position,&ray,&got_u,&got_v,&got_dist); 1169 ok( got_res == exp_res, "Expected result = %d, got %d\n",exp_res,got_res); 1170 1171 got_res = D3DXIntersectTri(&vertex[0], &vertex[1], &vertex[2], &position, &ray, NULL, NULL, NULL); 1172 ok(got_res == exp_res, "Expected result = %d, got %d\n", exp_res, got_res); 1173 } 1174 1175 static void D3DXCreateMeshTest(void) 1176 { 1177 HRESULT hr; 1178 IDirect3DDevice9 *device, *test_device; 1179 ID3DXMesh *d3dxmesh; 1180 int i, size; 1181 D3DVERTEXELEMENT9 test_decl[MAX_FVF_DECL_SIZE]; 1182 DWORD options; 1183 struct mesh mesh; 1184 struct test_context *test_context; 1185 1186 static const D3DVERTEXELEMENT9 decl1[] = 1187 { 1188 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 1189 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 1190 D3DDECL_END(), 1191 }; 1192 1193 static const D3DVERTEXELEMENT9 decl2[] = 1194 { 1195 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 1196 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 1197 {0, 24, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_PSIZE, 0}, 1198 {0, 28, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 1}, 1199 {0, 32, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 1200 /* 8 bytes padding */ 1201 {0, 44, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1}, 1202 D3DDECL_END(), 1203 }; 1204 1205 static const D3DVERTEXELEMENT9 decl3[] = 1206 { 1207 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 1208 {1, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 1209 D3DDECL_END(), 1210 }; 1211 1212 hr = D3DXCreateMesh(0, 0, 0, NULL, NULL, NULL); 1213 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 1214 1215 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl1, NULL, &d3dxmesh); 1216 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 1217 1218 test_context = new_test_context(); 1219 if (!test_context) 1220 { 1221 skip("Couldn't create test context\n"); 1222 return; 1223 } 1224 device = test_context->device; 1225 1226 hr = D3DXCreateMesh(0, 3, D3DXMESH_MANAGED, decl1, device, &d3dxmesh); 1227 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 1228 1229 hr = D3DXCreateMesh(1, 0, D3DXMESH_MANAGED, decl1, device, &d3dxmesh); 1230 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 1231 1232 hr = D3DXCreateMesh(1, 3, 0, decl1, device, &d3dxmesh); 1233 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK); 1234 1235 if (hr == D3D_OK) 1236 { 1237 d3dxmesh->lpVtbl->Release(d3dxmesh); 1238 } 1239 1240 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, 0, device, &d3dxmesh); 1241 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 1242 1243 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl1, device, NULL); 1244 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 1245 1246 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl1, device, &d3dxmesh); 1247 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); 1248 1249 if (hr == D3D_OK) 1250 { 1251 /* device */ 1252 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, NULL); 1253 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 1254 1255 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, &test_device); 1256 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK); 1257 ok(test_device == device, "Got result %p, expected %p\n", test_device, device); 1258 1259 if (hr == D3D_OK) 1260 { 1261 IDirect3DDevice9_Release(device); 1262 } 1263 1264 /* declaration */ 1265 hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, NULL); 1266 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 1267 1268 hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, test_decl); 1269 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); 1270 1271 if (hr == D3D_OK) 1272 { 1273 size = ARRAY_SIZE(decl1); 1274 for (i = 0; i < size - 1; i++) 1275 { 1276 ok(test_decl[i].Stream == decl1[i].Stream, "Returned stream %d, expected %d\n", test_decl[i].Stream, decl1[i].Stream); 1277 ok(test_decl[i].Type == decl1[i].Type, "Returned type %d, expected %d\n", test_decl[i].Type, decl1[i].Type); 1278 ok(test_decl[i].Method == decl1[i].Method, "Returned method %d, expected %d\n", test_decl[i].Method, decl1[i].Method); 1279 ok(test_decl[i].Usage == decl1[i].Usage, "Returned usage %d, expected %d\n", test_decl[i].Usage, decl1[i].Usage); 1280 ok(test_decl[i].UsageIndex == decl1[i].UsageIndex, "Returned usage index %d, expected %d\n", test_decl[i].UsageIndex, decl1[i].UsageIndex); 1281 ok(test_decl[i].Offset == decl1[i].Offset, "Returned offset %d, expected %d\n", test_decl[i].Offset, decl1[i].Offset); 1282 } 1283 ok(decl1[size-1].Stream == 0xFF, "Returned too long vertex declaration\n"); /* end element */ 1284 } 1285 1286 /* options */ 1287 options = d3dxmesh->lpVtbl->GetOptions(d3dxmesh); 1288 ok(options == D3DXMESH_MANAGED, "Got result %x, expected %x (D3DXMESH_MANAGED)\n", options, D3DXMESH_MANAGED); 1289 1290 /* rest */ 1291 if (!new_mesh(&mesh, 3, 1)) 1292 { 1293 skip("Couldn't create mesh\n"); 1294 } 1295 else 1296 { 1297 memset(mesh.vertices, 0, mesh.number_of_vertices * sizeof(*mesh.vertices)); 1298 memset(mesh.faces, 0, mesh.number_of_faces * sizeof(*mesh.faces)); 1299 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL; 1300 1301 compare_mesh("createmesh1", d3dxmesh, &mesh); 1302 1303 free_mesh(&mesh); 1304 } 1305 1306 d3dxmesh->lpVtbl->Release(d3dxmesh); 1307 } 1308 1309 /* Test a declaration that can't be converted to an FVF. */ 1310 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl2, device, &d3dxmesh); 1311 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); 1312 1313 if (hr == D3D_OK) 1314 { 1315 /* device */ 1316 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, NULL); 1317 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 1318 1319 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, &test_device); 1320 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK); 1321 ok(test_device == device, "Got result %p, expected %p\n", test_device, device); 1322 1323 if (hr == D3D_OK) 1324 { 1325 IDirect3DDevice9_Release(device); 1326 } 1327 1328 /* declaration */ 1329 hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, test_decl); 1330 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); 1331 1332 if (hr == D3D_OK) 1333 { 1334 size = ARRAY_SIZE(decl2); 1335 for (i = 0; i < size - 1; i++) 1336 { 1337 ok(test_decl[i].Stream == decl2[i].Stream, "Returned stream %d, expected %d\n", test_decl[i].Stream, decl2[i].Stream); 1338 ok(test_decl[i].Type == decl2[i].Type, "Returned type %d, expected %d\n", test_decl[i].Type, decl2[i].Type); 1339 ok(test_decl[i].Method == decl2[i].Method, "Returned method %d, expected %d\n", test_decl[i].Method, decl2[i].Method); 1340 ok(test_decl[i].Usage == decl2[i].Usage, "Returned usage %d, expected %d\n", test_decl[i].Usage, decl2[i].Usage); 1341 ok(test_decl[i].UsageIndex == decl2[i].UsageIndex, "Returned usage index %d, expected %d\n", test_decl[i].UsageIndex, decl2[i].UsageIndex); 1342 ok(test_decl[i].Offset == decl2[i].Offset, "Returned offset %d, expected %d\n", test_decl[i].Offset, decl2[i].Offset); 1343 } 1344 ok(decl2[size-1].Stream == 0xFF, "Returned too long vertex declaration\n"); /* end element */ 1345 } 1346 1347 /* options */ 1348 options = d3dxmesh->lpVtbl->GetOptions(d3dxmesh); 1349 ok(options == D3DXMESH_MANAGED, "Got result %x, expected %x (D3DXMESH_MANAGED)\n", options, D3DXMESH_MANAGED); 1350 1351 /* rest */ 1352 if (!new_mesh(&mesh, 3, 1)) 1353 { 1354 skip("Couldn't create mesh\n"); 1355 } 1356 else 1357 { 1358 memset(mesh.vertices, 0, mesh.number_of_vertices * sizeof(*mesh.vertices)); 1359 memset(mesh.faces, 0, mesh.number_of_faces * sizeof(*mesh.faces)); 1360 mesh.fvf = 0; 1361 mesh.vertex_size = 60; 1362 1363 compare_mesh("createmesh2", d3dxmesh, &mesh); 1364 1365 free_mesh(&mesh); 1366 } 1367 1368 mesh.vertex_size = d3dxmesh->lpVtbl->GetNumBytesPerVertex(d3dxmesh); 1369 ok(mesh.vertex_size == 60, "Got vertex size %u, expected %u\n", mesh.vertex_size, 60); 1370 1371 d3dxmesh->lpVtbl->Release(d3dxmesh); 1372 } 1373 1374 /* Test a declaration with multiple streams. */ 1375 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl3, device, &d3dxmesh); 1376 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 1377 1378 free_test_context(test_context); 1379 } 1380 1381 static void D3DXCreateMeshFVFTest(void) 1382 { 1383 HRESULT hr; 1384 IDirect3DDevice9 *device, *test_device; 1385 ID3DXMesh *d3dxmesh; 1386 int i, size; 1387 D3DVERTEXELEMENT9 test_decl[MAX_FVF_DECL_SIZE]; 1388 DWORD options; 1389 struct mesh mesh; 1390 struct test_context *test_context; 1391 1392 static const D3DVERTEXELEMENT9 decl[] = 1393 { 1394 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 1395 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 1396 D3DDECL_END(), 1397 }; 1398 1399 hr = D3DXCreateMeshFVF(0, 0, 0, 0, NULL, NULL); 1400 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 1401 1402 hr = D3DXCreateMeshFVF(1, 3, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, NULL, &d3dxmesh); 1403 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 1404 1405 test_context = new_test_context(); 1406 if (!test_context) 1407 { 1408 skip("Couldn't create test context\n"); 1409 return; 1410 } 1411 device = test_context->device; 1412 1413 hr = D3DXCreateMeshFVF(0, 3, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, device, &d3dxmesh); 1414 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 1415 1416 hr = D3DXCreateMeshFVF(1, 0, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, device, &d3dxmesh); 1417 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 1418 1419 hr = D3DXCreateMeshFVF(1, 3, 0, D3DFVF_XYZ | D3DFVF_NORMAL, device, &d3dxmesh); 1420 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK); 1421 1422 if (hr == D3D_OK) 1423 { 1424 d3dxmesh->lpVtbl->Release(d3dxmesh); 1425 } 1426 1427 hr = D3DXCreateMeshFVF(1, 3, D3DXMESH_MANAGED, 0xdeadbeef, device, &d3dxmesh); 1428 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 1429 1430 hr = D3DXCreateMeshFVF(1, 3, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, device, NULL); 1431 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 1432 1433 hr = D3DXCreateMeshFVF(1, 3, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, device, &d3dxmesh); 1434 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); 1435 1436 if (hr == D3D_OK) 1437 { 1438 /* device */ 1439 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, NULL); 1440 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 1441 1442 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, &test_device); 1443 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK); 1444 ok(test_device == device, "Got result %p, expected %p\n", test_device, device); 1445 1446 if (hr == D3D_OK) 1447 { 1448 IDirect3DDevice9_Release(device); 1449 } 1450 1451 /* declaration */ 1452 hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, NULL); 1453 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 1454 1455 hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, test_decl); 1456 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); 1457 1458 if (hr == D3D_OK) 1459 { 1460 size = ARRAY_SIZE(decl); 1461 for (i = 0; i < size - 1; i++) 1462 { 1463 ok(test_decl[i].Stream == decl[i].Stream, "Returned stream %d, expected %d\n", test_decl[i].Stream, decl[i].Stream); 1464 ok(test_decl[i].Type == decl[i].Type, "Returned type %d, expected %d\n", test_decl[i].Type, decl[i].Type); 1465 ok(test_decl[i].Method == decl[i].Method, "Returned method %d, expected %d\n", test_decl[i].Method, decl[i].Method); 1466 ok(test_decl[i].Usage == decl[i].Usage, "Returned usage %d, expected %d\n", test_decl[i].Usage, decl[i].Usage); 1467 ok(test_decl[i].UsageIndex == decl[i].UsageIndex, "Returned usage index %d, expected %d\n", 1468 test_decl[i].UsageIndex, decl[i].UsageIndex); 1469 ok(test_decl[i].Offset == decl[i].Offset, "Returned offset %d, expected %d\n", test_decl[i].Offset, decl[i].Offset); 1470 } 1471 ok(decl[size-1].Stream == 0xFF, "Returned too long vertex declaration\n"); /* end element */ 1472 } 1473 1474 /* options */ 1475 options = d3dxmesh->lpVtbl->GetOptions(d3dxmesh); 1476 ok(options == D3DXMESH_MANAGED, "Got result %x, expected %x (D3DXMESH_MANAGED)\n", options, D3DXMESH_MANAGED); 1477 1478 /* rest */ 1479 if (!new_mesh(&mesh, 3, 1)) 1480 { 1481 skip("Couldn't create mesh\n"); 1482 } 1483 else 1484 { 1485 memset(mesh.vertices, 0, mesh.number_of_vertices * sizeof(*mesh.vertices)); 1486 memset(mesh.faces, 0, mesh.number_of_faces * sizeof(*mesh.faces)); 1487 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL; 1488 1489 compare_mesh("createmeshfvf", d3dxmesh, &mesh); 1490 1491 free_mesh(&mesh); 1492 } 1493 1494 d3dxmesh->lpVtbl->Release(d3dxmesh); 1495 } 1496 1497 free_test_context(test_context); 1498 } 1499 1500 #define check_vertex_buffer(mesh, vertices, num_vertices, fvf) \ 1501 check_vertex_buffer_(__LINE__, mesh, vertices, num_vertices, fvf) 1502 static void check_vertex_buffer_(int line, ID3DXMesh *mesh, const void *vertices, DWORD num_vertices, DWORD fvf) 1503 { 1504 DWORD mesh_num_vertices = mesh->lpVtbl->GetNumVertices(mesh); 1505 DWORD mesh_fvf = mesh->lpVtbl->GetFVF(mesh); 1506 const void *mesh_vertices; 1507 HRESULT hr; 1508 1509 ok_(__FILE__,line)(fvf == mesh_fvf, "expected FVF %x, got %x\n", fvf, mesh_fvf); 1510 ok_(__FILE__,line)(num_vertices == mesh_num_vertices, 1511 "Expected %u vertices, got %u\n", num_vertices, mesh_num_vertices); 1512 1513 hr = mesh->lpVtbl->LockVertexBuffer(mesh, D3DLOCK_READONLY, (void**)&mesh_vertices); 1514 ok_(__FILE__,line)(hr == D3D_OK, "LockVertexBuffer returned %x, expected %x (D3D_OK)\n", hr, D3D_OK); 1515 if (FAILED(hr)) 1516 return; 1517 1518 if (mesh_fvf == fvf) { 1519 DWORD vertex_size = D3DXGetFVFVertexSize(fvf), i; 1520 1521 for (i = 0; i < min(num_vertices, mesh_num_vertices); i++) 1522 { 1523 const FLOAT *exp_float = vertices; 1524 const FLOAT *got_float = mesh_vertices; 1525 DWORD texcount; 1526 DWORD pos_dim = 0; 1527 int j; 1528 BOOL last_beta_dword = FALSE; 1529 char prefix[128]; 1530 1531 switch (fvf & D3DFVF_POSITION_MASK) { 1532 case D3DFVF_XYZ: pos_dim = 3; break; 1533 case D3DFVF_XYZRHW: pos_dim = 4; break; 1534 case D3DFVF_XYZB1: 1535 case D3DFVF_XYZB2: 1536 case D3DFVF_XYZB3: 1537 case D3DFVF_XYZB4: 1538 case D3DFVF_XYZB5: 1539 pos_dim = (fvf & D3DFVF_POSITION_MASK) - D3DFVF_XYZB1 + 1; 1540 if (fvf & (D3DFVF_LASTBETA_UBYTE4 | D3DFVF_LASTBETA_D3DCOLOR)) 1541 { 1542 pos_dim--; 1543 last_beta_dword = TRUE; 1544 } 1545 break; 1546 case D3DFVF_XYZW: pos_dim = 4; break; 1547 } 1548 sprintf(prefix, "vertex[%u] position, ", i); 1549 check_floats_(line, prefix, got_float, exp_float, pos_dim); 1550 exp_float += pos_dim; 1551 got_float += pos_dim; 1552 1553 if (last_beta_dword) { 1554 ok_(__FILE__,line)(*(DWORD*)exp_float == *(DWORD*)got_float, 1555 "Vertex[%u]: Expected last beta %08x, got %08x\n", i, *(DWORD*)exp_float, *(DWORD*)got_float); 1556 exp_float++; 1557 got_float++; 1558 } 1559 1560 if (fvf & D3DFVF_NORMAL) { 1561 sprintf(prefix, "vertex[%u] normal, ", i); 1562 check_floats_(line, prefix, got_float, exp_float, 3); 1563 exp_float += 3; 1564 got_float += 3; 1565 } 1566 if (fvf & D3DFVF_PSIZE) { 1567 ok_(__FILE__,line)(compare(*exp_float, *got_float), 1568 "Vertex[%u]: Expected psize %g, got %g\n", i, *exp_float, *got_float); 1569 exp_float++; 1570 got_float++; 1571 } 1572 if (fvf & D3DFVF_DIFFUSE) { 1573 ok_(__FILE__,line)(*(DWORD*)exp_float == *(DWORD*)got_float, 1574 "Vertex[%u]: Expected diffuse %08x, got %08x\n", i, *(DWORD*)exp_float, *(DWORD*)got_float); 1575 exp_float++; 1576 got_float++; 1577 } 1578 if (fvf & D3DFVF_SPECULAR) { 1579 ok_(__FILE__,line)(*(DWORD*)exp_float == *(DWORD*)got_float, 1580 "Vertex[%u]: Expected specular %08x, got %08x\n", i, *(DWORD*)exp_float, *(DWORD*)got_float); 1581 exp_float++; 1582 got_float++; 1583 } 1584 1585 texcount = (fvf & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT; 1586 for (j = 0; j < texcount; j++) { 1587 DWORD dim = (((fvf >> (16 + 2 * j)) + 1) & 0x03) + 1; 1588 sprintf(prefix, "vertex[%u] texture, ", i); 1589 check_floats_(line, prefix, got_float, exp_float, dim); 1590 exp_float += dim; 1591 got_float += dim; 1592 } 1593 1594 vertices = (BYTE*)vertices + vertex_size; 1595 mesh_vertices = (BYTE*)mesh_vertices + vertex_size; 1596 } 1597 } 1598 1599 mesh->lpVtbl->UnlockVertexBuffer(mesh); 1600 } 1601 1602 #define check_index_buffer(mesh, indices, num_indices, index_size) \ 1603 check_index_buffer_(__LINE__, mesh, indices, num_indices, index_size) 1604 static void check_index_buffer_(int line, ID3DXMesh *mesh, const void *indices, DWORD num_indices, DWORD index_size) 1605 { 1606 DWORD mesh_index_size = (mesh->lpVtbl->GetOptions(mesh) & D3DXMESH_32BIT) ? 4 : 2; 1607 DWORD mesh_num_indices = mesh->lpVtbl->GetNumFaces(mesh) * 3; 1608 const void *mesh_indices; 1609 HRESULT hr; 1610 DWORD i; 1611 1612 ok_(__FILE__,line)(index_size == mesh_index_size, 1613 "Expected index size %u, got %u\n", index_size, mesh_index_size); 1614 ok_(__FILE__,line)(num_indices == mesh_num_indices, 1615 "Expected %u indices, got %u\n", num_indices, mesh_num_indices); 1616 1617 hr = mesh->lpVtbl->LockIndexBuffer(mesh, D3DLOCK_READONLY, (void**)&mesh_indices); 1618 ok_(__FILE__,line)(hr == D3D_OK, "LockIndexBuffer returned %x, expected %x (D3D_OK)\n", hr, D3D_OK); 1619 if (FAILED(hr)) 1620 return; 1621 1622 if (mesh_index_size == index_size) { 1623 for (i = 0; i < min(num_indices, mesh_num_indices); i++) 1624 { 1625 if (index_size == 4) 1626 ok_(__FILE__,line)(*(DWORD*)indices == *(DWORD*)mesh_indices, 1627 "Index[%u]: expected %u, got %u\n", i, *(DWORD*)indices, *(DWORD*)mesh_indices); 1628 else 1629 ok_(__FILE__,line)(*(WORD*)indices == *(WORD*)mesh_indices, 1630 "Index[%u]: expected %u, got %u\n", i, *(WORD*)indices, *(WORD*)mesh_indices); 1631 indices = (BYTE*)indices + index_size; 1632 mesh_indices = (BYTE*)mesh_indices + index_size; 1633 } 1634 } 1635 mesh->lpVtbl->UnlockIndexBuffer(mesh); 1636 } 1637 1638 #define check_matrix(got, expected) check_matrix_(__LINE__, got, expected) 1639 static void check_matrix_(int line, const D3DXMATRIX *got, const D3DXMATRIX *expected) 1640 { 1641 int i, j; 1642 for (i = 0; i < 4; i++) { 1643 for (j = 0; j < 4; j++) { 1644 ok_(__FILE__,line)(compare(U(*expected).m[i][j], U(*got).m[i][j]), 1645 "matrix[%u][%u]: expected %g, got %g\n", 1646 i, j, U(*expected).m[i][j], U(*got).m[i][j]); 1647 } 1648 } 1649 } 1650 1651 static void check_colorvalue_(int line, const char *prefix, const D3DCOLORVALUE got, const D3DCOLORVALUE expected) 1652 { 1653 ok_(__FILE__,line)(expected.r == got.r && expected.g == got.g && expected.b == got.b && expected.a == got.a, 1654 "%sExpected (%g, %g, %g, %g), got (%g, %g, %g, %g)\n", prefix, 1655 expected.r, expected.g, expected.b, expected.a, got.r, got.g, got.b, got.a); 1656 } 1657 1658 #define check_materials(got, got_count, expected, expected_count) \ 1659 check_materials_(__LINE__, got, got_count, expected, expected_count) 1660 static void check_materials_(int line, const D3DXMATERIAL *got, DWORD got_count, const D3DXMATERIAL *expected, DWORD expected_count) 1661 { 1662 int i; 1663 ok_(__FILE__,line)(expected_count == got_count, "Expected %u materials, got %u\n", expected_count, got_count); 1664 if (!expected) { 1665 ok_(__FILE__,line)(got == NULL, "Expected NULL material ptr, got %p\n", got); 1666 return; 1667 } 1668 for (i = 0; i < min(expected_count, got_count); i++) 1669 { 1670 if (!expected[i].pTextureFilename) 1671 ok_(__FILE__,line)(got[i].pTextureFilename == NULL, 1672 "Expected NULL pTextureFilename, got %p\n", got[i].pTextureFilename); 1673 else 1674 ok_(__FILE__,line)(!strcmp(expected[i].pTextureFilename, got[i].pTextureFilename), 1675 "Expected '%s' for pTextureFilename, got '%s'\n", expected[i].pTextureFilename, got[i].pTextureFilename); 1676 check_colorvalue_(line, "Diffuse: ", got[i].MatD3D.Diffuse, expected[i].MatD3D.Diffuse); 1677 check_colorvalue_(line, "Ambient: ", got[i].MatD3D.Ambient, expected[i].MatD3D.Ambient); 1678 check_colorvalue_(line, "Specular: ", got[i].MatD3D.Specular, expected[i].MatD3D.Specular); 1679 check_colorvalue_(line, "Emissive: ", got[i].MatD3D.Emissive, expected[i].MatD3D.Emissive); 1680 ok_(__FILE__,line)(expected[i].MatD3D.Power == got[i].MatD3D.Power, 1681 "Power: Expected %g, got %g\n", expected[i].MatD3D.Power, got[i].MatD3D.Power); 1682 } 1683 } 1684 1685 #define check_generated_adjacency(mesh, got, epsilon) check_generated_adjacency_(__LINE__, mesh, got, epsilon) 1686 static void check_generated_adjacency_(int line, ID3DXMesh *mesh, const DWORD *got, FLOAT epsilon) 1687 { 1688 DWORD *expected; 1689 DWORD num_faces = mesh->lpVtbl->GetNumFaces(mesh); 1690 HRESULT hr; 1691 1692 expected = HeapAlloc(GetProcessHeap(), 0, num_faces * sizeof(DWORD) * 3); 1693 if (!expected) { 1694 skip_(__FILE__, line)("Out of memory\n"); 1695 return; 1696 } 1697 hr = mesh->lpVtbl->GenerateAdjacency(mesh, epsilon, expected); 1698 ok_(__FILE__, line)(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 1699 if (SUCCEEDED(hr)) 1700 { 1701 int i; 1702 for (i = 0; i < num_faces; i++) 1703 { 1704 ok_(__FILE__, line)(expected[i * 3] == got[i * 3] && 1705 expected[i * 3 + 1] == got[i * 3 + 1] && 1706 expected[i * 3 + 2] == got[i * 3 + 2], 1707 "Face %u adjacencies: Expected (%u, %u, %u), got (%u, %u, %u)\n", i, 1708 expected[i * 3], expected[i * 3 + 1], expected[i * 3 + 2], 1709 got[i * 3], got[i * 3 + 1], got[i * 3 + 2]); 1710 } 1711 } 1712 HeapFree(GetProcessHeap(), 0, expected); 1713 } 1714 1715 #define check_generated_effects(materials, num_materials, effects) \ 1716 check_generated_effects_(__LINE__, materials, num_materials, effects) 1717 static void check_generated_effects_(int line, const D3DXMATERIAL *materials, DWORD num_materials, const D3DXEFFECTINSTANCE *effects) 1718 { 1719 int i; 1720 static const struct { 1721 const char *name; 1722 DWORD name_size; 1723 DWORD num_bytes; 1724 DWORD value_offset; 1725 } params[] = { 1726 #define EFFECT_TABLE_ENTRY(str, field) \ 1727 {str, sizeof(str), sizeof(materials->MatD3D.field), offsetof(D3DXMATERIAL, MatD3D.field)} 1728 EFFECT_TABLE_ENTRY("Diffuse", Diffuse), 1729 EFFECT_TABLE_ENTRY("Power", Power), 1730 EFFECT_TABLE_ENTRY("Specular", Specular), 1731 EFFECT_TABLE_ENTRY("Emissive", Emissive), 1732 EFFECT_TABLE_ENTRY("Ambient", Ambient), 1733 #undef EFFECT_TABLE_ENTRY 1734 }; 1735 1736 if (!num_materials) { 1737 ok_(__FILE__, line)(effects == NULL, "Expected NULL effects, got %p\n", effects); 1738 return; 1739 } 1740 for (i = 0; i < num_materials; i++) 1741 { 1742 int j; 1743 DWORD expected_num_defaults = ARRAY_SIZE(params) + (materials[i].pTextureFilename ? 1 : 0); 1744 1745 ok_(__FILE__,line)(expected_num_defaults == effects[i].NumDefaults, 1746 "effect[%u] NumDefaults: Expected %u, got %u\n", i, 1747 expected_num_defaults, effects[i].NumDefaults); 1748 for (j = 0; j < min(ARRAY_SIZE(params), effects[i].NumDefaults); j++) 1749 { 1750 int k; 1751 D3DXEFFECTDEFAULT *got_param = &effects[i].pDefaults[j]; 1752 ok_(__FILE__,line)(!strcmp(params[j].name, got_param->pParamName), 1753 "effect[%u].pDefaults[%u].pParamName: Expected '%s', got '%s'\n", i, j, 1754 params[j].name, got_param->pParamName); 1755 ok_(__FILE__,line)(D3DXEDT_FLOATS == got_param->Type, 1756 "effect[%u].pDefaults[%u].Type: Expected %u, got %u\n", i, j, 1757 D3DXEDT_FLOATS, got_param->Type); 1758 ok_(__FILE__,line)(params[j].num_bytes == got_param->NumBytes, 1759 "effect[%u].pDefaults[%u].NumBytes: Expected %u, got %u\n", i, j, 1760 params[j].num_bytes, got_param->NumBytes); 1761 for (k = 0; k < min(params[j].num_bytes, got_param->NumBytes) / 4; k++) 1762 { 1763 FLOAT expected = ((FLOAT*)((BYTE*)&materials[i] + params[j].value_offset))[k]; 1764 FLOAT got = ((FLOAT*)got_param->pValue)[k]; 1765 ok_(__FILE__,line)(compare(expected, got), 1766 "effect[%u].pDefaults[%u] float value %u: Expected %g, got %g\n", i, j, k, expected, got); 1767 } 1768 } 1769 if (effects[i].NumDefaults > ARRAY_SIZE(params)) { 1770 D3DXEFFECTDEFAULT *got_param = &effects[i].pDefaults[j]; 1771 static const char *expected_name = "Texture0@Name"; 1772 1773 ok_(__FILE__,line)(!strcmp(expected_name, got_param->pParamName), 1774 "effect[%u].pDefaults[%u].pParamName: Expected '%s', got '%s'\n", i, j, 1775 expected_name, got_param->pParamName); 1776 ok_(__FILE__,line)(D3DXEDT_STRING == got_param->Type, 1777 "effect[%u].pDefaults[%u].Type: Expected %u, got %u\n", i, j, 1778 D3DXEDT_STRING, got_param->Type); 1779 if (materials[i].pTextureFilename) { 1780 ok_(__FILE__,line)(strlen(materials[i].pTextureFilename) + 1 == got_param->NumBytes, 1781 "effect[%u] texture filename length: Expected %u, got %u\n", i, 1782 (DWORD)strlen(materials[i].pTextureFilename) + 1, got_param->NumBytes); 1783 ok_(__FILE__,line)(!strcmp(materials[i].pTextureFilename, got_param->pValue), 1784 "effect[%u] texture filename: Expected '%s', got '%s'\n", i, 1785 materials[i].pTextureFilename, (char*)got_param->pValue); 1786 } 1787 } 1788 } 1789 } 1790 1791 static char *strdupA(const char *p) 1792 { 1793 char *ret; 1794 if (!p) return NULL; 1795 ret = HeapAlloc(GetProcessHeap(), 0, strlen(p) + 1); 1796 if (ret) strcpy(ret, p); 1797 return ret; 1798 } 1799 1800 static HRESULT CALLBACK ID3DXAllocateHierarchyImpl_DestroyFrame(ID3DXAllocateHierarchy *iface, LPD3DXFRAME frame) 1801 { 1802 TRACECALLBACK("ID3DXAllocateHierarchyImpl_DestroyFrame(%p, %p)\n", iface, frame); 1803 if (frame) { 1804 HeapFree(GetProcessHeap(), 0, frame->Name); 1805 HeapFree(GetProcessHeap(), 0, frame); 1806 } 1807 return D3D_OK; 1808 } 1809 1810 static HRESULT CALLBACK ID3DXAllocateHierarchyImpl_CreateFrame(ID3DXAllocateHierarchy *iface, 1811 const char *name, D3DXFRAME **new_frame) 1812 { 1813 D3DXFRAME *frame; 1814 1815 TRACECALLBACK("ID3DXAllocateHierarchyImpl_CreateFrame(%p, '%s', %p)\n", iface, name, new_frame); 1816 frame = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*frame)); 1817 if (!frame) 1818 return E_OUTOFMEMORY; 1819 if (name) { 1820 frame->Name = strdupA(name); 1821 if (!frame->Name) { 1822 HeapFree(GetProcessHeap(), 0, frame); 1823 return E_OUTOFMEMORY; 1824 } 1825 } 1826 *new_frame = frame; 1827 return D3D_OK; 1828 } 1829 1830 static HRESULT destroy_mesh_container(LPD3DXMESHCONTAINER mesh_container) 1831 { 1832 int i; 1833 1834 if (!mesh_container) 1835 return D3D_OK; 1836 HeapFree(GetProcessHeap(), 0, mesh_container->Name); 1837 if (U(mesh_container->MeshData).pMesh) 1838 IUnknown_Release(U(mesh_container->MeshData).pMesh); 1839 if (mesh_container->pMaterials) { 1840 for (i = 0; i < mesh_container->NumMaterials; i++) 1841 HeapFree(GetProcessHeap(), 0, mesh_container->pMaterials[i].pTextureFilename); 1842 HeapFree(GetProcessHeap(), 0, mesh_container->pMaterials); 1843 } 1844 if (mesh_container->pEffects) { 1845 for (i = 0; i < mesh_container->NumMaterials; i++) { 1846 HeapFree(GetProcessHeap(), 0, mesh_container->pEffects[i].pEffectFilename); 1847 if (mesh_container->pEffects[i].pDefaults) { 1848 int j; 1849 for (j = 0; j < mesh_container->pEffects[i].NumDefaults; j++) { 1850 HeapFree(GetProcessHeap(), 0, mesh_container->pEffects[i].pDefaults[j].pParamName); 1851 HeapFree(GetProcessHeap(), 0, mesh_container->pEffects[i].pDefaults[j].pValue); 1852 } 1853 HeapFree(GetProcessHeap(), 0, mesh_container->pEffects[i].pDefaults); 1854 } 1855 } 1856 HeapFree(GetProcessHeap(), 0, mesh_container->pEffects); 1857 } 1858 HeapFree(GetProcessHeap(), 0, mesh_container->pAdjacency); 1859 if (mesh_container->pSkinInfo) 1860 IUnknown_Release(mesh_container->pSkinInfo); 1861 HeapFree(GetProcessHeap(), 0, mesh_container); 1862 return D3D_OK; 1863 } 1864 1865 static HRESULT CALLBACK ID3DXAllocateHierarchyImpl_DestroyMeshContainer(ID3DXAllocateHierarchy *iface, LPD3DXMESHCONTAINER mesh_container) 1866 { 1867 TRACECALLBACK("ID3DXAllocateHierarchyImpl_DestroyMeshContainer(%p, %p)\n", iface, mesh_container); 1868 return destroy_mesh_container(mesh_container); 1869 } 1870 1871 static HRESULT CALLBACK ID3DXAllocateHierarchyImpl_CreateMeshContainer(ID3DXAllocateHierarchy *iface, 1872 const char *name, const D3DXMESHDATA *mesh_data, const D3DXMATERIAL *materials, 1873 const D3DXEFFECTINSTANCE *effects, DWORD num_materials, const DWORD *adjacency, 1874 ID3DXSkinInfo *skin_info, D3DXMESHCONTAINER **new_mesh_container) 1875 { 1876 LPD3DXMESHCONTAINER mesh_container = NULL; 1877 int i; 1878 1879 TRACECALLBACK("ID3DXAllocateHierarchyImpl_CreateMeshContainer(%p, '%s', %u, %p, %p, %p, %d, %p, %p, %p)\n", 1880 iface, name, mesh_data->Type, U(*mesh_data).pMesh, materials, effects, 1881 num_materials, adjacency, skin_info, *new_mesh_container); 1882 1883 mesh_container = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*mesh_container)); 1884 if (!mesh_container) 1885 return E_OUTOFMEMORY; 1886 1887 if (name) { 1888 mesh_container->Name = strdupA(name); 1889 if (!mesh_container->Name) 1890 goto error; 1891 } 1892 1893 mesh_container->NumMaterials = num_materials; 1894 if (num_materials) { 1895 mesh_container->pMaterials = HeapAlloc(GetProcessHeap(), 0, num_materials * sizeof(*materials)); 1896 if (!mesh_container->pMaterials) 1897 goto error; 1898 1899 memcpy(mesh_container->pMaterials, materials, num_materials * sizeof(*materials)); 1900 for (i = 0; i < num_materials; i++) 1901 mesh_container->pMaterials[i].pTextureFilename = NULL; 1902 for (i = 0; i < num_materials; i++) { 1903 if (materials[i].pTextureFilename) { 1904 mesh_container->pMaterials[i].pTextureFilename = strdupA(materials[i].pTextureFilename); 1905 if (!mesh_container->pMaterials[i].pTextureFilename) 1906 goto error; 1907 } 1908 } 1909 1910 mesh_container->pEffects = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, num_materials * sizeof(*effects)); 1911 if (!mesh_container->pEffects) 1912 goto error; 1913 for (i = 0; i < num_materials; i++) { 1914 int j; 1915 const D3DXEFFECTINSTANCE *effect_src = &effects[i]; 1916 D3DXEFFECTINSTANCE *effect_dest = &mesh_container->pEffects[i]; 1917 1918 if (effect_src->pEffectFilename) { 1919 effect_dest->pEffectFilename = strdupA(effect_src->pEffectFilename); 1920 if (!effect_dest->pEffectFilename) 1921 goto error; 1922 } 1923 effect_dest->pDefaults = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 1924 effect_src->NumDefaults * sizeof(*effect_src->pDefaults)); 1925 if (!effect_dest->pDefaults) 1926 goto error; 1927 effect_dest->NumDefaults = effect_src->NumDefaults; 1928 for (j = 0; j < effect_src->NumDefaults; j++) { 1929 const D3DXEFFECTDEFAULT *default_src = &effect_src->pDefaults[j]; 1930 D3DXEFFECTDEFAULT *default_dest = &effect_dest->pDefaults[j]; 1931 1932 if (default_src->pParamName) { 1933 default_dest->pParamName = strdupA(default_src->pParamName); 1934 if (!default_dest->pParamName) 1935 goto error; 1936 } 1937 default_dest->NumBytes = default_src->NumBytes; 1938 default_dest->Type = default_src->Type; 1939 default_dest->pValue = HeapAlloc(GetProcessHeap(), 0, default_src->NumBytes); 1940 memcpy(default_dest->pValue, default_src->pValue, default_src->NumBytes); 1941 } 1942 } 1943 } 1944 1945 ok(adjacency != NULL, "Expected non-NULL adjacency, got NULL\n"); 1946 if (adjacency) { 1947 if (mesh_data->Type == D3DXMESHTYPE_MESH || mesh_data->Type == D3DXMESHTYPE_PMESH) { 1948 ID3DXBaseMesh *basemesh = (ID3DXBaseMesh*)U(*mesh_data).pMesh; 1949 DWORD num_faces = basemesh->lpVtbl->GetNumFaces(basemesh); 1950 size_t size = num_faces * sizeof(DWORD) * 3; 1951 mesh_container->pAdjacency = HeapAlloc(GetProcessHeap(), 0, size); 1952 if (!mesh_container->pAdjacency) 1953 goto error; 1954 memcpy(mesh_container->pAdjacency, adjacency, size); 1955 } else { 1956 ok(mesh_data->Type == D3DXMESHTYPE_PATCHMESH, "Unknown mesh type %u\n", mesh_data->Type); 1957 if (mesh_data->Type == D3DXMESHTYPE_PATCHMESH) 1958 trace("FIXME: copying adjacency data for patch mesh not implemented\n"); 1959 } 1960 } 1961 1962 memcpy(&mesh_container->MeshData, mesh_data, sizeof(*mesh_data)); 1963 if (U(*mesh_data).pMesh) 1964 IUnknown_AddRef(U(*mesh_data).pMesh); 1965 if (skin_info) { 1966 mesh_container->pSkinInfo = skin_info; 1967 skin_info->lpVtbl->AddRef(skin_info); 1968 } 1969 *new_mesh_container = mesh_container; 1970 1971 return S_OK; 1972 error: 1973 destroy_mesh_container(mesh_container); 1974 return E_OUTOFMEMORY; 1975 } 1976 1977 static ID3DXAllocateHierarchyVtbl ID3DXAllocateHierarchyImpl_Vtbl = { 1978 ID3DXAllocateHierarchyImpl_CreateFrame, 1979 ID3DXAllocateHierarchyImpl_CreateMeshContainer, 1980 ID3DXAllocateHierarchyImpl_DestroyFrame, 1981 ID3DXAllocateHierarchyImpl_DestroyMeshContainer, 1982 }; 1983 static ID3DXAllocateHierarchy alloc_hier = { &ID3DXAllocateHierarchyImpl_Vtbl }; 1984 1985 #define test_LoadMeshFromX(device, xfile_str, vertex_array, fvf, index_array, materials_array, check_adjacency) \ 1986 test_LoadMeshFromX_(__LINE__, device, xfile_str, sizeof(xfile_str) - 1, vertex_array, ARRAY_SIZE(vertex_array), fvf, \ 1987 index_array, ARRAY_SIZE(index_array), sizeof(*index_array), materials_array, ARRAY_SIZE(materials_array), \ 1988 check_adjacency); 1989 static void test_LoadMeshFromX_(int line, IDirect3DDevice9 *device, const char *xfile_str, size_t xfile_strlen, 1990 const void *vertices, DWORD num_vertices, DWORD fvf, const void *indices, DWORD num_indices, size_t index_size, 1991 const D3DXMATERIAL *expected_materials, DWORD expected_num_materials, BOOL check_adjacency) 1992 { 1993 HRESULT hr; 1994 ID3DXBuffer *materials = NULL; 1995 ID3DXBuffer *effects = NULL; 1996 ID3DXBuffer *adjacency = NULL; 1997 ID3DXMesh *mesh = NULL; 1998 DWORD num_materials = 0; 1999 2000 /* Adjacency is not checked when the X file contains multiple meshes, 2001 * since calling GenerateAdjacency on the merged mesh is not equivalent 2002 * to calling GenerateAdjacency on the individual meshes and then merging 2003 * the adjacency data. */ 2004 hr = D3DXLoadMeshFromXInMemory(xfile_str, xfile_strlen, D3DXMESH_MANAGED, device, 2005 check_adjacency ? &adjacency : NULL, &materials, &effects, &num_materials, &mesh); 2006 ok_(__FILE__,line)(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 2007 if (SUCCEEDED(hr)) { 2008 D3DXMATERIAL *materials_ptr = materials ? ID3DXBuffer_GetBufferPointer(materials) : NULL; 2009 D3DXEFFECTINSTANCE *effects_ptr = effects ? ID3DXBuffer_GetBufferPointer(effects) : NULL; 2010 DWORD *adjacency_ptr = check_adjacency ? ID3DXBuffer_GetBufferPointer(adjacency) : NULL; 2011 2012 check_vertex_buffer_(line, mesh, vertices, num_vertices, fvf); 2013 check_index_buffer_(line, mesh, indices, num_indices, index_size); 2014 check_materials_(line, materials_ptr, num_materials, expected_materials, expected_num_materials); 2015 check_generated_effects_(line, materials_ptr, num_materials, effects_ptr); 2016 if (check_adjacency) 2017 check_generated_adjacency_(line, mesh, adjacency_ptr, 0.0f); 2018 2019 if (materials) ID3DXBuffer_Release(materials); 2020 if (effects) ID3DXBuffer_Release(effects); 2021 if (adjacency) ID3DXBuffer_Release(adjacency); 2022 IUnknown_Release(mesh); 2023 } 2024 } 2025 2026 static void D3DXLoadMeshTest(void) 2027 { 2028 static const char empty_xfile[] = "xof 0303txt 0032"; 2029 /*________________________*/ 2030 static const char simple_xfile[] = 2031 "xof 0303txt 0032" 2032 "Mesh {" 2033 "3;" 2034 "0.0; 0.0; 0.0;," 2035 "0.0; 1.0; 0.0;," 2036 "1.0; 1.0; 0.0;;" 2037 "1;" 2038 "3; 0, 1, 2;;" 2039 "}"; 2040 static const WORD simple_index_buffer[] = {0, 1, 2}; 2041 static const D3DXVECTOR3 simple_vertex_buffer[] = { 2042 {0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {1.0, 1.0, 0.0} 2043 }; 2044 const DWORD simple_fvf = D3DFVF_XYZ; 2045 static const char framed_xfile[] = 2046 "xof 0303txt 0032" 2047 "Frame {" 2048 "Mesh { 3; 0.0; 0.0; 0.0;, 0.0; 1.0; 0.0;, 1.0; 1.0; 0.0;; 1; 3; 0, 1, 2;; }" 2049 "FrameTransformMatrix {" /* translation (0.0, 0.0, 2.0) */ 2050 "1.0, 0.0, 0.0, 0.0," 2051 "0.0, 1.0, 0.0, 0.0," 2052 "0.0, 0.0, 1.0, 0.0," 2053 "0.0, 0.0, 2.0, 1.0;;" 2054 "}" 2055 "Mesh { 3; 0.0; 0.0; 0.0;, 0.0; 1.0; 0.0;, 2.0; 1.0; 0.0;; 1; 3; 0, 1, 2;; }" 2056 "FrameTransformMatrix {" /* translation (0.0, 0.0, 3.0) */ 2057 "1.0, 0.0, 0.0, 0.0," 2058 "0.0, 1.0, 0.0, 0.0," 2059 "0.0, 0.0, 1.0, 0.0," 2060 "0.0, 0.0, 3.0, 1.0;;" 2061 "}" 2062 "Mesh { 3; 0.0; 0.0; 0.0;, 0.0; 1.0; 0.0;, 3.0; 1.0; 0.0;; 1; 3; 0, 1, 2;; }" 2063 "}"; 2064 static const WORD framed_index_buffer[] = { 0, 1, 2 }; 2065 static const D3DXVECTOR3 framed_vertex_buffers[3][3] = { 2066 {{0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {1.0, 1.0, 0.0}}, 2067 {{0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {2.0, 1.0, 0.0}}, 2068 {{0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {3.0, 1.0, 0.0}}, 2069 }; 2070 static const WORD merged_index_buffer[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 }; 2071 /* frame transforms accumulates for D3DXLoadMeshFromX */ 2072 static const D3DXVECTOR3 merged_vertex_buffer[] = { 2073 {0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {1.0, 1.0, 0.0}, 2074 {0.0, 0.0, 2.0}, {0.0, 1.0, 2.0}, {2.0, 1.0, 2.0}, 2075 {0.0, 0.0, 5.0}, {0.0, 1.0, 5.0}, {3.0, 1.0, 5.0}, 2076 }; 2077 const DWORD framed_fvf = D3DFVF_XYZ; 2078 /*________________________*/ 2079 static const char box_xfile[] = 2080 "xof 0303txt 0032" 2081 "Mesh {" 2082 "8;" /* DWORD nVertices; */ 2083 /* array Vector vertices[nVertices]; */ 2084 "0.0; 0.0; 0.0;," 2085 "0.0; 0.0; 1.0;," 2086 "0.0; 1.0; 0.0;," 2087 "0.0; 1.0; 1.0;," 2088 "1.0; 0.0; 0.0;," 2089 "1.0; 0.0; 1.0;," 2090 "1.0; 1.0; 0.0;," 2091 "1.0; 1.0; 1.0;;" 2092 "6;" /* DWORD nFaces; */ 2093 /* array MeshFace faces[nFaces]; */ 2094 "4; 0, 1, 3, 2;," /* (left side) */ 2095 "4; 2, 3, 7, 6;," /* (top side) */ 2096 "4; 6, 7, 5, 4;," /* (right side) */ 2097 "4; 1, 0, 4, 5;," /* (bottom side) */ 2098 "4; 1, 5, 7, 3;," /* (back side) */ 2099 "4; 0, 2, 6, 4;;" /* (front side) */ 2100 "MeshNormals {" 2101 "6;" /* DWORD nNormals; */ 2102 /* array Vector normals[nNormals]; */ 2103 "-1.0; 0.0; 0.0;," 2104 "0.0; 1.0; 0.0;," 2105 "1.0; 0.0; 0.0;," 2106 "0.0; -1.0; 0.0;," 2107 "0.0; 0.0; 1.0;," 2108 "0.0; 0.0; -1.0;;" 2109 "6;" /* DWORD nFaceNormals; */ 2110 /* array MeshFace faceNormals[nFaceNormals]; */ 2111 "4; 0, 0, 0, 0;," 2112 "4; 1, 1, 1, 1;," 2113 "4; 2, 2, 2, 2;," 2114 "4; 3, 3, 3, 3;," 2115 "4; 4, 4, 4, 4;," 2116 "4; 5, 5, 5, 5;;" 2117 "}" 2118 "MeshMaterialList materials {" 2119 "2;" /* DWORD nMaterials; */ 2120 "6;" /* DWORD nFaceIndexes; */ 2121 /* array DWORD faceIndexes[nFaceIndexes]; */ 2122 "0, 0, 0, 1, 1, 1;;" 2123 "Material {" 2124 /* ColorRGBA faceColor; */ 2125 "0.0; 0.0; 1.0; 1.0;;" 2126 /* FLOAT power; */ 2127 "0.5;" 2128 /* ColorRGB specularColor; */ 2129 "1.0; 1.0; 1.0;;" 2130 /* ColorRGB emissiveColor; */ 2131 "0.0; 0.0; 0.0;;" 2132 "}" 2133 "Material {" 2134 /* ColorRGBA faceColor; */ 2135 "1.0; 1.0; 1.0; 1.0;;" 2136 /* FLOAT power; */ 2137 "1.0;" 2138 /* ColorRGB specularColor; */ 2139 "1.0; 1.0; 1.0;;" 2140 /* ColorRGB emissiveColor; */ 2141 "0.0; 0.0; 0.0;;" 2142 "TextureFilename { \"texture.jpg\"; }" 2143 "}" 2144 "}" 2145 "MeshVertexColors {" 2146 "8;" /* DWORD nVertexColors; */ 2147 /* array IndexedColor vertexColors[nVertexColors]; */ 2148 "0; 0.0; 0.0; 0.0; 0.0;;" 2149 "1; 0.0; 0.0; 1.0; 0.1;;" 2150 "2; 0.0; 1.0; 0.0; 0.2;;" 2151 "3; 0.0; 1.0; 1.0; 0.3;;" 2152 "4; 1.0; 0.0; 0.0; 0.4;;" 2153 "5; 1.0; 0.0; 1.0; 0.5;;" 2154 "6; 1.0; 1.0; 0.0; 0.6;;" 2155 "7; 1.0; 1.0; 1.0; 0.7;;" 2156 "}" 2157 "MeshTextureCoords {" 2158 "8;" /* DWORD nTextureCoords; */ 2159 /* array Coords2d textureCoords[nTextureCoords]; */ 2160 "0.0; 1.0;," 2161 "1.0; 1.0;," 2162 "0.0; 0.0;," 2163 "1.0; 0.0;," 2164 "1.0; 1.0;," 2165 "0.0; 1.0;," 2166 "1.0; 0.0;," 2167 "0.0; 0.0;;" 2168 "}" 2169 "}"; 2170 static const WORD box_index_buffer[] = { 2171 0, 1, 3, 2172 0, 3, 2, 2173 8, 9, 7, 2174 8, 7, 6, 2175 10, 11, 5, 2176 10, 5, 4, 2177 12, 13, 14, 2178 12, 14, 15, 2179 16, 17, 18, 2180 16, 18, 19, 2181 20, 21, 22, 2182 20, 22, 23, 2183 }; 2184 static const struct { 2185 D3DXVECTOR3 position; 2186 D3DXVECTOR3 normal; 2187 D3DCOLOR diffuse; 2188 D3DXVECTOR2 tex_coords; 2189 } box_vertex_buffer[] = { 2190 {{0.0, 0.0, 0.0}, {-1.0, 0.0, 0.0}, 0x00000000, {0.0, 1.0}}, 2191 {{0.0, 0.0, 1.0}, {-1.0, 0.0, 0.0}, 0x1a0000ff, {1.0, 1.0}}, 2192 {{0.0, 1.0, 0.0}, {-1.0, 0.0, 0.0}, 0x3300ff00, {0.0, 0.0}}, 2193 {{0.0, 1.0, 1.0}, {-1.0, 0.0, 0.0}, 0x4d00ffff, {1.0, 0.0}}, 2194 {{1.0, 0.0, 0.0}, {1.0, 0.0, 0.0}, 0x66ff0000, {1.0, 1.0}}, 2195 {{1.0, 0.0, 1.0}, {1.0, 0.0, 0.0}, 0x80ff00ff, {0.0, 1.0}}, 2196 {{1.0, 1.0, 0.0}, {0.0, 1.0, 0.0}, 0x99ffff00, {1.0, 0.0}}, 2197 {{1.0, 1.0, 1.0}, {0.0, 1.0, 0.0}, 0xb3ffffff, {0.0, 0.0}}, 2198 {{0.0, 1.0, 0.0}, {0.0, 1.0, 0.0}, 0x3300ff00, {0.0, 0.0}}, 2199 {{0.0, 1.0, 1.0}, {0.0, 1.0, 0.0}, 0x4d00ffff, {1.0, 0.0}}, 2200 {{1.0, 1.0, 0.0}, {1.0, 0.0, 0.0}, 0x99ffff00, {1.0, 0.0}}, 2201 {{1.0, 1.0, 1.0}, {1.0, 0.0, 0.0}, 0xb3ffffff, {0.0, 0.0}}, 2202 {{0.0, 0.0, 1.0}, {0.0, -1.0, 0.0}, 0x1a0000ff, {1.0, 1.0}}, 2203 {{0.0, 0.0, 0.0}, {0.0, -1.0, 0.0}, 0x00000000, {0.0, 1.0}}, 2204 {{1.0, 0.0, 0.0}, {0.0, -1.0, 0.0}, 0x66ff0000, {1.0, 1.0}}, 2205 {{1.0, 0.0, 1.0}, {0.0, -1.0, 0.0}, 0x80ff00ff, {0.0, 1.0}}, 2206 {{0.0, 0.0, 1.0}, {0.0, 0.0, 1.0}, 0x1a0000ff, {1.0, 1.0}}, 2207 {{1.0, 0.0, 1.0}, {0.0, 0.0, 1.0}, 0x80ff00ff, {0.0, 1.0}}, 2208 {{1.0, 1.0, 1.0}, {0.0, 0.0, 1.0}, 0xb3ffffff, {0.0, 0.0}}, 2209 {{0.0, 1.0, 1.0}, {0.0, 0.0, 1.0}, 0x4d00ffff, {1.0, 0.0}}, 2210 {{0.0, 0.0, 0.0}, {0.0, 0.0, -1.0}, 0x00000000, {0.0, 1.0}}, 2211 {{0.0, 1.0, 0.0}, {0.0, 0.0, -1.0}, 0x3300ff00, {0.0, 0.0}}, 2212 {{1.0, 1.0, 0.0}, {0.0, 0.0, -1.0}, 0x99ffff00, {1.0, 0.0}}, 2213 {{1.0, 0.0, 0.0}, {0.0, 0.0, -1.0}, 0x66ff0000, {1.0, 1.0}}, 2214 }; 2215 static const D3DXMATERIAL box_materials[] = { 2216 { 2217 { 2218 {0.0, 0.0, 1.0, 1.0}, /* Diffuse */ 2219 {0.0, 0.0, 0.0, 1.0}, /* Ambient */ 2220 {1.0, 1.0, 1.0, 1.0}, /* Specular */ 2221 {0.0, 0.0, 0.0, 1.0}, /* Emissive */ 2222 0.5, /* Power */ 2223 }, 2224 NULL, /* pTextureFilename */ 2225 }, 2226 { 2227 { 2228 {1.0, 1.0, 1.0, 1.0}, /* Diffuse */ 2229 {0.0, 0.0, 0.0, 1.0}, /* Ambient */ 2230 {1.0, 1.0, 1.0, 1.0}, /* Specular */ 2231 {0.0, 0.0, 0.0, 1.0}, /* Emissive */ 2232 1.0, /* Power */ 2233 }, 2234 (char *)"texture.jpg", /* pTextureFilename */ 2235 }, 2236 }; 2237 static const char box_anim_xfile[] = 2238 "xof 0303txt 0032" 2239 "Mesh CubeMesh {" 2240 "8;" /* DWORD nVertices; */ 2241 /* array Vector vertices[nVertices]; */ 2242 "0.0; 0.0; 0.0;," 2243 "0.0; 0.0; 1.0;," 2244 "0.0; 1.0; 0.0;," 2245 "0.0; 1.0; 1.0;," 2246 "1.0; 0.0; 0.0;," 2247 "1.0; 0.0; 1.0;," 2248 "1.0; 1.0; 0.0;," 2249 "1.0; 1.0; 1.0;;" 2250 "6;" /* DWORD nFaces; */ 2251 /* array MeshFace faces[nFaces]; */ 2252 "4; 0, 1, 3, 2;," /* left side */ 2253 "4; 2, 3, 7, 6;," /* top side */ 2254 "4; 6, 7, 5, 4;," /* right side */ 2255 "4; 1, 0, 4, 5;," /* bottom side */ 2256 "4; 1, 5, 7, 3;," /* back side */ 2257 "4; 0, 2, 6, 4;;" /* front side */ 2258 "MeshNormals {" 2259 "6;" /* DWORD nNormals; */ 2260 /* array Vector normals[nNormals]; */ 2261 "-1.0; 0.0; 0.0;," 2262 "0.0; 1.0; 0.0;," 2263 "1.0; 0.0; 0.0;," 2264 "0.0; -1.0; 0.0;," 2265 "0.0; 0.0; 1.0;," 2266 "0.0; 0.0; -1.0;;" 2267 "6;" /* DWORD nFaceNormals; */ 2268 /* array MeshFace faceNormals[nFaceNormals]; */ 2269 "4; 0, 0, 0, 0;," 2270 "4; 1, 1, 1, 1;," 2271 "4; 2, 2, 2, 2;," 2272 "4; 3, 3, 3, 3;," 2273 "4; 4, 4, 4, 4;," 2274 "4; 5, 5, 5, 5;;" 2275 "}" 2276 "MeshMaterialList materials {" 2277 "2;" /* DWORD nMaterials; */ 2278 "6;" /* DWORD nFaceIndexes; */ 2279 /* array DWORD faceIndexes[nFaceIndexes]; */ 2280 "0, 0, 0, 1, 1, 1;;" 2281 "Material {" 2282 /* ColorRGBA faceColor; */ 2283 "0.0; 0.0; 1.0; 1.0;;" 2284 /* FLOAT power; */ 2285 "0.5;" 2286 /* ColorRGB specularColor; */ 2287 "1.0; 1.0; 1.0;;" 2288 /* ColorRGB emissiveColor; */ 2289 "0.0; 0.0; 0.0;;" 2290 "}" 2291 "Material {" 2292 /* ColorRGBA faceColor; */ 2293 "1.0; 1.0; 1.0; 1.0;;" 2294 /* FLOAT power; */ 2295 "1.0;" 2296 /* ColorRGB specularColor; */ 2297 "1.0; 1.0; 1.0;;" 2298 /* ColorRGB emissiveColor; */ 2299 "0.0; 0.0; 0.0;;" 2300 "TextureFilename { \"texture.jpg\"; }" 2301 "}" 2302 "}" 2303 "MeshVertexColors {" 2304 "8;" /* DWORD nVertexColors; */ 2305 /* array IndexedColor vertexColors[nVertexColors]; */ 2306 "0; 0.0; 0.0; 0.0; 0.0;;" 2307 "1; 0.0; 0.0; 1.0; 0.1;;" 2308 "2; 0.0; 1.0; 0.0; 0.2;;" 2309 "3; 0.0; 1.0; 1.0; 0.3;;" 2310 "4; 1.0; 0.0; 0.0; 0.4;;" 2311 "5; 1.0; 0.0; 1.0; 0.5;;" 2312 "6; 1.0; 1.0; 0.0; 0.6;;" 2313 "7; 1.0; 1.0; 1.0; 0.7;;" 2314 "}" 2315 "MeshTextureCoords {" 2316 "8;" /* DWORD nTextureCoords; */ 2317 /* array Coords2d textureCoords[nTextureCoords]; */ 2318 "0.0; 1.0;," 2319 "1.0; 1.0;," 2320 "0.0; 0.0;," 2321 "1.0; 0.0;," 2322 "1.0; 1.0;," 2323 "0.0; 1.0;," 2324 "1.0; 0.0;," 2325 "0.0; 0.0;;" 2326 "}" 2327 "}" 2328 "Frame CubeFrame {" 2329 "FrameTransformMatrix {" 2330 /* Matrix4x4 frameMatrix; */ 2331 "1.0, 0.0, 0.0, 0.0," 2332 "0.0, 1.0, 0.0, 0.0," 2333 "0.0, 0.0, 1.0, 0.0," 2334 "0.0, 0.0, 0.0, 1.0;;" 2335 "}" 2336 "{CubeMesh}" 2337 "}" 2338 "AnimationSet AnimationSet0 {" 2339 "Animation Animation0 {" 2340 "{CubeFrame}" 2341 "AnimationKey {" 2342 "2;" /* DWORD keyType; */ 2343 "9;" /* DWORD nKeys; */ 2344 /* array TimedFloatKeys keys[nKeys]; */ 2345 "10; 3; -100.0, 0.0, 0.0;;," 2346 "20; 3; -75.0, 0.0, 0.0;;," 2347 "30; 3; -50.0, 0.0, 0.0;;," 2348 "40; 3; -25.5, 0.0, 0.0;;," 2349 "50; 3; 0.0, 0.0, 0.0;;," 2350 "60; 3; 25.5, 0.0, 0.0;;," 2351 "70; 3; 50.0, 0.0, 0.0;;," 2352 "80; 3; 75.5, 0.0, 0.0;;," 2353 "90; 3; 100.0, 0.0, 0.0;;;" 2354 "}" 2355 "}" 2356 "}"; 2357 2358 const DWORD box_fvf = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_TEX1; 2359 /*________________________*/ 2360 static const D3DXMATERIAL default_materials[] = { 2361 { 2362 { 2363 {0.5, 0.5, 0.5, 0.0}, /* Diffuse */ 2364 {0.0, 0.0, 0.0, 0.0}, /* Ambient */ 2365 {0.5, 0.5, 0.5, 0.0}, /* Specular */ 2366 {0.0, 0.0, 0.0, 0.0}, /* Emissive */ 2367 0.0, /* Power */ 2368 }, 2369 NULL, /* pTextureFilename */ 2370 } 2371 }; 2372 HRESULT hr; 2373 IDirect3DDevice9 *device = NULL; 2374 ID3DXMesh *mesh = NULL; 2375 D3DXFRAME *frame_hier = NULL; 2376 D3DXMATRIX transform; 2377 struct test_context *test_context; 2378 ID3DXAnimationController *controller; 2379 2380 if (!(test_context = new_test_context())) 2381 { 2382 skip("Couldn't create test context\n"); 2383 return; 2384 } 2385 device = test_context->device; 2386 2387 hr = D3DXLoadMeshHierarchyFromXInMemory(NULL, sizeof(simple_xfile) - 1, 2388 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL); 2389 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 2390 2391 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, 0, 2392 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL); 2393 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 2394 2395 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1, 2396 D3DXMESH_MANAGED, NULL, &alloc_hier, NULL, &frame_hier, NULL); 2397 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 2398 2399 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1, 2400 D3DXMESH_MANAGED, device, NULL, NULL, &frame_hier, NULL); 2401 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 2402 2403 hr = D3DXLoadMeshHierarchyFromXInMemory(empty_xfile, sizeof(empty_xfile) - 1, 2404 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL); 2405 ok(hr == E_FAIL, "Expected E_FAIL, got %#x\n", hr); 2406 2407 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1, 2408 D3DXMESH_MANAGED, device, &alloc_hier, NULL, NULL, NULL); 2409 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 2410 2411 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1, 2412 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL); 2413 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 2414 if (SUCCEEDED(hr)) { 2415 D3DXMESHCONTAINER *container = frame_hier->pMeshContainer; 2416 2417 ok(frame_hier->Name == NULL, "Expected NULL, got '%s'\n", frame_hier->Name); 2418 D3DXMatrixIdentity(&transform); 2419 check_matrix(&frame_hier->TransformationMatrix, &transform); 2420 2421 ok(!strcmp(container->Name, ""), "Expected '', got '%s'\n", container->Name); 2422 ok(container->MeshData.Type == D3DXMESHTYPE_MESH, "Expected %d, got %d\n", 2423 D3DXMESHTYPE_MESH, container->MeshData.Type); 2424 mesh = U(container->MeshData).pMesh; 2425 check_vertex_buffer(mesh, simple_vertex_buffer, ARRAY_SIZE(simple_vertex_buffer), simple_fvf); 2426 check_index_buffer(mesh, simple_index_buffer, ARRAY_SIZE(simple_index_buffer), sizeof(*simple_index_buffer)); 2427 check_materials(container->pMaterials, container->NumMaterials, NULL, 0); 2428 check_generated_effects(container->pMaterials, container->NumMaterials, container->pEffects); 2429 check_generated_adjacency(mesh, container->pAdjacency, 0.0f); 2430 hr = D3DXFrameDestroy(frame_hier, &alloc_hier); 2431 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 2432 frame_hier = NULL; 2433 } 2434 2435 controller = (ID3DXAnimationController *)0xdeadbeef; 2436 hr = D3DXLoadMeshHierarchyFromXInMemory(box_anim_xfile, sizeof(box_anim_xfile) - 1, 2437 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, &controller); 2438 todo_wine ok(hr == D3D_OK, "Expected D3D_OK, got %#x.\n", hr); 2439 if (SUCCEEDED(hr)) 2440 { 2441 ok(controller != NULL, "Animation Controller NULL.\n"); 2442 2443 hr = D3DXFrameDestroy(frame_hier, &alloc_hier); 2444 ok(hr == D3D_OK, "Expected D3D_OK, got %#x.\n", hr); 2445 if (controller) 2446 controller->lpVtbl->Release(controller); 2447 2448 frame_hier = NULL; 2449 } 2450 2451 controller = (ID3DXAnimationController *)0xdeadbeef; 2452 hr = D3DXLoadMeshHierarchyFromXInMemory(box_xfile, sizeof(box_xfile) - 1, 2453 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, &controller); 2454 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 2455 if (SUCCEEDED(hr)) 2456 { 2457 D3DXMESHCONTAINER *container = frame_hier->pMeshContainer; 2458 2459 ok(!controller, "Animation Controller returned.\n"); 2460 ok(frame_hier->Name == NULL, "Expected NULL, got '%s'\n", frame_hier->Name); 2461 D3DXMatrixIdentity(&transform); 2462 check_matrix(&frame_hier->TransformationMatrix, &transform); 2463 2464 ok(!strcmp(container->Name, ""), "Expected '', got '%s'\n", container->Name); 2465 ok(container->MeshData.Type == D3DXMESHTYPE_MESH, "Expected %d, got %d\n", 2466 D3DXMESHTYPE_MESH, container->MeshData.Type); 2467 mesh = U(container->MeshData).pMesh; 2468 check_vertex_buffer(mesh, box_vertex_buffer, ARRAY_SIZE(box_vertex_buffer), box_fvf); 2469 check_index_buffer(mesh, box_index_buffer, ARRAY_SIZE(box_index_buffer), sizeof(*box_index_buffer)); 2470 check_materials(container->pMaterials, container->NumMaterials, box_materials, ARRAY_SIZE(box_materials)); 2471 check_generated_effects(container->pMaterials, container->NumMaterials, container->pEffects); 2472 check_generated_adjacency(mesh, container->pAdjacency, 0.0f); 2473 hr = D3DXFrameDestroy(frame_hier, &alloc_hier); 2474 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 2475 frame_hier = NULL; 2476 } 2477 2478 hr = D3DXLoadMeshHierarchyFromXInMemory(framed_xfile, sizeof(framed_xfile) - 1, 2479 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL); 2480 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 2481 if (SUCCEEDED(hr)) { 2482 D3DXMESHCONTAINER *container = frame_hier->pMeshContainer; 2483 int i; 2484 2485 ok(!strcmp(frame_hier->Name, ""), "Expected '', got '%s'\n", frame_hier->Name); 2486 /* last frame transform replaces the first */ 2487 D3DXMatrixIdentity(&transform); 2488 U(transform).m[3][2] = 3.0; 2489 check_matrix(&frame_hier->TransformationMatrix, &transform); 2490 2491 for (i = 0; i < 3; i++) { 2492 ok(!strcmp(container->Name, ""), "Expected '', got '%s'\n", container->Name); 2493 ok(container->MeshData.Type == D3DXMESHTYPE_MESH, "Expected %d, got %d\n", 2494 D3DXMESHTYPE_MESH, container->MeshData.Type); 2495 mesh = U(container->MeshData).pMesh; 2496 check_vertex_buffer(mesh, framed_vertex_buffers[i], ARRAY_SIZE(framed_vertex_buffers[0]), framed_fvf); 2497 check_index_buffer(mesh, framed_index_buffer, ARRAY_SIZE(framed_index_buffer), sizeof(*framed_index_buffer)); 2498 check_materials(container->pMaterials, container->NumMaterials, NULL, 0); 2499 check_generated_effects(container->pMaterials, container->NumMaterials, container->pEffects); 2500 check_generated_adjacency(mesh, container->pAdjacency, 0.0f); 2501 container = container->pNextMeshContainer; 2502 } 2503 ok(container == NULL, "Expected NULL, got %p\n", container); 2504 hr = D3DXFrameDestroy(frame_hier, &alloc_hier); 2505 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 2506 frame_hier = NULL; 2507 } 2508 2509 2510 hr = D3DXLoadMeshFromXInMemory(NULL, 0, D3DXMESH_MANAGED, 2511 device, NULL, NULL, NULL, NULL, &mesh); 2512 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 2513 2514 hr = D3DXLoadMeshFromXInMemory(NULL, sizeof(simple_xfile) - 1, D3DXMESH_MANAGED, 2515 device, NULL, NULL, NULL, NULL, &mesh); 2516 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 2517 2518 hr = D3DXLoadMeshFromXInMemory(simple_xfile, 0, D3DXMESH_MANAGED, 2519 device, NULL, NULL, NULL, NULL, &mesh); 2520 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 2521 2522 hr = D3DXLoadMeshFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1, D3DXMESH_MANAGED, 2523 device, NULL, NULL, NULL, NULL, NULL); 2524 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 2525 2526 hr = D3DXLoadMeshFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1, D3DXMESH_MANAGED, 2527 NULL, NULL, NULL, NULL, NULL, &mesh); 2528 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 2529 2530 hr = D3DXLoadMeshFromXInMemory(empty_xfile, sizeof(empty_xfile) - 1, D3DXMESH_MANAGED, 2531 device, NULL, NULL, NULL, NULL, &mesh); 2532 ok(hr == E_FAIL, "Expected E_FAIL, got %#x\n", hr); 2533 2534 hr = D3DXLoadMeshFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1, D3DXMESH_MANAGED, 2535 device, NULL, NULL, NULL, NULL, &mesh); 2536 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 2537 if (SUCCEEDED(hr)) 2538 IUnknown_Release(mesh); 2539 2540 test_LoadMeshFromX(device, simple_xfile, simple_vertex_buffer, simple_fvf, simple_index_buffer, default_materials, TRUE); 2541 test_LoadMeshFromX(device, box_xfile, box_vertex_buffer, box_fvf, box_index_buffer, box_materials, TRUE); 2542 test_LoadMeshFromX(device, framed_xfile, merged_vertex_buffer, framed_fvf, merged_index_buffer, default_materials, FALSE); 2543 2544 free_test_context(test_context); 2545 } 2546 2547 static BOOL compute_box(struct mesh *mesh, float width, float height, float depth) 2548 { 2549 unsigned int i, face; 2550 static const D3DXVECTOR3 unit_box[] = 2551 { 2552 {-1.0f, -1.0f, -1.0f}, {-1.0f, -1.0f, 1.0f}, {-1.0f, 1.0f, 1.0f}, {-1.0f, 1.0f, -1.0f}, 2553 {-1.0f, 1.0f, -1.0f}, {-1.0f, 1.0f, 1.0f}, { 1.0f, 1.0f, 1.0f}, { 1.0f, 1.0f, -1.0f}, 2554 { 1.0f, 1.0f, -1.0f}, { 1.0f, 1.0f, 1.0f}, { 1.0f, -1.0f, 1.0f}, { 1.0f, -1.0f, -1.0f}, 2555 {-1.0f, -1.0f, 1.0f}, {-1.0f, -1.0f, -1.0f}, { 1.0f, -1.0f, -1.0f}, { 1.0f, -1.0f, 1.0f}, 2556 {-1.0f, -1.0f, 1.0f}, { 1.0f, -1.0f, 1.0f}, { 1.0f, 1.0f, 1.0f}, {-1.0f, 1.0f, 1.0f}, 2557 {-1.0f, -1.0f, -1.0f}, {-1.0f, 1.0f, -1.0f}, { 1.0f, 1.0f, -1.0f}, { 1.0f, -1.0f, -1.0f} 2558 }; 2559 static const D3DXVECTOR3 normals[] = 2560 { 2561 {-1.0f, 0.0f, 0.0f}, { 0.0f, 1.0f, 0.0f}, { 1.0f, 0.0f, 0.0f}, 2562 { 0.0f, -1.0f, 0.0f}, { 0.0f, 0.0f, 1.0f}, { 0.0f, 0.0f, -1.0f} 2563 }; 2564 2565 if (!new_mesh(mesh, 24, 12)) 2566 { 2567 return FALSE; 2568 } 2569 2570 width /= 2.0f; 2571 height /= 2.0f; 2572 depth /= 2.0f; 2573 2574 for (i = 0; i < 24; i++) 2575 { 2576 mesh->vertices[i].position.x = width * unit_box[i].x; 2577 mesh->vertices[i].position.y = height * unit_box[i].y; 2578 mesh->vertices[i].position.z = depth * unit_box[i].z; 2579 mesh->vertices[i].normal.x = normals[i / 4].x; 2580 mesh->vertices[i].normal.y = normals[i / 4].y; 2581 mesh->vertices[i].normal.z = normals[i / 4].z; 2582 } 2583 2584 face = 0; 2585 for (i = 0; i < 12; i++) 2586 { 2587 mesh->faces[i][0] = face++; 2588 mesh->faces[i][1] = face++; 2589 mesh->faces[i][2] = (i % 2) ? face - 4 : face; 2590 } 2591 2592 return TRUE; 2593 } 2594 2595 static void test_box(IDirect3DDevice9 *device, float width, float height, float depth) 2596 { 2597 HRESULT hr; 2598 ID3DXMesh *box; 2599 struct mesh mesh; 2600 char name[256]; 2601 2602 hr = D3DXCreateBox(device, width, height, depth, &box, NULL); 2603 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); 2604 if (hr != D3D_OK) 2605 { 2606 skip("Couldn't create box\n"); 2607 return; 2608 } 2609 2610 if (!compute_box(&mesh, width, height, depth)) 2611 { 2612 skip("Couldn't create mesh\n"); 2613 box->lpVtbl->Release(box); 2614 return; 2615 } 2616 2617 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL; 2618 2619 sprintf(name, "box (%g, %g, %g)", width, height, depth); 2620 compare_mesh(name, box, &mesh); 2621 2622 free_mesh(&mesh); 2623 2624 box->lpVtbl->Release(box); 2625 } 2626 static void D3DXCreateBoxTest(void) 2627 { 2628 HRESULT hr; 2629 IDirect3DDevice9* device; 2630 ID3DXMesh* box; 2631 ID3DXBuffer* ppBuffer; 2632 DWORD *buffer; 2633 static const DWORD adjacency[36]= 2634 {6, 9, 1, 2, 10, 0, 2635 1, 9, 3, 4, 10, 2, 2636 3, 8, 5, 7, 11, 4, 2637 0, 11, 7, 5, 8, 6, 2638 7, 4, 9, 2, 0, 8, 2639 1, 3, 11, 5, 6, 10}; 2640 unsigned int i; 2641 struct test_context *test_context; 2642 2643 if (!(test_context = new_test_context())) 2644 { 2645 skip("Couldn't create test context\n"); 2646 return; 2647 } 2648 device = test_context->device; 2649 2650 hr = D3DXCreateBox(device,2.0f,20.0f,4.9f,NULL, &ppBuffer); 2651 ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr); 2652 2653 hr = D3DXCreateBox(NULL,22.0f,20.0f,4.9f,&box, &ppBuffer); 2654 ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr); 2655 2656 hr = D3DXCreateBox(device,-2.0f,20.0f,4.9f,&box, &ppBuffer); 2657 ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr); 2658 2659 hr = D3DXCreateBox(device,22.0f,-20.0f,4.9f,&box, &ppBuffer); 2660 ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr); 2661 2662 hr = D3DXCreateBox(device,22.0f,20.0f,-4.9f,&box, &ppBuffer); 2663 ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr); 2664 2665 ppBuffer = NULL; 2666 hr = D3DXCreateBox(device,10.9f,20.0f,4.9f,&box, &ppBuffer); 2667 ok(hr==D3D_OK, "Expected D3D_OK, received %#x\n", hr); 2668 2669 buffer = ID3DXBuffer_GetBufferPointer(ppBuffer); 2670 for(i=0; i<36; i++) 2671 ok(adjacency[i]==buffer[i], "expected adjacency %d: %#x, received %#x\n",i,adjacency[i], buffer[i]); 2672 2673 box->lpVtbl->Release(box); 2674 ID3DXBuffer_Release(ppBuffer); 2675 2676 test_box(device, 10.9f, 20.0f, 4.9f); 2677 2678 free_test_context(test_context); 2679 } 2680 2681 static BOOL compute_polygon(struct mesh *mesh, float length, unsigned int sides) 2682 { 2683 unsigned int i; 2684 float angle, scale; 2685 2686 if (!new_mesh(mesh, sides + 1, sides)) 2687 return FALSE; 2688 2689 angle = D3DX_PI / sides; 2690 scale = 0.5f * length / sinf(angle); 2691 angle *= 2.0f; 2692 2693 mesh->vertices[0].position.x = 0.0f; 2694 mesh->vertices[0].position.y = 0.0f; 2695 mesh->vertices[0].position.z = 0.0f; 2696 mesh->vertices[0].normal.x = 0.0f; 2697 mesh->vertices[0].normal.y = 0.0f; 2698 mesh->vertices[0].normal.z = 1.0f; 2699 2700 for (i = 0; i < sides; ++i) 2701 { 2702 mesh->vertices[i + 1].position.x = cosf(angle * i) * scale; 2703 mesh->vertices[i + 1].position.y = sinf(angle * i) * scale; 2704 mesh->vertices[i + 1].position.z = 0.0f; 2705 mesh->vertices[i + 1].normal.x = 0.0f; 2706 mesh->vertices[i + 1].normal.y = 0.0f; 2707 mesh->vertices[i + 1].normal.z = 1.0f; 2708 2709 mesh->faces[i][0] = 0; 2710 mesh->faces[i][1] = i + 1; 2711 mesh->faces[i][2] = i + 2; 2712 } 2713 2714 mesh->faces[sides - 1][2] = 1; 2715 2716 return TRUE; 2717 } 2718 2719 static void test_polygon(IDirect3DDevice9 *device, float length, unsigned int sides) 2720 { 2721 HRESULT hr; 2722 ID3DXMesh *polygon; 2723 struct mesh mesh; 2724 char name[64]; 2725 2726 hr = D3DXCreatePolygon(device, length, sides, &polygon, NULL); 2727 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); 2728 if (hr != D3D_OK) 2729 { 2730 skip("Couldn't create polygon\n"); 2731 return; 2732 } 2733 2734 if (!compute_polygon(&mesh, length, sides)) 2735 { 2736 skip("Couldn't create mesh\n"); 2737 polygon->lpVtbl->Release(polygon); 2738 return; 2739 } 2740 2741 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL; 2742 2743 sprintf(name, "polygon (%g, %u)", length, sides); 2744 compare_mesh(name, polygon, &mesh); 2745 2746 free_mesh(&mesh); 2747 2748 polygon->lpVtbl->Release(polygon); 2749 } 2750 2751 static void D3DXCreatePolygonTest(void) 2752 { 2753 HRESULT hr; 2754 IDirect3DDevice9 *device; 2755 ID3DXMesh *polygon; 2756 ID3DXBuffer *adjacency; 2757 DWORD (*buffer)[3], buffer_size; 2758 unsigned int i; 2759 struct test_context *test_context; 2760 2761 if (!(test_context = new_test_context())) 2762 { 2763 skip("Couldn't create test context\n"); 2764 return; 2765 } 2766 device = test_context->device; 2767 2768 hr = D3DXCreatePolygon(device, 2.0f, 11, NULL, &adjacency); 2769 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr); 2770 2771 hr = D3DXCreatePolygon(NULL, 2.0f, 11, &polygon, &adjacency); 2772 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr); 2773 2774 hr = D3DXCreatePolygon(device, -2.0f, 11, &polygon, &adjacency); 2775 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr); 2776 2777 polygon = (void *)0xdeadbeef; 2778 adjacency = (void *)0xdeadbeef; 2779 hr = D3DXCreatePolygon(device, 2.0f, 0, &polygon, &adjacency); 2780 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr); 2781 ok(polygon == (void *)0xdeadbeef, "Polygon was changed to %p\n", polygon); 2782 ok(adjacency == (void *)0xdeadbeef, "Adjacency was changed to %p\n", adjacency); 2783 2784 hr = D3DXCreatePolygon(device, 2.0f, 2, &polygon, &adjacency); 2785 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr); 2786 2787 adjacency = NULL; 2788 hr = D3DXCreatePolygon(device, 3.0f, 11, &polygon, &adjacency); 2789 ok(hr == D3D_OK, "Expected D3D_OK, received %#x\n", hr); 2790 2791 buffer_size = ID3DXBuffer_GetBufferSize(adjacency); 2792 ok(buffer_size == 33 * sizeof(DWORD), "Wrong adjacency buffer size %u\n", buffer_size); 2793 2794 buffer = ID3DXBuffer_GetBufferPointer(adjacency); 2795 for (i = 0; i < 11; ++i) 2796 { 2797 ok(buffer[i][0] == (i + 10) % 11, "Wrong adjacency[%d][0] = %u\n", i, buffer[i][0]); 2798 ok(buffer[i][1] == ~0U, "Wrong adjacency[%d][1] = %u\n", i, buffer[i][1]); 2799 ok(buffer[i][2] == (i + 1) % 11, "Wrong adjacency[%d][2] = %u\n", i, buffer[i][2]); 2800 } 2801 2802 polygon->lpVtbl->Release(polygon); 2803 ID3DXBuffer_Release(adjacency); 2804 2805 test_polygon(device, 2.0f, 3); 2806 test_polygon(device, 10.0f, 3); 2807 test_polygon(device, 10.0f, 5); 2808 test_polygon(device, 10.0f, 10); 2809 test_polygon(device, 20.0f, 10); 2810 test_polygon(device, 20.0f, 32000); 2811 2812 free_test_context(test_context); 2813 } 2814 2815 struct sincos_table 2816 { 2817 float *sin; 2818 float *cos; 2819 }; 2820 2821 static void free_sincos_table(struct sincos_table *sincos_table) 2822 { 2823 HeapFree(GetProcessHeap(), 0, sincos_table->cos); 2824 HeapFree(GetProcessHeap(), 0, sincos_table->sin); 2825 } 2826 2827 /* pre compute sine and cosine tables; caller must free */ 2828 static BOOL compute_sincos_table(struct sincos_table *sincos_table, float angle_start, float angle_step, int n) 2829 { 2830 float angle; 2831 int i; 2832 2833 sincos_table->sin = HeapAlloc(GetProcessHeap(), 0, n * sizeof(*sincos_table->sin)); 2834 if (!sincos_table->sin) 2835 { 2836 return FALSE; 2837 } 2838 sincos_table->cos = HeapAlloc(GetProcessHeap(), 0, n * sizeof(*sincos_table->cos)); 2839 if (!sincos_table->cos) 2840 { 2841 HeapFree(GetProcessHeap(), 0, sincos_table->sin); 2842 return FALSE; 2843 } 2844 2845 angle = angle_start; 2846 for (i = 0; i < n; i++) 2847 { 2848 sincos_table->sin[i] = sin(angle); 2849 sincos_table->cos[i] = cos(angle); 2850 angle += angle_step; 2851 } 2852 2853 return TRUE; 2854 } 2855 2856 static WORD vertex_index(UINT slices, int slice, int stack) 2857 { 2858 return stack*slices+slice+1; 2859 } 2860 2861 /* slices = subdivisions along xy plane, stacks = subdivisions along z axis */ 2862 static BOOL compute_sphere(struct mesh *mesh, FLOAT radius, UINT slices, UINT stacks) 2863 { 2864 float theta_step, theta_start; 2865 struct sincos_table theta; 2866 float phi_step, phi_start; 2867 struct sincos_table phi; 2868 DWORD number_of_vertices, number_of_faces; 2869 DWORD vertex, face; 2870 int slice, stack; 2871 2872 /* theta = angle on xy plane wrt x axis */ 2873 theta_step = D3DX_PI / stacks; 2874 theta_start = theta_step; 2875 2876 /* phi = angle on xz plane wrt z axis */ 2877 phi_step = -2 * D3DX_PI / slices; 2878 phi_start = D3DX_PI / 2; 2879 2880 if (!compute_sincos_table(&theta, theta_start, theta_step, stacks)) 2881 { 2882 return FALSE; 2883 } 2884 if (!compute_sincos_table(&phi, phi_start, phi_step, slices)) 2885 { 2886 free_sincos_table(&theta); 2887 return FALSE; 2888 } 2889 2890 number_of_vertices = 2 + slices * (stacks-1); 2891 number_of_faces = 2 * slices + (stacks - 2) * (2 * slices); 2892 2893 if (!new_mesh(mesh, number_of_vertices, number_of_faces)) 2894 { 2895 free_sincos_table(&phi); 2896 free_sincos_table(&theta); 2897 return FALSE; 2898 } 2899 2900 vertex = 0; 2901 face = 0; 2902 2903 mesh->vertices[vertex].normal.x = 0.0f; 2904 mesh->vertices[vertex].normal.y = 0.0f; 2905 mesh->vertices[vertex].normal.z = 1.0f; 2906 mesh->vertices[vertex].position.x = 0.0f; 2907 mesh->vertices[vertex].position.y = 0.0f; 2908 mesh->vertices[vertex].position.z = radius; 2909 vertex++; 2910 2911 for (stack = 0; stack < stacks - 1; stack++) 2912 { 2913 for (slice = 0; slice < slices; slice++) 2914 { 2915 mesh->vertices[vertex].normal.x = theta.sin[stack] * phi.cos[slice]; 2916 mesh->vertices[vertex].normal.y = theta.sin[stack] * phi.sin[slice]; 2917 mesh->vertices[vertex].normal.z = theta.cos[stack]; 2918 mesh->vertices[vertex].position.x = radius * theta.sin[stack] * phi.cos[slice]; 2919 mesh->vertices[vertex].position.y = radius * theta.sin[stack] * phi.sin[slice]; 2920 mesh->vertices[vertex].position.z = radius * theta.cos[stack]; 2921 vertex++; 2922 2923 if (slice > 0) 2924 { 2925 if (stack == 0) 2926 { 2927 /* top stack is triangle fan */ 2928 mesh->faces[face][0] = 0; 2929 mesh->faces[face][1] = slice + 1; 2930 mesh->faces[face][2] = slice; 2931 face++; 2932 } 2933 else 2934 { 2935 /* stacks in between top and bottom are quad strips */ 2936 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1); 2937 mesh->faces[face][1] = vertex_index(slices, slice, stack-1); 2938 mesh->faces[face][2] = vertex_index(slices, slice-1, stack); 2939 face++; 2940 2941 mesh->faces[face][0] = vertex_index(slices, slice, stack-1); 2942 mesh->faces[face][1] = vertex_index(slices, slice, stack); 2943 mesh->faces[face][2] = vertex_index(slices, slice-1, stack); 2944 face++; 2945 } 2946 } 2947 } 2948 2949 if (stack == 0) 2950 { 2951 mesh->faces[face][0] = 0; 2952 mesh->faces[face][1] = 1; 2953 mesh->faces[face][2] = slice; 2954 face++; 2955 } 2956 else 2957 { 2958 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1); 2959 mesh->faces[face][1] = vertex_index(slices, 0, stack-1); 2960 mesh->faces[face][2] = vertex_index(slices, slice-1, stack); 2961 face++; 2962 2963 mesh->faces[face][0] = vertex_index(slices, 0, stack-1); 2964 mesh->faces[face][1] = vertex_index(slices, 0, stack); 2965 mesh->faces[face][2] = vertex_index(slices, slice-1, stack); 2966 face++; 2967 } 2968 } 2969 2970 mesh->vertices[vertex].position.x = 0.0f; 2971 mesh->vertices[vertex].position.y = 0.0f; 2972 mesh->vertices[vertex].position.z = -radius; 2973 mesh->vertices[vertex].normal.x = 0.0f; 2974 mesh->vertices[vertex].normal.y = 0.0f; 2975 mesh->vertices[vertex].normal.z = -1.0f; 2976 2977 /* bottom stack is triangle fan */ 2978 for (slice = 1; slice < slices; slice++) 2979 { 2980 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1); 2981 mesh->faces[face][1] = vertex_index(slices, slice, stack-1); 2982 mesh->faces[face][2] = vertex; 2983 face++; 2984 } 2985 2986 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1); 2987 mesh->faces[face][1] = vertex_index(slices, 0, stack-1); 2988 mesh->faces[face][2] = vertex; 2989 2990 free_sincos_table(&phi); 2991 free_sincos_table(&theta); 2992 2993 return TRUE; 2994 } 2995 2996 static void test_sphere(IDirect3DDevice9 *device, FLOAT radius, UINT slices, UINT stacks) 2997 { 2998 HRESULT hr; 2999 ID3DXMesh *sphere; 3000 struct mesh mesh; 3001 char name[256]; 3002 3003 hr = D3DXCreateSphere(device, radius, slices, stacks, &sphere, NULL); 3004 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); 3005 if (hr != D3D_OK) 3006 { 3007 skip("Couldn't create sphere\n"); 3008 return; 3009 } 3010 3011 if (!compute_sphere(&mesh, radius, slices, stacks)) 3012 { 3013 skip("Couldn't create mesh\n"); 3014 sphere->lpVtbl->Release(sphere); 3015 return; 3016 } 3017 3018 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL; 3019 3020 sprintf(name, "sphere (%g, %u, %u)", radius, slices, stacks); 3021 compare_mesh(name, sphere, &mesh); 3022 3023 free_mesh(&mesh); 3024 3025 sphere->lpVtbl->Release(sphere); 3026 } 3027 3028 static void D3DXCreateSphereTest(void) 3029 { 3030 HRESULT hr; 3031 IDirect3DDevice9* device; 3032 ID3DXMesh* sphere = NULL; 3033 struct test_context *test_context; 3034 3035 hr = D3DXCreateSphere(NULL, 0.0f, 0, 0, NULL, NULL); 3036 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL); 3037 3038 hr = D3DXCreateSphere(NULL, 0.1f, 0, 0, NULL, NULL); 3039 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL); 3040 3041 hr = D3DXCreateSphere(NULL, 0.0f, 1, 0, NULL, NULL); 3042 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL); 3043 3044 hr = D3DXCreateSphere(NULL, 0.0f, 0, 1, NULL, NULL); 3045 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL); 3046 3047 if (!(test_context = new_test_context())) 3048 { 3049 skip("Couldn't create test context\n"); 3050 return; 3051 } 3052 device = test_context->device; 3053 3054 hr = D3DXCreateSphere(device, 1.0f, 1, 1, &sphere, NULL); 3055 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL); 3056 3057 hr = D3DXCreateSphere(device, 1.0f, 2, 1, &sphere, NULL); 3058 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 3059 3060 hr = D3DXCreateSphere(device, 1.0f, 1, 2, &sphere, NULL); 3061 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 3062 3063 hr = D3DXCreateSphere(device, -0.1f, 1, 2, &sphere, NULL); 3064 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 3065 3066 test_sphere(device, 0.0f, 2, 2); 3067 test_sphere(device, 1.0f, 2, 2); 3068 test_sphere(device, 1.0f, 3, 2); 3069 test_sphere(device, 1.0f, 4, 4); 3070 test_sphere(device, 1.0f, 3, 4); 3071 test_sphere(device, 5.0f, 6, 7); 3072 test_sphere(device, 10.0f, 11, 12); 3073 3074 free_test_context(test_context); 3075 } 3076 3077 static BOOL compute_cylinder(struct mesh *mesh, FLOAT radius1, FLOAT radius2, FLOAT length, UINT slices, UINT stacks) 3078 { 3079 float theta_step, theta_start; 3080 struct sincos_table theta; 3081 FLOAT delta_radius, radius, radius_step; 3082 FLOAT z, z_step, z_normal; 3083 DWORD number_of_vertices, number_of_faces; 3084 DWORD vertex, face; 3085 int slice, stack; 3086 3087 /* theta = angle on xy plane wrt x axis */ 3088 theta_step = -2 * D3DX_PI / slices; 3089 theta_start = D3DX_PI / 2; 3090 3091 if (!compute_sincos_table(&theta, theta_start, theta_step, slices)) 3092 { 3093 return FALSE; 3094 } 3095 3096 number_of_vertices = 2 + (slices * (3 + stacks)); 3097 number_of_faces = 2 * slices + stacks * (2 * slices); 3098 3099 if (!new_mesh(mesh, number_of_vertices, number_of_faces)) 3100 { 3101 free_sincos_table(&theta); 3102 return FALSE; 3103 } 3104 3105 vertex = 0; 3106 face = 0; 3107 3108 delta_radius = radius1 - radius2; 3109 radius = radius1; 3110 radius_step = delta_radius / stacks; 3111 3112 z = -length / 2; 3113 z_step = length / stacks; 3114 z_normal = delta_radius / length; 3115 if (isnan(z_normal)) 3116 { 3117 z_normal = 0.0f; 3118 } 3119 3120 mesh->vertices[vertex].normal.x = 0.0f; 3121 mesh->vertices[vertex].normal.y = 0.0f; 3122 mesh->vertices[vertex].normal.z = -1.0f; 3123 mesh->vertices[vertex].position.x = 0.0f; 3124 mesh->vertices[vertex].position.y = 0.0f; 3125 mesh->vertices[vertex++].position.z = z; 3126 3127 for (slice = 0; slice < slices; slice++, vertex++) 3128 { 3129 mesh->vertices[vertex].normal.x = 0.0f; 3130 mesh->vertices[vertex].normal.y = 0.0f; 3131 mesh->vertices[vertex].normal.z = -1.0f; 3132 mesh->vertices[vertex].position.x = radius * theta.cos[slice]; 3133 mesh->vertices[vertex].position.y = radius * theta.sin[slice]; 3134 mesh->vertices[vertex].position.z = z; 3135 3136 if (slice > 0) 3137 { 3138 mesh->faces[face][0] = 0; 3139 mesh->faces[face][1] = slice; 3140 mesh->faces[face++][2] = slice + 1; 3141 } 3142 } 3143 3144 mesh->faces[face][0] = 0; 3145 mesh->faces[face][1] = slice; 3146 mesh->faces[face++][2] = 1; 3147 3148 for (stack = 1; stack <= stacks+1; stack++) 3149 { 3150 for (slice = 0; slice < slices; slice++, vertex++) 3151 { 3152 mesh->vertices[vertex].normal.x = theta.cos[slice]; 3153 mesh->vertices[vertex].normal.y = theta.sin[slice]; 3154 mesh->vertices[vertex].normal.z = z_normal; 3155 D3DXVec3Normalize(&mesh->vertices[vertex].normal, &mesh->vertices[vertex].normal); 3156 mesh->vertices[vertex].position.x = radius * theta.cos[slice]; 3157 mesh->vertices[vertex].position.y = radius * theta.sin[slice]; 3158 mesh->vertices[vertex].position.z = z; 3159 3160 if (stack > 1 && slice > 0) 3161 { 3162 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1); 3163 mesh->faces[face][1] = vertex_index(slices, slice-1, stack); 3164 mesh->faces[face++][2] = vertex_index(slices, slice, stack-1); 3165 3166 mesh->faces[face][0] = vertex_index(slices, slice, stack-1); 3167 mesh->faces[face][1] = vertex_index(slices, slice-1, stack); 3168 mesh->faces[face++][2] = vertex_index(slices, slice, stack); 3169 } 3170 } 3171 3172 if (stack > 1) 3173 { 3174 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1); 3175 mesh->faces[face][1] = vertex_index(slices, slice-1, stack); 3176 mesh->faces[face++][2] = vertex_index(slices, 0, stack-1); 3177 3178 mesh->faces[face][0] = vertex_index(slices, 0, stack-1); 3179 mesh->faces[face][1] = vertex_index(slices, slice-1, stack); 3180 mesh->faces[face++][2] = vertex_index(slices, 0, stack); 3181 } 3182 3183 if (stack < stacks + 1) 3184 { 3185 z += z_step; 3186 radius -= radius_step; 3187 } 3188 } 3189 3190 for (slice = 0; slice < slices; slice++, vertex++) 3191 { 3192 mesh->vertices[vertex].normal.x = 0.0f; 3193 mesh->vertices[vertex].normal.y = 0.0f; 3194 mesh->vertices[vertex].normal.z = 1.0f; 3195 mesh->vertices[vertex].position.x = radius * theta.cos[slice]; 3196 mesh->vertices[vertex].position.y = radius * theta.sin[slice]; 3197 mesh->vertices[vertex].position.z = z; 3198 3199 if (slice > 0) 3200 { 3201 mesh->faces[face][0] = vertex_index(slices, slice-1, stack); 3202 mesh->faces[face][1] = number_of_vertices - 1; 3203 mesh->faces[face++][2] = vertex_index(slices, slice, stack); 3204 } 3205 } 3206 3207 mesh->vertices[vertex].position.x = 0.0f; 3208 mesh->vertices[vertex].position.y = 0.0f; 3209 mesh->vertices[vertex].position.z = z; 3210 mesh->vertices[vertex].normal.x = 0.0f; 3211 mesh->vertices[vertex].normal.y = 0.0f; 3212 mesh->vertices[vertex].normal.z = 1.0f; 3213 3214 mesh->faces[face][0] = vertex_index(slices, slice-1, stack); 3215 mesh->faces[face][1] = number_of_vertices - 1; 3216 mesh->faces[face][2] = vertex_index(slices, 0, stack); 3217 3218 free_sincos_table(&theta); 3219 3220 return TRUE; 3221 } 3222 3223 static void test_cylinder(IDirect3DDevice9 *device, FLOAT radius1, FLOAT radius2, FLOAT length, UINT slices, UINT stacks) 3224 { 3225 HRESULT hr; 3226 ID3DXMesh *cylinder; 3227 struct mesh mesh; 3228 char name[256]; 3229 3230 hr = D3DXCreateCylinder(device, radius1, radius2, length, slices, stacks, &cylinder, NULL); 3231 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); 3232 if (hr != D3D_OK) 3233 { 3234 skip("Couldn't create cylinder\n"); 3235 return; 3236 } 3237 3238 if (!compute_cylinder(&mesh, radius1, radius2, length, slices, stacks)) 3239 { 3240 skip("Couldn't create mesh\n"); 3241 cylinder->lpVtbl->Release(cylinder); 3242 return; 3243 } 3244 3245 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL; 3246 3247 sprintf(name, "cylinder (%g, %g, %g, %u, %u)", radius1, radius2, length, slices, stacks); 3248 compare_mesh(name, cylinder, &mesh); 3249 3250 free_mesh(&mesh); 3251 3252 cylinder->lpVtbl->Release(cylinder); 3253 } 3254 3255 static void D3DXCreateCylinderTest(void) 3256 { 3257 HRESULT hr; 3258 IDirect3DDevice9* device; 3259 ID3DXMesh* cylinder = NULL; 3260 struct test_context *test_context; 3261 3262 hr = D3DXCreateCylinder(NULL, 0.0f, 0.0f, 0.0f, 0, 0, NULL, NULL); 3263 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL); 3264 3265 hr = D3DXCreateCylinder(NULL, 1.0f, 1.0f, 1.0f, 2, 1, &cylinder, NULL); 3266 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL); 3267 3268 if (!(test_context = new_test_context())) 3269 { 3270 skip("Couldn't create test context\n"); 3271 return; 3272 } 3273 device = test_context->device; 3274 3275 hr = D3DXCreateCylinder(device, -0.1f, 1.0f, 1.0f, 2, 1, &cylinder, NULL); 3276 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL); 3277 3278 hr = D3DXCreateCylinder(device, 0.0f, 1.0f, 1.0f, 2, 1, &cylinder, NULL); 3279 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n",hr); 3280 3281 if (SUCCEEDED(hr) && cylinder) 3282 { 3283 cylinder->lpVtbl->Release(cylinder); 3284 } 3285 3286 hr = D3DXCreateCylinder(device, 1.0f, -0.1f, 1.0f, 2, 1, &cylinder, NULL); 3287 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL); 3288 3289 hr = D3DXCreateCylinder(device, 1.0f, 0.0f, 1.0f, 2, 1, &cylinder, NULL); 3290 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n",hr); 3291 3292 if (SUCCEEDED(hr) && cylinder) 3293 { 3294 cylinder->lpVtbl->Release(cylinder); 3295 } 3296 3297 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, -0.1f, 2, 1, &cylinder, NULL); 3298 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL); 3299 3300 /* Test with length == 0.0f succeeds */ 3301 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, 0.0f, 2, 1, &cylinder, NULL); 3302 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n",hr); 3303 3304 if (SUCCEEDED(hr) && cylinder) 3305 { 3306 cylinder->lpVtbl->Release(cylinder); 3307 } 3308 3309 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, 1.0f, 1, 1, &cylinder, NULL); 3310 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL); 3311 3312 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, 1.0f, 2, 0, &cylinder, NULL); 3313 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL); 3314 3315 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, 1.0f, 2, 1, NULL, NULL); 3316 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL); 3317 3318 test_cylinder(device, 0.0f, 0.0f, 0.0f, 2, 1); 3319 test_cylinder(device, 1.0f, 1.0f, 1.0f, 2, 1); 3320 test_cylinder(device, 1.0f, 1.0f, 2.0f, 3, 4); 3321 test_cylinder(device, 3.0f, 2.0f, 4.0f, 3, 4); 3322 test_cylinder(device, 2.0f, 3.0f, 4.0f, 3, 4); 3323 test_cylinder(device, 3.0f, 4.0f, 5.0f, 11, 20); 3324 3325 free_test_context(test_context); 3326 } 3327 3328 static BOOL compute_torus(struct mesh *mesh, float innerradius, float outerradius, UINT sides, UINT rings) 3329 { 3330 float phi, phi_step, sin_phi, cos_phi; 3331 float theta, theta_step, sin_theta, cos_theta; 3332 unsigned int numvert, numfaces, i, j; 3333 3334 numvert = sides * rings; 3335 numfaces = numvert * 2; 3336 3337 if (!new_mesh(mesh, numvert, numfaces)) 3338 return FALSE; 3339 3340 phi_step = D3DX_PI / sides * 2.0f; 3341 theta_step = D3DX_PI / rings * -2.0f; 3342 3343 theta = 0.0f; 3344 3345 for (i = 0; i < rings; ++i) 3346 { 3347 phi = 0.0f; 3348 3349 cos_theta = cosf(theta); 3350 sin_theta = sinf(theta); 3351 3352 for (j = 0; j < sides; ++j) 3353 { 3354 sin_phi = sinf(phi); 3355 cos_phi = cosf(phi); 3356 3357 mesh->vertices[i * sides + j].position.x = (innerradius * cos_phi + outerradius) * cos_theta; 3358 mesh->vertices[i * sides + j].position.y = (innerradius * cos_phi + outerradius) * sin_theta; 3359 mesh->vertices[i * sides + j].position.z = innerradius * sin_phi; 3360 mesh->vertices[i * sides + j].normal.x = cos_phi * cos_theta; 3361 mesh->vertices[i * sides + j].normal.y = cos_phi * sin_theta; 3362 mesh->vertices[i * sides + j].normal.z = sin_phi; 3363 3364 phi += phi_step; 3365 } 3366 3367 theta += theta_step; 3368 } 3369 3370 for (i = 0; i < numfaces - sides * 2; ++i) 3371 { 3372 mesh->faces[i][0] = i % 2 ? i / 2 + sides : i / 2; 3373 mesh->faces[i][1] = (i / 2 + 1) % sides ? i / 2 + 1 : i / 2 + 1 - sides; 3374 mesh->faces[i][2] = (i + 1) % (sides * 2) ? (i + 1) / 2 + sides : (i + 1) / 2; 3375 } 3376 3377 for (j = 0; i < numfaces; ++i, ++j) 3378 { 3379 mesh->faces[i][0] = i % 2 ? j / 2 : i / 2; 3380 mesh->faces[i][1] = (i / 2 + 1) % sides ? i / 2 + 1 : i / 2 + 1 - sides; 3381 mesh->faces[i][2] = i == numfaces - 1 ? 0 : (j + 1) / 2; 3382 } 3383 3384 return TRUE; 3385 } 3386 3387 static void test_torus(IDirect3DDevice9 *device, float innerradius, float outerradius, UINT sides, UINT rings) 3388 { 3389 HRESULT hr; 3390 ID3DXMesh *torus; 3391 struct mesh mesh; 3392 char name[256]; 3393 3394 hr = D3DXCreateTorus(device, innerradius, outerradius, sides, rings, &torus, NULL); 3395 ok(hr == D3D_OK, "Got result %#x, expected 0 (D3D_OK)\n", hr); 3396 if (hr != D3D_OK) 3397 { 3398 skip("Couldn't create torus\n"); 3399 return; 3400 } 3401 3402 if (!compute_torus(&mesh, innerradius, outerradius, sides, rings)) 3403 { 3404 skip("Couldn't create mesh\n"); 3405 torus->lpVtbl->Release(torus); 3406 return; 3407 } 3408 3409 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL; 3410 3411 sprintf(name, "torus (%g, %g, %u, %u)", innerradius, outerradius, sides, rings); 3412 compare_mesh(name, torus, &mesh); 3413 3414 free_mesh(&mesh); 3415 3416 torus->lpVtbl->Release(torus); 3417 } 3418 3419 static void D3DXCreateTorusTest(void) 3420 { 3421 HRESULT hr; 3422 IDirect3DDevice9* device; 3423 ID3DXMesh* torus = NULL; 3424 struct test_context *test_context; 3425 3426 if (!(test_context = new_test_context())) 3427 { 3428 skip("Couldn't create test context\n"); 3429 return; 3430 } 3431 device = test_context->device; 3432 3433 hr = D3DXCreateTorus(NULL, 0.0f, 0.0f, 3, 3, &torus, NULL); 3434 ok(hr == D3DERR_INVALIDCALL, "Got result %#x, expected %#x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 3435 3436 hr = D3DXCreateTorus(device, -1.0f, 0.0f, 3, 3, &torus, NULL); 3437 ok(hr == D3DERR_INVALIDCALL, "Got result %#x, expected %#x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 3438 3439 hr = D3DXCreateTorus(device, 0.0f, -1.0f, 3, 3, &torus, NULL); 3440 ok(hr == D3DERR_INVALIDCALL, "Got result %#x, expected %#x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 3441 3442 hr = D3DXCreateTorus(device, 0.0f, 0.0f, 2, 3, &torus, NULL); 3443 ok(hr == D3DERR_INVALIDCALL, "Got result %#x, expected %#x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 3444 3445 hr = D3DXCreateTorus(device, 0.0f, 0.0f, 3, 2, &torus, NULL); 3446 ok(hr == D3DERR_INVALIDCALL, "Got result %#x, expected %#x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 3447 3448 hr = D3DXCreateTorus(device, 0.0f, 0.0f, 3, 3, NULL, NULL); 3449 ok(hr == D3DERR_INVALIDCALL, "Got result %#x, expected %#x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 3450 3451 test_torus(device, 0.0f, 0.0f, 3, 3); 3452 test_torus(device, 1.0f, 1.0f, 3, 3); 3453 test_torus(device, 1.0f, 1.0f, 32, 64); 3454 test_torus(device, 0.0f, 1.0f, 5, 5); 3455 test_torus(device, 1.0f, 0.0f, 5, 5); 3456 test_torus(device, 5.0f, 0.2f, 8, 8); 3457 test_torus(device, 0.2f, 1.0f, 60, 3); 3458 test_torus(device, 0.2f, 1.0f, 8, 70); 3459 3460 free_test_context(test_context); 3461 } 3462 3463 struct dynamic_array 3464 { 3465 int count, capacity; 3466 void *items; 3467 }; 3468 3469 enum pointtype { 3470 POINTTYPE_CURVE = 0, 3471 POINTTYPE_CORNER, 3472 POINTTYPE_CURVE_START, 3473 POINTTYPE_CURVE_END, 3474 POINTTYPE_CURVE_MIDDLE, 3475 }; 3476 3477 struct point2d 3478 { 3479 D3DXVECTOR2 pos; 3480 enum pointtype corner; 3481 }; 3482 3483 /* is a dynamic_array */ 3484 struct outline 3485 { 3486 int count, capacity; 3487 struct point2d *items; 3488 }; 3489 3490 /* is a dynamic_array */ 3491 struct outline_array 3492 { 3493 int count, capacity; 3494 struct outline *items; 3495 }; 3496 3497 struct glyphinfo 3498 { 3499 struct outline_array outlines; 3500 float offset_x; 3501 }; 3502 3503 static BOOL reserve(struct dynamic_array *array, int count, int itemsize) 3504 { 3505 if (count > array->capacity) { 3506 void *new_buffer; 3507 int new_capacity; 3508 if (array->items && array->capacity) { 3509 new_capacity = max(array->capacity * 2, count); 3510 new_buffer = HeapReAlloc(GetProcessHeap(), 0, array->items, new_capacity * itemsize); 3511 } else { 3512 new_capacity = max(16, count); 3513 new_buffer = HeapAlloc(GetProcessHeap(), 0, new_capacity * itemsize); 3514 } 3515 if (!new_buffer) 3516 return FALSE; 3517 array->items = new_buffer; 3518 array->capacity = new_capacity; 3519 } 3520 return TRUE; 3521 } 3522 3523 static struct point2d *add_point(struct outline *array) 3524 { 3525 struct point2d *item; 3526 3527 if (!reserve((struct dynamic_array *)array, array->count + 1, sizeof(array->items[0]))) 3528 return NULL; 3529 3530 item = &array->items[array->count++]; 3531 ZeroMemory(item, sizeof(*item)); 3532 return item; 3533 } 3534 3535 static struct outline *add_outline(struct outline_array *array) 3536 { 3537 struct outline *item; 3538 3539 if (!reserve((struct dynamic_array *)array, array->count + 1, sizeof(array->items[0]))) 3540 return NULL; 3541 3542 item = &array->items[array->count++]; 3543 ZeroMemory(item, sizeof(*item)); 3544 return item; 3545 } 3546 3547 static inline D3DXVECTOR2 *convert_fixed_to_float(POINTFX *pt, int count, float emsquare) 3548 { 3549 D3DXVECTOR2 *ret = (D3DXVECTOR2*)pt; 3550 while (count--) { 3551 D3DXVECTOR2 *pt_flt = (D3DXVECTOR2*)pt; 3552 pt_flt->x = (pt->x.value + pt->x.fract / (float)0x10000) / emsquare; 3553 pt_flt->y = (pt->y.value + pt->y.fract / (float)0x10000) / emsquare; 3554 pt++; 3555 } 3556 return ret; 3557 } 3558 3559 static HRESULT add_bezier_points(struct outline *outline, const D3DXVECTOR2 *p1, 3560 const D3DXVECTOR2 *p2, const D3DXVECTOR2 *p3, 3561 float max_deviation) 3562 { 3563 D3DXVECTOR2 split1 = {0, 0}, split2 = {0, 0}, middle, vec; 3564 float deviation; 3565 3566 D3DXVec2Scale(&split1, D3DXVec2Add(&split1, p1, p2), 0.5f); 3567 D3DXVec2Scale(&split2, D3DXVec2Add(&split2, p2, p3), 0.5f); 3568 D3DXVec2Scale(&middle, D3DXVec2Add(&middle, &split1, &split2), 0.5f); 3569 3570 deviation = D3DXVec2Length(D3DXVec2Subtract(&vec, &middle, p2)); 3571 if (deviation < max_deviation) { 3572 struct point2d *pt = add_point(outline); 3573 if (!pt) return E_OUTOFMEMORY; 3574 pt->pos = *p2; 3575 pt->corner = POINTTYPE_CURVE; 3576 /* the end point is omitted because the end line merges into the next segment of 3577 * the split bezier curve, and the end of the split bezier curve is added outside 3578 * this recursive function. */ 3579 } else { 3580 HRESULT hr = add_bezier_points(outline, p1, &split1, &middle, max_deviation); 3581 if (hr != S_OK) return hr; 3582 hr = add_bezier_points(outline, &middle, &split2, p3, max_deviation); 3583 if (hr != S_OK) return hr; 3584 } 3585 3586 return S_OK; 3587 } 3588 3589 static inline BOOL is_direction_similar(D3DXVECTOR2 *dir1, D3DXVECTOR2 *dir2, float cos_theta) 3590 { 3591 /* dot product = cos(theta) */ 3592 return D3DXVec2Dot(dir1, dir2) > cos_theta; 3593 } 3594 3595 static inline D3DXVECTOR2 *unit_vec2(D3DXVECTOR2 *dir, const D3DXVECTOR2 *pt1, const D3DXVECTOR2 *pt2) 3596 { 3597 return D3DXVec2Normalize(D3DXVec2Subtract(dir, pt2, pt1), dir); 3598 } 3599 3600 static BOOL attempt_line_merge(struct outline *outline, 3601 int pt_index, 3602 const D3DXVECTOR2 *nextpt, 3603 BOOL to_curve) 3604 { 3605 D3DXVECTOR2 curdir, lastdir; 3606 struct point2d *prevpt, *pt; 3607 BOOL ret = FALSE; 3608 const float cos_half = cos(D3DXToRadian(0.5f)); 3609 3610 pt = &outline->items[pt_index]; 3611 pt_index = (pt_index - 1 + outline->count) % outline->count; 3612 prevpt = &outline->items[pt_index]; 3613 3614 if (to_curve) 3615 pt->corner = pt->corner != POINTTYPE_CORNER ? POINTTYPE_CURVE_MIDDLE : POINTTYPE_CURVE_START; 3616 3617 if (outline->count < 2) 3618 return FALSE; 3619 3620 /* remove last point if the next line continues the last line */ 3621 unit_vec2(&lastdir, &prevpt->pos, &pt->pos); 3622 unit_vec2(&curdir, &pt->pos, nextpt); 3623 if (is_direction_similar(&lastdir, &curdir, cos_half)) 3624 { 3625 outline->count--; 3626 if (pt->corner == POINTTYPE_CURVE_END) 3627 prevpt->corner = pt->corner; 3628 if (prevpt->corner == POINTTYPE_CURVE_END && to_curve) 3629 prevpt->corner = POINTTYPE_CURVE_MIDDLE; 3630 pt = prevpt; 3631 3632 ret = TRUE; 3633 if (outline->count < 2) 3634 return ret; 3635 3636 pt_index = (pt_index - 1 + outline->count) % outline->count; 3637 prevpt = &outline->items[pt_index]; 3638 unit_vec2(&lastdir, &prevpt->pos, &pt->pos); 3639 unit_vec2(&curdir, &pt->pos, nextpt); 3640 } 3641 return ret; 3642 } 3643 3644 static HRESULT create_outline(struct glyphinfo *glyph, void *raw_outline, int datasize, 3645 float max_deviation, float emsquare) 3646 { 3647 const float cos_45 = cos(D3DXToRadian(45.0f)); 3648 const float cos_90 = cos(D3DXToRadian(90.0f)); 3649 TTPOLYGONHEADER *header = (TTPOLYGONHEADER *)raw_outline; 3650 3651 while ((char *)header < (char *)raw_outline + datasize) 3652 { 3653 TTPOLYCURVE *curve = (TTPOLYCURVE *)(header + 1); 3654 struct point2d *lastpt, *pt; 3655 D3DXVECTOR2 lastdir; 3656 D3DXVECTOR2 *pt_flt; 3657 int j; 3658 struct outline *outline = add_outline(&glyph->outlines); 3659 3660 if (!outline) 3661 return E_OUTOFMEMORY; 3662 3663 pt = add_point(outline); 3664 if (!pt) 3665 return E_OUTOFMEMORY; 3666 pt_flt = convert_fixed_to_float(&header->pfxStart, 1, emsquare); 3667 pt->pos = *pt_flt; 3668 pt->corner = POINTTYPE_CORNER; 3669 3670 if (header->dwType != TT_POLYGON_TYPE) 3671 trace("Unknown header type %d\n", header->dwType); 3672 3673 while ((char *)curve < (char *)header + header->cb) 3674 { 3675 D3DXVECTOR2 bezier_start = outline->items[outline->count - 1].pos; 3676 BOOL to_curve = curve->wType != TT_PRIM_LINE && curve->cpfx > 1; 3677 3678 if (!curve->cpfx) { 3679 curve = (TTPOLYCURVE *)&curve->apfx[curve->cpfx]; 3680 continue; 3681 } 3682 3683 pt_flt = convert_fixed_to_float(curve->apfx, curve->cpfx, emsquare); 3684 3685 attempt_line_merge(outline, outline->count - 1, &pt_flt[0], to_curve); 3686 3687 if (to_curve) 3688 { 3689 HRESULT hr; 3690 int count = curve->cpfx; 3691 j = 0; 3692 3693 while (count > 2) 3694 { 3695 D3DXVECTOR2 bezier_end; 3696 3697 D3DXVec2Scale(&bezier_end, D3DXVec2Add(&bezier_end, &pt_flt[j], &pt_flt[j+1]), 0.5f); 3698 hr = add_bezier_points(outline, &bezier_start, &pt_flt[j], &bezier_end, max_deviation); 3699 if (hr != S_OK) 3700 return hr; 3701 bezier_start = bezier_end; 3702 count--; 3703 j++; 3704 } 3705 hr = add_bezier_points(outline, &bezier_start, &pt_flt[j], &pt_flt[j+1], max_deviation); 3706 if (hr != S_OK) 3707 return hr; 3708 3709 pt = add_point(outline); 3710 if (!pt) 3711 return E_OUTOFMEMORY; 3712 j++; 3713 pt->pos = pt_flt[j]; 3714 pt->corner = POINTTYPE_CURVE_END; 3715 } else { 3716 for (j = 0; j < curve->cpfx; j++) 3717 { 3718 pt = add_point(outline); 3719 if (!pt) 3720 return E_OUTOFMEMORY; 3721 pt->pos = pt_flt[j]; 3722 pt->corner = POINTTYPE_CORNER; 3723 } 3724 } 3725 3726 curve = (TTPOLYCURVE *)&curve->apfx[curve->cpfx]; 3727 } 3728 3729 /* remove last point if the next line continues the last line */ 3730 if (outline->count >= 3) { 3731 BOOL to_curve; 3732 3733 lastpt = &outline->items[outline->count - 1]; 3734 pt = &outline->items[0]; 3735 if (pt->pos.x == lastpt->pos.x && pt->pos.y == lastpt->pos.y) { 3736 if (lastpt->corner == POINTTYPE_CURVE_END) 3737 { 3738 if (pt->corner == POINTTYPE_CURVE_START) 3739 pt->corner = POINTTYPE_CURVE_MIDDLE; 3740 else 3741 pt->corner = POINTTYPE_CURVE_END; 3742 } 3743 outline->count--; 3744 } else { 3745 /* outline closed with a line from end to start point */ 3746 attempt_line_merge(outline, outline->count - 1, &pt->pos, FALSE); 3747 } 3748 lastpt = &outline->items[0]; 3749 to_curve = lastpt->corner != POINTTYPE_CORNER && lastpt->corner != POINTTYPE_CURVE_END; 3750 if (lastpt->corner == POINTTYPE_CURVE_START) 3751 lastpt->corner = POINTTYPE_CORNER; 3752 pt = &outline->items[1]; 3753 if (attempt_line_merge(outline, 0, &pt->pos, to_curve)) 3754 *lastpt = outline->items[outline->count]; 3755 } 3756 3757 lastpt = &outline->items[outline->count - 1]; 3758 pt = &outline->items[0]; 3759 unit_vec2(&lastdir, &lastpt->pos, &pt->pos); 3760 for (j = 0; j < outline->count; j++) 3761 { 3762 D3DXVECTOR2 curdir; 3763 3764 lastpt = pt; 3765 pt = &outline->items[(j + 1) % outline->count]; 3766 unit_vec2(&curdir, &lastpt->pos, &pt->pos); 3767 3768 switch (lastpt->corner) 3769 { 3770 case POINTTYPE_CURVE_START: 3771 case POINTTYPE_CURVE_END: 3772 if (!is_direction_similar(&lastdir, &curdir, cos_45)) 3773 lastpt->corner = POINTTYPE_CORNER; 3774 break; 3775 case POINTTYPE_CURVE_MIDDLE: 3776 if (!is_direction_similar(&lastdir, &curdir, cos_90)) 3777 lastpt->corner = POINTTYPE_CORNER; 3778 else 3779 lastpt->corner = POINTTYPE_CURVE; 3780 break; 3781 default: 3782 break; 3783 } 3784 lastdir = curdir; 3785 } 3786 3787 header = (TTPOLYGONHEADER *)((char *)header + header->cb); 3788 } 3789 return S_OK; 3790 } 3791 3792 static void free_outline(struct outline *outline) 3793 { 3794 HeapFree(GetProcessHeap(), 0, outline->items); 3795 } 3796 3797 static void free_glyphinfo(struct glyphinfo *glyph) 3798 { 3799 unsigned int i; 3800 3801 for (i = 0; i < glyph->outlines.count; ++i) 3802 free_outline(&glyph->outlines.items[i]); 3803 HeapFree(GetProcessHeap(), 0, glyph->outlines.items); 3804 } 3805 3806 static void compute_text_mesh(struct mesh *mesh, const char *text, 3807 float deviation, float extrusion, float otmEMSquare, const struct glyphinfo *glyphs) 3808 { 3809 DWORD nb_vertices, nb_faces; 3810 DWORD nb_corners, nb_outline_points; 3811 int textlen = 0; 3812 int i; 3813 struct vertex *vertex_ptr; 3814 face *face_ptr; 3815 3816 textlen = strlen(text); 3817 3818 /* corner points need an extra vertex for the different side faces normals */ 3819 nb_corners = 0; 3820 nb_outline_points = 0; 3821 for (i = 0; i < textlen; i++) 3822 { 3823 int j; 3824 for (j = 0; j < glyphs[i].outlines.count; j++) 3825 { 3826 int k; 3827 struct outline *outline = &glyphs[i].outlines.items[j]; 3828 nb_outline_points += outline->count; 3829 nb_corners++; /* first outline point always repeated as a corner */ 3830 for (k = 1; k < outline->count; k++) 3831 if (outline->items[k].corner) 3832 nb_corners++; 3833 } 3834 } 3835 3836 nb_vertices = (nb_outline_points + nb_corners) * 2 + textlen; 3837 nb_faces = nb_outline_points * 2; 3838 3839 ok(new_mesh(mesh, nb_vertices, nb_faces), "Failed to create reference text mesh.\n"); 3840 3841 /* convert 2D vertices and faces into 3D mesh */ 3842 vertex_ptr = mesh->vertices; 3843 face_ptr = mesh->faces; 3844 for (i = 0; i < textlen; i++) 3845 { 3846 int j; 3847 3848 /* side vertices and faces */ 3849 for (j = 0; j < glyphs[i].outlines.count; j++) 3850 { 3851 struct vertex *outline_vertices = vertex_ptr; 3852 struct outline *outline = &glyphs[i].outlines.items[j]; 3853 int k; 3854 struct point2d *prevpt = &outline->items[outline->count - 1]; 3855 struct point2d *pt = &outline->items[0]; 3856 3857 for (k = 1; k <= outline->count; k++) 3858 { 3859 struct vertex vtx; 3860 struct point2d *nextpt = &outline->items[k % outline->count]; 3861 WORD vtx_idx = vertex_ptr - mesh->vertices; 3862 D3DXVECTOR2 vec; 3863 3864 if (pt->corner == POINTTYPE_CURVE_START) 3865 D3DXVec2Subtract(&vec, &pt->pos, &prevpt->pos); 3866 else if (pt->corner) 3867 D3DXVec2Subtract(&vec, &nextpt->pos, &pt->pos); 3868 else 3869 D3DXVec2Subtract(&vec, &nextpt->pos, &prevpt->pos); 3870 D3DXVec2Normalize(&vec, &vec); 3871 vtx.normal.x = -vec.y; 3872 vtx.normal.y = vec.x; 3873 vtx.normal.z = 0; 3874 3875 vtx.position.x = pt->pos.x + glyphs[i].offset_x; 3876 vtx.position.y = pt->pos.y; 3877 vtx.position.z = 0; 3878 *vertex_ptr++ = vtx; 3879 3880 vtx.position.z = -extrusion; 3881 *vertex_ptr++ = vtx; 3882 3883 vtx.position.x = nextpt->pos.x + glyphs[i].offset_x; 3884 vtx.position.y = nextpt->pos.y; 3885 if (pt->corner && nextpt->corner && nextpt->corner != POINTTYPE_CURVE_END) { 3886 vtx.position.z = -extrusion; 3887 *vertex_ptr++ = vtx; 3888 vtx.position.z = 0; 3889 *vertex_ptr++ = vtx; 3890 3891 (*face_ptr)[0] = vtx_idx; 3892 (*face_ptr)[1] = vtx_idx + 2; 3893 (*face_ptr)[2] = vtx_idx + 1; 3894 face_ptr++; 3895 3896 (*face_ptr)[0] = vtx_idx; 3897 (*face_ptr)[1] = vtx_idx + 3; 3898 (*face_ptr)[2] = vtx_idx + 2; 3899 face_ptr++; 3900 } else { 3901 if (nextpt->corner) { 3902 if (nextpt->corner == POINTTYPE_CURVE_END) { 3903 struct point2d *nextpt2 = &outline->items[(k + 1) % outline->count]; 3904 D3DXVec2Subtract(&vec, &nextpt2->pos, &nextpt->pos); 3905 } else { 3906 D3DXVec2Subtract(&vec, &nextpt->pos, &pt->pos); 3907 } 3908 D3DXVec2Normalize(&vec, &vec); 3909 vtx.normal.x = -vec.y; 3910 vtx.normal.y = vec.x; 3911 3912 vtx.position.z = 0; 3913 *vertex_ptr++ = vtx; 3914 vtx.position.z = -extrusion; 3915 *vertex_ptr++ = vtx; 3916 } 3917 3918 (*face_ptr)[0] = vtx_idx; 3919 (*face_ptr)[1] = vtx_idx + 3; 3920 (*face_ptr)[2] = vtx_idx + 1; 3921 face_ptr++; 3922 3923 (*face_ptr)[0] = vtx_idx; 3924 (*face_ptr)[1] = vtx_idx + 2; 3925 (*face_ptr)[2] = vtx_idx + 3; 3926 face_ptr++; 3927 } 3928 3929 prevpt = pt; 3930 pt = nextpt; 3931 } 3932 if (!pt->corner) { 3933 *vertex_ptr++ = *outline_vertices++; 3934 *vertex_ptr++ = *outline_vertices++; 3935 } 3936 } 3937 3938 /* FIXME: compute expected faces */ 3939 /* Add placeholder to separate glyph outlines */ 3940 vertex_ptr->position.x = 0; 3941 vertex_ptr->position.y = 0; 3942 vertex_ptr->position.z = 0; 3943 vertex_ptr->normal.x = 0; 3944 vertex_ptr->normal.y = 0; 3945 vertex_ptr->normal.z = 1; 3946 vertex_ptr++; 3947 } 3948 } 3949 3950 static void compare_text_outline_mesh(const char *name, ID3DXMesh *d3dxmesh, struct mesh *mesh, 3951 size_t textlen, float extrusion, const struct glyphinfo *glyphs) 3952 { 3953 HRESULT hr; 3954 DWORD number_of_vertices, number_of_faces; 3955 IDirect3DVertexBuffer9 *vertex_buffer = NULL; 3956 IDirect3DIndexBuffer9 *index_buffer = NULL; 3957 D3DVERTEXBUFFER_DESC vertex_buffer_description; 3958 D3DINDEXBUFFER_DESC index_buffer_description; 3959 struct vertex *vertices = NULL; 3960 face *faces = NULL; 3961 int expected, i; 3962 int vtx_idx1, face_idx1, vtx_idx2, face_idx2; 3963 3964 number_of_vertices = d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh); 3965 number_of_faces = d3dxmesh->lpVtbl->GetNumFaces(d3dxmesh); 3966 3967 hr = d3dxmesh->lpVtbl->GetVertexBuffer(d3dxmesh, &vertex_buffer); 3968 ok(hr == D3D_OK, "Test %s, unexpected hr %#x.\n", name, hr); 3969 hr = IDirect3DVertexBuffer9_GetDesc(vertex_buffer, &vertex_buffer_description); 3970 ok(hr == D3D_OK, "Test %s, unexpected hr %#x.\n", name, hr); 3971 ok(vertex_buffer_description.Format == D3DFMT_VERTEXDATA, "Test %s, unexpected format %u.\n", 3972 name, vertex_buffer_description.Format); 3973 ok(vertex_buffer_description.Type == D3DRTYPE_VERTEXBUFFER, "Test %s, unexpected resource type %u.\n", 3974 name, vertex_buffer_description.Type); 3975 ok(!vertex_buffer_description.Usage, "Test %s, unexpected usage %#x.\n", name, vertex_buffer_description.Usage); 3976 ok(vertex_buffer_description.Pool == D3DPOOL_MANAGED, "Test %s, unexpected pool %u.\n", 3977 name, vertex_buffer_description.Pool); 3978 ok(vertex_buffer_description.FVF == mesh->fvf, "Test %s, unexpected FVF %#x (expected %#x).\n", 3979 name, vertex_buffer_description.FVF, mesh->fvf); 3980 if (!mesh->fvf) 3981 expected = number_of_vertices * mesh->vertex_size; 3982 else 3983 expected = number_of_vertices * D3DXGetFVFVertexSize(mesh->fvf); 3984 ok(vertex_buffer_description.Size == expected, "Test %s, unexpected size %u (expected %u).\n", 3985 name, vertex_buffer_description.Size, expected); 3986 3987 hr = d3dxmesh->lpVtbl->GetIndexBuffer(d3dxmesh, &index_buffer); 3988 ok(hr == D3D_OK, "Test %s, unexpected hr %#x.\n", name, hr); 3989 hr = IDirect3DIndexBuffer9_GetDesc(index_buffer, &index_buffer_description); 3990 ok(hr == D3D_OK, "Test %s, unexpected hr %#x.\n", name, hr); 3991 ok(index_buffer_description.Format == D3DFMT_INDEX16, "Test %s, unexpected format %u.\n", 3992 name, index_buffer_description.Format); 3993 ok(index_buffer_description.Type == D3DRTYPE_INDEXBUFFER, "Test %s, unexpected resource type %u.\n", 3994 name, index_buffer_description.Type); 3995 ok(!index_buffer_description.Usage, "Test %s, unexpected usage %#x.\n", 3996 name, index_buffer_description.Usage); 3997 ok(index_buffer_description.Pool == D3DPOOL_MANAGED, "Test %s, unexpected pool %u.\n", 3998 name, index_buffer_description.Pool); 3999 expected = number_of_faces * sizeof(WORD) * 3; 4000 ok(index_buffer_description.Size == expected, "Test %s, unexpected size %u.\n", 4001 name, index_buffer_description.Size); 4002 4003 hr = IDirect3DVertexBuffer9_Lock(vertex_buffer, 0, number_of_vertices * sizeof(D3DXVECTOR3) * 2, 4004 (void **)&vertices, D3DLOCK_DISCARD); 4005 ok(hr == D3D_OK, "Test %s, unexpected hr %#x.\n", name, hr); 4006 hr = IDirect3DIndexBuffer9_Lock(index_buffer, 0, number_of_faces * sizeof(WORD) * 3, 4007 (void **)&faces, D3DLOCK_DISCARD); 4008 ok(hr == D3D_OK, "Test %s, unexpected hr %#x.\n", name, hr); 4009 face_idx1 = 0; 4010 vtx_idx2 = 0; 4011 face_idx2 = 0; 4012 vtx_idx1 = 0; 4013 for (i = 0; i < textlen; i++) 4014 { 4015 int nb_outline_vertices1, nb_outline_faces1; 4016 int nb_outline_vertices2, nb_outline_faces2; 4017 int nb_back_vertices, nb_back_faces; 4018 int first_vtx1, first_vtx2; 4019 int first_face1, first_face2; 4020 int j; 4021 4022 first_vtx1 = vtx_idx1; 4023 first_vtx2 = vtx_idx2; 4024 /* Glyphs without outlines do not generate any vertices. */ 4025 if (glyphs[i].outlines.count > 0) 4026 { 4027 for (; vtx_idx1 < number_of_vertices; vtx_idx1++) 4028 { 4029 if (vertices[vtx_idx1].normal.z != 0) 4030 break; 4031 } 4032 4033 for (; vtx_idx2 < mesh->number_of_vertices; vtx_idx2++) 4034 { 4035 if (mesh->vertices[vtx_idx2].normal.z != 0) 4036 break; 4037 } 4038 } 4039 nb_outline_vertices1 = vtx_idx1 - first_vtx1; 4040 nb_outline_vertices2 = vtx_idx2 - first_vtx2; 4041 ok(nb_outline_vertices1 == nb_outline_vertices2, 4042 "Test %s, glyph %d, outline vertex count result %d, expected %d\n", name, i, 4043 nb_outline_vertices1, nb_outline_vertices2); 4044 4045 for (j = 0; j < min(nb_outline_vertices1, nb_outline_vertices2); j++) 4046 { 4047 vtx_idx1 = first_vtx1 + j; 4048 vtx_idx2 = first_vtx2 + j; 4049 ok(compare_vec3(vertices[vtx_idx1].position, mesh->vertices[vtx_idx2].position), 4050 "Test %s, glyph %d, vertex position %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1, 4051 vertices[vtx_idx1].position.x, vertices[vtx_idx1].position.y, vertices[vtx_idx1].position.z, 4052 mesh->vertices[vtx_idx2].position.x, mesh->vertices[vtx_idx2].position.y, mesh->vertices[vtx_idx2].position.z); 4053 ok(compare_vec3(vertices[vtx_idx1].normal, mesh->vertices[first_vtx2 + j].normal), 4054 "Test %s, glyph %d, vertex normal %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1, 4055 vertices[vtx_idx1].normal.x, vertices[vtx_idx1].normal.y, vertices[vtx_idx1].normal.z, 4056 mesh->vertices[vtx_idx2].normal.x, mesh->vertices[vtx_idx2].normal.y, mesh->vertices[vtx_idx2].normal.z); 4057 } 4058 vtx_idx1 = first_vtx1 + nb_outline_vertices1; 4059 vtx_idx2 = first_vtx2 + nb_outline_vertices2; 4060 4061 first_face1 = face_idx1; 4062 first_face2 = face_idx2; 4063 for (; face_idx1 < number_of_faces; face_idx1++) 4064 { 4065 if (faces[face_idx1][0] >= vtx_idx1 || 4066 faces[face_idx1][1] >= vtx_idx1 || 4067 faces[face_idx1][2] >= vtx_idx1) 4068 break; 4069 } 4070 for (; face_idx2 < mesh->number_of_faces; face_idx2++) 4071 { 4072 if (mesh->faces[face_idx2][0] >= vtx_idx2 || 4073 mesh->faces[face_idx2][1] >= vtx_idx2 || 4074 mesh->faces[face_idx2][2] >= vtx_idx2) 4075 break; 4076 } 4077 nb_outline_faces1 = face_idx1 - first_face1; 4078 nb_outline_faces2 = face_idx2 - first_face2; 4079 ok(nb_outline_faces1 == nb_outline_faces2, 4080 "Test %s, glyph %d, outline face count result %d, expected %d\n", name, i, 4081 nb_outline_faces1, nb_outline_faces2); 4082 4083 for (j = 0; j < min(nb_outline_faces1, nb_outline_faces2); j++) 4084 { 4085 face_idx1 = first_face1 + j; 4086 face_idx2 = first_face2 + j; 4087 ok(faces[face_idx1][0] - first_vtx1 == mesh->faces[face_idx2][0] - first_vtx2 && 4088 faces[face_idx1][1] - first_vtx1 == mesh->faces[face_idx2][1] - first_vtx2 && 4089 faces[face_idx1][2] - first_vtx1 == mesh->faces[face_idx2][2] - first_vtx2, 4090 "Test %s, glyph %d, face %d, result (%d, %d, %d), expected (%d, %d, %d)\n", name, i, face_idx1, 4091 faces[face_idx1][0], faces[face_idx1][1], faces[face_idx1][2], 4092 mesh->faces[face_idx2][0] - first_vtx2 + first_vtx1, 4093 mesh->faces[face_idx2][1] - first_vtx2 + first_vtx1, 4094 mesh->faces[face_idx2][2] - first_vtx2 + first_vtx1); 4095 } 4096 face_idx1 = first_face1 + nb_outline_faces1; 4097 face_idx2 = first_face2 + nb_outline_faces2; 4098 4099 /* partial test on back vertices and faces */ 4100 first_vtx1 = vtx_idx1; 4101 for (; vtx_idx1 < number_of_vertices; vtx_idx1++) { 4102 struct vertex vtx; 4103 4104 if (vertices[vtx_idx1].normal.z != 1.0f) 4105 break; 4106 4107 vtx.position.z = 0.0f; 4108 vtx.normal.x = 0.0f; 4109 vtx.normal.y = 0.0f; 4110 vtx.normal.z = 1.0f; 4111 ok(compare(vertices[vtx_idx1].position.z, vtx.position.z), 4112 "Test %s, glyph %d, vertex position.z %d, result %g, expected %g\n", name, i, vtx_idx1, 4113 vertices[vtx_idx1].position.z, vtx.position.z); 4114 ok(compare_vec3(vertices[vtx_idx1].normal, vtx.normal), 4115 "Test %s, glyph %d, vertex normal %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1, 4116 vertices[vtx_idx1].normal.x, vertices[vtx_idx1].normal.y, vertices[vtx_idx1].normal.z, 4117 vtx.normal.x, vtx.normal.y, vtx.normal.z); 4118 } 4119 nb_back_vertices = vtx_idx1 - first_vtx1; 4120 first_face1 = face_idx1; 4121 for (; face_idx1 < number_of_faces; face_idx1++) 4122 { 4123 const D3DXVECTOR3 *vtx1, *vtx2, *vtx3; 4124 D3DXVECTOR3 normal; 4125 D3DXVECTOR3 v1 = {0, 0, 0}; 4126 D3DXVECTOR3 v2 = {0, 0, 0}; 4127 D3DXVECTOR3 forward = {0.0f, 0.0f, 1.0f}; 4128 4129 if (faces[face_idx1][0] >= vtx_idx1 || 4130 faces[face_idx1][1] >= vtx_idx1 || 4131 faces[face_idx1][2] >= vtx_idx1) 4132 break; 4133 4134 vtx1 = &vertices[faces[face_idx1][0]].position; 4135 vtx2 = &vertices[faces[face_idx1][1]].position; 4136 vtx3 = &vertices[faces[face_idx1][2]].position; 4137 4138 D3DXVec3Subtract(&v1, vtx2, vtx1); 4139 D3DXVec3Subtract(&v2, vtx3, vtx2); 4140 D3DXVec3Cross(&normal, &v1, &v2); 4141 D3DXVec3Normalize(&normal, &normal); 4142 ok(!D3DXVec3Length(&normal) || compare_vec3(normal, forward), 4143 "Test %s, glyph %d, face %d normal, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, face_idx1, 4144 normal.x, normal.y, normal.z, forward.x, forward.y, forward.z); 4145 } 4146 nb_back_faces = face_idx1 - first_face1; 4147 4148 /* compare front and back faces & vertices */ 4149 if (extrusion == 0.0f) { 4150 /* Oddly there are only back faces in this case */ 4151 nb_back_vertices /= 2; 4152 nb_back_faces /= 2; 4153 face_idx1 -= nb_back_faces; 4154 vtx_idx1 -= nb_back_vertices; 4155 } 4156 for (j = 0; j < nb_back_vertices; j++) 4157 { 4158 struct vertex vtx = vertices[first_vtx1]; 4159 vtx.position.z = -extrusion; 4160 vtx.normal.x = 0.0f; 4161 vtx.normal.y = 0.0f; 4162 vtx.normal.z = extrusion == 0.0f ? 1.0f : -1.0f; 4163 ok(compare_vec3(vertices[vtx_idx1].position, vtx.position), 4164 "Test %s, glyph %d, vertex position %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1, 4165 vertices[vtx_idx1].position.x, vertices[vtx_idx1].position.y, vertices[vtx_idx1].position.z, 4166 vtx.position.x, vtx.position.y, vtx.position.z); 4167 ok(compare_vec3(vertices[vtx_idx1].normal, vtx.normal), 4168 "Test %s, glyph %d, vertex normal %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1, 4169 vertices[vtx_idx1].normal.x, vertices[vtx_idx1].normal.y, vertices[vtx_idx1].normal.z, 4170 vtx.normal.x, vtx.normal.y, vtx.normal.z); 4171 vtx_idx1++; 4172 first_vtx1++; 4173 } 4174 for (j = 0; j < nb_back_faces; j++) 4175 { 4176 int f1, f2; 4177 if (extrusion == 0.0f) { 4178 f1 = 1; 4179 f2 = 2; 4180 } else { 4181 f1 = 2; 4182 f2 = 1; 4183 } 4184 ok(faces[face_idx1][0] == faces[first_face1][0] + nb_back_vertices && 4185 faces[face_idx1][1] == faces[first_face1][f1] + nb_back_vertices && 4186 faces[face_idx1][2] == faces[first_face1][f2] + nb_back_vertices, 4187 "Test %s, glyph %d, face %d, result (%d, %d, %d), expected (%d, %d, %d)\n", name, i, face_idx1, 4188 faces[face_idx1][0], faces[face_idx1][1], faces[face_idx1][2], 4189 faces[first_face1][0] - nb_back_faces, 4190 faces[first_face1][f1] - nb_back_faces, 4191 faces[first_face1][f2] - nb_back_faces); 4192 first_face1++; 4193 face_idx1++; 4194 } 4195 4196 /* skip to the outline for the next glyph */ 4197 for (; vtx_idx2 < mesh->number_of_vertices; vtx_idx2++) { 4198 if (mesh->vertices[vtx_idx2].normal.z == 0) 4199 break; 4200 } 4201 for (; face_idx2 < mesh->number_of_faces; face_idx2++) 4202 { 4203 if (mesh->faces[face_idx2][0] >= vtx_idx2 || 4204 mesh->faces[face_idx2][1] >= vtx_idx2 || 4205 mesh->faces[face_idx2][2] >= vtx_idx2) break; 4206 } 4207 } 4208 4209 IDirect3DIndexBuffer9_Unlock(index_buffer); 4210 IDirect3DVertexBuffer9_Unlock(vertex_buffer); 4211 IDirect3DIndexBuffer9_Release(index_buffer); 4212 IDirect3DVertexBuffer9_Release(vertex_buffer); 4213 } 4214 4215 static void test_createtext(IDirect3DDevice9 *device, HDC hdc, const char *text, float deviation, float extrusion) 4216 { 4217 static const MAT2 identity = {{0, 1}, {0, 0}, {0, 0}, {0, 1}}; 4218 HRESULT hr; 4219 ID3DXMesh *d3dxmesh = NULL; 4220 struct mesh mesh = {0}; 4221 char name[256]; 4222 OUTLINETEXTMETRICA otm; 4223 GLYPHMETRICS gm; 4224 struct glyphinfo *glyphs; 4225 GLYPHMETRICSFLOAT *glyphmetrics_float = HeapAlloc(GetProcessHeap(), 0, sizeof(GLYPHMETRICSFLOAT) * strlen(text)); 4226 int i; 4227 LOGFONTA lf; 4228 float offset_x; 4229 size_t textlen; 4230 HFONT font = NULL, oldfont = NULL; 4231 char *raw_outline; 4232 4233 sprintf(name, "text ('%s', %f, %f)", text, deviation, extrusion); 4234 4235 hr = D3DXCreateTextA(device, hdc, text, deviation, extrusion, &d3dxmesh, NULL, glyphmetrics_float); 4236 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); 4237 4238 /* must select a modified font having lfHeight = otm.otmEMSquare before 4239 * calling GetGlyphOutline to get the expected values */ 4240 ok(GetObjectA(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf), "Failed to get current DC font.\n"); 4241 ok(GetOutlineTextMetricsA(hdc, sizeof(otm), &otm), "Failed to get DC font outline.\n"); 4242 lf.lfHeight = otm.otmEMSquare; 4243 lf.lfWidth = 0; 4244 ok(!!(font = CreateFontIndirectA(&lf)), "Failed to create font.\n"); 4245 4246 textlen = strlen(text); 4247 glyphs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, textlen * sizeof(*glyphs)); 4248 oldfont = SelectObject(hdc, font); 4249 4250 for (i = 0; i < textlen; i++) 4251 { 4252 GetGlyphOutlineA(hdc, text[i], GGO_NATIVE, &gm, 0, NULL, &identity); 4253 compare_float(glyphmetrics_float[i].gmfBlackBoxX, gm.gmBlackBoxX / (float)otm.otmEMSquare); 4254 compare_float(glyphmetrics_float[i].gmfBlackBoxY, gm.gmBlackBoxY / (float)otm.otmEMSquare); 4255 compare_float(glyphmetrics_float[i].gmfptGlyphOrigin.x, gm.gmptGlyphOrigin.x / (float)otm.otmEMSquare); 4256 compare_float(glyphmetrics_float[i].gmfptGlyphOrigin.y, gm.gmptGlyphOrigin.y / (float)otm.otmEMSquare); 4257 compare_float(glyphmetrics_float[i].gmfCellIncX, gm.gmCellIncX / (float)otm.otmEMSquare); 4258 compare_float(glyphmetrics_float[i].gmfCellIncY, gm.gmCellIncY / (float)otm.otmEMSquare); 4259 } 4260 4261 if (deviation == 0.0f) 4262 deviation = 1.0f / otm.otmEMSquare; 4263 4264 offset_x = 0.0f; 4265 for (i = 0; i < textlen; i++) 4266 { 4267 DWORD datasize; 4268 4269 glyphs[i].offset_x = offset_x; 4270 4271 datasize = GetGlyphOutlineA(hdc, text[i], GGO_NATIVE, &gm, 0, NULL, &identity); 4272 ok(datasize != GDI_ERROR, "Failed to retrieve GDI glyph outline size.\n"); 4273 raw_outline = HeapAlloc(GetProcessHeap(), 0, datasize); 4274 datasize = GetGlyphOutlineA(hdc, text[i], GGO_NATIVE, &gm, datasize, raw_outline, &identity); 4275 ok(datasize != GDI_ERROR, "Failed to retrieve GDI glyph outline.\n"); 4276 create_outline(&glyphs[i], raw_outline, datasize, deviation, otm.otmEMSquare); 4277 HeapFree(GetProcessHeap(), 0, raw_outline); 4278 4279 offset_x += gm.gmCellIncX / (float)otm.otmEMSquare; 4280 } 4281 4282 SelectObject(hdc, oldfont); 4283 4284 compute_text_mesh(&mesh, text, deviation, extrusion, otm.otmEMSquare, glyphs); 4285 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL; 4286 4287 compare_text_outline_mesh(name, d3dxmesh, &mesh, textlen, extrusion, glyphs); 4288 4289 free_mesh(&mesh); 4290 d3dxmesh->lpVtbl->Release(d3dxmesh); 4291 DeleteObject(font); 4292 HeapFree(GetProcessHeap(), 0, glyphmetrics_float); 4293 4294 for (i = 0; i < textlen; i++) 4295 free_glyphinfo(&glyphs[i]); 4296 HeapFree(GetProcessHeap(), 0, glyphs); 4297 } 4298 4299 static void D3DXCreateTextTest(void) 4300 { 4301 HRESULT hr; 4302 HDC hdc; 4303 IDirect3DDevice9* device; 4304 ID3DXMesh* d3dxmesh = NULL; 4305 HFONT hFont; 4306 OUTLINETEXTMETRICA otm; 4307 int number_of_vertices; 4308 int number_of_faces; 4309 struct test_context *test_context; 4310 4311 if (!(test_context = new_test_context())) 4312 { 4313 skip("Couldn't create test context\n"); 4314 return; 4315 } 4316 device = test_context->device; 4317 4318 hdc = CreateCompatibleDC(NULL); 4319 4320 hFont = CreateFontA(12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, 4321 CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, "Arial"); 4322 SelectObject(hdc, hFont); 4323 GetOutlineTextMetricsA(hdc, sizeof(otm), &otm); 4324 4325 hr = D3DXCreateTextA(device, hdc, "wine", 0.001f, 0.4f, NULL, NULL, NULL); 4326 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 4327 4328 /* D3DXCreateTextA page faults from passing NULL text */ 4329 4330 hr = D3DXCreateTextW(device, hdc, NULL, 0.001f, 0.4f, &d3dxmesh, NULL, NULL); 4331 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 4332 4333 hr = D3DXCreateTextA(device, hdc, "", 0.001f, 0.4f, &d3dxmesh, NULL, NULL); 4334 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 4335 4336 hr = D3DXCreateTextA(device, hdc, " ", 0.001f, 0.4f, &d3dxmesh, NULL, NULL); 4337 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 4338 4339 hr = D3DXCreateTextA(NULL, hdc, "wine", 0.001f, 0.4f, &d3dxmesh, NULL, NULL); 4340 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 4341 4342 hr = D3DXCreateTextA(device, NULL, "wine", 0.001f, 0.4f, &d3dxmesh, NULL, NULL); 4343 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 4344 4345 hr = D3DXCreateTextA(device, hdc, "wine", -FLT_MIN, 0.4f, &d3dxmesh, NULL, NULL); 4346 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 4347 4348 hr = D3DXCreateTextA(device, hdc, "wine", 0.001f, -FLT_MIN, &d3dxmesh, NULL, NULL); 4349 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 4350 4351 /* deviation = 0.0f treated as if deviation = 1.0f / otm.otmEMSquare */ 4352 hr = D3DXCreateTextA(device, hdc, "wine", 1.0f / otm.otmEMSquare, 0.4f, &d3dxmesh, NULL, NULL); 4353 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK); 4354 number_of_vertices = d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh); 4355 number_of_faces = d3dxmesh->lpVtbl->GetNumFaces(d3dxmesh); 4356 d3dxmesh->lpVtbl->Release(d3dxmesh); 4357 4358 hr = D3DXCreateTextA(device, hdc, "wine", 0.0f, 0.4f, &d3dxmesh, NULL, NULL); 4359 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK); 4360 ok(number_of_vertices == d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh), 4361 "Got %d vertices, expected %d\n", 4362 d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh), number_of_vertices); 4363 ok(number_of_faces == d3dxmesh->lpVtbl->GetNumFaces(d3dxmesh), 4364 "Got %d faces, expected %d\n", 4365 d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh), number_of_faces); 4366 d3dxmesh->lpVtbl->Release(d3dxmesh); 4367 4368 if (0) 4369 { 4370 /* too much detail requested, so will appear to hang */ 4371 trace("Waiting for D3DXCreateText to finish with deviation = FLT_MIN ...\n"); 4372 hr = D3DXCreateTextA(device, hdc, "wine", FLT_MIN, 0.4f, &d3dxmesh, NULL, NULL); 4373 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK); 4374 if (SUCCEEDED(hr) && d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh); 4375 trace("D3DXCreateText finish with deviation = FLT_MIN\n"); 4376 } 4377 4378 hr = D3DXCreateTextA(device, hdc, "wine", 0.001f, 0.4f, &d3dxmesh, NULL, NULL); 4379 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK); 4380 if (SUCCEEDED(hr) && d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh); 4381 4382 test_createtext(device, hdc, "wine", FLT_MAX, 0.4f); 4383 test_createtext(device, hdc, "wine", 0.001f, FLT_MIN); 4384 test_createtext(device, hdc, "wine", 0.001f, 0.0f); 4385 test_createtext(device, hdc, "wine", 0.001f, FLT_MAX); 4386 test_createtext(device, hdc, "wine", 0.0f, 1.0f); 4387 test_createtext(device, hdc, " wine", 1.0f, 0.0f); 4388 test_createtext(device, hdc, "wine ", 1.0f, 0.0f); 4389 test_createtext(device, hdc, "wi ne", 1.0f, 0.0f); 4390 4391 DeleteDC(hdc); 4392 DeleteObject(hFont); 4393 4394 free_test_context(test_context); 4395 } 4396 4397 static void test_get_decl_length(void) 4398 { 4399 static const D3DVERTEXELEMENT9 declaration1[] = 4400 { 4401 {0, 0, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4402 {1, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4403 {2, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4404 {3, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4405 {4, 0, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4406 {5, 0, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4407 {6, 0, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4408 {7, 0, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4409 {8, 0, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4410 {9, 0, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4411 {10, 0, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4412 {11, 0, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4413 {12, 0, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4414 {13, 0, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4415 {14, 0, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4416 D3DDECL_END(), 4417 }; 4418 static const D3DVERTEXELEMENT9 declaration2[] = 4419 { 4420 {0, 8, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4421 {1, 8, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4422 {2, 8, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4423 {3, 8, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4424 {4, 8, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4425 {5, 8, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4426 {6, 8, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4427 {7, 8, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4428 {0, 8, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4429 {1, 8, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4430 {2, 8, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4431 {3, 8, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4432 {4, 8, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4433 {5, 8, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4434 {6, 8, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4435 {7, 8, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4436 D3DDECL_END(), 4437 }; 4438 UINT size; 4439 4440 size = D3DXGetDeclLength(declaration1); 4441 ok(size == 15, "Got size %u, expected 15.\n", size); 4442 4443 size = D3DXGetDeclLength(declaration2); 4444 ok(size == 16, "Got size %u, expected 16.\n", size); 4445 } 4446 4447 static void test_get_decl_vertex_size(void) 4448 { 4449 static const D3DVERTEXELEMENT9 declaration1[] = 4450 { 4451 {0, 0, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4452 {1, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4453 {2, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4454 {3, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4455 {4, 0, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4456 {5, 0, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4457 {6, 0, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4458 {7, 0, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4459 {8, 0, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4460 {9, 0, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4461 {10, 0, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4462 {11, 0, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4463 {12, 0, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4464 {13, 0, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4465 {14, 0, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4466 D3DDECL_END(), 4467 }; 4468 static const D3DVERTEXELEMENT9 declaration2[] = 4469 { 4470 {0, 8, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4471 {1, 8, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4472 {2, 8, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4473 {3, 8, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4474 {4, 8, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4475 {5, 8, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4476 {6, 8, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4477 {7, 8, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4478 {0, 8, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4479 {1, 8, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4480 {2, 8, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4481 {3, 8, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4482 {4, 8, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4483 {5, 8, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4484 {6, 8, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4485 {7, 8, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4486 D3DDECL_END(), 4487 }; 4488 static const UINT sizes1[] = 4489 { 4490 4, 8, 12, 16, 4491 4, 4, 4, 8, 4492 4, 4, 8, 4, 4493 4, 4, 8, 0, 4494 }; 4495 static const UINT sizes2[] = 4496 { 4497 12, 16, 20, 24, 4498 12, 12, 16, 16, 4499 }; 4500 unsigned int i; 4501 UINT size; 4502 4503 size = D3DXGetDeclVertexSize(NULL, 0); 4504 ok(size == 0, "Got size %#x, expected 0.\n", size); 4505 4506 for (i = 0; i < 16; ++i) 4507 { 4508 size = D3DXGetDeclVertexSize(declaration1, i); 4509 ok(size == sizes1[i], "Got size %u for stream %u, expected %u.\n", size, i, sizes1[i]); 4510 } 4511 4512 for (i = 0; i < 8; ++i) 4513 { 4514 size = D3DXGetDeclVertexSize(declaration2, i); 4515 ok(size == sizes2[i], "Got size %u for stream %u, expected %u.\n", size, i, sizes2[i]); 4516 } 4517 } 4518 4519 static void D3DXGenerateAdjacencyTest(void) 4520 { 4521 HRESULT hr; 4522 IDirect3DDevice9 *device; 4523 ID3DXMesh *d3dxmesh = NULL; 4524 D3DXVECTOR3 *vertices = NULL; 4525 WORD *indices = NULL; 4526 int i; 4527 struct { 4528 DWORD num_vertices; 4529 D3DXVECTOR3 vertices[6]; 4530 DWORD num_faces; 4531 WORD indices[3 * 3]; 4532 FLOAT epsilon; 4533 DWORD adjacency[3 * 3]; 4534 } test_data[] = { 4535 { /* for epsilon < 0, indices must match for faces to be adjacent */ 4536 4, {{0.0, 0.0, 0.0}, {1.0, 0.0, 0.0}, {1.0, 1.0, 0.0}, {0.0, 1.0, 0.0}}, 4537 2, {0, 1, 2, 0, 2, 3}, 4538 -1.0, 4539 {-1, -1, 1, 0, -1, -1}, 4540 }, 4541 { 4542 6, {{0.0, 0.0, 0.0}, {1.0, 0.0, 0.0}, {1.0, 1.0, 0.0}, {0.0, 0.0, 0.0}, {1.0, 1.0, 0.0}, {0.0, 1.0, 0.0}}, 4543 2, {0, 1, 2, 3, 4, 5}, 4544 -1.0, 4545 {-1, -1, -1, -1, -1, -1}, 4546 }, 4547 { /* for epsilon == 0, indices or vertices must match for faces to be adjacent */ 4548 6, {{0.0, 0.0, 0.0}, {1.0, 0.0, 0.0}, {1.0, 1.0, 0.0}, {0.0, 0.0, 0.0}, {1.0, 1.0, 0.0}, {0.0, 1.0, 0.0}}, 4549 2, {0, 1, 2, 3, 4, 5}, 4550 0.0, 4551 {-1, -1, 1, 0, -1, -1}, 4552 }, 4553 { /* for epsilon > 0, vertices must be less than (but NOT equal to) epsilon distance away */ 4554 6, {{0.0, 0.0, 0.0}, {1.0, 0.0, 0.0}, {1.0, 1.0, 0.0}, {0.0, 0.0, 0.25}, {1.0, 1.0, 0.25}, {0.0, 1.0, 0.25}}, 4555 2, {0, 1, 2, 3, 4, 5}, 4556 0.25, 4557 {-1, -1, -1, -1, -1, -1}, 4558 }, 4559 { /* for epsilon > 0, vertices must be less than (but NOT equal to) epsilon distance away */ 4560 6, {{0.0, 0.0, 0.0}, {1.0, 0.0, 0.0}, {1.0, 1.0, 0.0}, {0.0, 0.0, 0.25}, {1.0, 1.0, 0.25}, {0.0, 1.0, 0.25}}, 4561 2, {0, 1, 2, 3, 4, 5}, 4562 0.250001, 4563 {-1, -1, 1, 0, -1, -1}, 4564 }, 4565 { /* length between vertices are compared to epsilon, not the individual dimension deltas */ 4566 6, {{0.0, 0.0, 0.0}, {1.0, 0.0, 0.0}, {1.0, 1.0, 0.0}, {0.0, 0.25, 0.25}, {1.0, 1.25, 0.25}, {0.0, 1.25, 0.25}}, 4567 2, {0, 1, 2, 3, 4, 5}, 4568 0.353, /* < sqrt(0.25*0.25 + 0.25*0.25) */ 4569 {-1, -1, -1, -1, -1, -1}, 4570 }, 4571 { 4572 6, {{0.0, 0.0, 0.0}, {1.0, 0.0, 0.0}, {1.0, 1.0, 0.0}, {0.0, 0.25, 0.25}, {1.0, 1.25, 0.25}, {0.0, 1.25, 0.25}}, 4573 2, {0, 1, 2, 3, 4, 5}, 4574 0.354, /* > sqrt(0.25*0.25 + 0.25*0.25) */ 4575 {-1, -1, 1, 0, -1, -1}, 4576 }, 4577 { /* adjacent faces must have opposite winding orders at the shared edge */ 4578 4, {{0.0, 0.0, 0.0}, {1.0, 0.0, 0.0}, {1.0, 1.0, 0.0}, {0.0, 1.0, 0.0}}, 4579 2, {0, 1, 2, 0, 3, 2}, 4580 0.0, 4581 {-1, -1, -1, -1, -1, -1}, 4582 }, 4583 }; 4584 struct test_context *test_context; 4585 4586 if (!(test_context = new_test_context())) 4587 { 4588 skip("Couldn't create test context\n"); 4589 return; 4590 } 4591 device = test_context->device; 4592 4593 for (i = 0; i < ARRAY_SIZE(test_data); i++) 4594 { 4595 DWORD adjacency[ARRAY_SIZE(test_data[0].adjacency)]; 4596 int j; 4597 4598 if (d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh); 4599 d3dxmesh = NULL; 4600 4601 hr = D3DXCreateMeshFVF(test_data[i].num_faces, test_data[i].num_vertices, 0, D3DFVF_XYZ, device, &d3dxmesh); 4602 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK); 4603 4604 hr = d3dxmesh->lpVtbl->LockVertexBuffer(d3dxmesh, D3DLOCK_DISCARD, (void**)&vertices); 4605 ok(hr == D3D_OK, "test %d: Got result %x, expected %x (D3D_OK)\n", i, hr, D3D_OK); 4606 if (FAILED(hr)) continue; 4607 CopyMemory(vertices, test_data[i].vertices, test_data[i].num_vertices * sizeof(test_data[0].vertices[0])); 4608 d3dxmesh->lpVtbl->UnlockVertexBuffer(d3dxmesh); 4609 4610 hr = d3dxmesh->lpVtbl->LockIndexBuffer(d3dxmesh, D3DLOCK_DISCARD, (void**)&indices); 4611 ok(hr == D3D_OK, "test %d: Got result %x, expected %x (D3D_OK)\n", i, hr, D3D_OK); 4612 if (FAILED(hr)) continue; 4613 CopyMemory(indices, test_data[i].indices, test_data[i].num_faces * 3 * sizeof(test_data[0].indices[0])); 4614 d3dxmesh->lpVtbl->UnlockIndexBuffer(d3dxmesh); 4615 4616 if (i == 0) { 4617 hr = d3dxmesh->lpVtbl->GenerateAdjacency(d3dxmesh, 0.0f, NULL); 4618 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 4619 } 4620 4621 hr = d3dxmesh->lpVtbl->GenerateAdjacency(d3dxmesh, test_data[i].epsilon, adjacency); 4622 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK); 4623 if (FAILED(hr)) continue; 4624 4625 for (j = 0; j < test_data[i].num_faces * 3; j++) 4626 ok(adjacency[j] == test_data[i].adjacency[j], 4627 "Test %d adjacency %d: Got result %u, expected %u\n", i, j, 4628 adjacency[j], test_data[i].adjacency[j]); 4629 } 4630 if (d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh); 4631 4632 free_test_context(test_context); 4633 } 4634 4635 static void test_update_semantics(void) 4636 { 4637 HRESULT hr; 4638 struct test_context *test_context = NULL; 4639 ID3DXMesh *mesh = NULL; 4640 D3DVERTEXELEMENT9 declaration0[] = 4641 { 4642 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4643 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 4644 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0}, 4645 D3DDECL_END() 4646 }; 4647 D3DVERTEXELEMENT9 declaration_pos_type_color[] = 4648 { 4649 {0, 0, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4650 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 4651 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0}, 4652 D3DDECL_END() 4653 }; 4654 D3DVERTEXELEMENT9 declaration_smaller[] = 4655 { 4656 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4657 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 4658 D3DDECL_END() 4659 }; 4660 D3DVERTEXELEMENT9 declaration_larger[] = 4661 { 4662 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4663 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 4664 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0}, 4665 {0, 40, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT, 0}, 4666 D3DDECL_END() 4667 }; 4668 D3DVERTEXELEMENT9 declaration_multiple_streams[] = 4669 { 4670 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4671 {1, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT, 0}, 4672 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 4673 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0}, 4674 4675 D3DDECL_END() 4676 }; 4677 D3DVERTEXELEMENT9 declaration_double_usage[] = 4678 { 4679 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4680 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4681 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 4682 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0}, 4683 D3DDECL_END() 4684 }; 4685 D3DVERTEXELEMENT9 declaration_undefined_type[] = 4686 { 4687 {0, 0, D3DDECLTYPE_UNUSED+1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4688 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 4689 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0}, 4690 D3DDECL_END() 4691 }; 4692 D3DVERTEXELEMENT9 declaration_not_4_byte_aligned_offset[] = 4693 { 4694 {0, 3, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4695 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 4696 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0}, 4697 D3DDECL_END() 4698 }; 4699 static const struct 4700 { 4701 D3DXVECTOR3 position0; 4702 D3DXVECTOR3 position1; 4703 D3DXVECTOR3 normal; 4704 DWORD color; 4705 } 4706 vertices[] = 4707 { 4708 { { 0.0f, 1.0f, 0.f}, { 1.0f, 0.0f, 0.f}, {0.0f, 0.0f, 1.0f}, 0xffff0000 }, 4709 { { 1.0f, -1.0f, 0.f}, {-1.0f, -1.0f, 0.f}, {0.0f, 0.0f, 1.0f}, 0xff00ff00 }, 4710 { {-1.0f, -1.0f, 0.f}, {-1.0f, 1.0f, 0.f}, {0.0f, 0.0f, 1.0f}, 0xff0000ff }, 4711 }; 4712 unsigned int faces[] = {0, 1, 2}; 4713 unsigned int attributes[] = {0}; 4714 unsigned int num_faces = ARRAY_SIZE(faces) / 3; 4715 unsigned int num_vertices = ARRAY_SIZE(vertices); 4716 int offset = sizeof(D3DXVECTOR3); 4717 DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM; 4718 void *vertex_buffer; 4719 void *index_buffer; 4720 DWORD *attributes_buffer; 4721 D3DVERTEXELEMENT9 declaration[MAX_FVF_DECL_SIZE]; 4722 D3DVERTEXELEMENT9 *decl_ptr; 4723 DWORD exp_vertex_size = sizeof(*vertices); 4724 DWORD vertex_size = 0; 4725 int equal; 4726 int i = 0; 4727 int *decl_mem; 4728 int filler_a = 0xaaaaaaaa; 4729 int filler_b = 0xbbbbbbbb; 4730 4731 test_context = new_test_context(); 4732 if (!test_context) 4733 { 4734 skip("Couldn't create a test_context\n"); 4735 goto cleanup; 4736 } 4737 4738 hr = D3DXCreateMesh(num_faces, num_vertices, options, declaration0, 4739 test_context->device, &mesh); 4740 if (FAILED(hr)) 4741 { 4742 skip("Couldn't create test mesh %#x\n", hr); 4743 goto cleanup; 4744 } 4745 4746 mesh->lpVtbl->LockVertexBuffer(mesh, 0, &vertex_buffer); 4747 memcpy(vertex_buffer, vertices, sizeof(vertices)); 4748 mesh->lpVtbl->UnlockVertexBuffer(mesh); 4749 4750 mesh->lpVtbl->LockIndexBuffer(mesh, 0, &index_buffer); 4751 memcpy(index_buffer, faces, sizeof(faces)); 4752 mesh->lpVtbl->UnlockIndexBuffer(mesh); 4753 4754 mesh->lpVtbl->LockAttributeBuffer(mesh, 0, &attributes_buffer); 4755 memcpy(attributes_buffer, attributes, sizeof(attributes)); 4756 mesh->lpVtbl->UnlockAttributeBuffer(mesh); 4757 4758 /* Get the declaration and try to change it */ 4759 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration); 4760 if (FAILED(hr)) 4761 { 4762 skip("Couldn't get vertex declaration %#x\n", hr); 4763 goto cleanup; 4764 } 4765 equal = memcmp(declaration, declaration0, sizeof(declaration0)); 4766 ok(equal == 0, "Vertex declarations were not equal\n"); 4767 4768 for (decl_ptr = declaration; decl_ptr->Stream != 0xFF; decl_ptr++) 4769 { 4770 if (decl_ptr->Usage == D3DDECLUSAGE_POSITION) 4771 { 4772 /* Use second vertex position instead of first */ 4773 decl_ptr->Offset = offset; 4774 } 4775 } 4776 4777 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration); 4778 ok(hr == D3D_OK, "Test UpdateSemantics, got %#x expected %#x\n", hr, D3D_OK); 4779 4780 /* Check that declaration was written by getting it again */ 4781 memset(declaration, 0, sizeof(declaration)); 4782 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration); 4783 if (FAILED(hr)) 4784 { 4785 skip("Couldn't get vertex declaration %#x\n", hr); 4786 goto cleanup; 4787 } 4788 4789 for (decl_ptr = declaration; decl_ptr->Stream != 0xFF; decl_ptr++) 4790 { 4791 if (decl_ptr->Usage == D3DDECLUSAGE_POSITION) 4792 { 4793 ok(decl_ptr->Offset == offset, "Test UpdateSemantics, got offset %d expected %d\n", 4794 decl_ptr->Offset, offset); 4795 } 4796 } 4797 4798 /* Check that GetDeclaration only writes up to the D3DDECL_END() marker and 4799 * not the full MAX_FVF_DECL_SIZE elements. 4800 */ 4801 memset(declaration, filler_a, sizeof(declaration)); 4802 memcpy(declaration, declaration0, sizeof(declaration0)); 4803 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration); 4804 ok(hr == D3D_OK, "Test UpdateSemantics, " 4805 "got %#x expected D3D_OK\n", hr); 4806 memset(declaration, filler_b, sizeof(declaration)); 4807 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration); 4808 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr); 4809 decl_mem = (int*)declaration; 4810 for (i = sizeof(declaration0)/sizeof(*decl_mem); i < sizeof(declaration)/sizeof(*decl_mem); i++) 4811 { 4812 equal = memcmp(&decl_mem[i], &filler_b, sizeof(filler_b)); 4813 ok(equal == 0, 4814 "GetDeclaration wrote past the D3DDECL_END() marker. " 4815 "Got %#x, expected %#x\n", decl_mem[i], filler_b); 4816 if (equal != 0) break; 4817 } 4818 4819 /* UpdateSemantics does not check for overlapping fields */ 4820 memset(declaration, 0, sizeof(declaration)); 4821 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration); 4822 if (FAILED(hr)) 4823 { 4824 skip("Couldn't get vertex declaration %#x\n", hr); 4825 goto cleanup; 4826 } 4827 4828 for (decl_ptr = declaration; decl_ptr->Stream != 0xFF; decl_ptr++) 4829 { 4830 if (decl_ptr->Type == D3DDECLTYPE_FLOAT3) 4831 { 4832 decl_ptr->Type = D3DDECLTYPE_FLOAT4; 4833 } 4834 } 4835 4836 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration); 4837 ok(hr == D3D_OK, "Test UpdateSemantics for overlapping fields, " 4838 "got %#x expected D3D_OK\n", hr); 4839 4840 /* Set the position type to color instead of float3 */ 4841 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_pos_type_color); 4842 ok(hr == D3D_OK, "Test UpdateSemantics position type color, " 4843 "got %#x expected D3D_OK\n", hr); 4844 4845 /* The following test cases show that NULL, smaller or larger declarations, 4846 * and declarations with non-zero Stream values are not accepted. 4847 * UpdateSemantics returns D3DERR_INVALIDCALL and the previously set 4848 * declaration will be used by DrawSubset, GetNumBytesPerVertex, and 4849 * GetDeclaration. 4850 */ 4851 4852 /* Null declaration (invalid declaration) */ 4853 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */ 4854 hr = mesh->lpVtbl->UpdateSemantics(mesh, NULL); 4855 ok(hr == D3DERR_INVALIDCALL, "Test UpdateSemantics null pointer declaration, " 4856 "got %#x expected D3DERR_INVALIDCALL\n", hr); 4857 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh); 4858 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n", 4859 vertex_size, exp_vertex_size); 4860 memset(declaration, 0, sizeof(declaration)); 4861 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration); 4862 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr); 4863 equal = memcmp(declaration, declaration0, sizeof(declaration0)); 4864 ok(equal == 0, "Vertex declarations were not equal\n"); 4865 4866 /* Smaller vertex declaration (invalid declaration) */ 4867 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */ 4868 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_smaller); 4869 ok(hr == D3DERR_INVALIDCALL, "Test UpdateSemantics for smaller vertex declaration, " 4870 "got %#x expected D3DERR_INVALIDCALL\n", hr); 4871 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh); 4872 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n", 4873 vertex_size, exp_vertex_size); 4874 memset(declaration, 0, sizeof(declaration)); 4875 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration); 4876 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr); 4877 equal = memcmp(declaration, declaration0, sizeof(declaration0)); 4878 ok(equal == 0, "Vertex declarations were not equal\n"); 4879 4880 /* Larger vertex declaration (invalid declaration) */ 4881 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */ 4882 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_larger); 4883 ok(hr == D3DERR_INVALIDCALL, "Test UpdateSemantics for larger vertex declaration, " 4884 "got %#x expected D3DERR_INVALIDCALL\n", hr); 4885 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh); 4886 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n", 4887 vertex_size, exp_vertex_size); 4888 memset(declaration, 0, sizeof(declaration)); 4889 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration); 4890 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr); 4891 equal = memcmp(declaration, declaration0, sizeof(declaration0)); 4892 ok(equal == 0, "Vertex declarations were not equal\n"); 4893 4894 /* Use multiple streams and keep the same vertex size (invalid declaration) */ 4895 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */ 4896 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_multiple_streams); 4897 ok(hr == D3DERR_INVALIDCALL, "Test UpdateSemantics using multiple streams, " 4898 "got %#x expected D3DERR_INVALIDCALL\n", hr); 4899 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh); 4900 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n", 4901 vertex_size, exp_vertex_size); 4902 memset(declaration, 0, sizeof(declaration)); 4903 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration); 4904 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr); 4905 equal = memcmp(declaration, declaration0, sizeof(declaration0)); 4906 ok(equal == 0, "Vertex declarations were not equal\n"); 4907 4908 /* The next following test cases show that some invalid declarations are 4909 * accepted with a D3D_OK. An access violation is thrown on Windows if 4910 * DrawSubset is called. The methods GetNumBytesPerVertex and GetDeclaration 4911 * are not affected, which indicates that the declaration is cached. 4912 */ 4913 4914 /* Double usage (invalid declaration) */ 4915 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */ 4916 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_double_usage); 4917 ok(hr == D3D_OK, "Test UpdateSemantics double usage, " 4918 "got %#x expected D3D_OK\n", hr); 4919 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh); 4920 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n", 4921 vertex_size, exp_vertex_size); 4922 memset(declaration, 0, sizeof(declaration)); 4923 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration); 4924 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr); 4925 equal = memcmp(declaration, declaration_double_usage, sizeof(declaration_double_usage)); 4926 ok(equal == 0, "Vertex declarations were not equal\n"); 4927 4928 /* Set the position to an undefined type (invalid declaration) */ 4929 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */ 4930 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_undefined_type); 4931 ok(hr == D3D_OK, "Test UpdateSemantics undefined type, " 4932 "got %#x expected D3D_OK\n", hr); 4933 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh); 4934 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n", 4935 vertex_size, exp_vertex_size); 4936 memset(declaration, 0, sizeof(declaration)); 4937 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration); 4938 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr); 4939 equal = memcmp(declaration, declaration_undefined_type, sizeof(declaration_undefined_type)); 4940 ok(equal == 0, "Vertex declarations were not equal\n"); 4941 4942 /* Use a not 4 byte aligned offset (invalid declaration) */ 4943 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */ 4944 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_not_4_byte_aligned_offset); 4945 ok(hr == D3D_OK, "Test UpdateSemantics not 4 byte aligned offset, " 4946 "got %#x expected D3D_OK\n", hr); 4947 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh); 4948 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n", 4949 vertex_size, exp_vertex_size); 4950 memset(declaration, 0, sizeof(declaration)); 4951 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration); 4952 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr); 4953 equal = memcmp(declaration, declaration_not_4_byte_aligned_offset, 4954 sizeof(declaration_not_4_byte_aligned_offset)); 4955 ok(equal == 0, "Vertex declarations were not equal\n"); 4956 4957 cleanup: 4958 if (mesh) 4959 mesh->lpVtbl->Release(mesh); 4960 4961 free_test_context(test_context); 4962 } 4963 4964 static void test_create_skin_info(void) 4965 { 4966 HRESULT hr; 4967 ID3DXSkinInfo *skininfo = NULL; 4968 D3DVERTEXELEMENT9 empty_declaration[] = { D3DDECL_END() }; 4969 D3DVERTEXELEMENT9 declaration_out[MAX_FVF_DECL_SIZE]; 4970 const D3DVERTEXELEMENT9 declaration_with_nonzero_stream[] = { 4971 {1, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 4972 D3DDECL_END() 4973 }; 4974 4975 hr = D3DXCreateSkinInfo(0, empty_declaration, 0, &skininfo); 4976 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 4977 if (skininfo) IUnknown_Release(skininfo); 4978 skininfo = NULL; 4979 4980 hr = D3DXCreateSkinInfo(1, NULL, 1, &skininfo); 4981 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 4982 4983 hr = D3DXCreateSkinInfo(1, declaration_with_nonzero_stream, 1, &skininfo); 4984 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 4985 4986 hr = D3DXCreateSkinInfoFVF(1, 0, 1, &skininfo); 4987 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 4988 if (skininfo) 4989 { 4990 DWORD dword_result; 4991 float flt_result; 4992 const char *string_result; 4993 D3DXMATRIX *transform; 4994 D3DXMATRIX identity_matrix; 4995 4996 /* test initial values */ 4997 hr = skininfo->lpVtbl->GetDeclaration(skininfo, declaration_out); 4998 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 4999 if (SUCCEEDED(hr)) 5000 compare_elements(declaration_out, empty_declaration, __LINE__, 0); 5001 5002 dword_result = skininfo->lpVtbl->GetNumBones(skininfo); 5003 ok(dword_result == 1, "Expected 1, got %u\n", dword_result); 5004 5005 flt_result = skininfo->lpVtbl->GetMinBoneInfluence(skininfo); 5006 ok(flt_result == 0.0f, "Expected 0.0, got %g\n", flt_result); 5007 5008 string_result = skininfo->lpVtbl->GetBoneName(skininfo, 0); 5009 ok(string_result == NULL, "Expected NULL, got %p\n", string_result); 5010 5011 dword_result = skininfo->lpVtbl->GetFVF(skininfo); 5012 ok(dword_result == 0, "Expected 0, got %u\n", dword_result); 5013 5014 dword_result = skininfo->lpVtbl->GetNumBoneInfluences(skininfo, 0); 5015 ok(dword_result == 0, "Expected 0, got %u\n", dword_result); 5016 5017 dword_result = skininfo->lpVtbl->GetNumBoneInfluences(skininfo, 1); 5018 ok(dword_result == 0, "Expected 0, got %u\n", dword_result); 5019 5020 transform = skininfo->lpVtbl->GetBoneOffsetMatrix(skininfo, -1); 5021 ok(transform == NULL, "Expected NULL, got %p\n", transform); 5022 5023 { 5024 /* test [GS]etBoneOffsetMatrix */ 5025 hr = skininfo->lpVtbl->SetBoneOffsetMatrix(skininfo, 1, &identity_matrix); 5026 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 5027 5028 hr = skininfo->lpVtbl->SetBoneOffsetMatrix(skininfo, 0, NULL); 5029 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 5030 5031 D3DXMatrixIdentity(&identity_matrix); 5032 hr = skininfo->lpVtbl->SetBoneOffsetMatrix(skininfo, 0, &identity_matrix); 5033 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 5034 5035 transform = skininfo->lpVtbl->GetBoneOffsetMatrix(skininfo, 0); 5036 check_matrix(transform, &identity_matrix); 5037 } 5038 5039 { 5040 /* test [GS]etBoneName */ 5041 const char *name_in = "testBoneName"; 5042 const char *string_result2; 5043 5044 hr = skininfo->lpVtbl->SetBoneName(skininfo, 1, name_in); 5045 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 5046 5047 hr = skininfo->lpVtbl->SetBoneName(skininfo, 0, NULL); 5048 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 5049 5050 hr = skininfo->lpVtbl->SetBoneName(skininfo, 0, name_in); 5051 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 5052 5053 string_result = skininfo->lpVtbl->GetBoneName(skininfo, 0); 5054 ok(string_result != NULL, "Expected non-NULL string, got %p\n", string_result); 5055 ok(!strcmp(string_result, name_in), "Expected '%s', got '%s'\n", name_in, string_result); 5056 5057 string_result2 = skininfo->lpVtbl->GetBoneName(skininfo, 0); 5058 ok(string_result == string_result2, "Expected %p, got %p\n", string_result, string_result2); 5059 5060 string_result = skininfo->lpVtbl->GetBoneName(skininfo, 1); 5061 ok(string_result == NULL, "Expected NULL, got %p\n", string_result); 5062 } 5063 5064 { 5065 /* test [GS]etBoneInfluence */ 5066 DWORD vertices[2]; 5067 FLOAT weights[2]; 5068 int i; 5069 DWORD num_influences; 5070 DWORD exp_vertices[2]; 5071 FLOAT exp_weights[2]; 5072 5073 /* vertex and weight arrays untouched when num_influences is 0 */ 5074 vertices[0] = 0xdeadbeef; 5075 weights[0] = FLT_MAX; 5076 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, vertices, weights); 5077 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 5078 ok(vertices[0] == 0xdeadbeef, "expected 0xdeadbeef, got %#x\n", vertices[0]); 5079 ok(weights[0] == FLT_MAX, "expected %g, got %g\n", FLT_MAX, weights[0]); 5080 5081 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 1, vertices, weights); 5082 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 5083 5084 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, NULL, NULL); 5085 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 5086 5087 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, vertices, NULL); 5088 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 5089 5090 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, NULL, weights); 5091 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 5092 5093 5094 /* no vertex or weight value checking */ 5095 exp_vertices[0] = 0; 5096 exp_vertices[1] = 0x87654321; 5097 exp_weights[0] = 0.5; 5098 exp_weights[1] = NAN; 5099 num_influences = 2; 5100 5101 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 1, num_influences, vertices, weights); 5102 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 5103 5104 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, num_influences, NULL, weights); 5105 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 5106 5107 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, num_influences, vertices, NULL); 5108 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 5109 5110 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, num_influences, NULL, NULL); 5111 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 5112 5113 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, num_influences, exp_vertices, exp_weights); 5114 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 5115 5116 memset(vertices, 0, sizeof(vertices)); 5117 memset(weights, 0, sizeof(weights)); 5118 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, vertices, weights); 5119 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 5120 for (i = 0; i < num_influences; i++) { 5121 ok(exp_vertices[i] == vertices[i], 5122 "influence[%d]: expected vertex %u, got %u\n", i, exp_vertices[i], vertices[i]); 5123 ok((isnan(exp_weights[i]) && isnan(weights[i])) || exp_weights[i] == weights[i], 5124 "influence[%d]: expected weights %g, got %g\n", i, exp_weights[i], weights[i]); 5125 } 5126 5127 /* vertices and weights aren't returned after setting num_influences to 0 */ 5128 memset(vertices, 0, sizeof(vertices)); 5129 memset(weights, 0, sizeof(weights)); 5130 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, 0, vertices, weights); 5131 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 5132 5133 vertices[0] = 0xdeadbeef; 5134 weights[0] = FLT_MAX; 5135 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, vertices, weights); 5136 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 5137 ok(vertices[0] == 0xdeadbeef, "expected vertex 0xdeadbeef, got %u\n", vertices[0]); 5138 ok(weights[0] == FLT_MAX, "expected weight %g, got %g\n", FLT_MAX, weights[0]); 5139 } 5140 5141 { 5142 /* test [GS]etFVF and [GS]etDeclaration */ 5143 D3DVERTEXELEMENT9 declaration_in[MAX_FVF_DECL_SIZE]; 5144 DWORD fvf = D3DFVF_XYZ; 5145 DWORD got_fvf; 5146 5147 hr = skininfo->lpVtbl->SetDeclaration(skininfo, NULL); 5148 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 5149 5150 hr = skininfo->lpVtbl->SetDeclaration(skininfo, declaration_with_nonzero_stream); 5151 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 5152 5153 hr = skininfo->lpVtbl->SetFVF(skininfo, 0); 5154 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 5155 5156 hr = D3DXDeclaratorFromFVF(fvf, declaration_in); 5157 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 5158 hr = skininfo->lpVtbl->SetDeclaration(skininfo, declaration_in); 5159 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 5160 got_fvf = skininfo->lpVtbl->GetFVF(skininfo); 5161 ok(fvf == got_fvf, "Expected %#x, got %#x\n", fvf, got_fvf); 5162 hr = skininfo->lpVtbl->GetDeclaration(skininfo, declaration_out); 5163 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 5164 compare_elements(declaration_out, declaration_in, __LINE__, 0); 5165 5166 hr = skininfo->lpVtbl->SetDeclaration(skininfo, empty_declaration); 5167 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 5168 got_fvf = skininfo->lpVtbl->GetFVF(skininfo); 5169 ok(got_fvf == 0, "Expected 0, got %#x\n", got_fvf); 5170 hr = skininfo->lpVtbl->GetDeclaration(skininfo, declaration_out); 5171 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 5172 compare_elements(declaration_out, empty_declaration, __LINE__, 0); 5173 5174 hr = skininfo->lpVtbl->SetFVF(skininfo, fvf); 5175 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 5176 got_fvf = skininfo->lpVtbl->GetFVF(skininfo); 5177 ok(fvf == got_fvf, "Expected %#x, got %#x\n", fvf, got_fvf); 5178 hr = skininfo->lpVtbl->GetDeclaration(skininfo, declaration_out); 5179 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 5180 compare_elements(declaration_out, declaration_in, __LINE__, 0); 5181 } 5182 } 5183 if (skininfo) IUnknown_Release(skininfo); 5184 skininfo = NULL; 5185 5186 hr = D3DXCreateSkinInfoFVF(1, D3DFVF_XYZ, 1, NULL); 5187 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 5188 5189 hr = D3DXCreateSkinInfo(1, NULL, 1, &skininfo); 5190 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 5191 } 5192 5193 static void test_convert_adjacency_to_point_reps(void) 5194 { 5195 HRESULT hr; 5196 struct test_context *test_context = NULL; 5197 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM; 5198 const DWORD options_16bit = D3DXMESH_SYSTEMMEM; 5199 const D3DVERTEXELEMENT9 declaration[] = 5200 { 5201 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 5202 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 5203 {0, 24, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0}, 5204 D3DDECL_END() 5205 }; 5206 const unsigned int VERTS_PER_FACE = 3; 5207 void *vertex_buffer; 5208 void *index_buffer; 5209 DWORD *attributes_buffer; 5210 int i, j; 5211 enum color { RED = 0xffff0000, GREEN = 0xff00ff00, BLUE = 0xff0000ff}; 5212 struct vertex_pnc 5213 { 5214 D3DXVECTOR3 position; 5215 D3DXVECTOR3 normal; 5216 enum color color; /* In case of manual visual inspection */ 5217 }; 5218 #ifndef __REACTOS__ 5219 D3DXVECTOR3 up = {0.0f, 0.0f, 1.0f}; 5220 #else 5221 #define up {0.0f, 0.0f, 1.0f} 5222 #endif 5223 /* mesh0 (one face) 5224 * 5225 * 0--1 5226 * | / 5227 * |/ 5228 * 2 5229 */ 5230 const struct vertex_pnc vertices0[] = 5231 { 5232 {{ 0.0f, 3.0f, 0.f}, up, RED}, 5233 {{ 2.0f, 3.0f, 0.f}, up, GREEN}, 5234 {{ 0.0f, 0.0f, 0.f}, up, BLUE}, 5235 }; 5236 const DWORD indices0[] = {0, 1, 2}; 5237 const unsigned int num_vertices0 = ARRAY_SIZE(vertices0); 5238 const unsigned int num_faces0 = ARRAY_SIZE(indices0) / VERTS_PER_FACE; 5239 const DWORD adjacency0[] = {-1, -1, -1}; 5240 const DWORD exp_point_rep0[] = {0, 1, 2}; 5241 /* mesh1 (right) 5242 * 5243 * 0--1 3 5244 * | / /| 5245 * |/ / | 5246 * 2 5--4 5247 */ 5248 const struct vertex_pnc vertices1[] = 5249 { 5250 {{ 0.0f, 3.0f, 0.f}, up, RED}, 5251 {{ 2.0f, 3.0f, 0.f}, up, GREEN}, 5252 {{ 0.0f, 0.0f, 0.f}, up, BLUE}, 5253 5254 {{ 3.0f, 3.0f, 0.f}, up, GREEN}, 5255 {{ 3.0f, 0.0f, 0.f}, up, RED}, 5256 {{ 1.0f, 0.0f, 0.f}, up, BLUE}, 5257 }; 5258 const DWORD indices1[] = {0, 1, 2, 3, 4, 5}; 5259 const unsigned int num_vertices1 = ARRAY_SIZE(vertices1); 5260 const unsigned int num_faces1 = ARRAY_SIZE(indices1) / VERTS_PER_FACE; 5261 const DWORD adjacency1[] = {-1, 1, -1, -1, -1, 0}; 5262 const DWORD exp_point_rep1[] = {0, 1, 2, 1, 4, 2}; 5263 /* mesh2 (left) 5264 * 5265 * 3 0--1 5266 * /| | / 5267 * / | |/ 5268 * 5--4 2 5269 */ 5270 const struct vertex_pnc vertices2[] = 5271 { 5272 {{ 0.0f, 3.0f, 0.f}, up, RED}, 5273 {{ 2.0f, 3.0f, 0.f}, up, GREEN}, 5274 {{ 0.0f, 0.0f, 0.f}, up, BLUE}, 5275 5276 {{-1.0f, 3.0f, 0.f}, up, RED}, 5277 {{-1.0f, 0.0f, 0.f}, up, GREEN}, 5278 {{-3.0f, 0.0f, 0.f}, up, BLUE}, 5279 }; 5280 const DWORD indices2[] = {0, 1, 2, 3, 4, 5}; 5281 const unsigned int num_vertices2 = ARRAY_SIZE(vertices2); 5282 const unsigned int num_faces2 = ARRAY_SIZE(indices2) / VERTS_PER_FACE; 5283 const DWORD adjacency2[] = {-1, -1, 1, 0, -1, -1}; 5284 const DWORD exp_point_rep2[] = {0, 1, 2, 0, 2, 5}; 5285 /* mesh3 (above) 5286 * 5287 * 3 5288 * /| 5289 * / | 5290 * 5--4 5291 * 0--1 5292 * | / 5293 * |/ 5294 * 2 5295 */ 5296 struct vertex_pnc vertices3[] = 5297 { 5298 {{ 0.0f, 3.0f, 0.f}, up, RED}, 5299 {{ 2.0f, 3.0f, 0.f}, up, GREEN}, 5300 {{ 0.0f, 0.0f, 0.f}, up, BLUE}, 5301 5302 {{ 2.0f, 7.0f, 0.f}, up, BLUE}, 5303 {{ 2.0f, 4.0f, 0.f}, up, GREEN}, 5304 {{ 0.0f, 4.0f, 0.f}, up, RED}, 5305 }; 5306 const DWORD indices3[] = {0, 1, 2, 3, 4, 5}; 5307 const unsigned int num_vertices3 = ARRAY_SIZE(vertices3); 5308 const unsigned int num_faces3 = ARRAY_SIZE(indices3) / VERTS_PER_FACE; 5309 const DWORD adjacency3[] = {1, -1, -1, -1, 0, -1}; 5310 const DWORD exp_point_rep3[] = {0, 1, 2, 3, 1, 0}; 5311 /* mesh4 (below, tip against tip) 5312 * 5313 * 0--1 5314 * | / 5315 * |/ 5316 * 2 5317 * 3 5318 * |\ 5319 * | \ 5320 * 5--4 5321 */ 5322 struct vertex_pnc vertices4[] = 5323 { 5324 {{ 0.0f, 3.0f, 0.f}, up, RED}, 5325 {{ 2.0f, 3.0f, 0.f}, up, GREEN}, 5326 {{ 0.0f, 0.0f, 0.f}, up, BLUE}, 5327 5328 {{ 0.0f, -4.0f, 0.f}, up, BLUE}, 5329 {{ 2.0f, -7.0f, 0.f}, up, GREEN}, 5330 {{ 0.0f, -7.0f, 0.f}, up, RED}, 5331 }; 5332 const DWORD indices4[] = {0, 1, 2, 3, 4, 5}; 5333 const unsigned int num_vertices4 = ARRAY_SIZE(vertices4); 5334 const unsigned int num_faces4 = ARRAY_SIZE(indices4) / VERTS_PER_FACE; 5335 const DWORD adjacency4[] = {-1, -1, -1, -1, -1, -1}; 5336 const DWORD exp_point_rep4[] = {0, 1, 2, 3, 4, 5}; 5337 /* mesh5 (gap in mesh) 5338 * 5339 * 0 3-----4 15 5340 * / \ \ / / \ 5341 * / \ \ / / \ 5342 * 2-----1 5 17-----16 5343 * 6-----7 9 12-----13 5344 * \ / / \ \ / 5345 * \ / / \ \ / 5346 * 8 10-----11 14 5347 * 5348 */ 5349 const struct vertex_pnc vertices5[] = 5350 { 5351 {{ 0.0f, 1.0f, 0.f}, up, RED}, 5352 {{ 1.0f, -1.0f, 0.f}, up, GREEN}, 5353 {{-1.0f, -1.0f, 0.f}, up, BLUE}, 5354 5355 {{ 0.1f, 1.0f, 0.f}, up, RED}, 5356 {{ 2.1f, 1.0f, 0.f}, up, BLUE}, 5357 {{ 1.1f, -1.0f, 0.f}, up, GREEN}, 5358 5359 {{-1.0f, -1.1f, 0.f}, up, BLUE}, 5360 {{ 1.0f, -1.1f, 0.f}, up, GREEN}, 5361 {{ 0.0f, -3.1f, 0.f}, up, RED}, 5362 5363 {{ 1.1f, -1.1f, 0.f}, up, GREEN}, 5364 {{ 2.1f, -3.1f, 0.f}, up, BLUE}, 5365 {{ 0.1f, -3.1f, 0.f}, up, RED}, 5366 5367 {{ 1.2f, -1.1f, 0.f}, up, GREEN}, 5368 {{ 3.2f, -1.1f, 0.f}, up, RED}, 5369 {{ 2.2f, -3.1f, 0.f}, up, BLUE}, 5370 5371 {{ 2.2f, 1.0f, 0.f}, up, BLUE}, 5372 {{ 3.2f, -1.0f, 0.f}, up, RED}, 5373 {{ 1.2f, -1.0f, 0.f}, up, GREEN}, 5374 }; 5375 const DWORD indices5[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}; 5376 const unsigned int num_vertices5 = ARRAY_SIZE(vertices5); 5377 const unsigned int num_faces5 = ARRAY_SIZE(indices5) / VERTS_PER_FACE; 5378 const DWORD adjacency5[] = {-1, 2, -1, -1, 5, -1, 0, -1, -1, 4, -1, -1, 5, -1, 3, -1, 4, 1}; 5379 const DWORD exp_point_rep5[] = {0, 1, 2, 3, 4, 5, 2, 1, 8, 5, 10, 11, 5, 13, 10, 4, 13, 5}; 5380 const WORD indices5_16bit[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}; 5381 /* mesh6 (indices re-ordering) 5382 * 5383 * 0--1 6 3 5384 * | / /| |\ 5385 * |/ / | | \ 5386 * 2 8--7 5--4 5387 */ 5388 const struct vertex_pnc vertices6[] = 5389 { 5390 {{ 0.0f, 3.0f, 0.f}, up, RED}, 5391 {{ 2.0f, 3.0f, 0.f}, up, GREEN}, 5392 {{ 0.0f, 0.0f, 0.f}, up, BLUE}, 5393 5394 {{ 3.0f, 3.0f, 0.f}, up, GREEN}, 5395 {{ 3.0f, 0.0f, 0.f}, up, RED}, 5396 {{ 1.0f, 0.0f, 0.f}, up, BLUE}, 5397 5398 {{ 4.0f, 3.0f, 0.f}, up, GREEN}, 5399 {{ 6.0f, 0.0f, 0.f}, up, BLUE}, 5400 {{ 4.0f, 0.0f, 0.f}, up, RED}, 5401 }; 5402 const DWORD indices6[] = {0, 1, 2, 6, 7, 8, 3, 4, 5}; 5403 const unsigned int num_vertices6 = ARRAY_SIZE(vertices6); 5404 const unsigned int num_faces6 = ARRAY_SIZE(indices6) / VERTS_PER_FACE; 5405 const DWORD adjacency6[] = {-1, 1, -1, 2, -1, 0, -1, -1, 1}; 5406 const DWORD exp_point_rep6[] = {0, 1, 2, 1, 4, 5, 1, 5, 2}; 5407 /* mesh7 (expands collapsed triangle) 5408 * 5409 * 0--1 3 5410 * | / /| 5411 * |/ / | 5412 * 2 5--4 5413 */ 5414 const struct vertex_pnc vertices7[] = 5415 { 5416 {{ 0.0f, 3.0f, 0.f}, up, RED}, 5417 {{ 2.0f, 3.0f, 0.f}, up, GREEN}, 5418 {{ 0.0f, 0.0f, 0.f}, up, BLUE}, 5419 5420 {{ 3.0f, 3.0f, 0.f}, up, GREEN}, 5421 {{ 3.0f, 0.0f, 0.f}, up, RED}, 5422 {{ 1.0f, 0.0f, 0.f}, up, BLUE}, 5423 }; 5424 const DWORD indices7[] = {0, 1, 2, 3, 3, 3}; /* Face 1 is collapsed*/ 5425 const unsigned int num_vertices7 = ARRAY_SIZE(vertices7); 5426 const unsigned int num_faces7 = ARRAY_SIZE(indices7) / VERTS_PER_FACE; 5427 const DWORD adjacency7[] = {-1, -1, -1, -1, -1, -1}; 5428 const DWORD exp_point_rep7[] = {0, 1, 2, 3, 4, 5}; 5429 /* mesh8 (indices re-ordering and double replacement) 5430 * 5431 * 0--1 9 6 5432 * | / /| |\ 5433 * |/ / | | \ 5434 * 2 11-10 8--7 5435 * 3--4 5436 * | / 5437 * |/ 5438 * 5 5439 */ 5440 const struct vertex_pnc vertices8[] = 5441 { 5442 {{ 0.0f, 3.0f, 0.f}, up, RED}, 5443 {{ 2.0f, 3.0f, 0.f}, up, GREEN}, 5444 {{ 0.0f, 0.0f, 0.f}, up, BLUE}, 5445 5446 {{ 4.0, -4.0, 0.f}, up, RED}, 5447 {{ 6.0, -4.0, 0.f}, up, BLUE}, 5448 {{ 4.0, -7.0, 0.f}, up, GREEN}, 5449 5450 {{ 4.0f, 3.0f, 0.f}, up, GREEN}, 5451 {{ 6.0f, 0.0f, 0.f}, up, BLUE}, 5452 {{ 4.0f, 0.0f, 0.f}, up, RED}, 5453 5454 {{ 3.0f, 3.0f, 0.f}, up, GREEN}, 5455 {{ 3.0f, 0.0f, 0.f}, up, RED}, 5456 {{ 1.0f, 0.0f, 0.f}, up, BLUE}, 5457 }; 5458 const DWORD indices8[] = {0, 1, 2, 9, 10, 11, 6, 7, 8, 3, 4, 5}; 5459 const unsigned int num_vertices8 = ARRAY_SIZE(vertices8); 5460 const unsigned int num_faces8 = ARRAY_SIZE(indices8) / VERTS_PER_FACE; 5461 const DWORD adjacency8[] = {-1, 1, -1, 2, -1, 0, -1, 3, 1, 2, -1, -1}; 5462 const DWORD exp_point_rep8[] = {0, 1, 2, 3, 4, 5, 1, 4, 3, 1, 3, 2}; 5463 /* mesh9 (right, shared vertices) 5464 * 5465 * 0--1 5466 * | /| 5467 * |/ | 5468 * 2--3 5469 */ 5470 const struct vertex_pnc vertices9[] = 5471 { 5472 {{ 0.0f, 3.0f, 0.f}, up, RED}, 5473 {{ 2.0f, 3.0f, 0.f}, up, GREEN}, 5474 {{ 0.0f, 0.0f, 0.f}, up, BLUE}, 5475 5476 {{ 2.0f, 0.0f, 0.f}, up, RED}, 5477 }; 5478 const DWORD indices9[] = {0, 1, 2, 1, 3, 2}; 5479 const unsigned int num_vertices9 = ARRAY_SIZE(vertices9); 5480 const unsigned int num_faces9 = ARRAY_SIZE(indices9) / VERTS_PER_FACE; 5481 const DWORD adjacency9[] = {-1, 1, -1, -1, -1, 0}; 5482 const DWORD exp_point_rep9[] = {0, 1, 2, 3}; 5483 /* All mesh data */ 5484 ID3DXMesh *mesh = NULL; 5485 ID3DXMesh *mesh_null_check = NULL; 5486 unsigned int attributes[] = {0}; 5487 struct 5488 { 5489 const struct vertex_pnc *vertices; 5490 const DWORD *indices; 5491 const DWORD num_vertices; 5492 const DWORD num_faces; 5493 const DWORD *adjacency; 5494 const DWORD *exp_point_reps; 5495 const DWORD options; 5496 } 5497 tc[] = 5498 { 5499 { 5500 vertices0, 5501 indices0, 5502 num_vertices0, 5503 num_faces0, 5504 adjacency0, 5505 exp_point_rep0, 5506 options 5507 }, 5508 { 5509 vertices1, 5510 indices1, 5511 num_vertices1, 5512 num_faces1, 5513 adjacency1, 5514 exp_point_rep1, 5515 options 5516 }, 5517 { 5518 vertices2, 5519 indices2, 5520 num_vertices2, 5521 num_faces2, 5522 adjacency2, 5523 exp_point_rep2, 5524 options 5525 }, 5526 { 5527 vertices3, 5528 indices3, 5529 num_vertices3, 5530 num_faces3, 5531 adjacency3, 5532 exp_point_rep3, 5533 options 5534 }, 5535 { 5536 vertices4, 5537 indices4, 5538 num_vertices4, 5539 num_faces4, 5540 adjacency4, 5541 exp_point_rep4, 5542 options 5543 }, 5544 { 5545 vertices5, 5546 indices5, 5547 num_vertices5, 5548 num_faces5, 5549 adjacency5, 5550 exp_point_rep5, 5551 options 5552 }, 5553 { 5554 vertices6, 5555 indices6, 5556 num_vertices6, 5557 num_faces6, 5558 adjacency6, 5559 exp_point_rep6, 5560 options 5561 }, 5562 { 5563 vertices7, 5564 indices7, 5565 num_vertices7, 5566 num_faces7, 5567 adjacency7, 5568 exp_point_rep7, 5569 options 5570 }, 5571 { 5572 vertices8, 5573 indices8, 5574 num_vertices8, 5575 num_faces8, 5576 adjacency8, 5577 exp_point_rep8, 5578 options 5579 }, 5580 { 5581 vertices9, 5582 indices9, 5583 num_vertices9, 5584 num_faces9, 5585 adjacency9, 5586 exp_point_rep9, 5587 options 5588 }, 5589 { 5590 vertices5, 5591 (DWORD*)indices5_16bit, 5592 num_vertices5, 5593 num_faces5, 5594 adjacency5, 5595 exp_point_rep5, 5596 options_16bit 5597 }, 5598 }; 5599 DWORD *point_reps = NULL; 5600 5601 test_context = new_test_context(); 5602 if (!test_context) 5603 { 5604 skip("Couldn't create test context\n"); 5605 goto cleanup; 5606 } 5607 5608 for (i = 0; i < ARRAY_SIZE(tc); i++) 5609 { 5610 hr = D3DXCreateMesh(tc[i].num_faces, tc[i].num_vertices, tc[i].options, declaration, 5611 test_context->device, &mesh); 5612 if (FAILED(hr)) 5613 { 5614 skip("Couldn't create mesh %d. Got %x expected D3D_OK\n", i, hr); 5615 goto cleanup; 5616 } 5617 5618 if (i == 0) /* Save first mesh for later NULL checks */ 5619 mesh_null_check = mesh; 5620 5621 point_reps = HeapAlloc(GetProcessHeap(), 0, tc[i].num_vertices * sizeof(*point_reps)); 5622 if (!point_reps) 5623 { 5624 skip("Couldn't allocate point reps array.\n"); 5625 goto cleanup; 5626 } 5627 5628 hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, &vertex_buffer); 5629 if (FAILED(hr)) 5630 { 5631 skip("Couldn't lock vertex buffer.\n"); 5632 goto cleanup; 5633 } 5634 memcpy(vertex_buffer, tc[i].vertices, tc[i].num_vertices * sizeof(*tc[i].vertices)); 5635 hr = mesh->lpVtbl->UnlockVertexBuffer(mesh); 5636 if (FAILED(hr)) 5637 { 5638 skip("Couldn't unlock vertex buffer.\n"); 5639 goto cleanup; 5640 } 5641 5642 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, &index_buffer); 5643 if (FAILED(hr)) 5644 { 5645 skip("Couldn't lock index buffer.\n"); 5646 goto cleanup; 5647 } 5648 if (tc[i].options & D3DXMESH_32BIT) 5649 { 5650 memcpy(index_buffer, tc[i].indices, VERTS_PER_FACE * tc[i].num_faces * sizeof(DWORD)); 5651 } 5652 else 5653 { 5654 memcpy(index_buffer, tc[i].indices, VERTS_PER_FACE * tc[i].num_faces * sizeof(WORD)); 5655 } 5656 hr = mesh->lpVtbl->UnlockIndexBuffer(mesh); 5657 if (FAILED(hr)) { 5658 skip("Couldn't unlock index buffer.\n"); 5659 goto cleanup; 5660 } 5661 5662 hr = mesh->lpVtbl->LockAttributeBuffer(mesh, 0, &attributes_buffer); 5663 if (FAILED(hr)) 5664 { 5665 skip("Couldn't lock attributes buffer.\n"); 5666 goto cleanup; 5667 } 5668 memcpy(attributes_buffer, attributes, sizeof(attributes)); 5669 hr = mesh->lpVtbl->UnlockAttributeBuffer(mesh); 5670 if (FAILED(hr)) 5671 { 5672 skip("Couldn't unlock attributes buffer.\n"); 5673 goto cleanup; 5674 } 5675 5676 /* Convert adjacency to point representation */ 5677 for (j = 0; j < tc[i].num_vertices; j++) point_reps[j] = -1; 5678 hr = mesh->lpVtbl->ConvertAdjacencyToPointReps(mesh, tc[i].adjacency, point_reps); 5679 ok(hr == D3D_OK, "ConvertAdjacencyToPointReps failed case %d. " 5680 "Got %x expected D3D_OK\n", i, hr); 5681 5682 /* Check point representation */ 5683 for (j = 0; j < tc[i].num_vertices; j++) 5684 { 5685 ok(point_reps[j] == tc[i].exp_point_reps[j], 5686 "Unexpected point representation at (%d, %d)." 5687 " Got %d expected %d\n", 5688 i, j, point_reps[j], tc[i].exp_point_reps[j]); 5689 } 5690 5691 HeapFree(GetProcessHeap(), 0, point_reps); 5692 point_reps = NULL; 5693 5694 if (i != 0) /* First mesh will be freed during cleanup */ 5695 mesh->lpVtbl->Release(mesh); 5696 } 5697 5698 /* NULL checks */ 5699 hr = mesh_null_check->lpVtbl->ConvertAdjacencyToPointReps(mesh_null_check, tc[0].adjacency, NULL); 5700 ok(hr == D3DERR_INVALIDCALL, "ConvertAdjacencyToPointReps point_reps NULL. " 5701 "Got %x expected D3DERR_INVALIDCALL\n", hr); 5702 hr = mesh_null_check->lpVtbl->ConvertAdjacencyToPointReps(mesh_null_check, NULL, NULL); 5703 ok(hr == D3DERR_INVALIDCALL, "ConvertAdjacencyToPointReps adjacency and point_reps NULL. " 5704 "Got %x expected D3DERR_INVALIDCALL\n", hr); 5705 5706 cleanup: 5707 if (mesh_null_check) 5708 mesh_null_check->lpVtbl->Release(mesh_null_check); 5709 HeapFree(GetProcessHeap(), 0, point_reps); 5710 free_test_context(test_context); 5711 #ifdef __REACTOS__ 5712 #undef up 5713 #endif 5714 } 5715 5716 static void test_convert_point_reps_to_adjacency(void) 5717 { 5718 HRESULT hr; 5719 struct test_context *test_context = NULL; 5720 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM; 5721 const DWORD options_16bit = D3DXMESH_SYSTEMMEM; 5722 const D3DVERTEXELEMENT9 declaration[] = 5723 { 5724 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 5725 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 5726 {0, 24, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0}, 5727 D3DDECL_END() 5728 }; 5729 const unsigned int VERTS_PER_FACE = 3; 5730 void *vertex_buffer; 5731 void *index_buffer; 5732 DWORD *attributes_buffer; 5733 int i, j; 5734 enum color { RED = 0xffff0000, GREEN = 0xff00ff00, BLUE = 0xff0000ff}; 5735 struct vertex_pnc 5736 { 5737 D3DXVECTOR3 position; 5738 D3DXVECTOR3 normal; 5739 enum color color; /* In case of manual visual inspection */ 5740 }; 5741 #ifndef __REACTOS__ 5742 D3DXVECTOR3 up = {0.0f, 0.0f, 1.0f}; 5743 #else 5744 #define up {0.0f, 0.0f, 1.0f} 5745 #endif 5746 5747 /* mesh0 (one face) 5748 * 5749 * 0--1 5750 * | / 5751 * |/ 5752 * 2 5753 */ 5754 const struct vertex_pnc vertices0[] = 5755 { 5756 {{ 0.0f, 3.0f, 0.f}, up, RED}, 5757 {{ 2.0f, 3.0f, 0.f}, up, GREEN}, 5758 {{ 0.0f, 0.0f, 0.f}, up, BLUE}, 5759 }; 5760 const DWORD indices0[] = {0, 1, 2}; 5761 const unsigned int num_vertices0 = ARRAY_SIZE(vertices0); 5762 const unsigned int num_faces0 = num_vertices0 / VERTS_PER_FACE; 5763 const DWORD exp_adjacency0[] = {-1, -1, -1}; 5764 const DWORD exp_id_adjacency0[] = {-1, -1, -1}; 5765 const DWORD point_rep0[] = {0, 1, 2}; 5766 /* mesh1 (right) 5767 * 5768 * 0--1 3 5769 * | / /| 5770 * |/ / | 5771 * 2 5--4 5772 */ 5773 const struct vertex_pnc vertices1[] = 5774 { 5775 {{ 0.0f, 3.0f, 0.f}, up, RED}, 5776 {{ 2.0f, 3.0f, 0.f}, up, GREEN}, 5777 {{ 0.0f, 0.0f, 0.f}, up, BLUE}, 5778 5779 {{ 3.0f, 3.0f, 0.f}, up, GREEN}, 5780 {{ 3.0f, 0.0f, 0.f}, up, RED}, 5781 {{ 1.0f, 0.0f, 0.f}, up, BLUE}, 5782 }; 5783 const DWORD indices1[] = {0, 1, 2, 3, 4, 5}; 5784 const unsigned int num_vertices1 = ARRAY_SIZE(vertices1); 5785 const unsigned int num_faces1 = num_vertices1 / VERTS_PER_FACE; 5786 const DWORD exp_adjacency1[] = {-1, 1, -1, -1, -1, 0}; 5787 const DWORD exp_id_adjacency1[] = {-1, -1, -1, -1, -1, -1}; 5788 const DWORD point_rep1[] = {0, 1, 2, 1, 4, 2}; 5789 /* mesh2 (left) 5790 * 5791 * 3 0--1 5792 * /| | / 5793 * / | |/ 5794 * 5--4 2 5795 */ 5796 const struct vertex_pnc vertices2[] = 5797 { 5798 {{ 0.0f, 3.0f, 0.f}, up, RED}, 5799 {{ 2.0f, 3.0f, 0.f}, up, GREEN}, 5800 {{ 0.0f, 0.0f, 0.f}, up, BLUE}, 5801 5802 {{-1.0f, 3.0f, 0.f}, up, RED}, 5803 {{-1.0f, 0.0f, 0.f}, up, GREEN}, 5804 {{-3.0f, 0.0f, 0.f}, up, BLUE}, 5805 }; 5806 const DWORD indices2[] = {0, 1, 2, 3, 4, 5}; 5807 const unsigned int num_vertices2 = ARRAY_SIZE(vertices2); 5808 const unsigned int num_faces2 = num_vertices2 / VERTS_PER_FACE; 5809 const DWORD exp_adjacency2[] = {-1, -1, 1, 0, -1, -1}; 5810 const DWORD exp_id_adjacency2[] = {-1, -1, -1, -1, -1, -1}; 5811 const DWORD point_rep2[] = {0, 1, 2, 0, 2, 5}; 5812 /* mesh3 (above) 5813 * 5814 * 3 5815 * /| 5816 * / | 5817 * 5--4 5818 * 0--1 5819 * | / 5820 * |/ 5821 * 2 5822 */ 5823 struct vertex_pnc vertices3[] = 5824 { 5825 {{ 0.0f, 3.0f, 0.f}, up, RED}, 5826 {{ 2.0f, 3.0f, 0.f}, up, GREEN}, 5827 {{ 0.0f, 0.0f, 0.f}, up, BLUE}, 5828 5829 {{ 2.0f, 7.0f, 0.f}, up, BLUE}, 5830 {{ 2.0f, 4.0f, 0.f}, up, GREEN}, 5831 {{ 0.0f, 4.0f, 0.f}, up, RED}, 5832 }; 5833 const DWORD indices3[] = {0, 1, 2, 3, 4, 5}; 5834 const unsigned int num_vertices3 = ARRAY_SIZE(vertices3); 5835 const unsigned int num_faces3 = num_vertices3 / VERTS_PER_FACE; 5836 const DWORD exp_adjacency3[] = {1, -1, -1, -1, 0, -1}; 5837 const DWORD exp_id_adjacency3[] = {-1, -1, -1, -1, -1, -1}; 5838 const DWORD point_rep3[] = {0, 1, 2, 3, 1, 0}; 5839 /* mesh4 (below, tip against tip) 5840 * 5841 * 0--1 5842 * | / 5843 * |/ 5844 * 2 5845 * 3 5846 * |\ 5847 * | \ 5848 * 5--4 5849 */ 5850 struct vertex_pnc vertices4[] = 5851 { 5852 {{ 0.0f, 3.0f, 0.f}, up, RED}, 5853 {{ 2.0f, 3.0f, 0.f}, up, GREEN}, 5854 {{ 0.0f, 0.0f, 0.f}, up, BLUE}, 5855 5856 {{ 0.0f, -4.0f, 0.f}, up, BLUE}, 5857 {{ 2.0f, -7.0f, 0.f}, up, GREEN}, 5858 {{ 0.0f, -7.0f, 0.f}, up, RED}, 5859 }; 5860 const DWORD indices4[] = {0, 1, 2, 3, 4, 5}; 5861 const unsigned int num_vertices4 = ARRAY_SIZE(vertices4); 5862 const unsigned int num_faces4 = num_vertices4 / VERTS_PER_FACE; 5863 const DWORD exp_adjacency4[] = {-1, -1, -1, -1, -1, -1}; 5864 const DWORD exp_id_adjacency4[] = {-1, -1, -1, -1, -1, -1}; 5865 const DWORD point_rep4[] = {0, 1, 2, 3, 4, 5}; 5866 /* mesh5 (gap in mesh) 5867 * 5868 * 0 3-----4 15 5869 * / \ \ / / \ 5870 * / \ \ / / \ 5871 * 2-----1 5 17-----16 5872 * 6-----7 9 12-----13 5873 * \ / / \ \ / 5874 * \ / / \ \ / 5875 * 8 10-----11 14 5876 * 5877 */ 5878 const struct vertex_pnc vertices5[] = 5879 { 5880 {{ 0.0f, 1.0f, 0.f}, up, RED}, 5881 {{ 1.0f, -1.0f, 0.f}, up, GREEN}, 5882 {{-1.0f, -1.0f, 0.f}, up, BLUE}, 5883 5884 {{ 0.1f, 1.0f, 0.f}, up, RED}, 5885 {{ 2.1f, 1.0f, 0.f}, up, BLUE}, 5886 {{ 1.1f, -1.0f, 0.f}, up, GREEN}, 5887 5888 {{-1.0f, -1.1f, 0.f}, up, BLUE}, 5889 {{ 1.0f, -1.1f, 0.f}, up, GREEN}, 5890 {{ 0.0f, -3.1f, 0.f}, up, RED}, 5891 5892 {{ 1.1f, -1.1f, 0.f}, up, GREEN}, 5893 {{ 2.1f, -3.1f, 0.f}, up, BLUE}, 5894 {{ 0.1f, -3.1f, 0.f}, up, RED}, 5895 5896 {{ 1.2f, -1.1f, 0.f}, up, GREEN}, 5897 {{ 3.2f, -1.1f, 0.f}, up, RED}, 5898 {{ 2.2f, -3.1f, 0.f}, up, BLUE}, 5899 5900 {{ 2.2f, 1.0f, 0.f}, up, BLUE}, 5901 {{ 3.2f, -1.0f, 0.f}, up, RED}, 5902 {{ 1.2f, -1.0f, 0.f}, up, GREEN}, 5903 }; 5904 const DWORD indices5[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}; 5905 const unsigned int num_vertices5 = ARRAY_SIZE(vertices5); 5906 const unsigned int num_faces5 = num_vertices5 / VERTS_PER_FACE; 5907 const DWORD exp_adjacency5[] = {-1, 2, -1, -1, 5, -1, 0, -1, -1, 4, -1, -1, 5, -1, 3, -1, 4, 1}; 5908 const DWORD exp_id_adjacency5[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; 5909 const DWORD point_rep5[] = {0, 1, 2, 3, 4, 5, 2, 1, 8, 5, 10, 11, 5, 13, 10, 4, 13, 5}; 5910 /* mesh6 (indices re-ordering) 5911 * 5912 * 0--1 6 3 5913 * | / /| |\ 5914 * |/ / | | \ 5915 * 2 8--7 5--4 5916 */ 5917 const struct vertex_pnc vertices6[] = 5918 { 5919 {{ 0.0f, 3.0f, 0.f}, up, RED}, 5920 {{ 2.0f, 3.0f, 0.f}, up, GREEN}, 5921 {{ 0.0f, 0.0f, 0.f}, up, BLUE}, 5922 5923 {{ 3.0f, 3.0f, 0.f}, up, GREEN}, 5924 {{ 3.0f, 0.0f, 0.f}, up, RED}, 5925 {{ 1.0f, 0.0f, 0.f}, up, BLUE}, 5926 5927 {{ 4.0f, 3.0f, 0.f}, up, GREEN}, 5928 {{ 6.0f, 0.0f, 0.f}, up, BLUE}, 5929 {{ 4.0f, 0.0f, 0.f}, up, RED}, 5930 }; 5931 const DWORD indices6[] = {0, 1, 2, 6, 7, 8, 3, 4, 5}; 5932 const unsigned int num_vertices6 = ARRAY_SIZE(vertices6); 5933 const unsigned int num_faces6 = num_vertices6 / VERTS_PER_FACE; 5934 const DWORD exp_adjacency6[] = {-1, 1, -1, 2, -1, 0, -1, -1, 1}; 5935 const DWORD exp_id_adjacency6[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1}; 5936 const DWORD point_rep6[] = {0, 1, 2, 1, 4, 5, 1, 5, 2}; 5937 /* mesh7 (expands collapsed triangle) 5938 * 5939 * 0--1 3 5940 * | / /| 5941 * |/ / | 5942 * 2 5--4 5943 */ 5944 const struct vertex_pnc vertices7[] = 5945 { 5946 {{ 0.0f, 3.0f, 0.f}, up, RED}, 5947 {{ 2.0f, 3.0f, 0.f}, up, GREEN}, 5948 {{ 0.0f, 0.0f, 0.f}, up, BLUE}, 5949 5950 {{ 3.0f, 3.0f, 0.f}, up, GREEN}, 5951 {{ 3.0f, 0.0f, 0.f}, up, RED}, 5952 {{ 1.0f, 0.0f, 0.f}, up, BLUE}, 5953 }; 5954 const DWORD indices7[] = {0, 1, 2, 3, 3, 3}; /* Face 1 is collapsed*/ 5955 const unsigned int num_vertices7 = ARRAY_SIZE(vertices7); 5956 const unsigned int num_faces7 = num_vertices7 / VERTS_PER_FACE; 5957 const DWORD exp_adjacency7[] = {-1, -1, -1, -1, -1, -1}; 5958 const DWORD exp_id_adjacency7[] = {-1, -1, -1, -1, -1, -1}; 5959 const DWORD point_rep7[] = {0, 1, 2, 3, 4, 5}; 5960 /* mesh8 (indices re-ordering and double replacement) 5961 * 5962 * 0--1 9 6 5963 * | / /| |\ 5964 * |/ / | | \ 5965 * 2 11-10 8--7 5966 * 3--4 5967 * | / 5968 * |/ 5969 * 5 5970 */ 5971 const struct vertex_pnc vertices8[] = 5972 { 5973 {{ 0.0f, 3.0f, 0.f}, up, RED}, 5974 {{ 2.0f, 3.0f, 0.f}, up, GREEN}, 5975 {{ 0.0f, 0.0f, 0.f}, up, BLUE}, 5976 5977 {{ 4.0, -4.0, 0.f}, up, RED}, 5978 {{ 6.0, -4.0, 0.f}, up, BLUE}, 5979 {{ 4.0, -7.0, 0.f}, up, GREEN}, 5980 5981 {{ 4.0f, 3.0f, 0.f}, up, GREEN}, 5982 {{ 6.0f, 0.0f, 0.f}, up, BLUE}, 5983 {{ 4.0f, 0.0f, 0.f}, up, RED}, 5984 5985 {{ 3.0f, 3.0f, 0.f}, up, GREEN}, 5986 {{ 3.0f, 0.0f, 0.f}, up, RED}, 5987 {{ 1.0f, 0.0f, 0.f}, up, BLUE}, 5988 }; 5989 const DWORD indices8[] = {0, 1, 2, 9, 10, 11, 6, 7, 8, 3, 4, 5}; 5990 const WORD indices8_16bit[] = {0, 1, 2, 9, 10, 11, 6, 7, 8, 3, 4, 5}; 5991 const unsigned int num_vertices8 = ARRAY_SIZE(vertices8); 5992 const unsigned int num_faces8 = num_vertices8 / VERTS_PER_FACE; 5993 const DWORD exp_adjacency8[] = {-1, 1, -1, 2, -1, 0, -1, 3, 1, 2, -1, -1}; 5994 const DWORD exp_id_adjacency8[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; 5995 const DWORD point_rep8[] = {0, 1, 2, 3, 4, 5, 1, 4, 3, 1, 3, 2}; 5996 /* mesh9 (right, shared vertices) 5997 * 5998 * 0--1 5999 * | /| 6000 * |/ | 6001 * 2--3 6002 */ 6003 const struct vertex_pnc vertices9[] = 6004 { 6005 {{ 0.0f, 3.0f, 0.f}, up, RED}, 6006 {{ 2.0f, 3.0f, 0.f}, up, GREEN}, 6007 {{ 0.0f, 0.0f, 0.f}, up, BLUE}, 6008 6009 {{ 2.0f, 0.0f, 0.f}, up, RED}, 6010 }; 6011 const DWORD indices9[] = {0, 1, 2, 1, 3, 2}; 6012 const unsigned int num_vertices9 = ARRAY_SIZE(vertices9); 6013 const unsigned int num_faces9 = 2; 6014 const DWORD exp_adjacency9[] = {-1, 1, -1, -1, -1, 0}; 6015 const DWORD exp_id_adjacency9[] = {-1, 1, -1, -1, -1, 0}; 6016 const DWORD point_rep9[] = {0, 1, 2, 3}; 6017 /* All mesh data */ 6018 ID3DXMesh *mesh = NULL; 6019 ID3DXMesh *mesh_null_check = NULL; 6020 unsigned int attributes[] = {0}; 6021 struct 6022 { 6023 const struct vertex_pnc *vertices; 6024 const DWORD *indices; 6025 const DWORD num_vertices; 6026 const DWORD num_faces; 6027 const DWORD *point_reps; 6028 const DWORD *exp_adjacency; 6029 const DWORD *exp_id_adjacency; 6030 const DWORD options; 6031 } 6032 tc[] = 6033 { 6034 { 6035 vertices0, 6036 indices0, 6037 num_vertices0, 6038 num_faces0, 6039 point_rep0, 6040 exp_adjacency0, 6041 exp_id_adjacency0, 6042 options 6043 }, 6044 { 6045 vertices1, 6046 indices1, 6047 num_vertices1, 6048 num_faces1, 6049 point_rep1, 6050 exp_adjacency1, 6051 exp_id_adjacency1, 6052 options 6053 }, 6054 { 6055 vertices2, 6056 indices2, 6057 num_vertices2, 6058 num_faces2, 6059 point_rep2, 6060 exp_adjacency2, 6061 exp_id_adjacency2, 6062 options 6063 }, 6064 { 6065 vertices3, 6066 indices3, 6067 num_vertices3, 6068 num_faces3, 6069 point_rep3, 6070 exp_adjacency3, 6071 exp_id_adjacency3, 6072 options 6073 }, 6074 { 6075 vertices4, 6076 indices4, 6077 num_vertices4, 6078 num_faces4, 6079 point_rep4, 6080 exp_adjacency4, 6081 exp_id_adjacency4, 6082 options 6083 }, 6084 { 6085 vertices5, 6086 indices5, 6087 num_vertices5, 6088 num_faces5, 6089 point_rep5, 6090 exp_adjacency5, 6091 exp_id_adjacency5, 6092 options 6093 }, 6094 { 6095 vertices6, 6096 indices6, 6097 num_vertices6, 6098 num_faces6, 6099 point_rep6, 6100 exp_adjacency6, 6101 exp_id_adjacency6, 6102 options 6103 }, 6104 { 6105 vertices7, 6106 indices7, 6107 num_vertices7, 6108 num_faces7, 6109 point_rep7, 6110 exp_adjacency7, 6111 exp_id_adjacency7, 6112 options 6113 }, 6114 { 6115 vertices8, 6116 indices8, 6117 num_vertices8, 6118 num_faces8, 6119 point_rep8, 6120 exp_adjacency8, 6121 exp_id_adjacency8, 6122 options 6123 }, 6124 { 6125 vertices9, 6126 indices9, 6127 num_vertices9, 6128 num_faces9, 6129 point_rep9, 6130 exp_adjacency9, 6131 exp_id_adjacency9, 6132 options 6133 }, 6134 { 6135 vertices8, 6136 (DWORD*)indices8_16bit, 6137 num_vertices8, 6138 num_faces8, 6139 point_rep8, 6140 exp_adjacency8, 6141 exp_id_adjacency8, 6142 options_16bit 6143 }, 6144 }; 6145 DWORD *adjacency = NULL; 6146 #ifdef __REACTOS__ 6147 #undef up 6148 #endif 6149 6150 test_context = new_test_context(); 6151 if (!test_context) 6152 { 6153 skip("Couldn't create test context\n"); 6154 goto cleanup; 6155 } 6156 6157 for (i = 0; i < ARRAY_SIZE(tc); i++) 6158 { 6159 hr = D3DXCreateMesh(tc[i].num_faces, tc[i].num_vertices, tc[i].options, 6160 declaration, test_context->device, &mesh); 6161 if (FAILED(hr)) 6162 { 6163 skip("Couldn't create mesh %d. Got %x expected D3D_OK\n", i, hr); 6164 goto cleanup; 6165 } 6166 6167 if (i == 0) /* Save first mesh for later NULL checks */ 6168 mesh_null_check = mesh; 6169 6170 adjacency = HeapAlloc(GetProcessHeap(), 0, VERTS_PER_FACE * tc[i].num_faces * sizeof(*adjacency)); 6171 if (!adjacency) 6172 { 6173 skip("Couldn't allocate adjacency array.\n"); 6174 goto cleanup; 6175 } 6176 6177 hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, &vertex_buffer); 6178 if (FAILED(hr)) 6179 { 6180 skip("Couldn't lock vertex buffer.\n"); 6181 goto cleanup; 6182 } 6183 memcpy(vertex_buffer, tc[i].vertices, tc[i].num_vertices * sizeof(*tc[i].vertices)); 6184 hr = mesh->lpVtbl->UnlockVertexBuffer(mesh); 6185 if (FAILED(hr)) 6186 { 6187 skip("Couldn't unlock vertex buffer.\n"); 6188 goto cleanup; 6189 } 6190 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, &index_buffer); 6191 if (FAILED(hr)) 6192 { 6193 skip("Couldn't lock index buffer.\n"); 6194 goto cleanup; 6195 } 6196 if (tc[i].options & D3DXMESH_32BIT) 6197 { 6198 memcpy(index_buffer, tc[i].indices, VERTS_PER_FACE * tc[i].num_faces * sizeof(DWORD)); 6199 } 6200 else 6201 { 6202 memcpy(index_buffer, tc[i].indices, VERTS_PER_FACE * tc[i].num_faces * sizeof(WORD)); 6203 } 6204 hr = mesh->lpVtbl->UnlockIndexBuffer(mesh); 6205 if (FAILED(hr)) { 6206 skip("Couldn't unlock index buffer.\n"); 6207 goto cleanup; 6208 } 6209 6210 hr = mesh->lpVtbl->LockAttributeBuffer(mesh, 0, &attributes_buffer); 6211 if (FAILED(hr)) 6212 { 6213 skip("Couldn't lock attributes buffer.\n"); 6214 goto cleanup; 6215 } 6216 memcpy(attributes_buffer, attributes, sizeof(attributes)); 6217 hr = mesh->lpVtbl->UnlockAttributeBuffer(mesh); 6218 if (FAILED(hr)) 6219 { 6220 skip("Couldn't unlock attributes buffer.\n"); 6221 goto cleanup; 6222 } 6223 6224 /* Convert point representation to adjacency*/ 6225 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++) adjacency[j] = -2; 6226 6227 hr = mesh->lpVtbl->ConvertPointRepsToAdjacency(mesh, tc[i].point_reps, adjacency); 6228 ok(hr == D3D_OK, "ConvertPointRepsToAdjacency failed case %d. " 6229 "Got %x expected D3D_OK\n", i, hr); 6230 /* Check adjacency */ 6231 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++) 6232 { 6233 ok(adjacency[j] == tc[i].exp_adjacency[j], 6234 "Unexpected adjacency information at (%d, %d)." 6235 " Got %d expected %d\n", 6236 i, j, adjacency[j], tc[i].exp_adjacency[j]); 6237 } 6238 6239 /* NULL point representation is considered identity. */ 6240 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++) adjacency[j] = -2; 6241 hr = mesh_null_check->lpVtbl->ConvertPointRepsToAdjacency(mesh, NULL, adjacency); 6242 ok(hr == D3D_OK, "ConvertPointRepsToAdjacency NULL point_reps. " 6243 "Got %x expected D3D_OK\n", hr); 6244 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++) 6245 { 6246 ok(adjacency[j] == tc[i].exp_id_adjacency[j], 6247 "Unexpected adjacency information (id) at (%d, %d)." 6248 " Got %d expected %d\n", 6249 i, j, adjacency[j], tc[i].exp_id_adjacency[j]); 6250 } 6251 6252 HeapFree(GetProcessHeap(), 0, adjacency); 6253 adjacency = NULL; 6254 if (i != 0) /* First mesh will be freed during cleanup */ 6255 mesh->lpVtbl->Release(mesh); 6256 } 6257 6258 /* NULL checks */ 6259 hr = mesh_null_check->lpVtbl->ConvertPointRepsToAdjacency(mesh_null_check, tc[0].point_reps, NULL); 6260 ok(hr == D3DERR_INVALIDCALL, "ConvertPointRepsToAdjacency NULL adjacency. " 6261 "Got %x expected D3DERR_INVALIDCALL\n", hr); 6262 hr = mesh_null_check->lpVtbl->ConvertPointRepsToAdjacency(mesh_null_check, NULL, NULL); 6263 ok(hr == D3DERR_INVALIDCALL, "ConvertPointRepsToAdjacency NULL point_reps and adjacency. " 6264 "Got %x expected D3DERR_INVALIDCALL\n", hr); 6265 6266 cleanup: 6267 if (mesh_null_check) 6268 mesh_null_check->lpVtbl->Release(mesh_null_check); 6269 HeapFree(GetProcessHeap(), 0, adjacency); 6270 free_test_context(test_context); 6271 } 6272 6273 static HRESULT init_test_mesh(const DWORD num_faces, const DWORD num_vertices, 6274 const DWORD options, 6275 const D3DVERTEXELEMENT9 *declaration, 6276 IDirect3DDevice9 *device, ID3DXMesh **mesh_ptr, 6277 const void *vertices, const DWORD vertex_size, 6278 const DWORD *indices, const DWORD *attributes) 6279 { 6280 HRESULT hr; 6281 void *vertex_buffer; 6282 void *index_buffer; 6283 DWORD *attributes_buffer; 6284 ID3DXMesh *mesh = NULL; 6285 6286 hr = D3DXCreateMesh(num_faces, num_vertices, options, declaration, device, mesh_ptr); 6287 if (FAILED(hr)) 6288 { 6289 skip("Couldn't create mesh. Got %x expected D3D_OK\n", hr); 6290 goto cleanup; 6291 } 6292 mesh = *mesh_ptr; 6293 6294 hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, &vertex_buffer); 6295 if (FAILED(hr)) 6296 { 6297 skip("Couldn't lock vertex buffer.\n"); 6298 goto cleanup; 6299 } 6300 memcpy(vertex_buffer, vertices, num_vertices * vertex_size); 6301 hr = mesh->lpVtbl->UnlockVertexBuffer(mesh); 6302 if (FAILED(hr)) 6303 { 6304 skip("Couldn't unlock vertex buffer.\n"); 6305 goto cleanup; 6306 } 6307 6308 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, &index_buffer); 6309 if (FAILED(hr)) 6310 { 6311 skip("Couldn't lock index buffer.\n"); 6312 goto cleanup; 6313 } 6314 if (options & D3DXMESH_32BIT) 6315 { 6316 if (indices) 6317 memcpy(index_buffer, indices, 3 * num_faces * sizeof(DWORD)); 6318 else 6319 { 6320 /* Fill index buffer with 0, 1, 2, ...*/ 6321 DWORD *indices_32bit = (DWORD*)index_buffer; 6322 UINT i; 6323 for (i = 0; i < 3 * num_faces; i++) 6324 indices_32bit[i] = i; 6325 } 6326 } 6327 else 6328 { 6329 if (indices) 6330 memcpy(index_buffer, indices, 3 * num_faces * sizeof(WORD)); 6331 else 6332 { 6333 /* Fill index buffer with 0, 1, 2, ...*/ 6334 WORD *indices_16bit = (WORD*)index_buffer; 6335 UINT i; 6336 for (i = 0; i < 3 * num_faces; i++) 6337 indices_16bit[i] = i; 6338 } 6339 } 6340 hr = mesh->lpVtbl->UnlockIndexBuffer(mesh); 6341 if (FAILED(hr)) { 6342 skip("Couldn't unlock index buffer.\n"); 6343 goto cleanup; 6344 } 6345 6346 hr = mesh->lpVtbl->LockAttributeBuffer(mesh, 0, &attributes_buffer); 6347 if (FAILED(hr)) 6348 { 6349 skip("Couldn't lock attributes buffer.\n"); 6350 goto cleanup; 6351 } 6352 6353 if (attributes) 6354 memcpy(attributes_buffer, attributes, num_faces * sizeof(*attributes)); 6355 else 6356 memset(attributes_buffer, 0, num_faces * sizeof(*attributes)); 6357 6358 hr = mesh->lpVtbl->UnlockAttributeBuffer(mesh); 6359 if (FAILED(hr)) 6360 { 6361 skip("Couldn't unlock attributes buffer.\n"); 6362 goto cleanup; 6363 } 6364 6365 hr = D3D_OK; 6366 cleanup: 6367 return hr; 6368 } 6369 6370 /* Using structs instead of bit-fields in order to avoid compiler issues. */ 6371 struct udec3 6372 { 6373 UINT x; 6374 UINT y; 6375 UINT z; 6376 UINT w; 6377 }; 6378 6379 struct dec3n 6380 { 6381 INT x; 6382 INT y; 6383 INT z; 6384 INT w; 6385 }; 6386 6387 static DWORD init_udec3_dword(UINT x, UINT y, UINT z, UINT w) 6388 { 6389 DWORD d = 0; 6390 6391 d |= x & 0x3ff; 6392 d |= (y << 10) & 0xffc00; 6393 d |= (z << 20) & 0x3ff00000; 6394 d |= (w << 30) & 0xc0000000; 6395 6396 return d; 6397 } 6398 6399 static DWORD init_dec3n_dword(INT x, INT y, INT z, INT w) 6400 { 6401 DWORD d = 0; 6402 6403 d |= x & 0x3ff; 6404 d |= (y << 10) & 0xffc00; 6405 d |= (z << 20) & 0x3ff00000; 6406 d |= (w << 30) & 0xc0000000; 6407 6408 return d; 6409 } 6410 6411 static struct udec3 dword_to_udec3(DWORD d) 6412 { 6413 struct udec3 v; 6414 6415 v.x = d & 0x3ff; 6416 v.y = (d & 0xffc00) >> 10; 6417 v.z = (d & 0x3ff00000) >> 20; 6418 v.w = (d & 0xc0000000) >> 30; 6419 6420 return v; 6421 } 6422 6423 static struct dec3n dword_to_dec3n(DWORD d) 6424 { 6425 struct dec3n v; 6426 6427 v.x = d & 0x3ff; 6428 v.y = (d & 0xffc00) >> 10; 6429 v.z = (d & 0x3ff00000) >> 20; 6430 v.w = (d & 0xc0000000) >> 30; 6431 6432 return v; 6433 } 6434 6435 static void check_vertex_components(int line, int mesh_number, int vertex_number, BYTE *got_ptr, const BYTE *exp_ptr, D3DVERTEXELEMENT9 *declaration) 6436 { 6437 const char *usage_strings[] = 6438 { 6439 "position", 6440 "blend weight", 6441 "blend indices", 6442 "normal", 6443 "point size", 6444 "texture coordinates", 6445 "tangent", 6446 "binormal", 6447 "tessellation factor", 6448 "position transformed", 6449 "color", 6450 "fog", 6451 "depth", 6452 "sample" 6453 }; 6454 D3DVERTEXELEMENT9 *decl_ptr; 6455 const float PRECISION = 1e-5f; 6456 6457 for (decl_ptr = declaration; decl_ptr->Stream != 0xFF; decl_ptr++) 6458 { 6459 switch (decl_ptr->Type) 6460 { 6461 case D3DDECLTYPE_FLOAT1: 6462 { 6463 FLOAT *got = (FLOAT*)(got_ptr + decl_ptr->Offset); 6464 FLOAT *exp = (FLOAT*)(exp_ptr + decl_ptr->Offset); 6465 FLOAT diff = fabsf(*got - *exp); 6466 ok_(__FILE__,line)(diff <= PRECISION, "Mesh %d: Got %f for vertex %d %s, expected %f.\n", 6467 mesh_number, *got, vertex_number, usage_strings[decl_ptr->Usage], *exp); 6468 break; 6469 } 6470 case D3DDECLTYPE_FLOAT2: 6471 { 6472 D3DXVECTOR2 *got = (D3DXVECTOR2*)(got_ptr + decl_ptr->Offset); 6473 D3DXVECTOR2 *exp = (D3DXVECTOR2*)(exp_ptr + decl_ptr->Offset); 6474 FLOAT diff = max(fabsf(got->x - exp->x), fabsf(got->y - exp->y)); 6475 ok_(__FILE__,line)(diff <= PRECISION, "Mesh %d: Got (%f, %f) for vertex %d %s, expected (%f, %f).\n", 6476 mesh_number, got->x, got->y, vertex_number, usage_strings[decl_ptr->Usage], exp->x, exp->y); 6477 break; 6478 } 6479 case D3DDECLTYPE_FLOAT3: 6480 { 6481 D3DXVECTOR3 *got = (D3DXVECTOR3*)(got_ptr + decl_ptr->Offset); 6482 D3DXVECTOR3 *exp = (D3DXVECTOR3*)(exp_ptr + decl_ptr->Offset); 6483 FLOAT diff = max(fabsf(got->x - exp->x), fabsf(got->y - exp->y)); 6484 diff = max(diff, fabsf(got->z - exp->z)); 6485 ok_(__FILE__,line)(diff <= PRECISION, "Mesh %d: Got (%f, %f, %f) for vertex %d %s, expected (%f, %f, %f).\n", 6486 mesh_number, got->x, got->y, got->z, vertex_number, usage_strings[decl_ptr->Usage], exp->x, exp->y, exp->z); 6487 break; 6488 } 6489 case D3DDECLTYPE_FLOAT4: 6490 { 6491 D3DXVECTOR4 *got = (D3DXVECTOR4*)(got_ptr + decl_ptr->Offset); 6492 D3DXVECTOR4 *exp = (D3DXVECTOR4*)(exp_ptr + decl_ptr->Offset); 6493 FLOAT diff = max(fabsf(got->x - exp->x), fabsf(got->y - exp->y)); 6494 diff = max(diff, fabsf(got->z - exp->z)); 6495 diff = max(diff, fabsf(got->w - exp->w)); 6496 ok_(__FILE__,line)(diff <= PRECISION, "Mesh %d: Got (%f, %f, %f, %f) for vertex %d %s, expected (%f, %f, %f, %f).\n", 6497 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); 6498 break; 6499 } 6500 case D3DDECLTYPE_D3DCOLOR: 6501 { 6502 BYTE *got = got_ptr + decl_ptr->Offset; 6503 const BYTE *exp = exp_ptr + decl_ptr->Offset; 6504 BOOL same_color = got[0] == exp[0] && got[1] == exp[1] 6505 && got[2] == exp[2] && got[3] == exp[3]; 6506 const char *color_types[] = {"diffuse", "specular", "undefined color"}; 6507 BYTE usage_index = decl_ptr->UsageIndex; 6508 if (usage_index > 1) usage_index = 2; 6509 ok_(__FILE__,line)(same_color, "Mesh %d: Got (%u, %u, %u, %u) for vertex %d %s, expected (%u, %u, %u, %u).\n", 6510 mesh_number, got[0], got[1], got[2], got[3], vertex_number, color_types[usage_index], exp[0], exp[1], exp[2], exp[3]); 6511 break; 6512 } 6513 case D3DDECLTYPE_UBYTE4: 6514 case D3DDECLTYPE_UBYTE4N: 6515 { 6516 BYTE *got = got_ptr + decl_ptr->Offset; 6517 const BYTE *exp = exp_ptr + decl_ptr->Offset; 6518 BOOL same = got[0] == exp[0] && got[1] == exp[1] 6519 && got[2] == exp[2] && got[3] == exp[3]; 6520 ok_(__FILE__,line)(same, "Mesh %d: Got (%u, %u, %u, %u) for vertex %d %s, expected (%u, %u, %u, %u).\n", 6521 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]); 6522 break; 6523 } 6524 case D3DDECLTYPE_SHORT2: 6525 case D3DDECLTYPE_SHORT2N: 6526 { 6527 SHORT *got = (SHORT*)(got_ptr + decl_ptr->Offset); 6528 SHORT *exp = (SHORT*)(exp_ptr + decl_ptr->Offset); 6529 BOOL same = got[0] == exp[0] && got[1] == exp[1]; 6530 ok_(__FILE__,line)(same, "Mesh %d: Got (%hd, %hd) for vertex %d %s, expected (%hd, %hd).\n", 6531 mesh_number, got[0], got[1], vertex_number, usage_strings[decl_ptr->Usage], exp[0], exp[1]); 6532 break; 6533 } 6534 case D3DDECLTYPE_SHORT4: 6535 case D3DDECLTYPE_SHORT4N: 6536 { 6537 SHORT *got = (SHORT*)(got_ptr + decl_ptr->Offset); 6538 SHORT *exp = (SHORT*)(exp_ptr + decl_ptr->Offset); 6539 BOOL same = got[0] == exp[0] && got[1] == exp[1] 6540 && got[2] == exp[2] && got[3] == exp[3]; 6541 ok_(__FILE__,line)(same, "Mesh %d: Got (%hd, %hd, %hd, %hd) for vertex %d %s, expected (%hd, %hd, %hd, %hd).\n", 6542 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]); 6543 break; 6544 } 6545 case D3DDECLTYPE_USHORT2N: 6546 { 6547 USHORT *got = (USHORT*)(got_ptr + decl_ptr->Offset); 6548 USHORT *exp = (USHORT*)(exp_ptr + decl_ptr->Offset); 6549 BOOL same = got[0] == exp[0] && got[1] == exp[1]; 6550 ok_(__FILE__,line)(same, "Mesh %d: Got (%hu, %hu) for vertex %d %s, expected (%hu, %hu).\n", 6551 mesh_number, got[0], got[1], vertex_number, usage_strings[decl_ptr->Usage], exp[0], exp[1]); 6552 break; 6553 } 6554 case D3DDECLTYPE_USHORT4N: 6555 { 6556 USHORT *got = (USHORT*)(got_ptr + decl_ptr->Offset); 6557 USHORT *exp = (USHORT*)(exp_ptr + decl_ptr->Offset); 6558 BOOL same = got[0] == exp[0] && got[1] == exp[1] 6559 && got[2] == exp[2] && got[3] == exp[3]; 6560 ok_(__FILE__,line)(same, "Mesh %d: Got (%hu, %hu, %hu, %hu) for vertex %d %s, expected (%hu, %hu, %hu, %hu).\n", 6561 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]); 6562 break; 6563 } 6564 case D3DDECLTYPE_UDEC3: 6565 { 6566 DWORD *got = (DWORD*)(got_ptr + decl_ptr->Offset); 6567 DWORD *exp = (DWORD*)(exp_ptr + decl_ptr->Offset); 6568 BOOL same = memcmp(got, exp, sizeof(*got)) == 0; 6569 struct udec3 got_udec3 = dword_to_udec3(*got); 6570 struct udec3 exp_udec3 = dword_to_udec3(*exp); 6571 ok_(__FILE__,line)(same, "Mesh %d: Got (%u, %u, %u, %u) for vertex %d %s, expected (%u, %u, %u, %u).\n", 6572 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); 6573 6574 break; 6575 } 6576 case D3DDECLTYPE_DEC3N: 6577 { 6578 DWORD *got = (DWORD*)(got_ptr + decl_ptr->Offset); 6579 DWORD *exp = (DWORD*)(exp_ptr + decl_ptr->Offset); 6580 BOOL same = memcmp(got, exp, sizeof(*got)) == 0; 6581 struct dec3n got_dec3n = dword_to_dec3n(*got); 6582 struct dec3n exp_dec3n = dword_to_dec3n(*exp); 6583 ok_(__FILE__,line)(same, "Mesh %d: Got (%d, %d, %d, %d) for vertex %d %s, expected (%d, %d, %d, %d).\n", 6584 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); 6585 break; 6586 } 6587 case D3DDECLTYPE_FLOAT16_2: 6588 { 6589 WORD *got = (WORD*)(got_ptr + decl_ptr->Offset); 6590 WORD *exp = (WORD*)(exp_ptr + decl_ptr->Offset); 6591 BOOL same = got[0] == exp[0] && got[1] == exp[1]; 6592 ok_(__FILE__,line)(same, "Mesh %d: Got (%hx, %hx) for vertex %d %s, expected (%hx, %hx).\n", 6593 mesh_number, got[0], got[1], vertex_number, usage_strings[decl_ptr->Usage], exp[0], exp[1]); 6594 break; 6595 } 6596 case D3DDECLTYPE_FLOAT16_4: 6597 { 6598 WORD *got = (WORD*)(got_ptr + decl_ptr->Offset); 6599 WORD *exp = (WORD*)(exp_ptr + decl_ptr->Offset); 6600 BOOL same = got[0] == exp[0] && got[1] == exp[1] 6601 && got[2] == exp[2] && got[3] == exp[3]; 6602 ok_(__FILE__,line)(same, "Mesh %d: Got (%hx, %hx, %hx, %hx) for vertex %d %s, expected (%hx, %hx, %hx, %hx).\n", 6603 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]); 6604 break; 6605 } 6606 default: 6607 break; 6608 } 6609 } 6610 } 6611 6612 static void test_weld_vertices(void) 6613 { 6614 HRESULT hr; 6615 struct test_context *test_context = NULL; 6616 DWORD i; 6617 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM; 6618 const DWORD options_16bit = D3DXMESH_SYSTEMMEM; 6619 BYTE *vertices = NULL; 6620 DWORD *indices = NULL; 6621 WORD *indices_16bit = NULL; 6622 const UINT VERTS_PER_FACE = 3; 6623 #ifndef __REACTOS__ 6624 const D3DXVECTOR3 up = {0.0f, 0.0f, 1.0f}; 6625 #else 6626 #define up {0.0f, 0.0f, 1.0f} 6627 #endif 6628 struct vertex_normal 6629 { 6630 D3DXVECTOR3 position; 6631 D3DXVECTOR3 normal; 6632 }; 6633 struct vertex_blendweight 6634 { 6635 D3DXVECTOR3 position; 6636 FLOAT blendweight; 6637 }; 6638 struct vertex_texcoord 6639 { 6640 D3DXVECTOR3 position; 6641 D3DXVECTOR2 texcoord; 6642 }; 6643 struct vertex_color 6644 { 6645 D3DXVECTOR3 position; 6646 DWORD color; 6647 }; 6648 struct vertex_color_ubyte4 6649 { 6650 D3DXVECTOR3 position; 6651 BYTE color[4]; 6652 }; 6653 struct vertex_texcoord_short2 6654 { 6655 D3DXVECTOR3 position; 6656 SHORT texcoord[2]; 6657 }; 6658 struct vertex_texcoord_ushort2n 6659 { 6660 D3DXVECTOR3 position; 6661 USHORT texcoord[2]; 6662 }; 6663 struct vertex_normal_short4 6664 { 6665 D3DXVECTOR3 position; 6666 SHORT normal[4]; 6667 }; 6668 struct vertex_texcoord_float16_2 6669 { 6670 D3DXVECTOR3 position; 6671 WORD texcoord[2]; 6672 }; 6673 struct vertex_texcoord_float16_4 6674 { 6675 D3DXVECTOR3 position; 6676 WORD texcoord[4]; 6677 }; 6678 struct vertex_normal_udec3 6679 { 6680 D3DXVECTOR3 position; 6681 DWORD normal; 6682 }; 6683 struct vertex_normal_dec3n 6684 { 6685 D3DXVECTOR3 position; 6686 DWORD normal; 6687 }; 6688 UINT vertex_size_normal = sizeof(struct vertex_normal); 6689 UINT vertex_size_blendweight = sizeof(struct vertex_blendweight); 6690 UINT vertex_size_texcoord = sizeof(struct vertex_texcoord); 6691 UINT vertex_size_color = sizeof(struct vertex_color); 6692 UINT vertex_size_color_ubyte4 = sizeof(struct vertex_color_ubyte4); 6693 UINT vertex_size_texcoord_short2 = sizeof(struct vertex_texcoord_short2); 6694 UINT vertex_size_normal_short4 = sizeof(struct vertex_normal_short4); 6695 UINT vertex_size_texcoord_float16_2 = sizeof(struct vertex_texcoord_float16_2); 6696 UINT vertex_size_texcoord_float16_4 = sizeof(struct vertex_texcoord_float16_4); 6697 UINT vertex_size_normal_udec3 = sizeof(struct vertex_normal_udec3); 6698 UINT vertex_size_normal_dec3n = sizeof(struct vertex_normal_dec3n); 6699 D3DVERTEXELEMENT9 declaration_normal[] = 6700 { 6701 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 6702 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 6703 D3DDECL_END() 6704 }; 6705 D3DVERTEXELEMENT9 declaration_normal3[] = 6706 { 6707 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 3}, 6708 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 6709 D3DDECL_END() 6710 }; 6711 D3DVERTEXELEMENT9 declaration_blendweight[] = 6712 { 6713 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 6714 {0, 12, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BLENDWEIGHT, 0}, 6715 D3DDECL_END() 6716 }; 6717 D3DVERTEXELEMENT9 declaration_texcoord[] = 6718 { 6719 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 6720 {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 6721 D3DDECL_END() 6722 }; 6723 D3DVERTEXELEMENT9 declaration_color[] = 6724 { 6725 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 6726 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0}, 6727 D3DDECL_END() 6728 }; 6729 D3DVERTEXELEMENT9 declaration_color_ubyte4n[] = 6730 { 6731 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 6732 {0, 12, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0}, 6733 D3DDECL_END() 6734 }; 6735 D3DVERTEXELEMENT9 declaration_color_ubyte4[] = 6736 { 6737 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 6738 {0, 12, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0}, 6739 D3DDECL_END() 6740 }; 6741 D3DVERTEXELEMENT9 declaration_texcoord_short2[] = 6742 { 6743 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 6744 {0, 12, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 6745 D3DDECL_END() 6746 }; 6747 D3DVERTEXELEMENT9 declaration_texcoord_short2n[] = 6748 { 6749 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 6750 {0, 12, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 6751 D3DDECL_END() 6752 }; 6753 D3DVERTEXELEMENT9 declaration_texcoord_ushort2n[] = 6754 { 6755 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 6756 {0, 12, D3DDECLTYPE_USHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 6757 D3DDECL_END() 6758 }; 6759 D3DVERTEXELEMENT9 declaration_normal_short4[] = 6760 { 6761 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 6762 {0, 12, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 6763 D3DDECL_END() 6764 }; 6765 D3DVERTEXELEMENT9 declaration_normal_short4n[] = 6766 { 6767 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 6768 {0, 12, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 6769 D3DDECL_END() 6770 }; 6771 D3DVERTEXELEMENT9 declaration_normal_ushort4n[] = 6772 { 6773 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 6774 {0, 12, D3DDECLTYPE_USHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 6775 D3DDECL_END() 6776 }; 6777 D3DVERTEXELEMENT9 declaration_texcoord10[] = 6778 { 6779 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 6780 {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 10}, 6781 D3DDECL_END() 6782 }; 6783 D3DVERTEXELEMENT9 declaration_color2[] = 6784 { 6785 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 6786 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 2}, 6787 D3DDECL_END() 6788 }; 6789 D3DVERTEXELEMENT9 declaration_color1[] = 6790 { 6791 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 6792 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 1}, 6793 D3DDECL_END() 6794 }; 6795 D3DVERTEXELEMENT9 declaration_texcoord_float16_2[] = 6796 { 6797 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 6798 {0, 12, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 6799 D3DDECL_END() 6800 }; 6801 D3DVERTEXELEMENT9 declaration_texcoord_float16_4[] = 6802 { 6803 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 6804 {0, 12, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 6805 D3DDECL_END() 6806 }; 6807 D3DVERTEXELEMENT9 declaration_normal_udec3[] = 6808 { 6809 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 6810 {0, 12, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 6811 D3DDECL_END() 6812 }; 6813 D3DVERTEXELEMENT9 declaration_normal_dec3n[] = 6814 { 6815 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 6816 {0, 12, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 6817 D3DDECL_END() 6818 }; 6819 /* Test 0. One face and no welding. 6820 * 6821 * 0--1 6822 * | / 6823 * |/ 6824 * 2 6825 */ 6826 const struct vertex vertices0[] = 6827 { 6828 {{ 0.0f, 3.0f, 0.f}, up}, 6829 {{ 2.0f, 3.0f, 0.f}, up}, 6830 {{ 0.0f, 0.0f, 0.f}, up}, 6831 }; 6832 const DWORD indices0[] = {0, 1, 2}; 6833 const DWORD attributes0[] = {0}; 6834 const DWORD exp_indices0[] = {0, 1, 2}; 6835 const UINT num_vertices0 = ARRAY_SIZE(vertices0); 6836 const UINT num_faces0 = ARRAY_SIZE(indices0) / VERTS_PER_FACE; 6837 const DWORD flags0 = D3DXWELDEPSILONS_WELDALL; 6838 /* epsilons0 is NULL */ 6839 const DWORD adjacency0[] = {-1, -1, -1}; 6840 const struct vertex exp_vertices0[] = 6841 { 6842 {{ 0.0f, 3.0f, 0.f}, up}, 6843 {{ 2.0f, 3.0f, 0.f}, up}, 6844 {{ 0.0f, 0.0f, 0.f}, up}, 6845 }; 6846 const DWORD exp_face_remap0[] = {0}; 6847 const DWORD exp_vertex_remap0[] = {0, 1, 2}; 6848 const DWORD exp_new_num_vertices0 = ARRAY_SIZE(exp_vertices0); 6849 /* Test 1. Two vertices should be removed without regard to epsilon. 6850 * 6851 * 0--1 3 6852 * | / /| 6853 * |/ / | 6854 * 2 5--4 6855 */ 6856 const struct vertex_normal vertices1[] = 6857 { 6858 {{ 0.0f, 3.0f, 0.f}, up}, 6859 {{ 2.0f, 3.0f, 0.f}, up}, 6860 {{ 0.0f, 0.0f, 0.f}, up}, 6861 6862 {{ 3.0f, 3.0f, 0.f}, up}, 6863 {{ 3.0f, 0.0f, 0.f}, up}, 6864 {{ 1.0f, 0.0f, 0.f}, up}, 6865 }; 6866 const DWORD indices1[] = {0, 1, 2, 3, 4, 5}; 6867 const DWORD attributes1[] = {0, 0}; 6868 const UINT num_vertices1 = ARRAY_SIZE(vertices1); 6869 const UINT num_faces1 = ARRAY_SIZE(indices1) / VERTS_PER_FACE; 6870 const DWORD flags1 = D3DXWELDEPSILONS_WELDALL; 6871 /* epsilons1 is NULL */ 6872 const DWORD adjacency1[] = {-1, 1, -1, -1, -1, 0}; 6873 const struct vertex_normal exp_vertices1[] = 6874 { 6875 {{ 0.0f, 3.0f, 0.f}, up}, 6876 {{ 2.0f, 3.0f, 0.f}, up}, 6877 {{ 0.0f, 0.0f, 0.f}, up}, 6878 6879 {{ 3.0f, 0.0f, 0.f}, up} 6880 }; 6881 const DWORD exp_indices1[] = {0, 1, 2, 1, 3, 2}; 6882 const DWORD exp_face_remap1[] = {0, 1}; 6883 const DWORD exp_vertex_remap1[] = {0, 1, 2, 4, -1, -1}; 6884 const DWORD exp_new_num_vertices1 = ARRAY_SIZE(exp_vertices1); 6885 /* Test 2. Two faces. No vertices should be removed because of normal 6886 * epsilon, but the positions should be replaced. */ 6887 const struct vertex_normal vertices2[] = 6888 { 6889 {{ 0.0f, 3.0f, 0.f}, up}, 6890 {{ 2.0f, 3.0f, 0.f}, up}, 6891 {{ 0.0f, 0.0f, 0.f}, up}, 6892 6893 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}}, 6894 {{ 3.0f, 0.0f, 0.f}, up}, 6895 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}}, 6896 }; 6897 const DWORD indices2[] = {0, 1, 2, 3, 4, 5}; 6898 const DWORD attributes2[] = {0, 0}; 6899 const UINT num_vertices2 = ARRAY_SIZE(vertices2); 6900 const UINT num_faces2 = ARRAY_SIZE(indices2) / VERTS_PER_FACE; 6901 DWORD flags2 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 6902 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}; 6903 const DWORD adjacency2[] = {-1, 1, -1, -1, -1, 0}; 6904 const struct vertex_normal exp_vertices2[] = 6905 { 6906 {{ 0.0f, 3.0f, 0.f}, up}, 6907 {{ 2.0f, 3.0f, 0.f}, up}, 6908 {{ 0.0f, 0.0f, 0.f}, up}, 6909 6910 {{ 2.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}}, 6911 {{ 3.0f, 0.0f, 0.f}, up}, 6912 {{ 0.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}}, 6913 }; 6914 const DWORD exp_indices2[] = {0, 1, 2, 3, 4, 5}; 6915 const DWORD exp_face_remap2[] = {0, 1}; 6916 const DWORD exp_vertex_remap2[] = {0, 1, 2, 3, 4, 5}; 6917 const DWORD exp_new_num_vertices2 = ARRAY_SIZE(exp_vertices2); 6918 /* Test 3. Two faces. One vertex should be removed because of normal epsilon. */ 6919 const struct vertex_normal vertices3[] = 6920 { 6921 {{ 0.0f, 3.0f, 0.f}, up}, 6922 {{ 2.0f, 3.0f, 0.f}, up}, 6923 {{ 0.0f, 0.0f, 0.f}, up}, 6924 6925 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}}, 6926 {{ 3.0f, 0.0f, 0.f}, up}, 6927 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}}, 6928 }; 6929 const DWORD indices3[] = {0, 1, 2, 3, 4, 5}; 6930 const DWORD attributes3[] = {0, 0}; 6931 const UINT num_vertices3 = ARRAY_SIZE(vertices3); 6932 const UINT num_faces3 = ARRAY_SIZE(indices3) / VERTS_PER_FACE; 6933 DWORD flags3 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 6934 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}; 6935 const DWORD adjacency3[] = {-1, 1, -1, -1, -1, 0}; 6936 const struct vertex_normal exp_vertices3[] = 6937 { 6938 {{ 0.0f, 3.0f, 0.f}, up}, 6939 {{ 2.0f, 3.0f, 0.f}, up}, 6940 {{ 0.0f, 0.0f, 0.f}, up}, 6941 6942 {{ 3.0f, 0.0f, 0.f}, up}, 6943 {{ 0.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}}, 6944 }; 6945 const DWORD exp_indices3[] = {0, 1, 2, 1, 3, 4}; 6946 const DWORD exp_face_remap3[] = {0, 1}; 6947 const DWORD exp_vertex_remap3[] = {0, 1, 2, 4, 5, -1}; 6948 const DWORD exp_new_num_vertices3 = ARRAY_SIZE(exp_vertices3); 6949 /* Test 4 Two faces. Two vertices should be removed. */ 6950 const struct vertex_normal vertices4[] = 6951 { 6952 {{ 0.0f, 3.0f, 0.f}, up}, 6953 {{ 2.0f, 3.0f, 0.f}, up}, 6954 {{ 0.0f, 0.0f, 0.f}, up}, 6955 6956 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}}, 6957 {{ 3.0f, 0.0f, 0.f}, up}, 6958 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}}, 6959 }; 6960 const DWORD indices4[] = {0, 1, 2, 3, 4, 5}; 6961 const DWORD attributes4[] = {0, 0}; 6962 const UINT num_vertices4 = ARRAY_SIZE(vertices4); 6963 const UINT num_faces4 = ARRAY_SIZE(indices4) / VERTS_PER_FACE; 6964 DWORD flags4 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 6965 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}; 6966 const DWORD adjacency4[] = {-1, 1, -1, -1, -1, 0}; 6967 const struct vertex_normal exp_vertices4[] = 6968 { 6969 {{ 0.0f, 3.0f, 0.f}, up}, 6970 {{ 2.0f, 3.0f, 0.f}, up}, 6971 {{ 0.0f, 0.0f, 0.f}, up}, 6972 6973 {{ 3.0f, 0.0f, 0.f}, up}, 6974 }; 6975 const DWORD exp_indices4[] = {0, 1, 2, 1, 3, 2}; 6976 const DWORD exp_face_remap4[] = {0, 1}; 6977 const DWORD exp_vertex_remap4[] = {0, 1, 2, 4, -1, -1}; 6978 const DWORD exp_new_num_vertices4 = ARRAY_SIZE(exp_vertices4); 6979 /* Test 5. Odd face ordering. 6980 * 6981 * 0--1 6 3 6982 * | / /| |\ 6983 * |/ / | | \ 6984 * 2 8--7 5--4 6985 */ 6986 const struct vertex_normal vertices5[] = 6987 { 6988 {{ 0.0f, 3.0f, 0.f}, up}, 6989 {{ 2.0f, 3.0f, 0.f}, up}, 6990 {{ 0.0f, 0.0f, 0.f}, up}, 6991 6992 {{ 3.0f, 3.0f, 0.f}, up}, 6993 {{ 3.0f, 0.0f, 0.f}, up}, 6994 {{ 1.0f, 0.0f, 0.f}, up}, 6995 6996 {{ 4.0f, 3.0f, 0.f}, up}, 6997 {{ 6.0f, 0.0f, 0.f}, up}, 6998 {{ 4.0f, 0.0f, 0.f}, up}, 6999 }; 7000 const DWORD indices5[] = {0, 1, 2, 6, 7, 8, 3, 4, 5}; 7001 const DWORD exp_indices5[] = {0, 1, 2, 1, 4, 2, 1, 3, 4}; 7002 const DWORD attributes5[] = {0, 0, 0}; 7003 const UINT num_vertices5 = ARRAY_SIZE(vertices5); 7004 const UINT num_faces5 = ARRAY_SIZE(indices5) / VERTS_PER_FACE; 7005 DWORD flags5 = D3DXWELDEPSILONS_WELDALL; 7006 const DWORD adjacency5[] = {-1, 1, -1, 2, -1, 0, -1, -1, 1}; 7007 const struct vertex_normal exp_vertices5[] = 7008 { 7009 {{ 0.0f, 3.0f, 0.f}, up}, 7010 {{ 2.0f, 3.0f, 0.f}, up}, 7011 {{ 0.0f, 0.0f, 0.f}, up}, 7012 7013 {{ 3.0f, 0.0f, 0.f}, up}, 7014 {{ 1.0f, 0.0f, 0.f}, up}, 7015 }; 7016 const DWORD exp_face_remap5[] = {0, 1, 2}; 7017 const DWORD exp_vertex_remap5[] = {0, 1, 2, 4, 5, -1, -1, -1, -1}; 7018 const DWORD exp_new_num_vertices5 = ARRAY_SIZE(exp_vertices5); 7019 /* Test 6. Two faces. Do not remove flag is used, so no vertices should be 7020 * removed. */ 7021 const struct vertex_normal vertices6[] = 7022 { 7023 {{ 0.0f, 3.0f, 0.f}, up}, 7024 {{ 2.0f, 3.0f, 0.f}, up}, 7025 {{ 0.0f, 0.0f, 0.f}, up}, 7026 7027 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}}, 7028 {{ 3.0f, 0.0f, 0.f}, up}, 7029 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}}, 7030 }; 7031 const DWORD indices6[] = {0, 1, 2, 3, 4, 5}; 7032 const DWORD attributes6[] = {0, 0}; 7033 const UINT num_vertices6 = ARRAY_SIZE(vertices6); 7034 const UINT num_faces6 = ARRAY_SIZE(indices6) / VERTS_PER_FACE; 7035 DWORD flags6 = D3DXWELDEPSILONS_WELDPARTIALMATCHES | D3DXWELDEPSILONS_DONOTREMOVEVERTICES; 7036 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}; 7037 const DWORD adjacency6[] = {-1, 1, -1, -1, -1, 0}; 7038 const struct vertex_normal exp_vertices6[] = 7039 { 7040 {{ 0.0f, 3.0f, 0.f}, up}, 7041 {{ 2.0f, 3.0f, 0.f}, up}, 7042 {{ 0.0f, 0.0f, 0.f}, up}, 7043 7044 {{ 2.0f, 3.0f, 0.f}, up}, 7045 {{ 3.0f, 0.0f, 0.f}, up}, 7046 {{ 0.0f, 0.0f, 0.f}, up}, 7047 7048 }; 7049 const DWORD exp_indices6[] = {0, 1, 2, 3, 4, 5}; 7050 const DWORD exp_face_remap6[] = {0, 1}; 7051 const DWORD exp_vertex_remap6[] = {0, 1, 2, 3, 4, 5}; 7052 const DWORD exp_new_num_vertices6 = ARRAY_SIZE(exp_vertices6); 7053 /* Test 7. Same as test 6 but with 16 bit indices. */ 7054 const WORD indices6_16bit[] = {0, 1, 2, 3, 4, 5}; 7055 /* Test 8. No flags. Same result as D3DXWELDEPSILONS_WELDPARTIALMATCHES. */ 7056 const struct vertex_normal vertices8[] = 7057 { 7058 {{ 0.0f, 3.0f, 0.f}, up}, 7059 {{ 2.0f, 3.0f, 0.f}, up}, 7060 {{ 0.0f, 0.0f, 0.f}, up}, 7061 7062 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}}, 7063 {{ 3.0f, 0.0f, 0.f}, up}, 7064 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}}, 7065 }; 7066 const DWORD indices8[] = {0, 1, 2, 1, 3, 4}; 7067 const DWORD attributes8[] = {0, 0}; 7068 const UINT num_vertices8 = ARRAY_SIZE(vertices8); 7069 const UINT num_faces8 = ARRAY_SIZE(indices8) / VERTS_PER_FACE; 7070 DWORD flags8 = 0; 7071 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}; 7072 const DWORD adjacency8[] = {-1, 1, -1, -1, -1, 0}; 7073 const struct vertex_normal exp_vertices8[] = 7074 { 7075 {{ 0.0f, 3.0f, 0.f}, up}, 7076 {{ 2.0f, 3.0f, 0.f}, up}, 7077 {{ 0.0f, 0.0f, 0.f}, up}, 7078 7079 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}}, 7080 {{ 3.0f, 0.0f, 0.f}, up}, 7081 }; 7082 const DWORD exp_indices8[] = {0, 1, 2, 1, 3, 4}; 7083 const DWORD exp_face_remap8[] = {0, 1}; 7084 const DWORD exp_vertex_remap8[] = {0, 1, 2, 3, 4, -1}; 7085 const DWORD exp_new_num_vertices8 = ARRAY_SIZE(exp_vertices8); 7086 /* Test 9. Vertices are removed even though they belong to separate 7087 * attribute groups if D3DXWELDEPSILONS_DONOTSPLIT is set. */ 7088 const struct vertex_normal vertices9[] = 7089 { 7090 {{ 0.0f, 3.0f, 0.f}, up}, 7091 {{ 2.0f, 3.0f, 0.f}, up}, 7092 {{ 0.0f, 0.0f, 0.f}, up}, 7093 7094 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}}, 7095 {{ 3.0f, 0.0f, 0.f}, up}, 7096 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}}, 7097 }; 7098 const DWORD indices9[] = {0, 1, 2, 3, 4, 5}; 7099 const DWORD attributes9[] = {0, 1}; 7100 const UINT num_vertices9 = ARRAY_SIZE(vertices9); 7101 const UINT num_faces9 = ARRAY_SIZE(indices9) / VERTS_PER_FACE; 7102 DWORD flags9 = D3DXWELDEPSILONS_WELDPARTIALMATCHES | D3DXWELDEPSILONS_DONOTSPLIT; 7103 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}; 7104 const DWORD adjacency9[] = {-1, 1, -1, -1, -1, 0}; 7105 const struct vertex_normal exp_vertices9[] = 7106 { 7107 {{ 0.0f, 3.0f, 0.f}, up}, 7108 {{ 2.0f, 3.0f, 0.f}, up}, 7109 {{ 0.0f, 0.0f, 0.f}, up}, 7110 7111 {{ 3.0f, 0.0f, 0.f}, up}, 7112 }; 7113 const DWORD exp_indices9[] = {0, 1, 2, 1, 3, 2}; 7114 const DWORD exp_face_remap9[] = {0, 1}; 7115 const DWORD exp_vertex_remap9[] = {0, 1, 2, 4, -1, -1}; 7116 const DWORD exp_new_num_vertices9 = ARRAY_SIZE(exp_vertices9); 7117 /* Test 10. Weld blendweight (FLOAT1). */ 7118 const struct vertex_blendweight vertices10[] = 7119 { 7120 {{ 0.0f, 3.0f, 0.f}, 1.0f}, 7121 {{ 2.0f, 3.0f, 0.f}, 1.0f}, 7122 {{ 0.0f, 0.0f, 0.f}, 1.0f}, 7123 7124 {{ 3.0f, 3.0f, 0.f}, 0.9}, 7125 {{ 3.0f, 0.0f, 0.f}, 1.0}, 7126 {{ 1.0f, 0.0f, 0.f}, 0.4}, 7127 }; 7128 const DWORD indices10[] = {0, 1, 2, 3, 4, 5}; 7129 const DWORD attributes10[] = {0, 0}; 7130 const UINT num_vertices10 = ARRAY_SIZE(vertices10); 7131 const UINT num_faces10 = ARRAY_SIZE(indices10) / VERTS_PER_FACE; 7132 DWORD flags10 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7133 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}; 7134 const DWORD adjacency10[] = {-1, 1, -1, -1, -1, 0}; 7135 const struct vertex_blendweight exp_vertices10[] = 7136 { 7137 {{ 0.0f, 3.0f, 0.f}, 1.0f}, 7138 {{ 2.0f, 3.0f, 0.f}, 1.0f}, 7139 {{ 0.0f, 0.0f, 0.f}, 1.0f}, 7140 7141 {{ 3.0f, 0.0f, 0.f}, 1.0}, 7142 {{ 0.0f, 0.0f, 0.f}, 0.4}, 7143 }; 7144 const DWORD exp_indices10[] = {0, 1, 2, 1, 3, 4}; 7145 const DWORD exp_face_remap10[] = {0, 1}; 7146 const DWORD exp_vertex_remap10[] = {0, 1, 2, 4, 5, -1}; 7147 const DWORD exp_new_num_vertices10 = ARRAY_SIZE(exp_vertices10); 7148 /* Test 11. Weld texture coordinates. */ 7149 const struct vertex_texcoord vertices11[] = 7150 { 7151 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f}}, 7152 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.7f}}, 7153 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}}, 7154 7155 {{ 3.0f, 3.0f, 0.f}, {0.2f, 0.3f}}, 7156 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f}}, 7157 {{ 1.0f, 0.0f, 0.f}, {0.1f, 0.2f}} 7158 }; 7159 const DWORD indices11[] = {0, 1, 2, 3, 4, 5}; 7160 const DWORD attributes11[] = {0, 0}; 7161 const UINT num_vertices11 = ARRAY_SIZE(vertices11); 7162 const UINT num_faces11 = ARRAY_SIZE(indices11) / VERTS_PER_FACE; 7163 DWORD flags11 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7164 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}; 7165 const DWORD adjacency11[] = {-1, 1, -1, -1, -1, 0}; 7166 const struct vertex_texcoord exp_vertices11[] = 7167 { 7168 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f}}, 7169 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.7f}}, 7170 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}}, 7171 7172 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f}}, 7173 {{ 0.0f, 0.0f, 0.f}, {0.1f, 0.2f}}, 7174 }; 7175 const DWORD exp_indices11[] = {0, 1, 2, 1, 3, 4}; 7176 const DWORD exp_face_remap11[] = {0, 1}; 7177 const DWORD exp_vertex_remap11[] = {0, 1, 2, 4, 5, -1}; 7178 const DWORD exp_new_num_vertices11 = ARRAY_SIZE(exp_vertices11); 7179 /* Test 12. Weld with color. */ 7180 const struct vertex_color vertices12[] = 7181 { 7182 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF}, 7183 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF}, 7184 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF}, 7185 7186 {{ 3.0f, 3.0f, 0.f}, 0x00000000}, 7187 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF}, 7188 {{ 1.0f, 0.0f, 0.f}, 0x88888888}, 7189 }; 7190 const DWORD indices12[] = {0, 1, 2, 3, 4, 5}; 7191 const DWORD attributes12[] = {0, 0}; 7192 const UINT num_vertices12 = ARRAY_SIZE(vertices12); 7193 const UINT num_faces12 = ARRAY_SIZE(indices12) / VERTS_PER_FACE; 7194 DWORD flags12 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7195 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}; 7196 const DWORD adjacency12[] = {-1, 1, -1, -1, -1, 0}; 7197 const struct vertex_color exp_vertices12[] = 7198 { 7199 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF}, 7200 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF}, 7201 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF}, 7202 7203 {{ 2.0f, 3.0f, 0.f}, 0x00000000}, 7204 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF}, 7205 }; 7206 const DWORD exp_indices12[] = {0, 1, 2, 3, 4, 2}; 7207 const DWORD exp_face_remap12[] = {0, 1}; 7208 const DWORD exp_vertex_remap12[] = {0, 1, 2, 3, 4, -1}; 7209 const DWORD exp_new_num_vertices12 = ARRAY_SIZE(exp_vertices12); 7210 /* Test 13. Two faces. One vertex should be removed because of normal epsilon. 7211 * This is similar to test 3, but the declaration has been changed to NORMAL3. 7212 */ 7213 const struct vertex_normal vertices13[] = 7214 { 7215 {{ 0.0f, 3.0f, 0.f}, up}, 7216 {{ 2.0f, 3.0f, 0.f}, up}, 7217 {{ 0.0f, 0.0f, 0.f}, up}, 7218 7219 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}}, 7220 {{ 3.0f, 0.0f, 0.f}, up}, 7221 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}}, 7222 }; 7223 const DWORD indices13[] = {0, 1, 2, 3, 4, 5}; 7224 const DWORD attributes13[] = {0, 0}; 7225 const UINT num_vertices13 = ARRAY_SIZE(vertices3); 7226 const UINT num_faces13 = ARRAY_SIZE(indices3) / VERTS_PER_FACE; 7227 DWORD flags13 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7228 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}; 7229 const DWORD adjacency13[] = {-1, 1, -1, -1, -1, 0}; 7230 const struct vertex_normal exp_vertices13[] = 7231 { 7232 {{ 0.0f, 3.0f, 0.f}, up}, 7233 {{ 2.0f, 3.0f, 0.f}, up}, 7234 {{ 0.0f, 0.0f, 0.f}, up}, 7235 7236 {{ 3.0f, 0.0f, 0.f}, up}, 7237 {{ 0.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}}, 7238 }; 7239 const DWORD exp_indices13[] = {0, 1, 2, 1, 3, 4}; 7240 const DWORD exp_face_remap13[] = {0, 1}; 7241 const DWORD exp_vertex_remap13[] = {0, 1, 2, 4, 5, -1}; 7242 const DWORD exp_new_num_vertices13 = ARRAY_SIZE(exp_vertices13); 7243 /* Test 14. Another test for welding with color. */ 7244 const struct vertex_color vertices14[] = 7245 { 7246 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF}, 7247 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF}, 7248 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF}, 7249 7250 {{ 3.0f, 3.0f, 0.f}, 0x00000000}, 7251 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF}, 7252 {{ 1.0f, 0.0f, 0.f}, 0x01010101}, 7253 }; 7254 const DWORD indices14[] = {0, 1, 2, 3, 4, 5}; 7255 const DWORD attributes14[] = {0, 0}; 7256 const UINT num_vertices14 = ARRAY_SIZE(vertices14); 7257 const UINT num_faces14 = ARRAY_SIZE(indices14) / VERTS_PER_FACE; 7258 DWORD flags14 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7259 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}; 7260 const DWORD adjacency14[] = {-1, 1, -1, -1, -1, 0}; 7261 const struct vertex_color exp_vertices14[] = 7262 { 7263 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF}, 7264 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF}, 7265 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF}, 7266 7267 {{ 2.0f, 3.0f, 0.f}, 0x00000000}, 7268 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF}, 7269 }; 7270 const DWORD exp_indices14[] = {0, 1, 2, 3, 4, 2}; 7271 const DWORD exp_face_remap14[] = {0, 1}; 7272 const DWORD exp_vertex_remap14[] = {0, 1, 2, 3, 4, -1}; 7273 const DWORD exp_new_num_vertices14 = ARRAY_SIZE(exp_vertices14); 7274 /* Test 15. Weld with color, but as UBYTE4N instead of D3DCOLOR. It shows 7275 * that UBYTE4N and D3DCOLOR are compared the same way. 7276 */ 7277 const struct vertex_color_ubyte4 vertices15[] = 7278 { 7279 {{ 0.0f, 3.0f, 0.f}, {255, 255, 255, 255}}, 7280 {{ 2.0f, 3.0f, 0.f}, {255, 255, 255, 255}}, 7281 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}}, 7282 7283 {{ 3.0f, 3.0f, 0.f}, { 0, 0, 0, 0}}, 7284 {{ 3.0f, 0.0f, 0.f}, {255, 255, 255, 255}}, 7285 {{ 1.0f, 0.0f, 0.f}, { 1, 1, 1, 1}}, 7286 }; 7287 const DWORD indices15[] = {0, 1, 2, 3, 4, 5}; 7288 const DWORD attributes15[] = {0, 0}; 7289 const UINT num_vertices15 = ARRAY_SIZE(vertices15); 7290 const UINT num_faces15 = ARRAY_SIZE(indices15) / VERTS_PER_FACE; 7291 DWORD flags15 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7292 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}; 7293 const DWORD adjacency15[] = {-1, 1, -1, -1, -1, 0}; 7294 const struct vertex_color_ubyte4 exp_vertices15[] = 7295 { 7296 {{ 0.0f, 3.0f, 0.f}, {255, 255, 255, 255}}, 7297 {{ 2.0f, 3.0f, 0.f}, {255, 255, 255, 255}}, 7298 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}}, 7299 7300 {{ 2.0f, 3.0f, 0.f}, { 0, 0, 0, 0}}, 7301 {{ 3.0f, 0.0f, 0.f}, {255, 255, 255, 255}}, 7302 }; 7303 const DWORD exp_indices15[] = {0, 1, 2, 3, 4, 2}; 7304 const DWORD exp_face_remap15[] = {0, 1}; 7305 const DWORD exp_vertex_remap15[] = {0, 1, 2, 3, 4, -1}; 7306 const DWORD exp_new_num_vertices15 = ARRAY_SIZE(exp_vertices15); 7307 /* Test 16. Weld with color, but as UBYTE4 instead of D3DCOLOR. It shows 7308 * that UBYTE4 is not normalized and that epsilon is truncated and compared 7309 * directly to each of the four bytes. 7310 */ 7311 const struct vertex_color_ubyte4 vertices16[] = 7312 { 7313 {{ 0.0f, 3.0f, 0.f}, {255, 255, 255, 255}}, 7314 {{ 2.0f, 3.0f, 0.f}, {255, 255, 255, 255}}, 7315 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}}, 7316 7317 {{ 3.0f, 3.0f, 0.f}, { 0, 0, 0, 0}}, 7318 {{ 3.0f, 0.0f, 0.f}, {255, 255, 255, 255}}, 7319 {{ 1.0f, 0.0f, 0.f}, { 1, 1, 1, 1}}, 7320 }; 7321 const DWORD indices16[] = {0, 1, 2, 3, 4, 5}; 7322 const DWORD attributes16[] = {0, 0}; 7323 const UINT num_vertices16 = ARRAY_SIZE(vertices16); 7324 const UINT num_faces16 = ARRAY_SIZE(indices16) / VERTS_PER_FACE; 7325 DWORD flags16 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7326 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}; 7327 const DWORD adjacency16[] = {-1, 1, -1, -1, -1, 0}; 7328 const struct vertex_color_ubyte4 exp_vertices16[] = 7329 { 7330 {{ 0.0f, 3.0f, 0.f}, {255, 255, 255, 255}}, 7331 {{ 2.0f, 3.0f, 0.f}, {255, 255, 255, 255}}, 7332 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}}, 7333 7334 {{ 2.0f, 3.0f, 0.f}, { 0, 0, 0, 0}}, 7335 {{ 3.0f, 0.0f, 0.f}, {255, 255, 255, 255}}, 7336 }; 7337 const DWORD exp_indices16[] = {0, 1, 2, 3, 4, 2}; 7338 const DWORD exp_face_remap16[] = {0, 1}; 7339 const DWORD exp_vertex_remap16[] = {0, 1, 2, 3, 4, -1}; 7340 const DWORD exp_new_num_vertices16 = ARRAY_SIZE(exp_vertices16); 7341 /* Test 17. Weld texture coordinates but as SHORT2 instead of D3DXVECTOR2.*/ 7342 const struct vertex_texcoord_short2 vertices17[] = 7343 { 7344 {{ 0.0f, 3.0f, 0.f}, { 0, 0}}, 7345 {{ 2.0f, 3.0f, 0.f}, { 0, 0}}, 7346 {{ 0.0f, 0.0f, 0.f}, { 0, 0}}, 7347 7348 {{ 3.0f, 3.0f, 0.f}, {32767, 32767}}, 7349 {{ 3.0f, 0.0f, 0.f}, {0, 0}}, 7350 {{ 1.0f, 0.0f, 0.f}, {32766, 32766}}, 7351 }; 7352 const DWORD indices17[] = {0, 1, 2, 3, 4, 5}; 7353 const DWORD attributes17[] = {0, 0}; 7354 const UINT num_vertices17 = ARRAY_SIZE(vertices17); 7355 const UINT num_faces17 = ARRAY_SIZE(indices17) / VERTS_PER_FACE; 7356 DWORD flags17 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7357 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}; 7358 const DWORD adjacency17[] = {-1, 1, -1, -1, -1, 0}; 7359 const struct vertex_texcoord_short2 exp_vertices17[] = 7360 { 7361 {{ 0.0f, 3.0f, 0.f}, { 0, 0}}, 7362 {{ 2.0f, 3.0f, 0.f}, { 0, 0}}, 7363 {{ 0.0f, 0.0f, 0.f}, { 0, 0}}, 7364 7365 {{ 2.0f, 3.0f, 0.f}, {32767, 32767}}, 7366 {{ 3.0f, 0.0f, 0.f}, {0, 0}}, 7367 }; 7368 const DWORD exp_indices17[] = {0, 1, 2, 3, 4, 2}; 7369 const DWORD exp_face_remap17[] = {0, 1}; 7370 const DWORD exp_vertex_remap17[] = {0, 1, 2, 3, 4, -1}; 7371 const DWORD exp_new_num_vertices17 = ARRAY_SIZE(exp_vertices17); 7372 /* Test 18. Weld texture coordinates but as SHORT2N instead of D3DXVECTOR2. */ 7373 const struct vertex_texcoord_short2 vertices18[] = 7374 { 7375 {{ 0.0f, 3.0f, 0.f}, { 0, 0}}, 7376 {{ 2.0f, 3.0f, 0.f}, { 0, 0}}, 7377 {{ 0.0f, 0.0f, 0.f}, { 0, 0}}, 7378 7379 {{ 3.0f, 3.0f, 0.f}, {32767, 32767}}, 7380 {{ 3.0f, 0.0f, 0.f}, {0, 0}}, 7381 {{ 1.0f, 0.0f, 0.f}, {32766, 32766}}, 7382 }; 7383 const DWORD indices18[] = {0, 1, 2, 3, 4, 5}; 7384 const DWORD attributes18[] = {0, 0}; 7385 const UINT num_vertices18 = ARRAY_SIZE(vertices18); 7386 const UINT num_faces18 = ARRAY_SIZE(indices18) / VERTS_PER_FACE; 7387 DWORD flags18 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7388 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}; 7389 const DWORD adjacency18[] = {-1, 1, -1, -1, -1, 0}; 7390 const struct vertex_texcoord_short2 exp_vertices18[] = 7391 { 7392 {{ 0.0f, 3.0f, 0.f}, { 0, 0}}, 7393 {{ 2.0f, 3.0f, 0.f}, { 0, 0}}, 7394 {{ 0.0f, 0.0f, 0.f}, { 0, 0}}, 7395 7396 {{ 2.0f, 3.0f, 0.f}, {32767, 32767}}, 7397 {{ 3.0f, 0.0f, 0.f}, {0, 0}}, 7398 }; 7399 const DWORD exp_indices18[] = {0, 1, 2, 3, 4, 2}; 7400 const DWORD exp_face_remap18[] = {0, 1}; 7401 const DWORD exp_vertex_remap18[] = {0, 1, 2, 3, 4, -1}; 7402 const DWORD exp_new_num_vertices18 = ARRAY_SIZE(exp_vertices18); 7403 /* Test 19. Weld texture coordinates but as USHORT2N instead of D3DXVECTOR2. */ 7404 const struct vertex_texcoord_ushort2n vertices19[] = 7405 { 7406 {{ 0.0f, 3.0f, 0.f}, { 0, 0}}, 7407 {{ 2.0f, 3.0f, 0.f}, { 0, 0}}, 7408 {{ 0.0f, 0.0f, 0.f}, { 0, 0}}, 7409 7410 {{ 3.0f, 3.0f, 0.f}, {65535, 65535}}, 7411 {{ 3.0f, 0.0f, 0.f}, {0, 0}}, 7412 {{ 1.0f, 0.0f, 0.f}, {65534, 65534}}, 7413 }; 7414 const DWORD indices19[] = {0, 1, 2, 3, 4, 5}; 7415 const DWORD attributes19[] = {0, 0}; 7416 const UINT num_vertices19 = ARRAY_SIZE(vertices19); 7417 const UINT num_faces19 = ARRAY_SIZE(indices19) / VERTS_PER_FACE; 7418 DWORD flags19 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7419 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}; 7420 const DWORD adjacency19[] = {-1, 1, -1, -1, -1, 0}; 7421 const struct vertex_texcoord_ushort2n exp_vertices19[] = 7422 { 7423 {{ 0.0f, 3.0f, 0.f}, { 0, 0}}, 7424 {{ 2.0f, 3.0f, 0.f}, { 0, 0}}, 7425 {{ 0.0f, 0.0f, 0.f}, { 0, 0}}, 7426 7427 {{ 2.0f, 3.0f, 0.f}, {65535, 65535}}, 7428 {{ 3.0f, 0.0f, 0.f}, {0, 0}}, 7429 }; 7430 const DWORD exp_indices19[] = {0, 1, 2, 3, 4, 2}; 7431 const DWORD exp_face_remap19[] = {0, 1}; 7432 const DWORD exp_vertex_remap19[] = {0, 1, 2, 3, 4, -1}; 7433 const DWORD exp_new_num_vertices19 = ARRAY_SIZE(exp_vertices19); 7434 /* Test 20. Weld normal as SHORT4 instead of D3DXVECTOR3. */ 7435 const struct vertex_normal_short4 vertices20[] = 7436 { 7437 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, 7438 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, 7439 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}}, 7440 7441 {{ 3.0f, 3.0f, 0.f}, {32767, 32767, 32767, 32767}}, 7442 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}}, 7443 {{ 1.0f, 0.0f, 0.f}, {32766, 32766, 32766, 32766}}, 7444 }; 7445 const DWORD indices20[] = {0, 1, 2, 3, 4, 5}; 7446 const DWORD attributes20[] = {0, 0}; 7447 const UINT num_vertices20 = ARRAY_SIZE(vertices20); 7448 const UINT num_faces20 = ARRAY_SIZE(indices20) / VERTS_PER_FACE; 7449 DWORD flags20 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7450 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}; 7451 const DWORD adjacency20[] = {-1, 1, -1, -1, -1, 0}; 7452 const struct vertex_normal_short4 exp_vertices20[] = 7453 { 7454 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, 7455 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, 7456 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}}, 7457 7458 {{ 2.0f, 3.0f, 0.f}, {32767, 32767, 32767, 32767}}, 7459 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}}, 7460 }; 7461 const DWORD exp_indices20[] = {0, 1, 2, 3, 4, 2}; 7462 const DWORD exp_face_remap20[] = {0, 1}; 7463 const DWORD exp_vertex_remap20[] = {0, 1, 2, 3, 4, -1}; 7464 const DWORD exp_new_num_vertices20 = ARRAY_SIZE(exp_vertices20); 7465 /* Test 21. Weld normal as SHORT4N instead of D3DXVECTOR3. */ 7466 const struct vertex_normal_short4 vertices21[] = 7467 { 7468 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, 7469 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, 7470 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}}, 7471 7472 {{ 3.0f, 3.0f, 0.f}, {32767, 32767, 32767, 32767}}, 7473 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}}, 7474 {{ 1.0f, 0.0f, 0.f}, {32766, 32766, 32766, 32766}}, 7475 }; 7476 const DWORD indices21[] = {0, 1, 2, 3, 4, 5}; 7477 const DWORD attributes21[] = {0, 0}; 7478 const UINT num_vertices21 = ARRAY_SIZE(vertices21); 7479 const UINT num_faces21 = ARRAY_SIZE(indices21) / VERTS_PER_FACE; 7480 DWORD flags21 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7481 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}; 7482 const DWORD adjacency21[] = {-1, 1, -1, -1, -1, 0}; 7483 const struct vertex_normal_short4 exp_vertices21[] = 7484 { 7485 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, 7486 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, 7487 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}}, 7488 7489 {{ 2.0f, 3.0f, 0.f}, {32767, 32767, 32767, 32767}}, 7490 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}}, 7491 }; 7492 const DWORD exp_indices21[] = {0, 1, 2, 3, 4, 2}; 7493 const DWORD exp_face_remap21[] = {0, 1}; 7494 const DWORD exp_vertex_remap21[] = {0, 1, 2, 3, 4, -1}; 7495 const DWORD exp_new_num_vertices21 = ARRAY_SIZE(exp_vertices21); 7496 /* Test 22. Weld normal as USHORT4N instead of D3DXVECTOR3. */ 7497 const struct vertex_normal_short4 vertices22[] = 7498 { 7499 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, 7500 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, 7501 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}}, 7502 7503 {{ 3.0f, 3.0f, 0.f}, {65535, 65535, 65535, 65535}}, 7504 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}}, 7505 {{ 1.0f, 0.0f, 0.f}, {65534, 65534, 65534, 65534}}, 7506 }; 7507 const DWORD indices22[] = {0, 1, 2, 3, 4, 5}; 7508 const DWORD attributes22[] = {0, 0}; 7509 const UINT num_vertices22 = ARRAY_SIZE(vertices22); 7510 const UINT num_faces22 = ARRAY_SIZE(indices22) / VERTS_PER_FACE; 7511 DWORD flags22 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7512 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}; 7513 const DWORD adjacency22[] = {-1, 1, -1, -1, -1, 0}; 7514 const struct vertex_normal_short4 exp_vertices22[] = 7515 { 7516 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, 7517 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, 7518 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}}, 7519 7520 {{ 2.0f, 3.0f, 0.f}, {65535, 65535, 65535, 65535}}, 7521 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}}, 7522 }; 7523 const DWORD exp_indices22[] = {0, 1, 2, 3, 4, 2}; 7524 const DWORD exp_face_remap22[] = {0, 1}; 7525 const DWORD exp_vertex_remap22[] = {0, 1, 2, 3, 4, -1}; 7526 const DWORD exp_new_num_vertices22 = ARRAY_SIZE(exp_vertices22); 7527 /* Test 23. Weld texture coordinates as FLOAT16_2. Similar to test 11, but 7528 * with texture coordinates converted to float16 in hex. */ 7529 const struct vertex_texcoord_float16_2 vertices23[] = 7530 { 7531 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */ 7532 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */ 7533 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */ 7534 7535 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd}}, /* {0.2f, 0.3f} */ 7536 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */ 7537 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */ 7538 }; 7539 const DWORD indices23[] = {0, 1, 2, 3, 4, 5}; 7540 const DWORD attributes23[] = {0, 0}; 7541 const UINT num_vertices23 = ARRAY_SIZE(vertices23); 7542 const UINT num_faces23 = ARRAY_SIZE(indices23) / VERTS_PER_FACE; 7543 DWORD flags23 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7544 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}; 7545 const DWORD adjacency23[] = {-1, 1, -1, -1, -1, 0}; 7546 const struct vertex_texcoord_float16_2 exp_vertices23[] = 7547 { 7548 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */ 7549 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */ 7550 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */ 7551 7552 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */ 7553 {{ 0.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */ 7554 }; 7555 const DWORD exp_indices23[] = {0, 1, 2, 1, 3, 4}; 7556 const DWORD exp_face_remap23[] = {0, 1}; 7557 const DWORD exp_vertex_remap23[] = {0, 1, 2, 4, 5, -1}; 7558 const DWORD exp_new_num_vertices23 = ARRAY_SIZE(exp_vertices23); 7559 /* Test 24. Weld texture coordinates as FLOAT16_4. Similar to test 24. */ 7560 const struct vertex_texcoord_float16_4 vertices24[] = 7561 { 7562 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}}, 7563 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a, 0x3800, 0x399a}}, 7564 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd, 0xb266, 0xb4cd}}, 7565 7566 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd, 0x3266, 0x34cd}}, 7567 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}}, 7568 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266, 0x2e66, 0x3266}}, 7569 }; 7570 const DWORD indices24[] = {0, 1, 2, 3, 4, 5}; 7571 const DWORD attributes24[] = {0, 0}; 7572 const UINT num_vertices24 = ARRAY_SIZE(vertices24); 7573 const UINT num_faces24 = ARRAY_SIZE(indices24) / VERTS_PER_FACE; 7574 DWORD flags24 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7575 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}; 7576 const DWORD adjacency24[] = {-1, 1, -1, -1, -1, 0}; 7577 const struct vertex_texcoord_float16_4 exp_vertices24[] = 7578 { 7579 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}}, 7580 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a, 0x3800, 0x399a}}, 7581 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd, 0xb266, 0xb4cd}}, 7582 7583 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}}, 7584 {{ 0.0f, 0.0f, 0.f}, {0x2e66, 0x3266, 0x2e66, 0x3266}}, 7585 }; 7586 const DWORD exp_indices24[] = {0, 1, 2, 1, 3, 4}; 7587 const DWORD exp_face_remap24[] = {0, 1}; 7588 const DWORD exp_vertex_remap24[] = {0, 1, 2, 4, 5, -1}; 7589 const DWORD exp_new_num_vertices24 = ARRAY_SIZE(exp_vertices24); 7590 /* Test 25. Weld texture coordinates with usage index 10 (TEXCOORD10). The 7591 * usage index is capped at 7, so the epsilon for TEXCOORD7 is used instead. 7592 */ 7593 const struct vertex_texcoord vertices25[] = 7594 { 7595 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f}}, 7596 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.7f}}, 7597 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}}, 7598 7599 {{ 3.0f, 3.0f, 0.f}, {0.2f, 0.3f}}, 7600 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f}}, 7601 {{ 1.0f, 0.0f, 0.f}, {0.1f, 0.2f}} 7602 }; 7603 const DWORD indices25[] = {0, 1, 2, 3, 4, 5}; 7604 const DWORD attributes25[] = {0, 0}; 7605 const UINT num_vertices25 = ARRAY_SIZE(vertices25); 7606 const UINT num_faces25 = ARRAY_SIZE(indices25) / VERTS_PER_FACE; 7607 DWORD flags25 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7608 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}; 7609 const DWORD adjacency25[] = {-1, 1, -1, -1, -1, 0}; 7610 const struct vertex_texcoord exp_vertices25[] = 7611 { 7612 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f}}, 7613 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.7f}}, 7614 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}}, 7615 7616 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f}}, 7617 {{ 0.0f, 0.0f, 0.f}, {0.1f, 0.2f}}, 7618 }; 7619 const DWORD exp_indices25[] = {0, 1, 2, 1, 3, 4}; 7620 const DWORD exp_face_remap25[] = {0, 1}; 7621 const DWORD exp_vertex_remap25[] = {0, 1, 2, 4, 5, -1}; 7622 const DWORD exp_new_num_vertices25 = ARRAY_SIZE(exp_vertices25); 7623 /* Test 26. Weld color with usage index larger than 1. Shows that none of 7624 * the epsilon values are used. */ 7625 const struct vertex_color vertices26[] = 7626 { 7627 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF}, 7628 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF}, 7629 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF}, 7630 7631 {{ 3.0f, 3.0f, 0.f}, 0x00000000}, 7632 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF}, 7633 {{ 1.0f, 0.0f, 0.f}, 0x01010101}, 7634 }; 7635 const DWORD indices26[] = {0, 1, 2, 3, 4, 5}; 7636 const DWORD attributes26[] = {0, 0}; 7637 const UINT num_vertices26 = ARRAY_SIZE(vertices26); 7638 const UINT num_faces26 = ARRAY_SIZE(indices26) / VERTS_PER_FACE; 7639 DWORD flags26 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7640 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}; 7641 const DWORD adjacency26[] = {-1, 1, -1, -1, -1, 0}; 7642 const struct vertex_color exp_vertices26[] = 7643 { 7644 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF}, 7645 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF}, 7646 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF}, 7647 7648 {{ 2.0f, 3.0f, 0.f}, 0x00000000}, 7649 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF}, 7650 {{ 0.0f, 0.0f, 0.f}, 0x01010101}, 7651 }; 7652 const DWORD exp_indices26[] = {0, 1, 2, 3, 4, 5}; 7653 const DWORD exp_face_remap26[] = {0, 1}; 7654 const DWORD exp_vertex_remap26[] = {0, 1, 2, 3, 4, 5}; 7655 const DWORD exp_new_num_vertices26 = ARRAY_SIZE(exp_vertices26); 7656 /* Test 27. Weld color with usage index 1 (specular). */ 7657 /* Previously this test used float color values and index > 1 but that case 7658 * appears to be effectively unhandled in native so the test gave 7659 * inconsistent results. */ 7660 const struct vertex_color vertices27[] = 7661 { 7662 {{ 0.0f, 3.0f, 0.0f}, 0x00000000}, 7663 {{ 2.0f, 3.0f, 0.0f}, 0x10203040}, 7664 {{ 0.0f, 0.0f, 0.0f}, 0x50607080}, 7665 7666 {{ 3.0f, 3.0f, 0.0f}, 0x11213141}, 7667 {{ 3.0f, 0.0f, 0.0f}, 0xffffffff}, 7668 {{ 1.0f, 0.0f, 0.0f}, 0x51617181}, 7669 }; 7670 const DWORD indices27[] = {0, 1, 2, 3, 4, 5}; 7671 const DWORD attributes27[] = {0, 0}; 7672 const UINT num_vertices27 = ARRAY_SIZE(vertices27); 7673 const UINT num_faces27 = ARRAY_SIZE(indices27) / VERTS_PER_FACE; 7674 DWORD flags27 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7675 const D3DXWELDEPSILONS epsilons27 = 7676 { 7677 1.1f, 0.0f, 0.0f, 0.0f, 2.0f / 255.0f, 0.0f, 7678 {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, 0.0f, 0.0f, 0.0f 7679 }; 7680 const DWORD adjacency27[] = {-1, 1, -1, -1, -1, 0}; 7681 const struct vertex_color exp_vertices27[] = 7682 { 7683 {{ 0.0f, 3.0f, 0.0f}, 0x00000000}, 7684 {{ 2.0f, 3.0f, 0.0f}, 0x10203040}, 7685 {{ 0.0f, 0.0f, 0.0f}, 0x50607080}, 7686 7687 {{ 3.0f, 0.0f, 0.0f}, 0xffffffff}, 7688 }; 7689 const DWORD exp_indices27[] = {0, 1, 2, 1, 3, 2}; 7690 const DWORD exp_face_remap27[] = {0, 1}; 7691 const DWORD exp_vertex_remap27[] = {0, 1, 2, 4, -1, -1}; 7692 const DWORD exp_new_num_vertices27 = ARRAY_SIZE(exp_vertices27); 7693 /* Test 28. Weld one normal with UDEC3. */ 7694 const DWORD dword_udec3_zero = init_udec3_dword(0, 0, 0, 1); 7695 const DWORD dword_udec3_1023 = init_udec3_dword(1023, 1023, 1023, 1); 7696 const DWORD dword_udec3_1022 = init_udec3_dword(1022, 1022, 1022, 1); 7697 const struct vertex_normal_udec3 vertices28[] = 7698 { 7699 {{ 0.0f, 3.0f, 0.f}, dword_udec3_zero}, 7700 {{ 2.0f, 3.0f, 0.f}, dword_udec3_zero}, 7701 {{ 0.0f, 0.0f, 0.f}, dword_udec3_zero}, 7702 7703 {{ 3.0f, 3.0f, 0.f}, dword_udec3_1023}, 7704 {{ 3.0f, 0.0f, 0.f}, dword_udec3_zero}, 7705 {{ 1.0f, 0.0f, 0.f}, dword_udec3_1022}, 7706 }; 7707 const DWORD indices28[] = {0, 1, 2, 3, 4, 5}; 7708 const DWORD attributes28[] = {0, 0}; 7709 const UINT num_vertices28 = ARRAY_SIZE(vertices28); 7710 const UINT num_faces28 = ARRAY_SIZE(indices28) / VERTS_PER_FACE; 7711 DWORD flags28 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7712 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}; 7713 const DWORD adjacency28[] = {-1, 1, -1, -1, -1, 0}; 7714 const struct vertex_normal_udec3 exp_vertices28[] = 7715 { 7716 {{ 0.0f, 3.0f, 0.f}, dword_udec3_zero}, 7717 {{ 2.0f, 3.0f, 0.f}, dword_udec3_zero}, 7718 {{ 0.0f, 0.0f, 0.f}, dword_udec3_zero}, 7719 7720 {{ 2.0f, 3.0f, 0.f}, dword_udec3_1023}, 7721 {{ 3.0f, 0.0f, 0.f}, dword_udec3_zero}, 7722 }; 7723 const DWORD exp_indices28[] = {0, 1, 2, 3, 4, 2}; 7724 const DWORD exp_face_remap28[] = {0, 1}; 7725 const DWORD exp_vertex_remap28[] = {0, 1, 2, 3, 4, -1}; 7726 const DWORD exp_new_num_vertices28 = ARRAY_SIZE(exp_vertices28); 7727 /* Test 29. Weld one normal with DEC3N. */ 7728 const DWORD dword_dec3n_zero = init_dec3n_dword(0, 0, 0, 1); 7729 const DWORD dword_dec3n_511 = init_dec3n_dword(511, 511, 511, 1); 7730 const DWORD dword_dec3n_510 = init_dec3n_dword(510, 510, 510, 1); 7731 const struct vertex_normal_dec3n vertices29[] = 7732 { 7733 {{ 0.0f, 3.0f, 0.f}, dword_dec3n_zero}, 7734 {{ 2.0f, 3.0f, 0.f}, dword_dec3n_zero}, 7735 {{ 0.0f, 0.0f, 0.f}, dword_dec3n_zero}, 7736 7737 {{ 3.0f, 3.0f, 0.f}, dword_dec3n_511}, 7738 {{ 3.0f, 0.0f, 0.f}, dword_dec3n_zero}, 7739 {{ 1.0f, 0.0f, 0.f}, dword_dec3n_510}, 7740 }; 7741 const DWORD indices29[] = {0, 1, 2, 3, 4, 5}; 7742 const DWORD attributes29[] = {0, 0}; 7743 const UINT num_vertices29 = ARRAY_SIZE(vertices29); 7744 const UINT num_faces29 = ARRAY_SIZE(indices29) / VERTS_PER_FACE; 7745 DWORD flags29 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7746 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}; 7747 const DWORD adjacency29[] = {-1, 1, -1, -1, -1, 0}; 7748 const struct vertex_normal_dec3n exp_vertices29[] = 7749 { 7750 {{ 0.0f, 3.0f, 0.f}, dword_dec3n_zero}, 7751 {{ 2.0f, 3.0f, 0.f}, dword_dec3n_zero}, 7752 {{ 0.0f, 0.0f, 0.f}, dword_dec3n_zero}, 7753 7754 {{ 2.0f, 3.0f, 0.f}, dword_dec3n_511}, 7755 {{ 3.0f, 0.0f, 0.f}, dword_dec3n_zero}, 7756 }; 7757 const DWORD exp_indices29[] = {0, 1, 2, 3, 4, 2}; 7758 const DWORD exp_face_remap29[] = {0, 1}; 7759 const DWORD exp_vertex_remap29[] = {0, 1, 2, 3, 4, -1}; 7760 const DWORD exp_new_num_vertices29 = ARRAY_SIZE(exp_vertices29); 7761 /* All mesh data */ 7762 DWORD *adjacency_out = NULL; 7763 DWORD *face_remap = NULL; 7764 ID3DXMesh *mesh = NULL; 7765 ID3DXBuffer *vertex_remap = NULL; 7766 struct 7767 { 7768 const BYTE *vertices; 7769 const DWORD *indices; 7770 const DWORD *attributes; 7771 const DWORD num_vertices; 7772 const DWORD num_faces; 7773 const DWORD options; 7774 D3DVERTEXELEMENT9 *declaration; 7775 const UINT vertex_size; 7776 const DWORD flags; 7777 const D3DXWELDEPSILONS *epsilons; 7778 const DWORD *adjacency; 7779 const BYTE *exp_vertices; 7780 const DWORD *exp_indices; 7781 const DWORD *exp_face_remap; 7782 const DWORD *exp_vertex_remap; 7783 const DWORD exp_new_num_vertices; 7784 } 7785 tc[] = 7786 { 7787 { 7788 (BYTE*)vertices0, 7789 indices0, 7790 attributes0, 7791 num_vertices0, 7792 num_faces0, 7793 options, 7794 declaration_normal, 7795 vertex_size_normal, 7796 flags0, 7797 NULL, 7798 adjacency0, 7799 (BYTE*)exp_vertices0, 7800 exp_indices0, 7801 exp_face_remap0, 7802 exp_vertex_remap0, 7803 exp_new_num_vertices0 7804 }, 7805 { 7806 (BYTE*)vertices1, 7807 indices1, 7808 attributes1, 7809 num_vertices1, 7810 num_faces1, 7811 options, 7812 declaration_normal, 7813 vertex_size_normal, 7814 flags1, 7815 NULL, 7816 adjacency1, 7817 (BYTE*)exp_vertices1, 7818 exp_indices1, 7819 exp_face_remap1, 7820 exp_vertex_remap1, 7821 exp_new_num_vertices1 7822 }, 7823 { 7824 (BYTE*)vertices2, 7825 indices2, 7826 attributes2, 7827 num_vertices2, 7828 num_faces2, 7829 options, 7830 declaration_normal, 7831 vertex_size_normal, 7832 flags2, 7833 &epsilons2, 7834 adjacency2, 7835 (BYTE*)exp_vertices2, 7836 exp_indices2, 7837 exp_face_remap2, 7838 exp_vertex_remap2, 7839 exp_new_num_vertices2 7840 }, 7841 { 7842 (BYTE*)vertices3, 7843 indices3, 7844 attributes3, 7845 num_vertices3, 7846 num_faces3, 7847 options, 7848 declaration_normal, 7849 vertex_size_normal, 7850 flags3, 7851 &epsilons3, 7852 adjacency3, 7853 (BYTE*)exp_vertices3, 7854 exp_indices3, 7855 exp_face_remap3, 7856 exp_vertex_remap3, 7857 exp_new_num_vertices3 7858 }, 7859 { 7860 (BYTE*)vertices4, 7861 indices4, 7862 attributes4, 7863 num_vertices4, 7864 num_faces4, 7865 options, 7866 declaration_normal, 7867 vertex_size_normal, 7868 flags4, 7869 &epsilons4, 7870 adjacency4, 7871 (BYTE*)exp_vertices4, 7872 exp_indices4, 7873 exp_face_remap4, 7874 exp_vertex_remap4, 7875 exp_new_num_vertices4 7876 }, 7877 /* Unusual ordering. */ 7878 { 7879 (BYTE*)vertices5, 7880 indices5, 7881 attributes5, 7882 num_vertices5, 7883 num_faces5, 7884 options, 7885 declaration_normal, 7886 vertex_size_normal, 7887 flags5, 7888 NULL, 7889 adjacency5, 7890 (BYTE*)exp_vertices5, 7891 exp_indices5, 7892 exp_face_remap5, 7893 exp_vertex_remap5, 7894 exp_new_num_vertices5 7895 }, 7896 { 7897 (BYTE*)vertices6, 7898 indices6, 7899 attributes6, 7900 num_vertices6, 7901 num_faces6, 7902 options, 7903 declaration_normal, 7904 vertex_size_normal, 7905 flags6, 7906 &epsilons6, 7907 adjacency6, 7908 (BYTE*)exp_vertices6, 7909 exp_indices6, 7910 exp_face_remap6, 7911 exp_vertex_remap6, 7912 exp_new_num_vertices6 7913 }, 7914 { 7915 (BYTE*)vertices6, 7916 (DWORD*)indices6_16bit, 7917 attributes6, 7918 num_vertices6, 7919 num_faces6, 7920 options_16bit, 7921 declaration_normal, 7922 vertex_size_normal, 7923 flags6, 7924 &epsilons6, 7925 adjacency6, 7926 (BYTE*)exp_vertices6, 7927 exp_indices6, 7928 exp_face_remap6, 7929 exp_vertex_remap6, 7930 exp_new_num_vertices6 7931 }, 7932 { 7933 (BYTE*)vertices8, 7934 indices8, 7935 attributes8, 7936 num_vertices8, 7937 num_faces8, 7938 options, 7939 declaration_normal, 7940 vertex_size_normal, 7941 flags8, 7942 &epsilons8, 7943 adjacency8, 7944 (BYTE*)exp_vertices8, 7945 exp_indices8, 7946 exp_face_remap8, 7947 exp_vertex_remap8, 7948 exp_new_num_vertices8 7949 }, 7950 { 7951 (BYTE*)vertices9, 7952 indices9, 7953 attributes9, 7954 num_vertices9, 7955 num_faces9, 7956 options, 7957 declaration_normal, 7958 vertex_size_normal, 7959 flags9, 7960 &epsilons9, 7961 adjacency9, 7962 (BYTE*)exp_vertices9, 7963 exp_indices9, 7964 exp_face_remap9, 7965 exp_vertex_remap9, 7966 exp_new_num_vertices9 7967 }, 7968 { 7969 (BYTE*)vertices10, 7970 indices10, 7971 attributes10, 7972 num_vertices10, 7973 num_faces10, 7974 options, 7975 declaration_blendweight, 7976 vertex_size_blendweight, 7977 flags10, 7978 &epsilons10, 7979 adjacency10, 7980 (BYTE*)exp_vertices10, 7981 exp_indices10, 7982 exp_face_remap10, 7983 exp_vertex_remap10, 7984 exp_new_num_vertices10 7985 }, 7986 { 7987 (BYTE*)vertices11, 7988 indices11, 7989 attributes11, 7990 num_vertices11, 7991 num_faces11, 7992 options, 7993 declaration_texcoord, 7994 vertex_size_texcoord, 7995 flags11, 7996 &epsilons11, 7997 adjacency11, 7998 (BYTE*)exp_vertices11, 7999 exp_indices11, 8000 exp_face_remap11, 8001 exp_vertex_remap11, 8002 exp_new_num_vertices11 8003 }, 8004 { 8005 (BYTE*)vertices12, 8006 indices12, 8007 attributes12, 8008 num_vertices12, 8009 num_faces12, 8010 options, 8011 declaration_color, 8012 vertex_size_color, 8013 flags12, 8014 &epsilons12, 8015 adjacency12, 8016 (BYTE*)exp_vertices12, 8017 exp_indices12, 8018 exp_face_remap12, 8019 exp_vertex_remap12, 8020 exp_new_num_vertices12 8021 }, 8022 { 8023 (BYTE*)vertices13, 8024 indices13, 8025 attributes13, 8026 num_vertices13, 8027 num_faces13, 8028 options, 8029 declaration_normal3, 8030 vertex_size_normal, 8031 flags13, 8032 &epsilons13, 8033 adjacency13, 8034 (BYTE*)exp_vertices13, 8035 exp_indices13, 8036 exp_face_remap13, 8037 exp_vertex_remap13, 8038 exp_new_num_vertices13 8039 }, 8040 { 8041 (BYTE*)vertices14, 8042 indices14, 8043 attributes14, 8044 num_vertices14, 8045 num_faces14, 8046 options, 8047 declaration_color, 8048 vertex_size_color, 8049 flags14, 8050 &epsilons14, 8051 adjacency14, 8052 (BYTE*)exp_vertices14, 8053 exp_indices14, 8054 exp_face_remap14, 8055 exp_vertex_remap14, 8056 exp_new_num_vertices14 8057 }, 8058 { 8059 (BYTE*)vertices15, 8060 indices15, 8061 attributes15, 8062 num_vertices15, 8063 num_faces15, 8064 options, 8065 declaration_color_ubyte4n, 8066 vertex_size_color_ubyte4, /* UBYTE4 same size as UBYTE4N */ 8067 flags15, 8068 &epsilons15, 8069 adjacency15, 8070 (BYTE*)exp_vertices15, 8071 exp_indices15, 8072 exp_face_remap15, 8073 exp_vertex_remap15, 8074 exp_new_num_vertices15 8075 }, 8076 { 8077 (BYTE*)vertices16, 8078 indices16, 8079 attributes16, 8080 num_vertices16, 8081 num_faces16, 8082 options, 8083 declaration_color_ubyte4, 8084 vertex_size_color_ubyte4, 8085 flags16, 8086 &epsilons16, 8087 adjacency16, 8088 (BYTE*)exp_vertices16, 8089 exp_indices16, 8090 exp_face_remap16, 8091 exp_vertex_remap16, 8092 exp_new_num_vertices16 8093 }, 8094 { 8095 (BYTE*)vertices17, 8096 indices17, 8097 attributes17, 8098 num_vertices17, 8099 num_faces17, 8100 options, 8101 declaration_texcoord_short2, 8102 vertex_size_texcoord_short2, 8103 flags17, 8104 &epsilons17, 8105 adjacency17, 8106 (BYTE*)exp_vertices17, 8107 exp_indices17, 8108 exp_face_remap17, 8109 exp_vertex_remap17, 8110 exp_new_num_vertices17 8111 }, 8112 { 8113 (BYTE*)vertices18, 8114 indices18, 8115 attributes18, 8116 num_vertices18, 8117 num_faces18, 8118 options, 8119 declaration_texcoord_short2n, 8120 vertex_size_texcoord_short2, /* SHORT2 same size as SHORT2N */ 8121 flags18, 8122 &epsilons18, 8123 adjacency18, 8124 (BYTE*)exp_vertices18, 8125 exp_indices18, 8126 exp_face_remap18, 8127 exp_vertex_remap18, 8128 exp_new_num_vertices18 8129 }, 8130 { 8131 (BYTE*)vertices19, 8132 indices19, 8133 attributes19, 8134 num_vertices19, 8135 num_faces19, 8136 options, 8137 declaration_texcoord_ushort2n, 8138 vertex_size_texcoord_short2, /* SHORT2 same size as USHORT2N */ 8139 flags19, 8140 &epsilons19, 8141 adjacency19, 8142 (BYTE*)exp_vertices19, 8143 exp_indices19, 8144 exp_face_remap19, 8145 exp_vertex_remap19, 8146 exp_new_num_vertices19 8147 }, 8148 { 8149 (BYTE*)vertices20, 8150 indices20, 8151 attributes20, 8152 num_vertices20, 8153 num_faces20, 8154 options, 8155 declaration_normal_short4, 8156 vertex_size_normal_short4, 8157 flags20, 8158 &epsilons20, 8159 adjacency20, 8160 (BYTE*)exp_vertices20, 8161 exp_indices20, 8162 exp_face_remap20, 8163 exp_vertex_remap20, 8164 exp_new_num_vertices20 8165 }, 8166 { 8167 (BYTE*)vertices21, 8168 indices21, 8169 attributes21, 8170 num_vertices21, 8171 num_faces21, 8172 options, 8173 declaration_normal_short4n, 8174 vertex_size_normal_short4, /* SHORT4 same size as SHORT4N */ 8175 flags21, 8176 &epsilons21, 8177 adjacency21, 8178 (BYTE*)exp_vertices21, 8179 exp_indices21, 8180 exp_face_remap21, 8181 exp_vertex_remap21, 8182 exp_new_num_vertices21 8183 }, 8184 { 8185 (BYTE*)vertices22, 8186 indices22, 8187 attributes22, 8188 num_vertices22, 8189 num_faces22, 8190 options, 8191 declaration_normal_ushort4n, 8192 vertex_size_normal_short4, /* SHORT4 same size as USHORT4N */ 8193 flags22, 8194 &epsilons22, 8195 adjacency22, 8196 (BYTE*)exp_vertices22, 8197 exp_indices22, 8198 exp_face_remap22, 8199 exp_vertex_remap22, 8200 exp_new_num_vertices22 8201 }, 8202 { 8203 (BYTE*)vertices23, 8204 indices23, 8205 attributes23, 8206 num_vertices23, 8207 num_faces23, 8208 options, 8209 declaration_texcoord_float16_2, 8210 vertex_size_texcoord_float16_2, 8211 flags23, 8212 &epsilons23, 8213 adjacency23, 8214 (BYTE*)exp_vertices23, 8215 exp_indices23, 8216 exp_face_remap23, 8217 exp_vertex_remap23, 8218 exp_new_num_vertices23 8219 }, 8220 { 8221 (BYTE*)vertices24, 8222 indices24, 8223 attributes24, 8224 num_vertices24, 8225 num_faces24, 8226 options, 8227 declaration_texcoord_float16_4, 8228 vertex_size_texcoord_float16_4, 8229 flags24, 8230 &epsilons24, 8231 adjacency24, 8232 (BYTE*)exp_vertices24, 8233 exp_indices24, 8234 exp_face_remap24, 8235 exp_vertex_remap24, 8236 exp_new_num_vertices24 8237 }, 8238 { 8239 (BYTE*)vertices25, 8240 indices25, 8241 attributes25, 8242 num_vertices25, 8243 num_faces25, 8244 options, 8245 declaration_texcoord10, 8246 vertex_size_texcoord, 8247 flags25, 8248 &epsilons25, 8249 adjacency25, 8250 (BYTE*)exp_vertices25, 8251 exp_indices25, 8252 exp_face_remap25, 8253 exp_vertex_remap25, 8254 exp_new_num_vertices25 8255 }, 8256 { 8257 (BYTE*)vertices26, 8258 indices26, 8259 attributes26, 8260 num_vertices26, 8261 num_faces26, 8262 options, 8263 declaration_color2, 8264 vertex_size_color, 8265 flags26, 8266 &epsilons26, 8267 adjacency26, 8268 (BYTE*)exp_vertices26, 8269 exp_indices26, 8270 exp_face_remap26, 8271 exp_vertex_remap26, 8272 exp_new_num_vertices26 8273 }, 8274 { 8275 (BYTE*)vertices27, 8276 indices27, 8277 attributes27, 8278 num_vertices27, 8279 num_faces27, 8280 options, 8281 declaration_color1, 8282 vertex_size_color, 8283 flags27, 8284 &epsilons27, 8285 adjacency27, 8286 (BYTE*)exp_vertices27, 8287 exp_indices27, 8288 exp_face_remap27, 8289 exp_vertex_remap27, 8290 exp_new_num_vertices27 8291 }, 8292 { 8293 (BYTE*)vertices28, 8294 indices28, 8295 attributes28, 8296 num_vertices28, 8297 num_faces28, 8298 options, 8299 declaration_normal_udec3, 8300 vertex_size_normal_udec3, 8301 flags28, 8302 &epsilons28, 8303 adjacency28, 8304 (BYTE*)exp_vertices28, 8305 exp_indices28, 8306 exp_face_remap28, 8307 exp_vertex_remap28, 8308 exp_new_num_vertices28 8309 }, 8310 { 8311 (BYTE*)vertices29, 8312 indices29, 8313 attributes29, 8314 num_vertices29, 8315 num_faces29, 8316 options, 8317 declaration_normal_dec3n, 8318 vertex_size_normal_dec3n, 8319 flags29, 8320 &epsilons29, 8321 adjacency29, 8322 (BYTE*)exp_vertices29, 8323 exp_indices29, 8324 exp_face_remap29, 8325 exp_vertex_remap29, 8326 exp_new_num_vertices29 8327 } 8328 }; 8329 #ifdef __REACTOS__ 8330 #undef up 8331 #endif 8332 8333 test_context = new_test_context(); 8334 if (!test_context) 8335 { 8336 skip("Couldn't create test context\n"); 8337 goto cleanup; 8338 } 8339 8340 for (i = 0; i < ARRAY_SIZE(tc); i++) 8341 { 8342 DWORD j; 8343 DWORD *vertex_remap_ptr; 8344 DWORD new_num_vertices; 8345 8346 hr = init_test_mesh(tc[i].num_faces, tc[i].num_vertices, tc[i].options, 8347 tc[i].declaration, test_context->device, &mesh, 8348 tc[i].vertices, tc[i].vertex_size, 8349 tc[i].indices, tc[i].attributes); 8350 if (FAILED(hr)) 8351 { 8352 skip("Couldn't initialize test mesh %d.\n", i); 8353 goto cleanup; 8354 } 8355 8356 /* Allocate out parameters */ 8357 adjacency_out = HeapAlloc(GetProcessHeap(), 0, VERTS_PER_FACE * tc[i].num_faces * sizeof(*adjacency_out)); 8358 if (!adjacency_out) 8359 { 8360 skip("Couldn't allocate adjacency_out array.\n"); 8361 goto cleanup; 8362 } 8363 face_remap = HeapAlloc(GetProcessHeap(), 0, tc[i].num_faces * sizeof(*face_remap)); 8364 if (!face_remap) 8365 { 8366 skip("Couldn't allocate face_remap array.\n"); 8367 goto cleanup; 8368 } 8369 8370 hr = D3DXWeldVertices(mesh, tc[i].flags, tc[i].epsilons, tc[i].adjacency, 8371 adjacency_out, face_remap, &vertex_remap); 8372 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 8373 /* Check number of vertices*/ 8374 new_num_vertices = mesh->lpVtbl->GetNumVertices(mesh); 8375 ok(new_num_vertices == tc[i].exp_new_num_vertices, 8376 "Mesh %d: new_num_vertices == %d, expected %d.\n", 8377 i, new_num_vertices, tc[i].exp_new_num_vertices); 8378 /* Check index buffer */ 8379 if (tc[i].options & D3DXMESH_32BIT) 8380 { 8381 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, (void**)&indices); 8382 if (FAILED(hr)) 8383 { 8384 skip("Couldn't lock index buffer.\n"); 8385 goto cleanup; 8386 } 8387 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++) 8388 { 8389 ok(indices[j] == tc[i].exp_indices[j], 8390 "Mesh %d: indices[%d] == %d, expected %d\n", 8391 i, j, indices[j], tc[i].exp_indices[j]); 8392 } 8393 } 8394 else 8395 { 8396 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, (void**)&indices_16bit); 8397 if (FAILED(hr)) 8398 { 8399 skip("Couldn't lock index buffer.\n"); 8400 goto cleanup; 8401 } 8402 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++) 8403 { 8404 ok(indices_16bit[j] == tc[i].exp_indices[j], 8405 "Mesh %d: indices_16bit[%d] == %d, expected %d\n", 8406 i, j, indices_16bit[j], tc[i].exp_indices[j]); 8407 } 8408 } 8409 mesh->lpVtbl->UnlockIndexBuffer(mesh); 8410 indices = NULL; 8411 indices_16bit = NULL; 8412 /* Check adjacency_out */ 8413 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++) 8414 { 8415 ok(adjacency_out[j] == tc[i].adjacency[j], 8416 "Mesh %d: adjacency_out[%d] == %d, expected %d\n", 8417 i, j, adjacency_out[j], tc[i].adjacency[j]); 8418 } 8419 /* Check face_remap */ 8420 for (j = 0; j < tc[i].num_faces; j++) 8421 { 8422 ok(face_remap[j] == tc[i].exp_face_remap[j], 8423 "Mesh %d: face_remap[%d] == %d, expected %d\n", 8424 i, j, face_remap[j], tc[i].exp_face_remap[j]); 8425 } 8426 /* Check vertex_remap */ 8427 vertex_remap_ptr = vertex_remap->lpVtbl->GetBufferPointer(vertex_remap); 8428 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++) 8429 { 8430 ok(vertex_remap_ptr[j] == tc[i].exp_vertex_remap[j], 8431 "Mesh %d: vertex_remap_ptr[%d] == %d, expected %d\n", 8432 i, j, vertex_remap_ptr[j], tc[i].exp_vertex_remap[j]); 8433 } 8434 /* Check vertex buffer */ 8435 hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, (void*)&vertices); 8436 if (FAILED(hr)) 8437 { 8438 skip("Couldn't lock vertex buffer.\n"); 8439 goto cleanup; 8440 } 8441 /* Check contents of re-ordered vertex buffer */ 8442 for (j = 0; j < tc[i].exp_new_num_vertices; j++) 8443 { 8444 int index = tc[i].vertex_size*j; 8445 check_vertex_components(__LINE__, i, j, &vertices[index], &tc[i].exp_vertices[index], tc[i].declaration); 8446 } 8447 mesh->lpVtbl->UnlockVertexBuffer(mesh); 8448 vertices = NULL; 8449 8450 /* Free mesh and output data */ 8451 HeapFree(GetProcessHeap(), 0, adjacency_out); 8452 adjacency_out = NULL; 8453 HeapFree(GetProcessHeap(), 0, face_remap); 8454 face_remap = NULL; 8455 vertex_remap->lpVtbl->Release(vertex_remap); 8456 vertex_remap = NULL; 8457 mesh->lpVtbl->Release(mesh); 8458 mesh = NULL; 8459 } 8460 8461 cleanup: 8462 HeapFree(GetProcessHeap(), 0, adjacency_out); 8463 HeapFree(GetProcessHeap(), 0, face_remap); 8464 if (indices) mesh->lpVtbl->UnlockIndexBuffer(mesh); 8465 if (indices_16bit) mesh->lpVtbl->UnlockIndexBuffer(mesh); 8466 if (mesh) mesh->lpVtbl->Release(mesh); 8467 if (vertex_remap) vertex_remap->lpVtbl->Release(vertex_remap); 8468 if (vertices) mesh->lpVtbl->UnlockVertexBuffer(mesh); 8469 free_test_context(test_context); 8470 } 8471 8472 static void test_clone_mesh(void) 8473 { 8474 HRESULT hr; 8475 struct test_context *test_context = NULL; 8476 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM; 8477 D3DVERTEXELEMENT9 declaration_pn[] = 8478 { 8479 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8480 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 8481 D3DDECL_END() 8482 }; 8483 D3DVERTEXELEMENT9 declaration_pntc[] = 8484 { 8485 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8486 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 8487 {0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 8488 D3DDECL_END() 8489 }; 8490 D3DVERTEXELEMENT9 declaration_ptcn[] = 8491 { 8492 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8493 {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 8494 {0, 20, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 8495 D3DDECL_END() 8496 }; 8497 D3DVERTEXELEMENT9 declaration_ptc[] = 8498 { 8499 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8500 {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 8501 D3DDECL_END() 8502 }; 8503 D3DVERTEXELEMENT9 declaration_ptc_float16_2[] = 8504 { 8505 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8506 {0, 12, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 8507 D3DDECL_END() 8508 }; 8509 D3DVERTEXELEMENT9 declaration_ptc_float16_4[] = 8510 { 8511 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8512 {0, 12, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 8513 D3DDECL_END() 8514 }; 8515 D3DVERTEXELEMENT9 declaration_ptc_float1[] = 8516 { 8517 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8518 {0, 12, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 8519 D3DDECL_END() 8520 }; 8521 D3DVERTEXELEMENT9 declaration_ptc_float3[] = 8522 { 8523 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8524 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 8525 D3DDECL_END() 8526 }; 8527 D3DVERTEXELEMENT9 declaration_ptc_float4[] = 8528 { 8529 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8530 {0, 12, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 8531 D3DDECL_END() 8532 }; 8533 D3DVERTEXELEMENT9 declaration_ptc_d3dcolor[] = 8534 { 8535 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8536 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 8537 D3DDECL_END() 8538 }; 8539 D3DVERTEXELEMENT9 declaration_ptc_ubyte4[] = 8540 { 8541 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8542 {0, 12, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 8543 D3DDECL_END() 8544 }; 8545 D3DVERTEXELEMENT9 declaration_ptc_ubyte4n[] = 8546 { 8547 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8548 {0, 12, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 8549 D3DDECL_END() 8550 }; 8551 D3DVERTEXELEMENT9 declaration_ptc_short2[] = 8552 { 8553 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8554 {0, 12, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 8555 D3DDECL_END() 8556 }; 8557 D3DVERTEXELEMENT9 declaration_ptc_short4[] = 8558 { 8559 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8560 {0, 12, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 8561 D3DDECL_END() 8562 }; 8563 D3DVERTEXELEMENT9 declaration_ptc_short2n[] = 8564 { 8565 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8566 {0, 12, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 8567 D3DDECL_END() 8568 }; 8569 D3DVERTEXELEMENT9 declaration_ptc_short4n[] = 8570 { 8571 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8572 {0, 12, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 8573 D3DDECL_END() 8574 }; 8575 D3DVERTEXELEMENT9 declaration_ptc_ushort2n[] = 8576 { 8577 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8578 {0, 12, D3DDECLTYPE_USHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 8579 D3DDECL_END() 8580 }; 8581 D3DVERTEXELEMENT9 declaration_ptc_ushort4n[] = 8582 { 8583 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8584 {0, 12, D3DDECLTYPE_USHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 8585 D3DDECL_END() 8586 }; 8587 D3DVERTEXELEMENT9 declaration_ptc_float16_2_partialu[] = 8588 { 8589 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8590 {0, 12, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_PARTIALU, D3DDECLUSAGE_TEXCOORD, 0}, 8591 D3DDECL_END() 8592 }; 8593 D3DVERTEXELEMENT9 declaration_pntc1[] = 8594 { 8595 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8596 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 8597 {0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1}, 8598 D3DDECL_END() 8599 }; 8600 const unsigned int VERTS_PER_FACE = 3; 8601 BYTE *vertices = NULL; 8602 INT i; 8603 struct vertex_pn 8604 { 8605 D3DXVECTOR3 position; 8606 D3DXVECTOR3 normal; 8607 }; 8608 struct vertex_pntc 8609 { 8610 D3DXVECTOR3 position; 8611 D3DXVECTOR3 normal; 8612 D3DXVECTOR2 texcoords; 8613 }; 8614 struct vertex_ptcn 8615 { 8616 D3DXVECTOR3 position; 8617 D3DXVECTOR2 texcoords; 8618 D3DXVECTOR3 normal; 8619 }; 8620 struct vertex_ptc 8621 { 8622 D3DXVECTOR3 position; 8623 D3DXVECTOR2 texcoords; 8624 }; 8625 struct vertex_ptc_float16_2 8626 { 8627 D3DXVECTOR3 position; 8628 WORD texcoords[2]; /* float16_2 */ 8629 }; 8630 struct vertex_ptc_float16_4 8631 { 8632 D3DXVECTOR3 position; 8633 WORD texcoords[4]; /* float16_4 */ 8634 }; 8635 struct vertex_ptc_float1 8636 { 8637 D3DXVECTOR3 position; 8638 FLOAT texcoords; 8639 }; 8640 struct vertex_ptc_float3 8641 { 8642 D3DXVECTOR3 position; 8643 FLOAT texcoords[3]; 8644 }; 8645 struct vertex_ptc_float4 8646 { 8647 D3DXVECTOR3 position; 8648 FLOAT texcoords[4]; 8649 }; 8650 struct vertex_ptc_d3dcolor 8651 { 8652 D3DXVECTOR3 position; 8653 BYTE texcoords[4]; 8654 }; 8655 struct vertex_ptc_ubyte4 8656 { 8657 D3DXVECTOR3 position; 8658 BYTE texcoords[4]; 8659 }; 8660 struct vertex_ptc_ubyte4n 8661 { 8662 D3DXVECTOR3 position; 8663 BYTE texcoords[4]; 8664 }; 8665 struct vertex_ptc_short2 8666 { 8667 D3DXVECTOR3 position; 8668 SHORT texcoords[2]; 8669 }; 8670 struct vertex_ptc_short4 8671 { 8672 D3DXVECTOR3 position; 8673 SHORT texcoords[4]; 8674 }; 8675 struct vertex_ptc_ushort2n 8676 { 8677 D3DXVECTOR3 position; 8678 USHORT texcoords[2]; 8679 }; 8680 struct vertex_ptc_ushort4n 8681 { 8682 D3DXVECTOR3 position; 8683 USHORT texcoords[4]; 8684 }; 8685 struct vertex_ptc_udec3 8686 { 8687 D3DXVECTOR3 position; 8688 DWORD texcoords; 8689 }; 8690 struct vertex_ptc_dec3n 8691 { 8692 D3DXVECTOR3 position; 8693 DWORD texcoords; 8694 }; 8695 #ifndef __REACTOS__ 8696 D3DXVECTOR3 up = {0.0f, 0.0f, 1.0f}; 8697 D3DXVECTOR2 zero_vec2 = {0.0f, 0.0f}; 8698 #else 8699 #define up {0.0f, 0.0f, 1.0f} 8700 #define zero_vec2 {0.0f, 0.0f} 8701 #endif 8702 /* Test 0. Check that a mesh can be cloned if the new declaration is the 8703 * same as the one used to create the mesh. 8704 * 8705 * 0--1 3 8706 * | / /| 8707 * |/ / | 8708 * 2 5--4 8709 */ 8710 const struct vertex_pn vertices0[] = 8711 { 8712 {{ 0.0f, 3.0f, 0.f}, up}, 8713 {{ 2.0f, 3.0f, 0.f}, up}, 8714 {{ 0.0f, 0.0f, 0.f}, up}, 8715 8716 {{ 3.0f, 3.0f, 0.f}, up}, 8717 {{ 3.0f, 0.0f, 0.f}, up}, 8718 {{ 1.0f, 0.0f, 0.f}, up}, 8719 }; 8720 const UINT num_vertices0 = ARRAY_SIZE(vertices0); 8721 const UINT num_faces0 = ARRAY_SIZE(vertices0) / VERTS_PER_FACE; 8722 const UINT vertex_size0 = sizeof(*vertices0); 8723 /* Test 1. Check that 16-bit indices are handled. */ 8724 const DWORD options_16bit = D3DXMESH_SYSTEMMEM; 8725 /* Test 2. Check that the size of each vertex is increased and the data 8726 * moved if the new declaration adds an element after the original elements. 8727 */ 8728 const struct vertex_pntc exp_vertices2[] = 8729 { 8730 {{ 0.0f, 3.0f, 0.f}, up, zero_vec2}, 8731 {{ 2.0f, 3.0f, 0.f}, up, zero_vec2}, 8732 {{ 0.0f, 0.0f, 0.f}, up, zero_vec2}, 8733 8734 {{ 3.0f, 3.0f, 0.f}, up, zero_vec2}, 8735 {{ 3.0f, 0.0f, 0.f}, up, zero_vec2}, 8736 {{ 1.0f, 0.0f, 0.f}, up, zero_vec2}, 8737 }; 8738 const UINT exp_vertex_size2 = sizeof(*exp_vertices2); 8739 /* Test 3. Check that the size of each vertex is increased and the data 8740 * moved if the new declaration adds an element between the original 8741 * elements. 8742 */ 8743 const struct vertex_ptcn exp_vertices3[] = 8744 { 8745 {{ 0.0f, 3.0f, 0.f}, zero_vec2, up}, 8746 {{ 2.0f, 3.0f, 0.f}, zero_vec2, up}, 8747 {{ 0.0f, 0.0f, 0.f}, zero_vec2, up}, 8748 8749 {{ 3.0f, 3.0f, 0.f}, zero_vec2, up}, 8750 {{ 3.0f, 0.0f, 0.f}, zero_vec2, up}, 8751 {{ 1.0f, 0.0f, 0.f}, zero_vec2, up}, 8752 }; 8753 const UINT exp_vertex_size3 = sizeof(*exp_vertices3); 8754 /* Test 4. Test that data types can be converted, e.g. FLOAT2 to FLOAT16_2. */ 8755 const struct vertex_ptc vertices4[] = 8756 { 8757 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}}, 8758 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}}, 8759 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}}, 8760 8761 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}}, 8762 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}}, 8763 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}}, 8764 }; 8765 const UINT num_vertices4 = ARRAY_SIZE(vertices4); 8766 const UINT num_faces4 = ARRAY_SIZE(vertices4) / VERTS_PER_FACE; 8767 const UINT vertex_size4 = sizeof(*vertices4); 8768 const struct vertex_ptc_float16_2 exp_vertices4[] = 8769 { 8770 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */ 8771 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */ 8772 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */ 8773 8774 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd}}, /* {0.2f, 0.3f} */ 8775 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */ 8776 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */ 8777 }; 8778 const UINT exp_vertex_size4 = sizeof(*exp_vertices4); 8779 /* Test 5. Convert FLOAT2 to FLOAT16_4. */ 8780 const struct vertex_ptc vertices5[] = 8781 { 8782 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}}, 8783 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}}, 8784 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}}, 8785 8786 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}}, 8787 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}}, 8788 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}}, 8789 }; 8790 const UINT num_vertices5 = ARRAY_SIZE(vertices5); 8791 const UINT num_faces5 = ARRAY_SIZE(vertices5) / VERTS_PER_FACE; 8792 const UINT vertex_size5 = sizeof(*vertices5); 8793 const struct vertex_ptc_float16_4 exp_vertices5[] = 8794 { 8795 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00, 0, 0x3c00}}, /* {1.0f, 1.0f, 0.0f, 1.0f} */ 8796 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a, 0, 0x3c00}}, /* {0.5f, 0.7f, 0.0f, 1.0f} */ 8797 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd, 0, 0x3c00}}, /* {-0.2f, -0.3f, 0.0f, 1.0f} */ 8798 8799 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd, 0, 0x3c00}}, /* {0.2f, 0.3f, 0.0f, 1.0f} */ 8800 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00, 0, 0x3c00}}, /* {1.0f, 1.0f, 0.0f, 1.0f} */ 8801 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266, 0, 0x3c00}}, /* {0.1f, 0.2f, 0.0f, 1.0f} */ 8802 }; 8803 const UINT exp_vertex_size5 = sizeof(*exp_vertices5); 8804 /* Test 6. Convert FLOAT2 to FLOAT1. */ 8805 const struct vertex_ptc vertices6[] = 8806 { 8807 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}}, 8808 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}}, 8809 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}}, 8810 8811 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}}, 8812 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}}, 8813 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}}, 8814 }; 8815 const UINT num_vertices6 = ARRAY_SIZE(vertices6); 8816 const UINT num_faces6 = ARRAY_SIZE(vertices6) / VERTS_PER_FACE; 8817 const UINT vertex_size6 = sizeof(*vertices6); 8818 const struct vertex_ptc_float1 exp_vertices6[] = 8819 { 8820 {{ 0.0f, 3.0f, 0.f}, 1.0f}, 8821 {{ 2.0f, 3.0f, 0.f}, 0.5f}, 8822 {{ 0.0f, 0.0f, 0.f}, -0.2f}, 8823 8824 {{ 3.0f, 3.0f, 0.f}, 0.2f}, 8825 {{ 3.0f, 0.0f, 0.f}, 1.0f}, 8826 {{ 1.0f, 0.0f, 0.f}, 0.1f}, 8827 }; 8828 const UINT exp_vertex_size6 = sizeof(*exp_vertices6); 8829 /* Test 7. Convert FLOAT2 to FLOAT3. */ 8830 const struct vertex_ptc vertices7[] = 8831 { 8832 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}}, 8833 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}}, 8834 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}}, 8835 8836 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}}, 8837 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}}, 8838 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}}, 8839 }; 8840 const UINT num_vertices7 = ARRAY_SIZE(vertices7); 8841 const UINT num_faces7 = ARRAY_SIZE(vertices7) / VERTS_PER_FACE; 8842 const UINT vertex_size7 = sizeof(*vertices7); 8843 const struct vertex_ptc_float3 exp_vertices7[] = 8844 { 8845 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f, 0.0f}}, 8846 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f, 0.0f}}, 8847 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f, 0.0f}}, 8848 8849 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f, 0.0f}}, 8850 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f, 0.0f}}, 8851 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f, 0.0f}}, 8852 }; 8853 const UINT exp_vertex_size7 = sizeof(*exp_vertices7); 8854 /* Test 8. Convert FLOAT2 to FLOAT4. */ 8855 const struct vertex_ptc vertices8[] = 8856 { 8857 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}}, 8858 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}}, 8859 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}}, 8860 8861 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}}, 8862 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}}, 8863 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}}, 8864 }; 8865 const UINT num_vertices8 = ARRAY_SIZE(vertices8); 8866 const UINT num_faces8 = ARRAY_SIZE(vertices8) / VERTS_PER_FACE; 8867 const UINT vertex_size8 = sizeof(*vertices8); 8868 const struct vertex_ptc_float4 exp_vertices8[] = 8869 { 8870 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f, 0.0f, 1.0f}}, 8871 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f, 0.0f, 1.0f}}, 8872 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f, 0.0f, 1.0f}}, 8873 8874 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f, 0.0f, 1.0f}}, 8875 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f, 0.0f, 1.0f}}, 8876 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f, 0.0f, 1.0f}}, 8877 }; 8878 const UINT exp_vertex_size8 = sizeof(*exp_vertices8); 8879 /* Test 9. Convert FLOAT2 to D3DCOLOR. */ 8880 const struct vertex_ptc vertices9[] = 8881 { 8882 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}}, 8883 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}}, 8884 {{ 0.0f, 0.0f, 0.f}, {-0.4f, -0.6f}}, 8885 8886 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}}, 8887 {{ 3.0f, 0.0f, 0.f}, { 2.0f, 256.0f}}, 8888 {{ 1.0f, 0.0f, 0.f}, { 0.11f, 0.2f}}, 8889 }; 8890 const UINT num_vertices9 = ARRAY_SIZE(vertices9); 8891 const UINT num_faces9 = ARRAY_SIZE(vertices9) / VERTS_PER_FACE; 8892 const UINT vertex_size9 = sizeof(*vertices9); 8893 const struct vertex_ptc_d3dcolor exp_vertices9[] = 8894 { 8895 {{ 0.0f, 3.0f, 0.f}, {0, 255, 255, 255}}, 8896 {{ 2.0f, 3.0f, 0.f}, {0, 179, 128, 255}}, 8897 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 255}}, 8898 8899 {{ 3.0f, 3.0f, 0.f}, {0, 77, 51, 255}}, 8900 {{ 3.0f, 0.0f, 0.f}, {0, 255, 255, 255}}, 8901 {{ 1.0f, 0.0f, 0.f}, {0, 51, 28, 255}}, 8902 }; 8903 const UINT exp_vertex_size9 = sizeof(*exp_vertices9); 8904 /* Test 10. Convert FLOAT2 to UBYTE4. */ 8905 const struct vertex_ptc vertices10[] = 8906 { 8907 {{ 0.0f, 3.0f, 0.f}, { 0.0f, 1.0f}}, 8908 {{ 2.0f, 3.0f, 0.f}, { 2.0f, 3.0f}}, 8909 {{ 0.0f, 0.0f, 0.f}, { 254.0f, 255.0f}}, 8910 8911 {{ 3.0f, 3.0f, 0.f}, { 256.0f, 257.0f}}, 8912 {{ 3.0f, 0.0f, 0.f}, { 1.4f, 1.5f}}, 8913 {{ 1.0f, 0.0f, 0.f}, {-4.0f, -5.0f}}, 8914 }; 8915 const UINT num_vertices10 = ARRAY_SIZE(vertices10); 8916 const UINT num_faces10 = ARRAY_SIZE(vertices10) / VERTS_PER_FACE; 8917 const UINT vertex_size10 = sizeof(*vertices10); 8918 const struct vertex_ptc_ubyte4 exp_vertices10[] = 8919 { 8920 {{ 0.0f, 3.0f, 0.f}, {0, 1, 0, 1}}, 8921 {{ 2.0f, 3.0f, 0.f}, {2, 3, 0, 1}}, 8922 {{ 0.0f, 0.0f, 0.f}, {254, 255, 0, 1}}, 8923 8924 {{ 3.0f, 3.0f, 0.f}, {0, 1, 0, 1}}, 8925 {{ 3.0f, 0.0f, 0.f}, {1, 2, 0, 1}}, 8926 {{ 1.0f, 0.0f, 0.f}, {0, 0, 0, 1}}, 8927 }; 8928 const UINT exp_vertex_size10 = sizeof(*exp_vertices10); 8929 /* Test 11. Convert FLOAT2 to SHORT2. */ 8930 const struct vertex_ptc vertices11[] = 8931 { 8932 {{ 0.0f, 3.0f, 0.f}, { 1.0f, -1.0f}}, 8933 {{ 2.0f, 3.0f, 0.f}, { 0.4f, 0.5f}}, 8934 {{ 0.0f, 0.0f, 0.f}, {-0.5f, -5.0f}}, 8935 8936 {{ 3.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MIN}}, 8937 {{ 3.0f, 0.0f, 0.f}, {SHRT_MAX + 1.0f, SHRT_MIN - 1.0f}}, 8938 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX + 2.0f, SHRT_MIN - 2.0f}}, 8939 8940 {{ 4.0f, 3.0f, 0.f}, {2 * SHRT_MAX, 2 * SHRT_MIN}}, 8941 {{ 6.0f, 0.0f, 0.f}, {3 * SHRT_MAX, 3 * SHRT_MIN}}, 8942 {{ 4.0f, 0.0f, 0.f}, {4 * SHRT_MAX, 4 * SHRT_MIN}}, 8943 }; 8944 const UINT num_vertices11 = ARRAY_SIZE(vertices11); 8945 const UINT num_faces11 = ARRAY_SIZE(vertices11) / VERTS_PER_FACE; 8946 const UINT vertex_size11 = sizeof(*vertices11); 8947 const struct vertex_ptc_short2 exp_vertices11[] = 8948 { 8949 {{ 0.0f, 3.0f, 0.f}, {1, 0}}, 8950 {{ 2.0f, 3.0f, 0.f}, {0, 1}}, 8951 {{ 0.0f, 0.0f, 0.f}, {0, -4}}, 8952 8953 {{ 3.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MIN + 1}}, 8954 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MIN}}, 8955 {{ 1.0f, 0.0f, 0.f}, {SHRT_MIN + 1, SHRT_MAX}}, 8956 8957 {{ 4.0f, 3.0f, 0.f}, {-2, 1}}, 8958 {{ 6.0f, 0.0f, 0.f}, {32765, -32767}}, 8959 {{ 4.0f, 0.0f, 0.f}, {-4, 1}}, 8960 }; 8961 const UINT exp_vertex_size11 = sizeof(*exp_vertices11); 8962 /* Test 12. Convert FLOAT2 to SHORT4. */ 8963 const struct vertex_ptc vertices12[] = 8964 { 8965 {{ 0.0f, 3.0f, 0.f}, { 1.0f, -1.0f}}, 8966 {{ 2.0f, 3.0f, 0.f}, { 0.4f, 0.5f}}, 8967 {{ 0.0f, 0.0f, 0.f}, {-0.5f, -5.0f}}, 8968 8969 {{ 3.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MIN}}, 8970 {{ 3.0f, 0.0f, 0.f}, {SHRT_MAX + 1.0f, SHRT_MIN - 1.0f}}, 8971 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX + 2.0f, SHRT_MIN - 2.0f}}, 8972 8973 {{ 4.0f, 3.0f, 0.f}, {2 * SHRT_MAX, 2 * SHRT_MIN}}, 8974 {{ 6.0f, 0.0f, 0.f}, {3 * SHRT_MAX, 3 * SHRT_MIN}}, 8975 {{ 4.0f, 0.0f, 0.f}, {4 * SHRT_MAX, 4 * SHRT_MIN}}, 8976 }; 8977 const UINT num_vertices12 = ARRAY_SIZE(vertices12); 8978 const UINT num_faces12 = ARRAY_SIZE(vertices12) / VERTS_PER_FACE; 8979 const UINT vertex_size12 = sizeof(*vertices12); 8980 const struct vertex_ptc_short4 exp_vertices12[] = 8981 { 8982 {{ 0.0f, 3.0f, 0.f}, {1, 0, 0, 1}}, 8983 {{ 2.0f, 3.0f, 0.f}, {0, 1, 0, 1}}, 8984 {{ 0.0f, 0.0f, 0.f}, {0, -4, 0, 1}}, 8985 8986 {{ 3.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MIN + 1, 0, 1}}, 8987 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MIN, 0, 1}}, 8988 {{ 1.0f, 0.0f, 0.f}, {SHRT_MIN + 1, SHRT_MAX, 0, 1}}, 8989 8990 {{ 4.0f, 3.0f, 0.f}, {-2, 1, 0, 1}}, 8991 {{ 6.0f, 0.0f, 0.f}, {32765, -32767, 0, 1}}, 8992 {{ 4.0f, 0.0f, 0.f}, {-4, 1, 0, 1}}, 8993 }; 8994 const UINT exp_vertex_size12 = sizeof(*exp_vertices12); 8995 /* Test 13. Convert FLOAT2 to UBYTE4N. */ 8996 const struct vertex_ptc vertices13[] = 8997 { 8998 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 2.0f}}, 8999 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}}, 9000 {{ 0.0f, 0.0f, 0.f}, {-0.4f, -0.5f}}, 9001 9002 {{ 3.0f, 3.0f, 0.f}, {-0.6f, -1.0f}}, 9003 {{ 3.0f, 0.0f, 0.f}, {UCHAR_MAX, UCHAR_MAX + 1}}, 9004 {{ 1.0f, 0.0f, 0.f}, {2 * UCHAR_MAX, -UCHAR_MAX}}, 9005 }; 9006 const UINT num_vertices13 = ARRAY_SIZE(vertices13); 9007 const UINT num_faces13 = ARRAY_SIZE(vertices13) / VERTS_PER_FACE; 9008 const UINT vertex_size13 = sizeof(*vertices13); 9009 const struct vertex_ptc_ubyte4n exp_vertices13[] = 9010 { 9011 {{ 0.0f, 3.0f, 0.f}, {255, 255, 0, 255}}, 9012 {{ 2.0f, 3.0f, 0.f}, {128, 179, 0, 255}}, 9013 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 255}}, 9014 9015 {{ 3.0f, 3.0f, 0.f}, {0, 0, 0, 255}}, 9016 {{ 3.0f, 0.0f, 0.f}, {255, 255, 0, 255}}, 9017 {{ 1.0f, 0.0f, 0.f}, {255, 0, 0, 255}}, 9018 }; 9019 const UINT exp_vertex_size13 = sizeof(*exp_vertices13); 9020 /* Test 14. Convert FLOAT2 to SHORT2N. */ 9021 const struct vertex_ptc vertices14[] = 9022 { 9023 {{ 0.0f, 3.0f, 0.f}, {1.0f, 2.0f}}, 9024 {{ 2.0f, 3.0f, 0.f}, {0.4f, 0.5f}}, 9025 {{ 0.0f, 0.0f, 0.f}, {0.6f, -1.0f}}, 9026 9027 {{ 3.0f, 3.0f, 0.f}, {-0.4f, -0.5f}}, 9028 {{ 3.0f, 0.0f, 0.f}, {-0.9f, -0.99997}}, 9029 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX, SHRT_MIN}}, 9030 }; 9031 const UINT num_vertices14 = ARRAY_SIZE(vertices14); 9032 const UINT num_faces14 = ARRAY_SIZE(vertices14) / VERTS_PER_FACE; 9033 const UINT vertex_size14 = sizeof(*vertices14); 9034 const struct vertex_ptc_short2 exp_vertices14[] = 9035 { 9036 {{ 0.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MAX}}, 9037 {{ 2.0f, 3.0f, 0.f}, {13107, 16384}}, 9038 {{ 0.0f, 0.0f, 0.f}, {19660, SHRT_MIN + 2}}, 9039 9040 {{ 3.0f, 3.0f, 0.f}, {-13106, -16383}}, 9041 {{ 3.0f, 0.0f, 0.f}, {-29489, SHRT_MIN + 3}}, 9042 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX, SHRT_MIN + 2}}, 9043 }; 9044 const UINT exp_vertex_size14 = sizeof(*exp_vertices14); 9045 /* Test 15. Convert FLOAT2 to SHORT4N. */ 9046 const struct vertex_ptc vertices15[] = 9047 { 9048 {{ 0.0f, 3.0f, 0.f}, {1.0f, 2.0f}}, 9049 {{ 2.0f, 3.0f, 0.f}, {0.4f, 0.5f}}, 9050 {{ 0.0f, 0.0f, 0.f}, {0.6f, -1.0f}}, 9051 9052 {{ 3.0f, 3.0f, 0.f}, {-0.4f, -0.5f}}, 9053 {{ 3.0f, 0.0f, 0.f}, {-0.9f, -0.99997}}, 9054 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX, SHRT_MIN}}, 9055 }; 9056 const UINT num_vertices15 = ARRAY_SIZE(vertices15); 9057 const UINT num_faces15 = ARRAY_SIZE(vertices15) / VERTS_PER_FACE; 9058 const UINT vertex_size15 = sizeof(*vertices15); 9059 const struct vertex_ptc_short4 exp_vertices15[] = 9060 { 9061 {{ 0.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MAX, 0, SHRT_MAX}}, 9062 {{ 2.0f, 3.0f, 0.f}, {13107, 16384, 0, SHRT_MAX}}, 9063 {{ 0.0f, 0.0f, 0.f}, {19660, SHRT_MIN + 2, 0, SHRT_MAX}}, 9064 9065 {{ 3.0f, 3.0f, 0.f}, {-13106, -16383, 0, SHRT_MAX}}, 9066 {{ 3.0f, 0.0f, 0.f}, {-29489, SHRT_MIN + 3, 0, SHRT_MAX}}, 9067 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX, SHRT_MIN + 2, 0, SHRT_MAX}}, 9068 }; 9069 const UINT exp_vertex_size15 = sizeof(*exp_vertices15); 9070 /* Test 16. Convert FLOAT2 to USHORT2N. */ 9071 const struct vertex_ptc vertices16[] = 9072 { 9073 {{ 0.0f, 3.0f, 0.f}, {1.0f, 2.0f}}, 9074 {{ 2.0f, 3.0f, 0.f}, {0.4f, 0.5f}}, 9075 {{ 0.0f, 0.0f, 0.f}, {0.6f, -1.0f}}, 9076 9077 {{ 3.0f, 3.0f, 0.f}, {-0.4f, -0.5f}}, 9078 {{ 3.0f, 0.0f, 0.f}, {-0.9f, 0.99998f}}, 9079 {{ 1.0f, 0.0f, 0.f}, {USHRT_MAX, 0.0f}}, 9080 }; 9081 const UINT num_vertices16 = ARRAY_SIZE(vertices16); 9082 const UINT num_faces16 = ARRAY_SIZE(vertices16) / VERTS_PER_FACE; 9083 const UINT vertex_size16 = sizeof(*vertices16); 9084 const struct vertex_ptc_ushort2n exp_vertices16[] = 9085 { 9086 {{ 0.0f, 3.0f, 0.f}, {USHRT_MAX, USHRT_MAX}}, 9087 {{ 2.0f, 3.0f, 0.f}, {26214, 32768}}, 9088 {{ 0.0f, 0.0f, 0.f}, {39321, 0}}, 9089 9090 {{ 3.0f, 3.0f, 0.f}, {0, 0}}, 9091 {{ 3.0f, 0.0f, 0.f}, {0, USHRT_MAX - 1}}, 9092 {{ 1.0f, 0.0f, 0.f}, {USHRT_MAX, 0}}, 9093 }; 9094 const UINT exp_vertex_size16 = sizeof(*exp_vertices16); 9095 /* Test 17. Convert FLOAT2 to USHORT4N. */ 9096 const struct vertex_ptc vertices17[] = 9097 { 9098 {{ 0.0f, 3.0f, 0.f}, {1.0f, 2.0f}}, 9099 {{ 2.0f, 3.0f, 0.f}, {0.4f, 0.5f}}, 9100 {{ 0.0f, 0.0f, 0.f}, {0.6f, -1.0f}}, 9101 9102 {{ 3.0f, 3.0f, 0.f}, {-0.4f, -0.5f}}, 9103 {{ 3.0f, 0.0f, 0.f}, {-0.9f, 0.99998f}}, 9104 {{ 1.0f, 0.0f, 0.f}, {USHRT_MAX, 0.0f}}, 9105 }; 9106 const UINT num_vertices17 = ARRAY_SIZE(vertices17); 9107 const UINT num_faces17 = ARRAY_SIZE(vertices17) / VERTS_PER_FACE; 9108 const UINT vertex_size17 = sizeof(*vertices17); 9109 const struct vertex_ptc_ushort4n exp_vertices17[] = 9110 { 9111 {{ 0.0f, 3.0f, 0.f}, {USHRT_MAX, USHRT_MAX, 0, USHRT_MAX}}, 9112 {{ 2.0f, 3.0f, 0.f}, {26214, 32768, 0, USHRT_MAX}}, 9113 {{ 0.0f, 0.0f, 0.f}, {39321, 0, 0, USHRT_MAX}}, 9114 9115 {{ 3.0f, 3.0f, 0.f}, {0, 0, 0, USHRT_MAX}}, 9116 {{ 3.0f, 0.0f, 0.f}, {0, USHRT_MAX - 1, 0, USHRT_MAX}}, 9117 {{ 1.0f, 0.0f, 0.f}, {USHRT_MAX, 0, 0, USHRT_MAX}}, 9118 }; 9119 const UINT exp_vertex_size17 = sizeof(*exp_vertices17); 9120 /* Test 18. Test that the method field is compared by converting a FLOAT2 to 9121 * FLOAT16_2. where the method field has been change from 9122 * D3DDECLMETHOD_DEFAULT to D3DDECLMETHOD_PARTIALU. */ 9123 const struct vertex_ptc vertices18[] = 9124 { 9125 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}}, 9126 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}}, 9127 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}}, 9128 9129 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}}, 9130 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}}, 9131 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}}, 9132 }; 9133 const UINT num_vertices18 = ARRAY_SIZE(vertices18); 9134 const UINT num_faces18 = ARRAY_SIZE(vertices18) / VERTS_PER_FACE; 9135 const UINT vertex_size18 = sizeof(*vertices18); 9136 const struct vertex_ptc_float16_2 exp_vertices18[] = 9137 { 9138 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */ 9139 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */ 9140 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */ 9141 9142 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd}}, /* {0.2f, 0.3f} */ 9143 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */ 9144 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */ 9145 }; 9146 const UINT exp_vertex_size18 = sizeof(*exp_vertices18); 9147 /* Test 19. Test that data is lost if usage index changes, e.g. TEXCOORD0 9148 * TEXCOORD1. */ 9149 const struct vertex_pntc vertices19[] = 9150 { 9151 {{ 0.0f, 3.0f, 0.f}, up, { 1.0f, 1.0f}}, 9152 {{ 2.0f, 3.0f, 0.f}, up, { 0.5f, 0.7f}}, 9153 {{ 0.0f, 0.0f, 0.f}, up, {-0.2f, -0.3f}}, 9154 9155 {{ 3.0f, 3.0f, 0.f}, up, { 0.2f, 0.3f}}, 9156 {{ 3.0f, 0.0f, 0.f}, up, { 1.0f, 1.0f}}, 9157 {{ 1.0f, 0.0f, 0.f}, up, { 0.1f, 0.2f}}, 9158 }; 9159 const UINT num_vertices19 = ARRAY_SIZE(vertices19); 9160 const UINT num_faces19 = ARRAY_SIZE(vertices19) / VERTS_PER_FACE; 9161 const UINT vertex_size19 = sizeof(*vertices19); 9162 const struct vertex_pntc exp_vertices19[] = 9163 { 9164 {{ 0.0f, 3.0f, 0.f}, up, zero_vec2}, 9165 {{ 2.0f, 3.0f, 0.f}, up, zero_vec2}, 9166 {{ 0.0f, 0.0f, 0.f}, up, zero_vec2}, 9167 9168 {{ 3.0f, 3.0f, 0.f}, up, zero_vec2}, 9169 {{ 3.0f, 0.0f, 0.f}, up, zero_vec2}, 9170 {{ 1.0f, 0.0f, 0.f}, up, zero_vec2}, 9171 }; 9172 const UINT exp_vertex_size19 = sizeof(*exp_vertices19); 9173 /* Test 20. Another test that data is lost if usage index changes, e.g. 9174 * TEXCOORD1 to TEXCOORD0. */ 9175 const struct vertex_pntc vertices20[] = 9176 { 9177 {{ 0.0f, 3.0f, 0.f}, up, { 1.0f, 1.0f}}, 9178 {{ 2.0f, 3.0f, 0.f}, up, { 0.5f, 0.7f}}, 9179 {{ 0.0f, 0.0f, 0.f}, up, {-0.2f, -0.3f}}, 9180 9181 {{ 3.0f, 3.0f, 0.f}, up, { 0.2f, 0.3f}}, 9182 {{ 3.0f, 0.0f, 0.f}, up, { 1.0f, 1.0f}}, 9183 {{ 1.0f, 0.0f, 0.f}, up, { 0.1f, 0.2f}}, 9184 }; 9185 const UINT num_vertices20 = ARRAY_SIZE(vertices20); 9186 const UINT num_faces20 = ARRAY_SIZE(vertices20) / VERTS_PER_FACE; 9187 const UINT vertex_size20 = sizeof(*vertices20); 9188 const struct vertex_pntc exp_vertices20[] = 9189 { 9190 {{ 0.0f, 3.0f, 0.f}, up, zero_vec2}, 9191 {{ 2.0f, 3.0f, 0.f}, up, zero_vec2}, 9192 {{ 0.0f, 0.0f, 0.f}, up, zero_vec2}, 9193 9194 {{ 3.0f, 3.0f, 0.f}, up, zero_vec2}, 9195 {{ 3.0f, 0.0f, 0.f}, up, zero_vec2}, 9196 {{ 1.0f, 0.0f, 0.f}, up, zero_vec2}, 9197 }; 9198 const UINT exp_vertex_size20 = sizeof(*exp_vertices20); 9199 /* Test 21. Convert FLOAT1 to FLOAT2. */ 9200 const struct vertex_ptc_float1 vertices21[] = 9201 { 9202 {{ 0.0f, 3.0f, 0.f}, 1.0f}, 9203 {{ 2.0f, 3.0f, 0.f}, 0.5f}, 9204 {{ 0.0f, 0.0f, 0.f}, -0.2f}, 9205 9206 {{ 3.0f, 3.0f, 0.f}, 0.2f}, 9207 {{ 3.0f, 0.0f, 0.f}, 1.0f}, 9208 {{ 1.0f, 0.0f, 0.f}, 0.1f}, 9209 }; 9210 const UINT num_vertices21 = ARRAY_SIZE(vertices21); 9211 const UINT num_faces21 = ARRAY_SIZE(vertices21) / VERTS_PER_FACE; 9212 const UINT vertex_size21 = sizeof(*vertices21); 9213 const struct vertex_ptc exp_vertices21[] = 9214 { 9215 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 0.0f}}, 9216 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.0f}}, 9217 {{ 0.0f, 0.0f, 0.f}, {-0.2f, 0.0f}}, 9218 9219 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.0f}}, 9220 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 0.0f}}, 9221 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.0f}}, 9222 }; 9223 const UINT exp_vertex_size21 = sizeof(*exp_vertices21); 9224 /* Test 22. Convert FLOAT1 to FLOAT3. */ 9225 const struct vertex_ptc_float1 vertices22[] = 9226 { 9227 {{ 0.0f, 3.0f, 0.f}, 1.0f}, 9228 {{ 2.0f, 3.0f, 0.f}, 0.5f}, 9229 {{ 0.0f, 0.0f, 0.f}, -0.2f}, 9230 9231 {{ 3.0f, 3.0f, 0.f}, 0.2f}, 9232 {{ 3.0f, 0.0f, 0.f}, 1.0f}, 9233 {{ 1.0f, 0.0f, 0.f}, 0.1f}, 9234 }; 9235 const UINT num_vertices22 = ARRAY_SIZE(vertices22); 9236 const UINT num_faces22 = ARRAY_SIZE(vertices22) / VERTS_PER_FACE; 9237 const UINT vertex_size22 = sizeof(*vertices22); 9238 const struct vertex_ptc_float3 exp_vertices22[] = 9239 { 9240 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 0.0f, 0.0f}}, 9241 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.0f, 0.0f}}, 9242 {{ 0.0f, 0.0f, 0.f}, {-0.2f, 0.0f, 0.0f}}, 9243 9244 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.0f, 0.0f}}, 9245 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 0.0f, 0.0f}}, 9246 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.0f, 0.0f}}, 9247 }; 9248 const UINT exp_vertex_size22 = sizeof(*exp_vertices22); 9249 /* Test 23. Convert FLOAT1 to FLOAT4. */ 9250 const struct vertex_ptc_float1 vertices23[] = 9251 { 9252 {{ 0.0f, 3.0f, 0.f}, 1.0f}, 9253 {{ 2.0f, 3.0f, 0.f}, 0.5f}, 9254 {{ 0.0f, 0.0f, 0.f}, -0.2f}, 9255 9256 {{ 3.0f, 3.0f, 0.f}, 0.2f}, 9257 {{ 3.0f, 0.0f, 0.f}, 1.0f}, 9258 {{ 1.0f, 0.0f, 0.f}, 0.1f}, 9259 }; 9260 const UINT num_vertices23 = ARRAY_SIZE(vertices23); 9261 const UINT num_faces23 = ARRAY_SIZE(vertices23) / VERTS_PER_FACE; 9262 const UINT vertex_size23 = sizeof(*vertices23); 9263 const struct vertex_ptc_float4 exp_vertices23[] = 9264 { 9265 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 0.0f, 0.0f, 1.0f}}, 9266 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.0f, 0.0f, 1.0f}}, 9267 {{ 0.0f, 0.0f, 0.f}, {-0.2f, 0.0f, 0.0f, 1.0f}}, 9268 9269 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.0f, 0.0f, 1.0f}}, 9270 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 0.0f, 0.0f, 1.0f}}, 9271 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.0f, 0.0f, 1.0f}}, 9272 }; 9273 const UINT exp_vertex_size23 = sizeof(*exp_vertices23); 9274 /* Test 24. Convert FLOAT1 to D3DCOLOR. */ 9275 const struct vertex_ptc_float1 vertices24[] = 9276 { 9277 {{ 0.0f, 3.0f, 0.f}, 1.0f}, 9278 {{ 2.0f, 3.0f, 0.f}, 0.5f}, 9279 {{ 0.0f, 0.0f, 0.f}, -0.2f}, 9280 9281 {{ 3.0f, 3.0f, 0.f}, 0.2f}, 9282 {{ 3.0f, 0.0f, 0.f}, 1.0f}, 9283 {{ 1.0f, 0.0f, 0.f}, 0.11f}, 9284 }; 9285 const UINT num_vertices24 = ARRAY_SIZE(vertices24); 9286 const UINT num_faces24 = ARRAY_SIZE(vertices24) / VERTS_PER_FACE; 9287 const UINT vertex_size24 = sizeof(*vertices24); 9288 const struct vertex_ptc_d3dcolor exp_vertices24[] = 9289 { 9290 {{ 0.0f, 3.0f, 0.f}, {0, 0, 255, 255}}, 9291 {{ 2.0f, 3.0f, 0.f}, {0, 0, 128, 255}}, 9292 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 255}}, 9293 9294 {{ 3.0f, 3.0f, 0.f}, {0, 0, 51, 255}}, 9295 {{ 3.0f, 0.0f, 0.f}, {0, 0, 255, 255}}, 9296 {{ 1.0f, 0.0f, 0.f}, {0, 0, 28, 255}}, 9297 }; 9298 const UINT exp_vertex_size24 = sizeof(*exp_vertices24); 9299 /* Test 25. Convert FLOAT1 to ubyte4. */ 9300 const struct vertex_ptc_float1 vertices25[] = 9301 { 9302 {{ 0.0f, 3.0f, 0.f}, 0.0f}, 9303 {{ 2.0f, 3.0f, 0.f}, 1.4f}, 9304 {{ 0.0f, 0.0f, 0.f}, 1.5f}, 9305 9306 {{ 3.0f, 3.0f, 0.f}, 255.0f}, 9307 {{ 3.0f, 0.0f, 0.f}, 256.0f}, 9308 {{ 1.0f, 0.0f, 0.f}, -1.0f}, 9309 }; 9310 const UINT num_vertices25 = ARRAY_SIZE(vertices25); 9311 const UINT num_faces25 = ARRAY_SIZE(vertices25) / VERTS_PER_FACE; 9312 const UINT vertex_size25 = sizeof(*vertices25); 9313 const struct vertex_ptc_ubyte4 exp_vertices25[] = 9314 { 9315 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 1}}, 9316 {{ 2.0f, 3.0f, 0.f}, {1, 0, 0, 1}}, 9317 {{ 0.0f, 0.0f, 0.f}, {2, 0, 0, 1}}, 9318 9319 {{ 3.0f, 3.0f, 0.f}, {255, 0, 0, 1}}, 9320 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 1}}, 9321 {{ 1.0f, 0.0f, 0.f}, {0, 0, 0, 1}}, 9322 }; 9323 const UINT exp_vertex_size25 = sizeof(*exp_vertices25); 9324 /* Test 26. Convert FLOAT4 to D3DCOLOR. */ 9325 const struct vertex_ptc_float4 vertices26[] = 9326 { 9327 {{ 0.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.4f, 0.5f}}, 9328 {{ 2.0f, 3.0f, 0.f}, {-0.4f, -0.5f, -1.0f, -2.0f}}, 9329 {{ 0.0f, 0.0f, 0.f}, {254.0f, 255.0f, 256.0f, 257.0f}}, 9330 9331 {{ 3.0f, 3.0f, 0.f}, {0.1f, 0.2f, 0.3f, 0.4f}}, 9332 {{ 3.0f, 0.0f, 0.f}, {0.5f, 0.6f, 0.7f, 0.8f}}, 9333 {{ 1.0f, 0.0f, 0.f}, {0.9f, 0.99f, 0.995f, 0.999f}}, 9334 }; 9335 const UINT num_vertices26 = ARRAY_SIZE(vertices26); 9336 const UINT num_faces26 = ARRAY_SIZE(vertices26) / VERTS_PER_FACE; 9337 const UINT vertex_size26 = sizeof(*vertices26); 9338 const struct vertex_ptc_d3dcolor exp_vertices26[] = 9339 { 9340 {{ 0.0f, 3.0f, 0.f}, {102, 255, 0, 128}}, 9341 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, 9342 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}}, 9343 9344 {{ 3.0f, 3.0f, 0.f}, {77, 51, 26, 102}}, 9345 {{ 3.0f, 0.0f, 0.f}, {179, 153, 128, 204}}, 9346 {{ 1.0f, 0.0f, 0.f}, {254, 252, 230, 255}}, 9347 }; 9348 const UINT exp_vertex_size26 = sizeof(*exp_vertices26); 9349 /* Test 27. Convert D3DCOLOR to FLOAT4. */ 9350 const struct vertex_ptc_d3dcolor vertices27[] = 9351 { 9352 {{ 0.0f, 3.0f, 0.f}, {102, 255, 0, 128}}, 9353 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, 9354 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}}, 9355 9356 {{ 3.0f, 3.0f, 0.f}, {77, 51, 26, 102}}, 9357 {{ 3.0f, 0.0f, 0.f}, {179, 153, 128, 204}}, 9358 {{ 1.0f, 0.0f, 0.f}, {254, 252, 230, 255}}, 9359 }; 9360 const UINT num_vertices27 = ARRAY_SIZE(vertices27); 9361 const UINT num_faces27 = ARRAY_SIZE(vertices27) / VERTS_PER_FACE; 9362 const UINT vertex_size27 = sizeof(*vertices27); 9363 const struct vertex_ptc_float4 exp_vertices27[] = 9364 { 9365 {{ 0.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.4f, 0.501961f}}, 9366 {{ 2.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}}, 9367 {{ 0.0f, 0.0f, 0.f}, {1.0f, 1.0f, 1.0f, 1.0f}}, 9368 9369 {{ 3.0f, 3.0f, 0.f}, {0.101961f, 0.2f, 0.301961f, 0.4f}}, 9370 {{ 3.0f, 0.0f, 0.f}, {0.501961f, 0.6f, 0.701961f, 0.8f}}, 9371 {{ 1.0f, 0.0f, 0.f}, {0.901961f, 0.988235f, 0.996078f, 1.0f}}, 9372 }; 9373 const UINT exp_vertex_size27 = sizeof(*exp_vertices27); 9374 /* Test 28. Convert UBYTE4 to FLOAT4. */ 9375 const struct vertex_ptc_ubyte4 vertices28[] = 9376 { 9377 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, 9378 {{ 2.0f, 3.0f, 0.f}, {1, 1, 1, 1}}, 9379 {{ 0.0f, 0.0f, 0.f}, {1, 0, 1, 0}}, 9380 9381 {{ 3.0f, 3.0f, 0.f}, {0, 1, 0, 1}}, 9382 {{ 3.0f, 0.0f, 0.f}, {10, 20, 30, 40}}, 9383 {{ 1.0f, 0.0f, 0.f}, {50, 60, 127, 255}}, 9384 }; 9385 const UINT num_vertices28 = ARRAY_SIZE(vertices28); 9386 const UINT num_faces28 = ARRAY_SIZE(vertices28) / VERTS_PER_FACE; 9387 const UINT vertex_size28 = sizeof(*vertices28); 9388 const struct vertex_ptc_float4 exp_vertices28[] = 9389 { 9390 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}}, 9391 {{ 2.0f, 3.0f, 0.f}, {1.0f, 1.0f, 1.0f, 1.0f}}, 9392 {{ 0.0f, 0.0f, 0.f}, {1.0f, 0.0f, 1.0f, 0.0f}}, 9393 9394 {{ 3.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.0f, 1.0f}}, 9395 {{ 3.0f, 0.0f, 0.f}, {10.0f, 20.0f, 30.0f, 40.0f}}, 9396 {{ 1.0f, 0.0f, 0.f}, {50.0f, 60.0f, 127.0f, 255.0f}}, 9397 }; 9398 const UINT exp_vertex_size28 = sizeof(*exp_vertices28); 9399 /* Test 29. Convert SHORT2 to FLOAT4. */ 9400 const struct vertex_ptc_short2 vertices29[] = 9401 { 9402 {{ 0.0f, 3.0f, 0.f}, {0, 0}}, 9403 {{ 2.0f, 3.0f, 0.f}, {0, 1}}, 9404 {{ 0.0f, 0.0f, 0.f}, {1, 0}}, 9405 9406 {{ 3.0f, 3.0f, 0.f}, {1, 1}}, 9407 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MAX}}, 9408 {{ 1.0f, 0.0f, 0.f}, {-42, 42}}, 9409 }; 9410 const UINT num_vertices29 = ARRAY_SIZE(vertices29); 9411 const UINT num_faces29 = ARRAY_SIZE(vertices29) / VERTS_PER_FACE; 9412 const UINT vertex_size29 = sizeof(*vertices29); 9413 const struct vertex_ptc_float4 exp_vertices29[] = 9414 { 9415 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 1.0f}}, 9416 {{ 2.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.0f, 1.0f }}, 9417 {{ 0.0f, 0.0f, 0.f}, {1.0f, 0.0f, 0.0f, 1.0f}}, 9418 9419 {{ 3.0f, 3.0f, 0.f}, {1.0f, 1.0f, 0.0f, 1.0f}}, 9420 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MAX, 0.0f, 1.0f}}, 9421 {{ 1.0f, 0.0f, 0.f}, {-42.0f, 42.0f, 0.0f, 1.0f}}, 9422 }; 9423 const UINT exp_vertex_size29 = sizeof(*exp_vertices29); 9424 /* Test 29. Convert SHORT4 to FLOAT4. */ 9425 const struct vertex_ptc_short4 vertices30[] = 9426 { 9427 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, 9428 {{ 2.0f, 3.0f, 0.f}, {0, 1, 0, 1}}, 9429 {{ 0.0f, 0.0f, 0.f}, {1, 0, 1, 0}}, 9430 9431 {{ 3.0f, 3.0f, 0.f}, {1, 1, 1, 1}}, 9432 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MAX, 1, 0}}, 9433 {{ 1.0f, 0.0f, 0.f}, {-42, 42, SHRT_MAX, SHRT_MIN}}, 9434 }; 9435 const UINT num_vertices30 = ARRAY_SIZE(vertices30); 9436 const UINT num_faces30 = ARRAY_SIZE(vertices30) / VERTS_PER_FACE; 9437 const UINT vertex_size30 = sizeof(*vertices30); 9438 const struct vertex_ptc_float4 exp_vertices30[] = 9439 { 9440 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}}, 9441 {{ 2.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.0f, 1.0f }}, 9442 {{ 0.0f, 0.0f, 0.f}, {1.0f, 0.0f, 1.0f, 0.0f}}, 9443 9444 {{ 3.0f, 3.0f, 0.f}, {1.0f, 1.0f, 1.0f, 1.0f}}, 9445 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MAX, 1.0f, 0.0f}}, 9446 {{ 1.0f, 0.0f, 0.f}, {-42.0f, 42.0f, SHRT_MAX, SHRT_MIN}}, 9447 }; 9448 const UINT exp_vertex_size30 = sizeof(*exp_vertices30); 9449 /* Test 31. Convert UBYTE4N to FLOAT4. */ 9450 const struct vertex_ptc_ubyte4n vertices31[] = 9451 { 9452 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, 9453 {{ 2.0f, 3.0f, 0.f}, {1, 1, 1, 1}}, 9454 {{ 0.0f, 0.0f, 0.f}, {1, 0, 1, 0}}, 9455 9456 {{ 3.0f, 3.0f, 0.f}, {0, 1, 0, 1}}, 9457 {{ 3.0f, 0.0f, 0.f}, {10, 20, 30, 40}}, 9458 {{ 1.0f, 0.0f, 0.f}, {50, 60, 70, UCHAR_MAX}}, 9459 }; 9460 const UINT num_vertices31 = ARRAY_SIZE(vertices31); 9461 const UINT num_faces31 = ARRAY_SIZE(vertices31) / VERTS_PER_FACE; 9462 const UINT vertex_size31 = sizeof(*vertices31); 9463 const struct vertex_ptc_float4 exp_vertices31[] = 9464 { 9465 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}}, 9466 {{ 2.0f, 3.0f, 0.f}, {(FLOAT)1/UCHAR_MAX, (FLOAT)1/UCHAR_MAX, (FLOAT)1/UCHAR_MAX, (FLOAT)1/UCHAR_MAX}}, 9467 {{ 0.0f, 0.0f, 0.f}, {(FLOAT)1/UCHAR_MAX, 0.0f, (FLOAT)1/UCHAR_MAX, 0.0f}}, 9468 9469 {{ 3.0f, 3.0f, 0.f}, {0.0f, (FLOAT)1/UCHAR_MAX, 0.0f, (FLOAT)1/UCHAR_MAX}}, 9470 {{ 3.0f, 0.0f, 0.f}, {(FLOAT)10/UCHAR_MAX, (FLOAT)20/UCHAR_MAX, (FLOAT)30/UCHAR_MAX, (FLOAT)40/UCHAR_MAX}}, 9471 {{ 1.0f, 0.0f, 0.f}, {(FLOAT)50/UCHAR_MAX, (FLOAT)60/UCHAR_MAX, (FLOAT)70/UCHAR_MAX, 1.0f}}, 9472 }; 9473 const UINT exp_vertex_size31 = sizeof(*exp_vertices31); 9474 /* Test 32. Convert SHORT2N to FLOAT4. */ 9475 const struct vertex_ptc_short2 vertices32[] = 9476 { 9477 {{ 0.0f, 3.0f, 0.f}, {0, 0}}, 9478 {{ 2.0f, 3.0f, 0.f}, {0, 1}}, 9479 {{ 0.0f, 0.0f, 0.f}, {1, 0}}, 9480 9481 {{ 3.0f, 3.0f, 0.f}, {1, 1}}, 9482 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN + 1, SHRT_MAX}}, 9483 {{ 1.0f, 0.0f, 0.f}, {-42, 42}}, 9484 }; 9485 const UINT num_vertices32 = ARRAY_SIZE(vertices32); 9486 const UINT num_faces32 = ARRAY_SIZE(vertices32) / VERTS_PER_FACE; 9487 const UINT vertex_size32 = sizeof(*vertices32); 9488 const struct vertex_ptc_float4 exp_vertices32[] = 9489 { 9490 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 1.0f}}, 9491 {{ 2.0f, 3.0f, 0.f}, {0.0f, 1.0f/SHRT_MAX, 0.0f, 1.0f}}, 9492 {{ 0.0f, 0.0f, 0.f}, {1.0f/SHRT_MAX, 0.0f, 0.0f, 1.0f}}, 9493 9494 {{ 3.0f, 3.0f, 0.f}, {1.0f/SHRT_MAX, 1.0f/SHRT_MAX, 0.0f, 1.0f}}, 9495 {{ 3.0f, 0.0f, 0.f}, {-1.0f, 1.0f, 0.0f, 1.0f}}, 9496 {{ 1.0f, 0.0f, 0.f}, {-42.0f/SHRT_MAX, 42.0f/SHRT_MAX, 0.0f, 1.0f}}, 9497 }; 9498 const UINT exp_vertex_size32 = sizeof(*exp_vertices32); 9499 /* Test 33. Convert SHORT4N to FLOAT4. */ 9500 const struct vertex_ptc_short4 vertices33[] = 9501 { 9502 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, 9503 {{ 2.0f, 3.0f, 0.f}, {0, 1, 0, 1}}, 9504 {{ 0.0f, 0.0f, 0.f}, {1, 0, 1, 0}}, 9505 9506 {{ 3.0f, 3.0f, 0.f}, {1, 1, 1, 1}}, 9507 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN + 1, SHRT_MAX, SHRT_MIN + 1, SHRT_MAX}}, 9508 {{ 1.0f, 0.0f, 0.f}, {-42, 42, 1, 1}}, 9509 }; 9510 const UINT num_vertices33 = ARRAY_SIZE(vertices33); 9511 const UINT num_faces33 = ARRAY_SIZE(vertices33) / VERTS_PER_FACE; 9512 const UINT vertex_size33 = sizeof(*vertices33); 9513 const struct vertex_ptc_float4 exp_vertices33[] = 9514 { 9515 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}}, 9516 {{ 2.0f, 3.0f, 0.f}, {0.0f, 1.0f/SHRT_MAX, 0.0f, 1.0f/SHRT_MAX}}, 9517 {{ 0.0f, 0.0f, 0.f}, {1.0f/SHRT_MAX, 0.0f, 1.0f/SHRT_MAX, 0.0f}}, 9518 9519 {{ 3.0f, 3.0f, 0.f}, {1.0f/SHRT_MAX, 1.0f/SHRT_MAX, 1.0f/SHRT_MAX, 1.0f/SHRT_MAX}}, 9520 {{ 3.0f, 0.0f, 0.f}, {-1.0f, 1.0f, -1.0f, 1.0f}}, 9521 {{ 1.0f, 0.0f, 0.f}, {-42.0f/SHRT_MAX, 42.0f/SHRT_MAX, 1.0f/SHRT_MAX, 1.0f/SHRT_MAX}}, 9522 }; 9523 const UINT exp_vertex_size33 = sizeof(*exp_vertices33); 9524 /* Test 34. Convert FLOAT16_2 to FLOAT4. */ 9525 const struct vertex_ptc_float16_2 vertices34[] = 9526 { 9527 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */ 9528 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */ 9529 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */ 9530 9531 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd}}, /* {0.2f, 0.3f} */ 9532 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */ 9533 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */ 9534 }; 9535 const UINT num_vertices34 = ARRAY_SIZE(vertices34); 9536 const UINT num_faces34 = ARRAY_SIZE(vertices34) / VERTS_PER_FACE; 9537 const UINT vertex_size34 = sizeof(*vertices34); 9538 const struct vertex_ptc_float4 exp_vertices34[] = 9539 { 9540 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f, 0.0f, 1.0f}}, 9541 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.700195f, 0.0f, 1.0f}}, 9542 {{ 0.0f, 0.0f, 0.f}, {-0.199951f, -0.300049f, 0.0f, 1.0f}}, 9543 9544 {{ 3.0f, 3.0f, 0.f}, {0.199951f, 0.300049f, 0.0f, 1.0f}}, 9545 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f, 0.0f, 1.0f}}, 9546 {{ 1.0f, 0.0f, 0.f}, {0.099976f, 0.199951f, 0.0f, 1.0f}}, 9547 }; 9548 const UINT exp_vertex_size34 = sizeof(*exp_vertices34); 9549 /* Test 35. Convert FLOAT16_4 to FLOAT4. */ 9550 const struct vertex_ptc_float16_4 vertices35[] = 9551 { 9552 {{ 0.0f, 3.0f, 0.f}, {0x0000, 0x0000, 0x0000, 0x0000}}, 9553 {{ 2.0f, 3.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}}, 9554 {{ 0.0f, 0.0f, 0.f}, {0x3c00, 0x0000, 0x3c00, 0x0000}}, 9555 9556 {{ 3.0f, 3.0f, 0.f}, {0x0000, 0x3c00, 0x0000, 0x3c00}}, 9557 {{ 3.0f, 0.0f, 0.f}, {0x3800, 0x399a, 0xb266, 0xb4cd}}, 9558 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266, 0x2e66, 0x3266}}, 9559 }; 9560 const UINT num_vertices35 = ARRAY_SIZE(vertices35); 9561 const UINT num_faces35 = ARRAY_SIZE(vertices35) / VERTS_PER_FACE; 9562 const UINT vertex_size35 = sizeof(*vertices35); 9563 const struct vertex_ptc_float4 exp_vertices35[] = 9564 { 9565 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}}, 9566 {{ 2.0f, 3.0f, 0.f}, {1.0f, 1.0f, 1.0f, 1.0f}}, 9567 {{ 0.0f, 0.0f, 0.f}, {1.0f, 0.0f, 1.0f, 0.0f}}, 9568 9569 {{ 3.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.0f, 1.0f}}, 9570 {{ 3.0f, 0.0f, 0.f}, {0.5f, 0.700195f, -0.199951f, -0.300049f}}, 9571 {{ 1.0f, 0.0f, 0.f}, {0.099976f, 0.199951f, 0.099976f, 0.199951f}}, 9572 }; 9573 const UINT exp_vertex_size35 = sizeof(*exp_vertices35); 9574 /* Test 36. Check that vertex buffer sharing is ok. */ 9575 const struct vertex_pn vertices36[] = 9576 { 9577 {{ 0.0f, 3.0f, 0.f}, up}, 9578 {{ 2.0f, 3.0f, 0.f}, up}, 9579 {{ 0.0f, 0.0f, 0.f}, up}, 9580 }; 9581 const UINT num_vertices36 = ARRAY_SIZE(vertices36); 9582 const UINT num_faces36 = ARRAY_SIZE(vertices36) / VERTS_PER_FACE; 9583 const UINT vertex_size36 = sizeof(*vertices36); 9584 const DWORD clone_options36 = options | D3DXMESH_VB_SHARE; 9585 /* Common mesh data */ 9586 ID3DXMesh *mesh = NULL; 9587 ID3DXMesh *mesh_clone = NULL; 9588 struct 9589 { 9590 const BYTE *vertices; 9591 const DWORD *indices; 9592 const DWORD *attributes; 9593 const UINT num_vertices; 9594 const UINT num_faces; 9595 const UINT vertex_size; 9596 const DWORD create_options; 9597 const DWORD clone_options; 9598 D3DVERTEXELEMENT9 *declaration; 9599 D3DVERTEXELEMENT9 *new_declaration; 9600 const BYTE *exp_vertices; 9601 const UINT exp_vertex_size; 9602 } 9603 tc[] = 9604 { 9605 { 9606 (BYTE*)vertices0, 9607 NULL, 9608 NULL, 9609 num_vertices0, 9610 num_faces0, 9611 vertex_size0, 9612 options, 9613 options, 9614 declaration_pn, 9615 declaration_pn, 9616 (BYTE*)vertices0, 9617 vertex_size0 9618 }, 9619 { 9620 (BYTE*)vertices0, 9621 NULL, 9622 NULL, 9623 num_vertices0, 9624 num_faces0, 9625 vertex_size0, 9626 options_16bit, 9627 options_16bit, 9628 declaration_pn, 9629 declaration_pn, 9630 (BYTE*)vertices0, 9631 vertex_size0 9632 }, 9633 { 9634 (BYTE*)vertices0, 9635 NULL, 9636 NULL, 9637 num_vertices0, 9638 num_faces0, 9639 vertex_size0, 9640 options, 9641 options, 9642 declaration_pn, 9643 declaration_pntc, 9644 (BYTE*)exp_vertices2, 9645 exp_vertex_size2 9646 }, 9647 { 9648 (BYTE*)vertices0, 9649 NULL, 9650 NULL, 9651 num_vertices0, 9652 num_faces0, 9653 vertex_size0, 9654 options, 9655 options, 9656 declaration_pn, 9657 declaration_ptcn, 9658 (BYTE*)exp_vertices3, 9659 exp_vertex_size3 9660 }, 9661 { 9662 (BYTE*)vertices4, 9663 NULL, 9664 NULL, 9665 num_vertices4, 9666 num_faces4, 9667 vertex_size4, 9668 options, 9669 options, 9670 declaration_ptc, 9671 declaration_ptc_float16_2, 9672 (BYTE*)exp_vertices4, 9673 exp_vertex_size4 9674 }, 9675 { 9676 (BYTE*)vertices5, 9677 NULL, 9678 NULL, 9679 num_vertices5, 9680 num_faces5, 9681 vertex_size5, 9682 options, 9683 options, 9684 declaration_ptc, 9685 declaration_ptc_float16_4, 9686 (BYTE*)exp_vertices5, 9687 exp_vertex_size5 9688 }, 9689 { 9690 (BYTE*)vertices6, 9691 NULL, 9692 NULL, 9693 num_vertices6, 9694 num_faces6, 9695 vertex_size6, 9696 options, 9697 options, 9698 declaration_ptc, 9699 declaration_ptc_float1, 9700 (BYTE*)exp_vertices6, 9701 exp_vertex_size6 9702 }, 9703 { 9704 (BYTE*)vertices7, 9705 NULL, 9706 NULL, 9707 num_vertices7, 9708 num_faces7, 9709 vertex_size7, 9710 options, 9711 options, 9712 declaration_ptc, 9713 declaration_ptc_float3, 9714 (BYTE*)exp_vertices7, 9715 exp_vertex_size7 9716 }, 9717 { 9718 (BYTE*)vertices8, 9719 NULL, 9720 NULL, 9721 num_vertices8, 9722 num_faces8, 9723 vertex_size8, 9724 options, 9725 options, 9726 declaration_ptc, 9727 declaration_ptc_float4, 9728 (BYTE*)exp_vertices8, 9729 exp_vertex_size8 9730 }, 9731 { 9732 (BYTE*)vertices9, 9733 NULL, 9734 NULL, 9735 num_vertices9, 9736 num_faces9, 9737 vertex_size9, 9738 options, 9739 options, 9740 declaration_ptc, 9741 declaration_ptc_d3dcolor, 9742 (BYTE*)exp_vertices9, 9743 exp_vertex_size9 9744 }, 9745 { 9746 (BYTE*)vertices10, 9747 NULL, 9748 NULL, 9749 num_vertices10, 9750 num_faces10, 9751 vertex_size10, 9752 options, 9753 options, 9754 declaration_ptc, 9755 declaration_ptc_ubyte4, 9756 (BYTE*)exp_vertices10, 9757 exp_vertex_size10 9758 }, 9759 { 9760 (BYTE*)vertices11, 9761 NULL, 9762 NULL, 9763 num_vertices11, 9764 num_faces11, 9765 vertex_size11, 9766 options, 9767 options, 9768 declaration_ptc, 9769 declaration_ptc_short2, 9770 (BYTE*)exp_vertices11, 9771 exp_vertex_size11 9772 }, 9773 { 9774 (BYTE*)vertices12, 9775 NULL, 9776 NULL, 9777 num_vertices12, 9778 num_faces12, 9779 vertex_size12, 9780 options, 9781 options, 9782 declaration_ptc, 9783 declaration_ptc_short4, 9784 (BYTE*)exp_vertices12, 9785 exp_vertex_size12 9786 }, 9787 { 9788 (BYTE*)vertices13, 9789 NULL, 9790 NULL, 9791 num_vertices13, 9792 num_faces13, 9793 vertex_size13, 9794 options, 9795 options, 9796 declaration_ptc, 9797 declaration_ptc_ubyte4n, 9798 (BYTE*)exp_vertices13, 9799 exp_vertex_size13 9800 }, 9801 { 9802 (BYTE*)vertices14, 9803 NULL, 9804 NULL, 9805 num_vertices14, 9806 num_faces14, 9807 vertex_size14, 9808 options, 9809 options, 9810 declaration_ptc, 9811 declaration_ptc_short2n, 9812 (BYTE*)exp_vertices14, 9813 exp_vertex_size14 9814 }, 9815 { 9816 (BYTE*)vertices15, 9817 NULL, 9818 NULL, 9819 num_vertices15, 9820 num_faces15, 9821 vertex_size15, 9822 options, 9823 options, 9824 declaration_ptc, 9825 declaration_ptc_short4n, 9826 (BYTE*)exp_vertices15, 9827 exp_vertex_size15 9828 }, 9829 { 9830 (BYTE*)vertices16, 9831 NULL, 9832 NULL, 9833 num_vertices16, 9834 num_faces16, 9835 vertex_size16, 9836 options, 9837 options, 9838 declaration_ptc, 9839 declaration_ptc_ushort2n, 9840 (BYTE*)exp_vertices16, 9841 exp_vertex_size16 9842 }, 9843 { 9844 (BYTE*)vertices17, 9845 NULL, 9846 NULL, 9847 num_vertices17, 9848 num_faces17, 9849 vertex_size17, 9850 options, 9851 options, 9852 declaration_ptc, 9853 declaration_ptc_ushort4n, 9854 (BYTE*)exp_vertices17, 9855 exp_vertex_size17 9856 }, 9857 { 9858 (BYTE*)vertices18, 9859 NULL, 9860 NULL, 9861 num_vertices18, 9862 num_faces18, 9863 vertex_size18, 9864 options, 9865 options, 9866 declaration_ptc, 9867 declaration_ptc_float16_2_partialu, 9868 (BYTE*)exp_vertices18, 9869 exp_vertex_size18 9870 }, 9871 { 9872 (BYTE*)vertices19, 9873 NULL, 9874 NULL, 9875 num_vertices19, 9876 num_faces19, 9877 vertex_size19, 9878 options, 9879 options, 9880 declaration_pntc, 9881 declaration_pntc1, 9882 (BYTE*)exp_vertices19, 9883 exp_vertex_size19 9884 }, 9885 { 9886 (BYTE*)vertices20, 9887 NULL, 9888 NULL, 9889 num_vertices20, 9890 num_faces20, 9891 vertex_size20, 9892 options, 9893 options, 9894 declaration_pntc1, 9895 declaration_pntc, 9896 (BYTE*)exp_vertices20, 9897 exp_vertex_size20 9898 }, 9899 { 9900 (BYTE*)vertices21, 9901 NULL, 9902 NULL, 9903 num_vertices21, 9904 num_faces21, 9905 vertex_size21, 9906 options, 9907 options, 9908 declaration_ptc_float1, 9909 declaration_ptc, 9910 (BYTE*)exp_vertices21, 9911 exp_vertex_size21 9912 }, 9913 { 9914 (BYTE*)vertices22, 9915 NULL, 9916 NULL, 9917 num_vertices22, 9918 num_faces22, 9919 vertex_size22, 9920 options, 9921 options, 9922 declaration_ptc_float1, 9923 declaration_ptc_float3, 9924 (BYTE*)exp_vertices22, 9925 exp_vertex_size22 9926 }, 9927 { 9928 (BYTE*)vertices23, 9929 NULL, 9930 NULL, 9931 num_vertices23, 9932 num_faces23, 9933 vertex_size23, 9934 options, 9935 options, 9936 declaration_ptc_float1, 9937 declaration_ptc_float4, 9938 (BYTE*)exp_vertices23, 9939 exp_vertex_size23 9940 }, 9941 { 9942 (BYTE*)vertices24, 9943 NULL, 9944 NULL, 9945 num_vertices24, 9946 num_faces24, 9947 vertex_size24, 9948 options, 9949 options, 9950 declaration_ptc_float1, 9951 declaration_ptc_d3dcolor, 9952 (BYTE*)exp_vertices24, 9953 exp_vertex_size24 9954 }, 9955 { 9956 (BYTE*)vertices25, 9957 NULL, 9958 NULL, 9959 num_vertices25, 9960 num_faces25, 9961 vertex_size25, 9962 options, 9963 options, 9964 declaration_ptc_float1, 9965 declaration_ptc_ubyte4, 9966 (BYTE*)exp_vertices25, 9967 exp_vertex_size25 9968 }, 9969 { 9970 (BYTE*)vertices26, 9971 NULL, 9972 NULL, 9973 num_vertices26, 9974 num_faces26, 9975 vertex_size26, 9976 options, 9977 options, 9978 declaration_ptc_float4, 9979 declaration_ptc_d3dcolor, 9980 (BYTE*)exp_vertices26, 9981 exp_vertex_size26 9982 }, 9983 { 9984 (BYTE*)vertices27, 9985 NULL, 9986 NULL, 9987 num_vertices27, 9988 num_faces27, 9989 vertex_size27, 9990 options, 9991 options, 9992 declaration_ptc_d3dcolor, 9993 declaration_ptc_float4, 9994 (BYTE*)exp_vertices27, 9995 exp_vertex_size27 9996 }, 9997 { 9998 (BYTE*)vertices28, 9999 NULL, 10000 NULL, 10001 num_vertices28, 10002 num_faces28, 10003 vertex_size28, 10004 options, 10005 options, 10006 declaration_ptc_ubyte4, 10007 declaration_ptc_float4, 10008 (BYTE*)exp_vertices28, 10009 exp_vertex_size28 10010 }, 10011 { 10012 (BYTE*)vertices29, 10013 NULL, 10014 NULL, 10015 num_vertices29, 10016 num_faces29, 10017 vertex_size29, 10018 options, 10019 options, 10020 declaration_ptc_short2, 10021 declaration_ptc_float4, 10022 (BYTE*)exp_vertices29, 10023 exp_vertex_size29 10024 }, 10025 { 10026 (BYTE*)vertices30, 10027 NULL, 10028 NULL, 10029 num_vertices30, 10030 num_faces30, 10031 vertex_size30, 10032 options, 10033 options, 10034 declaration_ptc_short4, 10035 declaration_ptc_float4, 10036 (BYTE*)exp_vertices30, 10037 exp_vertex_size30 10038 }, 10039 { 10040 (BYTE*)vertices31, 10041 NULL, 10042 NULL, 10043 num_vertices31, 10044 num_faces31, 10045 vertex_size31, 10046 options, 10047 options, 10048 declaration_ptc_ubyte4n, 10049 declaration_ptc_float4, 10050 (BYTE*)exp_vertices31, 10051 exp_vertex_size31 10052 }, 10053 { 10054 (BYTE*)vertices32, 10055 NULL, 10056 NULL, 10057 num_vertices32, 10058 num_faces32, 10059 vertex_size32, 10060 options, 10061 options, 10062 declaration_ptc_short2n, 10063 declaration_ptc_float4, 10064 (BYTE*)exp_vertices32, 10065 exp_vertex_size32 10066 }, 10067 { 10068 (BYTE*)vertices33, 10069 NULL, 10070 NULL, 10071 num_vertices33, 10072 num_faces33, 10073 vertex_size33, 10074 options, 10075 options, 10076 declaration_ptc_short4n, 10077 declaration_ptc_float4, 10078 (BYTE*)exp_vertices33, 10079 exp_vertex_size33 10080 }, 10081 { 10082 (BYTE*)vertices34, 10083 NULL, 10084 NULL, 10085 num_vertices34, 10086 num_faces34, 10087 vertex_size34, 10088 options, 10089 options, 10090 declaration_ptc_float16_2, 10091 declaration_ptc_float4, 10092 (BYTE*)exp_vertices34, 10093 exp_vertex_size34 10094 }, 10095 { 10096 (BYTE*)vertices35, 10097 NULL, 10098 NULL, 10099 num_vertices35, 10100 num_faces35, 10101 vertex_size35, 10102 options, 10103 options, 10104 declaration_ptc_float16_4, 10105 declaration_ptc_float4, 10106 (BYTE*)exp_vertices35, 10107 exp_vertex_size35 10108 }, 10109 { 10110 (BYTE*)vertices36, 10111 NULL, 10112 NULL, 10113 num_vertices36, 10114 num_faces36, 10115 vertex_size36, 10116 options, 10117 clone_options36, 10118 declaration_pn, 10119 declaration_pn, 10120 (BYTE*)vertices36, 10121 vertex_size36 10122 }, 10123 }; 10124 #ifdef __REACTOS__ 10125 #undef up 10126 #undef zero_vec2 10127 #endif 10128 10129 test_context = new_test_context(); 10130 if (!test_context) 10131 { 10132 skip("Couldn't create test context\n"); 10133 goto cleanup; 10134 } 10135 10136 for (i = 0; i < ARRAY_SIZE(tc); i++) 10137 { 10138 UINT j; 10139 D3DVERTEXELEMENT9 new_declaration[MAX_FVF_DECL_SIZE]; 10140 UINT exp_new_decl_length, new_decl_length; 10141 UINT exp_new_decl_size, new_decl_size; 10142 10143 hr = init_test_mesh(tc[i].num_faces, tc[i].num_vertices, 10144 tc[i].create_options, 10145 tc[i].declaration, 10146 test_context->device, &mesh, 10147 tc[i].vertices, tc[i].vertex_size, 10148 tc[i].indices, tc[i].attributes); 10149 if (FAILED(hr)) 10150 { 10151 skip("Couldn't initialize test mesh %d. Got %x expected D3D_OK\n", i, hr); 10152 goto cleanup; 10153 } 10154 10155 hr = mesh->lpVtbl->CloneMesh(mesh, tc[i].clone_options, tc[i].new_declaration, 10156 test_context->device, &mesh_clone); 10157 ok(hr == D3D_OK, "CloneMesh test case %d failed. Got %x\n, expected D3D_OK\n", i, hr); 10158 10159 hr = mesh_clone->lpVtbl->GetDeclaration(mesh_clone, new_declaration); 10160 ok(hr == D3D_OK, "GetDeclaration test case %d failed. Got %x\n, expected D3D_OK\n", i, hr); 10161 /* Check declaration elements */ 10162 for (j = 0; tc[i].new_declaration[j].Stream != 0xFF; j++) 10163 { 10164 ok(memcmp(&tc[i].new_declaration[j], &new_declaration[j], sizeof(*new_declaration)) == 0, 10165 "Test case %d failed. Declaration element %d did not match.\n", i, j); 10166 } 10167 10168 /* Check declaration length */ 10169 exp_new_decl_length = D3DXGetDeclLength(tc[i].new_declaration); 10170 new_decl_length = D3DXGetDeclLength(new_declaration); 10171 ok(new_decl_length == exp_new_decl_length, 10172 "Test case %d failed. Got new declaration length %d, expected %d\n", 10173 i, new_decl_length, exp_new_decl_length); 10174 10175 /* Check declaration size */ 10176 exp_new_decl_size = D3DXGetDeclVertexSize(tc[i].new_declaration, 0); 10177 new_decl_size = D3DXGetDeclVertexSize(new_declaration, 0); 10178 ok(new_decl_size == exp_new_decl_size, 10179 "Test case %d failed. Got new declaration size %d, expected %d\n", 10180 i, new_decl_size, exp_new_decl_size); 10181 10182 /* Check vertex data in cloned mesh */ 10183 hr = mesh_clone->lpVtbl->LockVertexBuffer(mesh_clone, 0, (void**)&vertices); 10184 if (FAILED(hr)) 10185 { 10186 skip("Couldn't lock cloned vertex buffer.\n"); 10187 goto cleanup; 10188 } 10189 for (j = 0; j < tc[i].num_vertices; j++) 10190 { 10191 UINT index = tc[i].exp_vertex_size * j; 10192 check_vertex_components(__LINE__, i, j, &vertices[index], &tc[i].exp_vertices[index], tc[i].new_declaration); 10193 } 10194 hr = mesh_clone->lpVtbl->UnlockVertexBuffer(mesh_clone); 10195 if (FAILED(hr)) 10196 { 10197 skip("Couldn't unlock vertex buffer.\n"); 10198 goto cleanup; 10199 } 10200 vertices = NULL; 10201 mesh->lpVtbl->Release(mesh); 10202 mesh = NULL; 10203 mesh_clone->lpVtbl->Release(mesh_clone); 10204 mesh_clone = NULL; 10205 } 10206 10207 /* The following test shows that it is not possible to share a vertex buffer 10208 * with D3DXMESH_VB_SHARE and change the vertex declaration at the same 10209 * time. It reuses the test data from test 2. 10210 */ 10211 hr = init_test_mesh(tc[2].num_faces, tc[2].num_vertices, 10212 tc[2].create_options, 10213 tc[2].declaration, 10214 test_context->device, &mesh, 10215 tc[2].vertices, tc[2].vertex_size, 10216 tc[2].indices, tc[2].attributes); 10217 if (FAILED(hr)) 10218 { 10219 skip("Couldn't initialize test mesh for D3DXMESH_VB_SHARE case." 10220 " Got %x expected D3D_OK\n", hr); 10221 goto cleanup; 10222 } 10223 10224 hr = mesh->lpVtbl->CloneMesh(mesh, tc[2].create_options | D3DXMESH_VB_SHARE, 10225 tc[2].new_declaration, test_context->device, 10226 &mesh_clone); 10227 ok(hr == D3DERR_INVALIDCALL, "CloneMesh D3DXMESH_VB_SHARE with new" 10228 " declaration. Got %x, expected D3DERR_INVALIDCALL\n", 10229 hr); 10230 mesh->lpVtbl->Release(mesh); 10231 mesh = NULL; 10232 mesh_clone = NULL; 10233 10234 cleanup: 10235 if (vertices) mesh->lpVtbl->UnlockVertexBuffer(mesh); 10236 if (mesh) mesh->lpVtbl->Release(mesh); 10237 if (mesh_clone) mesh_clone->lpVtbl->Release(mesh_clone); 10238 free_test_context(test_context); 10239 } 10240 10241 static void test_valid_mesh(void) 10242 { 10243 HRESULT hr; 10244 struct test_context *test_context = NULL; 10245 UINT i; 10246 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM; 10247 const D3DVERTEXELEMENT9 declaration[] = 10248 { 10249 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 10250 D3DDECL_END() 10251 }; 10252 const unsigned int VERTS_PER_FACE = 3; 10253 /* mesh0 (one face) 10254 * 10255 * 0--1 10256 * | / 10257 * |/ 10258 * 2 10259 */ 10260 const D3DXVECTOR3 vertices0[] = 10261 { 10262 { 0.0f, 3.0f, 0.f}, 10263 { 2.0f, 3.0f, 0.f}, 10264 { 0.0f, 0.0f, 0.f}, 10265 }; 10266 const DWORD indices0[] = {0, 1, 2}; 10267 const unsigned int num_vertices0 = ARRAY_SIZE(vertices0); 10268 const unsigned int num_faces0 = ARRAY_SIZE(indices0) / VERTS_PER_FACE; 10269 const DWORD adjacency0[] = {-1, -1, -1}; 10270 const HRESULT exp_hr0 = D3D_OK; 10271 /* mesh1 (Simple bow-tie) 10272 * 10273 * 0--1 1--3 10274 * | / \ | 10275 * |/ \| 10276 * 2 4 10277 */ 10278 const D3DXVECTOR3 vertices1[] = 10279 { 10280 { 0.0f, 3.0f, 0.f}, 10281 { 2.0f, 3.0f, 0.f}, 10282 { 0.0f, 0.0f, 0.f}, 10283 10284 { 4.0f, 3.0f, 0.f}, 10285 { 4.0f, 0.0f, 0.f}, 10286 }; 10287 const DWORD indices1[] = {0, 1, 2, 1, 3, 4}; 10288 const unsigned int num_vertices1 = ARRAY_SIZE(vertices1); 10289 const unsigned int num_faces1 = ARRAY_SIZE(indices1) / VERTS_PER_FACE; 10290 const DWORD adjacency1[] = {-1, -1, -1, -1, -1, -1}; 10291 const HRESULT exp_hr1 = D3DXERR_INVALIDMESH; 10292 /* Common mesh data */ 10293 ID3DXMesh *mesh = NULL; 10294 UINT vertex_size = sizeof(D3DXVECTOR3); 10295 ID3DXBuffer *errors_and_warnings = NULL; 10296 struct 10297 { 10298 const D3DXVECTOR3 *vertices; 10299 const DWORD *indices; 10300 const UINT num_vertices; 10301 const UINT num_faces; 10302 const DWORD *adjacency; 10303 const HRESULT exp_hr; 10304 } 10305 tc[] = 10306 { 10307 { 10308 vertices0, 10309 indices0, 10310 num_vertices0, 10311 num_faces0, 10312 adjacency0, 10313 exp_hr0, 10314 }, 10315 { 10316 vertices1, 10317 indices1, 10318 num_vertices1, 10319 num_faces1, 10320 adjacency1, 10321 exp_hr1, 10322 }, 10323 }; 10324 10325 test_context = new_test_context(); 10326 if (!test_context) 10327 { 10328 skip("Couldn't create test context\n"); 10329 goto cleanup; 10330 } 10331 10332 for (i = 0; i < ARRAY_SIZE(tc); i++) 10333 { 10334 hr = init_test_mesh(tc[i].num_faces, tc[i].num_vertices, 10335 options, declaration, 10336 test_context->device, &mesh, 10337 tc[i].vertices, vertex_size, 10338 tc[i].indices, NULL); 10339 if (FAILED(hr)) 10340 { 10341 skip("Couldn't initialize test mesh %d. Got %x expected D3D_OK\n", i, hr); 10342 goto cleanup; 10343 } 10344 10345 hr = D3DXValidMesh(mesh, tc[i].adjacency, &errors_and_warnings); 10346 todo_wine ok(hr == tc[i].exp_hr, "D3DXValidMesh test case %d failed. " 10347 "Got %x\n, expected %x\n", i, hr, tc[i].exp_hr); 10348 10349 /* Note errors_and_warnings is deliberately not checked because that 10350 * would require copying wast amounts of the text output. */ 10351 if (errors_and_warnings) 10352 { 10353 ID3DXBuffer_Release(errors_and_warnings); 10354 errors_and_warnings = NULL; 10355 } 10356 mesh->lpVtbl->Release(mesh); 10357 mesh = NULL; 10358 } 10359 10360 cleanup: 10361 if (mesh) mesh->lpVtbl->Release(mesh); 10362 free_test_context(test_context); 10363 } 10364 10365 static void test_optimize_faces(void) 10366 { 10367 HRESULT hr; 10368 UINT i; 10369 DWORD smallest_face_remap; 10370 /* mesh0 10371 * 10372 * 0--1 10373 * | / 10374 * |/ 10375 * 2 10376 */ 10377 const DWORD indices0[] = {0, 1, 2}; 10378 const UINT num_faces0 = 1; 10379 const UINT num_vertices0 = 3; 10380 const DWORD exp_face_remap0[] = {0}; 10381 /* mesh1 10382 * 10383 * 0--1 3 10384 * | / /| 10385 * |/ / | 10386 * 2 5--4 10387 */ 10388 const DWORD indices1[] = {0, 1, 2, 3, 4, 5}; 10389 const UINT num_faces1 = 2; 10390 const UINT num_vertices1 = 6; 10391 const DWORD exp_face_remap1[] = {1, 0}; 10392 /* mesh2 10393 * 10394 * 0--1 10395 * | /| 10396 * |/ | 10397 * 2--3 10398 */ 10399 const DWORD indices2[] = {0, 1, 2, 1, 3, 2}; 10400 const UINT num_faces2 = 2; 10401 const UINT num_vertices2 = 4; 10402 const DWORD exp_face_remap2[] = {1, 0}; 10403 /* mesh3 10404 * 10405 * 0--1 10406 * | /| 10407 * |/ | 10408 * 2--3 10409 * | /| 10410 * |/ | 10411 * 4--5 10412 */ 10413 const DWORD indices3[] = {0, 1, 2, 1, 3, 2, 2, 3, 4, 3, 4, 5}; 10414 const UINT num_faces3 = 4; 10415 const UINT num_vertices3 = 6; 10416 const DWORD exp_face_remap3[] = {3, 2, 1, 0}; 10417 /* mesh4 10418 * 10419 * 0--1 10420 * | /| 10421 * |/ | 10422 * 2--3 10423 * | /| 10424 * |/ | 10425 * 4--5 10426 */ 10427 const WORD indices4[] = {0, 1, 2, 1, 3, 2, 2, 3, 4, 3, 4, 5}; 10428 const UINT num_faces4 = 4; 10429 const UINT num_vertices4 = 6; 10430 const DWORD exp_face_remap4[] = {3, 2, 1, 0}; 10431 /* Test cases are stored in the tc array */ 10432 struct 10433 { 10434 const VOID *indices; 10435 const UINT num_faces; 10436 const UINT num_vertices; 10437 const BOOL indices_are_32bit; 10438 const DWORD *exp_face_remap; 10439 } 10440 tc[] = 10441 { 10442 { 10443 indices0, 10444 num_faces0, 10445 num_vertices0, 10446 TRUE, 10447 exp_face_remap0 10448 }, 10449 { 10450 indices1, 10451 num_faces1, 10452 num_vertices1, 10453 TRUE, 10454 exp_face_remap1 10455 }, 10456 { 10457 indices2, 10458 num_faces2, 10459 num_vertices2, 10460 TRUE, 10461 exp_face_remap2 10462 }, 10463 { 10464 indices3, 10465 num_faces3, 10466 num_vertices3, 10467 TRUE, 10468 exp_face_remap3 10469 }, 10470 { 10471 indices4, 10472 num_faces4, 10473 num_vertices4, 10474 FALSE, 10475 exp_face_remap4 10476 }, 10477 }; 10478 10479 /* Go through all test cases */ 10480 for (i = 0; i < ARRAY_SIZE(tc); i++) 10481 { 10482 DWORD j; 10483 DWORD *face_remap; 10484 face_remap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 10485 tc[i].num_faces*sizeof(*face_remap)); 10486 10487 hr = D3DXOptimizeFaces(tc[i].indices, tc[i].num_faces, 10488 tc[i].num_vertices, tc[i].indices_are_32bit, 10489 face_remap); 10490 ok(hr == D3D_OK, "D3DXOptimizeFaces test case %d failed. " 10491 "Got %x\n, expected D3D_OK\n", i, hr); 10492 10493 /* Compare face remap with expected face remap */ 10494 for (j = 0; j < tc[i].num_faces; j++) 10495 { 10496 ok(tc[i].exp_face_remap[j] == face_remap[j], 10497 "Test case %d: Got face %d at %d, expected %d\n", i, 10498 face_remap[j], j, tc[i].exp_face_remap[j]); 10499 } 10500 10501 HeapFree(GetProcessHeap(), 0, face_remap); 10502 } 10503 10504 /* face_remap must not be NULL */ 10505 hr = D3DXOptimizeFaces(tc[0].indices, tc[0].num_faces, 10506 tc[0].num_vertices, tc[0].indices_are_32bit, 10507 NULL); 10508 ok(hr == D3DERR_INVALIDCALL, "D3DXOptimizeFaces passed NULL face_remap " 10509 "pointer. Got %x\n, expected D3DERR_INVALIDCALL\n", hr); 10510 10511 /* Number of faces must be smaller than 2^15 */ 10512 hr = D3DXOptimizeFaces(tc[0].indices, 2 << 15, 10513 tc[0].num_vertices, FALSE, 10514 &smallest_face_remap); 10515 ok(hr == D3DERR_INVALIDCALL, "D3DXOptimizeFaces should not accept 2^15 " 10516 "faces when using 16-bit indices. Got %x\n, expected D3DERR_INVALIDCALL\n", hr); 10517 } 10518 10519 static HRESULT clear_normals(ID3DXMesh *mesh) 10520 { 10521 HRESULT hr; 10522 BYTE *vertices; 10523 size_t normal_size; 10524 DWORD i, num_vertices, vertex_stride; 10525 const D3DXVECTOR4 normal = {NAN, NAN, NAN, NAN}; 10526 D3DVERTEXELEMENT9 *normal_declaration = NULL; 10527 D3DVERTEXELEMENT9 declaration[MAX_FVF_DECL_SIZE] = {D3DDECL_END()}; 10528 10529 if (FAILED(hr = mesh->lpVtbl->GetDeclaration(mesh, declaration))) 10530 return hr; 10531 10532 for (i = 0; declaration[i].Stream != 0xff; i++) 10533 { 10534 if (declaration[i].Usage == D3DDECLUSAGE_NORMAL && !declaration[i].UsageIndex) 10535 { 10536 normal_declaration = &declaration[i]; 10537 break; 10538 } 10539 } 10540 10541 if (!normal_declaration) 10542 return D3DERR_INVALIDCALL; 10543 10544 if (normal_declaration->Type == D3DDECLTYPE_FLOAT3) 10545 { 10546 normal_size = sizeof(D3DXVECTOR3); 10547 } 10548 else if (normal_declaration->Type == D3DDECLTYPE_FLOAT4) 10549 { 10550 normal_size = sizeof(D3DXVECTOR4); 10551 } 10552 else 10553 { 10554 trace("Cannot clear normals\n"); 10555 return E_NOTIMPL; 10556 } 10557 10558 num_vertices = mesh->lpVtbl->GetNumVertices(mesh); 10559 vertex_stride = mesh->lpVtbl->GetNumBytesPerVertex(mesh); 10560 10561 if (FAILED(hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, (void **)&vertices))) 10562 return hr; 10563 10564 vertices += normal_declaration->Offset; 10565 10566 for (i = 0; i < num_vertices; i++, vertices += vertex_stride) 10567 memcpy(vertices, &normal, normal_size); 10568 10569 return mesh->lpVtbl->UnlockVertexBuffer(mesh); 10570 } 10571 10572 static void compare_normals(unsigned int line, const char *test_name, 10573 ID3DXMesh *mesh, const D3DXVECTOR3 *normals, unsigned int num_normals) 10574 { 10575 unsigned int i; 10576 BYTE *vertices; 10577 DWORD num_vertices, vertex_stride; 10578 D3DVERTEXELEMENT9 *normal_declaration = NULL; 10579 D3DVERTEXELEMENT9 declaration[MAX_FVF_DECL_SIZE] = {D3DDECL_END()}; 10580 10581 if (FAILED(mesh->lpVtbl->GetDeclaration(mesh, declaration))) 10582 { 10583 ok_(__FILE__, line)(0, "%s: Failed to get declaration\n", test_name); 10584 return; 10585 } 10586 10587 for (i = 0; declaration[i].Stream != 0xff; i++) 10588 { 10589 if (declaration[i].Usage == D3DDECLUSAGE_NORMAL && !declaration[i].UsageIndex) 10590 { 10591 normal_declaration = &declaration[i]; 10592 break; 10593 } 10594 } 10595 10596 if (!normal_declaration) 10597 { 10598 ok_(__FILE__, line)(0, "%s: Mesh has no normals\n", test_name); 10599 return; 10600 } 10601 10602 if (normal_declaration->Type != D3DDECLTYPE_FLOAT3 && normal_declaration->Type != D3DDECLTYPE_FLOAT4) 10603 { 10604 ok_(__FILE__, line)(0, "%s: Mesh has invalid normals type\n", test_name); 10605 return; 10606 } 10607 10608 num_vertices = mesh->lpVtbl->GetNumVertices(mesh); 10609 vertex_stride = mesh->lpVtbl->GetNumBytesPerVertex(mesh); 10610 10611 ok_(__FILE__, line)(num_vertices == num_normals, "%s: Expected %u vertices, got %u\n", test_name, 10612 num_normals, num_vertices); 10613 10614 if (FAILED(mesh->lpVtbl->LockVertexBuffer(mesh, 0, (void **)&vertices))) 10615 { 10616 ok_(__FILE__, line)(0, "%s: Failed to compare normals\n", test_name); 10617 return; 10618 } 10619 10620 vertices += normal_declaration->Offset; 10621 10622 for (i = 0; i < min(num_vertices, num_normals); i++, vertices += vertex_stride) 10623 { 10624 if (normal_declaration->Type == D3DDECLTYPE_FLOAT3) 10625 { 10626 const D3DXVECTOR3 *n = (D3DXVECTOR3 *)vertices; 10627 ok_(__FILE__, line)(compare_vec3(*n, normals[i]), 10628 "%s: normal %2u, expected (%f, %f, %f), got (%f, %f, %f)\n", 10629 test_name, i, normals[i].x, normals[i].y, normals[i].z, n->x, n->y, n->z); 10630 } 10631 else 10632 { 10633 const D3DXVECTOR4 *n = (D3DXVECTOR4 *)vertices; 10634 const D3DXVECTOR4 normal = {normals[i].x, normals[i].y, normals[i].z, 1.0f}; 10635 ok_(__FILE__, line)(compare_vec4(*n, normal), 10636 "%s: normal %2u, expected (%f, %f, %f, %f), got (%f, %f, %f, %f)\n", 10637 test_name, i, normals[i].x, normals[i].y, normals[i].z, 1.0f, 10638 n->x, n->y, n->z, n->w); 10639 } 10640 } 10641 10642 mesh->lpVtbl->UnlockVertexBuffer(mesh); 10643 } 10644 10645 static HRESULT compute_normals_D3DXComputeNormals(ID3DXMesh *mesh, const DWORD *adjacency) 10646 { 10647 return D3DXComputeNormals((ID3DXBaseMesh *)mesh, adjacency); 10648 } 10649 10650 static HRESULT compute_normals_D3DXComputeTangentFrameEx(ID3DXMesh *mesh, const DWORD *adjacency) 10651 { 10652 return D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, 10653 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS, 10654 adjacency, -1.01f, -0.01f, -1.01f, NULL, NULL); 10655 } 10656 10657 static void test_compute_normals(void) 10658 { 10659 HRESULT hr; 10660 ULONG refcount; 10661 ID3DXMesh *mesh, *cloned_mesh; 10662 ID3DXBuffer *adjacency; 10663 IDirect3DDevice9 *device; 10664 struct test_context *test_context; 10665 unsigned int i; 10666 10667 static const struct compute_normals_func 10668 { 10669 const char *name; 10670 HRESULT (*apply)(ID3DXMesh *mesh, const DWORD *adjacency); 10671 } 10672 compute_normals_funcs[] = 10673 { 10674 {"D3DXComputeNormals", compute_normals_D3DXComputeNormals }, 10675 {"D3DXComputeTangentFrameEx", compute_normals_D3DXComputeTangentFrameEx} 10676 }; 10677 10678 static const D3DXVECTOR3 box_normals[24] = 10679 { 10680 {-1.0f, 0.0f, 0.0f}, {-1.0f, 0.0f, 0.0f}, {-1.0f, 0.0f, 0.0f}, {-1.0f, 0.0f, 0.0f}, 10681 { 0.0f, 1.0f, 0.0f}, { 0.0f, 1.0f, 0.0f}, { 0.0f, 1.0f, 0.0f}, { 0.0f, 1.0f, 0.0f}, 10682 { 1.0f, 0.0f, 0.0f}, { 1.0f, 0.0f, 0.0f}, { 1.0f, 0.0f, 0.0f}, { 1.0f, 0.0f, 0.0f}, 10683 { 0.0f,-1.0f, 0.0f}, { 0.0f,-1.0f, 0.0f}, { 0.0f,-1.0f, 0.0f}, { 0.0f,-1.0f, 0.0f}, 10684 { 0.0f, 0.0f, 1.0f}, { 0.0f, 0.0f, 1.0f}, { 0.0f, 0.0f, 1.0f}, { 0.0f, 0.0f, 1.0f}, 10685 { 0.0f, 0.0f,-1.0f}, { 0.0f, 0.0f,-1.0f}, { 0.0f, 0.0f,-1.0f}, { 0.0f, 0.0f,-1.0f} 10686 }; 10687 const float box_normal_component = 1.0f / sqrtf(3.0f); 10688 const D3DXVECTOR3 box_normals_adjacency[24] = 10689 { 10690 {-box_normal_component, -box_normal_component, -box_normal_component}, 10691 {-box_normal_component, -box_normal_component, box_normal_component}, 10692 {-box_normal_component, box_normal_component, box_normal_component}, 10693 {-box_normal_component, box_normal_component, -box_normal_component}, 10694 {-box_normal_component, box_normal_component, -box_normal_component}, 10695 {-box_normal_component, box_normal_component, box_normal_component}, 10696 { box_normal_component, box_normal_component, box_normal_component}, 10697 { box_normal_component, box_normal_component, -box_normal_component}, 10698 { box_normal_component, box_normal_component, -box_normal_component}, 10699 { box_normal_component, box_normal_component, box_normal_component}, 10700 { box_normal_component, -box_normal_component, box_normal_component}, 10701 { box_normal_component, -box_normal_component, -box_normal_component}, 10702 {-box_normal_component, -box_normal_component, box_normal_component}, 10703 {-box_normal_component, -box_normal_component, -box_normal_component}, 10704 { box_normal_component, -box_normal_component, -box_normal_component}, 10705 { box_normal_component, -box_normal_component, box_normal_component}, 10706 {-box_normal_component, -box_normal_component, box_normal_component}, 10707 { box_normal_component, -box_normal_component, box_normal_component}, 10708 { box_normal_component, box_normal_component, box_normal_component}, 10709 {-box_normal_component, box_normal_component, box_normal_component}, 10710 {-box_normal_component, -box_normal_component, -box_normal_component}, 10711 {-box_normal_component, box_normal_component, -box_normal_component}, 10712 { box_normal_component, box_normal_component, -box_normal_component}, 10713 { box_normal_component, -box_normal_component, -box_normal_component} 10714 }; 10715 static const D3DXVECTOR3 box_normals_adjacency_area[24] = 10716 { 10717 {-0.666667f, -0.333333f, -0.666667f}, {-0.333333f, -0.666667f, 0.666667f}, 10718 {-0.816496f, 0.408248f, 0.408248f}, {-0.408248f, 0.816496f, -0.408248f}, 10719 {-0.408248f, 0.816496f, -0.408248f}, {-0.816496f, 0.408248f, 0.408248f}, 10720 { 0.333333f, 0.666667f, 0.666667f}, { 0.666667f, 0.333333f, -0.666667f}, 10721 { 0.666667f, 0.333333f, -0.666667f}, { 0.333333f, 0.666667f, 0.666667f}, 10722 { 0.816496f, -0.408248f, 0.408248f}, { 0.408248f, -0.816496f, -0.408248f}, 10723 {-0.333333f, -0.666667f, 0.666667f}, {-0.666667f, -0.333333f, -0.666667f}, 10724 { 0.408248f, -0.816496f, -0.408248f}, { 0.816496f, -0.408248f, 0.408248f}, 10725 {-0.333333f, -0.666667f, 0.666667f}, { 0.816497f, -0.408248f, 0.408248f}, 10726 { 0.333333f, 0.666667f, 0.666667f}, {-0.816497f, 0.408248f, 0.408248f}, 10727 {-0.666667f, -0.333333f, -0.666667f}, {-0.408248f, 0.816497f, -0.408248f}, 10728 { 0.666667f, 0.333333f, -0.666667f}, { 0.408248f, -0.816496f, -0.408248f} 10729 }; 10730 static const D3DXVECTOR3 box_normals_position1f[24] = {{0}}; 10731 static const D3DXVECTOR3 box_normals_position2f[24] = 10732 { 10733 {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f}, 10734 {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, 1.0f}, 10735 {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, -1.0f}, 10736 {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}, 10737 {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, -1.0f}, 10738 {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f}, 10739 {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}, 10740 {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, -1.0f} 10741 }; 10742 10743 static const D3DXVECTOR3 sphere_normals[22] = 10744 { 10745 { 0.000000f, -0.000000f, 1.000000f}, { 0.000000f, 0.582244f, 0.813014f}, 10746 { 0.582244f, -0.000000f, 0.813014f}, {-0.000000f, -0.582244f, 0.813014f}, 10747 {-0.582244f, 0.000000f, 0.813014f}, {-0.000000f, 0.890608f, 0.454772f}, 10748 { 0.890608f, 0.000000f, 0.454772f}, { 0.000000f, -0.890608f, 0.454772f}, 10749 {-0.890608f, -0.000000f, 0.454772f}, { 0.000000f, 1.000000f, -0.000000f}, 10750 { 1.000000f, -0.000000f, -0.000000f}, {-0.000000f, -1.000000f, -0.000000f}, 10751 {-1.000000f, 0.000000f, -0.000000f}, { 0.000000f, 0.890608f, -0.454773f}, 10752 { 0.890608f, -0.000000f, -0.454772f}, {-0.000000f, -0.890608f, -0.454773f}, 10753 {-0.890608f, 0.000000f, -0.454773f}, { 0.000000f, 0.582244f, -0.813015f}, 10754 { 0.582244f, -0.000000f, -0.813015f}, { 0.000000f, -0.582244f, -0.813015f}, 10755 {-0.582243f, 0.000000f, -0.813015f}, { 0.000000f, 0.000000f, -1.000000f} 10756 }; 10757 static const D3DXVECTOR3 sphere_normals_area[22] = 10758 { 10759 { 0.000000f, -0.000000f, 1.000000f}, {-0.215311f, 0.554931f, 0.803550f}, 10760 { 0.554931f, 0.215311f, 0.803550f}, { 0.215311f, -0.554931f, 0.803550f}, 10761 {-0.554931f, -0.215311f, 0.803550f}, {-0.126638f, 0.872121f, 0.472618f}, 10762 { 0.872121f, 0.126638f, 0.472618f}, { 0.126638f, -0.872121f, 0.472618f}, 10763 {-0.872121f, -0.126637f, 0.472618f}, { 0.000000f, 1.000000f, -0.000000f}, 10764 { 1.000000f, -0.000000f, -0.000000f}, {-0.000000f, -1.000000f, -0.000000f}, 10765 {-1.000000f, 0.000000f, -0.000000f}, { 0.126638f, 0.872121f, -0.472618f}, 10766 { 0.872121f, -0.126638f, -0.472618f}, {-0.126638f, -0.872121f, -0.472618f}, 10767 {-0.872121f, 0.126638f, -0.472618f}, { 0.215311f, 0.554931f, -0.803550f}, 10768 { 0.554931f, -0.215311f, -0.803550f}, {-0.215311f, -0.554931f, -0.803550f}, 10769 {-0.554931f, 0.215311f, -0.803550f}, { 0.000000f, 0.000000f, -1.000000f} 10770 }; 10771 static const D3DXVECTOR3 sphere_normals_equal[22] = 10772 { 10773 { 0.000000f, -0.000000f, 1.000000f}, {-0.134974f, 0.522078f, 0.842150f}, 10774 { 0.522078f, 0.134974f, 0.842150f}, { 0.134974f, -0.522078f, 0.842150f}, 10775 {-0.522078f, -0.134974f, 0.842150f}, {-0.026367f, 0.857121f, 0.514440f}, 10776 { 0.857121f, 0.026367f, 0.514440f}, { 0.026367f, -0.857121f, 0.514440f}, 10777 {-0.857121f, -0.026367f, 0.514440f}, { 0.000000f, 1.000000f, -0.000000f}, 10778 { 1.000000f, -0.000000f, -0.000000f}, {-0.000000f, -1.000000f, -0.000000f}, 10779 {-1.000000f, 0.000000f, -0.000000f}, { 0.026367f, 0.857121f, -0.514440f}, 10780 { 0.857121f, -0.026367f, -0.514440f}, {-0.026367f, -0.857121f, -0.514440f}, 10781 {-0.857121f, 0.026367f, -0.514440f}, { 0.134975f, 0.522078f, -0.842150f}, 10782 { 0.522078f, -0.134975f, -0.842150f}, {-0.134974f, -0.522078f, -0.842150f}, 10783 {-0.522078f, 0.134974f, -0.842150f}, { 0.000000f, 0.000000f, -1.000000f} 10784 }; 10785 10786 static const D3DVERTEXELEMENT9 position3f_normal1f_declaration[] = 10787 { 10788 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 10789 {0, sizeof(D3DXVECTOR3), D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 10790 D3DDECL_END() 10791 }; 10792 static const D3DVERTEXELEMENT9 position3f_normal2f_declaration[] = 10793 { 10794 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 10795 {0, sizeof(D3DXVECTOR3), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 10796 D3DDECL_END() 10797 }; 10798 static const D3DVERTEXELEMENT9 normal4f_position3f_declaration[] = 10799 { 10800 {0, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 10801 {0, sizeof(D3DXVECTOR4), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 10802 D3DDECL_END() 10803 }; 10804 static const D3DVERTEXELEMENT9 position1f_normal3f_declaration[] = 10805 { 10806 {0, 0, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 10807 {0, sizeof(float), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 10808 D3DDECL_END() 10809 }; 10810 static const D3DVERTEXELEMENT9 position2f_normal3f_declaration[] = 10811 { 10812 {0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 10813 {0, sizeof(D3DXVECTOR2), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 10814 D3DDECL_END() 10815 }; 10816 static const D3DVERTEXELEMENT9 position4f_normal3f_declaration[] = 10817 { 10818 {0, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 10819 {0, sizeof(D3DXVECTOR4), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 10820 D3DDECL_END() 10821 }; 10822 10823 for (i = 0; i < ARRAY_SIZE(compute_normals_funcs); i++) 10824 { 10825 hr = compute_normals_funcs[i].apply(NULL, NULL); 10826 ok(hr == D3DERR_INVALIDCALL, "%s returned %#x, expected D3DERR_INVALIDCALL\n", compute_normals_funcs[i].name, hr); 10827 } 10828 10829 if (!(test_context = new_test_context())) 10830 { 10831 skip("Couldn't create test context\n"); 10832 return; 10833 } 10834 device = test_context->device; 10835 10836 hr = D3DXCreateBox(device, 1.0f, 1.0f, 1.0f, &mesh, &adjacency); 10837 ok(SUCCEEDED(hr), "D3DXCreateBox failed %#x\n", hr); 10838 10839 /* Check wrong input */ 10840 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, 10841 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE, NULL, -1.01f, -0.01f, -1.01f, NULL, NULL); 10842 todo_wine ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr); 10843 10844 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DDECLUSAGE_NORMAL, 0, 10845 D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_BY_AREA | D3DXTANGENT_WEIGHT_EQUAL, 10846 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL); 10847 ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr); 10848 10849 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, 10850 D3DDECLUSAGE_NORMAL, 0, 0, NULL, -1.01f, -0.01f, -1.01f, NULL, NULL); 10851 todo_wine ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr); 10852 10853 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, 10854 D3DDECLUSAGE_NORMAL, 1, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS, 10855 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL); 10856 ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr); 10857 10858 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, 10859 D3DX_DEFAULT, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS, 10860 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL); 10861 ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr); 10862 10863 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, 10864 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_CALCULATE_NORMALS, 10865 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL); 10866 todo_wine ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr); 10867 10868 for (i = 0; i < ARRAY_SIZE(compute_normals_funcs); i++) 10869 { 10870 const struct compute_normals_func *func = &compute_normals_funcs[i]; 10871 10872 /* Mesh without normals */ 10873 hr = mesh->lpVtbl->CloneMeshFVF(mesh, 0, D3DFVF_XYZ, device, &cloned_mesh); 10874 ok(SUCCEEDED(hr), "CloneMeshFVF failed %#x\n", hr); 10875 10876 hr = func->apply(cloned_mesh, NULL); 10877 ok(hr == D3DERR_INVALIDCALL, "%s returned %#x, expected D3DERR_INVALIDCALL\n", func->name, hr); 10878 10879 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh); 10880 ok(!refcount, "Mesh has %u references left\n", refcount); 10881 10882 /* Mesh without positions */ 10883 hr = mesh->lpVtbl->CloneMeshFVF(mesh, 0, D3DFVF_NORMAL, device, &cloned_mesh); 10884 ok(SUCCEEDED(hr), "CloneMeshFVF failed %#x\n", hr); 10885 10886 hr = func->apply(cloned_mesh, NULL); 10887 ok(hr == D3DERR_INVALIDCALL, "%s returned %#x, expected D3DERR_INVALIDCALL\n", func->name, hr); 10888 10889 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh); 10890 ok(!refcount, "Mesh has %u references left\n", refcount); 10891 10892 /* Mesh with D3DDECLTYPE_FLOAT1 normals */ 10893 hr = mesh->lpVtbl->CloneMesh(mesh, 0, position3f_normal1f_declaration, device, &cloned_mesh); 10894 ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr); 10895 10896 hr = func->apply(cloned_mesh, NULL); 10897 ok(hr == D3DERR_INVALIDCALL, "%s returned %#x, expected D3DERR_INVALIDCALL\n", func->name, hr); 10898 10899 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh); 10900 ok(!refcount, "Mesh has %u references left\n", refcount); 10901 10902 /* Mesh with D3DDECLTYPE_FLOAT2 normals */ 10903 hr = mesh->lpVtbl->CloneMesh(mesh, 0, position3f_normal2f_declaration, device, &cloned_mesh); 10904 ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr); 10905 10906 hr = func->apply(cloned_mesh, NULL); 10907 ok(hr == D3DERR_INVALIDCALL, "%s returned %#x, expected D3DERR_INVALIDCALL\n", func->name, hr); 10908 10909 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh); 10910 ok(!refcount, "Mesh has %u references left\n", refcount); 10911 10912 /* Mesh without adjacency data */ 10913 hr = clear_normals(mesh); 10914 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr); 10915 10916 hr = func->apply(mesh, NULL); 10917 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr); 10918 10919 compare_normals(__LINE__, func->name, mesh, box_normals, ARRAY_SIZE(box_normals)); 10920 10921 /* Mesh with adjacency data */ 10922 hr = clear_normals(mesh); 10923 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr); 10924 10925 hr = func->apply(mesh, ID3DXBuffer_GetBufferPointer(adjacency)); 10926 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr); 10927 10928 compare_normals(__LINE__, func->name, mesh, box_normals_adjacency, ARRAY_SIZE(box_normals_adjacency)); 10929 10930 /* Mesh with custom vertex format, D3DDECLTYPE_FLOAT4 normals and adjacency */ 10931 hr = mesh->lpVtbl->CloneMesh(mesh, 0, normal4f_position3f_declaration, device, &cloned_mesh); 10932 ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr); 10933 10934 hr = clear_normals(cloned_mesh); 10935 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr); 10936 10937 hr = func->apply(cloned_mesh, ID3DXBuffer_GetBufferPointer(adjacency)); 10938 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr); 10939 10940 compare_normals(__LINE__, func->name, cloned_mesh, box_normals_adjacency, ARRAY_SIZE(box_normals_adjacency)); 10941 10942 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh); 10943 ok(!refcount, "Mesh has %u references left\n", refcount); 10944 10945 /* Mesh with D3DDECLTYPE_FLOAT1 positions and D3DDECLTYPE_FLOAT3 normals */ 10946 hr = mesh->lpVtbl->CloneMesh(mesh, 0, position1f_normal3f_declaration, device, &cloned_mesh); 10947 ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr); 10948 10949 hr = clear_normals(cloned_mesh); 10950 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr); 10951 10952 hr = func->apply(cloned_mesh, ID3DXBuffer_GetBufferPointer(adjacency)); 10953 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr); 10954 10955 compare_normals(__LINE__, func->name, cloned_mesh, box_normals_position1f, ARRAY_SIZE(box_normals_position1f)); 10956 10957 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh); 10958 ok(!refcount, "Mesh has %u references left\n", refcount); 10959 10960 /* Mesh with D3DDECLTYPE_FLOAT2 positions and D3DDECLTYPE_FLOAT3 normals */ 10961 hr = mesh->lpVtbl->CloneMesh(mesh, 0, position2f_normal3f_declaration, device, &cloned_mesh); 10962 ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr); 10963 10964 hr = clear_normals(cloned_mesh); 10965 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr); 10966 10967 hr = func->apply(cloned_mesh, ID3DXBuffer_GetBufferPointer(adjacency)); 10968 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr); 10969 10970 compare_normals(__LINE__, func->name, cloned_mesh, box_normals_position2f, ARRAY_SIZE(box_normals_position2f)); 10971 10972 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh); 10973 ok(!refcount, "Mesh has %u references left\n", refcount); 10974 10975 /* Mesh with D3DDECLTYPE_FLOAT4 positions and D3DDECLTYPE_FLOAT3 normals */ 10976 hr = mesh->lpVtbl->CloneMesh(mesh, 0, position4f_normal3f_declaration, device, &cloned_mesh); 10977 ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr); 10978 10979 hr = clear_normals(cloned_mesh); 10980 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr); 10981 10982 hr = func->apply(cloned_mesh, ID3DXBuffer_GetBufferPointer(adjacency)); 10983 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr); 10984 10985 compare_normals(__LINE__, func->name, cloned_mesh, box_normals_adjacency, ARRAY_SIZE(box_normals_adjacency)); 10986 10987 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh); 10988 ok(!refcount, "Mesh has %u references left\n", refcount); 10989 } 10990 10991 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, 10992 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_BY_AREA, 10993 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL); 10994 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr); 10995 10996 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, box_normals, ARRAY_SIZE(box_normals)); 10997 10998 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, 10999 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_BY_AREA, 11000 ID3DXBuffer_GetBufferPointer(adjacency), -1.01f, -0.01f, -1.01f, NULL, NULL); 11001 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr); 11002 11003 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, box_normals_adjacency_area, ARRAY_SIZE(box_normals_adjacency_area)); 11004 11005 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, 11006 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_EQUAL, 11007 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL); 11008 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr); 11009 11010 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, box_normals, ARRAY_SIZE(box_normals)); 11011 11012 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, 11013 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_EQUAL, 11014 ID3DXBuffer_GetBufferPointer(adjacency), -1.01f, -0.01f, -1.01f, NULL, NULL); 11015 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr); 11016 11017 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, box_normals_adjacency_area, ARRAY_SIZE(box_normals_adjacency_area)); 11018 11019 refcount = mesh->lpVtbl->Release(mesh); 11020 ok(!refcount, "Mesh has %u references left\n", refcount); 11021 refcount = ID3DXBuffer_Release(adjacency); 11022 ok(!refcount, "Buffer has %u references left\n", refcount); 11023 11024 hr = D3DXCreateSphere(device, 1.0f, 4, 6, &mesh, &adjacency); 11025 ok(SUCCEEDED(hr), "D3DXCreateSphere failed %#x\n", hr); 11026 11027 for (i = 0; i < ARRAY_SIZE(compute_normals_funcs); i++) 11028 { 11029 const struct compute_normals_func *func = &compute_normals_funcs[i]; 11030 11031 /* Sphere without adjacency data */ 11032 hr = clear_normals(mesh); 11033 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr); 11034 11035 hr = func->apply(mesh, NULL); 11036 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr); 11037 11038 compare_normals(__LINE__, func->name, mesh, sphere_normals, ARRAY_SIZE(sphere_normals)); 11039 11040 /* Sphere with adjacency data */ 11041 hr = clear_normals(mesh); 11042 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr); 11043 11044 hr = func->apply(mesh, ID3DXBuffer_GetBufferPointer(adjacency)); 11045 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr); 11046 11047 compare_normals(__LINE__, func->name, mesh, sphere_normals, ARRAY_SIZE(sphere_normals)); 11048 } 11049 11050 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, 11051 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_BY_AREA, 11052 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL); 11053 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr); 11054 11055 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, sphere_normals_area, ARRAY_SIZE(sphere_normals_area)); 11056 11057 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, 11058 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_BY_AREA, 11059 ID3DXBuffer_GetBufferPointer(adjacency), -1.01f, -0.01f, -1.01f, NULL, NULL); 11060 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr); 11061 11062 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, sphere_normals_area, ARRAY_SIZE(sphere_normals_area)); 11063 11064 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, 11065 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_EQUAL, 11066 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL); 11067 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr); 11068 11069 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, sphere_normals_equal, ARRAY_SIZE(sphere_normals_equal)); 11070 11071 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, 11072 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_EQUAL, 11073 ID3DXBuffer_GetBufferPointer(adjacency), -1.01f, -0.01f, -1.01f, NULL, NULL); 11074 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr); 11075 11076 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, sphere_normals_equal, ARRAY_SIZE(sphere_normals_equal)); 11077 11078 refcount = mesh->lpVtbl->Release(mesh); 11079 ok(!refcount, "Mesh has %u references left\n", refcount); 11080 refcount = ID3DXBuffer_Release(adjacency); 11081 ok(!refcount, "Buffer has %u references left\n", refcount); 11082 11083 free_test_context(test_context); 11084 } 11085 11086 static void D3DXCreateAnimationControllerTest(void) 11087 { 11088 HRESULT hr; 11089 ID3DXAnimationController *animation; 11090 UINT value; 11091 11092 hr = D3DXCreateAnimationController(0, 0, 0, 0, NULL); 11093 ok(hr == D3D_OK, "Got unexpected hr returned %#x.\n", hr); 11094 11095 animation = (void*)0xdeadbeef; 11096 hr = D3DXCreateAnimationController(0, 1, 1, 1, &animation); 11097 ok(hr == D3D_OK, "Got unexpected hr returned %#x.\n", hr); 11098 ok(animation == (void*)0xdeadbeef, "Got unexpected animation %p.\n", animation); 11099 11100 animation = (void*)0xdeadbeef; 11101 hr = D3DXCreateAnimationController(1, 0, 1, 1, &animation); 11102 ok(hr == D3D_OK, "Got unexpected hr returned %#x.\n", hr); 11103 ok(animation == (void*)0xdeadbeef, "Got unexpected animation %p.\n", animation); 11104 11105 animation = (void*)0xdeadbeef; 11106 hr = D3DXCreateAnimationController(1, 1, 0, 1, &animation); 11107 ok(hr == D3D_OK, "Got unexpected hr returned %#x.\n", hr); 11108 ok(animation == (void*)0xdeadbeef, "Got unexpected animation %p.\n", animation); 11109 11110 animation = (void*)0xdeadbeef; 11111 hr = D3DXCreateAnimationController(1, 1, 1, 0, &animation); 11112 ok(hr == D3D_OK, "Got unexpected hr returned %#x.\n", hr); 11113 ok(animation == (void*)0xdeadbeef, "Got unexpected animation %p.\n", animation); 11114 11115 hr = D3DXCreateAnimationController(1, 1, 1, 1, &animation); 11116 ok(hr == D3D_OK, "Got unexpected hr returned %#x.\n", hr); 11117 11118 value = animation->lpVtbl->GetMaxNumAnimationOutputs(animation); 11119 ok(value == 1, "Got unexpected value %u.\n", value); 11120 11121 value = animation->lpVtbl->GetMaxNumAnimationSets(animation); 11122 ok(value == 1, "Got unexpected value %u.\n", value); 11123 11124 value = animation->lpVtbl->GetMaxNumTracks(animation); 11125 ok(value == 1, "Got unexpected value %u.\n", value); 11126 11127 value = animation->lpVtbl->GetMaxNumEvents(animation); 11128 ok(value == 1, "Got unexpected value %u.\n", value); 11129 11130 animation->lpVtbl->Release(animation); 11131 11132 hr = D3DXCreateAnimationController(100, 101, 102, 103, &animation); 11133 ok(hr == D3D_OK, "Got unexpected hr returned %#x.\n", hr); 11134 11135 value = animation->lpVtbl->GetMaxNumAnimationOutputs(animation); 11136 ok(value == 100, "Got unexpected value %u.\n", value); 11137 11138 value = animation->lpVtbl->GetMaxNumAnimationSets(animation); 11139 ok(value == 101, "Got unexpected value %u.\n", value); 11140 11141 value = animation->lpVtbl->GetMaxNumTracks(animation); 11142 ok(value == 102, "Got unexpected value %u.\n", value); 11143 11144 value = animation->lpVtbl->GetMaxNumEvents(animation); 11145 ok(value == 103, "Got unexpected value %u.\n", value); 11146 11147 animation->lpVtbl->Release(animation); 11148 } 11149 11150 static void test_D3DXFrameFind(void) 11151 { 11152 static char n1[] = "name1"; 11153 static char n2[] = "name2"; 11154 static char n3[] = "name3"; 11155 static char n4[] = "name4"; 11156 static char n5[] = "name5"; 11157 static char n6[] = "name6"; 11158 static char N1[] = "Name1"; 11159 D3DXFRAME root, sibling, sibling2, child, *ret; 11160 D3DXFRAME child2, child3; 11161 11162 ret = D3DXFrameFind(NULL, NULL); 11163 ok(ret == NULL, "Unexpected frame, %p.\n", ret); 11164 11165 ret = D3DXFrameFind(NULL, "test"); 11166 ok(ret == NULL, "Unexpected frame, %p.\n", ret); 11167 11168 memset(&root, 0, sizeof(root)); 11169 11170 ret = D3DXFrameFind(&root, NULL); 11171 ok(ret == &root, "Unexpected frame, %p.\n", ret); 11172 11173 root.Name = n1; 11174 ret = D3DXFrameFind(&root, NULL); 11175 ok(ret == NULL, "Unexpected frame, %p.\n", ret); 11176 11177 ret = D3DXFrameFind(&root, n1); 11178 ok(ret == &root, "Unexpected frame, %p.\n", ret); 11179 11180 ret = D3DXFrameFind(&root, N1); 11181 ok(ret == NULL, "Unexpected frame, %p.\n", ret); 11182 11183 /* Test siblings order traversal. */ 11184 memset(&sibling, 0, sizeof(sibling)); 11185 sibling.Name = n2; 11186 root.pFrameSibling = &sibling; 11187 ret = D3DXFrameFind(&root, n2); 11188 ok(ret == &sibling, "Unexpected frame, %p.\n", ret); 11189 11190 memset(&sibling2, 0, sizeof(sibling2)); 11191 sibling2.Name = n2; 11192 sibling.pFrameSibling = &sibling2; 11193 ret = D3DXFrameFind(&root, n2); 11194 ok(ret == &sibling, "Unexpected frame, %p.\n", ret); 11195 11196 sibling2.Name = n3; 11197 ret = D3DXFrameFind(&root, n3); 11198 ok(ret == &sibling2, "Unexpected frame, %p.\n", ret); 11199 11200 /* Siblings first. */ 11201 memset(&child, 0, sizeof(child)); 11202 child.Name = n2; 11203 root.pFrameFirstChild = &child; 11204 ret = D3DXFrameFind(&root, n2); 11205 ok(ret == &sibling, "Unexpected frame, %p.\n", ret); 11206 11207 child.Name = n4; 11208 ret = D3DXFrameFind(&root, n4); 11209 ok(ret == &child, "Unexpected frame, %p.\n", ret); 11210 11211 /* Link a grandchild and another one for sibling. */ 11212 memset(&child2, 0, sizeof(child2)); 11213 memset(&child3, 0, sizeof(child3)); 11214 child2.Name = child3.Name = n5; 11215 sibling.pFrameFirstChild = &child2; 11216 child.pFrameFirstChild = &child3; 11217 ret = D3DXFrameFind(&root, n5); 11218 ok(ret == &child2, "Unexpected frame, %p.\n", ret); 11219 11220 child3.Name = n6; 11221 ret = D3DXFrameFind(&root, n6); 11222 ok(ret == &child3, "Unexpected frame, %p.\n", ret); 11223 } 11224 11225 START_TEST(mesh) 11226 { 11227 D3DXBoundProbeTest(); 11228 D3DXComputeBoundingBoxTest(); 11229 D3DXComputeBoundingSphereTest(); 11230 D3DXGetFVFVertexSizeTest(); 11231 D3DXIntersectTriTest(); 11232 D3DXCreateMeshTest(); 11233 D3DXCreateMeshFVFTest(); 11234 D3DXLoadMeshTest(); 11235 D3DXCreateBoxTest(); 11236 D3DXCreatePolygonTest(); 11237 D3DXCreateSphereTest(); 11238 D3DXCreateCylinderTest(); 11239 D3DXCreateTextTest(); 11240 D3DXCreateTorusTest(); 11241 D3DXCreateAnimationControllerTest(); 11242 test_get_decl_length(); 11243 test_get_decl_vertex_size(); 11244 test_fvf_decl_conversion(); 11245 D3DXGenerateAdjacencyTest(); 11246 test_update_semantics(); 11247 test_create_skin_info(); 11248 test_convert_adjacency_to_point_reps(); 11249 test_convert_point_reps_to_adjacency(); 11250 test_weld_vertices(); 11251 test_clone_mesh(); 11252 test_valid_mesh(); 11253 test_optimize_faces(); 11254 test_compute_normals(); 11255 test_D3DXFrameFind(); 11256 } 11257