1 /* 2 * Copyright 2008 David Adam 3 * Copyright 2008 Luis Busquets 4 * Copyright 2009 Henri Verbeet for CodeWeavers 5 * Copyright 2011 Michael Mc Donnell 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 20 */ 21 22 #define COBJMACROS 23 #include <stdio.h> 24 #include <float.h> 25 #include <limits.h> 26 #include "wine/test.h" 27 #include "d3dx9.h" 28 #include "initguid.h" 29 #include "rmxftmpl.h" 30 #include "rmxfguid.h" 31 32 #ifndef NAN 33 /* From wine/port.h */ 34 static inline float __port_nan(void) 35 { 36 static const unsigned __nan_bytes = 0x7fc00000; 37 return *(const float *)&__nan_bytes; 38 } 39 #define NAN __port_nan() 40 #endif 41 42 /* Set the WINETEST_DEBUG environment variable to be greater than 1 for verbose 43 * function call traces of ID3DXAllocateHierarchy callbacks. */ 44 #define TRACECALLBACK if(winetest_debug > 1) trace 45 46 #define admitted_error 0.0001f 47 48 #define compare_vertex_sizes(type, exp) \ 49 got=D3DXGetFVFVertexSize(type); \ 50 ok(got==exp, "Expected: %d, Got: %d\n", exp, got); 51 52 #define compare_float(got, exp) \ 53 do { \ 54 float _got = (got); \ 55 float _exp = (exp); \ 56 ok(_got == _exp, "Expected: %g, Got: %g\n", _exp, _got); \ 57 } while (0) 58 59 static BOOL compare(FLOAT u, FLOAT v) 60 { 61 return (fabs(u-v) < admitted_error); 62 } 63 64 static BOOL compare_vec3(D3DXVECTOR3 u, D3DXVECTOR3 v) 65 { 66 return ( compare(u.x, v.x) && compare(u.y, v.y) && compare(u.z, v.z) ); 67 } 68 69 static BOOL compare_vec4(D3DXVECTOR4 u, D3DXVECTOR4 v) 70 { 71 return compare(u.x, v.x) && compare(u.y, v.y) && compare(u.z, v.z) && compare(u.w, v.w); 72 } 73 74 #define check_floats(got, exp, dim) check_floats_(__LINE__, "", got, exp, dim) 75 static void check_floats_(int line, const char *prefix, const float *got, const float *exp, int dim) 76 { 77 int i; 78 char exp_buffer[256] = ""; 79 char got_buffer[256] = ""; 80 char *exp_buffer_ptr = exp_buffer; 81 char *got_buffer_ptr = got_buffer; 82 BOOL equal = TRUE; 83 84 for (i = 0; i < dim; i++) { 85 if (i) { 86 exp_buffer_ptr += sprintf(exp_buffer_ptr, ", "); 87 got_buffer_ptr += sprintf(got_buffer_ptr, ", "); 88 } 89 equal = equal && compare(*exp, *got); 90 exp_buffer_ptr += sprintf(exp_buffer_ptr, "%g", *exp); 91 got_buffer_ptr += sprintf(got_buffer_ptr, "%g", *got); 92 exp++; got++; 93 } 94 ok_(__FILE__,line)(equal, "%sExpected (%s), got (%s)", prefix, exp_buffer, got_buffer); 95 } 96 97 struct vertex 98 { 99 D3DXVECTOR3 position; 100 D3DXVECTOR3 normal; 101 }; 102 103 typedef WORD face[3]; 104 105 static BOOL compare_face(face a, face b) 106 { 107 return (a[0]==b[0] && a[1] == b[1] && a[2] == b[2]); 108 } 109 110 struct test_context 111 { 112 HWND hwnd; 113 IDirect3D9 *d3d; 114 IDirect3DDevice9 *device; 115 }; 116 117 /* Initializes a test context struct. Use it to initialize DirectX. 118 * 119 * Returns NULL if an error occurred. 120 */ 121 static struct test_context *new_test_context(void) 122 { 123 HRESULT hr; 124 HWND hwnd = NULL; 125 IDirect3D9 *d3d = NULL; 126 IDirect3DDevice9 *device = NULL; 127 D3DPRESENT_PARAMETERS d3dpp = {0}; 128 struct test_context *test_context; 129 130 if (!(hwnd = CreateWindowA("static", "d3dx9_test", WS_OVERLAPPEDWINDOW, 0, 0, 131 640, 480, NULL, NULL, NULL, NULL))) 132 { 133 skip("Couldn't create application window\n"); 134 goto error; 135 } 136 137 d3d = Direct3DCreate9(D3D_SDK_VERSION); 138 if (!d3d) 139 { 140 skip("Couldn't create IDirect3D9 object\n"); 141 goto error; 142 } 143 144 memset(&d3dpp, 0, sizeof(d3dpp)); 145 d3dpp.Windowed = TRUE; 146 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; 147 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd, 148 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device); 149 if (FAILED(hr)) 150 { 151 skip("Couldn't create IDirect3DDevice9 object %#x\n", hr); 152 goto error; 153 } 154 155 test_context = HeapAlloc(GetProcessHeap(), 0, sizeof(*test_context)); 156 if (!test_context) 157 { 158 skip("Couldn't allocate memory for test_context\n"); 159 goto error; 160 } 161 test_context->hwnd = hwnd; 162 test_context->d3d = d3d; 163 test_context->device = device; 164 165 return test_context; 166 167 error: 168 if (device) 169 IDirect3DDevice9_Release(device); 170 171 if (d3d) 172 IDirect3D9_Release(d3d); 173 174 if (hwnd) 175 DestroyWindow(hwnd); 176 177 return NULL; 178 } 179 180 static void free_test_context(struct test_context *test_context) 181 { 182 if (!test_context) 183 return; 184 185 if (test_context->device) 186 IDirect3DDevice9_Release(test_context->device); 187 188 if (test_context->d3d) 189 IDirect3D9_Release(test_context->d3d); 190 191 if (test_context->hwnd) 192 DestroyWindow(test_context->hwnd); 193 194 HeapFree(GetProcessHeap(), 0, test_context); 195 } 196 197 struct mesh 198 { 199 DWORD number_of_vertices; 200 struct vertex *vertices; 201 202 DWORD number_of_faces; 203 face *faces; 204 205 DWORD fvf; 206 UINT vertex_size; 207 }; 208 209 static void free_mesh(struct mesh *mesh) 210 { 211 HeapFree(GetProcessHeap(), 0, mesh->faces); 212 HeapFree(GetProcessHeap(), 0, mesh->vertices); 213 } 214 215 static BOOL new_mesh(struct mesh *mesh, DWORD number_of_vertices, DWORD number_of_faces) 216 { 217 mesh->vertices = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, number_of_vertices * sizeof(*mesh->vertices)); 218 if (!mesh->vertices) 219 { 220 return FALSE; 221 } 222 mesh->number_of_vertices = number_of_vertices; 223 224 mesh->faces = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, number_of_faces * sizeof(*mesh->faces)); 225 if (!mesh->faces) 226 { 227 HeapFree(GetProcessHeap(), 0, mesh->vertices); 228 return FALSE; 229 } 230 mesh->number_of_faces = number_of_faces; 231 232 return TRUE; 233 } 234 235 static void compare_mesh(const char *name, ID3DXMesh *d3dxmesh, struct mesh *mesh) 236 { 237 HRESULT hr; 238 DWORD number_of_vertices, number_of_faces; 239 IDirect3DVertexBuffer9 *vertex_buffer; 240 IDirect3DIndexBuffer9 *index_buffer; 241 D3DVERTEXBUFFER_DESC vertex_buffer_description; 242 D3DINDEXBUFFER_DESC index_buffer_description; 243 struct vertex *vertices; 244 face *faces; 245 int expected, i; 246 247 number_of_vertices = d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh); 248 ok(number_of_vertices == mesh->number_of_vertices, "Test %s, result %u, expected %d\n", 249 name, number_of_vertices, mesh->number_of_vertices); 250 251 number_of_faces = d3dxmesh->lpVtbl->GetNumFaces(d3dxmesh); 252 ok(number_of_faces == mesh->number_of_faces, "Test %s, result %u, expected %d\n", 253 name, number_of_faces, mesh->number_of_faces); 254 255 /* vertex buffer */ 256 hr = d3dxmesh->lpVtbl->GetVertexBuffer(d3dxmesh, &vertex_buffer); 257 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr); 258 259 if (hr != D3D_OK) 260 { 261 skip("Couldn't get vertex buffer\n"); 262 } 263 else 264 { 265 hr = IDirect3DVertexBuffer9_GetDesc(vertex_buffer, &vertex_buffer_description); 266 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr); 267 268 if (hr != D3D_OK) 269 { 270 skip("Couldn't get vertex buffer description\n"); 271 } 272 else 273 { 274 ok(vertex_buffer_description.Format == D3DFMT_VERTEXDATA, "Test %s, result %x, expected %x (D3DFMT_VERTEXDATA)\n", 275 name, vertex_buffer_description.Format, D3DFMT_VERTEXDATA); 276 ok(vertex_buffer_description.Type == D3DRTYPE_VERTEXBUFFER, "Test %s, result %x, expected %x (D3DRTYPE_VERTEXBUFFER)\n", 277 name, vertex_buffer_description.Type, D3DRTYPE_VERTEXBUFFER); 278 ok(vertex_buffer_description.Usage == 0, "Test %s, result %x, expected %x\n", name, vertex_buffer_description.Usage, 0); 279 ok(vertex_buffer_description.Pool == D3DPOOL_MANAGED, "Test %s, result %x, expected %x (D3DPOOL_MANAGED)\n", 280 name, vertex_buffer_description.Pool, D3DPOOL_MANAGED); 281 ok(vertex_buffer_description.FVF == mesh->fvf, "Test %s, result %x, expected %x\n", 282 name, vertex_buffer_description.FVF, mesh->fvf); 283 if (mesh->fvf == 0) 284 { 285 expected = number_of_vertices * mesh->vertex_size; 286 } 287 else 288 { 289 expected = number_of_vertices * D3DXGetFVFVertexSize(mesh->fvf); 290 } 291 ok(vertex_buffer_description.Size == expected, "Test %s, result %x, expected %x\n", 292 name, vertex_buffer_description.Size, expected); 293 } 294 295 /* specify offset and size to avoid potential overruns */ 296 hr = IDirect3DVertexBuffer9_Lock(vertex_buffer, 0, number_of_vertices * sizeof(D3DXVECTOR3) * 2, 297 (void **)&vertices, D3DLOCK_DISCARD); 298 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr); 299 300 if (hr != D3D_OK) 301 { 302 skip("Couldn't lock vertex buffer\n"); 303 } 304 else 305 { 306 for (i = 0; i < number_of_vertices; i++) 307 { 308 ok(compare_vec3(vertices[i].position, mesh->vertices[i].position), 309 "Test %s, vertex position %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, 310 vertices[i].position.x, vertices[i].position.y, vertices[i].position.z, 311 mesh->vertices[i].position.x, mesh->vertices[i].position.y, mesh->vertices[i].position.z); 312 ok(compare_vec3(vertices[i].normal, mesh->vertices[i].normal), 313 "Test %s, vertex normal %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, 314 vertices[i].normal.x, vertices[i].normal.y, vertices[i].normal.z, 315 mesh->vertices[i].normal.x, mesh->vertices[i].normal.y, mesh->vertices[i].normal.z); 316 } 317 318 IDirect3DVertexBuffer9_Unlock(vertex_buffer); 319 } 320 321 IDirect3DVertexBuffer9_Release(vertex_buffer); 322 } 323 324 /* index buffer */ 325 hr = d3dxmesh->lpVtbl->GetIndexBuffer(d3dxmesh, &index_buffer); 326 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr); 327 328 if (!index_buffer) 329 { 330 skip("Couldn't get index buffer\n"); 331 } 332 else 333 { 334 hr = IDirect3DIndexBuffer9_GetDesc(index_buffer, &index_buffer_description); 335 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr); 336 337 if (hr != D3D_OK) 338 { 339 skip("Couldn't get index buffer description\n"); 340 } 341 else 342 { 343 ok(index_buffer_description.Format == D3DFMT_INDEX16, "Test %s, result %x, expected %x (D3DFMT_INDEX16)\n", 344 name, index_buffer_description.Format, D3DFMT_INDEX16); 345 ok(index_buffer_description.Type == D3DRTYPE_INDEXBUFFER, "Test %s, result %x, expected %x (D3DRTYPE_INDEXBUFFER)\n", 346 name, index_buffer_description.Type, D3DRTYPE_INDEXBUFFER); 347 ok(index_buffer_description.Usage == 0, "Test %s, result %#x, expected %#x.\n", 348 name, index_buffer_description.Usage, 0); 349 ok(index_buffer_description.Pool == D3DPOOL_MANAGED, "Test %s, result %x, expected %x (D3DPOOL_MANAGED)\n", 350 name, index_buffer_description.Pool, D3DPOOL_MANAGED); 351 expected = number_of_faces * sizeof(WORD) * 3; 352 ok(index_buffer_description.Size == expected, "Test %s, result %x, expected %x\n", 353 name, index_buffer_description.Size, expected); 354 } 355 356 /* specify offset and size to avoid potential overruns */ 357 hr = IDirect3DIndexBuffer9_Lock(index_buffer, 0, number_of_faces * sizeof(WORD) * 3, 358 (void **)&faces, D3DLOCK_DISCARD); 359 ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr); 360 361 if (hr != D3D_OK) 362 { 363 skip("Couldn't lock index buffer\n"); 364 } 365 else 366 { 367 for (i = 0; i < number_of_faces; i++) 368 { 369 ok(compare_face(faces[i], mesh->faces[i]), 370 "Test %s, face %d, result (%u, %u, %u), expected (%u, %u, %u)\n", name, i, 371 faces[i][0], faces[i][1], faces[i][2], 372 mesh->faces[i][0], mesh->faces[i][1], mesh->faces[i][2]); 373 } 374 375 IDirect3DIndexBuffer9_Unlock(index_buffer); 376 } 377 378 IDirect3DIndexBuffer9_Release(index_buffer); 379 } 380 } 381 382 static void D3DXBoundProbeTest(void) 383 { 384 BOOL result; 385 D3DXVECTOR3 bottom_point, center, top_point, raydirection, rayposition; 386 FLOAT radius; 387 388 /*____________Test the Box case___________________________*/ 389 bottom_point.x = -3.0f; bottom_point.y = -2.0f; bottom_point.z = -1.0f; 390 top_point.x = 7.0f; top_point.y = 8.0f; top_point.z = 9.0f; 391 392 raydirection.x = -4.0f; raydirection.y = -5.0f; raydirection.z = -6.0f; 393 rayposition.x = 5.0f; rayposition.y = 5.0f; rayposition.z = 11.0f; 394 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection); 395 ok(result == TRUE, "expected TRUE, received FALSE\n"); 396 397 raydirection.x = 4.0f; raydirection.y = 5.0f; raydirection.z = 6.0f; 398 rayposition.x = 5.0f; rayposition.y = 5.0f; rayposition.z = 11.0f; 399 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection); 400 ok(result == FALSE, "expected FALSE, received TRUE\n"); 401 402 rayposition.x = -4.0f; rayposition.y = 1.0f; rayposition.z = -2.0f; 403 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection); 404 ok(result == TRUE, "expected TRUE, received FALSE\n"); 405 406 bottom_point.x = 1.0f; bottom_point.y = 0.0f; bottom_point.z = 0.0f; 407 top_point.x = 1.0f; top_point.y = 0.0f; top_point.z = 0.0f; 408 rayposition.x = 0.0f; rayposition.y = 1.0f; rayposition.z = 0.0f; 409 raydirection.x = 0.0f; raydirection.y = 3.0f; raydirection.z = 0.0f; 410 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection); 411 ok(result == FALSE, "expected FALSE, received TRUE\n"); 412 413 bottom_point.x = 1.0f; bottom_point.y = 2.0f; bottom_point.z = 3.0f; 414 top_point.x = 10.0f; top_point.y = 15.0f; top_point.z = 20.0f; 415 416 raydirection.x = 7.0f; raydirection.y = 8.0f; raydirection.z = 9.0f; 417 rayposition.x = 3.0f; rayposition.y = 7.0f; rayposition.z = -6.0f; 418 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection); 419 ok(result == TRUE, "expected TRUE, received FALSE\n"); 420 421 bottom_point.x = 0.0f; bottom_point.y = 0.0f; bottom_point.z = 0.0f; 422 top_point.x = 1.0f; top_point.y = 1.0f; top_point.z = 1.0f; 423 424 raydirection.x = 0.0f; raydirection.y = 1.0f; raydirection.z = .0f; 425 rayposition.x = -3.0f; rayposition.y = 0.0f; rayposition.z = 0.0f; 426 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection); 427 ok(result == FALSE, "expected FALSE, received TRUE\n"); 428 429 raydirection.x = 1.0f; raydirection.y = 0.0f; raydirection.z = .0f; 430 rayposition.x = -3.0f; rayposition.y = 0.0f; rayposition.z = 0.0f; 431 result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection); 432 ok(result == TRUE, "expected TRUE, received FALSE\n"); 433 434 /*____________Test the Sphere case________________________*/ 435 radius = sqrt(77.0f); 436 center.x = 1.0f; center.y = 2.0f; center.z = 3.0f; 437 raydirection.x = 2.0f; raydirection.y = -4.0f; raydirection.z = 2.0f; 438 439 rayposition.x = 5.0f; rayposition.y = 5.0f; rayposition.z = 9.0f; 440 result = D3DXSphereBoundProbe(¢er, radius, &rayposition, &raydirection); 441 ok(result == TRUE, "expected TRUE, received FALSE\n"); 442 443 rayposition.x = 45.0f; rayposition.y = -75.0f; rayposition.z = 49.0f; 444 result = D3DXSphereBoundProbe(¢er, radius, &rayposition, &raydirection); 445 ok(result == FALSE, "expected FALSE, received TRUE\n"); 446 447 rayposition.x = 5.0f; rayposition.y = 11.0f; rayposition.z = 9.0f; 448 result = D3DXSphereBoundProbe(¢er, radius, &rayposition, &raydirection); 449 ok(result == FALSE, "expected FALSE, received TRUE\n"); 450 } 451 452 static void D3DXComputeBoundingBoxTest(void) 453 { 454 D3DXVECTOR3 exp_max, exp_min, got_max, got_min, vertex[5]; 455 HRESULT hr; 456 457 vertex[0].x = 1.0f; vertex[0].y = 1.0f; vertex[0].z = 1.0f; 458 vertex[1].x = 1.0f; vertex[1].y = 1.0f; vertex[1].z = 1.0f; 459 vertex[2].x = 1.0f; vertex[2].y = 1.0f; vertex[2].z = 1.0f; 460 vertex[3].x = 1.0f; vertex[3].y = 1.0f; vertex[3].z = 1.0f; 461 vertex[4].x = 9.0f; vertex[4].y = 9.0f; vertex[4].z = 9.0f; 462 463 exp_min.x = 1.0f; exp_min.y = 1.0f; exp_min.z = 1.0f; 464 exp_max.x = 9.0f; exp_max.y = 9.0f; exp_max.z = 9.0f; 465 466 hr = D3DXComputeBoundingBox(&vertex[3],2,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_min,&got_max); 467 468 ok( hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 469 ok( compare_vec3(exp_min,got_min), "Expected min: (%f, %f, %f), got: (%f, %f, %f)\n", exp_min.x,exp_min.y,exp_min.z,got_min.x,got_min.y,got_min.z); 470 ok( compare_vec3(exp_max,got_max), "Expected max: (%f, %f, %f), got: (%f, %f, %f)\n", exp_max.x,exp_max.y,exp_max.z,got_max.x,got_max.y,got_max.z); 471 472 /*________________________*/ 473 474 vertex[0].x = 2.0f; vertex[0].y = 5.9f; vertex[0].z = -1.2f; 475 vertex[1].x = -1.87f; vertex[1].y = 7.9f; vertex[1].z = 7.4f; 476 vertex[2].x = 7.43f; vertex[2].y = -0.9f; vertex[2].z = 11.9f; 477 vertex[3].x = -6.92f; vertex[3].y = 6.3f; vertex[3].z = -3.8f; 478 vertex[4].x = 11.4f; vertex[4].y = -8.1f; vertex[4].z = 4.5f; 479 480 exp_min.x = -6.92f; exp_min.y = -8.1f; exp_min.z = -3.80f; 481 exp_max.x = 11.4f; exp_max.y = 7.90f; exp_max.z = 11.9f; 482 483 hr = D3DXComputeBoundingBox(&vertex[0],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_min,&got_max); 484 485 ok( hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 486 ok( compare_vec3(exp_min,got_min), "Expected min: (%f, %f, %f), got: (%f, %f, %f)\n", exp_min.x,exp_min.y,exp_min.z,got_min.x,got_min.y,got_min.z); 487 ok( compare_vec3(exp_max,got_max), "Expected max: (%f, %f, %f), got: (%f, %f, %f)\n", exp_max.x,exp_max.y,exp_max.z,got_max.x,got_max.y,got_max.z); 488 489 /*________________________*/ 490 491 vertex[0].x = 2.0f; vertex[0].y = 5.9f; vertex[0].z = -1.2f; 492 vertex[1].x = -1.87f; vertex[1].y = 7.9f; vertex[1].z = 7.4f; 493 vertex[2].x = 7.43f; vertex[2].y = -0.9f; vertex[2].z = 11.9f; 494 vertex[3].x = -6.92f; vertex[3].y = 6.3f; vertex[3].z = -3.8f; 495 vertex[4].x = 11.4f; vertex[4].y = -8.1f; vertex[4].z = 4.5f; 496 497 exp_min.x = -6.92f; exp_min.y = -0.9f; exp_min.z = -3.8f; 498 exp_max.x = 7.43f; exp_max.y = 7.90f; exp_max.z = 11.9f; 499 500 hr = D3DXComputeBoundingBox(&vertex[0],4,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_min,&got_max); 501 502 ok( hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 503 ok( compare_vec3(exp_min,got_min), "Expected min: (%f, %f, %f), got: (%f, %f, %f)\n", exp_min.x,exp_min.y,exp_min.z,got_min.x,got_min.y,got_min.z); 504 ok( compare_vec3(exp_max,got_max), "Expected max: (%f, %f, %f), got: (%f, %f, %f)\n", exp_max.x,exp_max.y,exp_max.z,got_max.x,got_max.y,got_max.z); 505 506 /*________________________*/ 507 hr = D3DXComputeBoundingBox(NULL,5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_min,&got_max); 508 ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 509 510 /*________________________*/ 511 hr = D3DXComputeBoundingBox(&vertex[3],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),NULL,&got_max); 512 ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 513 514 /*________________________*/ 515 hr = D3DXComputeBoundingBox(&vertex[3],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_min,NULL); 516 ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 517 } 518 519 static void D3DXComputeBoundingSphereTest(void) 520 { 521 D3DXVECTOR3 exp_cen, got_cen, vertex[5]; 522 FLOAT exp_rad, got_rad; 523 HRESULT hr; 524 525 vertex[0].x = 1.0f; vertex[0].y = 1.0f; vertex[0].z = 1.0f; 526 vertex[1].x = 1.0f; vertex[1].y = 1.0f; vertex[1].z = 1.0f; 527 vertex[2].x = 1.0f; vertex[2].y = 1.0f; vertex[2].z = 1.0f; 528 vertex[3].x = 1.0f; vertex[3].y = 1.0f; vertex[3].z = 1.0f; 529 vertex[4].x = 9.0f; vertex[4].y = 9.0f; vertex[4].z = 9.0f; 530 531 exp_rad = 6.928203f; 532 exp_cen.x = 5.0; exp_cen.y = 5.0; exp_cen.z = 5.0; 533 534 hr = D3DXComputeBoundingSphere(&vertex[3],2,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_cen,&got_rad); 535 536 ok( hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 537 ok( compare(exp_rad, got_rad), "Expected radius: %f, got radius: %f\n", exp_rad, got_rad); 538 ok( compare_vec3(exp_cen,got_cen), "Expected center: (%f, %f, %f), got center: (%f, %f, %f)\n", exp_cen.x,exp_cen.y,exp_cen.z,got_cen.x,got_cen.y,got_cen.z); 539 540 /*________________________*/ 541 542 vertex[0].x = 2.0f; vertex[0].y = 5.9f; vertex[0].z = -1.2f; 543 vertex[1].x = -1.87f; vertex[1].y = 7.9f; vertex[1].z = 7.4f; 544 vertex[2].x = 7.43f; vertex[2].y = -0.9f; vertex[2].z = 11.9f; 545 vertex[3].x = -6.92f; vertex[3].y = 6.3f; vertex[3].z = -3.8f; 546 vertex[4].x = 11.4f; vertex[4].y = -8.1f; vertex[4].z = 4.5f; 547 548 exp_rad = 13.707883f; 549 exp_cen.x = 2.408f; exp_cen.y = 2.22f; exp_cen.z = 3.76f; 550 551 hr = D3DXComputeBoundingSphere(&vertex[0],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_cen,&got_rad); 552 553 ok( hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 554 ok( compare(exp_rad, got_rad), "Expected radius: %f, got radius: %f\n", exp_rad, got_rad); 555 ok( compare_vec3(exp_cen,got_cen), "Expected center: (%f, %f, %f), got center: (%f, %f, %f)\n", exp_cen.x,exp_cen.y,exp_cen.z,got_cen.x,got_cen.y,got_cen.z); 556 557 /*________________________*/ 558 hr = D3DXComputeBoundingSphere(NULL,5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_cen,&got_rad); 559 ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 560 561 /*________________________*/ 562 hr = D3DXComputeBoundingSphere(&vertex[3],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),NULL,&got_rad); 563 ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 564 565 /*________________________*/ 566 hr = D3DXComputeBoundingSphere(&vertex[3],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_cen,NULL); 567 ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 568 } 569 570 static void print_elements(const D3DVERTEXELEMENT9 *elements) 571 { 572 D3DVERTEXELEMENT9 last = D3DDECL_END(); 573 const D3DVERTEXELEMENT9 *ptr = elements; 574 int count = 0; 575 576 while (memcmp(ptr, &last, sizeof(D3DVERTEXELEMENT9))) 577 { 578 trace( 579 "[Element %d] Stream = %d, Offset = %d, Type = %d, Method = %d, Usage = %d, UsageIndex = %d\n", 580 count, ptr->Stream, ptr->Offset, ptr->Type, ptr->Method, ptr->Usage, ptr->UsageIndex); 581 ptr++; 582 count++; 583 } 584 } 585 586 static void compare_elements(const D3DVERTEXELEMENT9 *elements, const D3DVERTEXELEMENT9 *expected_elements, 587 unsigned int line, unsigned int test_id) 588 { 589 D3DVERTEXELEMENT9 last = D3DDECL_END(); 590 unsigned int i; 591 592 for (i = 0; i < MAX_FVF_DECL_SIZE; i++) 593 { 594 int end1 = memcmp(&elements[i], &last, sizeof(last)); 595 int end2 = memcmp(&expected_elements[i], &last, sizeof(last)); 596 int status; 597 598 if (!end1 && !end2) break; 599 600 status = !end1 ^ !end2; 601 ok(!status, "Line %u, test %u: Mismatch in size, test declaration is %s than expected.\n", 602 line, test_id, end1 ? "shorter" : "longer"); 603 if (status) 604 { 605 print_elements(elements); 606 break; 607 } 608 609 status = memcmp(&elements[i], &expected_elements[i], sizeof(D3DVERTEXELEMENT9)); 610 ok(!status, "Line %u, test %u: Mismatch in element %u.\n", line, test_id, i); 611 if (status) 612 { 613 print_elements(elements); 614 break; 615 } 616 } 617 } 618 619 static void test_fvf_to_decl(DWORD test_fvf, const D3DVERTEXELEMENT9 expected_elements[], 620 HRESULT expected_hr, unsigned int line, unsigned int test_id) 621 { 622 HRESULT hr; 623 D3DVERTEXELEMENT9 decl[MAX_FVF_DECL_SIZE]; 624 625 hr = D3DXDeclaratorFromFVF(test_fvf, decl); 626 ok(hr == expected_hr, 627 "Line %u, test %u: D3DXDeclaratorFromFVF returned %#x, expected %#x.\n", 628 line, test_id, hr, expected_hr); 629 if (SUCCEEDED(hr)) compare_elements(decl, expected_elements, line, test_id); 630 } 631 632 static void test_decl_to_fvf(const D3DVERTEXELEMENT9 *decl, DWORD expected_fvf, 633 HRESULT expected_hr, unsigned int line, unsigned int test_id) 634 { 635 HRESULT hr; 636 DWORD result_fvf = 0xdeadbeef; 637 638 hr = D3DXFVFFromDeclarator(decl, &result_fvf); 639 ok(hr == expected_hr, 640 "Line %u, test %u: D3DXFVFFromDeclarator returned %#x, expected %#x.\n", 641 line, test_id, hr, expected_hr); 642 if (SUCCEEDED(hr)) 643 { 644 ok(expected_fvf == result_fvf, "Line %u, test %u: Got FVF %#x, expected %#x.\n", 645 line, test_id, result_fvf, expected_fvf); 646 } 647 } 648 649 static void test_fvf_decl_conversion(void) 650 { 651 static const struct 652 { 653 D3DVERTEXELEMENT9 decl[MAXD3DDECLLENGTH + 1]; 654 DWORD fvf; 655 } 656 test_data[] = 657 { 658 {{ 659 D3DDECL_END(), 660 }, 0}, 661 {{ 662 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 663 D3DDECL_END(), 664 }, D3DFVF_XYZ}, 665 {{ 666 {0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITIONT, 0}, 667 D3DDECL_END(), 668 }, D3DFVF_XYZRHW}, 669 {{ 670 {0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITIONT, 0}, 671 D3DDECL_END(), 672 }, D3DFVF_XYZRHW}, 673 {{ 674 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 675 {0, 12, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, 676 D3DDECL_END(), 677 }, D3DFVF_XYZB1}, 678 {{ 679 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 680 {0, 12, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0}, 681 D3DDECL_END(), 682 }, D3DFVF_XYZB1 | D3DFVF_LASTBETA_UBYTE4}, 683 {{ 684 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 685 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0}, 686 D3DDECL_END(), 687 }, D3DFVF_XYZB1 | D3DFVF_LASTBETA_D3DCOLOR}, 688 {{ 689 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 690 {0, 12, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, 691 D3DDECL_END(), 692 }, D3DFVF_XYZB2}, 693 {{ 694 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 695 {0, 12, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, 696 {0, 16, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0}, 697 D3DDECL_END(), 698 }, D3DFVF_XYZB2 | D3DFVF_LASTBETA_UBYTE4}, 699 {{ 700 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 701 {0, 12, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, 702 {0, 16, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0}, 703 D3DDECL_END(), 704 }, D3DFVF_XYZB2 | D3DFVF_LASTBETA_D3DCOLOR}, 705 {{ 706 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 707 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, 708 D3DDECL_END(), 709 }, D3DFVF_XYZB3}, 710 {{ 711 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 712 {0, 12, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, 713 {0, 20, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0}, 714 D3DDECL_END(), 715 }, D3DFVF_XYZB3 | D3DFVF_LASTBETA_UBYTE4}, 716 {{ 717 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 718 {0, 12, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, 719 {0, 20, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0}, 720 D3DDECL_END(), 721 }, D3DFVF_XYZB3 | D3DFVF_LASTBETA_D3DCOLOR}, 722 {{ 723 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 724 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, 725 D3DDECL_END(), 726 }, D3DFVF_XYZB4}, 727 {{ 728 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 729 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, 730 {0, 24, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0}, 731 D3DDECL_END(), 732 }, D3DFVF_XYZB4 | D3DFVF_LASTBETA_UBYTE4}, 733 {{ 734 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 735 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, 736 {0, 24, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0}, 737 D3DDECL_END(), 738 }, D3DFVF_XYZB4 | D3DFVF_LASTBETA_D3DCOLOR}, 739 {{ 740 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 741 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, 742 {0, 28, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0}, 743 D3DDECL_END(), 744 }, D3DFVF_XYZB5 | D3DFVF_LASTBETA_UBYTE4}, 745 {{ 746 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 747 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, 748 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0}, 749 D3DDECL_END(), 750 }, D3DFVF_XYZB5 | D3DFVF_LASTBETA_D3DCOLOR}, 751 {{ 752 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0}, 753 D3DDECL_END(), 754 }, D3DFVF_NORMAL}, 755 {{ 756 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0}, 757 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0}, 758 D3DDECL_END(), 759 }, D3DFVF_NORMAL | D3DFVF_DIFFUSE}, 760 {{ 761 {0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_PSIZE, 0}, 762 D3DDECL_END(), 763 }, D3DFVF_PSIZE}, 764 {{ 765 {0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0}, 766 D3DDECL_END(), 767 }, D3DFVF_DIFFUSE}, 768 {{ 769 {0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1}, 770 D3DDECL_END(), 771 }, D3DFVF_SPECULAR}, 772 /* Make sure textures of different sizes work. */ 773 {{ 774 {0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0}, 775 D3DDECL_END(), 776 }, D3DFVF_TEXCOORDSIZE1(0) | D3DFVF_TEX1}, 777 {{ 778 {0, 0, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 0}, 779 D3DDECL_END(), 780 }, D3DFVF_TEXCOORDSIZE2(0) | D3DFVF_TEX1}, 781 {{ 782 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 0}, 783 D3DDECL_END(), 784 }, D3DFVF_TEXCOORDSIZE3(0) | D3DFVF_TEX1}, 785 {{ 786 {0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 0}, 787 D3DDECL_END(), 788 }, D3DFVF_TEXCOORDSIZE4(0) | D3DFVF_TEX1}, 789 /* Make sure the TEXCOORD index works correctly - try several textures. */ 790 {{ 791 {0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0}, 792 {0, 4, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 1}, 793 {0, 16, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 2}, 794 {0, 24, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 3}, 795 D3DDECL_END(), 796 }, D3DFVF_TEX4 | D3DFVF_TEXCOORDSIZE1(0) | D3DFVF_TEXCOORDSIZE3(1) 797 | D3DFVF_TEXCOORDSIZE2(2) | D3DFVF_TEXCOORDSIZE4(3)}, 798 /* Now try some combination tests. */ 799 {{ 800 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 801 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, 802 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0}, 803 {0, 32, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1}, 804 {0, 36, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 0}, 805 {0, 44, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 1}, 806 D3DDECL_END(), 807 }, D3DFVF_XYZB4 | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_TEX2 808 | D3DFVF_TEXCOORDSIZE2(0) | D3DFVF_TEXCOORDSIZE3(1)}, 809 {{ 810 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 811 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0}, 812 {0, 24, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_PSIZE, 0}, 813 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1}, 814 {0, 32, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0}, 815 {0, 36, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 1}, 816 D3DDECL_END(), 817 }, D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_PSIZE | D3DFVF_SPECULAR | D3DFVF_TEX2 818 | D3DFVF_TEXCOORDSIZE1(0) | D3DFVF_TEXCOORDSIZE4(1)}, 819 }; 820 unsigned int i; 821 822 for (i = 0; i < ARRAY_SIZE(test_data); ++i) 823 { 824 test_decl_to_fvf(test_data[i].decl, test_data[i].fvf, D3D_OK, __LINE__, i); 825 test_fvf_to_decl(test_data[i].fvf, test_data[i].decl, D3D_OK, __LINE__, i); 826 } 827 828 /* Usage indices for position and normal are apparently ignored. */ 829 { 830 const D3DVERTEXELEMENT9 decl[] = 831 { 832 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 1}, 833 D3DDECL_END(), 834 }; 835 test_decl_to_fvf(decl, D3DFVF_XYZ, D3D_OK, __LINE__, 0); 836 } 837 { 838 const D3DVERTEXELEMENT9 decl[] = 839 { 840 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 1}, 841 D3DDECL_END(), 842 }; 843 test_decl_to_fvf(decl, D3DFVF_NORMAL, D3D_OK, __LINE__, 0); 844 } 845 /* D3DFVF_LASTBETA_UBYTE4 and D3DFVF_LASTBETA_D3DCOLOR are ignored if 846 * there are no blend matrices. */ 847 { 848 const D3DVERTEXELEMENT9 decl[] = 849 { 850 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 851 D3DDECL_END(), 852 }; 853 test_fvf_to_decl(D3DFVF_XYZ | D3DFVF_LASTBETA_UBYTE4, decl, D3D_OK, __LINE__, 0); 854 } 855 { 856 const D3DVERTEXELEMENT9 decl[] = 857 { 858 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 859 D3DDECL_END(), 860 }; 861 test_fvf_to_decl(D3DFVF_XYZ | D3DFVF_LASTBETA_D3DCOLOR, decl, D3D_OK, __LINE__, 0); 862 } 863 /* D3DFVF_LASTBETA_UBYTE4 takes precedence over D3DFVF_LASTBETA_D3DCOLOR. */ 864 { 865 const D3DVERTEXELEMENT9 decl[] = 866 { 867 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 868 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, 869 {0, 28, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0}, 870 D3DDECL_END(), 871 }; 872 test_fvf_to_decl(D3DFVF_XYZB5 | D3DFVF_LASTBETA_D3DCOLOR | D3DFVF_LASTBETA_UBYTE4, 873 decl, D3D_OK, __LINE__, 0); 874 } 875 /* These are supposed to fail, both ways. */ 876 { 877 const D3DVERTEXELEMENT9 decl[] = 878 { 879 {0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITION, 0}, 880 D3DDECL_END(), 881 }; 882 test_decl_to_fvf(decl, D3DFVF_XYZW, D3DERR_INVALIDCALL, __LINE__, 0); 883 test_fvf_to_decl(D3DFVF_XYZW, decl, D3DERR_INVALIDCALL, __LINE__, 0); 884 } 885 { 886 const D3DVERTEXELEMENT9 decl[] = 887 { 888 {0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITION, 0}, 889 {0, 16, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0}, 890 D3DDECL_END(), 891 }; 892 test_decl_to_fvf(decl, D3DFVF_XYZW | D3DFVF_NORMAL, D3DERR_INVALIDCALL, __LINE__, 0); 893 test_fvf_to_decl(D3DFVF_XYZW | D3DFVF_NORMAL, decl, D3DERR_INVALIDCALL, __LINE__, 0); 894 } 895 { 896 const D3DVERTEXELEMENT9 decl[] = 897 { 898 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 899 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, 900 {0, 28, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDINDICES, 0}, 901 D3DDECL_END(), 902 }; 903 test_decl_to_fvf(decl, D3DFVF_XYZB5, D3DERR_INVALIDCALL, __LINE__, 0); 904 test_fvf_to_decl(D3DFVF_XYZB5, decl, D3DERR_INVALIDCALL, __LINE__, 0); 905 } 906 /* Test a declaration that can't be converted to an FVF. */ 907 { 908 const D3DVERTEXELEMENT9 decl[] = 909 { 910 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 911 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0}, 912 {0, 24, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_PSIZE, 0}, 913 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1}, 914 {0, 32, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0}, 915 /* 8 bytes padding */ 916 {0, 44, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 1}, 917 D3DDECL_END(), 918 }; 919 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0); 920 } 921 /* Elements must be ordered by offset. */ 922 { 923 const D3DVERTEXELEMENT9 decl[] = 924 { 925 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0}, 926 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 927 D3DDECL_END(), 928 }; 929 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0); 930 } 931 /* Basic tests for element order. */ 932 { 933 const D3DVERTEXELEMENT9 decl[] = 934 { 935 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 936 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0}, 937 {0, 16, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0}, 938 D3DDECL_END(), 939 }; 940 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0); 941 } 942 { 943 const D3DVERTEXELEMENT9 decl[] = 944 { 945 {0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0}, 946 {0, 4, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 947 D3DDECL_END(), 948 }; 949 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0); 950 } 951 { 952 const D3DVERTEXELEMENT9 decl[] = 953 { 954 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0}, 955 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 956 D3DDECL_END(), 957 }; 958 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0); 959 } 960 /* Textures must be ordered by texcoords. */ 961 { 962 const D3DVERTEXELEMENT9 decl[] = 963 { 964 {0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0}, 965 {0, 4, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 2}, 966 {0, 16, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 1}, 967 {0, 24, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 3}, 968 D3DDECL_END(), 969 }; 970 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0); 971 } 972 /* Duplicate elements are not allowed. */ 973 { 974 const D3DVERTEXELEMENT9 decl[] = 975 { 976 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 977 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0}, 978 {0, 16, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0}, 979 D3DDECL_END(), 980 }; 981 test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0); 982 } 983 /* Invalid FVFs cannot be converted to a declarator. */ 984 test_fvf_to_decl(0xdeadbeef, NULL, D3DERR_INVALIDCALL, __LINE__, 0); 985 } 986 987 static void D3DXGetFVFVertexSizeTest(void) 988 { 989 UINT got; 990 991 compare_vertex_sizes (D3DFVF_XYZ, 12); 992 993 compare_vertex_sizes (D3DFVF_XYZB3, 24); 994 995 compare_vertex_sizes (D3DFVF_XYZB5, 32); 996 997 compare_vertex_sizes (D3DFVF_XYZ | D3DFVF_NORMAL, 24); 998 999 compare_vertex_sizes (D3DFVF_XYZ | D3DFVF_DIFFUSE, 16); 1000 1001 compare_vertex_sizes ( 1002 D3DFVF_XYZ | 1003 D3DFVF_TEX1 | 1004 D3DFVF_TEXCOORDSIZE1(0), 16); 1005 compare_vertex_sizes ( 1006 D3DFVF_XYZ | 1007 D3DFVF_TEX2 | 1008 D3DFVF_TEXCOORDSIZE1(0) | 1009 D3DFVF_TEXCOORDSIZE1(1), 20); 1010 1011 compare_vertex_sizes ( 1012 D3DFVF_XYZ | 1013 D3DFVF_TEX1 | 1014 D3DFVF_TEXCOORDSIZE2(0), 20); 1015 1016 compare_vertex_sizes ( 1017 D3DFVF_XYZ | 1018 D3DFVF_TEX2 | 1019 D3DFVF_TEXCOORDSIZE2(0) | 1020 D3DFVF_TEXCOORDSIZE2(1), 28); 1021 1022 compare_vertex_sizes ( 1023 D3DFVF_XYZ | 1024 D3DFVF_TEX6 | 1025 D3DFVF_TEXCOORDSIZE2(0) | 1026 D3DFVF_TEXCOORDSIZE2(1) | 1027 D3DFVF_TEXCOORDSIZE2(2) | 1028 D3DFVF_TEXCOORDSIZE2(3) | 1029 D3DFVF_TEXCOORDSIZE2(4) | 1030 D3DFVF_TEXCOORDSIZE2(5), 60); 1031 1032 compare_vertex_sizes ( 1033 D3DFVF_XYZ | 1034 D3DFVF_TEX8 | 1035 D3DFVF_TEXCOORDSIZE2(0) | 1036 D3DFVF_TEXCOORDSIZE2(1) | 1037 D3DFVF_TEXCOORDSIZE2(2) | 1038 D3DFVF_TEXCOORDSIZE2(3) | 1039 D3DFVF_TEXCOORDSIZE2(4) | 1040 D3DFVF_TEXCOORDSIZE2(5) | 1041 D3DFVF_TEXCOORDSIZE2(6) | 1042 D3DFVF_TEXCOORDSIZE2(7), 76); 1043 1044 compare_vertex_sizes ( 1045 D3DFVF_XYZ | 1046 D3DFVF_TEX1 | 1047 D3DFVF_TEXCOORDSIZE3(0), 24); 1048 1049 compare_vertex_sizes ( 1050 D3DFVF_XYZ | 1051 D3DFVF_TEX4 | 1052 D3DFVF_TEXCOORDSIZE3(0) | 1053 D3DFVF_TEXCOORDSIZE3(1) | 1054 D3DFVF_TEXCOORDSIZE3(2) | 1055 D3DFVF_TEXCOORDSIZE3(3), 60); 1056 1057 compare_vertex_sizes ( 1058 D3DFVF_XYZ | 1059 D3DFVF_TEX1 | 1060 D3DFVF_TEXCOORDSIZE4(0), 28); 1061 1062 compare_vertex_sizes ( 1063 D3DFVF_XYZ | 1064 D3DFVF_TEX2 | 1065 D3DFVF_TEXCOORDSIZE4(0) | 1066 D3DFVF_TEXCOORDSIZE4(1), 44); 1067 1068 compare_vertex_sizes ( 1069 D3DFVF_XYZ | 1070 D3DFVF_TEX3 | 1071 D3DFVF_TEXCOORDSIZE4(0) | 1072 D3DFVF_TEXCOORDSIZE4(1) | 1073 D3DFVF_TEXCOORDSIZE4(2), 60); 1074 1075 compare_vertex_sizes ( 1076 D3DFVF_XYZB5 | 1077 D3DFVF_NORMAL | 1078 D3DFVF_DIFFUSE | 1079 D3DFVF_SPECULAR | 1080 D3DFVF_TEX8 | 1081 D3DFVF_TEXCOORDSIZE4(0) | 1082 D3DFVF_TEXCOORDSIZE4(1) | 1083 D3DFVF_TEXCOORDSIZE4(2) | 1084 D3DFVF_TEXCOORDSIZE4(3) | 1085 D3DFVF_TEXCOORDSIZE4(4) | 1086 D3DFVF_TEXCOORDSIZE4(5) | 1087 D3DFVF_TEXCOORDSIZE4(6) | 1088 D3DFVF_TEXCOORDSIZE4(7), 180); 1089 } 1090 1091 static void D3DXIntersectTriTest(void) 1092 { 1093 BOOL exp_res, got_res; 1094 D3DXVECTOR3 position, ray, vertex[3]; 1095 FLOAT exp_dist, got_dist, exp_u, got_u, exp_v, got_v; 1096 1097 vertex[0].x = 1.0f; vertex[0].y = 0.0f; vertex[0].z = 0.0f; 1098 vertex[1].x = 2.0f; vertex[1].y = 0.0f; vertex[1].z = 0.0f; 1099 vertex[2].x = 1.0f; vertex[2].y = 1.0f; vertex[2].z = 0.0f; 1100 1101 position.x = -14.5f; position.y = -23.75f; position.z = -32.0f; 1102 1103 ray.x = 2.0f; ray.y = 3.0f; ray.z = 4.0f; 1104 1105 exp_res = TRUE; exp_u = 0.5f; exp_v = 0.25f; exp_dist = 8.0f; 1106 1107 got_res = D3DXIntersectTri(&vertex[0], &vertex[1], &vertex[2], &position, &ray, &got_u, &got_v, &got_dist); 1108 ok(got_res == exp_res, "Expected result %d, got %d.\n", exp_res, got_res); 1109 ok(compare(exp_u, got_u), "Expected u %f, got %f.\n", exp_u, got_u); 1110 ok(compare(exp_v, got_v), "Expected v %f, got %f.\n", exp_v, got_v); 1111 ok(compare(exp_dist, got_dist), "Expected distance %f, got %f.\n", exp_dist, got_dist); 1112 1113 got_res = D3DXIntersectTri(&vertex[0], &vertex[1], &vertex[2], &position, &ray, NULL, NULL, NULL); 1114 ok(got_res == exp_res, "Expected result %d, got %d.\n", exp_res, got_res); 1115 1116 vertex[2].x = 1.0f; vertex[2].y = 0.0f; vertex[2].z = 0.0f; 1117 vertex[1].x = 2.0f; vertex[1].y = 0.0f; vertex[1].z = 0.0f; 1118 vertex[0].x = 1.0f; vertex[0].y = 1.0f; vertex[0].z = 0.0f; 1119 1120 got_u = got_v = got_dist = 0.0f; 1121 got_res = D3DXIntersectTri(&vertex[0], &vertex[1], &vertex[2], &position, &ray, &got_u, &got_v, &got_dist); 1122 ok(got_res == exp_res, "Expected result %d, got %d.\n", exp_res, got_res); 1123 ok(compare(exp_u, got_u), "Expected u %f, got %f.\n", exp_u, got_u); 1124 ok(compare(exp_v, got_v), "Expected v %f, got %f.\n", exp_v, got_v); 1125 ok(compare(exp_dist, got_dist), "Expected distance %f, got %f.\n", exp_dist, got_dist); 1126 1127 vertex[2].x = 1.0f; vertex[2].y = 0.0f; vertex[2].z = 0.0f; 1128 vertex[1].x = 2.0f; vertex[1].y = 0.0f; vertex[1].z = -0.5f; 1129 vertex[0].x = 1.0f; vertex[0].y = 1.0f; vertex[0].z = -1.0f; 1130 exp_u = 0.375f; 1131 exp_v = 0.5625f; 1132 exp_dist = 7.9375f; 1133 got_u = got_v = got_dist = 0.0f; 1134 got_res = D3DXIntersectTri(&vertex[0], &vertex[1], &vertex[2], &position, &ray, &got_u, &got_v, &got_dist); 1135 ok(got_res == exp_res, "Expected result %d, got %d.\n", exp_res, got_res); 1136 ok(compare(exp_u, got_u), "Expected u %f, got %f.\n", exp_u, got_u); 1137 ok(compare(exp_v, got_v), "Expected v %f, got %f.\n", exp_v, got_v); 1138 ok(compare(exp_dist, got_dist), "Expected distance %f, got %f.\n", exp_dist, got_dist); 1139 1140 1141 /*Only positive ray is taken in account*/ 1142 1143 vertex[0].x = 1.0f; vertex[0].y = 0.0f; vertex[0].z = 0.0f; 1144 vertex[1].x = 2.0f; vertex[1].y = 0.0f; vertex[1].z = 0.0f; 1145 vertex[2].x = 1.0f; vertex[2].y = 1.0f; vertex[2].z = 0.0f; 1146 1147 position.x = 17.5f; position.y = 24.25f; position.z = 32.0f; 1148 1149 ray.x = 2.0f; ray.y = 3.0f; ray.z = 4.0f; 1150 1151 exp_res = FALSE; 1152 1153 got_res = D3DXIntersectTri(&vertex[0],&vertex[1],&vertex[2],&position,&ray,&got_u,&got_v,&got_dist); 1154 ok( got_res == exp_res, "Expected result = %d, got %d\n",exp_res,got_res); 1155 1156 got_res = D3DXIntersectTri(&vertex[0], &vertex[1], &vertex[2], &position, &ray, NULL, NULL, NULL); 1157 ok(got_res == exp_res, "Expected result = %d, got %d\n", exp_res, got_res); 1158 1159 /*Intersection between ray and triangle in a same plane is considered as empty*/ 1160 1161 vertex[0].x = 4.0f; vertex[0].y = 0.0f; vertex[0].z = 0.0f; 1162 vertex[1].x = 6.0f; vertex[1].y = 0.0f; vertex[1].z = 0.0f; 1163 vertex[2].x = 4.0f; vertex[2].y = 2.0f; vertex[2].z = 0.0f; 1164 1165 position.x = 1.0f; position.y = 1.0f; position.z = 0.0f; 1166 1167 ray.x = 1.0f; ray.y = 0.0f; ray.z = 0.0f; 1168 1169 exp_res = FALSE; 1170 1171 got_res = D3DXIntersectTri(&vertex[0],&vertex[1],&vertex[2],&position,&ray,&got_u,&got_v,&got_dist); 1172 ok( got_res == exp_res, "Expected result = %d, got %d\n",exp_res,got_res); 1173 1174 got_res = D3DXIntersectTri(&vertex[0], &vertex[1], &vertex[2], &position, &ray, NULL, NULL, NULL); 1175 ok(got_res == exp_res, "Expected result = %d, got %d\n", exp_res, got_res); 1176 } 1177 1178 static void D3DXCreateMeshTest(void) 1179 { 1180 HRESULT hr; 1181 IDirect3DDevice9 *device, *test_device; 1182 ID3DXMesh *d3dxmesh; 1183 int i, size; 1184 D3DVERTEXELEMENT9 test_decl[MAX_FVF_DECL_SIZE]; 1185 DWORD options; 1186 struct mesh mesh; 1187 struct test_context *test_context; 1188 1189 static const D3DVERTEXELEMENT9 decl1[] = 1190 { 1191 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 1192 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 1193 D3DDECL_END(), 1194 }; 1195 1196 static const D3DVERTEXELEMENT9 decl2[] = 1197 { 1198 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 1199 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 1200 {0, 24, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_PSIZE, 0}, 1201 {0, 28, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 1}, 1202 {0, 32, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 1203 /* 8 bytes padding */ 1204 {0, 44, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1}, 1205 D3DDECL_END(), 1206 }; 1207 1208 static const D3DVERTEXELEMENT9 decl3[] = 1209 { 1210 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 1211 {1, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 1212 D3DDECL_END(), 1213 }; 1214 1215 hr = D3DXCreateMesh(0, 0, 0, NULL, NULL, NULL); 1216 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 1217 1218 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl1, NULL, &d3dxmesh); 1219 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 1220 1221 test_context = new_test_context(); 1222 if (!test_context) 1223 { 1224 skip("Couldn't create test context\n"); 1225 return; 1226 } 1227 device = test_context->device; 1228 1229 hr = D3DXCreateMesh(0, 3, D3DXMESH_MANAGED, decl1, device, &d3dxmesh); 1230 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 1231 1232 hr = D3DXCreateMesh(1, 0, D3DXMESH_MANAGED, decl1, device, &d3dxmesh); 1233 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 1234 1235 hr = D3DXCreateMesh(1, 3, 0, decl1, device, &d3dxmesh); 1236 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK); 1237 1238 if (hr == D3D_OK) 1239 { 1240 d3dxmesh->lpVtbl->Release(d3dxmesh); 1241 } 1242 1243 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, 0, device, &d3dxmesh); 1244 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 1245 1246 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl1, device, NULL); 1247 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 1248 1249 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl1, device, &d3dxmesh); 1250 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); 1251 1252 if (hr == D3D_OK) 1253 { 1254 /* device */ 1255 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, NULL); 1256 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 1257 1258 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, &test_device); 1259 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK); 1260 ok(test_device == device, "Got result %p, expected %p\n", test_device, device); 1261 1262 if (hr == D3D_OK) 1263 { 1264 IDirect3DDevice9_Release(device); 1265 } 1266 1267 /* declaration */ 1268 hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, NULL); 1269 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 1270 1271 hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, test_decl); 1272 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); 1273 1274 if (hr == D3D_OK) 1275 { 1276 size = ARRAY_SIZE(decl1); 1277 for (i = 0; i < size - 1; i++) 1278 { 1279 ok(test_decl[i].Stream == decl1[i].Stream, "Returned stream %d, expected %d\n", test_decl[i].Stream, decl1[i].Stream); 1280 ok(test_decl[i].Type == decl1[i].Type, "Returned type %d, expected %d\n", test_decl[i].Type, decl1[i].Type); 1281 ok(test_decl[i].Method == decl1[i].Method, "Returned method %d, expected %d\n", test_decl[i].Method, decl1[i].Method); 1282 ok(test_decl[i].Usage == decl1[i].Usage, "Returned usage %d, expected %d\n", test_decl[i].Usage, decl1[i].Usage); 1283 ok(test_decl[i].UsageIndex == decl1[i].UsageIndex, "Returned usage index %d, expected %d\n", test_decl[i].UsageIndex, decl1[i].UsageIndex); 1284 ok(test_decl[i].Offset == decl1[i].Offset, "Returned offset %d, expected %d\n", test_decl[i].Offset, decl1[i].Offset); 1285 } 1286 ok(decl1[size-1].Stream == 0xFF, "Returned too long vertex declaration\n"); /* end element */ 1287 } 1288 1289 /* options */ 1290 options = d3dxmesh->lpVtbl->GetOptions(d3dxmesh); 1291 ok(options == D3DXMESH_MANAGED, "Got result %x, expected %x (D3DXMESH_MANAGED)\n", options, D3DXMESH_MANAGED); 1292 1293 /* rest */ 1294 if (!new_mesh(&mesh, 3, 1)) 1295 { 1296 skip("Couldn't create mesh\n"); 1297 } 1298 else 1299 { 1300 memset(mesh.vertices, 0, mesh.number_of_vertices * sizeof(*mesh.vertices)); 1301 memset(mesh.faces, 0, mesh.number_of_faces * sizeof(*mesh.faces)); 1302 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL; 1303 1304 compare_mesh("createmesh1", d3dxmesh, &mesh); 1305 1306 free_mesh(&mesh); 1307 } 1308 1309 d3dxmesh->lpVtbl->Release(d3dxmesh); 1310 } 1311 1312 /* Test a declaration that can't be converted to an FVF. */ 1313 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl2, device, &d3dxmesh); 1314 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); 1315 1316 if (hr == D3D_OK) 1317 { 1318 /* device */ 1319 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, NULL); 1320 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 1321 1322 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, &test_device); 1323 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK); 1324 ok(test_device == device, "Got result %p, expected %p\n", test_device, device); 1325 1326 if (hr == D3D_OK) 1327 { 1328 IDirect3DDevice9_Release(device); 1329 } 1330 1331 /* declaration */ 1332 hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, test_decl); 1333 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); 1334 1335 if (hr == D3D_OK) 1336 { 1337 size = ARRAY_SIZE(decl2); 1338 for (i = 0; i < size - 1; i++) 1339 { 1340 ok(test_decl[i].Stream == decl2[i].Stream, "Returned stream %d, expected %d\n", test_decl[i].Stream, decl2[i].Stream); 1341 ok(test_decl[i].Type == decl2[i].Type, "Returned type %d, expected %d\n", test_decl[i].Type, decl2[i].Type); 1342 ok(test_decl[i].Method == decl2[i].Method, "Returned method %d, expected %d\n", test_decl[i].Method, decl2[i].Method); 1343 ok(test_decl[i].Usage == decl2[i].Usage, "Returned usage %d, expected %d\n", test_decl[i].Usage, decl2[i].Usage); 1344 ok(test_decl[i].UsageIndex == decl2[i].UsageIndex, "Returned usage index %d, expected %d\n", test_decl[i].UsageIndex, decl2[i].UsageIndex); 1345 ok(test_decl[i].Offset == decl2[i].Offset, "Returned offset %d, expected %d\n", test_decl[i].Offset, decl2[i].Offset); 1346 } 1347 ok(decl2[size-1].Stream == 0xFF, "Returned too long vertex declaration\n"); /* end element */ 1348 } 1349 1350 /* options */ 1351 options = d3dxmesh->lpVtbl->GetOptions(d3dxmesh); 1352 ok(options == D3DXMESH_MANAGED, "Got result %x, expected %x (D3DXMESH_MANAGED)\n", options, D3DXMESH_MANAGED); 1353 1354 /* rest */ 1355 if (!new_mesh(&mesh, 3, 1)) 1356 { 1357 skip("Couldn't create mesh\n"); 1358 } 1359 else 1360 { 1361 memset(mesh.vertices, 0, mesh.number_of_vertices * sizeof(*mesh.vertices)); 1362 memset(mesh.faces, 0, mesh.number_of_faces * sizeof(*mesh.faces)); 1363 mesh.fvf = 0; 1364 mesh.vertex_size = 60; 1365 1366 compare_mesh("createmesh2", d3dxmesh, &mesh); 1367 1368 free_mesh(&mesh); 1369 } 1370 1371 mesh.vertex_size = d3dxmesh->lpVtbl->GetNumBytesPerVertex(d3dxmesh); 1372 ok(mesh.vertex_size == 60, "Got vertex size %u, expected %u\n", mesh.vertex_size, 60); 1373 1374 d3dxmesh->lpVtbl->Release(d3dxmesh); 1375 } 1376 1377 /* Test a declaration with multiple streams. */ 1378 hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl3, device, &d3dxmesh); 1379 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 1380 1381 free_test_context(test_context); 1382 } 1383 1384 static void D3DXCreateMeshFVFTest(void) 1385 { 1386 HRESULT hr; 1387 IDirect3DDevice9 *device, *test_device; 1388 ID3DXMesh *d3dxmesh; 1389 int i, size; 1390 D3DVERTEXELEMENT9 test_decl[MAX_FVF_DECL_SIZE]; 1391 DWORD options; 1392 struct mesh mesh; 1393 struct test_context *test_context; 1394 1395 static const D3DVERTEXELEMENT9 decl[] = 1396 { 1397 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 1398 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 1399 D3DDECL_END(), 1400 }; 1401 1402 hr = D3DXCreateMeshFVF(0, 0, 0, 0, NULL, NULL); 1403 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 1404 1405 hr = D3DXCreateMeshFVF(1, 3, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, NULL, &d3dxmesh); 1406 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 1407 1408 test_context = new_test_context(); 1409 if (!test_context) 1410 { 1411 skip("Couldn't create test context\n"); 1412 return; 1413 } 1414 device = test_context->device; 1415 1416 hr = D3DXCreateMeshFVF(0, 3, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, device, &d3dxmesh); 1417 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 1418 1419 hr = D3DXCreateMeshFVF(1, 0, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, device, &d3dxmesh); 1420 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 1421 1422 hr = D3DXCreateMeshFVF(1, 3, 0, D3DFVF_XYZ | D3DFVF_NORMAL, device, &d3dxmesh); 1423 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK); 1424 1425 if (hr == D3D_OK) 1426 { 1427 d3dxmesh->lpVtbl->Release(d3dxmesh); 1428 } 1429 1430 hr = D3DXCreateMeshFVF(1, 3, D3DXMESH_MANAGED, 0xdeadbeef, device, &d3dxmesh); 1431 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 1432 1433 hr = D3DXCreateMeshFVF(1, 3, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, device, NULL); 1434 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 1435 1436 hr = D3DXCreateMeshFVF(1, 3, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, device, &d3dxmesh); 1437 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); 1438 1439 if (hr == D3D_OK) 1440 { 1441 /* device */ 1442 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, NULL); 1443 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 1444 1445 hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, &test_device); 1446 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK); 1447 ok(test_device == device, "Got result %p, expected %p\n", test_device, device); 1448 1449 if (hr == D3D_OK) 1450 { 1451 IDirect3DDevice9_Release(device); 1452 } 1453 1454 /* declaration */ 1455 hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, NULL); 1456 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 1457 1458 hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, test_decl); 1459 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); 1460 1461 if (hr == D3D_OK) 1462 { 1463 size = ARRAY_SIZE(decl); 1464 for (i = 0; i < size - 1; i++) 1465 { 1466 ok(test_decl[i].Stream == decl[i].Stream, "Returned stream %d, expected %d\n", test_decl[i].Stream, decl[i].Stream); 1467 ok(test_decl[i].Type == decl[i].Type, "Returned type %d, expected %d\n", test_decl[i].Type, decl[i].Type); 1468 ok(test_decl[i].Method == decl[i].Method, "Returned method %d, expected %d\n", test_decl[i].Method, decl[i].Method); 1469 ok(test_decl[i].Usage == decl[i].Usage, "Returned usage %d, expected %d\n", test_decl[i].Usage, decl[i].Usage); 1470 ok(test_decl[i].UsageIndex == decl[i].UsageIndex, "Returned usage index %d, expected %d\n", 1471 test_decl[i].UsageIndex, decl[i].UsageIndex); 1472 ok(test_decl[i].Offset == decl[i].Offset, "Returned offset %d, expected %d\n", test_decl[i].Offset, decl[i].Offset); 1473 } 1474 ok(decl[size-1].Stream == 0xFF, "Returned too long vertex declaration\n"); /* end element */ 1475 } 1476 1477 /* options */ 1478 options = d3dxmesh->lpVtbl->GetOptions(d3dxmesh); 1479 ok(options == D3DXMESH_MANAGED, "Got result %x, expected %x (D3DXMESH_MANAGED)\n", options, D3DXMESH_MANAGED); 1480 1481 /* rest */ 1482 if (!new_mesh(&mesh, 3, 1)) 1483 { 1484 skip("Couldn't create mesh\n"); 1485 } 1486 else 1487 { 1488 memset(mesh.vertices, 0, mesh.number_of_vertices * sizeof(*mesh.vertices)); 1489 memset(mesh.faces, 0, mesh.number_of_faces * sizeof(*mesh.faces)); 1490 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL; 1491 1492 compare_mesh("createmeshfvf", d3dxmesh, &mesh); 1493 1494 free_mesh(&mesh); 1495 } 1496 1497 d3dxmesh->lpVtbl->Release(d3dxmesh); 1498 } 1499 1500 free_test_context(test_context); 1501 } 1502 1503 #define check_vertex_buffer(mesh, vertices, num_vertices, fvf) \ 1504 check_vertex_buffer_(__LINE__, mesh, vertices, num_vertices, fvf) 1505 static void check_vertex_buffer_(int line, ID3DXMesh *mesh, const void *vertices, DWORD num_vertices, DWORD fvf) 1506 { 1507 DWORD mesh_num_vertices = mesh->lpVtbl->GetNumVertices(mesh); 1508 DWORD mesh_fvf = mesh->lpVtbl->GetFVF(mesh); 1509 const void *mesh_vertices; 1510 HRESULT hr; 1511 1512 ok_(__FILE__,line)(fvf == mesh_fvf, "expected FVF %x, got %x\n", fvf, mesh_fvf); 1513 ok_(__FILE__,line)(num_vertices == mesh_num_vertices, 1514 "Expected %u vertices, got %u\n", num_vertices, mesh_num_vertices); 1515 1516 hr = mesh->lpVtbl->LockVertexBuffer(mesh, D3DLOCK_READONLY, (void**)&mesh_vertices); 1517 ok_(__FILE__,line)(hr == D3D_OK, "LockVertexBuffer returned %x, expected %x (D3D_OK)\n", hr, D3D_OK); 1518 if (FAILED(hr)) 1519 return; 1520 1521 if (mesh_fvf == fvf) { 1522 DWORD vertex_size = D3DXGetFVFVertexSize(fvf), i; 1523 1524 for (i = 0; i < min(num_vertices, mesh_num_vertices); i++) 1525 { 1526 const FLOAT *exp_float = vertices; 1527 const FLOAT *got_float = mesh_vertices; 1528 DWORD texcount; 1529 DWORD pos_dim = 0; 1530 int j; 1531 BOOL last_beta_dword = FALSE; 1532 char prefix[128]; 1533 1534 switch (fvf & D3DFVF_POSITION_MASK) { 1535 case D3DFVF_XYZ: pos_dim = 3; break; 1536 case D3DFVF_XYZRHW: pos_dim = 4; break; 1537 case D3DFVF_XYZB1: 1538 case D3DFVF_XYZB2: 1539 case D3DFVF_XYZB3: 1540 case D3DFVF_XYZB4: 1541 case D3DFVF_XYZB5: 1542 pos_dim = (fvf & D3DFVF_POSITION_MASK) - D3DFVF_XYZB1 + 1; 1543 if (fvf & (D3DFVF_LASTBETA_UBYTE4 | D3DFVF_LASTBETA_D3DCOLOR)) 1544 { 1545 pos_dim--; 1546 last_beta_dword = TRUE; 1547 } 1548 break; 1549 case D3DFVF_XYZW: pos_dim = 4; break; 1550 } 1551 sprintf(prefix, "vertex[%u] position, ", i); 1552 check_floats_(line, prefix, got_float, exp_float, pos_dim); 1553 exp_float += pos_dim; 1554 got_float += pos_dim; 1555 1556 if (last_beta_dword) { 1557 ok_(__FILE__,line)(*(DWORD*)exp_float == *(DWORD*)got_float, 1558 "Vertex[%u]: Expected last beta %08x, got %08x\n", i, *(DWORD*)exp_float, *(DWORD*)got_float); 1559 exp_float++; 1560 got_float++; 1561 } 1562 1563 if (fvf & D3DFVF_NORMAL) { 1564 sprintf(prefix, "vertex[%u] normal, ", i); 1565 check_floats_(line, prefix, got_float, exp_float, 3); 1566 exp_float += 3; 1567 got_float += 3; 1568 } 1569 if (fvf & D3DFVF_PSIZE) { 1570 ok_(__FILE__,line)(compare(*exp_float, *got_float), 1571 "Vertex[%u]: Expected psize %g, got %g\n", i, *exp_float, *got_float); 1572 exp_float++; 1573 got_float++; 1574 } 1575 if (fvf & D3DFVF_DIFFUSE) { 1576 ok_(__FILE__,line)(*(DWORD*)exp_float == *(DWORD*)got_float, 1577 "Vertex[%u]: Expected diffuse %08x, got %08x\n", i, *(DWORD*)exp_float, *(DWORD*)got_float); 1578 exp_float++; 1579 got_float++; 1580 } 1581 if (fvf & D3DFVF_SPECULAR) { 1582 ok_(__FILE__,line)(*(DWORD*)exp_float == *(DWORD*)got_float, 1583 "Vertex[%u]: Expected specular %08x, got %08x\n", i, *(DWORD*)exp_float, *(DWORD*)got_float); 1584 exp_float++; 1585 got_float++; 1586 } 1587 1588 texcount = (fvf & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT; 1589 for (j = 0; j < texcount; j++) { 1590 DWORD dim = (((fvf >> (16 + 2 * j)) + 1) & 0x03) + 1; 1591 sprintf(prefix, "vertex[%u] texture, ", i); 1592 check_floats_(line, prefix, got_float, exp_float, dim); 1593 exp_float += dim; 1594 got_float += dim; 1595 } 1596 1597 vertices = (BYTE*)vertices + vertex_size; 1598 mesh_vertices = (BYTE*)mesh_vertices + vertex_size; 1599 } 1600 } 1601 1602 mesh->lpVtbl->UnlockVertexBuffer(mesh); 1603 } 1604 1605 #define check_index_buffer(mesh, indices, num_indices, index_size) \ 1606 check_index_buffer_(__LINE__, mesh, indices, num_indices, index_size) 1607 static void check_index_buffer_(int line, ID3DXMesh *mesh, const void *indices, DWORD num_indices, DWORD index_size) 1608 { 1609 DWORD mesh_index_size = (mesh->lpVtbl->GetOptions(mesh) & D3DXMESH_32BIT) ? 4 : 2; 1610 DWORD mesh_num_indices = mesh->lpVtbl->GetNumFaces(mesh) * 3; 1611 const void *mesh_indices; 1612 HRESULT hr; 1613 DWORD i; 1614 1615 ok_(__FILE__,line)(index_size == mesh_index_size, 1616 "Expected index size %u, got %u\n", index_size, mesh_index_size); 1617 ok_(__FILE__,line)(num_indices == mesh_num_indices, 1618 "Expected %u indices, got %u\n", num_indices, mesh_num_indices); 1619 1620 hr = mesh->lpVtbl->LockIndexBuffer(mesh, D3DLOCK_READONLY, (void**)&mesh_indices); 1621 ok_(__FILE__,line)(hr == D3D_OK, "LockIndexBuffer returned %x, expected %x (D3D_OK)\n", hr, D3D_OK); 1622 if (FAILED(hr)) 1623 return; 1624 1625 if (mesh_index_size == index_size) { 1626 for (i = 0; i < min(num_indices, mesh_num_indices); i++) 1627 { 1628 if (index_size == 4) 1629 ok_(__FILE__,line)(*(DWORD*)indices == *(DWORD*)mesh_indices, 1630 "Index[%u]: expected %u, got %u\n", i, *(DWORD*)indices, *(DWORD*)mesh_indices); 1631 else 1632 ok_(__FILE__,line)(*(WORD*)indices == *(WORD*)mesh_indices, 1633 "Index[%u]: expected %u, got %u\n", i, *(WORD*)indices, *(WORD*)mesh_indices); 1634 indices = (BYTE*)indices + index_size; 1635 mesh_indices = (BYTE*)mesh_indices + index_size; 1636 } 1637 } 1638 mesh->lpVtbl->UnlockIndexBuffer(mesh); 1639 } 1640 1641 #define check_matrix(got, expected) check_matrix_(__LINE__, got, expected) 1642 static void check_matrix_(int line, const D3DXMATRIX *got, const D3DXMATRIX *expected) 1643 { 1644 int i, j; 1645 for (i = 0; i < 4; i++) { 1646 for (j = 0; j < 4; j++) { 1647 ok_(__FILE__,line)(compare(U(*expected).m[i][j], U(*got).m[i][j]), 1648 "matrix[%u][%u]: expected %g, got %g\n", 1649 i, j, U(*expected).m[i][j], U(*got).m[i][j]); 1650 } 1651 } 1652 } 1653 1654 static void check_colorvalue_(int line, const char *prefix, const D3DCOLORVALUE got, const D3DCOLORVALUE expected) 1655 { 1656 ok_(__FILE__,line)(expected.r == got.r && expected.g == got.g && expected.b == got.b && expected.a == got.a, 1657 "%sExpected (%g, %g, %g, %g), got (%g, %g, %g, %g)\n", prefix, 1658 expected.r, expected.g, expected.b, expected.a, got.r, got.g, got.b, got.a); 1659 } 1660 1661 #define check_materials(got, got_count, expected, expected_count) \ 1662 check_materials_(__LINE__, got, got_count, expected, expected_count) 1663 static void check_materials_(int line, const D3DXMATERIAL *got, DWORD got_count, const D3DXMATERIAL *expected, DWORD expected_count) 1664 { 1665 int i; 1666 ok_(__FILE__,line)(expected_count == got_count, "Expected %u materials, got %u\n", expected_count, got_count); 1667 if (!expected) { 1668 ok_(__FILE__,line)(got == NULL, "Expected NULL material ptr, got %p\n", got); 1669 return; 1670 } 1671 for (i = 0; i < min(expected_count, got_count); i++) 1672 { 1673 if (!expected[i].pTextureFilename) 1674 ok_(__FILE__,line)(got[i].pTextureFilename == NULL, 1675 "Expected NULL pTextureFilename, got %p\n", got[i].pTextureFilename); 1676 else 1677 ok_(__FILE__,line)(!strcmp(expected[i].pTextureFilename, got[i].pTextureFilename), 1678 "Expected '%s' for pTextureFilename, got '%s'\n", expected[i].pTextureFilename, got[i].pTextureFilename); 1679 check_colorvalue_(line, "Diffuse: ", got[i].MatD3D.Diffuse, expected[i].MatD3D.Diffuse); 1680 check_colorvalue_(line, "Ambient: ", got[i].MatD3D.Ambient, expected[i].MatD3D.Ambient); 1681 check_colorvalue_(line, "Specular: ", got[i].MatD3D.Specular, expected[i].MatD3D.Specular); 1682 check_colorvalue_(line, "Emissive: ", got[i].MatD3D.Emissive, expected[i].MatD3D.Emissive); 1683 ok_(__FILE__,line)(expected[i].MatD3D.Power == got[i].MatD3D.Power, 1684 "Power: Expected %g, got %g\n", expected[i].MatD3D.Power, got[i].MatD3D.Power); 1685 } 1686 } 1687 1688 #define check_generated_adjacency(mesh, got, epsilon) check_generated_adjacency_(__LINE__, mesh, got, epsilon) 1689 static void check_generated_adjacency_(int line, ID3DXMesh *mesh, const DWORD *got, FLOAT epsilon) 1690 { 1691 DWORD *expected; 1692 DWORD num_faces = mesh->lpVtbl->GetNumFaces(mesh); 1693 HRESULT hr; 1694 1695 expected = HeapAlloc(GetProcessHeap(), 0, num_faces * sizeof(DWORD) * 3); 1696 if (!expected) { 1697 skip_(__FILE__, line)("Out of memory\n"); 1698 return; 1699 } 1700 hr = mesh->lpVtbl->GenerateAdjacency(mesh, epsilon, expected); 1701 ok_(__FILE__, line)(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 1702 if (SUCCEEDED(hr)) 1703 { 1704 int i; 1705 for (i = 0; i < num_faces; i++) 1706 { 1707 ok_(__FILE__, line)(expected[i * 3] == got[i * 3] && 1708 expected[i * 3 + 1] == got[i * 3 + 1] && 1709 expected[i * 3 + 2] == got[i * 3 + 2], 1710 "Face %u adjacencies: Expected (%u, %u, %u), got (%u, %u, %u)\n", i, 1711 expected[i * 3], expected[i * 3 + 1], expected[i * 3 + 2], 1712 got[i * 3], got[i * 3 + 1], got[i * 3 + 2]); 1713 } 1714 } 1715 HeapFree(GetProcessHeap(), 0, expected); 1716 } 1717 1718 #define check_generated_effects(materials, num_materials, effects) \ 1719 check_generated_effects_(__LINE__, materials, num_materials, effects) 1720 static void check_generated_effects_(int line, const D3DXMATERIAL *materials, DWORD num_materials, const D3DXEFFECTINSTANCE *effects) 1721 { 1722 int i; 1723 static const struct { 1724 const char *name; 1725 DWORD name_size; 1726 DWORD num_bytes; 1727 DWORD value_offset; 1728 } params[] = { 1729 #define EFFECT_TABLE_ENTRY(str, field) \ 1730 {str, sizeof(str), sizeof(materials->MatD3D.field), offsetof(D3DXMATERIAL, MatD3D.field)} 1731 EFFECT_TABLE_ENTRY("Diffuse", Diffuse), 1732 EFFECT_TABLE_ENTRY("Power", Power), 1733 EFFECT_TABLE_ENTRY("Specular", Specular), 1734 EFFECT_TABLE_ENTRY("Emissive", Emissive), 1735 EFFECT_TABLE_ENTRY("Ambient", Ambient), 1736 #undef EFFECT_TABLE_ENTRY 1737 }; 1738 1739 if (!num_materials) { 1740 ok_(__FILE__, line)(effects == NULL, "Expected NULL effects, got %p\n", effects); 1741 return; 1742 } 1743 for (i = 0; i < num_materials; i++) 1744 { 1745 int j; 1746 DWORD expected_num_defaults = ARRAY_SIZE(params) + (materials[i].pTextureFilename ? 1 : 0); 1747 1748 ok_(__FILE__,line)(expected_num_defaults == effects[i].NumDefaults, 1749 "effect[%u] NumDefaults: Expected %u, got %u\n", i, 1750 expected_num_defaults, effects[i].NumDefaults); 1751 for (j = 0; j < min(ARRAY_SIZE(params), effects[i].NumDefaults); j++) 1752 { 1753 int k; 1754 D3DXEFFECTDEFAULT *got_param = &effects[i].pDefaults[j]; 1755 ok_(__FILE__,line)(!strcmp(params[j].name, got_param->pParamName), 1756 "effect[%u].pDefaults[%u].pParamName: Expected '%s', got '%s'\n", i, j, 1757 params[j].name, got_param->pParamName); 1758 ok_(__FILE__,line)(D3DXEDT_FLOATS == got_param->Type, 1759 "effect[%u].pDefaults[%u].Type: Expected %u, got %u\n", i, j, 1760 D3DXEDT_FLOATS, got_param->Type); 1761 ok_(__FILE__,line)(params[j].num_bytes == got_param->NumBytes, 1762 "effect[%u].pDefaults[%u].NumBytes: Expected %u, got %u\n", i, j, 1763 params[j].num_bytes, got_param->NumBytes); 1764 for (k = 0; k < min(params[j].num_bytes, got_param->NumBytes) / 4; k++) 1765 { 1766 FLOAT expected = ((FLOAT*)((BYTE*)&materials[i] + params[j].value_offset))[k]; 1767 FLOAT got = ((FLOAT*)got_param->pValue)[k]; 1768 ok_(__FILE__,line)(compare(expected, got), 1769 "effect[%u].pDefaults[%u] float value %u: Expected %g, got %g\n", i, j, k, expected, got); 1770 } 1771 } 1772 if (effects[i].NumDefaults > ARRAY_SIZE(params)) { 1773 D3DXEFFECTDEFAULT *got_param = &effects[i].pDefaults[j]; 1774 static const char *expected_name = "Texture0@Name"; 1775 1776 ok_(__FILE__,line)(!strcmp(expected_name, got_param->pParamName), 1777 "effect[%u].pDefaults[%u].pParamName: Expected '%s', got '%s'\n", i, j, 1778 expected_name, got_param->pParamName); 1779 ok_(__FILE__,line)(D3DXEDT_STRING == got_param->Type, 1780 "effect[%u].pDefaults[%u].Type: Expected %u, got %u\n", i, j, 1781 D3DXEDT_STRING, got_param->Type); 1782 if (materials[i].pTextureFilename) { 1783 ok_(__FILE__,line)(strlen(materials[i].pTextureFilename) + 1 == got_param->NumBytes, 1784 "effect[%u] texture filename length: Expected %u, got %u\n", i, 1785 (DWORD)strlen(materials[i].pTextureFilename) + 1, got_param->NumBytes); 1786 ok_(__FILE__,line)(!strcmp(materials[i].pTextureFilename, got_param->pValue), 1787 "effect[%u] texture filename: Expected '%s', got '%s'\n", i, 1788 materials[i].pTextureFilename, (char*)got_param->pValue); 1789 } 1790 } 1791 } 1792 } 1793 1794 static char *strdupA(const char *p) 1795 { 1796 char *ret; 1797 if (!p) return NULL; 1798 ret = HeapAlloc(GetProcessHeap(), 0, strlen(p) + 1); 1799 if (ret) strcpy(ret, p); 1800 return ret; 1801 } 1802 1803 static HRESULT CALLBACK ID3DXAllocateHierarchyImpl_DestroyFrame(ID3DXAllocateHierarchy *iface, LPD3DXFRAME frame) 1804 { 1805 TRACECALLBACK("ID3DXAllocateHierarchyImpl_DestroyFrame(%p, %p)\n", iface, frame); 1806 if (frame) { 1807 HeapFree(GetProcessHeap(), 0, frame->Name); 1808 HeapFree(GetProcessHeap(), 0, frame); 1809 } 1810 return D3D_OK; 1811 } 1812 1813 static HRESULT CALLBACK ID3DXAllocateHierarchyImpl_CreateFrame(ID3DXAllocateHierarchy *iface, 1814 const char *name, D3DXFRAME **new_frame) 1815 { 1816 D3DXFRAME *frame; 1817 1818 TRACECALLBACK("ID3DXAllocateHierarchyImpl_CreateFrame(%p, '%s', %p)\n", iface, name, new_frame); 1819 frame = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*frame)); 1820 if (!frame) 1821 return E_OUTOFMEMORY; 1822 if (name) { 1823 frame->Name = strdupA(name); 1824 if (!frame->Name) { 1825 HeapFree(GetProcessHeap(), 0, frame); 1826 return E_OUTOFMEMORY; 1827 } 1828 } 1829 *new_frame = frame; 1830 return D3D_OK; 1831 } 1832 1833 static HRESULT destroy_mesh_container(LPD3DXMESHCONTAINER mesh_container) 1834 { 1835 int i; 1836 1837 if (!mesh_container) 1838 return D3D_OK; 1839 HeapFree(GetProcessHeap(), 0, mesh_container->Name); 1840 if (U(mesh_container->MeshData).pMesh) 1841 IUnknown_Release(U(mesh_container->MeshData).pMesh); 1842 if (mesh_container->pMaterials) { 1843 for (i = 0; i < mesh_container->NumMaterials; i++) 1844 HeapFree(GetProcessHeap(), 0, mesh_container->pMaterials[i].pTextureFilename); 1845 HeapFree(GetProcessHeap(), 0, mesh_container->pMaterials); 1846 } 1847 if (mesh_container->pEffects) { 1848 for (i = 0; i < mesh_container->NumMaterials; i++) { 1849 HeapFree(GetProcessHeap(), 0, mesh_container->pEffects[i].pEffectFilename); 1850 if (mesh_container->pEffects[i].pDefaults) { 1851 int j; 1852 for (j = 0; j < mesh_container->pEffects[i].NumDefaults; j++) { 1853 HeapFree(GetProcessHeap(), 0, mesh_container->pEffects[i].pDefaults[j].pParamName); 1854 HeapFree(GetProcessHeap(), 0, mesh_container->pEffects[i].pDefaults[j].pValue); 1855 } 1856 HeapFree(GetProcessHeap(), 0, mesh_container->pEffects[i].pDefaults); 1857 } 1858 } 1859 HeapFree(GetProcessHeap(), 0, mesh_container->pEffects); 1860 } 1861 HeapFree(GetProcessHeap(), 0, mesh_container->pAdjacency); 1862 if (mesh_container->pSkinInfo) 1863 IUnknown_Release(mesh_container->pSkinInfo); 1864 HeapFree(GetProcessHeap(), 0, mesh_container); 1865 return D3D_OK; 1866 } 1867 1868 static HRESULT CALLBACK ID3DXAllocateHierarchyImpl_DestroyMeshContainer(ID3DXAllocateHierarchy *iface, LPD3DXMESHCONTAINER mesh_container) 1869 { 1870 TRACECALLBACK("ID3DXAllocateHierarchyImpl_DestroyMeshContainer(%p, %p)\n", iface, mesh_container); 1871 return destroy_mesh_container(mesh_container); 1872 } 1873 1874 static HRESULT CALLBACK ID3DXAllocateHierarchyImpl_CreateMeshContainer(ID3DXAllocateHierarchy *iface, 1875 const char *name, const D3DXMESHDATA *mesh_data, const D3DXMATERIAL *materials, 1876 const D3DXEFFECTINSTANCE *effects, DWORD num_materials, const DWORD *adjacency, 1877 ID3DXSkinInfo *skin_info, D3DXMESHCONTAINER **new_mesh_container) 1878 { 1879 LPD3DXMESHCONTAINER mesh_container = NULL; 1880 int i; 1881 1882 TRACECALLBACK("ID3DXAllocateHierarchyImpl_CreateMeshContainer(%p, '%s', %u, %p, %p, %p, %d, %p, %p, %p)\n", 1883 iface, name, mesh_data->Type, U(*mesh_data).pMesh, materials, effects, 1884 num_materials, adjacency, skin_info, *new_mesh_container); 1885 1886 mesh_container = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*mesh_container)); 1887 if (!mesh_container) 1888 return E_OUTOFMEMORY; 1889 1890 if (name) { 1891 mesh_container->Name = strdupA(name); 1892 if (!mesh_container->Name) 1893 goto error; 1894 } 1895 1896 mesh_container->NumMaterials = num_materials; 1897 if (num_materials) { 1898 mesh_container->pMaterials = HeapAlloc(GetProcessHeap(), 0, num_materials * sizeof(*materials)); 1899 if (!mesh_container->pMaterials) 1900 goto error; 1901 1902 memcpy(mesh_container->pMaterials, materials, num_materials * sizeof(*materials)); 1903 for (i = 0; i < num_materials; i++) 1904 mesh_container->pMaterials[i].pTextureFilename = NULL; 1905 for (i = 0; i < num_materials; i++) { 1906 if (materials[i].pTextureFilename) { 1907 mesh_container->pMaterials[i].pTextureFilename = strdupA(materials[i].pTextureFilename); 1908 if (!mesh_container->pMaterials[i].pTextureFilename) 1909 goto error; 1910 } 1911 } 1912 1913 mesh_container->pEffects = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, num_materials * sizeof(*effects)); 1914 if (!mesh_container->pEffects) 1915 goto error; 1916 for (i = 0; i < num_materials; i++) { 1917 int j; 1918 const D3DXEFFECTINSTANCE *effect_src = &effects[i]; 1919 D3DXEFFECTINSTANCE *effect_dest = &mesh_container->pEffects[i]; 1920 1921 if (effect_src->pEffectFilename) { 1922 effect_dest->pEffectFilename = strdupA(effect_src->pEffectFilename); 1923 if (!effect_dest->pEffectFilename) 1924 goto error; 1925 } 1926 effect_dest->pDefaults = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 1927 effect_src->NumDefaults * sizeof(*effect_src->pDefaults)); 1928 if (!effect_dest->pDefaults) 1929 goto error; 1930 effect_dest->NumDefaults = effect_src->NumDefaults; 1931 for (j = 0; j < effect_src->NumDefaults; j++) { 1932 const D3DXEFFECTDEFAULT *default_src = &effect_src->pDefaults[j]; 1933 D3DXEFFECTDEFAULT *default_dest = &effect_dest->pDefaults[j]; 1934 1935 if (default_src->pParamName) { 1936 default_dest->pParamName = strdupA(default_src->pParamName); 1937 if (!default_dest->pParamName) 1938 goto error; 1939 } 1940 default_dest->NumBytes = default_src->NumBytes; 1941 default_dest->Type = default_src->Type; 1942 default_dest->pValue = HeapAlloc(GetProcessHeap(), 0, default_src->NumBytes); 1943 memcpy(default_dest->pValue, default_src->pValue, default_src->NumBytes); 1944 } 1945 } 1946 } 1947 1948 ok(adjacency != NULL, "Expected non-NULL adjacency, got NULL\n"); 1949 if (adjacency) { 1950 if (mesh_data->Type == D3DXMESHTYPE_MESH || mesh_data->Type == D3DXMESHTYPE_PMESH) { 1951 ID3DXBaseMesh *basemesh = (ID3DXBaseMesh*)U(*mesh_data).pMesh; 1952 DWORD num_faces = basemesh->lpVtbl->GetNumFaces(basemesh); 1953 size_t size = num_faces * sizeof(DWORD) * 3; 1954 mesh_container->pAdjacency = HeapAlloc(GetProcessHeap(), 0, size); 1955 if (!mesh_container->pAdjacency) 1956 goto error; 1957 memcpy(mesh_container->pAdjacency, adjacency, size); 1958 } else { 1959 ok(mesh_data->Type == D3DXMESHTYPE_PATCHMESH, "Unknown mesh type %u\n", mesh_data->Type); 1960 if (mesh_data->Type == D3DXMESHTYPE_PATCHMESH) 1961 trace("FIXME: copying adjacency data for patch mesh not implemented\n"); 1962 } 1963 } 1964 1965 memcpy(&mesh_container->MeshData, mesh_data, sizeof(*mesh_data)); 1966 if (U(*mesh_data).pMesh) 1967 IUnknown_AddRef(U(*mesh_data).pMesh); 1968 if (skin_info) { 1969 mesh_container->pSkinInfo = skin_info; 1970 skin_info->lpVtbl->AddRef(skin_info); 1971 } 1972 *new_mesh_container = mesh_container; 1973 1974 return S_OK; 1975 error: 1976 destroy_mesh_container(mesh_container); 1977 return E_OUTOFMEMORY; 1978 } 1979 1980 static ID3DXAllocateHierarchyVtbl ID3DXAllocateHierarchyImpl_Vtbl = { 1981 ID3DXAllocateHierarchyImpl_CreateFrame, 1982 ID3DXAllocateHierarchyImpl_CreateMeshContainer, 1983 ID3DXAllocateHierarchyImpl_DestroyFrame, 1984 ID3DXAllocateHierarchyImpl_DestroyMeshContainer, 1985 }; 1986 static ID3DXAllocateHierarchy alloc_hier = { &ID3DXAllocateHierarchyImpl_Vtbl }; 1987 1988 #define test_LoadMeshFromX(device, xfile_str, vertex_array, fvf, index_array, materials_array, check_adjacency) \ 1989 test_LoadMeshFromX_(__LINE__, device, xfile_str, sizeof(xfile_str) - 1, vertex_array, ARRAY_SIZE(vertex_array), fvf, \ 1990 index_array, ARRAY_SIZE(index_array), sizeof(*index_array), materials_array, ARRAY_SIZE(materials_array), \ 1991 check_adjacency); 1992 static void test_LoadMeshFromX_(int line, IDirect3DDevice9 *device, const char *xfile_str, size_t xfile_strlen, 1993 const void *vertices, DWORD num_vertices, DWORD fvf, const void *indices, DWORD num_indices, size_t index_size, 1994 const D3DXMATERIAL *expected_materials, DWORD expected_num_materials, BOOL check_adjacency) 1995 { 1996 HRESULT hr; 1997 ID3DXBuffer *materials = NULL; 1998 ID3DXBuffer *effects = NULL; 1999 ID3DXBuffer *adjacency = NULL; 2000 ID3DXMesh *mesh = NULL; 2001 DWORD num_materials = 0; 2002 2003 /* Adjacency is not checked when the X file contains multiple meshes, 2004 * since calling GenerateAdjacency on the merged mesh is not equivalent 2005 * to calling GenerateAdjacency on the individual meshes and then merging 2006 * the adjacency data. */ 2007 hr = D3DXLoadMeshFromXInMemory(xfile_str, xfile_strlen, D3DXMESH_MANAGED, device, 2008 check_adjacency ? &adjacency : NULL, &materials, &effects, &num_materials, &mesh); 2009 ok_(__FILE__,line)(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 2010 if (SUCCEEDED(hr)) { 2011 D3DXMATERIAL *materials_ptr = materials ? ID3DXBuffer_GetBufferPointer(materials) : NULL; 2012 D3DXEFFECTINSTANCE *effects_ptr = effects ? ID3DXBuffer_GetBufferPointer(effects) : NULL; 2013 DWORD *adjacency_ptr = check_adjacency ? ID3DXBuffer_GetBufferPointer(adjacency) : NULL; 2014 2015 check_vertex_buffer_(line, mesh, vertices, num_vertices, fvf); 2016 check_index_buffer_(line, mesh, indices, num_indices, index_size); 2017 check_materials_(line, materials_ptr, num_materials, expected_materials, expected_num_materials); 2018 check_generated_effects_(line, materials_ptr, num_materials, effects_ptr); 2019 if (check_adjacency) 2020 check_generated_adjacency_(line, mesh, adjacency_ptr, 0.0f); 2021 2022 if (materials) ID3DXBuffer_Release(materials); 2023 if (effects) ID3DXBuffer_Release(effects); 2024 if (adjacency) ID3DXBuffer_Release(adjacency); 2025 IUnknown_Release(mesh); 2026 } 2027 } 2028 2029 static void D3DXLoadMeshTest(void) 2030 { 2031 static const char empty_xfile[] = "xof 0303txt 0032"; 2032 /*________________________*/ 2033 static const char simple_xfile[] = 2034 "xof 0303txt 0032" 2035 "Mesh {" 2036 "3;" 2037 "0.0; 0.0; 0.0;," 2038 "0.0; 1.0; 0.0;," 2039 "1.0; 1.0; 0.0;;" 2040 "1;" 2041 "3; 0, 1, 2;;" 2042 "}"; 2043 static const WORD simple_index_buffer[] = {0, 1, 2}; 2044 static const D3DXVECTOR3 simple_vertex_buffer[] = { 2045 {0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {1.0, 1.0, 0.0} 2046 }; 2047 const DWORD simple_fvf = D3DFVF_XYZ; 2048 static const char framed_xfile[] = 2049 "xof 0303txt 0032" 2050 "Frame {" 2051 "Mesh { 3; 0.0; 0.0; 0.0;, 0.0; 1.0; 0.0;, 1.0; 1.0; 0.0;; 1; 3; 0, 1, 2;; }" 2052 "FrameTransformMatrix {" /* translation (0.0, 0.0, 2.0) */ 2053 "1.0, 0.0, 0.0, 0.0," 2054 "0.0, 1.0, 0.0, 0.0," 2055 "0.0, 0.0, 1.0, 0.0," 2056 "0.0, 0.0, 2.0, 1.0;;" 2057 "}" 2058 "Mesh { 3; 0.0; 0.0; 0.0;, 0.0; 1.0; 0.0;, 2.0; 1.0; 0.0;; 1; 3; 0, 1, 2;; }" 2059 "FrameTransformMatrix {" /* translation (0.0, 0.0, 3.0) */ 2060 "1.0, 0.0, 0.0, 0.0," 2061 "0.0, 1.0, 0.0, 0.0," 2062 "0.0, 0.0, 1.0, 0.0," 2063 "0.0, 0.0, 3.0, 1.0;;" 2064 "}" 2065 "Mesh { 3; 0.0; 0.0; 0.0;, 0.0; 1.0; 0.0;, 3.0; 1.0; 0.0;; 1; 3; 0, 1, 2;; }" 2066 "}"; 2067 static const WORD framed_index_buffer[] = { 0, 1, 2 }; 2068 static const D3DXVECTOR3 framed_vertex_buffers[3][3] = { 2069 {{0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {1.0, 1.0, 0.0}}, 2070 {{0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {2.0, 1.0, 0.0}}, 2071 {{0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {3.0, 1.0, 0.0}}, 2072 }; 2073 static const WORD merged_index_buffer[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 }; 2074 /* frame transforms accumulates for D3DXLoadMeshFromX */ 2075 static const D3DXVECTOR3 merged_vertex_buffer[] = { 2076 {0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {1.0, 1.0, 0.0}, 2077 {0.0, 0.0, 2.0}, {0.0, 1.0, 2.0}, {2.0, 1.0, 2.0}, 2078 {0.0, 0.0, 5.0}, {0.0, 1.0, 5.0}, {3.0, 1.0, 5.0}, 2079 }; 2080 const DWORD framed_fvf = D3DFVF_XYZ; 2081 /*________________________*/ 2082 static const char box_xfile[] = 2083 "xof 0303txt 0032" 2084 "Mesh {" 2085 "8;" /* DWORD nVertices; */ 2086 /* array Vector vertices[nVertices]; */ 2087 "0.0; 0.0; 0.0;," 2088 "0.0; 0.0; 1.0;," 2089 "0.0; 1.0; 0.0;," 2090 "0.0; 1.0; 1.0;," 2091 "1.0; 0.0; 0.0;," 2092 "1.0; 0.0; 1.0;," 2093 "1.0; 1.0; 0.0;," 2094 "1.0; 1.0; 1.0;;" 2095 "6;" /* DWORD nFaces; */ 2096 /* array MeshFace faces[nFaces]; */ 2097 "4; 0, 1, 3, 2;," /* (left side) */ 2098 "4; 2, 3, 7, 6;," /* (top side) */ 2099 "4; 6, 7, 5, 4;," /* (right side) */ 2100 "4; 1, 0, 4, 5;," /* (bottom side) */ 2101 "4; 1, 5, 7, 3;," /* (back side) */ 2102 "4; 0, 2, 6, 4;;" /* (front side) */ 2103 "MeshNormals {" 2104 "6;" /* DWORD nNormals; */ 2105 /* array Vector normals[nNormals]; */ 2106 "-1.0; 0.0; 0.0;," 2107 "0.0; 1.0; 0.0;," 2108 "1.0; 0.0; 0.0;," 2109 "0.0; -1.0; 0.0;," 2110 "0.0; 0.0; 1.0;," 2111 "0.0; 0.0; -1.0;;" 2112 "6;" /* DWORD nFaceNormals; */ 2113 /* array MeshFace faceNormals[nFaceNormals]; */ 2114 "4; 0, 0, 0, 0;," 2115 "4; 1, 1, 1, 1;," 2116 "4; 2, 2, 2, 2;," 2117 "4; 3, 3, 3, 3;," 2118 "4; 4, 4, 4, 4;," 2119 "4; 5, 5, 5, 5;;" 2120 "}" 2121 "MeshMaterialList materials {" 2122 "2;" /* DWORD nMaterials; */ 2123 "6;" /* DWORD nFaceIndexes; */ 2124 /* array DWORD faceIndexes[nFaceIndexes]; */ 2125 "0, 0, 0, 1, 1, 1;;" 2126 "Material {" 2127 /* ColorRGBA faceColor; */ 2128 "0.0; 0.0; 1.0; 1.0;;" 2129 /* FLOAT power; */ 2130 "0.5;" 2131 /* ColorRGB specularColor; */ 2132 "1.0; 1.0; 1.0;;" 2133 /* ColorRGB emissiveColor; */ 2134 "0.0; 0.0; 0.0;;" 2135 "}" 2136 "Material {" 2137 /* ColorRGBA faceColor; */ 2138 "1.0; 1.0; 1.0; 1.0;;" 2139 /* FLOAT power; */ 2140 "1.0;" 2141 /* ColorRGB specularColor; */ 2142 "1.0; 1.0; 1.0;;" 2143 /* ColorRGB emissiveColor; */ 2144 "0.0; 0.0; 0.0;;" 2145 "TextureFilename { \"texture.jpg\"; }" 2146 "}" 2147 "}" 2148 "MeshVertexColors {" 2149 "8;" /* DWORD nVertexColors; */ 2150 /* array IndexedColor vertexColors[nVertexColors]; */ 2151 "0; 0.0; 0.0; 0.0; 0.0;;" 2152 "1; 0.0; 0.0; 1.0; 0.1;;" 2153 "2; 0.0; 1.0; 0.0; 0.2;;" 2154 "3; 0.0; 1.0; 1.0; 0.3;;" 2155 "4; 1.0; 0.0; 0.0; 0.4;;" 2156 "5; 1.0; 0.0; 1.0; 0.5;;" 2157 "6; 1.0; 1.0; 0.0; 0.6;;" 2158 "7; 1.0; 1.0; 1.0; 0.7;;" 2159 "}" 2160 "MeshTextureCoords {" 2161 "8;" /* DWORD nTextureCoords; */ 2162 /* array Coords2d textureCoords[nTextureCoords]; */ 2163 "0.0; 1.0;," 2164 "1.0; 1.0;," 2165 "0.0; 0.0;," 2166 "1.0; 0.0;," 2167 "1.0; 1.0;," 2168 "0.0; 1.0;," 2169 "1.0; 0.0;," 2170 "0.0; 0.0;;" 2171 "}" 2172 "}"; 2173 static const WORD box_index_buffer[] = { 2174 0, 1, 3, 2175 0, 3, 2, 2176 8, 9, 7, 2177 8, 7, 6, 2178 10, 11, 5, 2179 10, 5, 4, 2180 12, 13, 14, 2181 12, 14, 15, 2182 16, 17, 18, 2183 16, 18, 19, 2184 20, 21, 22, 2185 20, 22, 23, 2186 }; 2187 static const struct { 2188 D3DXVECTOR3 position; 2189 D3DXVECTOR3 normal; 2190 D3DCOLOR diffuse; 2191 D3DXVECTOR2 tex_coords; 2192 } box_vertex_buffer[] = { 2193 {{0.0, 0.0, 0.0}, {-1.0, 0.0, 0.0}, 0x00000000, {0.0, 1.0}}, 2194 {{0.0, 0.0, 1.0}, {-1.0, 0.0, 0.0}, 0x1a0000ff, {1.0, 1.0}}, 2195 {{0.0, 1.0, 0.0}, {-1.0, 0.0, 0.0}, 0x3300ff00, {0.0, 0.0}}, 2196 {{0.0, 1.0, 1.0}, {-1.0, 0.0, 0.0}, 0x4d00ffff, {1.0, 0.0}}, 2197 {{1.0, 0.0, 0.0}, {1.0, 0.0, 0.0}, 0x66ff0000, {1.0, 1.0}}, 2198 {{1.0, 0.0, 1.0}, {1.0, 0.0, 0.0}, 0x80ff00ff, {0.0, 1.0}}, 2199 {{1.0, 1.0, 0.0}, {0.0, 1.0, 0.0}, 0x99ffff00, {1.0, 0.0}}, 2200 {{1.0, 1.0, 1.0}, {0.0, 1.0, 0.0}, 0xb3ffffff, {0.0, 0.0}}, 2201 {{0.0, 1.0, 0.0}, {0.0, 1.0, 0.0}, 0x3300ff00, {0.0, 0.0}}, 2202 {{0.0, 1.0, 1.0}, {0.0, 1.0, 0.0}, 0x4d00ffff, {1.0, 0.0}}, 2203 {{1.0, 1.0, 0.0}, {1.0, 0.0, 0.0}, 0x99ffff00, {1.0, 0.0}}, 2204 {{1.0, 1.0, 1.0}, {1.0, 0.0, 0.0}, 0xb3ffffff, {0.0, 0.0}}, 2205 {{0.0, 0.0, 1.0}, {0.0, -1.0, 0.0}, 0x1a0000ff, {1.0, 1.0}}, 2206 {{0.0, 0.0, 0.0}, {0.0, -1.0, 0.0}, 0x00000000, {0.0, 1.0}}, 2207 {{1.0, 0.0, 0.0}, {0.0, -1.0, 0.0}, 0x66ff0000, {1.0, 1.0}}, 2208 {{1.0, 0.0, 1.0}, {0.0, -1.0, 0.0}, 0x80ff00ff, {0.0, 1.0}}, 2209 {{0.0, 0.0, 1.0}, {0.0, 0.0, 1.0}, 0x1a0000ff, {1.0, 1.0}}, 2210 {{1.0, 0.0, 1.0}, {0.0, 0.0, 1.0}, 0x80ff00ff, {0.0, 1.0}}, 2211 {{1.0, 1.0, 1.0}, {0.0, 0.0, 1.0}, 0xb3ffffff, {0.0, 0.0}}, 2212 {{0.0, 1.0, 1.0}, {0.0, 0.0, 1.0}, 0x4d00ffff, {1.0, 0.0}}, 2213 {{0.0, 0.0, 0.0}, {0.0, 0.0, -1.0}, 0x00000000, {0.0, 1.0}}, 2214 {{0.0, 1.0, 0.0}, {0.0, 0.0, -1.0}, 0x3300ff00, {0.0, 0.0}}, 2215 {{1.0, 1.0, 0.0}, {0.0, 0.0, -1.0}, 0x99ffff00, {1.0, 0.0}}, 2216 {{1.0, 0.0, 0.0}, {0.0, 0.0, -1.0}, 0x66ff0000, {1.0, 1.0}}, 2217 }; 2218 static const D3DXMATERIAL box_materials[] = { 2219 { 2220 { 2221 {0.0, 0.0, 1.0, 1.0}, /* Diffuse */ 2222 {0.0, 0.0, 0.0, 1.0}, /* Ambient */ 2223 {1.0, 1.0, 1.0, 1.0}, /* Specular */ 2224 {0.0, 0.0, 0.0, 1.0}, /* Emissive */ 2225 0.5, /* Power */ 2226 }, 2227 NULL, /* pTextureFilename */ 2228 }, 2229 { 2230 { 2231 {1.0, 1.0, 1.0, 1.0}, /* Diffuse */ 2232 {0.0, 0.0, 0.0, 1.0}, /* Ambient */ 2233 {1.0, 1.0, 1.0, 1.0}, /* Specular */ 2234 {0.0, 0.0, 0.0, 1.0}, /* Emissive */ 2235 1.0, /* Power */ 2236 }, 2237 (char *)"texture.jpg", /* pTextureFilename */ 2238 }, 2239 }; 2240 static const char box_anim_xfile[] = 2241 "xof 0303txt 0032" 2242 "Mesh CubeMesh {" 2243 "8;" /* DWORD nVertices; */ 2244 /* array Vector vertices[nVertices]; */ 2245 "0.0; 0.0; 0.0;," 2246 "0.0; 0.0; 1.0;," 2247 "0.0; 1.0; 0.0;," 2248 "0.0; 1.0; 1.0;," 2249 "1.0; 0.0; 0.0;," 2250 "1.0; 0.0; 1.0;," 2251 "1.0; 1.0; 0.0;," 2252 "1.0; 1.0; 1.0;;" 2253 "6;" /* DWORD nFaces; */ 2254 /* array MeshFace faces[nFaces]; */ 2255 "4; 0, 1, 3, 2;," /* left side */ 2256 "4; 2, 3, 7, 6;," /* top side */ 2257 "4; 6, 7, 5, 4;," /* right side */ 2258 "4; 1, 0, 4, 5;," /* bottom side */ 2259 "4; 1, 5, 7, 3;," /* back side */ 2260 "4; 0, 2, 6, 4;;" /* front side */ 2261 "MeshNormals {" 2262 "6;" /* DWORD nNormals; */ 2263 /* array Vector normals[nNormals]; */ 2264 "-1.0; 0.0; 0.0;," 2265 "0.0; 1.0; 0.0;," 2266 "1.0; 0.0; 0.0;," 2267 "0.0; -1.0; 0.0;," 2268 "0.0; 0.0; 1.0;," 2269 "0.0; 0.0; -1.0;;" 2270 "6;" /* DWORD nFaceNormals; */ 2271 /* array MeshFace faceNormals[nFaceNormals]; */ 2272 "4; 0, 0, 0, 0;," 2273 "4; 1, 1, 1, 1;," 2274 "4; 2, 2, 2, 2;," 2275 "4; 3, 3, 3, 3;," 2276 "4; 4, 4, 4, 4;," 2277 "4; 5, 5, 5, 5;;" 2278 "}" 2279 "MeshMaterialList materials {" 2280 "2;" /* DWORD nMaterials; */ 2281 "6;" /* DWORD nFaceIndexes; */ 2282 /* array DWORD faceIndexes[nFaceIndexes]; */ 2283 "0, 0, 0, 1, 1, 1;;" 2284 "Material {" 2285 /* ColorRGBA faceColor; */ 2286 "0.0; 0.0; 1.0; 1.0;;" 2287 /* FLOAT power; */ 2288 "0.5;" 2289 /* ColorRGB specularColor; */ 2290 "1.0; 1.0; 1.0;;" 2291 /* ColorRGB emissiveColor; */ 2292 "0.0; 0.0; 0.0;;" 2293 "}" 2294 "Material {" 2295 /* ColorRGBA faceColor; */ 2296 "1.0; 1.0; 1.0; 1.0;;" 2297 /* FLOAT power; */ 2298 "1.0;" 2299 /* ColorRGB specularColor; */ 2300 "1.0; 1.0; 1.0;;" 2301 /* ColorRGB emissiveColor; */ 2302 "0.0; 0.0; 0.0;;" 2303 "TextureFilename { \"texture.jpg\"; }" 2304 "}" 2305 "}" 2306 "MeshVertexColors {" 2307 "8;" /* DWORD nVertexColors; */ 2308 /* array IndexedColor vertexColors[nVertexColors]; */ 2309 "0; 0.0; 0.0; 0.0; 0.0;;" 2310 "1; 0.0; 0.0; 1.0; 0.1;;" 2311 "2; 0.0; 1.0; 0.0; 0.2;;" 2312 "3; 0.0; 1.0; 1.0; 0.3;;" 2313 "4; 1.0; 0.0; 0.0; 0.4;;" 2314 "5; 1.0; 0.0; 1.0; 0.5;;" 2315 "6; 1.0; 1.0; 0.0; 0.6;;" 2316 "7; 1.0; 1.0; 1.0; 0.7;;" 2317 "}" 2318 "MeshTextureCoords {" 2319 "8;" /* DWORD nTextureCoords; */ 2320 /* array Coords2d textureCoords[nTextureCoords]; */ 2321 "0.0; 1.0;," 2322 "1.0; 1.0;," 2323 "0.0; 0.0;," 2324 "1.0; 0.0;," 2325 "1.0; 1.0;," 2326 "0.0; 1.0;," 2327 "1.0; 0.0;," 2328 "0.0; 0.0;;" 2329 "}" 2330 "}" 2331 "Frame CubeFrame {" 2332 "FrameTransformMatrix {" 2333 /* Matrix4x4 frameMatrix; */ 2334 "1.0, 0.0, 0.0, 0.0," 2335 "0.0, 1.0, 0.0, 0.0," 2336 "0.0, 0.0, 1.0, 0.0," 2337 "0.0, 0.0, 0.0, 1.0;;" 2338 "}" 2339 "{CubeMesh}" 2340 "}" 2341 "AnimationSet AnimationSet0 {" 2342 "Animation Animation0 {" 2343 "{CubeFrame}" 2344 "AnimationKey {" 2345 "2;" /* DWORD keyType; */ 2346 "9;" /* DWORD nKeys; */ 2347 /* array TimedFloatKeys keys[nKeys]; */ 2348 "10; 3; -100.0, 0.0, 0.0;;," 2349 "20; 3; -75.0, 0.0, 0.0;;," 2350 "30; 3; -50.0, 0.0, 0.0;;," 2351 "40; 3; -25.5, 0.0, 0.0;;," 2352 "50; 3; 0.0, 0.0, 0.0;;," 2353 "60; 3; 25.5, 0.0, 0.0;;," 2354 "70; 3; 50.0, 0.0, 0.0;;," 2355 "80; 3; 75.5, 0.0, 0.0;;," 2356 "90; 3; 100.0, 0.0, 0.0;;;" 2357 "}" 2358 "}" 2359 "}"; 2360 2361 const DWORD box_fvf = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_TEX1; 2362 /*________________________*/ 2363 static const D3DXMATERIAL default_materials[] = { 2364 { 2365 { 2366 {0.5, 0.5, 0.5, 0.0}, /* Diffuse */ 2367 {0.0, 0.0, 0.0, 0.0}, /* Ambient */ 2368 {0.5, 0.5, 0.5, 0.0}, /* Specular */ 2369 {0.0, 0.0, 0.0, 0.0}, /* Emissive */ 2370 0.0, /* Power */ 2371 }, 2372 NULL, /* pTextureFilename */ 2373 } 2374 }; 2375 HRESULT hr; 2376 IDirect3DDevice9 *device = NULL; 2377 ID3DXMesh *mesh = NULL; 2378 D3DXFRAME *frame_hier = NULL; 2379 D3DXMATRIX transform; 2380 struct test_context *test_context; 2381 ID3DXAnimationController *controller; 2382 2383 if (!(test_context = new_test_context())) 2384 { 2385 skip("Couldn't create test context\n"); 2386 return; 2387 } 2388 device = test_context->device; 2389 2390 hr = D3DXLoadMeshHierarchyFromXInMemory(NULL, sizeof(simple_xfile) - 1, 2391 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL); 2392 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 2393 2394 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, 0, 2395 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL); 2396 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 2397 2398 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1, 2399 D3DXMESH_MANAGED, NULL, &alloc_hier, NULL, &frame_hier, NULL); 2400 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 2401 2402 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1, 2403 D3DXMESH_MANAGED, device, NULL, NULL, &frame_hier, NULL); 2404 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 2405 2406 hr = D3DXLoadMeshHierarchyFromXInMemory(empty_xfile, sizeof(empty_xfile) - 1, 2407 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL); 2408 ok(hr == E_FAIL, "Expected E_FAIL, got %#x\n", hr); 2409 2410 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1, 2411 D3DXMESH_MANAGED, device, &alloc_hier, NULL, NULL, NULL); 2412 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 2413 2414 hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1, 2415 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL); 2416 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 2417 if (SUCCEEDED(hr)) { 2418 D3DXMESHCONTAINER *container = frame_hier->pMeshContainer; 2419 2420 ok(frame_hier->Name == NULL, "Expected NULL, got '%s'\n", frame_hier->Name); 2421 D3DXMatrixIdentity(&transform); 2422 check_matrix(&frame_hier->TransformationMatrix, &transform); 2423 2424 ok(!strcmp(container->Name, ""), "Expected '', got '%s'\n", container->Name); 2425 ok(container->MeshData.Type == D3DXMESHTYPE_MESH, "Expected %d, got %d\n", 2426 D3DXMESHTYPE_MESH, container->MeshData.Type); 2427 mesh = U(container->MeshData).pMesh; 2428 check_vertex_buffer(mesh, simple_vertex_buffer, ARRAY_SIZE(simple_vertex_buffer), simple_fvf); 2429 check_index_buffer(mesh, simple_index_buffer, ARRAY_SIZE(simple_index_buffer), sizeof(*simple_index_buffer)); 2430 check_materials(container->pMaterials, container->NumMaterials, NULL, 0); 2431 check_generated_effects(container->pMaterials, container->NumMaterials, container->pEffects); 2432 check_generated_adjacency(mesh, container->pAdjacency, 0.0f); 2433 hr = D3DXFrameDestroy(frame_hier, &alloc_hier); 2434 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 2435 frame_hier = NULL; 2436 } 2437 2438 controller = (ID3DXAnimationController *)0xdeadbeef; 2439 hr = D3DXLoadMeshHierarchyFromXInMemory(box_anim_xfile, sizeof(box_anim_xfile) - 1, 2440 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, &controller); 2441 todo_wine ok(hr == D3D_OK, "Expected D3D_OK, got %#x.\n", hr); 2442 if (SUCCEEDED(hr)) 2443 { 2444 ok(controller != NULL, "Animation Controller NULL.\n"); 2445 2446 hr = D3DXFrameDestroy(frame_hier, &alloc_hier); 2447 ok(hr == D3D_OK, "Expected D3D_OK, got %#x.\n", hr); 2448 if (controller) 2449 controller->lpVtbl->Release(controller); 2450 2451 frame_hier = NULL; 2452 } 2453 2454 controller = (ID3DXAnimationController *)0xdeadbeef; 2455 hr = D3DXLoadMeshHierarchyFromXInMemory(box_xfile, sizeof(box_xfile) - 1, 2456 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, &controller); 2457 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 2458 if (SUCCEEDED(hr)) 2459 { 2460 D3DXMESHCONTAINER *container = frame_hier->pMeshContainer; 2461 2462 ok(!controller, "Animation Controller returned.\n"); 2463 ok(frame_hier->Name == NULL, "Expected NULL, got '%s'\n", frame_hier->Name); 2464 D3DXMatrixIdentity(&transform); 2465 check_matrix(&frame_hier->TransformationMatrix, &transform); 2466 2467 ok(!strcmp(container->Name, ""), "Expected '', got '%s'\n", container->Name); 2468 ok(container->MeshData.Type == D3DXMESHTYPE_MESH, "Expected %d, got %d\n", 2469 D3DXMESHTYPE_MESH, container->MeshData.Type); 2470 mesh = U(container->MeshData).pMesh; 2471 check_vertex_buffer(mesh, box_vertex_buffer, ARRAY_SIZE(box_vertex_buffer), box_fvf); 2472 check_index_buffer(mesh, box_index_buffer, ARRAY_SIZE(box_index_buffer), sizeof(*box_index_buffer)); 2473 check_materials(container->pMaterials, container->NumMaterials, box_materials, ARRAY_SIZE(box_materials)); 2474 check_generated_effects(container->pMaterials, container->NumMaterials, container->pEffects); 2475 check_generated_adjacency(mesh, container->pAdjacency, 0.0f); 2476 hr = D3DXFrameDestroy(frame_hier, &alloc_hier); 2477 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 2478 frame_hier = NULL; 2479 } 2480 2481 hr = D3DXLoadMeshHierarchyFromXInMemory(framed_xfile, sizeof(framed_xfile) - 1, 2482 D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL); 2483 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 2484 if (SUCCEEDED(hr)) { 2485 D3DXMESHCONTAINER *container = frame_hier->pMeshContainer; 2486 int i; 2487 2488 ok(!strcmp(frame_hier->Name, ""), "Expected '', got '%s'\n", frame_hier->Name); 2489 /* last frame transform replaces the first */ 2490 D3DXMatrixIdentity(&transform); 2491 U(transform).m[3][2] = 3.0; 2492 check_matrix(&frame_hier->TransformationMatrix, &transform); 2493 2494 for (i = 0; i < 3; i++) { 2495 ok(!strcmp(container->Name, ""), "Expected '', got '%s'\n", container->Name); 2496 ok(container->MeshData.Type == D3DXMESHTYPE_MESH, "Expected %d, got %d\n", 2497 D3DXMESHTYPE_MESH, container->MeshData.Type); 2498 mesh = U(container->MeshData).pMesh; 2499 check_vertex_buffer(mesh, framed_vertex_buffers[i], ARRAY_SIZE(framed_vertex_buffers[0]), framed_fvf); 2500 check_index_buffer(mesh, framed_index_buffer, ARRAY_SIZE(framed_index_buffer), sizeof(*framed_index_buffer)); 2501 check_materials(container->pMaterials, container->NumMaterials, NULL, 0); 2502 check_generated_effects(container->pMaterials, container->NumMaterials, container->pEffects); 2503 check_generated_adjacency(mesh, container->pAdjacency, 0.0f); 2504 container = container->pNextMeshContainer; 2505 } 2506 ok(container == NULL, "Expected NULL, got %p\n", container); 2507 hr = D3DXFrameDestroy(frame_hier, &alloc_hier); 2508 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 2509 frame_hier = NULL; 2510 } 2511 2512 2513 hr = D3DXLoadMeshFromXInMemory(NULL, 0, D3DXMESH_MANAGED, 2514 device, NULL, NULL, NULL, NULL, &mesh); 2515 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 2516 2517 hr = D3DXLoadMeshFromXInMemory(NULL, sizeof(simple_xfile) - 1, D3DXMESH_MANAGED, 2518 device, NULL, NULL, NULL, NULL, &mesh); 2519 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 2520 2521 hr = D3DXLoadMeshFromXInMemory(simple_xfile, 0, D3DXMESH_MANAGED, 2522 device, NULL, NULL, NULL, NULL, &mesh); 2523 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 2524 2525 hr = D3DXLoadMeshFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1, D3DXMESH_MANAGED, 2526 device, NULL, NULL, NULL, NULL, NULL); 2527 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 2528 2529 hr = D3DXLoadMeshFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1, D3DXMESH_MANAGED, 2530 NULL, NULL, NULL, NULL, NULL, &mesh); 2531 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 2532 2533 hr = D3DXLoadMeshFromXInMemory(empty_xfile, sizeof(empty_xfile) - 1, D3DXMESH_MANAGED, 2534 device, NULL, NULL, NULL, NULL, &mesh); 2535 ok(hr == E_FAIL, "Expected E_FAIL, got %#x\n", hr); 2536 2537 hr = D3DXLoadMeshFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1, D3DXMESH_MANAGED, 2538 device, NULL, NULL, NULL, NULL, &mesh); 2539 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 2540 if (SUCCEEDED(hr)) 2541 IUnknown_Release(mesh); 2542 2543 test_LoadMeshFromX(device, simple_xfile, simple_vertex_buffer, simple_fvf, simple_index_buffer, default_materials, TRUE); 2544 test_LoadMeshFromX(device, box_xfile, box_vertex_buffer, box_fvf, box_index_buffer, box_materials, TRUE); 2545 test_LoadMeshFromX(device, framed_xfile, merged_vertex_buffer, framed_fvf, merged_index_buffer, default_materials, FALSE); 2546 2547 free_test_context(test_context); 2548 } 2549 2550 static BOOL compute_box(struct mesh *mesh, float width, float height, float depth) 2551 { 2552 unsigned int i, face; 2553 static const D3DXVECTOR3 unit_box[] = 2554 { 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 {-1.0f, -1.0f, 1.0f}, {-1.0f, -1.0f, -1.0f}, { 1.0f, -1.0f, -1.0f}, { 1.0f, -1.0f, 1.0f}, 2559 {-1.0f, -1.0f, 1.0f}, { 1.0f, -1.0f, 1.0f}, { 1.0f, 1.0f, 1.0f}, {-1.0f, 1.0f, 1.0f}, 2560 {-1.0f, -1.0f, -1.0f}, {-1.0f, 1.0f, -1.0f}, { 1.0f, 1.0f, -1.0f}, { 1.0f, -1.0f, -1.0f} 2561 }; 2562 static const D3DXVECTOR3 normals[] = 2563 { 2564 {-1.0f, 0.0f, 0.0f}, { 0.0f, 1.0f, 0.0f}, { 1.0f, 0.0f, 0.0f}, 2565 { 0.0f, -1.0f, 0.0f}, { 0.0f, 0.0f, 1.0f}, { 0.0f, 0.0f, -1.0f} 2566 }; 2567 2568 if (!new_mesh(mesh, 24, 12)) 2569 { 2570 return FALSE; 2571 } 2572 2573 width /= 2.0f; 2574 height /= 2.0f; 2575 depth /= 2.0f; 2576 2577 for (i = 0; i < 24; i++) 2578 { 2579 mesh->vertices[i].position.x = width * unit_box[i].x; 2580 mesh->vertices[i].position.y = height * unit_box[i].y; 2581 mesh->vertices[i].position.z = depth * unit_box[i].z; 2582 mesh->vertices[i].normal.x = normals[i / 4].x; 2583 mesh->vertices[i].normal.y = normals[i / 4].y; 2584 mesh->vertices[i].normal.z = normals[i / 4].z; 2585 } 2586 2587 face = 0; 2588 for (i = 0; i < 12; i++) 2589 { 2590 mesh->faces[i][0] = face++; 2591 mesh->faces[i][1] = face++; 2592 mesh->faces[i][2] = (i % 2) ? face - 4 : face; 2593 } 2594 2595 return TRUE; 2596 } 2597 2598 static void test_box(IDirect3DDevice9 *device, float width, float height, float depth) 2599 { 2600 HRESULT hr; 2601 ID3DXMesh *box; 2602 struct mesh mesh; 2603 char name[256]; 2604 2605 hr = D3DXCreateBox(device, width, height, depth, &box, NULL); 2606 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); 2607 if (hr != D3D_OK) 2608 { 2609 skip("Couldn't create box\n"); 2610 return; 2611 } 2612 2613 if (!compute_box(&mesh, width, height, depth)) 2614 { 2615 skip("Couldn't create mesh\n"); 2616 box->lpVtbl->Release(box); 2617 return; 2618 } 2619 2620 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL; 2621 2622 sprintf(name, "box (%g, %g, %g)", width, height, depth); 2623 compare_mesh(name, box, &mesh); 2624 2625 free_mesh(&mesh); 2626 2627 box->lpVtbl->Release(box); 2628 } 2629 static void D3DXCreateBoxTest(void) 2630 { 2631 HRESULT hr; 2632 IDirect3DDevice9* device; 2633 ID3DXMesh* box; 2634 ID3DXBuffer* ppBuffer; 2635 DWORD *buffer; 2636 static const DWORD adjacency[36]= 2637 {6, 9, 1, 2, 10, 0, 2638 1, 9, 3, 4, 10, 2, 2639 3, 8, 5, 7, 11, 4, 2640 0, 11, 7, 5, 8, 6, 2641 7, 4, 9, 2, 0, 8, 2642 1, 3, 11, 5, 6, 10}; 2643 unsigned int i; 2644 struct test_context *test_context; 2645 2646 if (!(test_context = new_test_context())) 2647 { 2648 skip("Couldn't create test context\n"); 2649 return; 2650 } 2651 device = test_context->device; 2652 2653 hr = D3DXCreateBox(device,2.0f,20.0f,4.9f,NULL, &ppBuffer); 2654 ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr); 2655 2656 hr = D3DXCreateBox(NULL,22.0f,20.0f,4.9f,&box, &ppBuffer); 2657 ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr); 2658 2659 hr = D3DXCreateBox(device,-2.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 hr = D3DXCreateBox(device,22.0f,20.0f,-4.9f,&box, &ppBuffer); 2666 ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr); 2667 2668 ppBuffer = NULL; 2669 hr = D3DXCreateBox(device,10.9f,20.0f,4.9f,&box, &ppBuffer); 2670 ok(hr==D3D_OK, "Expected D3D_OK, received %#x\n", hr); 2671 2672 buffer = ID3DXBuffer_GetBufferPointer(ppBuffer); 2673 for(i=0; i<36; i++) 2674 ok(adjacency[i]==buffer[i], "expected adjacency %d: %#x, received %#x\n",i,adjacency[i], buffer[i]); 2675 2676 box->lpVtbl->Release(box); 2677 ID3DXBuffer_Release(ppBuffer); 2678 2679 test_box(device, 10.9f, 20.0f, 4.9f); 2680 2681 free_test_context(test_context); 2682 } 2683 2684 static BOOL compute_polygon(struct mesh *mesh, float length, unsigned int sides) 2685 { 2686 unsigned int i; 2687 float angle, scale; 2688 2689 if (!new_mesh(mesh, sides + 1, sides)) 2690 return FALSE; 2691 2692 angle = D3DX_PI / sides; 2693 scale = 0.5f * length / sinf(angle); 2694 angle *= 2.0f; 2695 2696 mesh->vertices[0].position.x = 0.0f; 2697 mesh->vertices[0].position.y = 0.0f; 2698 mesh->vertices[0].position.z = 0.0f; 2699 mesh->vertices[0].normal.x = 0.0f; 2700 mesh->vertices[0].normal.y = 0.0f; 2701 mesh->vertices[0].normal.z = 1.0f; 2702 2703 for (i = 0; i < sides; ++i) 2704 { 2705 mesh->vertices[i + 1].position.x = cosf(angle * i) * scale; 2706 mesh->vertices[i + 1].position.y = sinf(angle * i) * scale; 2707 mesh->vertices[i + 1].position.z = 0.0f; 2708 mesh->vertices[i + 1].normal.x = 0.0f; 2709 mesh->vertices[i + 1].normal.y = 0.0f; 2710 mesh->vertices[i + 1].normal.z = 1.0f; 2711 2712 mesh->faces[i][0] = 0; 2713 mesh->faces[i][1] = i + 1; 2714 mesh->faces[i][2] = i + 2; 2715 } 2716 2717 mesh->faces[sides - 1][2] = 1; 2718 2719 return TRUE; 2720 } 2721 2722 static void test_polygon(IDirect3DDevice9 *device, float length, unsigned int sides) 2723 { 2724 HRESULT hr; 2725 ID3DXMesh *polygon; 2726 struct mesh mesh; 2727 char name[64]; 2728 2729 hr = D3DXCreatePolygon(device, length, sides, &polygon, NULL); 2730 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); 2731 if (hr != D3D_OK) 2732 { 2733 skip("Couldn't create polygon\n"); 2734 return; 2735 } 2736 2737 if (!compute_polygon(&mesh, length, sides)) 2738 { 2739 skip("Couldn't create mesh\n"); 2740 polygon->lpVtbl->Release(polygon); 2741 return; 2742 } 2743 2744 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL; 2745 2746 sprintf(name, "polygon (%g, %u)", length, sides); 2747 compare_mesh(name, polygon, &mesh); 2748 2749 free_mesh(&mesh); 2750 2751 polygon->lpVtbl->Release(polygon); 2752 } 2753 2754 static void D3DXCreatePolygonTest(void) 2755 { 2756 HRESULT hr; 2757 IDirect3DDevice9 *device; 2758 ID3DXMesh *polygon; 2759 ID3DXBuffer *adjacency; 2760 DWORD (*buffer)[3], buffer_size; 2761 unsigned int i; 2762 struct test_context *test_context; 2763 2764 if (!(test_context = new_test_context())) 2765 { 2766 skip("Couldn't create test context\n"); 2767 return; 2768 } 2769 device = test_context->device; 2770 2771 hr = D3DXCreatePolygon(device, 2.0f, 11, NULL, &adjacency); 2772 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr); 2773 2774 hr = D3DXCreatePolygon(NULL, 2.0f, 11, &polygon, &adjacency); 2775 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr); 2776 2777 hr = D3DXCreatePolygon(device, -2.0f, 11, &polygon, &adjacency); 2778 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr); 2779 2780 polygon = (void *)0xdeadbeef; 2781 adjacency = (void *)0xdeadbeef; 2782 hr = D3DXCreatePolygon(device, 2.0f, 0, &polygon, &adjacency); 2783 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr); 2784 ok(polygon == (void *)0xdeadbeef, "Polygon was changed to %p\n", polygon); 2785 ok(adjacency == (void *)0xdeadbeef, "Adjacency was changed to %p\n", adjacency); 2786 2787 hr = D3DXCreatePolygon(device, 2.0f, 2, &polygon, &adjacency); 2788 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr); 2789 2790 adjacency = NULL; 2791 hr = D3DXCreatePolygon(device, 3.0f, 11, &polygon, &adjacency); 2792 ok(hr == D3D_OK, "Expected D3D_OK, received %#x\n", hr); 2793 2794 buffer_size = ID3DXBuffer_GetBufferSize(adjacency); 2795 ok(buffer_size == 33 * sizeof(DWORD), "Wrong adjacency buffer size %u\n", buffer_size); 2796 2797 buffer = ID3DXBuffer_GetBufferPointer(adjacency); 2798 for (i = 0; i < 11; ++i) 2799 { 2800 ok(buffer[i][0] == (i + 10) % 11, "Wrong adjacency[%d][0] = %u\n", i, buffer[i][0]); 2801 ok(buffer[i][1] == ~0U, "Wrong adjacency[%d][1] = %u\n", i, buffer[i][1]); 2802 ok(buffer[i][2] == (i + 1) % 11, "Wrong adjacency[%d][2] = %u\n", i, buffer[i][2]); 2803 } 2804 2805 polygon->lpVtbl->Release(polygon); 2806 ID3DXBuffer_Release(adjacency); 2807 2808 test_polygon(device, 2.0f, 3); 2809 test_polygon(device, 10.0f, 3); 2810 test_polygon(device, 10.0f, 5); 2811 test_polygon(device, 10.0f, 10); 2812 test_polygon(device, 20.0f, 10); 2813 test_polygon(device, 20.0f, 32000); 2814 2815 free_test_context(test_context); 2816 } 2817 2818 struct sincos_table 2819 { 2820 float *sin; 2821 float *cos; 2822 }; 2823 2824 static void free_sincos_table(struct sincos_table *sincos_table) 2825 { 2826 HeapFree(GetProcessHeap(), 0, sincos_table->cos); 2827 HeapFree(GetProcessHeap(), 0, sincos_table->sin); 2828 } 2829 2830 /* pre compute sine and cosine tables; caller must free */ 2831 static BOOL compute_sincos_table(struct sincos_table *sincos_table, float angle_start, float angle_step, int n) 2832 { 2833 float angle; 2834 int i; 2835 2836 sincos_table->sin = HeapAlloc(GetProcessHeap(), 0, n * sizeof(*sincos_table->sin)); 2837 if (!sincos_table->sin) 2838 { 2839 return FALSE; 2840 } 2841 sincos_table->cos = HeapAlloc(GetProcessHeap(), 0, n * sizeof(*sincos_table->cos)); 2842 if (!sincos_table->cos) 2843 { 2844 HeapFree(GetProcessHeap(), 0, sincos_table->sin); 2845 return FALSE; 2846 } 2847 2848 angle = angle_start; 2849 for (i = 0; i < n; i++) 2850 { 2851 sincos_table->sin[i] = sin(angle); 2852 sincos_table->cos[i] = cos(angle); 2853 angle += angle_step; 2854 } 2855 2856 return TRUE; 2857 } 2858 2859 static WORD vertex_index(UINT slices, int slice, int stack) 2860 { 2861 return stack*slices+slice+1; 2862 } 2863 2864 /* slices = subdivisions along xy plane, stacks = subdivisions along z axis */ 2865 static BOOL compute_sphere(struct mesh *mesh, FLOAT radius, UINT slices, UINT stacks) 2866 { 2867 float theta_step, theta_start; 2868 struct sincos_table theta; 2869 float phi_step, phi_start; 2870 struct sincos_table phi; 2871 DWORD number_of_vertices, number_of_faces; 2872 DWORD vertex, face; 2873 int slice, stack; 2874 2875 /* theta = angle on xy plane wrt x axis */ 2876 theta_step = D3DX_PI / stacks; 2877 theta_start = theta_step; 2878 2879 /* phi = angle on xz plane wrt z axis */ 2880 phi_step = -2 * D3DX_PI / slices; 2881 phi_start = D3DX_PI / 2; 2882 2883 if (!compute_sincos_table(&theta, theta_start, theta_step, stacks)) 2884 { 2885 return FALSE; 2886 } 2887 if (!compute_sincos_table(&phi, phi_start, phi_step, slices)) 2888 { 2889 free_sincos_table(&theta); 2890 return FALSE; 2891 } 2892 2893 number_of_vertices = 2 + slices * (stacks-1); 2894 number_of_faces = 2 * slices + (stacks - 2) * (2 * slices); 2895 2896 if (!new_mesh(mesh, number_of_vertices, number_of_faces)) 2897 { 2898 free_sincos_table(&phi); 2899 free_sincos_table(&theta); 2900 return FALSE; 2901 } 2902 2903 vertex = 0; 2904 face = 0; 2905 2906 mesh->vertices[vertex].normal.x = 0.0f; 2907 mesh->vertices[vertex].normal.y = 0.0f; 2908 mesh->vertices[vertex].normal.z = 1.0f; 2909 mesh->vertices[vertex].position.x = 0.0f; 2910 mesh->vertices[vertex].position.y = 0.0f; 2911 mesh->vertices[vertex].position.z = radius; 2912 vertex++; 2913 2914 for (stack = 0; stack < stacks - 1; stack++) 2915 { 2916 for (slice = 0; slice < slices; slice++) 2917 { 2918 mesh->vertices[vertex].normal.x = theta.sin[stack] * phi.cos[slice]; 2919 mesh->vertices[vertex].normal.y = theta.sin[stack] * phi.sin[slice]; 2920 mesh->vertices[vertex].normal.z = theta.cos[stack]; 2921 mesh->vertices[vertex].position.x = radius * theta.sin[stack] * phi.cos[slice]; 2922 mesh->vertices[vertex].position.y = radius * theta.sin[stack] * phi.sin[slice]; 2923 mesh->vertices[vertex].position.z = radius * theta.cos[stack]; 2924 vertex++; 2925 2926 if (slice > 0) 2927 { 2928 if (stack == 0) 2929 { 2930 /* top stack is triangle fan */ 2931 mesh->faces[face][0] = 0; 2932 mesh->faces[face][1] = slice + 1; 2933 mesh->faces[face][2] = slice; 2934 face++; 2935 } 2936 else 2937 { 2938 /* stacks in between top and bottom are quad strips */ 2939 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1); 2940 mesh->faces[face][1] = vertex_index(slices, slice, stack-1); 2941 mesh->faces[face][2] = vertex_index(slices, slice-1, stack); 2942 face++; 2943 2944 mesh->faces[face][0] = vertex_index(slices, slice, stack-1); 2945 mesh->faces[face][1] = vertex_index(slices, slice, stack); 2946 mesh->faces[face][2] = vertex_index(slices, slice-1, stack); 2947 face++; 2948 } 2949 } 2950 } 2951 2952 if (stack == 0) 2953 { 2954 mesh->faces[face][0] = 0; 2955 mesh->faces[face][1] = 1; 2956 mesh->faces[face][2] = slice; 2957 face++; 2958 } 2959 else 2960 { 2961 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1); 2962 mesh->faces[face][1] = vertex_index(slices, 0, stack-1); 2963 mesh->faces[face][2] = vertex_index(slices, slice-1, stack); 2964 face++; 2965 2966 mesh->faces[face][0] = vertex_index(slices, 0, stack-1); 2967 mesh->faces[face][1] = vertex_index(slices, 0, stack); 2968 mesh->faces[face][2] = vertex_index(slices, slice-1, stack); 2969 face++; 2970 } 2971 } 2972 2973 mesh->vertices[vertex].position.x = 0.0f; 2974 mesh->vertices[vertex].position.y = 0.0f; 2975 mesh->vertices[vertex].position.z = -radius; 2976 mesh->vertices[vertex].normal.x = 0.0f; 2977 mesh->vertices[vertex].normal.y = 0.0f; 2978 mesh->vertices[vertex].normal.z = -1.0f; 2979 2980 /* bottom stack is triangle fan */ 2981 for (slice = 1; slice < slices; slice++) 2982 { 2983 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1); 2984 mesh->faces[face][1] = vertex_index(slices, slice, stack-1); 2985 mesh->faces[face][2] = vertex; 2986 face++; 2987 } 2988 2989 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1); 2990 mesh->faces[face][1] = vertex_index(slices, 0, stack-1); 2991 mesh->faces[face][2] = vertex; 2992 2993 free_sincos_table(&phi); 2994 free_sincos_table(&theta); 2995 2996 return TRUE; 2997 } 2998 2999 static void test_sphere(IDirect3DDevice9 *device, FLOAT radius, UINT slices, UINT stacks) 3000 { 3001 HRESULT hr; 3002 ID3DXMesh *sphere; 3003 struct mesh mesh; 3004 char name[256]; 3005 3006 hr = D3DXCreateSphere(device, radius, slices, stacks, &sphere, NULL); 3007 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); 3008 if (hr != D3D_OK) 3009 { 3010 skip("Couldn't create sphere\n"); 3011 return; 3012 } 3013 3014 if (!compute_sphere(&mesh, radius, slices, stacks)) 3015 { 3016 skip("Couldn't create mesh\n"); 3017 sphere->lpVtbl->Release(sphere); 3018 return; 3019 } 3020 3021 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL; 3022 3023 sprintf(name, "sphere (%g, %u, %u)", radius, slices, stacks); 3024 compare_mesh(name, sphere, &mesh); 3025 3026 free_mesh(&mesh); 3027 3028 sphere->lpVtbl->Release(sphere); 3029 } 3030 3031 static void D3DXCreateSphereTest(void) 3032 { 3033 HRESULT hr; 3034 IDirect3DDevice9* device; 3035 ID3DXMesh* sphere = NULL; 3036 struct test_context *test_context; 3037 3038 hr = D3DXCreateSphere(NULL, 0.0f, 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.1f, 0, 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, 1, 0, NULL, NULL); 3045 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL); 3046 3047 hr = D3DXCreateSphere(NULL, 0.0f, 0, 1, NULL, NULL); 3048 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL); 3049 3050 if (!(test_context = new_test_context())) 3051 { 3052 skip("Couldn't create test context\n"); 3053 return; 3054 } 3055 device = test_context->device; 3056 3057 hr = D3DXCreateSphere(device, 1.0f, 1, 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, 2, 1, &sphere, NULL); 3061 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 3062 3063 hr = D3DXCreateSphere(device, 1.0f, 1, 2, &sphere, NULL); 3064 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 3065 3066 hr = D3DXCreateSphere(device, -0.1f, 1, 2, &sphere, NULL); 3067 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 3068 3069 test_sphere(device, 0.0f, 2, 2); 3070 test_sphere(device, 1.0f, 2, 2); 3071 test_sphere(device, 1.0f, 3, 2); 3072 test_sphere(device, 1.0f, 4, 4); 3073 test_sphere(device, 1.0f, 3, 4); 3074 test_sphere(device, 5.0f, 6, 7); 3075 test_sphere(device, 10.0f, 11, 12); 3076 3077 free_test_context(test_context); 3078 } 3079 3080 static BOOL compute_cylinder(struct mesh *mesh, FLOAT radius1, FLOAT radius2, FLOAT length, UINT slices, UINT stacks) 3081 { 3082 float theta_step, theta_start; 3083 struct sincos_table theta; 3084 FLOAT delta_radius, radius, radius_step; 3085 FLOAT z, z_step, z_normal; 3086 DWORD number_of_vertices, number_of_faces; 3087 DWORD vertex, face; 3088 int slice, stack; 3089 3090 /* theta = angle on xy plane wrt x axis */ 3091 theta_step = -2 * D3DX_PI / slices; 3092 theta_start = D3DX_PI / 2; 3093 3094 if (!compute_sincos_table(&theta, theta_start, theta_step, slices)) 3095 { 3096 return FALSE; 3097 } 3098 3099 number_of_vertices = 2 + (slices * (3 + stacks)); 3100 number_of_faces = 2 * slices + stacks * (2 * slices); 3101 3102 if (!new_mesh(mesh, number_of_vertices, number_of_faces)) 3103 { 3104 free_sincos_table(&theta); 3105 return FALSE; 3106 } 3107 3108 vertex = 0; 3109 face = 0; 3110 3111 delta_radius = radius1 - radius2; 3112 radius = radius1; 3113 radius_step = delta_radius / stacks; 3114 3115 z = -length / 2; 3116 z_step = length / stacks; 3117 z_normal = delta_radius / length; 3118 if (isnan(z_normal)) 3119 { 3120 z_normal = 0.0f; 3121 } 3122 3123 mesh->vertices[vertex].normal.x = 0.0f; 3124 mesh->vertices[vertex].normal.y = 0.0f; 3125 mesh->vertices[vertex].normal.z = -1.0f; 3126 mesh->vertices[vertex].position.x = 0.0f; 3127 mesh->vertices[vertex].position.y = 0.0f; 3128 mesh->vertices[vertex++].position.z = z; 3129 3130 for (slice = 0; slice < slices; slice++, vertex++) 3131 { 3132 mesh->vertices[vertex].normal.x = 0.0f; 3133 mesh->vertices[vertex].normal.y = 0.0f; 3134 mesh->vertices[vertex].normal.z = -1.0f; 3135 mesh->vertices[vertex].position.x = radius * theta.cos[slice]; 3136 mesh->vertices[vertex].position.y = radius * theta.sin[slice]; 3137 mesh->vertices[vertex].position.z = z; 3138 3139 if (slice > 0) 3140 { 3141 mesh->faces[face][0] = 0; 3142 mesh->faces[face][1] = slice; 3143 mesh->faces[face++][2] = slice + 1; 3144 } 3145 } 3146 3147 mesh->faces[face][0] = 0; 3148 mesh->faces[face][1] = slice; 3149 mesh->faces[face++][2] = 1; 3150 3151 for (stack = 1; stack <= stacks+1; stack++) 3152 { 3153 for (slice = 0; slice < slices; slice++, vertex++) 3154 { 3155 mesh->vertices[vertex].normal.x = theta.cos[slice]; 3156 mesh->vertices[vertex].normal.y = theta.sin[slice]; 3157 mesh->vertices[vertex].normal.z = z_normal; 3158 D3DXVec3Normalize(&mesh->vertices[vertex].normal, &mesh->vertices[vertex].normal); 3159 mesh->vertices[vertex].position.x = radius * theta.cos[slice]; 3160 mesh->vertices[vertex].position.y = radius * theta.sin[slice]; 3161 mesh->vertices[vertex].position.z = z; 3162 3163 if (stack > 1 && slice > 0) 3164 { 3165 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1); 3166 mesh->faces[face][1] = vertex_index(slices, slice-1, stack); 3167 mesh->faces[face++][2] = vertex_index(slices, slice, stack-1); 3168 3169 mesh->faces[face][0] = vertex_index(slices, slice, stack-1); 3170 mesh->faces[face][1] = vertex_index(slices, slice-1, stack); 3171 mesh->faces[face++][2] = vertex_index(slices, slice, stack); 3172 } 3173 } 3174 3175 if (stack > 1) 3176 { 3177 mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1); 3178 mesh->faces[face][1] = vertex_index(slices, slice-1, stack); 3179 mesh->faces[face++][2] = vertex_index(slices, 0, stack-1); 3180 3181 mesh->faces[face][0] = vertex_index(slices, 0, stack-1); 3182 mesh->faces[face][1] = vertex_index(slices, slice-1, stack); 3183 mesh->faces[face++][2] = vertex_index(slices, 0, stack); 3184 } 3185 3186 if (stack < stacks + 1) 3187 { 3188 z += z_step; 3189 radius -= radius_step; 3190 } 3191 } 3192 3193 for (slice = 0; slice < slices; slice++, vertex++) 3194 { 3195 mesh->vertices[vertex].normal.x = 0.0f; 3196 mesh->vertices[vertex].normal.y = 0.0f; 3197 mesh->vertices[vertex].normal.z = 1.0f; 3198 mesh->vertices[vertex].position.x = radius * theta.cos[slice]; 3199 mesh->vertices[vertex].position.y = radius * theta.sin[slice]; 3200 mesh->vertices[vertex].position.z = z; 3201 3202 if (slice > 0) 3203 { 3204 mesh->faces[face][0] = vertex_index(slices, slice-1, stack); 3205 mesh->faces[face][1] = number_of_vertices - 1; 3206 mesh->faces[face++][2] = vertex_index(slices, slice, stack); 3207 } 3208 } 3209 3210 mesh->vertices[vertex].position.x = 0.0f; 3211 mesh->vertices[vertex].position.y = 0.0f; 3212 mesh->vertices[vertex].position.z = z; 3213 mesh->vertices[vertex].normal.x = 0.0f; 3214 mesh->vertices[vertex].normal.y = 0.0f; 3215 mesh->vertices[vertex].normal.z = 1.0f; 3216 3217 mesh->faces[face][0] = vertex_index(slices, slice-1, stack); 3218 mesh->faces[face][1] = number_of_vertices - 1; 3219 mesh->faces[face][2] = vertex_index(slices, 0, stack); 3220 3221 free_sincos_table(&theta); 3222 3223 return TRUE; 3224 } 3225 3226 static void test_cylinder(IDirect3DDevice9 *device, FLOAT radius1, FLOAT radius2, FLOAT length, UINT slices, UINT stacks) 3227 { 3228 HRESULT hr; 3229 ID3DXMesh *cylinder; 3230 struct mesh mesh; 3231 char name[256]; 3232 3233 hr = D3DXCreateCylinder(device, radius1, radius2, length, slices, stacks, &cylinder, NULL); 3234 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); 3235 if (hr != D3D_OK) 3236 { 3237 skip("Couldn't create cylinder\n"); 3238 return; 3239 } 3240 3241 if (!compute_cylinder(&mesh, radius1, radius2, length, slices, stacks)) 3242 { 3243 skip("Couldn't create mesh\n"); 3244 cylinder->lpVtbl->Release(cylinder); 3245 return; 3246 } 3247 3248 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL; 3249 3250 sprintf(name, "cylinder (%g, %g, %g, %u, %u)", radius1, radius2, length, slices, stacks); 3251 compare_mesh(name, cylinder, &mesh); 3252 3253 free_mesh(&mesh); 3254 3255 cylinder->lpVtbl->Release(cylinder); 3256 } 3257 3258 static void D3DXCreateCylinderTest(void) 3259 { 3260 HRESULT hr; 3261 IDirect3DDevice9* device; 3262 ID3DXMesh* cylinder = NULL; 3263 struct test_context *test_context; 3264 3265 hr = D3DXCreateCylinder(NULL, 0.0f, 0.0f, 0.0f, 0, 0, NULL, NULL); 3266 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL); 3267 3268 hr = D3DXCreateCylinder(NULL, 1.0f, 1.0f, 1.0f, 2, 1, &cylinder, NULL); 3269 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL); 3270 3271 if (!(test_context = new_test_context())) 3272 { 3273 skip("Couldn't create test context\n"); 3274 return; 3275 } 3276 device = test_context->device; 3277 3278 hr = D3DXCreateCylinder(device, -0.1f, 1.0f, 1.0f, 2, 1, &cylinder, NULL); 3279 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL); 3280 3281 hr = D3DXCreateCylinder(device, 0.0f, 1.0f, 1.0f, 2, 1, &cylinder, NULL); 3282 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n",hr); 3283 3284 if (SUCCEEDED(hr) && cylinder) 3285 { 3286 cylinder->lpVtbl->Release(cylinder); 3287 } 3288 3289 hr = D3DXCreateCylinder(device, 1.0f, -0.1f, 1.0f, 2, 1, &cylinder, NULL); 3290 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL); 3291 3292 hr = D3DXCreateCylinder(device, 1.0f, 0.0f, 1.0f, 2, 1, &cylinder, NULL); 3293 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n",hr); 3294 3295 if (SUCCEEDED(hr) && cylinder) 3296 { 3297 cylinder->lpVtbl->Release(cylinder); 3298 } 3299 3300 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, -0.1f, 2, 1, &cylinder, NULL); 3301 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL); 3302 3303 /* Test with length == 0.0f succeeds */ 3304 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, 0.0f, 2, 1, &cylinder, NULL); 3305 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n",hr); 3306 3307 if (SUCCEEDED(hr) && cylinder) 3308 { 3309 cylinder->lpVtbl->Release(cylinder); 3310 } 3311 3312 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, 1.0f, 1, 1, &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, 0, &cylinder, NULL); 3316 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL); 3317 3318 hr = D3DXCreateCylinder(device, 1.0f, 1.0f, 1.0f, 2, 1, NULL, NULL); 3319 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL); 3320 3321 test_cylinder(device, 0.0f, 0.0f, 0.0f, 2, 1); 3322 test_cylinder(device, 1.0f, 1.0f, 1.0f, 2, 1); 3323 test_cylinder(device, 1.0f, 1.0f, 2.0f, 3, 4); 3324 test_cylinder(device, 3.0f, 2.0f, 4.0f, 3, 4); 3325 test_cylinder(device, 2.0f, 3.0f, 4.0f, 3, 4); 3326 test_cylinder(device, 3.0f, 4.0f, 5.0f, 11, 20); 3327 3328 free_test_context(test_context); 3329 } 3330 3331 static BOOL compute_torus(struct mesh *mesh, float innerradius, float outerradius, UINT sides, UINT rings) 3332 { 3333 float phi, phi_step, sin_phi, cos_phi; 3334 float theta, theta_step, sin_theta, cos_theta; 3335 unsigned int numvert, numfaces, i, j; 3336 3337 numvert = sides * rings; 3338 numfaces = numvert * 2; 3339 3340 if (!new_mesh(mesh, numvert, numfaces)) 3341 return FALSE; 3342 3343 phi_step = D3DX_PI / sides * 2.0f; 3344 theta_step = D3DX_PI / rings * -2.0f; 3345 3346 theta = 0.0f; 3347 3348 for (i = 0; i < rings; ++i) 3349 { 3350 phi = 0.0f; 3351 3352 cos_theta = cosf(theta); 3353 sin_theta = sinf(theta); 3354 3355 for (j = 0; j < sides; ++j) 3356 { 3357 sin_phi = sinf(phi); 3358 cos_phi = cosf(phi); 3359 3360 mesh->vertices[i * sides + j].position.x = (innerradius * cos_phi + outerradius) * cos_theta; 3361 mesh->vertices[i * sides + j].position.y = (innerradius * cos_phi + outerradius) * sin_theta; 3362 mesh->vertices[i * sides + j].position.z = innerradius * sin_phi; 3363 mesh->vertices[i * sides + j].normal.x = cos_phi * cos_theta; 3364 mesh->vertices[i * sides + j].normal.y = cos_phi * sin_theta; 3365 mesh->vertices[i * sides + j].normal.z = sin_phi; 3366 3367 phi += phi_step; 3368 } 3369 3370 theta += theta_step; 3371 } 3372 3373 for (i = 0; i < numfaces - sides * 2; ++i) 3374 { 3375 mesh->faces[i][0] = i % 2 ? i / 2 + sides : i / 2; 3376 mesh->faces[i][1] = (i / 2 + 1) % sides ? i / 2 + 1 : i / 2 + 1 - sides; 3377 mesh->faces[i][2] = (i + 1) % (sides * 2) ? (i + 1) / 2 + sides : (i + 1) / 2; 3378 } 3379 3380 for (j = 0; i < numfaces; ++i, ++j) 3381 { 3382 mesh->faces[i][0] = i % 2 ? j / 2 : i / 2; 3383 mesh->faces[i][1] = (i / 2 + 1) % sides ? i / 2 + 1 : i / 2 + 1 - sides; 3384 mesh->faces[i][2] = i == numfaces - 1 ? 0 : (j + 1) / 2; 3385 } 3386 3387 return TRUE; 3388 } 3389 3390 static void test_torus(IDirect3DDevice9 *device, float innerradius, float outerradius, UINT sides, UINT rings) 3391 { 3392 HRESULT hr; 3393 ID3DXMesh *torus; 3394 struct mesh mesh; 3395 char name[256]; 3396 3397 hr = D3DXCreateTorus(device, innerradius, outerradius, sides, rings, &torus, NULL); 3398 ok(hr == D3D_OK, "Got result %#x, expected 0 (D3D_OK)\n", hr); 3399 if (hr != D3D_OK) 3400 { 3401 skip("Couldn't create torus\n"); 3402 return; 3403 } 3404 3405 if (!compute_torus(&mesh, innerradius, outerradius, sides, rings)) 3406 { 3407 skip("Couldn't create mesh\n"); 3408 torus->lpVtbl->Release(torus); 3409 return; 3410 } 3411 3412 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL; 3413 3414 sprintf(name, "torus (%g, %g, %u, %u)", innerradius, outerradius, sides, rings); 3415 compare_mesh(name, torus, &mesh); 3416 3417 free_mesh(&mesh); 3418 3419 torus->lpVtbl->Release(torus); 3420 } 3421 3422 static void D3DXCreateTorusTest(void) 3423 { 3424 HRESULT hr; 3425 IDirect3DDevice9* device; 3426 ID3DXMesh* torus = NULL; 3427 struct test_context *test_context; 3428 3429 if (!(test_context = new_test_context())) 3430 { 3431 skip("Couldn't create test context\n"); 3432 return; 3433 } 3434 device = test_context->device; 3435 3436 hr = D3DXCreateTorus(NULL, 0.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, -1.0f, 0.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, -1.0f, 3, 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, 2, 3, &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, 2, &torus, NULL); 3449 ok(hr == D3DERR_INVALIDCALL, "Got result %#x, expected %#x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 3450 3451 hr = D3DXCreateTorus(device, 0.0f, 0.0f, 3, 3, NULL, NULL); 3452 ok(hr == D3DERR_INVALIDCALL, "Got result %#x, expected %#x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 3453 3454 test_torus(device, 0.0f, 0.0f, 3, 3); 3455 test_torus(device, 1.0f, 1.0f, 3, 3); 3456 test_torus(device, 1.0f, 1.0f, 32, 64); 3457 test_torus(device, 0.0f, 1.0f, 5, 5); 3458 test_torus(device, 1.0f, 0.0f, 5, 5); 3459 test_torus(device, 5.0f, 0.2f, 8, 8); 3460 test_torus(device, 0.2f, 1.0f, 60, 3); 3461 test_torus(device, 0.2f, 1.0f, 8, 70); 3462 3463 free_test_context(test_context); 3464 } 3465 3466 struct dynamic_array 3467 { 3468 int count, capacity; 3469 void *items; 3470 }; 3471 3472 enum pointtype { 3473 POINTTYPE_CURVE = 0, 3474 POINTTYPE_CORNER, 3475 POINTTYPE_CURVE_START, 3476 POINTTYPE_CURVE_END, 3477 POINTTYPE_CURVE_MIDDLE, 3478 }; 3479 3480 struct point2d 3481 { 3482 D3DXVECTOR2 pos; 3483 enum pointtype corner; 3484 }; 3485 3486 /* is a dynamic_array */ 3487 struct outline 3488 { 3489 int count, capacity; 3490 struct point2d *items; 3491 }; 3492 3493 /* is a dynamic_array */ 3494 struct outline_array 3495 { 3496 int count, capacity; 3497 struct outline *items; 3498 }; 3499 3500 struct glyphinfo 3501 { 3502 struct outline_array outlines; 3503 float offset_x; 3504 }; 3505 3506 static BOOL reserve(struct dynamic_array *array, int count, int itemsize) 3507 { 3508 if (count > array->capacity) { 3509 void *new_buffer; 3510 int new_capacity; 3511 if (array->items && array->capacity) { 3512 new_capacity = max(array->capacity * 2, count); 3513 new_buffer = HeapReAlloc(GetProcessHeap(), 0, array->items, new_capacity * itemsize); 3514 } else { 3515 new_capacity = max(16, count); 3516 new_buffer = HeapAlloc(GetProcessHeap(), 0, new_capacity * itemsize); 3517 } 3518 if (!new_buffer) 3519 return FALSE; 3520 array->items = new_buffer; 3521 array->capacity = new_capacity; 3522 } 3523 return TRUE; 3524 } 3525 3526 static struct point2d *add_point(struct outline *array) 3527 { 3528 struct point2d *item; 3529 3530 if (!reserve((struct dynamic_array *)array, array->count + 1, sizeof(array->items[0]))) 3531 return NULL; 3532 3533 item = &array->items[array->count++]; 3534 ZeroMemory(item, sizeof(*item)); 3535 return item; 3536 } 3537 3538 static struct outline *add_outline(struct outline_array *array) 3539 { 3540 struct outline *item; 3541 3542 if (!reserve((struct dynamic_array *)array, array->count + 1, sizeof(array->items[0]))) 3543 return NULL; 3544 3545 item = &array->items[array->count++]; 3546 ZeroMemory(item, sizeof(*item)); 3547 return item; 3548 } 3549 3550 static inline D3DXVECTOR2 *convert_fixed_to_float(POINTFX *pt, int count, float emsquare) 3551 { 3552 D3DXVECTOR2 *ret = (D3DXVECTOR2*)pt; 3553 while (count--) { 3554 D3DXVECTOR2 *pt_flt = (D3DXVECTOR2*)pt; 3555 pt_flt->x = (pt->x.value + pt->x.fract / (float)0x10000) / emsquare; 3556 pt_flt->y = (pt->y.value + pt->y.fract / (float)0x10000) / emsquare; 3557 pt++; 3558 } 3559 return ret; 3560 } 3561 3562 static HRESULT add_bezier_points(struct outline *outline, const D3DXVECTOR2 *p1, 3563 const D3DXVECTOR2 *p2, const D3DXVECTOR2 *p3, 3564 float max_deviation) 3565 { 3566 D3DXVECTOR2 split1 = {0, 0}, split2 = {0, 0}, middle, vec; 3567 float deviation; 3568 3569 D3DXVec2Scale(&split1, D3DXVec2Add(&split1, p1, p2), 0.5f); 3570 D3DXVec2Scale(&split2, D3DXVec2Add(&split2, p2, p3), 0.5f); 3571 D3DXVec2Scale(&middle, D3DXVec2Add(&middle, &split1, &split2), 0.5f); 3572 3573 deviation = D3DXVec2Length(D3DXVec2Subtract(&vec, &middle, p2)); 3574 if (deviation < max_deviation) { 3575 struct point2d *pt = add_point(outline); 3576 if (!pt) return E_OUTOFMEMORY; 3577 pt->pos = *p2; 3578 pt->corner = POINTTYPE_CURVE; 3579 /* the end point is omitted because the end line merges into the next segment of 3580 * the split bezier curve, and the end of the split bezier curve is added outside 3581 * this recursive function. */ 3582 } else { 3583 HRESULT hr = add_bezier_points(outline, p1, &split1, &middle, max_deviation); 3584 if (hr != S_OK) return hr; 3585 hr = add_bezier_points(outline, &middle, &split2, p3, max_deviation); 3586 if (hr != S_OK) return hr; 3587 } 3588 3589 return S_OK; 3590 } 3591 3592 static inline BOOL is_direction_similar(D3DXVECTOR2 *dir1, D3DXVECTOR2 *dir2, float cos_theta) 3593 { 3594 /* dot product = cos(theta) */ 3595 return D3DXVec2Dot(dir1, dir2) > cos_theta; 3596 } 3597 3598 static inline D3DXVECTOR2 *unit_vec2(D3DXVECTOR2 *dir, const D3DXVECTOR2 *pt1, const D3DXVECTOR2 *pt2) 3599 { 3600 return D3DXVec2Normalize(D3DXVec2Subtract(dir, pt2, pt1), dir); 3601 } 3602 3603 static BOOL attempt_line_merge(struct outline *outline, 3604 int pt_index, 3605 const D3DXVECTOR2 *nextpt, 3606 BOOL to_curve) 3607 { 3608 D3DXVECTOR2 curdir, lastdir; 3609 struct point2d *prevpt, *pt; 3610 BOOL ret = FALSE; 3611 const float cos_half = cos(D3DXToRadian(0.5f)); 3612 3613 pt = &outline->items[pt_index]; 3614 pt_index = (pt_index - 1 + outline->count) % outline->count; 3615 prevpt = &outline->items[pt_index]; 3616 3617 if (to_curve) 3618 pt->corner = pt->corner != POINTTYPE_CORNER ? POINTTYPE_CURVE_MIDDLE : POINTTYPE_CURVE_START; 3619 3620 if (outline->count < 2) 3621 return FALSE; 3622 3623 /* remove last point if the next line continues the last line */ 3624 unit_vec2(&lastdir, &prevpt->pos, &pt->pos); 3625 unit_vec2(&curdir, &pt->pos, nextpt); 3626 if (is_direction_similar(&lastdir, &curdir, cos_half)) 3627 { 3628 outline->count--; 3629 if (pt->corner == POINTTYPE_CURVE_END) 3630 prevpt->corner = pt->corner; 3631 if (prevpt->corner == POINTTYPE_CURVE_END && to_curve) 3632 prevpt->corner = POINTTYPE_CURVE_MIDDLE; 3633 pt = prevpt; 3634 3635 ret = TRUE; 3636 if (outline->count < 2) 3637 return ret; 3638 3639 pt_index = (pt_index - 1 + outline->count) % outline->count; 3640 prevpt = &outline->items[pt_index]; 3641 unit_vec2(&lastdir, &prevpt->pos, &pt->pos); 3642 unit_vec2(&curdir, &pt->pos, nextpt); 3643 } 3644 return ret; 3645 } 3646 3647 static HRESULT create_outline(struct glyphinfo *glyph, void *raw_outline, int datasize, 3648 float max_deviation, float emsquare) 3649 { 3650 const float cos_45 = cos(D3DXToRadian(45.0f)); 3651 const float cos_90 = cos(D3DXToRadian(90.0f)); 3652 TTPOLYGONHEADER *header = (TTPOLYGONHEADER *)raw_outline; 3653 3654 while ((char *)header < (char *)raw_outline + datasize) 3655 { 3656 TTPOLYCURVE *curve = (TTPOLYCURVE *)(header + 1); 3657 struct point2d *lastpt, *pt; 3658 D3DXVECTOR2 lastdir; 3659 D3DXVECTOR2 *pt_flt; 3660 int j; 3661 struct outline *outline = add_outline(&glyph->outlines); 3662 3663 if (!outline) 3664 return E_OUTOFMEMORY; 3665 3666 pt = add_point(outline); 3667 if (!pt) 3668 return E_OUTOFMEMORY; 3669 pt_flt = convert_fixed_to_float(&header->pfxStart, 1, emsquare); 3670 pt->pos = *pt_flt; 3671 pt->corner = POINTTYPE_CORNER; 3672 3673 if (header->dwType != TT_POLYGON_TYPE) 3674 trace("Unknown header type %d\n", header->dwType); 3675 3676 while ((char *)curve < (char *)header + header->cb) 3677 { 3678 D3DXVECTOR2 bezier_start = outline->items[outline->count - 1].pos; 3679 BOOL to_curve = curve->wType != TT_PRIM_LINE && curve->cpfx > 1; 3680 3681 if (!curve->cpfx) { 3682 curve = (TTPOLYCURVE *)&curve->apfx[curve->cpfx]; 3683 continue; 3684 } 3685 3686 pt_flt = convert_fixed_to_float(curve->apfx, curve->cpfx, emsquare); 3687 3688 attempt_line_merge(outline, outline->count - 1, &pt_flt[0], to_curve); 3689 3690 if (to_curve) 3691 { 3692 HRESULT hr; 3693 int count = curve->cpfx; 3694 j = 0; 3695 3696 while (count > 2) 3697 { 3698 D3DXVECTOR2 bezier_end; 3699 3700 D3DXVec2Scale(&bezier_end, D3DXVec2Add(&bezier_end, &pt_flt[j], &pt_flt[j+1]), 0.5f); 3701 hr = add_bezier_points(outline, &bezier_start, &pt_flt[j], &bezier_end, max_deviation); 3702 if (hr != S_OK) 3703 return hr; 3704 bezier_start = bezier_end; 3705 count--; 3706 j++; 3707 } 3708 hr = add_bezier_points(outline, &bezier_start, &pt_flt[j], &pt_flt[j+1], max_deviation); 3709 if (hr != S_OK) 3710 return hr; 3711 3712 pt = add_point(outline); 3713 if (!pt) 3714 return E_OUTOFMEMORY; 3715 j++; 3716 pt->pos = pt_flt[j]; 3717 pt->corner = POINTTYPE_CURVE_END; 3718 } else { 3719 for (j = 0; j < curve->cpfx; j++) 3720 { 3721 pt = add_point(outline); 3722 if (!pt) 3723 return E_OUTOFMEMORY; 3724 pt->pos = pt_flt[j]; 3725 pt->corner = POINTTYPE_CORNER; 3726 } 3727 } 3728 3729 curve = (TTPOLYCURVE *)&curve->apfx[curve->cpfx]; 3730 } 3731 3732 /* remove last point if the next line continues the last line */ 3733 if (outline->count >= 3) { 3734 BOOL to_curve; 3735 3736 lastpt = &outline->items[outline->count - 1]; 3737 pt = &outline->items[0]; 3738 if (pt->pos.x == lastpt->pos.x && pt->pos.y == lastpt->pos.y) { 3739 if (lastpt->corner == POINTTYPE_CURVE_END) 3740 { 3741 if (pt->corner == POINTTYPE_CURVE_START) 3742 pt->corner = POINTTYPE_CURVE_MIDDLE; 3743 else 3744 pt->corner = POINTTYPE_CURVE_END; 3745 } 3746 outline->count--; 3747 } else { 3748 /* outline closed with a line from end to start point */ 3749 attempt_line_merge(outline, outline->count - 1, &pt->pos, FALSE); 3750 } 3751 lastpt = &outline->items[0]; 3752 to_curve = lastpt->corner != POINTTYPE_CORNER && lastpt->corner != POINTTYPE_CURVE_END; 3753 if (lastpt->corner == POINTTYPE_CURVE_START) 3754 lastpt->corner = POINTTYPE_CORNER; 3755 pt = &outline->items[1]; 3756 if (attempt_line_merge(outline, 0, &pt->pos, to_curve)) 3757 *lastpt = outline->items[outline->count]; 3758 } 3759 3760 lastpt = &outline->items[outline->count - 1]; 3761 pt = &outline->items[0]; 3762 unit_vec2(&lastdir, &lastpt->pos, &pt->pos); 3763 for (j = 0; j < outline->count; j++) 3764 { 3765 D3DXVECTOR2 curdir; 3766 3767 lastpt = pt; 3768 pt = &outline->items[(j + 1) % outline->count]; 3769 unit_vec2(&curdir, &lastpt->pos, &pt->pos); 3770 3771 switch (lastpt->corner) 3772 { 3773 case POINTTYPE_CURVE_START: 3774 case POINTTYPE_CURVE_END: 3775 if (!is_direction_similar(&lastdir, &curdir, cos_45)) 3776 lastpt->corner = POINTTYPE_CORNER; 3777 break; 3778 case POINTTYPE_CURVE_MIDDLE: 3779 if (!is_direction_similar(&lastdir, &curdir, cos_90)) 3780 lastpt->corner = POINTTYPE_CORNER; 3781 else 3782 lastpt->corner = POINTTYPE_CURVE; 3783 break; 3784 default: 3785 break; 3786 } 3787 lastdir = curdir; 3788 } 3789 3790 header = (TTPOLYGONHEADER *)((char *)header + header->cb); 3791 } 3792 return S_OK; 3793 } 3794 3795 static void free_outline(struct outline *outline) 3796 { 3797 HeapFree(GetProcessHeap(), 0, outline->items); 3798 } 3799 3800 static void free_glyphinfo(struct glyphinfo *glyph) 3801 { 3802 unsigned int i; 3803 3804 for (i = 0; i < glyph->outlines.count; ++i) 3805 free_outline(&glyph->outlines.items[i]); 3806 HeapFree(GetProcessHeap(), 0, glyph->outlines.items); 3807 } 3808 3809 static void compute_text_mesh(struct mesh *mesh, const char *text, 3810 float deviation, float extrusion, float otmEMSquare, const struct glyphinfo *glyphs) 3811 { 3812 DWORD nb_vertices, nb_faces; 3813 DWORD nb_corners, nb_outline_points; 3814 int textlen = 0; 3815 int i; 3816 struct vertex *vertex_ptr; 3817 face *face_ptr; 3818 3819 textlen = strlen(text); 3820 3821 /* corner points need an extra vertex for the different side faces normals */ 3822 nb_corners = 0; 3823 nb_outline_points = 0; 3824 for (i = 0; i < textlen; i++) 3825 { 3826 int j; 3827 for (j = 0; j < glyphs[i].outlines.count; j++) 3828 { 3829 int k; 3830 struct outline *outline = &glyphs[i].outlines.items[j]; 3831 nb_outline_points += outline->count; 3832 nb_corners++; /* first outline point always repeated as a corner */ 3833 for (k = 1; k < outline->count; k++) 3834 if (outline->items[k].corner) 3835 nb_corners++; 3836 } 3837 } 3838 3839 nb_vertices = (nb_outline_points + nb_corners) * 2 + textlen; 3840 nb_faces = nb_outline_points * 2; 3841 3842 ok(new_mesh(mesh, nb_vertices, nb_faces), "Failed to create reference text mesh.\n"); 3843 3844 /* convert 2D vertices and faces into 3D mesh */ 3845 vertex_ptr = mesh->vertices; 3846 face_ptr = mesh->faces; 3847 for (i = 0; i < textlen; i++) 3848 { 3849 int j; 3850 3851 /* side vertices and faces */ 3852 for (j = 0; j < glyphs[i].outlines.count; j++) 3853 { 3854 struct vertex *outline_vertices = vertex_ptr; 3855 struct outline *outline = &glyphs[i].outlines.items[j]; 3856 int k; 3857 struct point2d *prevpt = &outline->items[outline->count - 1]; 3858 struct point2d *pt = &outline->items[0]; 3859 3860 for (k = 1; k <= outline->count; k++) 3861 { 3862 struct vertex vtx; 3863 struct point2d *nextpt = &outline->items[k % outline->count]; 3864 WORD vtx_idx = vertex_ptr - mesh->vertices; 3865 D3DXVECTOR2 vec; 3866 3867 if (pt->corner == POINTTYPE_CURVE_START) 3868 D3DXVec2Subtract(&vec, &pt->pos, &prevpt->pos); 3869 else if (pt->corner) 3870 D3DXVec2Subtract(&vec, &nextpt->pos, &pt->pos); 3871 else 3872 D3DXVec2Subtract(&vec, &nextpt->pos, &prevpt->pos); 3873 D3DXVec2Normalize(&vec, &vec); 3874 vtx.normal.x = -vec.y; 3875 vtx.normal.y = vec.x; 3876 vtx.normal.z = 0; 3877 3878 vtx.position.x = pt->pos.x + glyphs[i].offset_x; 3879 vtx.position.y = pt->pos.y; 3880 vtx.position.z = 0; 3881 *vertex_ptr++ = vtx; 3882 3883 vtx.position.z = -extrusion; 3884 *vertex_ptr++ = vtx; 3885 3886 vtx.position.x = nextpt->pos.x + glyphs[i].offset_x; 3887 vtx.position.y = nextpt->pos.y; 3888 if (pt->corner && nextpt->corner && nextpt->corner != POINTTYPE_CURVE_END) { 3889 vtx.position.z = -extrusion; 3890 *vertex_ptr++ = vtx; 3891 vtx.position.z = 0; 3892 *vertex_ptr++ = vtx; 3893 3894 (*face_ptr)[0] = vtx_idx; 3895 (*face_ptr)[1] = vtx_idx + 2; 3896 (*face_ptr)[2] = vtx_idx + 1; 3897 face_ptr++; 3898 3899 (*face_ptr)[0] = vtx_idx; 3900 (*face_ptr)[1] = vtx_idx + 3; 3901 (*face_ptr)[2] = vtx_idx + 2; 3902 face_ptr++; 3903 } else { 3904 if (nextpt->corner) { 3905 if (nextpt->corner == POINTTYPE_CURVE_END) { 3906 struct point2d *nextpt2 = &outline->items[(k + 1) % outline->count]; 3907 D3DXVec2Subtract(&vec, &nextpt2->pos, &nextpt->pos); 3908 } else { 3909 D3DXVec2Subtract(&vec, &nextpt->pos, &pt->pos); 3910 } 3911 D3DXVec2Normalize(&vec, &vec); 3912 vtx.normal.x = -vec.y; 3913 vtx.normal.y = vec.x; 3914 3915 vtx.position.z = 0; 3916 *vertex_ptr++ = vtx; 3917 vtx.position.z = -extrusion; 3918 *vertex_ptr++ = vtx; 3919 } 3920 3921 (*face_ptr)[0] = vtx_idx; 3922 (*face_ptr)[1] = vtx_idx + 3; 3923 (*face_ptr)[2] = vtx_idx + 1; 3924 face_ptr++; 3925 3926 (*face_ptr)[0] = vtx_idx; 3927 (*face_ptr)[1] = vtx_idx + 2; 3928 (*face_ptr)[2] = vtx_idx + 3; 3929 face_ptr++; 3930 } 3931 3932 prevpt = pt; 3933 pt = nextpt; 3934 } 3935 if (!pt->corner) { 3936 *vertex_ptr++ = *outline_vertices++; 3937 *vertex_ptr++ = *outline_vertices++; 3938 } 3939 } 3940 3941 /* FIXME: compute expected faces */ 3942 /* Add placeholder to separate glyph outlines */ 3943 vertex_ptr->position.x = 0; 3944 vertex_ptr->position.y = 0; 3945 vertex_ptr->position.z = 0; 3946 vertex_ptr->normal.x = 0; 3947 vertex_ptr->normal.y = 0; 3948 vertex_ptr->normal.z = 1; 3949 vertex_ptr++; 3950 } 3951 } 3952 3953 static void compare_text_outline_mesh(const char *name, ID3DXMesh *d3dxmesh, struct mesh *mesh, 3954 size_t textlen, float extrusion, const struct glyphinfo *glyphs) 3955 { 3956 HRESULT hr; 3957 DWORD number_of_vertices, number_of_faces; 3958 IDirect3DVertexBuffer9 *vertex_buffer = NULL; 3959 IDirect3DIndexBuffer9 *index_buffer = NULL; 3960 D3DVERTEXBUFFER_DESC vertex_buffer_description; 3961 D3DINDEXBUFFER_DESC index_buffer_description; 3962 struct vertex *vertices = NULL; 3963 face *faces = NULL; 3964 int expected, i; 3965 int vtx_idx1, face_idx1, vtx_idx2, face_idx2; 3966 3967 number_of_vertices = d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh); 3968 number_of_faces = d3dxmesh->lpVtbl->GetNumFaces(d3dxmesh); 3969 3970 hr = d3dxmesh->lpVtbl->GetVertexBuffer(d3dxmesh, &vertex_buffer); 3971 ok(hr == D3D_OK, "Test %s, unexpected hr %#x.\n", name, hr); 3972 hr = IDirect3DVertexBuffer9_GetDesc(vertex_buffer, &vertex_buffer_description); 3973 ok(hr == D3D_OK, "Test %s, unexpected hr %#x.\n", name, hr); 3974 ok(vertex_buffer_description.Format == D3DFMT_VERTEXDATA, "Test %s, unexpected format %u.\n", 3975 name, vertex_buffer_description.Format); 3976 ok(vertex_buffer_description.Type == D3DRTYPE_VERTEXBUFFER, "Test %s, unexpected resource type %u.\n", 3977 name, vertex_buffer_description.Type); 3978 ok(!vertex_buffer_description.Usage, "Test %s, unexpected usage %#x.\n", name, vertex_buffer_description.Usage); 3979 ok(vertex_buffer_description.Pool == D3DPOOL_MANAGED, "Test %s, unexpected pool %u.\n", 3980 name, vertex_buffer_description.Pool); 3981 ok(vertex_buffer_description.FVF == mesh->fvf, "Test %s, unexpected FVF %#x (expected %#x).\n", 3982 name, vertex_buffer_description.FVF, mesh->fvf); 3983 if (!mesh->fvf) 3984 expected = number_of_vertices * mesh->vertex_size; 3985 else 3986 expected = number_of_vertices * D3DXGetFVFVertexSize(mesh->fvf); 3987 ok(vertex_buffer_description.Size == expected, "Test %s, unexpected size %u (expected %u).\n", 3988 name, vertex_buffer_description.Size, expected); 3989 3990 hr = d3dxmesh->lpVtbl->GetIndexBuffer(d3dxmesh, &index_buffer); 3991 ok(hr == D3D_OK, "Test %s, unexpected hr %#x.\n", name, hr); 3992 hr = IDirect3DIndexBuffer9_GetDesc(index_buffer, &index_buffer_description); 3993 ok(hr == D3D_OK, "Test %s, unexpected hr %#x.\n", name, hr); 3994 ok(index_buffer_description.Format == D3DFMT_INDEX16, "Test %s, unexpected format %u.\n", 3995 name, index_buffer_description.Format); 3996 ok(index_buffer_description.Type == D3DRTYPE_INDEXBUFFER, "Test %s, unexpected resource type %u.\n", 3997 name, index_buffer_description.Type); 3998 ok(!index_buffer_description.Usage, "Test %s, unexpected usage %#x.\n", 3999 name, index_buffer_description.Usage); 4000 ok(index_buffer_description.Pool == D3DPOOL_MANAGED, "Test %s, unexpected pool %u.\n", 4001 name, index_buffer_description.Pool); 4002 expected = number_of_faces * sizeof(WORD) * 3; 4003 ok(index_buffer_description.Size == expected, "Test %s, unexpected size %u.\n", 4004 name, index_buffer_description.Size); 4005 4006 hr = IDirect3DVertexBuffer9_Lock(vertex_buffer, 0, number_of_vertices * sizeof(D3DXVECTOR3) * 2, 4007 (void **)&vertices, D3DLOCK_DISCARD); 4008 ok(hr == D3D_OK, "Test %s, unexpected hr %#x.\n", name, hr); 4009 hr = IDirect3DIndexBuffer9_Lock(index_buffer, 0, number_of_faces * sizeof(WORD) * 3, 4010 (void **)&faces, D3DLOCK_DISCARD); 4011 ok(hr == D3D_OK, "Test %s, unexpected hr %#x.\n", name, hr); 4012 face_idx1 = 0; 4013 vtx_idx2 = 0; 4014 face_idx2 = 0; 4015 vtx_idx1 = 0; 4016 for (i = 0; i < textlen; i++) 4017 { 4018 int nb_outline_vertices1, nb_outline_faces1; 4019 int nb_outline_vertices2, nb_outline_faces2; 4020 int nb_back_vertices, nb_back_faces; 4021 int first_vtx1, first_vtx2; 4022 int first_face1, first_face2; 4023 int j; 4024 4025 first_vtx1 = vtx_idx1; 4026 first_vtx2 = vtx_idx2; 4027 /* Glyphs without outlines do not generate any vertices. */ 4028 if (glyphs[i].outlines.count > 0) 4029 { 4030 for (; vtx_idx1 < number_of_vertices; vtx_idx1++) 4031 { 4032 if (vertices[vtx_idx1].normal.z != 0) 4033 break; 4034 } 4035 4036 for (; vtx_idx2 < mesh->number_of_vertices; vtx_idx2++) 4037 { 4038 if (mesh->vertices[vtx_idx2].normal.z != 0) 4039 break; 4040 } 4041 } 4042 nb_outline_vertices1 = vtx_idx1 - first_vtx1; 4043 nb_outline_vertices2 = vtx_idx2 - first_vtx2; 4044 ok(nb_outline_vertices1 == nb_outline_vertices2, 4045 "Test %s, glyph %d, outline vertex count result %d, expected %d\n", name, i, 4046 nb_outline_vertices1, nb_outline_vertices2); 4047 4048 for (j = 0; j < min(nb_outline_vertices1, nb_outline_vertices2); j++) 4049 { 4050 vtx_idx1 = first_vtx1 + j; 4051 vtx_idx2 = first_vtx2 + j; 4052 ok(compare_vec3(vertices[vtx_idx1].position, mesh->vertices[vtx_idx2].position), 4053 "Test %s, glyph %d, vertex position %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1, 4054 vertices[vtx_idx1].position.x, vertices[vtx_idx1].position.y, vertices[vtx_idx1].position.z, 4055 mesh->vertices[vtx_idx2].position.x, mesh->vertices[vtx_idx2].position.y, mesh->vertices[vtx_idx2].position.z); 4056 ok(compare_vec3(vertices[vtx_idx1].normal, mesh->vertices[first_vtx2 + j].normal), 4057 "Test %s, glyph %d, vertex normal %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1, 4058 vertices[vtx_idx1].normal.x, vertices[vtx_idx1].normal.y, vertices[vtx_idx1].normal.z, 4059 mesh->vertices[vtx_idx2].normal.x, mesh->vertices[vtx_idx2].normal.y, mesh->vertices[vtx_idx2].normal.z); 4060 } 4061 vtx_idx1 = first_vtx1 + nb_outline_vertices1; 4062 vtx_idx2 = first_vtx2 + nb_outline_vertices2; 4063 4064 first_face1 = face_idx1; 4065 first_face2 = face_idx2; 4066 for (; face_idx1 < number_of_faces; face_idx1++) 4067 { 4068 if (faces[face_idx1][0] >= vtx_idx1 || 4069 faces[face_idx1][1] >= vtx_idx1 || 4070 faces[face_idx1][2] >= vtx_idx1) 4071 break; 4072 } 4073 for (; face_idx2 < mesh->number_of_faces; face_idx2++) 4074 { 4075 if (mesh->faces[face_idx2][0] >= vtx_idx2 || 4076 mesh->faces[face_idx2][1] >= vtx_idx2 || 4077 mesh->faces[face_idx2][2] >= vtx_idx2) 4078 break; 4079 } 4080 nb_outline_faces1 = face_idx1 - first_face1; 4081 nb_outline_faces2 = face_idx2 - first_face2; 4082 ok(nb_outline_faces1 == nb_outline_faces2, 4083 "Test %s, glyph %d, outline face count result %d, expected %d\n", name, i, 4084 nb_outline_faces1, nb_outline_faces2); 4085 4086 for (j = 0; j < min(nb_outline_faces1, nb_outline_faces2); j++) 4087 { 4088 face_idx1 = first_face1 + j; 4089 face_idx2 = first_face2 + j; 4090 ok(faces[face_idx1][0] - first_vtx1 == mesh->faces[face_idx2][0] - first_vtx2 && 4091 faces[face_idx1][1] - first_vtx1 == mesh->faces[face_idx2][1] - first_vtx2 && 4092 faces[face_idx1][2] - first_vtx1 == mesh->faces[face_idx2][2] - first_vtx2, 4093 "Test %s, glyph %d, face %d, result (%d, %d, %d), expected (%d, %d, %d)\n", name, i, face_idx1, 4094 faces[face_idx1][0], faces[face_idx1][1], faces[face_idx1][2], 4095 mesh->faces[face_idx2][0] - first_vtx2 + first_vtx1, 4096 mesh->faces[face_idx2][1] - first_vtx2 + first_vtx1, 4097 mesh->faces[face_idx2][2] - first_vtx2 + first_vtx1); 4098 } 4099 face_idx1 = first_face1 + nb_outline_faces1; 4100 face_idx2 = first_face2 + nb_outline_faces2; 4101 4102 /* partial test on back vertices and faces */ 4103 first_vtx1 = vtx_idx1; 4104 for (; vtx_idx1 < number_of_vertices; vtx_idx1++) { 4105 struct vertex vtx; 4106 4107 if (vertices[vtx_idx1].normal.z != 1.0f) 4108 break; 4109 4110 vtx.position.z = 0.0f; 4111 vtx.normal.x = 0.0f; 4112 vtx.normal.y = 0.0f; 4113 vtx.normal.z = 1.0f; 4114 ok(compare(vertices[vtx_idx1].position.z, vtx.position.z), 4115 "Test %s, glyph %d, vertex position.z %d, result %g, expected %g\n", name, i, vtx_idx1, 4116 vertices[vtx_idx1].position.z, vtx.position.z); 4117 ok(compare_vec3(vertices[vtx_idx1].normal, vtx.normal), 4118 "Test %s, glyph %d, vertex normal %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1, 4119 vertices[vtx_idx1].normal.x, vertices[vtx_idx1].normal.y, vertices[vtx_idx1].normal.z, 4120 vtx.normal.x, vtx.normal.y, vtx.normal.z); 4121 } 4122 nb_back_vertices = vtx_idx1 - first_vtx1; 4123 first_face1 = face_idx1; 4124 for (; face_idx1 < number_of_faces; face_idx1++) 4125 { 4126 const D3DXVECTOR3 *vtx1, *vtx2, *vtx3; 4127 D3DXVECTOR3 normal; 4128 D3DXVECTOR3 v1 = {0, 0, 0}; 4129 D3DXVECTOR3 v2 = {0, 0, 0}; 4130 D3DXVECTOR3 forward = {0.0f, 0.0f, 1.0f}; 4131 4132 if (faces[face_idx1][0] >= vtx_idx1 || 4133 faces[face_idx1][1] >= vtx_idx1 || 4134 faces[face_idx1][2] >= vtx_idx1) 4135 break; 4136 4137 vtx1 = &vertices[faces[face_idx1][0]].position; 4138 vtx2 = &vertices[faces[face_idx1][1]].position; 4139 vtx3 = &vertices[faces[face_idx1][2]].position; 4140 4141 D3DXVec3Subtract(&v1, vtx2, vtx1); 4142 D3DXVec3Subtract(&v2, vtx3, vtx2); 4143 D3DXVec3Cross(&normal, &v1, &v2); 4144 D3DXVec3Normalize(&normal, &normal); 4145 ok(!D3DXVec3Length(&normal) || compare_vec3(normal, forward), 4146 "Test %s, glyph %d, face %d normal, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, face_idx1, 4147 normal.x, normal.y, normal.z, forward.x, forward.y, forward.z); 4148 } 4149 nb_back_faces = face_idx1 - first_face1; 4150 4151 /* compare front and back faces & vertices */ 4152 if (extrusion == 0.0f) { 4153 /* Oddly there are only back faces in this case */ 4154 nb_back_vertices /= 2; 4155 nb_back_faces /= 2; 4156 face_idx1 -= nb_back_faces; 4157 vtx_idx1 -= nb_back_vertices; 4158 } 4159 for (j = 0; j < nb_back_vertices; j++) 4160 { 4161 struct vertex vtx = vertices[first_vtx1]; 4162 vtx.position.z = -extrusion; 4163 vtx.normal.x = 0.0f; 4164 vtx.normal.y = 0.0f; 4165 vtx.normal.z = extrusion == 0.0f ? 1.0f : -1.0f; 4166 ok(compare_vec3(vertices[vtx_idx1].position, vtx.position), 4167 "Test %s, glyph %d, vertex position %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1, 4168 vertices[vtx_idx1].position.x, vertices[vtx_idx1].position.y, vertices[vtx_idx1].position.z, 4169 vtx.position.x, vtx.position.y, vtx.position.z); 4170 ok(compare_vec3(vertices[vtx_idx1].normal, vtx.normal), 4171 "Test %s, glyph %d, vertex normal %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1, 4172 vertices[vtx_idx1].normal.x, vertices[vtx_idx1].normal.y, vertices[vtx_idx1].normal.z, 4173 vtx.normal.x, vtx.normal.y, vtx.normal.z); 4174 vtx_idx1++; 4175 first_vtx1++; 4176 } 4177 for (j = 0; j < nb_back_faces; j++) 4178 { 4179 int f1, f2; 4180 if (extrusion == 0.0f) { 4181 f1 = 1; 4182 f2 = 2; 4183 } else { 4184 f1 = 2; 4185 f2 = 1; 4186 } 4187 ok(faces[face_idx1][0] == faces[first_face1][0] + nb_back_vertices && 4188 faces[face_idx1][1] == faces[first_face1][f1] + nb_back_vertices && 4189 faces[face_idx1][2] == faces[first_face1][f2] + nb_back_vertices, 4190 "Test %s, glyph %d, face %d, result (%d, %d, %d), expected (%d, %d, %d)\n", name, i, face_idx1, 4191 faces[face_idx1][0], faces[face_idx1][1], faces[face_idx1][2], 4192 faces[first_face1][0] - nb_back_faces, 4193 faces[first_face1][f1] - nb_back_faces, 4194 faces[first_face1][f2] - nb_back_faces); 4195 first_face1++; 4196 face_idx1++; 4197 } 4198 4199 /* skip to the outline for the next glyph */ 4200 for (; vtx_idx2 < mesh->number_of_vertices; vtx_idx2++) { 4201 if (mesh->vertices[vtx_idx2].normal.z == 0) 4202 break; 4203 } 4204 for (; face_idx2 < mesh->number_of_faces; face_idx2++) 4205 { 4206 if (mesh->faces[face_idx2][0] >= vtx_idx2 || 4207 mesh->faces[face_idx2][1] >= vtx_idx2 || 4208 mesh->faces[face_idx2][2] >= vtx_idx2) break; 4209 } 4210 } 4211 4212 IDirect3DIndexBuffer9_Unlock(index_buffer); 4213 IDirect3DVertexBuffer9_Unlock(vertex_buffer); 4214 IDirect3DIndexBuffer9_Release(index_buffer); 4215 IDirect3DVertexBuffer9_Release(vertex_buffer); 4216 } 4217 4218 static void test_createtext(IDirect3DDevice9 *device, HDC hdc, const char *text, float deviation, float extrusion) 4219 { 4220 static const MAT2 identity = {{0, 1}, {0, 0}, {0, 0}, {0, 1}}; 4221 HRESULT hr; 4222 ID3DXMesh *d3dxmesh = NULL; 4223 struct mesh mesh = {0}; 4224 char name[256]; 4225 OUTLINETEXTMETRICA otm; 4226 GLYPHMETRICS gm; 4227 struct glyphinfo *glyphs; 4228 GLYPHMETRICSFLOAT *glyphmetrics_float = HeapAlloc(GetProcessHeap(), 0, sizeof(GLYPHMETRICSFLOAT) * strlen(text)); 4229 int i; 4230 LOGFONTA lf; 4231 float offset_x; 4232 size_t textlen; 4233 HFONT font = NULL, oldfont = NULL; 4234 char *raw_outline; 4235 4236 sprintf(name, "text ('%s', %f, %f)", text, deviation, extrusion); 4237 4238 hr = D3DXCreateTextA(device, hdc, text, deviation, extrusion, &d3dxmesh, NULL, glyphmetrics_float); 4239 ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); 4240 4241 /* must select a modified font having lfHeight = otm.otmEMSquare before 4242 * calling GetGlyphOutline to get the expected values */ 4243 ok(GetObjectA(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf), "Failed to get current DC font.\n"); 4244 ok(GetOutlineTextMetricsA(hdc, sizeof(otm), &otm), "Failed to get DC font outline.\n"); 4245 lf.lfHeight = otm.otmEMSquare; 4246 lf.lfWidth = 0; 4247 ok(!!(font = CreateFontIndirectA(&lf)), "Failed to create font.\n"); 4248 4249 textlen = strlen(text); 4250 glyphs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, textlen * sizeof(*glyphs)); 4251 oldfont = SelectObject(hdc, font); 4252 4253 for (i = 0; i < textlen; i++) 4254 { 4255 GetGlyphOutlineA(hdc, text[i], GGO_NATIVE, &gm, 0, NULL, &identity); 4256 compare_float(glyphmetrics_float[i].gmfBlackBoxX, gm.gmBlackBoxX / (float)otm.otmEMSquare); 4257 compare_float(glyphmetrics_float[i].gmfBlackBoxY, gm.gmBlackBoxY / (float)otm.otmEMSquare); 4258 compare_float(glyphmetrics_float[i].gmfptGlyphOrigin.x, gm.gmptGlyphOrigin.x / (float)otm.otmEMSquare); 4259 compare_float(glyphmetrics_float[i].gmfptGlyphOrigin.y, gm.gmptGlyphOrigin.y / (float)otm.otmEMSquare); 4260 compare_float(glyphmetrics_float[i].gmfCellIncX, gm.gmCellIncX / (float)otm.otmEMSquare); 4261 compare_float(glyphmetrics_float[i].gmfCellIncY, gm.gmCellIncY / (float)otm.otmEMSquare); 4262 } 4263 4264 if (deviation == 0.0f) 4265 deviation = 1.0f / otm.otmEMSquare; 4266 4267 offset_x = 0.0f; 4268 for (i = 0; i < textlen; i++) 4269 { 4270 DWORD datasize; 4271 4272 glyphs[i].offset_x = offset_x; 4273 4274 datasize = GetGlyphOutlineA(hdc, text[i], GGO_NATIVE, &gm, 0, NULL, &identity); 4275 ok(datasize != GDI_ERROR, "Failed to retrieve GDI glyph outline size.\n"); 4276 raw_outline = HeapAlloc(GetProcessHeap(), 0, datasize); 4277 datasize = GetGlyphOutlineA(hdc, text[i], GGO_NATIVE, &gm, datasize, raw_outline, &identity); 4278 ok(datasize != GDI_ERROR, "Failed to retrieve GDI glyph outline.\n"); 4279 create_outline(&glyphs[i], raw_outline, datasize, deviation, otm.otmEMSquare); 4280 HeapFree(GetProcessHeap(), 0, raw_outline); 4281 4282 offset_x += gm.gmCellIncX / (float)otm.otmEMSquare; 4283 } 4284 4285 SelectObject(hdc, oldfont); 4286 4287 compute_text_mesh(&mesh, text, deviation, extrusion, otm.otmEMSquare, glyphs); 4288 mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL; 4289 4290 compare_text_outline_mesh(name, d3dxmesh, &mesh, textlen, extrusion, glyphs); 4291 4292 free_mesh(&mesh); 4293 d3dxmesh->lpVtbl->Release(d3dxmesh); 4294 DeleteObject(font); 4295 HeapFree(GetProcessHeap(), 0, glyphmetrics_float); 4296 4297 for (i = 0; i < textlen; i++) 4298 free_glyphinfo(&glyphs[i]); 4299 HeapFree(GetProcessHeap(), 0, glyphs); 4300 } 4301 4302 static void D3DXCreateTextTest(void) 4303 { 4304 HRESULT hr; 4305 HDC hdc; 4306 IDirect3DDevice9* device; 4307 ID3DXMesh* d3dxmesh = NULL; 4308 HFONT hFont; 4309 OUTLINETEXTMETRICA otm; 4310 int number_of_vertices; 4311 int number_of_faces; 4312 struct test_context *test_context; 4313 4314 if (!(test_context = new_test_context())) 4315 { 4316 skip("Couldn't create test context\n"); 4317 return; 4318 } 4319 device = test_context->device; 4320 4321 hdc = CreateCompatibleDC(NULL); 4322 4323 hFont = CreateFontA(12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, 4324 CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, "Arial"); 4325 SelectObject(hdc, hFont); 4326 GetOutlineTextMetricsA(hdc, sizeof(otm), &otm); 4327 4328 hr = D3DXCreateTextA(device, hdc, "wine", 0.001f, 0.4f, NULL, NULL, NULL); 4329 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 4330 4331 /* D3DXCreateTextA page faults from passing NULL text */ 4332 4333 hr = D3DXCreateTextW(device, hdc, NULL, 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(device, hdc, " ", 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(NULL, hdc, "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, NULL, "wine", 0.001f, 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", -FLT_MIN, 0.4f, &d3dxmesh, NULL, NULL); 4349 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 4350 4351 hr = D3DXCreateTextA(device, hdc, "wine", 0.001f, -FLT_MIN, &d3dxmesh, NULL, NULL); 4352 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 4353 4354 /* deviation = 0.0f treated as if deviation = 1.0f / otm.otmEMSquare */ 4355 hr = D3DXCreateTextA(device, hdc, "wine", 1.0f / otm.otmEMSquare, 0.4f, &d3dxmesh, NULL, NULL); 4356 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK); 4357 number_of_vertices = d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh); 4358 number_of_faces = d3dxmesh->lpVtbl->GetNumFaces(d3dxmesh); 4359 d3dxmesh->lpVtbl->Release(d3dxmesh); 4360 4361 hr = D3DXCreateTextA(device, hdc, "wine", 0.0f, 0.4f, &d3dxmesh, NULL, NULL); 4362 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK); 4363 ok(number_of_vertices == d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh), 4364 "Got %d vertices, expected %d\n", 4365 d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh), number_of_vertices); 4366 ok(number_of_faces == d3dxmesh->lpVtbl->GetNumFaces(d3dxmesh), 4367 "Got %d faces, expected %d\n", 4368 d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh), number_of_faces); 4369 d3dxmesh->lpVtbl->Release(d3dxmesh); 4370 4371 if (0) 4372 { 4373 /* too much detail requested, so will appear to hang */ 4374 trace("Waiting for D3DXCreateText to finish with deviation = FLT_MIN ...\n"); 4375 hr = D3DXCreateTextA(device, hdc, "wine", FLT_MIN, 0.4f, &d3dxmesh, NULL, NULL); 4376 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK); 4377 if (SUCCEEDED(hr) && d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh); 4378 trace("D3DXCreateText finish with deviation = FLT_MIN\n"); 4379 } 4380 4381 hr = D3DXCreateTextA(device, hdc, "wine", 0.001f, 0.4f, &d3dxmesh, NULL, NULL); 4382 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK); 4383 if (SUCCEEDED(hr) && d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh); 4384 4385 test_createtext(device, hdc, "wine", FLT_MAX, 0.4f); 4386 test_createtext(device, hdc, "wine", 0.001f, FLT_MIN); 4387 test_createtext(device, hdc, "wine", 0.001f, 0.0f); 4388 test_createtext(device, hdc, "wine", 0.001f, FLT_MAX); 4389 test_createtext(device, hdc, "wine", 0.0f, 1.0f); 4390 test_createtext(device, hdc, " wine", 1.0f, 0.0f); 4391 test_createtext(device, hdc, "wine ", 1.0f, 0.0f); 4392 test_createtext(device, hdc, "wi ne", 1.0f, 0.0f); 4393 4394 DeleteDC(hdc); 4395 DeleteObject(hFont); 4396 4397 free_test_context(test_context); 4398 } 4399 4400 static void test_get_decl_length(void) 4401 { 4402 static const D3DVERTEXELEMENT9 declaration1[] = 4403 { 4404 {0, 0, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4405 {1, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4406 {2, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4407 {3, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4408 {4, 0, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4409 {5, 0, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4410 {6, 0, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4411 {7, 0, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4412 {8, 0, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4413 {9, 0, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4414 {10, 0, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4415 {11, 0, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4416 {12, 0, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4417 {13, 0, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4418 {14, 0, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4419 D3DDECL_END(), 4420 }; 4421 static const D3DVERTEXELEMENT9 declaration2[] = 4422 { 4423 {0, 8, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4424 {1, 8, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4425 {2, 8, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4426 {3, 8, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4427 {4, 8, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4428 {5, 8, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4429 {6, 8, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4430 {7, 8, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4431 {0, 8, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4432 {1, 8, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4433 {2, 8, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4434 {3, 8, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4435 {4, 8, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4436 {5, 8, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4437 {6, 8, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4438 {7, 8, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4439 D3DDECL_END(), 4440 }; 4441 UINT size; 4442 4443 size = D3DXGetDeclLength(declaration1); 4444 ok(size == 15, "Got size %u, expected 15.\n", size); 4445 4446 size = D3DXGetDeclLength(declaration2); 4447 ok(size == 16, "Got size %u, expected 16.\n", size); 4448 } 4449 4450 static void test_get_decl_vertex_size(void) 4451 { 4452 static const D3DVERTEXELEMENT9 declaration1[] = 4453 { 4454 {0, 0, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4455 {1, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4456 {2, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4457 {3, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4458 {4, 0, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4459 {5, 0, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4460 {6, 0, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4461 {7, 0, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4462 {8, 0, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4463 {9, 0, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4464 {10, 0, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4465 {11, 0, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4466 {12, 0, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4467 {13, 0, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4468 {14, 0, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4469 D3DDECL_END(), 4470 }; 4471 static const D3DVERTEXELEMENT9 declaration2[] = 4472 { 4473 {0, 8, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4474 {1, 8, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4475 {2, 8, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4476 {3, 8, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4477 {4, 8, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4478 {5, 8, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4479 {6, 8, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4480 {7, 8, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4481 {0, 8, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4482 {1, 8, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4483 {2, 8, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4484 {3, 8, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4485 {4, 8, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4486 {5, 8, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4487 {6, 8, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4488 {7, 8, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4489 D3DDECL_END(), 4490 }; 4491 static const UINT sizes1[] = 4492 { 4493 4, 8, 12, 16, 4494 4, 4, 4, 8, 4495 4, 4, 8, 4, 4496 4, 4, 8, 0, 4497 }; 4498 static const UINT sizes2[] = 4499 { 4500 12, 16, 20, 24, 4501 12, 12, 16, 16, 4502 }; 4503 unsigned int i; 4504 UINT size; 4505 4506 size = D3DXGetDeclVertexSize(NULL, 0); 4507 ok(size == 0, "Got size %#x, expected 0.\n", size); 4508 4509 for (i = 0; i < 16; ++i) 4510 { 4511 size = D3DXGetDeclVertexSize(declaration1, i); 4512 ok(size == sizes1[i], "Got size %u for stream %u, expected %u.\n", size, i, sizes1[i]); 4513 } 4514 4515 for (i = 0; i < 8; ++i) 4516 { 4517 size = D3DXGetDeclVertexSize(declaration2, i); 4518 ok(size == sizes2[i], "Got size %u for stream %u, expected %u.\n", size, i, sizes2[i]); 4519 } 4520 } 4521 4522 static void D3DXGenerateAdjacencyTest(void) 4523 { 4524 HRESULT hr; 4525 IDirect3DDevice9 *device; 4526 ID3DXMesh *d3dxmesh = NULL; 4527 D3DXVECTOR3 *vertices = NULL; 4528 WORD *indices = NULL; 4529 int i; 4530 struct { 4531 DWORD num_vertices; 4532 D3DXVECTOR3 vertices[6]; 4533 DWORD num_faces; 4534 WORD indices[3 * 3]; 4535 FLOAT epsilon; 4536 DWORD adjacency[3 * 3]; 4537 } test_data[] = { 4538 { /* for epsilon < 0, indices must match for faces to be adjacent */ 4539 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}}, 4540 2, {0, 1, 2, 0, 2, 3}, 4541 -1.0, 4542 {-1, -1, 1, 0, -1, -1}, 4543 }, 4544 { 4545 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}}, 4546 2, {0, 1, 2, 3, 4, 5}, 4547 -1.0, 4548 {-1, -1, -1, -1, -1, -1}, 4549 }, 4550 { /* for epsilon == 0, indices or vertices must match for faces to be adjacent */ 4551 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}}, 4552 2, {0, 1, 2, 3, 4, 5}, 4553 0.0, 4554 {-1, -1, 1, 0, -1, -1}, 4555 }, 4556 { /* for epsilon > 0, vertices must be less than (but NOT equal to) epsilon distance away */ 4557 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}}, 4558 2, {0, 1, 2, 3, 4, 5}, 4559 0.25, 4560 {-1, -1, -1, -1, -1, -1}, 4561 }, 4562 { /* for epsilon > 0, vertices must be less than (but NOT equal to) epsilon distance away */ 4563 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}}, 4564 2, {0, 1, 2, 3, 4, 5}, 4565 0.250001, 4566 {-1, -1, 1, 0, -1, -1}, 4567 }, 4568 { /* length between vertices are compared to epsilon, not the individual dimension deltas */ 4569 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}}, 4570 2, {0, 1, 2, 3, 4, 5}, 4571 0.353, /* < sqrt(0.25*0.25 + 0.25*0.25) */ 4572 {-1, -1, -1, -1, -1, -1}, 4573 }, 4574 { 4575 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}}, 4576 2, {0, 1, 2, 3, 4, 5}, 4577 0.354, /* > sqrt(0.25*0.25 + 0.25*0.25) */ 4578 {-1, -1, 1, 0, -1, -1}, 4579 }, 4580 { /* adjacent faces must have opposite winding orders at the shared edge */ 4581 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}}, 4582 2, {0, 1, 2, 0, 3, 2}, 4583 0.0, 4584 {-1, -1, -1, -1, -1, -1}, 4585 }, 4586 }; 4587 struct test_context *test_context; 4588 4589 if (!(test_context = new_test_context())) 4590 { 4591 skip("Couldn't create test context\n"); 4592 return; 4593 } 4594 device = test_context->device; 4595 4596 for (i = 0; i < ARRAY_SIZE(test_data); i++) 4597 { 4598 DWORD adjacency[ARRAY_SIZE(test_data[0].adjacency)]; 4599 int j; 4600 4601 if (d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh); 4602 d3dxmesh = NULL; 4603 4604 hr = D3DXCreateMeshFVF(test_data[i].num_faces, test_data[i].num_vertices, 0, D3DFVF_XYZ, device, &d3dxmesh); 4605 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK); 4606 4607 hr = d3dxmesh->lpVtbl->LockVertexBuffer(d3dxmesh, D3DLOCK_DISCARD, (void**)&vertices); 4608 ok(hr == D3D_OK, "test %d: Got result %x, expected %x (D3D_OK)\n", i, hr, D3D_OK); 4609 if (FAILED(hr)) continue; 4610 CopyMemory(vertices, test_data[i].vertices, test_data[i].num_vertices * sizeof(test_data[0].vertices[0])); 4611 d3dxmesh->lpVtbl->UnlockVertexBuffer(d3dxmesh); 4612 4613 hr = d3dxmesh->lpVtbl->LockIndexBuffer(d3dxmesh, D3DLOCK_DISCARD, (void**)&indices); 4614 ok(hr == D3D_OK, "test %d: Got result %x, expected %x (D3D_OK)\n", i, hr, D3D_OK); 4615 if (FAILED(hr)) continue; 4616 CopyMemory(indices, test_data[i].indices, test_data[i].num_faces * 3 * sizeof(test_data[0].indices[0])); 4617 d3dxmesh->lpVtbl->UnlockIndexBuffer(d3dxmesh); 4618 4619 if (i == 0) { 4620 hr = d3dxmesh->lpVtbl->GenerateAdjacency(d3dxmesh, 0.0f, NULL); 4621 ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); 4622 } 4623 4624 hr = d3dxmesh->lpVtbl->GenerateAdjacency(d3dxmesh, test_data[i].epsilon, adjacency); 4625 ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK); 4626 if (FAILED(hr)) continue; 4627 4628 for (j = 0; j < test_data[i].num_faces * 3; j++) 4629 ok(adjacency[j] == test_data[i].adjacency[j], 4630 "Test %d adjacency %d: Got result %u, expected %u\n", i, j, 4631 adjacency[j], test_data[i].adjacency[j]); 4632 } 4633 if (d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh); 4634 4635 free_test_context(test_context); 4636 } 4637 4638 static void test_update_semantics(void) 4639 { 4640 HRESULT hr; 4641 struct test_context *test_context = NULL; 4642 ID3DXMesh *mesh = NULL; 4643 D3DVERTEXELEMENT9 declaration0[] = 4644 { 4645 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4646 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 4647 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0}, 4648 D3DDECL_END() 4649 }; 4650 D3DVERTEXELEMENT9 declaration_pos_type_color[] = 4651 { 4652 {0, 0, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4653 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 4654 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0}, 4655 D3DDECL_END() 4656 }; 4657 D3DVERTEXELEMENT9 declaration_smaller[] = 4658 { 4659 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4660 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 4661 D3DDECL_END() 4662 }; 4663 D3DVERTEXELEMENT9 declaration_larger[] = 4664 { 4665 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4666 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 4667 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0}, 4668 {0, 40, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT, 0}, 4669 D3DDECL_END() 4670 }; 4671 D3DVERTEXELEMENT9 declaration_multiple_streams[] = 4672 { 4673 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4674 {1, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT, 0}, 4675 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 4676 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0}, 4677 4678 D3DDECL_END() 4679 }; 4680 D3DVERTEXELEMENT9 declaration_double_usage[] = 4681 { 4682 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4683 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4684 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 4685 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0}, 4686 D3DDECL_END() 4687 }; 4688 D3DVERTEXELEMENT9 declaration_undefined_type[] = 4689 { 4690 {0, 0, D3DDECLTYPE_UNUSED+1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4691 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 4692 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0}, 4693 D3DDECL_END() 4694 }; 4695 D3DVERTEXELEMENT9 declaration_not_4_byte_aligned_offset[] = 4696 { 4697 {0, 3, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 4698 {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 4699 {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0}, 4700 D3DDECL_END() 4701 }; 4702 static const struct 4703 { 4704 D3DXVECTOR3 position0; 4705 D3DXVECTOR3 position1; 4706 D3DXVECTOR3 normal; 4707 DWORD color; 4708 } 4709 vertices[] = 4710 { 4711 { { 0.0f, 1.0f, 0.f}, { 1.0f, 0.0f, 0.f}, {0.0f, 0.0f, 1.0f}, 0xffff0000 }, 4712 { { 1.0f, -1.0f, 0.f}, {-1.0f, -1.0f, 0.f}, {0.0f, 0.0f, 1.0f}, 0xff00ff00 }, 4713 { {-1.0f, -1.0f, 0.f}, {-1.0f, 1.0f, 0.f}, {0.0f, 0.0f, 1.0f}, 0xff0000ff }, 4714 }; 4715 unsigned int faces[] = {0, 1, 2}; 4716 unsigned int attributes[] = {0}; 4717 unsigned int num_faces = ARRAY_SIZE(faces) / 3; 4718 unsigned int num_vertices = ARRAY_SIZE(vertices); 4719 int offset = sizeof(D3DXVECTOR3); 4720 DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM; 4721 void *vertex_buffer; 4722 void *index_buffer; 4723 DWORD *attributes_buffer; 4724 D3DVERTEXELEMENT9 declaration[MAX_FVF_DECL_SIZE]; 4725 D3DVERTEXELEMENT9 *decl_ptr; 4726 DWORD exp_vertex_size = sizeof(*vertices); 4727 DWORD vertex_size = 0; 4728 int equal; 4729 int i = 0; 4730 int *decl_mem; 4731 int filler_a = 0xaaaaaaaa; 4732 int filler_b = 0xbbbbbbbb; 4733 4734 test_context = new_test_context(); 4735 if (!test_context) 4736 { 4737 skip("Couldn't create a test_context\n"); 4738 goto cleanup; 4739 } 4740 4741 hr = D3DXCreateMesh(num_faces, num_vertices, options, declaration0, 4742 test_context->device, &mesh); 4743 if (FAILED(hr)) 4744 { 4745 skip("Couldn't create test mesh %#x\n", hr); 4746 goto cleanup; 4747 } 4748 4749 mesh->lpVtbl->LockVertexBuffer(mesh, 0, &vertex_buffer); 4750 memcpy(vertex_buffer, vertices, sizeof(vertices)); 4751 mesh->lpVtbl->UnlockVertexBuffer(mesh); 4752 4753 mesh->lpVtbl->LockIndexBuffer(mesh, 0, &index_buffer); 4754 memcpy(index_buffer, faces, sizeof(faces)); 4755 mesh->lpVtbl->UnlockIndexBuffer(mesh); 4756 4757 mesh->lpVtbl->LockAttributeBuffer(mesh, 0, &attributes_buffer); 4758 memcpy(attributes_buffer, attributes, sizeof(attributes)); 4759 mesh->lpVtbl->UnlockAttributeBuffer(mesh); 4760 4761 /* Get the declaration and try to change it */ 4762 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration); 4763 if (FAILED(hr)) 4764 { 4765 skip("Couldn't get vertex declaration %#x\n", hr); 4766 goto cleanup; 4767 } 4768 equal = memcmp(declaration, declaration0, sizeof(declaration0)); 4769 ok(equal == 0, "Vertex declarations were not equal\n"); 4770 4771 for (decl_ptr = declaration; decl_ptr->Stream != 0xFF; decl_ptr++) 4772 { 4773 if (decl_ptr->Usage == D3DDECLUSAGE_POSITION) 4774 { 4775 /* Use second vertex position instead of first */ 4776 decl_ptr->Offset = offset; 4777 } 4778 } 4779 4780 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration); 4781 ok(hr == D3D_OK, "Test UpdateSemantics, got %#x expected %#x\n", hr, D3D_OK); 4782 4783 /* Check that declaration was written by getting it again */ 4784 memset(declaration, 0, sizeof(declaration)); 4785 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration); 4786 if (FAILED(hr)) 4787 { 4788 skip("Couldn't get vertex declaration %#x\n", hr); 4789 goto cleanup; 4790 } 4791 4792 for (decl_ptr = declaration; decl_ptr->Stream != 0xFF; decl_ptr++) 4793 { 4794 if (decl_ptr->Usage == D3DDECLUSAGE_POSITION) 4795 { 4796 ok(decl_ptr->Offset == offset, "Test UpdateSemantics, got offset %d expected %d\n", 4797 decl_ptr->Offset, offset); 4798 } 4799 } 4800 4801 /* Check that GetDeclaration only writes up to the D3DDECL_END() marker and 4802 * not the full MAX_FVF_DECL_SIZE elements. 4803 */ 4804 memset(declaration, filler_a, sizeof(declaration)); 4805 memcpy(declaration, declaration0, sizeof(declaration0)); 4806 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration); 4807 ok(hr == D3D_OK, "Test UpdateSemantics, " 4808 "got %#x expected D3D_OK\n", hr); 4809 memset(declaration, filler_b, sizeof(declaration)); 4810 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration); 4811 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr); 4812 decl_mem = (int*)declaration; 4813 for (i = sizeof(declaration0)/sizeof(*decl_mem); i < sizeof(declaration)/sizeof(*decl_mem); i++) 4814 { 4815 equal = memcmp(&decl_mem[i], &filler_b, sizeof(filler_b)); 4816 ok(equal == 0, 4817 "GetDeclaration wrote past the D3DDECL_END() marker. " 4818 "Got %#x, expected %#x\n", decl_mem[i], filler_b); 4819 if (equal != 0) break; 4820 } 4821 4822 /* UpdateSemantics does not check for overlapping fields */ 4823 memset(declaration, 0, sizeof(declaration)); 4824 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration); 4825 if (FAILED(hr)) 4826 { 4827 skip("Couldn't get vertex declaration %#x\n", hr); 4828 goto cleanup; 4829 } 4830 4831 for (decl_ptr = declaration; decl_ptr->Stream != 0xFF; decl_ptr++) 4832 { 4833 if (decl_ptr->Type == D3DDECLTYPE_FLOAT3) 4834 { 4835 decl_ptr->Type = D3DDECLTYPE_FLOAT4; 4836 } 4837 } 4838 4839 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration); 4840 ok(hr == D3D_OK, "Test UpdateSemantics for overlapping fields, " 4841 "got %#x expected D3D_OK\n", hr); 4842 4843 /* Set the position type to color instead of float3 */ 4844 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_pos_type_color); 4845 ok(hr == D3D_OK, "Test UpdateSemantics position type color, " 4846 "got %#x expected D3D_OK\n", hr); 4847 4848 /* The following test cases show that NULL, smaller or larger declarations, 4849 * and declarations with non-zero Stream values are not accepted. 4850 * UpdateSemantics returns D3DERR_INVALIDCALL and the previously set 4851 * declaration will be used by DrawSubset, GetNumBytesPerVertex, and 4852 * GetDeclaration. 4853 */ 4854 4855 /* Null declaration (invalid declaration) */ 4856 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */ 4857 hr = mesh->lpVtbl->UpdateSemantics(mesh, NULL); 4858 ok(hr == D3DERR_INVALIDCALL, "Test UpdateSemantics null pointer declaration, " 4859 "got %#x expected D3DERR_INVALIDCALL\n", hr); 4860 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh); 4861 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n", 4862 vertex_size, exp_vertex_size); 4863 memset(declaration, 0, sizeof(declaration)); 4864 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration); 4865 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr); 4866 equal = memcmp(declaration, declaration0, sizeof(declaration0)); 4867 ok(equal == 0, "Vertex declarations were not equal\n"); 4868 4869 /* Smaller vertex declaration (invalid declaration) */ 4870 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */ 4871 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_smaller); 4872 ok(hr == D3DERR_INVALIDCALL, "Test UpdateSemantics for smaller vertex declaration, " 4873 "got %#x expected D3DERR_INVALIDCALL\n", hr); 4874 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh); 4875 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n", 4876 vertex_size, exp_vertex_size); 4877 memset(declaration, 0, sizeof(declaration)); 4878 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration); 4879 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr); 4880 equal = memcmp(declaration, declaration0, sizeof(declaration0)); 4881 ok(equal == 0, "Vertex declarations were not equal\n"); 4882 4883 /* Larger vertex declaration (invalid declaration) */ 4884 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */ 4885 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_larger); 4886 ok(hr == D3DERR_INVALIDCALL, "Test UpdateSemantics for larger vertex declaration, " 4887 "got %#x expected D3DERR_INVALIDCALL\n", hr); 4888 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh); 4889 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n", 4890 vertex_size, exp_vertex_size); 4891 memset(declaration, 0, sizeof(declaration)); 4892 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration); 4893 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr); 4894 equal = memcmp(declaration, declaration0, sizeof(declaration0)); 4895 ok(equal == 0, "Vertex declarations were not equal\n"); 4896 4897 /* Use multiple streams and keep the same vertex size (invalid declaration) */ 4898 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */ 4899 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_multiple_streams); 4900 ok(hr == D3DERR_INVALIDCALL, "Test UpdateSemantics using multiple streams, " 4901 "got %#x expected D3DERR_INVALIDCALL\n", hr); 4902 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh); 4903 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n", 4904 vertex_size, exp_vertex_size); 4905 memset(declaration, 0, sizeof(declaration)); 4906 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration); 4907 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr); 4908 equal = memcmp(declaration, declaration0, sizeof(declaration0)); 4909 ok(equal == 0, "Vertex declarations were not equal\n"); 4910 4911 /* The next following test cases show that some invalid declarations are 4912 * accepted with a D3D_OK. An access violation is thrown on Windows if 4913 * DrawSubset is called. The methods GetNumBytesPerVertex and GetDeclaration 4914 * are not affected, which indicates that the declaration is cached. 4915 */ 4916 4917 /* Double usage (invalid declaration) */ 4918 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */ 4919 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_double_usage); 4920 ok(hr == D3D_OK, "Test UpdateSemantics double usage, " 4921 "got %#x expected D3D_OK\n", hr); 4922 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh); 4923 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n", 4924 vertex_size, exp_vertex_size); 4925 memset(declaration, 0, sizeof(declaration)); 4926 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration); 4927 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr); 4928 equal = memcmp(declaration, declaration_double_usage, sizeof(declaration_double_usage)); 4929 ok(equal == 0, "Vertex declarations were not equal\n"); 4930 4931 /* Set the position to an undefined type (invalid declaration) */ 4932 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */ 4933 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_undefined_type); 4934 ok(hr == D3D_OK, "Test UpdateSemantics undefined type, " 4935 "got %#x expected D3D_OK\n", hr); 4936 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh); 4937 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n", 4938 vertex_size, exp_vertex_size); 4939 memset(declaration, 0, sizeof(declaration)); 4940 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration); 4941 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr); 4942 equal = memcmp(declaration, declaration_undefined_type, sizeof(declaration_undefined_type)); 4943 ok(equal == 0, "Vertex declarations were not equal\n"); 4944 4945 /* Use a not 4 byte aligned offset (invalid declaration) */ 4946 mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */ 4947 hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_not_4_byte_aligned_offset); 4948 ok(hr == D3D_OK, "Test UpdateSemantics not 4 byte aligned offset, " 4949 "got %#x expected D3D_OK\n", hr); 4950 vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh); 4951 ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n", 4952 vertex_size, exp_vertex_size); 4953 memset(declaration, 0, sizeof(declaration)); 4954 hr = mesh->lpVtbl->GetDeclaration(mesh, declaration); 4955 ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr); 4956 equal = memcmp(declaration, declaration_not_4_byte_aligned_offset, 4957 sizeof(declaration_not_4_byte_aligned_offset)); 4958 ok(equal == 0, "Vertex declarations were not equal\n"); 4959 4960 cleanup: 4961 if (mesh) 4962 mesh->lpVtbl->Release(mesh); 4963 4964 free_test_context(test_context); 4965 } 4966 4967 static void test_create_skin_info(void) 4968 { 4969 HRESULT hr; 4970 ID3DXSkinInfo *skininfo = NULL; 4971 D3DVERTEXELEMENT9 empty_declaration[] = { D3DDECL_END() }; 4972 D3DVERTEXELEMENT9 declaration_out[MAX_FVF_DECL_SIZE]; 4973 const D3DVERTEXELEMENT9 declaration_with_nonzero_stream[] = { 4974 {1, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, 4975 D3DDECL_END() 4976 }; 4977 4978 hr = D3DXCreateSkinInfo(0, empty_declaration, 0, &skininfo); 4979 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 4980 if (skininfo) IUnknown_Release(skininfo); 4981 skininfo = NULL; 4982 4983 hr = D3DXCreateSkinInfo(1, NULL, 1, &skininfo); 4984 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 4985 4986 hr = D3DXCreateSkinInfo(1, declaration_with_nonzero_stream, 1, &skininfo); 4987 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 4988 4989 hr = D3DXCreateSkinInfoFVF(1, 0, 1, &skininfo); 4990 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 4991 if (skininfo) 4992 { 4993 DWORD dword_result; 4994 float flt_result; 4995 const char *string_result; 4996 D3DXMATRIX *transform; 4997 D3DXMATRIX identity_matrix; 4998 4999 /* test initial values */ 5000 hr = skininfo->lpVtbl->GetDeclaration(skininfo, declaration_out); 5001 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 5002 if (SUCCEEDED(hr)) 5003 compare_elements(declaration_out, empty_declaration, __LINE__, 0); 5004 5005 dword_result = skininfo->lpVtbl->GetNumBones(skininfo); 5006 ok(dword_result == 1, "Expected 1, got %u\n", dword_result); 5007 5008 flt_result = skininfo->lpVtbl->GetMinBoneInfluence(skininfo); 5009 ok(flt_result == 0.0f, "Expected 0.0, got %g\n", flt_result); 5010 5011 string_result = skininfo->lpVtbl->GetBoneName(skininfo, 0); 5012 ok(string_result == NULL, "Expected NULL, got %p\n", string_result); 5013 5014 dword_result = skininfo->lpVtbl->GetFVF(skininfo); 5015 ok(dword_result == 0, "Expected 0, got %u\n", dword_result); 5016 5017 dword_result = skininfo->lpVtbl->GetNumBoneInfluences(skininfo, 0); 5018 ok(dword_result == 0, "Expected 0, got %u\n", dword_result); 5019 5020 dword_result = skininfo->lpVtbl->GetNumBoneInfluences(skininfo, 1); 5021 ok(dword_result == 0, "Expected 0, got %u\n", dword_result); 5022 5023 transform = skininfo->lpVtbl->GetBoneOffsetMatrix(skininfo, -1); 5024 ok(transform == NULL, "Expected NULL, got %p\n", transform); 5025 5026 { 5027 /* test [GS]etBoneOffsetMatrix */ 5028 hr = skininfo->lpVtbl->SetBoneOffsetMatrix(skininfo, 1, &identity_matrix); 5029 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 5030 5031 hr = skininfo->lpVtbl->SetBoneOffsetMatrix(skininfo, 0, NULL); 5032 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 5033 5034 D3DXMatrixIdentity(&identity_matrix); 5035 hr = skininfo->lpVtbl->SetBoneOffsetMatrix(skininfo, 0, &identity_matrix); 5036 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 5037 5038 transform = skininfo->lpVtbl->GetBoneOffsetMatrix(skininfo, 0); 5039 check_matrix(transform, &identity_matrix); 5040 } 5041 5042 { 5043 /* test [GS]etBoneName */ 5044 const char *name_in = "testBoneName"; 5045 const char *string_result2; 5046 5047 hr = skininfo->lpVtbl->SetBoneName(skininfo, 1, name_in); 5048 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 5049 5050 hr = skininfo->lpVtbl->SetBoneName(skininfo, 0, NULL); 5051 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 5052 5053 hr = skininfo->lpVtbl->SetBoneName(skininfo, 0, name_in); 5054 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 5055 5056 string_result = skininfo->lpVtbl->GetBoneName(skininfo, 0); 5057 ok(string_result != NULL, "Expected non-NULL string, got %p\n", string_result); 5058 ok(!strcmp(string_result, name_in), "Expected '%s', got '%s'\n", name_in, string_result); 5059 5060 string_result2 = skininfo->lpVtbl->GetBoneName(skininfo, 0); 5061 ok(string_result == string_result2, "Expected %p, got %p\n", string_result, string_result2); 5062 5063 string_result = skininfo->lpVtbl->GetBoneName(skininfo, 1); 5064 ok(string_result == NULL, "Expected NULL, got %p\n", string_result); 5065 } 5066 5067 { 5068 /* test [GS]etBoneInfluence */ 5069 DWORD vertices[2]; 5070 FLOAT weights[2]; 5071 int i; 5072 DWORD num_influences; 5073 DWORD exp_vertices[2]; 5074 FLOAT exp_weights[2]; 5075 5076 /* vertex and weight arrays untouched when num_influences is 0 */ 5077 vertices[0] = 0xdeadbeef; 5078 weights[0] = FLT_MAX; 5079 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, vertices, weights); 5080 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 5081 ok(vertices[0] == 0xdeadbeef, "expected 0xdeadbeef, got %#x\n", vertices[0]); 5082 ok(weights[0] == FLT_MAX, "expected %g, got %g\n", FLT_MAX, weights[0]); 5083 5084 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 1, vertices, weights); 5085 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 5086 5087 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, NULL, NULL); 5088 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 5089 5090 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, vertices, NULL); 5091 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 5092 5093 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, NULL, weights); 5094 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 5095 5096 5097 /* no vertex or weight value checking */ 5098 exp_vertices[0] = 0; 5099 exp_vertices[1] = 0x87654321; 5100 exp_weights[0] = 0.5; 5101 exp_weights[1] = NAN; 5102 num_influences = 2; 5103 5104 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 1, num_influences, vertices, weights); 5105 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 5106 5107 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, num_influences, NULL, weights); 5108 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 5109 5110 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, num_influences, vertices, NULL); 5111 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 5112 5113 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, num_influences, NULL, NULL); 5114 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 5115 5116 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, num_influences, exp_vertices, exp_weights); 5117 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 5118 5119 memset(vertices, 0, sizeof(vertices)); 5120 memset(weights, 0, sizeof(weights)); 5121 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, vertices, weights); 5122 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 5123 for (i = 0; i < num_influences; i++) { 5124 ok(exp_vertices[i] == vertices[i], 5125 "influence[%d]: expected vertex %u, got %u\n", i, exp_vertices[i], vertices[i]); 5126 ok((isnan(exp_weights[i]) && isnan(weights[i])) || exp_weights[i] == weights[i], 5127 "influence[%d]: expected weights %g, got %g\n", i, exp_weights[i], weights[i]); 5128 } 5129 5130 /* vertices and weights aren't returned after setting num_influences to 0 */ 5131 memset(vertices, 0, sizeof(vertices)); 5132 memset(weights, 0, sizeof(weights)); 5133 hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, 0, vertices, weights); 5134 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 5135 5136 vertices[0] = 0xdeadbeef; 5137 weights[0] = FLT_MAX; 5138 hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, vertices, weights); 5139 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 5140 ok(vertices[0] == 0xdeadbeef, "expected vertex 0xdeadbeef, got %u\n", vertices[0]); 5141 ok(weights[0] == FLT_MAX, "expected weight %g, got %g\n", FLT_MAX, weights[0]); 5142 } 5143 5144 { 5145 /* test [GS]etFVF and [GS]etDeclaration */ 5146 D3DVERTEXELEMENT9 declaration_in[MAX_FVF_DECL_SIZE]; 5147 DWORD fvf = D3DFVF_XYZ; 5148 DWORD got_fvf; 5149 5150 hr = skininfo->lpVtbl->SetDeclaration(skininfo, NULL); 5151 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 5152 5153 hr = skininfo->lpVtbl->SetDeclaration(skininfo, declaration_with_nonzero_stream); 5154 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 5155 5156 hr = skininfo->lpVtbl->SetFVF(skininfo, 0); 5157 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 5158 5159 hr = D3DXDeclaratorFromFVF(fvf, declaration_in); 5160 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 5161 hr = skininfo->lpVtbl->SetDeclaration(skininfo, declaration_in); 5162 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 5163 got_fvf = skininfo->lpVtbl->GetFVF(skininfo); 5164 ok(fvf == got_fvf, "Expected %#x, got %#x\n", fvf, got_fvf); 5165 hr = skininfo->lpVtbl->GetDeclaration(skininfo, declaration_out); 5166 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 5167 compare_elements(declaration_out, declaration_in, __LINE__, 0); 5168 5169 hr = skininfo->lpVtbl->SetDeclaration(skininfo, empty_declaration); 5170 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 5171 got_fvf = skininfo->lpVtbl->GetFVF(skininfo); 5172 ok(got_fvf == 0, "Expected 0, got %#x\n", got_fvf); 5173 hr = skininfo->lpVtbl->GetDeclaration(skininfo, declaration_out); 5174 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 5175 compare_elements(declaration_out, empty_declaration, __LINE__, 0); 5176 5177 hr = skininfo->lpVtbl->SetFVF(skininfo, fvf); 5178 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 5179 got_fvf = skininfo->lpVtbl->GetFVF(skininfo); 5180 ok(fvf == got_fvf, "Expected %#x, got %#x\n", fvf, got_fvf); 5181 hr = skininfo->lpVtbl->GetDeclaration(skininfo, declaration_out); 5182 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 5183 compare_elements(declaration_out, declaration_in, __LINE__, 0); 5184 } 5185 } 5186 if (skininfo) IUnknown_Release(skininfo); 5187 skininfo = NULL; 5188 5189 hr = D3DXCreateSkinInfoFVF(1, D3DFVF_XYZ, 1, NULL); 5190 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 5191 5192 hr = D3DXCreateSkinInfo(1, NULL, 1, &skininfo); 5193 ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); 5194 } 5195 5196 static void test_convert_adjacency_to_point_reps(void) 5197 { 5198 HRESULT hr; 5199 struct test_context *test_context = NULL; 5200 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM; 5201 const DWORD options_16bit = D3DXMESH_SYSTEMMEM; 5202 const D3DVERTEXELEMENT9 declaration[] = 5203 { 5204 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 5205 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 5206 {0, 24, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0}, 5207 D3DDECL_END() 5208 }; 5209 const unsigned int VERTS_PER_FACE = 3; 5210 void *vertex_buffer; 5211 void *index_buffer; 5212 DWORD *attributes_buffer; 5213 int i, j; 5214 enum color { RED = 0xffff0000, GREEN = 0xff00ff00, BLUE = 0xff0000ff}; 5215 struct vertex_pnc 5216 { 5217 D3DXVECTOR3 position; 5218 D3DXVECTOR3 normal; 5219 enum color color; /* In case of manual visual inspection */ 5220 }; 5221 #ifndef __REACTOS__ 5222 D3DXVECTOR3 up = {0.0f, 0.0f, 1.0f}; 5223 #else 5224 #define up {0.0f, 0.0f, 1.0f} 5225 #endif 5226 /* mesh0 (one face) 5227 * 5228 * 0--1 5229 * | / 5230 * |/ 5231 * 2 5232 */ 5233 const struct vertex_pnc vertices0[] = 5234 { 5235 {{ 0.0f, 3.0f, 0.f}, up, RED}, 5236 {{ 2.0f, 3.0f, 0.f}, up, GREEN}, 5237 {{ 0.0f, 0.0f, 0.f}, up, BLUE}, 5238 }; 5239 const DWORD indices0[] = {0, 1, 2}; 5240 const unsigned int num_vertices0 = ARRAY_SIZE(vertices0); 5241 const unsigned int num_faces0 = ARRAY_SIZE(indices0) / VERTS_PER_FACE; 5242 const DWORD adjacency0[] = {-1, -1, -1}; 5243 const DWORD exp_point_rep0[] = {0, 1, 2}; 5244 /* mesh1 (right) 5245 * 5246 * 0--1 3 5247 * | / /| 5248 * |/ / | 5249 * 2 5--4 5250 */ 5251 const struct vertex_pnc vertices1[] = 5252 { 5253 {{ 0.0f, 3.0f, 0.f}, up, RED}, 5254 {{ 2.0f, 3.0f, 0.f}, up, GREEN}, 5255 {{ 0.0f, 0.0f, 0.f}, up, BLUE}, 5256 5257 {{ 3.0f, 3.0f, 0.f}, up, GREEN}, 5258 {{ 3.0f, 0.0f, 0.f}, up, RED}, 5259 {{ 1.0f, 0.0f, 0.f}, up, BLUE}, 5260 }; 5261 const DWORD indices1[] = {0, 1, 2, 3, 4, 5}; 5262 const unsigned int num_vertices1 = ARRAY_SIZE(vertices1); 5263 const unsigned int num_faces1 = ARRAY_SIZE(indices1) / VERTS_PER_FACE; 5264 const DWORD adjacency1[] = {-1, 1, -1, -1, -1, 0}; 5265 const DWORD exp_point_rep1[] = {0, 1, 2, 1, 4, 2}; 5266 /* mesh2 (left) 5267 * 5268 * 3 0--1 5269 * /| | / 5270 * / | |/ 5271 * 5--4 2 5272 */ 5273 const struct vertex_pnc vertices2[] = 5274 { 5275 {{ 0.0f, 3.0f, 0.f}, up, RED}, 5276 {{ 2.0f, 3.0f, 0.f}, up, GREEN}, 5277 {{ 0.0f, 0.0f, 0.f}, up, BLUE}, 5278 5279 {{-1.0f, 3.0f, 0.f}, up, RED}, 5280 {{-1.0f, 0.0f, 0.f}, up, GREEN}, 5281 {{-3.0f, 0.0f, 0.f}, up, BLUE}, 5282 }; 5283 const DWORD indices2[] = {0, 1, 2, 3, 4, 5}; 5284 const unsigned int num_vertices2 = ARRAY_SIZE(vertices2); 5285 const unsigned int num_faces2 = ARRAY_SIZE(indices2) / VERTS_PER_FACE; 5286 const DWORD adjacency2[] = {-1, -1, 1, 0, -1, -1}; 5287 const DWORD exp_point_rep2[] = {0, 1, 2, 0, 2, 5}; 5288 /* mesh3 (above) 5289 * 5290 * 3 5291 * /| 5292 * / | 5293 * 5--4 5294 * 0--1 5295 * | / 5296 * |/ 5297 * 2 5298 */ 5299 struct vertex_pnc vertices3[] = 5300 { 5301 {{ 0.0f, 3.0f, 0.f}, up, RED}, 5302 {{ 2.0f, 3.0f, 0.f}, up, GREEN}, 5303 {{ 0.0f, 0.0f, 0.f}, up, BLUE}, 5304 5305 {{ 2.0f, 7.0f, 0.f}, up, BLUE}, 5306 {{ 2.0f, 4.0f, 0.f}, up, GREEN}, 5307 {{ 0.0f, 4.0f, 0.f}, up, RED}, 5308 }; 5309 const DWORD indices3[] = {0, 1, 2, 3, 4, 5}; 5310 const unsigned int num_vertices3 = ARRAY_SIZE(vertices3); 5311 const unsigned int num_faces3 = ARRAY_SIZE(indices3) / VERTS_PER_FACE; 5312 const DWORD adjacency3[] = {1, -1, -1, -1, 0, -1}; 5313 const DWORD exp_point_rep3[] = {0, 1, 2, 3, 1, 0}; 5314 /* mesh4 (below, tip against tip) 5315 * 5316 * 0--1 5317 * | / 5318 * |/ 5319 * 2 5320 * 3 5321 * |\ 5322 * | \ 5323 * 5--4 5324 */ 5325 struct vertex_pnc vertices4[] = 5326 { 5327 {{ 0.0f, 3.0f, 0.f}, up, RED}, 5328 {{ 2.0f, 3.0f, 0.f}, up, GREEN}, 5329 {{ 0.0f, 0.0f, 0.f}, up, BLUE}, 5330 5331 {{ 0.0f, -4.0f, 0.f}, up, BLUE}, 5332 {{ 2.0f, -7.0f, 0.f}, up, GREEN}, 5333 {{ 0.0f, -7.0f, 0.f}, up, RED}, 5334 }; 5335 const DWORD indices4[] = {0, 1, 2, 3, 4, 5}; 5336 const unsigned int num_vertices4 = ARRAY_SIZE(vertices4); 5337 const unsigned int num_faces4 = ARRAY_SIZE(indices4) / VERTS_PER_FACE; 5338 const DWORD adjacency4[] = {-1, -1, -1, -1, -1, -1}; 5339 const DWORD exp_point_rep4[] = {0, 1, 2, 3, 4, 5}; 5340 /* mesh5 (gap in mesh) 5341 * 5342 * 0 3-----4 15 5343 * / \ \ / / \ 5344 * / \ \ / / \ 5345 * 2-----1 5 17-----16 5346 * 6-----7 9 12-----13 5347 * \ / / \ \ / 5348 * \ / / \ \ / 5349 * 8 10-----11 14 5350 * 5351 */ 5352 const struct vertex_pnc vertices5[] = 5353 { 5354 {{ 0.0f, 1.0f, 0.f}, up, RED}, 5355 {{ 1.0f, -1.0f, 0.f}, up, GREEN}, 5356 {{-1.0f, -1.0f, 0.f}, up, BLUE}, 5357 5358 {{ 0.1f, 1.0f, 0.f}, up, RED}, 5359 {{ 2.1f, 1.0f, 0.f}, up, BLUE}, 5360 {{ 1.1f, -1.0f, 0.f}, up, GREEN}, 5361 5362 {{-1.0f, -1.1f, 0.f}, up, BLUE}, 5363 {{ 1.0f, -1.1f, 0.f}, up, GREEN}, 5364 {{ 0.0f, -3.1f, 0.f}, up, RED}, 5365 5366 {{ 1.1f, -1.1f, 0.f}, up, GREEN}, 5367 {{ 2.1f, -3.1f, 0.f}, up, BLUE}, 5368 {{ 0.1f, -3.1f, 0.f}, up, RED}, 5369 5370 {{ 1.2f, -1.1f, 0.f}, up, GREEN}, 5371 {{ 3.2f, -1.1f, 0.f}, up, RED}, 5372 {{ 2.2f, -3.1f, 0.f}, up, BLUE}, 5373 5374 {{ 2.2f, 1.0f, 0.f}, up, BLUE}, 5375 {{ 3.2f, -1.0f, 0.f}, up, RED}, 5376 {{ 1.2f, -1.0f, 0.f}, up, GREEN}, 5377 }; 5378 const DWORD indices5[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}; 5379 const unsigned int num_vertices5 = ARRAY_SIZE(vertices5); 5380 const unsigned int num_faces5 = ARRAY_SIZE(indices5) / VERTS_PER_FACE; 5381 const DWORD adjacency5[] = {-1, 2, -1, -1, 5, -1, 0, -1, -1, 4, -1, -1, 5, -1, 3, -1, 4, 1}; 5382 const DWORD exp_point_rep5[] = {0, 1, 2, 3, 4, 5, 2, 1, 8, 5, 10, 11, 5, 13, 10, 4, 13, 5}; 5383 const WORD indices5_16bit[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}; 5384 /* mesh6 (indices re-ordering) 5385 * 5386 * 0--1 6 3 5387 * | / /| |\ 5388 * |/ / | | \ 5389 * 2 8--7 5--4 5390 */ 5391 const struct vertex_pnc vertices6[] = 5392 { 5393 {{ 0.0f, 3.0f, 0.f}, up, RED}, 5394 {{ 2.0f, 3.0f, 0.f}, up, GREEN}, 5395 {{ 0.0f, 0.0f, 0.f}, up, BLUE}, 5396 5397 {{ 3.0f, 3.0f, 0.f}, up, GREEN}, 5398 {{ 3.0f, 0.0f, 0.f}, up, RED}, 5399 {{ 1.0f, 0.0f, 0.f}, up, BLUE}, 5400 5401 {{ 4.0f, 3.0f, 0.f}, up, GREEN}, 5402 {{ 6.0f, 0.0f, 0.f}, up, BLUE}, 5403 {{ 4.0f, 0.0f, 0.f}, up, RED}, 5404 }; 5405 const DWORD indices6[] = {0, 1, 2, 6, 7, 8, 3, 4, 5}; 5406 const unsigned int num_vertices6 = ARRAY_SIZE(vertices6); 5407 const unsigned int num_faces6 = ARRAY_SIZE(indices6) / VERTS_PER_FACE; 5408 const DWORD adjacency6[] = {-1, 1, -1, 2, -1, 0, -1, -1, 1}; 5409 const DWORD exp_point_rep6[] = {0, 1, 2, 1, 4, 5, 1, 5, 2}; 5410 /* mesh7 (expands collapsed triangle) 5411 * 5412 * 0--1 3 5413 * | / /| 5414 * |/ / | 5415 * 2 5--4 5416 */ 5417 const struct vertex_pnc vertices7[] = 5418 { 5419 {{ 0.0f, 3.0f, 0.f}, up, RED}, 5420 {{ 2.0f, 3.0f, 0.f}, up, GREEN}, 5421 {{ 0.0f, 0.0f, 0.f}, up, BLUE}, 5422 5423 {{ 3.0f, 3.0f, 0.f}, up, GREEN}, 5424 {{ 3.0f, 0.0f, 0.f}, up, RED}, 5425 {{ 1.0f, 0.0f, 0.f}, up, BLUE}, 5426 }; 5427 const DWORD indices7[] = {0, 1, 2, 3, 3, 3}; /* Face 1 is collapsed*/ 5428 const unsigned int num_vertices7 = ARRAY_SIZE(vertices7); 5429 const unsigned int num_faces7 = ARRAY_SIZE(indices7) / VERTS_PER_FACE; 5430 const DWORD adjacency7[] = {-1, -1, -1, -1, -1, -1}; 5431 const DWORD exp_point_rep7[] = {0, 1, 2, 3, 4, 5}; 5432 /* mesh8 (indices re-ordering and double replacement) 5433 * 5434 * 0--1 9 6 5435 * | / /| |\ 5436 * |/ / | | \ 5437 * 2 11-10 8--7 5438 * 3--4 5439 * | / 5440 * |/ 5441 * 5 5442 */ 5443 const struct vertex_pnc vertices8[] = 5444 { 5445 {{ 0.0f, 3.0f, 0.f}, up, RED}, 5446 {{ 2.0f, 3.0f, 0.f}, up, GREEN}, 5447 {{ 0.0f, 0.0f, 0.f}, up, BLUE}, 5448 5449 {{ 4.0, -4.0, 0.f}, up, RED}, 5450 {{ 6.0, -4.0, 0.f}, up, BLUE}, 5451 {{ 4.0, -7.0, 0.f}, up, GREEN}, 5452 5453 {{ 4.0f, 3.0f, 0.f}, up, GREEN}, 5454 {{ 6.0f, 0.0f, 0.f}, up, BLUE}, 5455 {{ 4.0f, 0.0f, 0.f}, up, RED}, 5456 5457 {{ 3.0f, 3.0f, 0.f}, up, GREEN}, 5458 {{ 3.0f, 0.0f, 0.f}, up, RED}, 5459 {{ 1.0f, 0.0f, 0.f}, up, BLUE}, 5460 }; 5461 const DWORD indices8[] = {0, 1, 2, 9, 10, 11, 6, 7, 8, 3, 4, 5}; 5462 const unsigned int num_vertices8 = ARRAY_SIZE(vertices8); 5463 const unsigned int num_faces8 = ARRAY_SIZE(indices8) / VERTS_PER_FACE; 5464 const DWORD adjacency8[] = {-1, 1, -1, 2, -1, 0, -1, 3, 1, 2, -1, -1}; 5465 const DWORD exp_point_rep8[] = {0, 1, 2, 3, 4, 5, 1, 4, 3, 1, 3, 2}; 5466 /* mesh9 (right, shared vertices) 5467 * 5468 * 0--1 5469 * | /| 5470 * |/ | 5471 * 2--3 5472 */ 5473 const struct vertex_pnc vertices9[] = 5474 { 5475 {{ 0.0f, 3.0f, 0.f}, up, RED}, 5476 {{ 2.0f, 3.0f, 0.f}, up, GREEN}, 5477 {{ 0.0f, 0.0f, 0.f}, up, BLUE}, 5478 5479 {{ 2.0f, 0.0f, 0.f}, up, RED}, 5480 }; 5481 const DWORD indices9[] = {0, 1, 2, 1, 3, 2}; 5482 const unsigned int num_vertices9 = ARRAY_SIZE(vertices9); 5483 const unsigned int num_faces9 = ARRAY_SIZE(indices9) / VERTS_PER_FACE; 5484 const DWORD adjacency9[] = {-1, 1, -1, -1, -1, 0}; 5485 const DWORD exp_point_rep9[] = {0, 1, 2, 3}; 5486 /* All mesh data */ 5487 ID3DXMesh *mesh = NULL; 5488 ID3DXMesh *mesh_null_check = NULL; 5489 unsigned int attributes[] = {0}; 5490 struct 5491 { 5492 const struct vertex_pnc *vertices; 5493 const DWORD *indices; 5494 const DWORD num_vertices; 5495 const DWORD num_faces; 5496 const DWORD *adjacency; 5497 const DWORD *exp_point_reps; 5498 const DWORD options; 5499 } 5500 tc[] = 5501 { 5502 { 5503 vertices0, 5504 indices0, 5505 num_vertices0, 5506 num_faces0, 5507 adjacency0, 5508 exp_point_rep0, 5509 options 5510 }, 5511 { 5512 vertices1, 5513 indices1, 5514 num_vertices1, 5515 num_faces1, 5516 adjacency1, 5517 exp_point_rep1, 5518 options 5519 }, 5520 { 5521 vertices2, 5522 indices2, 5523 num_vertices2, 5524 num_faces2, 5525 adjacency2, 5526 exp_point_rep2, 5527 options 5528 }, 5529 { 5530 vertices3, 5531 indices3, 5532 num_vertices3, 5533 num_faces3, 5534 adjacency3, 5535 exp_point_rep3, 5536 options 5537 }, 5538 { 5539 vertices4, 5540 indices4, 5541 num_vertices4, 5542 num_faces4, 5543 adjacency4, 5544 exp_point_rep4, 5545 options 5546 }, 5547 { 5548 vertices5, 5549 indices5, 5550 num_vertices5, 5551 num_faces5, 5552 adjacency5, 5553 exp_point_rep5, 5554 options 5555 }, 5556 { 5557 vertices6, 5558 indices6, 5559 num_vertices6, 5560 num_faces6, 5561 adjacency6, 5562 exp_point_rep6, 5563 options 5564 }, 5565 { 5566 vertices7, 5567 indices7, 5568 num_vertices7, 5569 num_faces7, 5570 adjacency7, 5571 exp_point_rep7, 5572 options 5573 }, 5574 { 5575 vertices8, 5576 indices8, 5577 num_vertices8, 5578 num_faces8, 5579 adjacency8, 5580 exp_point_rep8, 5581 options 5582 }, 5583 { 5584 vertices9, 5585 indices9, 5586 num_vertices9, 5587 num_faces9, 5588 adjacency9, 5589 exp_point_rep9, 5590 options 5591 }, 5592 { 5593 vertices5, 5594 (DWORD*)indices5_16bit, 5595 num_vertices5, 5596 num_faces5, 5597 adjacency5, 5598 exp_point_rep5, 5599 options_16bit 5600 }, 5601 }; 5602 DWORD *point_reps = NULL; 5603 5604 test_context = new_test_context(); 5605 if (!test_context) 5606 { 5607 skip("Couldn't create test context\n"); 5608 goto cleanup; 5609 } 5610 5611 for (i = 0; i < ARRAY_SIZE(tc); i++) 5612 { 5613 hr = D3DXCreateMesh(tc[i].num_faces, tc[i].num_vertices, tc[i].options, declaration, 5614 test_context->device, &mesh); 5615 if (FAILED(hr)) 5616 { 5617 skip("Couldn't create mesh %d. Got %x expected D3D_OK\n", i, hr); 5618 goto cleanup; 5619 } 5620 5621 if (i == 0) /* Save first mesh for later NULL checks */ 5622 mesh_null_check = mesh; 5623 5624 point_reps = HeapAlloc(GetProcessHeap(), 0, tc[i].num_vertices * sizeof(*point_reps)); 5625 if (!point_reps) 5626 { 5627 skip("Couldn't allocate point reps array.\n"); 5628 goto cleanup; 5629 } 5630 5631 hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, &vertex_buffer); 5632 if (FAILED(hr)) 5633 { 5634 skip("Couldn't lock vertex buffer.\n"); 5635 goto cleanup; 5636 } 5637 memcpy(vertex_buffer, tc[i].vertices, tc[i].num_vertices * sizeof(*tc[i].vertices)); 5638 hr = mesh->lpVtbl->UnlockVertexBuffer(mesh); 5639 if (FAILED(hr)) 5640 { 5641 skip("Couldn't unlock vertex buffer.\n"); 5642 goto cleanup; 5643 } 5644 5645 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, &index_buffer); 5646 if (FAILED(hr)) 5647 { 5648 skip("Couldn't lock index buffer.\n"); 5649 goto cleanup; 5650 } 5651 if (tc[i].options & D3DXMESH_32BIT) 5652 { 5653 memcpy(index_buffer, tc[i].indices, VERTS_PER_FACE * tc[i].num_faces * sizeof(DWORD)); 5654 } 5655 else 5656 { 5657 memcpy(index_buffer, tc[i].indices, VERTS_PER_FACE * tc[i].num_faces * sizeof(WORD)); 5658 } 5659 hr = mesh->lpVtbl->UnlockIndexBuffer(mesh); 5660 if (FAILED(hr)) { 5661 skip("Couldn't unlock index buffer.\n"); 5662 goto cleanup; 5663 } 5664 5665 hr = mesh->lpVtbl->LockAttributeBuffer(mesh, 0, &attributes_buffer); 5666 if (FAILED(hr)) 5667 { 5668 skip("Couldn't lock attributes buffer.\n"); 5669 goto cleanup; 5670 } 5671 memcpy(attributes_buffer, attributes, sizeof(attributes)); 5672 hr = mesh->lpVtbl->UnlockAttributeBuffer(mesh); 5673 if (FAILED(hr)) 5674 { 5675 skip("Couldn't unlock attributes buffer.\n"); 5676 goto cleanup; 5677 } 5678 5679 /* Convert adjacency to point representation */ 5680 for (j = 0; j < tc[i].num_vertices; j++) point_reps[j] = -1; 5681 hr = mesh->lpVtbl->ConvertAdjacencyToPointReps(mesh, tc[i].adjacency, point_reps); 5682 ok(hr == D3D_OK, "ConvertAdjacencyToPointReps failed case %d. " 5683 "Got %x expected D3D_OK\n", i, hr); 5684 5685 /* Check point representation */ 5686 for (j = 0; j < tc[i].num_vertices; j++) 5687 { 5688 ok(point_reps[j] == tc[i].exp_point_reps[j], 5689 "Unexpected point representation at (%d, %d)." 5690 " Got %d expected %d\n", 5691 i, j, point_reps[j], tc[i].exp_point_reps[j]); 5692 } 5693 5694 HeapFree(GetProcessHeap(), 0, point_reps); 5695 point_reps = NULL; 5696 5697 if (i != 0) /* First mesh will be freed during cleanup */ 5698 mesh->lpVtbl->Release(mesh); 5699 } 5700 5701 /* NULL checks */ 5702 hr = mesh_null_check->lpVtbl->ConvertAdjacencyToPointReps(mesh_null_check, tc[0].adjacency, NULL); 5703 ok(hr == D3DERR_INVALIDCALL, "ConvertAdjacencyToPointReps point_reps NULL. " 5704 "Got %x expected D3DERR_INVALIDCALL\n", hr); 5705 hr = mesh_null_check->lpVtbl->ConvertAdjacencyToPointReps(mesh_null_check, NULL, NULL); 5706 ok(hr == D3DERR_INVALIDCALL, "ConvertAdjacencyToPointReps adjacency and point_reps NULL. " 5707 "Got %x expected D3DERR_INVALIDCALL\n", hr); 5708 5709 cleanup: 5710 if (mesh_null_check) 5711 mesh_null_check->lpVtbl->Release(mesh_null_check); 5712 HeapFree(GetProcessHeap(), 0, point_reps); 5713 free_test_context(test_context); 5714 #ifdef __REACTOS__ 5715 #undef up 5716 #endif 5717 } 5718 5719 static void test_convert_point_reps_to_adjacency(void) 5720 { 5721 HRESULT hr; 5722 struct test_context *test_context = NULL; 5723 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM; 5724 const DWORD options_16bit = D3DXMESH_SYSTEMMEM; 5725 const D3DVERTEXELEMENT9 declaration[] = 5726 { 5727 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 5728 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 5729 {0, 24, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0}, 5730 D3DDECL_END() 5731 }; 5732 const unsigned int VERTS_PER_FACE = 3; 5733 void *vertex_buffer; 5734 void *index_buffer; 5735 DWORD *attributes_buffer; 5736 int i, j; 5737 enum color { RED = 0xffff0000, GREEN = 0xff00ff00, BLUE = 0xff0000ff}; 5738 struct vertex_pnc 5739 { 5740 D3DXVECTOR3 position; 5741 D3DXVECTOR3 normal; 5742 enum color color; /* In case of manual visual inspection */ 5743 }; 5744 #ifndef __REACTOS__ 5745 D3DXVECTOR3 up = {0.0f, 0.0f, 1.0f}; 5746 #else 5747 #define up {0.0f, 0.0f, 1.0f} 5748 #endif 5749 5750 /* mesh0 (one face) 5751 * 5752 * 0--1 5753 * | / 5754 * |/ 5755 * 2 5756 */ 5757 const struct vertex_pnc vertices0[] = 5758 { 5759 {{ 0.0f, 3.0f, 0.f}, up, RED}, 5760 {{ 2.0f, 3.0f, 0.f}, up, GREEN}, 5761 {{ 0.0f, 0.0f, 0.f}, up, BLUE}, 5762 }; 5763 const DWORD indices0[] = {0, 1, 2}; 5764 const unsigned int num_vertices0 = ARRAY_SIZE(vertices0); 5765 const unsigned int num_faces0 = num_vertices0 / VERTS_PER_FACE; 5766 const DWORD exp_adjacency0[] = {-1, -1, -1}; 5767 const DWORD exp_id_adjacency0[] = {-1, -1, -1}; 5768 const DWORD point_rep0[] = {0, 1, 2}; 5769 /* mesh1 (right) 5770 * 5771 * 0--1 3 5772 * | / /| 5773 * |/ / | 5774 * 2 5--4 5775 */ 5776 const struct vertex_pnc vertices1[] = 5777 { 5778 {{ 0.0f, 3.0f, 0.f}, up, RED}, 5779 {{ 2.0f, 3.0f, 0.f}, up, GREEN}, 5780 {{ 0.0f, 0.0f, 0.f}, up, BLUE}, 5781 5782 {{ 3.0f, 3.0f, 0.f}, up, GREEN}, 5783 {{ 3.0f, 0.0f, 0.f}, up, RED}, 5784 {{ 1.0f, 0.0f, 0.f}, up, BLUE}, 5785 }; 5786 const DWORD indices1[] = {0, 1, 2, 3, 4, 5}; 5787 const unsigned int num_vertices1 = ARRAY_SIZE(vertices1); 5788 const unsigned int num_faces1 = num_vertices1 / VERTS_PER_FACE; 5789 const DWORD exp_adjacency1[] = {-1, 1, -1, -1, -1, 0}; 5790 const DWORD exp_id_adjacency1[] = {-1, -1, -1, -1, -1, -1}; 5791 const DWORD point_rep1[] = {0, 1, 2, 1, 4, 2}; 5792 /* mesh2 (left) 5793 * 5794 * 3 0--1 5795 * /| | / 5796 * / | |/ 5797 * 5--4 2 5798 */ 5799 const struct vertex_pnc vertices2[] = 5800 { 5801 {{ 0.0f, 3.0f, 0.f}, up, RED}, 5802 {{ 2.0f, 3.0f, 0.f}, up, GREEN}, 5803 {{ 0.0f, 0.0f, 0.f}, up, BLUE}, 5804 5805 {{-1.0f, 3.0f, 0.f}, up, RED}, 5806 {{-1.0f, 0.0f, 0.f}, up, GREEN}, 5807 {{-3.0f, 0.0f, 0.f}, up, BLUE}, 5808 }; 5809 const DWORD indices2[] = {0, 1, 2, 3, 4, 5}; 5810 const unsigned int num_vertices2 = ARRAY_SIZE(vertices2); 5811 const unsigned int num_faces2 = num_vertices2 / VERTS_PER_FACE; 5812 const DWORD exp_adjacency2[] = {-1, -1, 1, 0, -1, -1}; 5813 const DWORD exp_id_adjacency2[] = {-1, -1, -1, -1, -1, -1}; 5814 const DWORD point_rep2[] = {0, 1, 2, 0, 2, 5}; 5815 /* mesh3 (above) 5816 * 5817 * 3 5818 * /| 5819 * / | 5820 * 5--4 5821 * 0--1 5822 * | / 5823 * |/ 5824 * 2 5825 */ 5826 struct vertex_pnc vertices3[] = 5827 { 5828 {{ 0.0f, 3.0f, 0.f}, up, RED}, 5829 {{ 2.0f, 3.0f, 0.f}, up, GREEN}, 5830 {{ 0.0f, 0.0f, 0.f}, up, BLUE}, 5831 5832 {{ 2.0f, 7.0f, 0.f}, up, BLUE}, 5833 {{ 2.0f, 4.0f, 0.f}, up, GREEN}, 5834 {{ 0.0f, 4.0f, 0.f}, up, RED}, 5835 }; 5836 const DWORD indices3[] = {0, 1, 2, 3, 4, 5}; 5837 const unsigned int num_vertices3 = ARRAY_SIZE(vertices3); 5838 const unsigned int num_faces3 = num_vertices3 / VERTS_PER_FACE; 5839 const DWORD exp_adjacency3[] = {1, -1, -1, -1, 0, -1}; 5840 const DWORD exp_id_adjacency3[] = {-1, -1, -1, -1, -1, -1}; 5841 const DWORD point_rep3[] = {0, 1, 2, 3, 1, 0}; 5842 /* mesh4 (below, tip against tip) 5843 * 5844 * 0--1 5845 * | / 5846 * |/ 5847 * 2 5848 * 3 5849 * |\ 5850 * | \ 5851 * 5--4 5852 */ 5853 struct vertex_pnc vertices4[] = 5854 { 5855 {{ 0.0f, 3.0f, 0.f}, up, RED}, 5856 {{ 2.0f, 3.0f, 0.f}, up, GREEN}, 5857 {{ 0.0f, 0.0f, 0.f}, up, BLUE}, 5858 5859 {{ 0.0f, -4.0f, 0.f}, up, BLUE}, 5860 {{ 2.0f, -7.0f, 0.f}, up, GREEN}, 5861 {{ 0.0f, -7.0f, 0.f}, up, RED}, 5862 }; 5863 const DWORD indices4[] = {0, 1, 2, 3, 4, 5}; 5864 const unsigned int num_vertices4 = ARRAY_SIZE(vertices4); 5865 const unsigned int num_faces4 = num_vertices4 / VERTS_PER_FACE; 5866 const DWORD exp_adjacency4[] = {-1, -1, -1, -1, -1, -1}; 5867 const DWORD exp_id_adjacency4[] = {-1, -1, -1, -1, -1, -1}; 5868 const DWORD point_rep4[] = {0, 1, 2, 3, 4, 5}; 5869 /* mesh5 (gap in mesh) 5870 * 5871 * 0 3-----4 15 5872 * / \ \ / / \ 5873 * / \ \ / / \ 5874 * 2-----1 5 17-----16 5875 * 6-----7 9 12-----13 5876 * \ / / \ \ / 5877 * \ / / \ \ / 5878 * 8 10-----11 14 5879 * 5880 */ 5881 const struct vertex_pnc vertices5[] = 5882 { 5883 {{ 0.0f, 1.0f, 0.f}, up, RED}, 5884 {{ 1.0f, -1.0f, 0.f}, up, GREEN}, 5885 {{-1.0f, -1.0f, 0.f}, up, BLUE}, 5886 5887 {{ 0.1f, 1.0f, 0.f}, up, RED}, 5888 {{ 2.1f, 1.0f, 0.f}, up, BLUE}, 5889 {{ 1.1f, -1.0f, 0.f}, up, GREEN}, 5890 5891 {{-1.0f, -1.1f, 0.f}, up, BLUE}, 5892 {{ 1.0f, -1.1f, 0.f}, up, GREEN}, 5893 {{ 0.0f, -3.1f, 0.f}, up, RED}, 5894 5895 {{ 1.1f, -1.1f, 0.f}, up, GREEN}, 5896 {{ 2.1f, -3.1f, 0.f}, up, BLUE}, 5897 {{ 0.1f, -3.1f, 0.f}, up, RED}, 5898 5899 {{ 1.2f, -1.1f, 0.f}, up, GREEN}, 5900 {{ 3.2f, -1.1f, 0.f}, up, RED}, 5901 {{ 2.2f, -3.1f, 0.f}, up, BLUE}, 5902 5903 {{ 2.2f, 1.0f, 0.f}, up, BLUE}, 5904 {{ 3.2f, -1.0f, 0.f}, up, RED}, 5905 {{ 1.2f, -1.0f, 0.f}, up, GREEN}, 5906 }; 5907 const DWORD indices5[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}; 5908 const unsigned int num_vertices5 = ARRAY_SIZE(vertices5); 5909 const unsigned int num_faces5 = num_vertices5 / VERTS_PER_FACE; 5910 const DWORD exp_adjacency5[] = {-1, 2, -1, -1, 5, -1, 0, -1, -1, 4, -1, -1, 5, -1, 3, -1, 4, 1}; 5911 const DWORD exp_id_adjacency5[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; 5912 const DWORD point_rep5[] = {0, 1, 2, 3, 4, 5, 2, 1, 8, 5, 10, 11, 5, 13, 10, 4, 13, 5}; 5913 /* mesh6 (indices re-ordering) 5914 * 5915 * 0--1 6 3 5916 * | / /| |\ 5917 * |/ / | | \ 5918 * 2 8--7 5--4 5919 */ 5920 const struct vertex_pnc vertices6[] = 5921 { 5922 {{ 0.0f, 3.0f, 0.f}, up, RED}, 5923 {{ 2.0f, 3.0f, 0.f}, up, GREEN}, 5924 {{ 0.0f, 0.0f, 0.f}, up, BLUE}, 5925 5926 {{ 3.0f, 3.0f, 0.f}, up, GREEN}, 5927 {{ 3.0f, 0.0f, 0.f}, up, RED}, 5928 {{ 1.0f, 0.0f, 0.f}, up, BLUE}, 5929 5930 {{ 4.0f, 3.0f, 0.f}, up, GREEN}, 5931 {{ 6.0f, 0.0f, 0.f}, up, BLUE}, 5932 {{ 4.0f, 0.0f, 0.f}, up, RED}, 5933 }; 5934 const DWORD indices6[] = {0, 1, 2, 6, 7, 8, 3, 4, 5}; 5935 const unsigned int num_vertices6 = ARRAY_SIZE(vertices6); 5936 const unsigned int num_faces6 = num_vertices6 / VERTS_PER_FACE; 5937 const DWORD exp_adjacency6[] = {-1, 1, -1, 2, -1, 0, -1, -1, 1}; 5938 const DWORD exp_id_adjacency6[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1}; 5939 const DWORD point_rep6[] = {0, 1, 2, 1, 4, 5, 1, 5, 2}; 5940 /* mesh7 (expands collapsed triangle) 5941 * 5942 * 0--1 3 5943 * | / /| 5944 * |/ / | 5945 * 2 5--4 5946 */ 5947 const struct vertex_pnc vertices7[] = 5948 { 5949 {{ 0.0f, 3.0f, 0.f}, up, RED}, 5950 {{ 2.0f, 3.0f, 0.f}, up, GREEN}, 5951 {{ 0.0f, 0.0f, 0.f}, up, BLUE}, 5952 5953 {{ 3.0f, 3.0f, 0.f}, up, GREEN}, 5954 {{ 3.0f, 0.0f, 0.f}, up, RED}, 5955 {{ 1.0f, 0.0f, 0.f}, up, BLUE}, 5956 }; 5957 const DWORD indices7[] = {0, 1, 2, 3, 3, 3}; /* Face 1 is collapsed*/ 5958 const unsigned int num_vertices7 = ARRAY_SIZE(vertices7); 5959 const unsigned int num_faces7 = num_vertices7 / VERTS_PER_FACE; 5960 const DWORD exp_adjacency7[] = {-1, -1, -1, -1, -1, -1}; 5961 const DWORD exp_id_adjacency7[] = {-1, -1, -1, -1, -1, -1}; 5962 const DWORD point_rep7[] = {0, 1, 2, 3, 4, 5}; 5963 /* mesh8 (indices re-ordering and double replacement) 5964 * 5965 * 0--1 9 6 5966 * | / /| |\ 5967 * |/ / | | \ 5968 * 2 11-10 8--7 5969 * 3--4 5970 * | / 5971 * |/ 5972 * 5 5973 */ 5974 const struct vertex_pnc vertices8[] = 5975 { 5976 {{ 0.0f, 3.0f, 0.f}, up, RED}, 5977 {{ 2.0f, 3.0f, 0.f}, up, GREEN}, 5978 {{ 0.0f, 0.0f, 0.f}, up, BLUE}, 5979 5980 {{ 4.0, -4.0, 0.f}, up, RED}, 5981 {{ 6.0, -4.0, 0.f}, up, BLUE}, 5982 {{ 4.0, -7.0, 0.f}, up, GREEN}, 5983 5984 {{ 4.0f, 3.0f, 0.f}, up, GREEN}, 5985 {{ 6.0f, 0.0f, 0.f}, up, BLUE}, 5986 {{ 4.0f, 0.0f, 0.f}, up, RED}, 5987 5988 {{ 3.0f, 3.0f, 0.f}, up, GREEN}, 5989 {{ 3.0f, 0.0f, 0.f}, up, RED}, 5990 {{ 1.0f, 0.0f, 0.f}, up, BLUE}, 5991 }; 5992 const DWORD indices8[] = {0, 1, 2, 9, 10, 11, 6, 7, 8, 3, 4, 5}; 5993 const WORD indices8_16bit[] = {0, 1, 2, 9, 10, 11, 6, 7, 8, 3, 4, 5}; 5994 const unsigned int num_vertices8 = ARRAY_SIZE(vertices8); 5995 const unsigned int num_faces8 = num_vertices8 / VERTS_PER_FACE; 5996 const DWORD exp_adjacency8[] = {-1, 1, -1, 2, -1, 0, -1, 3, 1, 2, -1, -1}; 5997 const DWORD exp_id_adjacency8[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; 5998 const DWORD point_rep8[] = {0, 1, 2, 3, 4, 5, 1, 4, 3, 1, 3, 2}; 5999 /* mesh9 (right, shared vertices) 6000 * 6001 * 0--1 6002 * | /| 6003 * |/ | 6004 * 2--3 6005 */ 6006 const struct vertex_pnc vertices9[] = 6007 { 6008 {{ 0.0f, 3.0f, 0.f}, up, RED}, 6009 {{ 2.0f, 3.0f, 0.f}, up, GREEN}, 6010 {{ 0.0f, 0.0f, 0.f}, up, BLUE}, 6011 6012 {{ 2.0f, 0.0f, 0.f}, up, RED}, 6013 }; 6014 const DWORD indices9[] = {0, 1, 2, 1, 3, 2}; 6015 const unsigned int num_vertices9 = ARRAY_SIZE(vertices9); 6016 const unsigned int num_faces9 = 2; 6017 const DWORD exp_adjacency9[] = {-1, 1, -1, -1, -1, 0}; 6018 const DWORD exp_id_adjacency9[] = {-1, 1, -1, -1, -1, 0}; 6019 const DWORD point_rep9[] = {0, 1, 2, 3}; 6020 /* All mesh data */ 6021 ID3DXMesh *mesh = NULL; 6022 ID3DXMesh *mesh_null_check = NULL; 6023 unsigned int attributes[] = {0}; 6024 struct 6025 { 6026 const struct vertex_pnc *vertices; 6027 const DWORD *indices; 6028 const DWORD num_vertices; 6029 const DWORD num_faces; 6030 const DWORD *point_reps; 6031 const DWORD *exp_adjacency; 6032 const DWORD *exp_id_adjacency; 6033 const DWORD options; 6034 } 6035 tc[] = 6036 { 6037 { 6038 vertices0, 6039 indices0, 6040 num_vertices0, 6041 num_faces0, 6042 point_rep0, 6043 exp_adjacency0, 6044 exp_id_adjacency0, 6045 options 6046 }, 6047 { 6048 vertices1, 6049 indices1, 6050 num_vertices1, 6051 num_faces1, 6052 point_rep1, 6053 exp_adjacency1, 6054 exp_id_adjacency1, 6055 options 6056 }, 6057 { 6058 vertices2, 6059 indices2, 6060 num_vertices2, 6061 num_faces2, 6062 point_rep2, 6063 exp_adjacency2, 6064 exp_id_adjacency2, 6065 options 6066 }, 6067 { 6068 vertices3, 6069 indices3, 6070 num_vertices3, 6071 num_faces3, 6072 point_rep3, 6073 exp_adjacency3, 6074 exp_id_adjacency3, 6075 options 6076 }, 6077 { 6078 vertices4, 6079 indices4, 6080 num_vertices4, 6081 num_faces4, 6082 point_rep4, 6083 exp_adjacency4, 6084 exp_id_adjacency4, 6085 options 6086 }, 6087 { 6088 vertices5, 6089 indices5, 6090 num_vertices5, 6091 num_faces5, 6092 point_rep5, 6093 exp_adjacency5, 6094 exp_id_adjacency5, 6095 options 6096 }, 6097 { 6098 vertices6, 6099 indices6, 6100 num_vertices6, 6101 num_faces6, 6102 point_rep6, 6103 exp_adjacency6, 6104 exp_id_adjacency6, 6105 options 6106 }, 6107 { 6108 vertices7, 6109 indices7, 6110 num_vertices7, 6111 num_faces7, 6112 point_rep7, 6113 exp_adjacency7, 6114 exp_id_adjacency7, 6115 options 6116 }, 6117 { 6118 vertices8, 6119 indices8, 6120 num_vertices8, 6121 num_faces8, 6122 point_rep8, 6123 exp_adjacency8, 6124 exp_id_adjacency8, 6125 options 6126 }, 6127 { 6128 vertices9, 6129 indices9, 6130 num_vertices9, 6131 num_faces9, 6132 point_rep9, 6133 exp_adjacency9, 6134 exp_id_adjacency9, 6135 options 6136 }, 6137 { 6138 vertices8, 6139 (DWORD*)indices8_16bit, 6140 num_vertices8, 6141 num_faces8, 6142 point_rep8, 6143 exp_adjacency8, 6144 exp_id_adjacency8, 6145 options_16bit 6146 }, 6147 }; 6148 DWORD *adjacency = NULL; 6149 #ifdef __REACTOS__ 6150 #undef up 6151 #endif 6152 6153 test_context = new_test_context(); 6154 if (!test_context) 6155 { 6156 skip("Couldn't create test context\n"); 6157 goto cleanup; 6158 } 6159 6160 for (i = 0; i < ARRAY_SIZE(tc); i++) 6161 { 6162 hr = D3DXCreateMesh(tc[i].num_faces, tc[i].num_vertices, tc[i].options, 6163 declaration, test_context->device, &mesh); 6164 if (FAILED(hr)) 6165 { 6166 skip("Couldn't create mesh %d. Got %x expected D3D_OK\n", i, hr); 6167 goto cleanup; 6168 } 6169 6170 if (i == 0) /* Save first mesh for later NULL checks */ 6171 mesh_null_check = mesh; 6172 6173 adjacency = HeapAlloc(GetProcessHeap(), 0, VERTS_PER_FACE * tc[i].num_faces * sizeof(*adjacency)); 6174 if (!adjacency) 6175 { 6176 skip("Couldn't allocate adjacency array.\n"); 6177 goto cleanup; 6178 } 6179 6180 hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, &vertex_buffer); 6181 if (FAILED(hr)) 6182 { 6183 skip("Couldn't lock vertex buffer.\n"); 6184 goto cleanup; 6185 } 6186 memcpy(vertex_buffer, tc[i].vertices, tc[i].num_vertices * sizeof(*tc[i].vertices)); 6187 hr = mesh->lpVtbl->UnlockVertexBuffer(mesh); 6188 if (FAILED(hr)) 6189 { 6190 skip("Couldn't unlock vertex buffer.\n"); 6191 goto cleanup; 6192 } 6193 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, &index_buffer); 6194 if (FAILED(hr)) 6195 { 6196 skip("Couldn't lock index buffer.\n"); 6197 goto cleanup; 6198 } 6199 if (tc[i].options & D3DXMESH_32BIT) 6200 { 6201 memcpy(index_buffer, tc[i].indices, VERTS_PER_FACE * tc[i].num_faces * sizeof(DWORD)); 6202 } 6203 else 6204 { 6205 memcpy(index_buffer, tc[i].indices, VERTS_PER_FACE * tc[i].num_faces * sizeof(WORD)); 6206 } 6207 hr = mesh->lpVtbl->UnlockIndexBuffer(mesh); 6208 if (FAILED(hr)) { 6209 skip("Couldn't unlock index buffer.\n"); 6210 goto cleanup; 6211 } 6212 6213 hr = mesh->lpVtbl->LockAttributeBuffer(mesh, 0, &attributes_buffer); 6214 if (FAILED(hr)) 6215 { 6216 skip("Couldn't lock attributes buffer.\n"); 6217 goto cleanup; 6218 } 6219 memcpy(attributes_buffer, attributes, sizeof(attributes)); 6220 hr = mesh->lpVtbl->UnlockAttributeBuffer(mesh); 6221 if (FAILED(hr)) 6222 { 6223 skip("Couldn't unlock attributes buffer.\n"); 6224 goto cleanup; 6225 } 6226 6227 /* Convert point representation to adjacency*/ 6228 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++) adjacency[j] = -2; 6229 6230 hr = mesh->lpVtbl->ConvertPointRepsToAdjacency(mesh, tc[i].point_reps, adjacency); 6231 ok(hr == D3D_OK, "ConvertPointRepsToAdjacency failed case %d. " 6232 "Got %x expected D3D_OK\n", i, hr); 6233 /* Check adjacency */ 6234 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++) 6235 { 6236 ok(adjacency[j] == tc[i].exp_adjacency[j], 6237 "Unexpected adjacency information at (%d, %d)." 6238 " Got %d expected %d\n", 6239 i, j, adjacency[j], tc[i].exp_adjacency[j]); 6240 } 6241 6242 /* NULL point representation is considered identity. */ 6243 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++) adjacency[j] = -2; 6244 hr = mesh_null_check->lpVtbl->ConvertPointRepsToAdjacency(mesh, NULL, adjacency); 6245 ok(hr == D3D_OK, "ConvertPointRepsToAdjacency NULL point_reps. " 6246 "Got %x expected D3D_OK\n", hr); 6247 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++) 6248 { 6249 ok(adjacency[j] == tc[i].exp_id_adjacency[j], 6250 "Unexpected adjacency information (id) at (%d, %d)." 6251 " Got %d expected %d\n", 6252 i, j, adjacency[j], tc[i].exp_id_adjacency[j]); 6253 } 6254 6255 HeapFree(GetProcessHeap(), 0, adjacency); 6256 adjacency = NULL; 6257 if (i != 0) /* First mesh will be freed during cleanup */ 6258 mesh->lpVtbl->Release(mesh); 6259 } 6260 6261 /* NULL checks */ 6262 hr = mesh_null_check->lpVtbl->ConvertPointRepsToAdjacency(mesh_null_check, tc[0].point_reps, NULL); 6263 ok(hr == D3DERR_INVALIDCALL, "ConvertPointRepsToAdjacency NULL adjacency. " 6264 "Got %x expected D3DERR_INVALIDCALL\n", hr); 6265 hr = mesh_null_check->lpVtbl->ConvertPointRepsToAdjacency(mesh_null_check, NULL, NULL); 6266 ok(hr == D3DERR_INVALIDCALL, "ConvertPointRepsToAdjacency NULL point_reps and adjacency. " 6267 "Got %x expected D3DERR_INVALIDCALL\n", hr); 6268 6269 cleanup: 6270 if (mesh_null_check) 6271 mesh_null_check->lpVtbl->Release(mesh_null_check); 6272 HeapFree(GetProcessHeap(), 0, adjacency); 6273 free_test_context(test_context); 6274 } 6275 6276 static HRESULT init_test_mesh(const DWORD num_faces, const DWORD num_vertices, 6277 const DWORD options, 6278 const D3DVERTEXELEMENT9 *declaration, 6279 IDirect3DDevice9 *device, ID3DXMesh **mesh_ptr, 6280 const void *vertices, const DWORD vertex_size, 6281 const DWORD *indices, const DWORD *attributes) 6282 { 6283 HRESULT hr; 6284 void *vertex_buffer; 6285 void *index_buffer; 6286 DWORD *attributes_buffer; 6287 ID3DXMesh *mesh = NULL; 6288 6289 hr = D3DXCreateMesh(num_faces, num_vertices, options, declaration, device, mesh_ptr); 6290 if (FAILED(hr)) 6291 { 6292 skip("Couldn't create mesh. Got %x expected D3D_OK\n", hr); 6293 goto cleanup; 6294 } 6295 mesh = *mesh_ptr; 6296 6297 hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, &vertex_buffer); 6298 if (FAILED(hr)) 6299 { 6300 skip("Couldn't lock vertex buffer.\n"); 6301 goto cleanup; 6302 } 6303 memcpy(vertex_buffer, vertices, num_vertices * vertex_size); 6304 hr = mesh->lpVtbl->UnlockVertexBuffer(mesh); 6305 if (FAILED(hr)) 6306 { 6307 skip("Couldn't unlock vertex buffer.\n"); 6308 goto cleanup; 6309 } 6310 6311 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, &index_buffer); 6312 if (FAILED(hr)) 6313 { 6314 skip("Couldn't lock index buffer.\n"); 6315 goto cleanup; 6316 } 6317 if (options & D3DXMESH_32BIT) 6318 { 6319 if (indices) 6320 memcpy(index_buffer, indices, 3 * num_faces * sizeof(DWORD)); 6321 else 6322 { 6323 /* Fill index buffer with 0, 1, 2, ...*/ 6324 DWORD *indices_32bit = (DWORD*)index_buffer; 6325 UINT i; 6326 for (i = 0; i < 3 * num_faces; i++) 6327 indices_32bit[i] = i; 6328 } 6329 } 6330 else 6331 { 6332 if (indices) 6333 memcpy(index_buffer, indices, 3 * num_faces * sizeof(WORD)); 6334 else 6335 { 6336 /* Fill index buffer with 0, 1, 2, ...*/ 6337 WORD *indices_16bit = (WORD*)index_buffer; 6338 UINT i; 6339 for (i = 0; i < 3 * num_faces; i++) 6340 indices_16bit[i] = i; 6341 } 6342 } 6343 hr = mesh->lpVtbl->UnlockIndexBuffer(mesh); 6344 if (FAILED(hr)) { 6345 skip("Couldn't unlock index buffer.\n"); 6346 goto cleanup; 6347 } 6348 6349 hr = mesh->lpVtbl->LockAttributeBuffer(mesh, 0, &attributes_buffer); 6350 if (FAILED(hr)) 6351 { 6352 skip("Couldn't lock attributes buffer.\n"); 6353 goto cleanup; 6354 } 6355 6356 if (attributes) 6357 memcpy(attributes_buffer, attributes, num_faces * sizeof(*attributes)); 6358 else 6359 memset(attributes_buffer, 0, num_faces * sizeof(*attributes)); 6360 6361 hr = mesh->lpVtbl->UnlockAttributeBuffer(mesh); 6362 if (FAILED(hr)) 6363 { 6364 skip("Couldn't unlock attributes buffer.\n"); 6365 goto cleanup; 6366 } 6367 6368 hr = D3D_OK; 6369 cleanup: 6370 return hr; 6371 } 6372 6373 /* Using structs instead of bit-fields in order to avoid compiler issues. */ 6374 struct udec3 6375 { 6376 UINT x; 6377 UINT y; 6378 UINT z; 6379 UINT w; 6380 }; 6381 6382 struct dec3n 6383 { 6384 INT x; 6385 INT y; 6386 INT z; 6387 INT w; 6388 }; 6389 6390 static DWORD init_udec3_dword(UINT x, UINT y, UINT z, UINT w) 6391 { 6392 DWORD d = 0; 6393 6394 d |= x & 0x3ff; 6395 d |= (y << 10) & 0xffc00; 6396 d |= (z << 20) & 0x3ff00000; 6397 d |= (w << 30) & 0xc0000000; 6398 6399 return d; 6400 } 6401 6402 static DWORD init_dec3n_dword(INT x, INT y, INT z, INT w) 6403 { 6404 DWORD d = 0; 6405 6406 d |= x & 0x3ff; 6407 d |= (y << 10) & 0xffc00; 6408 d |= (z << 20) & 0x3ff00000; 6409 d |= (w << 30) & 0xc0000000; 6410 6411 return d; 6412 } 6413 6414 static struct udec3 dword_to_udec3(DWORD d) 6415 { 6416 struct udec3 v; 6417 6418 v.x = d & 0x3ff; 6419 v.y = (d & 0xffc00) >> 10; 6420 v.z = (d & 0x3ff00000) >> 20; 6421 v.w = (d & 0xc0000000) >> 30; 6422 6423 return v; 6424 } 6425 6426 static struct dec3n dword_to_dec3n(DWORD d) 6427 { 6428 struct dec3n v; 6429 6430 v.x = d & 0x3ff; 6431 v.y = (d & 0xffc00) >> 10; 6432 v.z = (d & 0x3ff00000) >> 20; 6433 v.w = (d & 0xc0000000) >> 30; 6434 6435 return v; 6436 } 6437 6438 static void check_vertex_components(int line, int mesh_number, int vertex_number, BYTE *got_ptr, const BYTE *exp_ptr, D3DVERTEXELEMENT9 *declaration) 6439 { 6440 const char *usage_strings[] = 6441 { 6442 "position", 6443 "blend weight", 6444 "blend indices", 6445 "normal", 6446 "point size", 6447 "texture coordinates", 6448 "tangent", 6449 "binormal", 6450 "tessellation factor", 6451 "position transformed", 6452 "color", 6453 "fog", 6454 "depth", 6455 "sample" 6456 }; 6457 D3DVERTEXELEMENT9 *decl_ptr; 6458 const float PRECISION = 1e-5f; 6459 6460 for (decl_ptr = declaration; decl_ptr->Stream != 0xFF; decl_ptr++) 6461 { 6462 switch (decl_ptr->Type) 6463 { 6464 case D3DDECLTYPE_FLOAT1: 6465 { 6466 FLOAT *got = (FLOAT*)(got_ptr + decl_ptr->Offset); 6467 FLOAT *exp = (FLOAT*)(exp_ptr + decl_ptr->Offset); 6468 FLOAT diff = fabsf(*got - *exp); 6469 ok_(__FILE__,line)(diff <= PRECISION, "Mesh %d: Got %f for vertex %d %s, expected %f.\n", 6470 mesh_number, *got, vertex_number, usage_strings[decl_ptr->Usage], *exp); 6471 break; 6472 } 6473 case D3DDECLTYPE_FLOAT2: 6474 { 6475 D3DXVECTOR2 *got = (D3DXVECTOR2*)(got_ptr + decl_ptr->Offset); 6476 D3DXVECTOR2 *exp = (D3DXVECTOR2*)(exp_ptr + decl_ptr->Offset); 6477 FLOAT diff = max(fabsf(got->x - exp->x), fabsf(got->y - exp->y)); 6478 ok_(__FILE__,line)(diff <= PRECISION, "Mesh %d: Got (%f, %f) for vertex %d %s, expected (%f, %f).\n", 6479 mesh_number, got->x, got->y, vertex_number, usage_strings[decl_ptr->Usage], exp->x, exp->y); 6480 break; 6481 } 6482 case D3DDECLTYPE_FLOAT3: 6483 { 6484 D3DXVECTOR3 *got = (D3DXVECTOR3*)(got_ptr + decl_ptr->Offset); 6485 D3DXVECTOR3 *exp = (D3DXVECTOR3*)(exp_ptr + decl_ptr->Offset); 6486 FLOAT diff = max(fabsf(got->x - exp->x), fabsf(got->y - exp->y)); 6487 diff = max(diff, fabsf(got->z - exp->z)); 6488 ok_(__FILE__,line)(diff <= PRECISION, "Mesh %d: Got (%f, %f, %f) for vertex %d %s, expected (%f, %f, %f).\n", 6489 mesh_number, got->x, got->y, got->z, vertex_number, usage_strings[decl_ptr->Usage], exp->x, exp->y, exp->z); 6490 break; 6491 } 6492 case D3DDECLTYPE_FLOAT4: 6493 { 6494 D3DXVECTOR4 *got = (D3DXVECTOR4*)(got_ptr + decl_ptr->Offset); 6495 D3DXVECTOR4 *exp = (D3DXVECTOR4*)(exp_ptr + decl_ptr->Offset); 6496 FLOAT diff = max(fabsf(got->x - exp->x), fabsf(got->y - exp->y)); 6497 diff = max(diff, fabsf(got->z - exp->z)); 6498 diff = max(diff, fabsf(got->w - exp->w)); 6499 ok_(__FILE__,line)(diff <= PRECISION, "Mesh %d: Got (%f, %f, %f, %f) for vertex %d %s, expected (%f, %f, %f, %f).\n", 6500 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); 6501 break; 6502 } 6503 case D3DDECLTYPE_D3DCOLOR: 6504 { 6505 BYTE *got = got_ptr + decl_ptr->Offset; 6506 const BYTE *exp = exp_ptr + decl_ptr->Offset; 6507 BOOL same_color = got[0] == exp[0] && got[1] == exp[1] 6508 && got[2] == exp[2] && got[3] == exp[3]; 6509 const char *color_types[] = {"diffuse", "specular", "undefined color"}; 6510 BYTE usage_index = decl_ptr->UsageIndex; 6511 if (usage_index > 1) usage_index = 2; 6512 ok_(__FILE__,line)(same_color, "Mesh %d: Got (%u, %u, %u, %u) for vertex %d %s, expected (%u, %u, %u, %u).\n", 6513 mesh_number, got[0], got[1], got[2], got[3], vertex_number, color_types[usage_index], exp[0], exp[1], exp[2], exp[3]); 6514 break; 6515 } 6516 case D3DDECLTYPE_UBYTE4: 6517 case D3DDECLTYPE_UBYTE4N: 6518 { 6519 BYTE *got = got_ptr + decl_ptr->Offset; 6520 const BYTE *exp = exp_ptr + decl_ptr->Offset; 6521 BOOL same = got[0] == exp[0] && got[1] == exp[1] 6522 && got[2] == exp[2] && got[3] == exp[3]; 6523 ok_(__FILE__,line)(same, "Mesh %d: Got (%u, %u, %u, %u) for vertex %d %s, expected (%u, %u, %u, %u).\n", 6524 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]); 6525 break; 6526 } 6527 case D3DDECLTYPE_SHORT2: 6528 case D3DDECLTYPE_SHORT2N: 6529 { 6530 SHORT *got = (SHORT*)(got_ptr + decl_ptr->Offset); 6531 SHORT *exp = (SHORT*)(exp_ptr + decl_ptr->Offset); 6532 BOOL same = got[0] == exp[0] && got[1] == exp[1]; 6533 ok_(__FILE__,line)(same, "Mesh %d: Got (%hd, %hd) for vertex %d %s, expected (%hd, %hd).\n", 6534 mesh_number, got[0], got[1], vertex_number, usage_strings[decl_ptr->Usage], exp[0], exp[1]); 6535 break; 6536 } 6537 case D3DDECLTYPE_SHORT4: 6538 case D3DDECLTYPE_SHORT4N: 6539 { 6540 SHORT *got = (SHORT*)(got_ptr + decl_ptr->Offset); 6541 SHORT *exp = (SHORT*)(exp_ptr + decl_ptr->Offset); 6542 BOOL same = got[0] == exp[0] && got[1] == exp[1] 6543 && got[2] == exp[2] && got[3] == exp[3]; 6544 ok_(__FILE__,line)(same, "Mesh %d: Got (%hd, %hd, %hd, %hd) for vertex %d %s, expected (%hd, %hd, %hd, %hd).\n", 6545 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]); 6546 break; 6547 } 6548 case D3DDECLTYPE_USHORT2N: 6549 { 6550 USHORT *got = (USHORT*)(got_ptr + decl_ptr->Offset); 6551 USHORT *exp = (USHORT*)(exp_ptr + decl_ptr->Offset); 6552 BOOL same = got[0] == exp[0] && got[1] == exp[1]; 6553 ok_(__FILE__,line)(same, "Mesh %d: Got (%hu, %hu) for vertex %d %s, expected (%hu, %hu).\n", 6554 mesh_number, got[0], got[1], vertex_number, usage_strings[decl_ptr->Usage], exp[0], exp[1]); 6555 break; 6556 } 6557 case D3DDECLTYPE_USHORT4N: 6558 { 6559 USHORT *got = (USHORT*)(got_ptr + decl_ptr->Offset); 6560 USHORT *exp = (USHORT*)(exp_ptr + decl_ptr->Offset); 6561 BOOL same = got[0] == exp[0] && got[1] == exp[1] 6562 && got[2] == exp[2] && got[3] == exp[3]; 6563 ok_(__FILE__,line)(same, "Mesh %d: Got (%hu, %hu, %hu, %hu) for vertex %d %s, expected (%hu, %hu, %hu, %hu).\n", 6564 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]); 6565 break; 6566 } 6567 case D3DDECLTYPE_UDEC3: 6568 { 6569 DWORD *got = (DWORD*)(got_ptr + decl_ptr->Offset); 6570 DWORD *exp = (DWORD*)(exp_ptr + decl_ptr->Offset); 6571 BOOL same = memcmp(got, exp, sizeof(*got)) == 0; 6572 struct udec3 got_udec3 = dword_to_udec3(*got); 6573 struct udec3 exp_udec3 = dword_to_udec3(*exp); 6574 ok_(__FILE__,line)(same, "Mesh %d: Got (%u, %u, %u, %u) for vertex %d %s, expected (%u, %u, %u, %u).\n", 6575 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); 6576 6577 break; 6578 } 6579 case D3DDECLTYPE_DEC3N: 6580 { 6581 DWORD *got = (DWORD*)(got_ptr + decl_ptr->Offset); 6582 DWORD *exp = (DWORD*)(exp_ptr + decl_ptr->Offset); 6583 BOOL same = memcmp(got, exp, sizeof(*got)) == 0; 6584 struct dec3n got_dec3n = dword_to_dec3n(*got); 6585 struct dec3n exp_dec3n = dword_to_dec3n(*exp); 6586 ok_(__FILE__,line)(same, "Mesh %d: Got (%d, %d, %d, %d) for vertex %d %s, expected (%d, %d, %d, %d).\n", 6587 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); 6588 break; 6589 } 6590 case D3DDECLTYPE_FLOAT16_2: 6591 { 6592 WORD *got = (WORD*)(got_ptr + decl_ptr->Offset); 6593 WORD *exp = (WORD*)(exp_ptr + decl_ptr->Offset); 6594 BOOL same = got[0] == exp[0] && got[1] == exp[1]; 6595 ok_(__FILE__,line)(same, "Mesh %d: Got (%hx, %hx) for vertex %d %s, expected (%hx, %hx).\n", 6596 mesh_number, got[0], got[1], vertex_number, usage_strings[decl_ptr->Usage], exp[0], exp[1]); 6597 break; 6598 } 6599 case D3DDECLTYPE_FLOAT16_4: 6600 { 6601 WORD *got = (WORD*)(got_ptr + decl_ptr->Offset); 6602 WORD *exp = (WORD*)(exp_ptr + decl_ptr->Offset); 6603 BOOL same = got[0] == exp[0] && got[1] == exp[1] 6604 && got[2] == exp[2] && got[3] == exp[3]; 6605 ok_(__FILE__,line)(same, "Mesh %d: Got (%hx, %hx, %hx, %hx) for vertex %d %s, expected (%hx, %hx, %hx, %hx).\n", 6606 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]); 6607 break; 6608 } 6609 default: 6610 break; 6611 } 6612 } 6613 } 6614 6615 static void test_weld_vertices(void) 6616 { 6617 HRESULT hr; 6618 struct test_context *test_context = NULL; 6619 DWORD i; 6620 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM; 6621 const DWORD options_16bit = D3DXMESH_SYSTEMMEM; 6622 BYTE *vertices = NULL; 6623 DWORD *indices = NULL; 6624 WORD *indices_16bit = NULL; 6625 const UINT VERTS_PER_FACE = 3; 6626 #ifndef __REACTOS__ 6627 const D3DXVECTOR3 up = {0.0f, 0.0f, 1.0f}; 6628 #else 6629 #define up {0.0f, 0.0f, 1.0f} 6630 #endif 6631 struct vertex_normal 6632 { 6633 D3DXVECTOR3 position; 6634 D3DXVECTOR3 normal; 6635 }; 6636 struct vertex_blendweight 6637 { 6638 D3DXVECTOR3 position; 6639 FLOAT blendweight; 6640 }; 6641 struct vertex_texcoord 6642 { 6643 D3DXVECTOR3 position; 6644 D3DXVECTOR2 texcoord; 6645 }; 6646 struct vertex_color 6647 { 6648 D3DXVECTOR3 position; 6649 DWORD color; 6650 }; 6651 struct vertex_color_ubyte4 6652 { 6653 D3DXVECTOR3 position; 6654 BYTE color[4]; 6655 }; 6656 struct vertex_texcoord_short2 6657 { 6658 D3DXVECTOR3 position; 6659 SHORT texcoord[2]; 6660 }; 6661 struct vertex_texcoord_ushort2n 6662 { 6663 D3DXVECTOR3 position; 6664 USHORT texcoord[2]; 6665 }; 6666 struct vertex_normal_short4 6667 { 6668 D3DXVECTOR3 position; 6669 SHORT normal[4]; 6670 }; 6671 struct vertex_texcoord_float16_2 6672 { 6673 D3DXVECTOR3 position; 6674 WORD texcoord[2]; 6675 }; 6676 struct vertex_texcoord_float16_4 6677 { 6678 D3DXVECTOR3 position; 6679 WORD texcoord[4]; 6680 }; 6681 struct vertex_normal_udec3 6682 { 6683 D3DXVECTOR3 position; 6684 DWORD normal; 6685 }; 6686 struct vertex_normal_dec3n 6687 { 6688 D3DXVECTOR3 position; 6689 DWORD normal; 6690 }; 6691 UINT vertex_size_normal = sizeof(struct vertex_normal); 6692 UINT vertex_size_blendweight = sizeof(struct vertex_blendweight); 6693 UINT vertex_size_texcoord = sizeof(struct vertex_texcoord); 6694 UINT vertex_size_color = sizeof(struct vertex_color); 6695 UINT vertex_size_color_ubyte4 = sizeof(struct vertex_color_ubyte4); 6696 UINT vertex_size_texcoord_short2 = sizeof(struct vertex_texcoord_short2); 6697 UINT vertex_size_normal_short4 = sizeof(struct vertex_normal_short4); 6698 UINT vertex_size_texcoord_float16_2 = sizeof(struct vertex_texcoord_float16_2); 6699 UINT vertex_size_texcoord_float16_4 = sizeof(struct vertex_texcoord_float16_4); 6700 UINT vertex_size_normal_udec3 = sizeof(struct vertex_normal_udec3); 6701 UINT vertex_size_normal_dec3n = sizeof(struct vertex_normal_dec3n); 6702 D3DVERTEXELEMENT9 declaration_normal[] = 6703 { 6704 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 6705 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 6706 D3DDECL_END() 6707 }; 6708 D3DVERTEXELEMENT9 declaration_normal3[] = 6709 { 6710 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 3}, 6711 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 6712 D3DDECL_END() 6713 }; 6714 D3DVERTEXELEMENT9 declaration_blendweight[] = 6715 { 6716 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 6717 {0, 12, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BLENDWEIGHT, 0}, 6718 D3DDECL_END() 6719 }; 6720 D3DVERTEXELEMENT9 declaration_texcoord[] = 6721 { 6722 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 6723 {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 6724 D3DDECL_END() 6725 }; 6726 D3DVERTEXELEMENT9 declaration_color[] = 6727 { 6728 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 6729 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0}, 6730 D3DDECL_END() 6731 }; 6732 D3DVERTEXELEMENT9 declaration_color_ubyte4n[] = 6733 { 6734 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 6735 {0, 12, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0}, 6736 D3DDECL_END() 6737 }; 6738 D3DVERTEXELEMENT9 declaration_color_ubyte4[] = 6739 { 6740 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 6741 {0, 12, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0}, 6742 D3DDECL_END() 6743 }; 6744 D3DVERTEXELEMENT9 declaration_texcoord_short2[] = 6745 { 6746 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 6747 {0, 12, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 6748 D3DDECL_END() 6749 }; 6750 D3DVERTEXELEMENT9 declaration_texcoord_short2n[] = 6751 { 6752 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 6753 {0, 12, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 6754 D3DDECL_END() 6755 }; 6756 D3DVERTEXELEMENT9 declaration_texcoord_ushort2n[] = 6757 { 6758 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 6759 {0, 12, D3DDECLTYPE_USHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 6760 D3DDECL_END() 6761 }; 6762 D3DVERTEXELEMENT9 declaration_normal_short4[] = 6763 { 6764 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 6765 {0, 12, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 6766 D3DDECL_END() 6767 }; 6768 D3DVERTEXELEMENT9 declaration_normal_short4n[] = 6769 { 6770 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 6771 {0, 12, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 6772 D3DDECL_END() 6773 }; 6774 D3DVERTEXELEMENT9 declaration_normal_ushort4n[] = 6775 { 6776 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 6777 {0, 12, D3DDECLTYPE_USHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 6778 D3DDECL_END() 6779 }; 6780 D3DVERTEXELEMENT9 declaration_texcoord10[] = 6781 { 6782 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 6783 {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 10}, 6784 D3DDECL_END() 6785 }; 6786 D3DVERTEXELEMENT9 declaration_color2[] = 6787 { 6788 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 6789 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 2}, 6790 D3DDECL_END() 6791 }; 6792 D3DVERTEXELEMENT9 declaration_color1[] = 6793 { 6794 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 6795 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 1}, 6796 D3DDECL_END() 6797 }; 6798 D3DVERTEXELEMENT9 declaration_texcoord_float16_2[] = 6799 { 6800 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 6801 {0, 12, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 6802 D3DDECL_END() 6803 }; 6804 D3DVERTEXELEMENT9 declaration_texcoord_float16_4[] = 6805 { 6806 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 6807 {0, 12, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 6808 D3DDECL_END() 6809 }; 6810 D3DVERTEXELEMENT9 declaration_normal_udec3[] = 6811 { 6812 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 6813 {0, 12, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 6814 D3DDECL_END() 6815 }; 6816 D3DVERTEXELEMENT9 declaration_normal_dec3n[] = 6817 { 6818 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 6819 {0, 12, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 6820 D3DDECL_END() 6821 }; 6822 /* Test 0. One face and no welding. 6823 * 6824 * 0--1 6825 * | / 6826 * |/ 6827 * 2 6828 */ 6829 const struct vertex vertices0[] = 6830 { 6831 {{ 0.0f, 3.0f, 0.f}, up}, 6832 {{ 2.0f, 3.0f, 0.f}, up}, 6833 {{ 0.0f, 0.0f, 0.f}, up}, 6834 }; 6835 const DWORD indices0[] = {0, 1, 2}; 6836 const DWORD attributes0[] = {0}; 6837 const DWORD exp_indices0[] = {0, 1, 2}; 6838 const UINT num_vertices0 = ARRAY_SIZE(vertices0); 6839 const UINT num_faces0 = ARRAY_SIZE(indices0) / VERTS_PER_FACE; 6840 const DWORD flags0 = D3DXWELDEPSILONS_WELDALL; 6841 /* epsilons0 is NULL */ 6842 const DWORD adjacency0[] = {-1, -1, -1}; 6843 const struct vertex exp_vertices0[] = 6844 { 6845 {{ 0.0f, 3.0f, 0.f}, up}, 6846 {{ 2.0f, 3.0f, 0.f}, up}, 6847 {{ 0.0f, 0.0f, 0.f}, up}, 6848 }; 6849 const DWORD exp_face_remap0[] = {0}; 6850 const DWORD exp_vertex_remap0[] = {0, 1, 2}; 6851 const DWORD exp_new_num_vertices0 = ARRAY_SIZE(exp_vertices0); 6852 /* Test 1. Two vertices should be removed without regard to epsilon. 6853 * 6854 * 0--1 3 6855 * | / /| 6856 * |/ / | 6857 * 2 5--4 6858 */ 6859 const struct vertex_normal vertices1[] = 6860 { 6861 {{ 0.0f, 3.0f, 0.f}, up}, 6862 {{ 2.0f, 3.0f, 0.f}, up}, 6863 {{ 0.0f, 0.0f, 0.f}, up}, 6864 6865 {{ 3.0f, 3.0f, 0.f}, up}, 6866 {{ 3.0f, 0.0f, 0.f}, up}, 6867 {{ 1.0f, 0.0f, 0.f}, up}, 6868 }; 6869 const DWORD indices1[] = {0, 1, 2, 3, 4, 5}; 6870 const DWORD attributes1[] = {0, 0}; 6871 const UINT num_vertices1 = ARRAY_SIZE(vertices1); 6872 const UINT num_faces1 = ARRAY_SIZE(indices1) / VERTS_PER_FACE; 6873 const DWORD flags1 = D3DXWELDEPSILONS_WELDALL; 6874 /* epsilons1 is NULL */ 6875 const DWORD adjacency1[] = {-1, 1, -1, -1, -1, 0}; 6876 const struct vertex_normal exp_vertices1[] = 6877 { 6878 {{ 0.0f, 3.0f, 0.f}, up}, 6879 {{ 2.0f, 3.0f, 0.f}, up}, 6880 {{ 0.0f, 0.0f, 0.f}, up}, 6881 6882 {{ 3.0f, 0.0f, 0.f}, up} 6883 }; 6884 const DWORD exp_indices1[] = {0, 1, 2, 1, 3, 2}; 6885 const DWORD exp_face_remap1[] = {0, 1}; 6886 const DWORD exp_vertex_remap1[] = {0, 1, 2, 4, -1, -1}; 6887 const DWORD exp_new_num_vertices1 = ARRAY_SIZE(exp_vertices1); 6888 /* Test 2. Two faces. No vertices should be removed because of normal 6889 * epsilon, but the positions should be replaced. */ 6890 const struct vertex_normal vertices2[] = 6891 { 6892 {{ 0.0f, 3.0f, 0.f}, up}, 6893 {{ 2.0f, 3.0f, 0.f}, up}, 6894 {{ 0.0f, 0.0f, 0.f}, up}, 6895 6896 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}}, 6897 {{ 3.0f, 0.0f, 0.f}, up}, 6898 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}}, 6899 }; 6900 const DWORD indices2[] = {0, 1, 2, 3, 4, 5}; 6901 const DWORD attributes2[] = {0, 0}; 6902 const UINT num_vertices2 = ARRAY_SIZE(vertices2); 6903 const UINT num_faces2 = ARRAY_SIZE(indices2) / VERTS_PER_FACE; 6904 DWORD flags2 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 6905 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}; 6906 const DWORD adjacency2[] = {-1, 1, -1, -1, -1, 0}; 6907 const struct vertex_normal exp_vertices2[] = 6908 { 6909 {{ 0.0f, 3.0f, 0.f}, up}, 6910 {{ 2.0f, 3.0f, 0.f}, up}, 6911 {{ 0.0f, 0.0f, 0.f}, up}, 6912 6913 {{ 2.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}}, 6914 {{ 3.0f, 0.0f, 0.f}, up}, 6915 {{ 0.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}}, 6916 }; 6917 const DWORD exp_indices2[] = {0, 1, 2, 3, 4, 5}; 6918 const DWORD exp_face_remap2[] = {0, 1}; 6919 const DWORD exp_vertex_remap2[] = {0, 1, 2, 3, 4, 5}; 6920 const DWORD exp_new_num_vertices2 = ARRAY_SIZE(exp_vertices2); 6921 /* Test 3. Two faces. One vertex should be removed because of normal epsilon. */ 6922 const struct vertex_normal vertices3[] = 6923 { 6924 {{ 0.0f, 3.0f, 0.f}, up}, 6925 {{ 2.0f, 3.0f, 0.f}, up}, 6926 {{ 0.0f, 0.0f, 0.f}, up}, 6927 6928 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}}, 6929 {{ 3.0f, 0.0f, 0.f}, up}, 6930 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}}, 6931 }; 6932 const DWORD indices3[] = {0, 1, 2, 3, 4, 5}; 6933 const DWORD attributes3[] = {0, 0}; 6934 const UINT num_vertices3 = ARRAY_SIZE(vertices3); 6935 const UINT num_faces3 = ARRAY_SIZE(indices3) / VERTS_PER_FACE; 6936 DWORD flags3 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 6937 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}; 6938 const DWORD adjacency3[] = {-1, 1, -1, -1, -1, 0}; 6939 const struct vertex_normal exp_vertices3[] = 6940 { 6941 {{ 0.0f, 3.0f, 0.f}, up}, 6942 {{ 2.0f, 3.0f, 0.f}, up}, 6943 {{ 0.0f, 0.0f, 0.f}, up}, 6944 6945 {{ 3.0f, 0.0f, 0.f}, up}, 6946 {{ 0.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}}, 6947 }; 6948 const DWORD exp_indices3[] = {0, 1, 2, 1, 3, 4}; 6949 const DWORD exp_face_remap3[] = {0, 1}; 6950 const DWORD exp_vertex_remap3[] = {0, 1, 2, 4, 5, -1}; 6951 const DWORD exp_new_num_vertices3 = ARRAY_SIZE(exp_vertices3); 6952 /* Test 4 Two faces. Two vertices should be removed. */ 6953 const struct vertex_normal vertices4[] = 6954 { 6955 {{ 0.0f, 3.0f, 0.f}, up}, 6956 {{ 2.0f, 3.0f, 0.f}, up}, 6957 {{ 0.0f, 0.0f, 0.f}, up}, 6958 6959 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}}, 6960 {{ 3.0f, 0.0f, 0.f}, up}, 6961 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}}, 6962 }; 6963 const DWORD indices4[] = {0, 1, 2, 3, 4, 5}; 6964 const DWORD attributes4[] = {0, 0}; 6965 const UINT num_vertices4 = ARRAY_SIZE(vertices4); 6966 const UINT num_faces4 = ARRAY_SIZE(indices4) / VERTS_PER_FACE; 6967 DWORD flags4 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 6968 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}; 6969 const DWORD adjacency4[] = {-1, 1, -1, -1, -1, 0}; 6970 const struct vertex_normal exp_vertices4[] = 6971 { 6972 {{ 0.0f, 3.0f, 0.f}, up}, 6973 {{ 2.0f, 3.0f, 0.f}, up}, 6974 {{ 0.0f, 0.0f, 0.f}, up}, 6975 6976 {{ 3.0f, 0.0f, 0.f}, up}, 6977 }; 6978 const DWORD exp_indices4[] = {0, 1, 2, 1, 3, 2}; 6979 const DWORD exp_face_remap4[] = {0, 1}; 6980 const DWORD exp_vertex_remap4[] = {0, 1, 2, 4, -1, -1}; 6981 const DWORD exp_new_num_vertices4 = ARRAY_SIZE(exp_vertices4); 6982 /* Test 5. Odd face ordering. 6983 * 6984 * 0--1 6 3 6985 * | / /| |\ 6986 * |/ / | | \ 6987 * 2 8--7 5--4 6988 */ 6989 const struct vertex_normal vertices5[] = 6990 { 6991 {{ 0.0f, 3.0f, 0.f}, up}, 6992 {{ 2.0f, 3.0f, 0.f}, up}, 6993 {{ 0.0f, 0.0f, 0.f}, up}, 6994 6995 {{ 3.0f, 3.0f, 0.f}, up}, 6996 {{ 3.0f, 0.0f, 0.f}, up}, 6997 {{ 1.0f, 0.0f, 0.f}, up}, 6998 6999 {{ 4.0f, 3.0f, 0.f}, up}, 7000 {{ 6.0f, 0.0f, 0.f}, up}, 7001 {{ 4.0f, 0.0f, 0.f}, up}, 7002 }; 7003 const DWORD indices5[] = {0, 1, 2, 6, 7, 8, 3, 4, 5}; 7004 const DWORD exp_indices5[] = {0, 1, 2, 1, 4, 2, 1, 3, 4}; 7005 const DWORD attributes5[] = {0, 0, 0}; 7006 const UINT num_vertices5 = ARRAY_SIZE(vertices5); 7007 const UINT num_faces5 = ARRAY_SIZE(indices5) / VERTS_PER_FACE; 7008 DWORD flags5 = D3DXWELDEPSILONS_WELDALL; 7009 const DWORD adjacency5[] = {-1, 1, -1, 2, -1, 0, -1, -1, 1}; 7010 const struct vertex_normal exp_vertices5[] = 7011 { 7012 {{ 0.0f, 3.0f, 0.f}, up}, 7013 {{ 2.0f, 3.0f, 0.f}, up}, 7014 {{ 0.0f, 0.0f, 0.f}, up}, 7015 7016 {{ 3.0f, 0.0f, 0.f}, up}, 7017 {{ 1.0f, 0.0f, 0.f}, up}, 7018 }; 7019 const DWORD exp_face_remap5[] = {0, 1, 2}; 7020 const DWORD exp_vertex_remap5[] = {0, 1, 2, 4, 5, -1, -1, -1, -1}; 7021 const DWORD exp_new_num_vertices5 = ARRAY_SIZE(exp_vertices5); 7022 /* Test 6. Two faces. Do not remove flag is used, so no vertices should be 7023 * removed. */ 7024 const struct vertex_normal vertices6[] = 7025 { 7026 {{ 0.0f, 3.0f, 0.f}, up}, 7027 {{ 2.0f, 3.0f, 0.f}, up}, 7028 {{ 0.0f, 0.0f, 0.f}, up}, 7029 7030 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}}, 7031 {{ 3.0f, 0.0f, 0.f}, up}, 7032 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}}, 7033 }; 7034 const DWORD indices6[] = {0, 1, 2, 3, 4, 5}; 7035 const DWORD attributes6[] = {0, 0}; 7036 const UINT num_vertices6 = ARRAY_SIZE(vertices6); 7037 const UINT num_faces6 = ARRAY_SIZE(indices6) / VERTS_PER_FACE; 7038 DWORD flags6 = D3DXWELDEPSILONS_WELDPARTIALMATCHES | D3DXWELDEPSILONS_DONOTREMOVEVERTICES; 7039 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}; 7040 const DWORD adjacency6[] = {-1, 1, -1, -1, -1, 0}; 7041 const struct vertex_normal exp_vertices6[] = 7042 { 7043 {{ 0.0f, 3.0f, 0.f}, up}, 7044 {{ 2.0f, 3.0f, 0.f}, up}, 7045 {{ 0.0f, 0.0f, 0.f}, up}, 7046 7047 {{ 2.0f, 3.0f, 0.f}, up}, 7048 {{ 3.0f, 0.0f, 0.f}, up}, 7049 {{ 0.0f, 0.0f, 0.f}, up}, 7050 7051 }; 7052 const DWORD exp_indices6[] = {0, 1, 2, 3, 4, 5}; 7053 const DWORD exp_face_remap6[] = {0, 1}; 7054 const DWORD exp_vertex_remap6[] = {0, 1, 2, 3, 4, 5}; 7055 const DWORD exp_new_num_vertices6 = ARRAY_SIZE(exp_vertices6); 7056 /* Test 7. Same as test 6 but with 16 bit indices. */ 7057 const WORD indices6_16bit[] = {0, 1, 2, 3, 4, 5}; 7058 /* Test 8. No flags. Same result as D3DXWELDEPSILONS_WELDPARTIALMATCHES. */ 7059 const struct vertex_normal vertices8[] = 7060 { 7061 {{ 0.0f, 3.0f, 0.f}, up}, 7062 {{ 2.0f, 3.0f, 0.f}, up}, 7063 {{ 0.0f, 0.0f, 0.f}, up}, 7064 7065 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}}, 7066 {{ 3.0f, 0.0f, 0.f}, up}, 7067 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}}, 7068 }; 7069 const DWORD indices8[] = {0, 1, 2, 1, 3, 4}; 7070 const DWORD attributes8[] = {0, 0}; 7071 const UINT num_vertices8 = ARRAY_SIZE(vertices8); 7072 const UINT num_faces8 = ARRAY_SIZE(indices8) / VERTS_PER_FACE; 7073 DWORD flags8 = 0; 7074 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}; 7075 const DWORD adjacency8[] = {-1, 1, -1, -1, -1, 0}; 7076 const struct vertex_normal exp_vertices8[] = 7077 { 7078 {{ 0.0f, 3.0f, 0.f}, up}, 7079 {{ 2.0f, 3.0f, 0.f}, up}, 7080 {{ 0.0f, 0.0f, 0.f}, up}, 7081 7082 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}}, 7083 {{ 3.0f, 0.0f, 0.f}, up}, 7084 }; 7085 const DWORD exp_indices8[] = {0, 1, 2, 1, 3, 4}; 7086 const DWORD exp_face_remap8[] = {0, 1}; 7087 const DWORD exp_vertex_remap8[] = {0, 1, 2, 3, 4, -1}; 7088 const DWORD exp_new_num_vertices8 = ARRAY_SIZE(exp_vertices8); 7089 /* Test 9. Vertices are removed even though they belong to separate 7090 * attribute groups if D3DXWELDEPSILONS_DONOTSPLIT is set. */ 7091 const struct vertex_normal vertices9[] = 7092 { 7093 {{ 0.0f, 3.0f, 0.f}, up}, 7094 {{ 2.0f, 3.0f, 0.f}, up}, 7095 {{ 0.0f, 0.0f, 0.f}, up}, 7096 7097 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}}, 7098 {{ 3.0f, 0.0f, 0.f}, up}, 7099 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}}, 7100 }; 7101 const DWORD indices9[] = {0, 1, 2, 3, 4, 5}; 7102 const DWORD attributes9[] = {0, 1}; 7103 const UINT num_vertices9 = ARRAY_SIZE(vertices9); 7104 const UINT num_faces9 = ARRAY_SIZE(indices9) / VERTS_PER_FACE; 7105 DWORD flags9 = D3DXWELDEPSILONS_WELDPARTIALMATCHES | D3DXWELDEPSILONS_DONOTSPLIT; 7106 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}; 7107 const DWORD adjacency9[] = {-1, 1, -1, -1, -1, 0}; 7108 const struct vertex_normal exp_vertices9[] = 7109 { 7110 {{ 0.0f, 3.0f, 0.f}, up}, 7111 {{ 2.0f, 3.0f, 0.f}, up}, 7112 {{ 0.0f, 0.0f, 0.f}, up}, 7113 7114 {{ 3.0f, 0.0f, 0.f}, up}, 7115 }; 7116 const DWORD exp_indices9[] = {0, 1, 2, 1, 3, 2}; 7117 const DWORD exp_face_remap9[] = {0, 1}; 7118 const DWORD exp_vertex_remap9[] = {0, 1, 2, 4, -1, -1}; 7119 const DWORD exp_new_num_vertices9 = ARRAY_SIZE(exp_vertices9); 7120 /* Test 10. Weld blendweight (FLOAT1). */ 7121 const struct vertex_blendweight vertices10[] = 7122 { 7123 {{ 0.0f, 3.0f, 0.f}, 1.0f}, 7124 {{ 2.0f, 3.0f, 0.f}, 1.0f}, 7125 {{ 0.0f, 0.0f, 0.f}, 1.0f}, 7126 7127 {{ 3.0f, 3.0f, 0.f}, 0.9}, 7128 {{ 3.0f, 0.0f, 0.f}, 1.0}, 7129 {{ 1.0f, 0.0f, 0.f}, 0.4}, 7130 }; 7131 const DWORD indices10[] = {0, 1, 2, 3, 4, 5}; 7132 const DWORD attributes10[] = {0, 0}; 7133 const UINT num_vertices10 = ARRAY_SIZE(vertices10); 7134 const UINT num_faces10 = ARRAY_SIZE(indices10) / VERTS_PER_FACE; 7135 DWORD flags10 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7136 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}; 7137 const DWORD adjacency10[] = {-1, 1, -1, -1, -1, 0}; 7138 const struct vertex_blendweight exp_vertices10[] = 7139 { 7140 {{ 0.0f, 3.0f, 0.f}, 1.0f}, 7141 {{ 2.0f, 3.0f, 0.f}, 1.0f}, 7142 {{ 0.0f, 0.0f, 0.f}, 1.0f}, 7143 7144 {{ 3.0f, 0.0f, 0.f}, 1.0}, 7145 {{ 0.0f, 0.0f, 0.f}, 0.4}, 7146 }; 7147 const DWORD exp_indices10[] = {0, 1, 2, 1, 3, 4}; 7148 const DWORD exp_face_remap10[] = {0, 1}; 7149 const DWORD exp_vertex_remap10[] = {0, 1, 2, 4, 5, -1}; 7150 const DWORD exp_new_num_vertices10 = ARRAY_SIZE(exp_vertices10); 7151 /* Test 11. Weld texture coordinates. */ 7152 const struct vertex_texcoord vertices11[] = 7153 { 7154 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f}}, 7155 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.7f}}, 7156 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}}, 7157 7158 {{ 3.0f, 3.0f, 0.f}, {0.2f, 0.3f}}, 7159 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f}}, 7160 {{ 1.0f, 0.0f, 0.f}, {0.1f, 0.2f}} 7161 }; 7162 const DWORD indices11[] = {0, 1, 2, 3, 4, 5}; 7163 const DWORD attributes11[] = {0, 0}; 7164 const UINT num_vertices11 = ARRAY_SIZE(vertices11); 7165 const UINT num_faces11 = ARRAY_SIZE(indices11) / VERTS_PER_FACE; 7166 DWORD flags11 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7167 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}; 7168 const DWORD adjacency11[] = {-1, 1, -1, -1, -1, 0}; 7169 const struct vertex_texcoord exp_vertices11[] = 7170 { 7171 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f}}, 7172 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.7f}}, 7173 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}}, 7174 7175 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f}}, 7176 {{ 0.0f, 0.0f, 0.f}, {0.1f, 0.2f}}, 7177 }; 7178 const DWORD exp_indices11[] = {0, 1, 2, 1, 3, 4}; 7179 const DWORD exp_face_remap11[] = {0, 1}; 7180 const DWORD exp_vertex_remap11[] = {0, 1, 2, 4, 5, -1}; 7181 const DWORD exp_new_num_vertices11 = ARRAY_SIZE(exp_vertices11); 7182 /* Test 12. Weld with color. */ 7183 const struct vertex_color vertices12[] = 7184 { 7185 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF}, 7186 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF}, 7187 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF}, 7188 7189 {{ 3.0f, 3.0f, 0.f}, 0x00000000}, 7190 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF}, 7191 {{ 1.0f, 0.0f, 0.f}, 0x88888888}, 7192 }; 7193 const DWORD indices12[] = {0, 1, 2, 3, 4, 5}; 7194 const DWORD attributes12[] = {0, 0}; 7195 const UINT num_vertices12 = ARRAY_SIZE(vertices12); 7196 const UINT num_faces12 = ARRAY_SIZE(indices12) / VERTS_PER_FACE; 7197 DWORD flags12 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7198 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}; 7199 const DWORD adjacency12[] = {-1, 1, -1, -1, -1, 0}; 7200 const struct vertex_color exp_vertices12[] = 7201 { 7202 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF}, 7203 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF}, 7204 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF}, 7205 7206 {{ 2.0f, 3.0f, 0.f}, 0x00000000}, 7207 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF}, 7208 }; 7209 const DWORD exp_indices12[] = {0, 1, 2, 3, 4, 2}; 7210 const DWORD exp_face_remap12[] = {0, 1}; 7211 const DWORD exp_vertex_remap12[] = {0, 1, 2, 3, 4, -1}; 7212 const DWORD exp_new_num_vertices12 = ARRAY_SIZE(exp_vertices12); 7213 /* Test 13. Two faces. One vertex should be removed because of normal epsilon. 7214 * This is similar to test 3, but the declaration has been changed to NORMAL3. 7215 */ 7216 const struct vertex_normal vertices13[] = 7217 { 7218 {{ 0.0f, 3.0f, 0.f}, up}, 7219 {{ 2.0f, 3.0f, 0.f}, up}, 7220 {{ 0.0f, 0.0f, 0.f}, up}, 7221 7222 {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}}, 7223 {{ 3.0f, 0.0f, 0.f}, up}, 7224 {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}}, 7225 }; 7226 const DWORD indices13[] = {0, 1, 2, 3, 4, 5}; 7227 const DWORD attributes13[] = {0, 0}; 7228 const UINT num_vertices13 = ARRAY_SIZE(vertices3); 7229 const UINT num_faces13 = ARRAY_SIZE(indices3) / VERTS_PER_FACE; 7230 DWORD flags13 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7231 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}; 7232 const DWORD adjacency13[] = {-1, 1, -1, -1, -1, 0}; 7233 const struct vertex_normal exp_vertices13[] = 7234 { 7235 {{ 0.0f, 3.0f, 0.f}, up}, 7236 {{ 2.0f, 3.0f, 0.f}, up}, 7237 {{ 0.0f, 0.0f, 0.f}, up}, 7238 7239 {{ 3.0f, 0.0f, 0.f}, up}, 7240 {{ 0.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}}, 7241 }; 7242 const DWORD exp_indices13[] = {0, 1, 2, 1, 3, 4}; 7243 const DWORD exp_face_remap13[] = {0, 1}; 7244 const DWORD exp_vertex_remap13[] = {0, 1, 2, 4, 5, -1}; 7245 const DWORD exp_new_num_vertices13 = ARRAY_SIZE(exp_vertices13); 7246 /* Test 14. Another test for welding with color. */ 7247 const struct vertex_color vertices14[] = 7248 { 7249 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF}, 7250 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF}, 7251 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF}, 7252 7253 {{ 3.0f, 3.0f, 0.f}, 0x00000000}, 7254 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF}, 7255 {{ 1.0f, 0.0f, 0.f}, 0x01010101}, 7256 }; 7257 const DWORD indices14[] = {0, 1, 2, 3, 4, 5}; 7258 const DWORD attributes14[] = {0, 0}; 7259 const UINT num_vertices14 = ARRAY_SIZE(vertices14); 7260 const UINT num_faces14 = ARRAY_SIZE(indices14) / VERTS_PER_FACE; 7261 DWORD flags14 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7262 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}; 7263 const DWORD adjacency14[] = {-1, 1, -1, -1, -1, 0}; 7264 const struct vertex_color exp_vertices14[] = 7265 { 7266 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF}, 7267 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF}, 7268 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF}, 7269 7270 {{ 2.0f, 3.0f, 0.f}, 0x00000000}, 7271 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF}, 7272 }; 7273 const DWORD exp_indices14[] = {0, 1, 2, 3, 4, 2}; 7274 const DWORD exp_face_remap14[] = {0, 1}; 7275 const DWORD exp_vertex_remap14[] = {0, 1, 2, 3, 4, -1}; 7276 const DWORD exp_new_num_vertices14 = ARRAY_SIZE(exp_vertices14); 7277 /* Test 15. Weld with color, but as UBYTE4N instead of D3DCOLOR. It shows 7278 * that UBYTE4N and D3DCOLOR are compared the same way. 7279 */ 7280 const struct vertex_color_ubyte4 vertices15[] = 7281 { 7282 {{ 0.0f, 3.0f, 0.f}, {255, 255, 255, 255}}, 7283 {{ 2.0f, 3.0f, 0.f}, {255, 255, 255, 255}}, 7284 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}}, 7285 7286 {{ 3.0f, 3.0f, 0.f}, { 0, 0, 0, 0}}, 7287 {{ 3.0f, 0.0f, 0.f}, {255, 255, 255, 255}}, 7288 {{ 1.0f, 0.0f, 0.f}, { 1, 1, 1, 1}}, 7289 }; 7290 const DWORD indices15[] = {0, 1, 2, 3, 4, 5}; 7291 const DWORD attributes15[] = {0, 0}; 7292 const UINT num_vertices15 = ARRAY_SIZE(vertices15); 7293 const UINT num_faces15 = ARRAY_SIZE(indices15) / VERTS_PER_FACE; 7294 DWORD flags15 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7295 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}; 7296 const DWORD adjacency15[] = {-1, 1, -1, -1, -1, 0}; 7297 const struct vertex_color_ubyte4 exp_vertices15[] = 7298 { 7299 {{ 0.0f, 3.0f, 0.f}, {255, 255, 255, 255}}, 7300 {{ 2.0f, 3.0f, 0.f}, {255, 255, 255, 255}}, 7301 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}}, 7302 7303 {{ 2.0f, 3.0f, 0.f}, { 0, 0, 0, 0}}, 7304 {{ 3.0f, 0.0f, 0.f}, {255, 255, 255, 255}}, 7305 }; 7306 const DWORD exp_indices15[] = {0, 1, 2, 3, 4, 2}; 7307 const DWORD exp_face_remap15[] = {0, 1}; 7308 const DWORD exp_vertex_remap15[] = {0, 1, 2, 3, 4, -1}; 7309 const DWORD exp_new_num_vertices15 = ARRAY_SIZE(exp_vertices15); 7310 /* Test 16. Weld with color, but as UBYTE4 instead of D3DCOLOR. It shows 7311 * that UBYTE4 is not normalized and that epsilon is truncated and compared 7312 * directly to each of the four bytes. 7313 */ 7314 const struct vertex_color_ubyte4 vertices16[] = 7315 { 7316 {{ 0.0f, 3.0f, 0.f}, {255, 255, 255, 255}}, 7317 {{ 2.0f, 3.0f, 0.f}, {255, 255, 255, 255}}, 7318 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}}, 7319 7320 {{ 3.0f, 3.0f, 0.f}, { 0, 0, 0, 0}}, 7321 {{ 3.0f, 0.0f, 0.f}, {255, 255, 255, 255}}, 7322 {{ 1.0f, 0.0f, 0.f}, { 1, 1, 1, 1}}, 7323 }; 7324 const DWORD indices16[] = {0, 1, 2, 3, 4, 5}; 7325 const DWORD attributes16[] = {0, 0}; 7326 const UINT num_vertices16 = ARRAY_SIZE(vertices16); 7327 const UINT num_faces16 = ARRAY_SIZE(indices16) / VERTS_PER_FACE; 7328 DWORD flags16 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7329 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}; 7330 const DWORD adjacency16[] = {-1, 1, -1, -1, -1, 0}; 7331 const struct vertex_color_ubyte4 exp_vertices16[] = 7332 { 7333 {{ 0.0f, 3.0f, 0.f}, {255, 255, 255, 255}}, 7334 {{ 2.0f, 3.0f, 0.f}, {255, 255, 255, 255}}, 7335 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}}, 7336 7337 {{ 2.0f, 3.0f, 0.f}, { 0, 0, 0, 0}}, 7338 {{ 3.0f, 0.0f, 0.f}, {255, 255, 255, 255}}, 7339 }; 7340 const DWORD exp_indices16[] = {0, 1, 2, 3, 4, 2}; 7341 const DWORD exp_face_remap16[] = {0, 1}; 7342 const DWORD exp_vertex_remap16[] = {0, 1, 2, 3, 4, -1}; 7343 const DWORD exp_new_num_vertices16 = ARRAY_SIZE(exp_vertices16); 7344 /* Test 17. Weld texture coordinates but as SHORT2 instead of D3DXVECTOR2.*/ 7345 const struct vertex_texcoord_short2 vertices17[] = 7346 { 7347 {{ 0.0f, 3.0f, 0.f}, { 0, 0}}, 7348 {{ 2.0f, 3.0f, 0.f}, { 0, 0}}, 7349 {{ 0.0f, 0.0f, 0.f}, { 0, 0}}, 7350 7351 {{ 3.0f, 3.0f, 0.f}, {32767, 32767}}, 7352 {{ 3.0f, 0.0f, 0.f}, {0, 0}}, 7353 {{ 1.0f, 0.0f, 0.f}, {32766, 32766}}, 7354 }; 7355 const DWORD indices17[] = {0, 1, 2, 3, 4, 5}; 7356 const DWORD attributes17[] = {0, 0}; 7357 const UINT num_vertices17 = ARRAY_SIZE(vertices17); 7358 const UINT num_faces17 = ARRAY_SIZE(indices17) / VERTS_PER_FACE; 7359 DWORD flags17 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7360 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}; 7361 const DWORD adjacency17[] = {-1, 1, -1, -1, -1, 0}; 7362 const struct vertex_texcoord_short2 exp_vertices17[] = 7363 { 7364 {{ 0.0f, 3.0f, 0.f}, { 0, 0}}, 7365 {{ 2.0f, 3.0f, 0.f}, { 0, 0}}, 7366 {{ 0.0f, 0.0f, 0.f}, { 0, 0}}, 7367 7368 {{ 2.0f, 3.0f, 0.f}, {32767, 32767}}, 7369 {{ 3.0f, 0.0f, 0.f}, {0, 0}}, 7370 }; 7371 const DWORD exp_indices17[] = {0, 1, 2, 3, 4, 2}; 7372 const DWORD exp_face_remap17[] = {0, 1}; 7373 const DWORD exp_vertex_remap17[] = {0, 1, 2, 3, 4, -1}; 7374 const DWORD exp_new_num_vertices17 = ARRAY_SIZE(exp_vertices17); 7375 /* Test 18. Weld texture coordinates but as SHORT2N instead of D3DXVECTOR2. */ 7376 const struct vertex_texcoord_short2 vertices18[] = 7377 { 7378 {{ 0.0f, 3.0f, 0.f}, { 0, 0}}, 7379 {{ 2.0f, 3.0f, 0.f}, { 0, 0}}, 7380 {{ 0.0f, 0.0f, 0.f}, { 0, 0}}, 7381 7382 {{ 3.0f, 3.0f, 0.f}, {32767, 32767}}, 7383 {{ 3.0f, 0.0f, 0.f}, {0, 0}}, 7384 {{ 1.0f, 0.0f, 0.f}, {32766, 32766}}, 7385 }; 7386 const DWORD indices18[] = {0, 1, 2, 3, 4, 5}; 7387 const DWORD attributes18[] = {0, 0}; 7388 const UINT num_vertices18 = ARRAY_SIZE(vertices18); 7389 const UINT num_faces18 = ARRAY_SIZE(indices18) / VERTS_PER_FACE; 7390 DWORD flags18 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7391 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}; 7392 const DWORD adjacency18[] = {-1, 1, -1, -1, -1, 0}; 7393 const struct vertex_texcoord_short2 exp_vertices18[] = 7394 { 7395 {{ 0.0f, 3.0f, 0.f}, { 0, 0}}, 7396 {{ 2.0f, 3.0f, 0.f}, { 0, 0}}, 7397 {{ 0.0f, 0.0f, 0.f}, { 0, 0}}, 7398 7399 {{ 2.0f, 3.0f, 0.f}, {32767, 32767}}, 7400 {{ 3.0f, 0.0f, 0.f}, {0, 0}}, 7401 }; 7402 const DWORD exp_indices18[] = {0, 1, 2, 3, 4, 2}; 7403 const DWORD exp_face_remap18[] = {0, 1}; 7404 const DWORD exp_vertex_remap18[] = {0, 1, 2, 3, 4, -1}; 7405 const DWORD exp_new_num_vertices18 = ARRAY_SIZE(exp_vertices18); 7406 /* Test 19. Weld texture coordinates but as USHORT2N instead of D3DXVECTOR2. */ 7407 const struct vertex_texcoord_ushort2n vertices19[] = 7408 { 7409 {{ 0.0f, 3.0f, 0.f}, { 0, 0}}, 7410 {{ 2.0f, 3.0f, 0.f}, { 0, 0}}, 7411 {{ 0.0f, 0.0f, 0.f}, { 0, 0}}, 7412 7413 {{ 3.0f, 3.0f, 0.f}, {65535, 65535}}, 7414 {{ 3.0f, 0.0f, 0.f}, {0, 0}}, 7415 {{ 1.0f, 0.0f, 0.f}, {65534, 65534}}, 7416 }; 7417 const DWORD indices19[] = {0, 1, 2, 3, 4, 5}; 7418 const DWORD attributes19[] = {0, 0}; 7419 const UINT num_vertices19 = ARRAY_SIZE(vertices19); 7420 const UINT num_faces19 = ARRAY_SIZE(indices19) / VERTS_PER_FACE; 7421 DWORD flags19 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7422 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}; 7423 const DWORD adjacency19[] = {-1, 1, -1, -1, -1, 0}; 7424 const struct vertex_texcoord_ushort2n exp_vertices19[] = 7425 { 7426 {{ 0.0f, 3.0f, 0.f}, { 0, 0}}, 7427 {{ 2.0f, 3.0f, 0.f}, { 0, 0}}, 7428 {{ 0.0f, 0.0f, 0.f}, { 0, 0}}, 7429 7430 {{ 2.0f, 3.0f, 0.f}, {65535, 65535}}, 7431 {{ 3.0f, 0.0f, 0.f}, {0, 0}}, 7432 }; 7433 const DWORD exp_indices19[] = {0, 1, 2, 3, 4, 2}; 7434 const DWORD exp_face_remap19[] = {0, 1}; 7435 const DWORD exp_vertex_remap19[] = {0, 1, 2, 3, 4, -1}; 7436 const DWORD exp_new_num_vertices19 = ARRAY_SIZE(exp_vertices19); 7437 /* Test 20. Weld normal as SHORT4 instead of D3DXVECTOR3. */ 7438 const struct vertex_normal_short4 vertices20[] = 7439 { 7440 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, 7441 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, 7442 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}}, 7443 7444 {{ 3.0f, 3.0f, 0.f}, {32767, 32767, 32767, 32767}}, 7445 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}}, 7446 {{ 1.0f, 0.0f, 0.f}, {32766, 32766, 32766, 32766}}, 7447 }; 7448 const DWORD indices20[] = {0, 1, 2, 3, 4, 5}; 7449 const DWORD attributes20[] = {0, 0}; 7450 const UINT num_vertices20 = ARRAY_SIZE(vertices20); 7451 const UINT num_faces20 = ARRAY_SIZE(indices20) / VERTS_PER_FACE; 7452 DWORD flags20 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7453 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}; 7454 const DWORD adjacency20[] = {-1, 1, -1, -1, -1, 0}; 7455 const struct vertex_normal_short4 exp_vertices20[] = 7456 { 7457 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, 7458 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, 7459 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}}, 7460 7461 {{ 2.0f, 3.0f, 0.f}, {32767, 32767, 32767, 32767}}, 7462 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}}, 7463 }; 7464 const DWORD exp_indices20[] = {0, 1, 2, 3, 4, 2}; 7465 const DWORD exp_face_remap20[] = {0, 1}; 7466 const DWORD exp_vertex_remap20[] = {0, 1, 2, 3, 4, -1}; 7467 const DWORD exp_new_num_vertices20 = ARRAY_SIZE(exp_vertices20); 7468 /* Test 21. Weld normal as SHORT4N instead of D3DXVECTOR3. */ 7469 const struct vertex_normal_short4 vertices21[] = 7470 { 7471 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, 7472 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, 7473 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}}, 7474 7475 {{ 3.0f, 3.0f, 0.f}, {32767, 32767, 32767, 32767}}, 7476 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}}, 7477 {{ 1.0f, 0.0f, 0.f}, {32766, 32766, 32766, 32766}}, 7478 }; 7479 const DWORD indices21[] = {0, 1, 2, 3, 4, 5}; 7480 const DWORD attributes21[] = {0, 0}; 7481 const UINT num_vertices21 = ARRAY_SIZE(vertices21); 7482 const UINT num_faces21 = ARRAY_SIZE(indices21) / VERTS_PER_FACE; 7483 DWORD flags21 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7484 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}; 7485 const DWORD adjacency21[] = {-1, 1, -1, -1, -1, 0}; 7486 const struct vertex_normal_short4 exp_vertices21[] = 7487 { 7488 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, 7489 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, 7490 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}}, 7491 7492 {{ 2.0f, 3.0f, 0.f}, {32767, 32767, 32767, 32767}}, 7493 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}}, 7494 }; 7495 const DWORD exp_indices21[] = {0, 1, 2, 3, 4, 2}; 7496 const DWORD exp_face_remap21[] = {0, 1}; 7497 const DWORD exp_vertex_remap21[] = {0, 1, 2, 3, 4, -1}; 7498 const DWORD exp_new_num_vertices21 = ARRAY_SIZE(exp_vertices21); 7499 /* Test 22. Weld normal as USHORT4N instead of D3DXVECTOR3. */ 7500 const struct vertex_normal_short4 vertices22[] = 7501 { 7502 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, 7503 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, 7504 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}}, 7505 7506 {{ 3.0f, 3.0f, 0.f}, {-1, -1, -1, -1}}, 7507 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}}, 7508 {{ 1.0f, 0.0f, 0.f}, {-2, -2, -2, -2}}, 7509 }; 7510 const DWORD indices22[] = {0, 1, 2, 3, 4, 5}; 7511 const DWORD attributes22[] = {0, 0}; 7512 const UINT num_vertices22 = ARRAY_SIZE(vertices22); 7513 const UINT num_faces22 = ARRAY_SIZE(indices22) / VERTS_PER_FACE; 7514 DWORD flags22 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7515 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}; 7516 const DWORD adjacency22[] = {-1, 1, -1, -1, -1, 0}; 7517 const struct vertex_normal_short4 exp_vertices22[] = 7518 { 7519 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, 7520 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, 7521 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}}, 7522 7523 {{ 2.0f, 3.0f, 0.f}, {-1, -1, -1, -1}}, 7524 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}}, 7525 }; 7526 const DWORD exp_indices22[] = {0, 1, 2, 3, 4, 2}; 7527 const DWORD exp_face_remap22[] = {0, 1}; 7528 const DWORD exp_vertex_remap22[] = {0, 1, 2, 3, 4, -1}; 7529 const DWORD exp_new_num_vertices22 = ARRAY_SIZE(exp_vertices22); 7530 /* Test 23. Weld texture coordinates as FLOAT16_2. Similar to test 11, but 7531 * with texture coordinates converted to float16 in hex. */ 7532 const struct vertex_texcoord_float16_2 vertices23[] = 7533 { 7534 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */ 7535 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */ 7536 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */ 7537 7538 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd}}, /* {0.2f, 0.3f} */ 7539 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */ 7540 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */ 7541 }; 7542 const DWORD indices23[] = {0, 1, 2, 3, 4, 5}; 7543 const DWORD attributes23[] = {0, 0}; 7544 const UINT num_vertices23 = ARRAY_SIZE(vertices23); 7545 const UINT num_faces23 = ARRAY_SIZE(indices23) / VERTS_PER_FACE; 7546 DWORD flags23 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7547 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}; 7548 const DWORD adjacency23[] = {-1, 1, -1, -1, -1, 0}; 7549 const struct vertex_texcoord_float16_2 exp_vertices23[] = 7550 { 7551 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */ 7552 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */ 7553 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */ 7554 7555 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */ 7556 {{ 0.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */ 7557 }; 7558 const DWORD exp_indices23[] = {0, 1, 2, 1, 3, 4}; 7559 const DWORD exp_face_remap23[] = {0, 1}; 7560 const DWORD exp_vertex_remap23[] = {0, 1, 2, 4, 5, -1}; 7561 const DWORD exp_new_num_vertices23 = ARRAY_SIZE(exp_vertices23); 7562 /* Test 24. Weld texture coordinates as FLOAT16_4. Similar to test 24. */ 7563 const struct vertex_texcoord_float16_4 vertices24[] = 7564 { 7565 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}}, 7566 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a, 0x3800, 0x399a}}, 7567 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd, 0xb266, 0xb4cd}}, 7568 7569 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd, 0x3266, 0x34cd}}, 7570 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}}, 7571 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266, 0x2e66, 0x3266}}, 7572 }; 7573 const DWORD indices24[] = {0, 1, 2, 3, 4, 5}; 7574 const DWORD attributes24[] = {0, 0}; 7575 const UINT num_vertices24 = ARRAY_SIZE(vertices24); 7576 const UINT num_faces24 = ARRAY_SIZE(indices24) / VERTS_PER_FACE; 7577 DWORD flags24 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7578 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}; 7579 const DWORD adjacency24[] = {-1, 1, -1, -1, -1, 0}; 7580 const struct vertex_texcoord_float16_4 exp_vertices24[] = 7581 { 7582 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}}, 7583 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a, 0x3800, 0x399a}}, 7584 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd, 0xb266, 0xb4cd}}, 7585 7586 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}}, 7587 {{ 0.0f, 0.0f, 0.f}, {0x2e66, 0x3266, 0x2e66, 0x3266}}, 7588 }; 7589 const DWORD exp_indices24[] = {0, 1, 2, 1, 3, 4}; 7590 const DWORD exp_face_remap24[] = {0, 1}; 7591 const DWORD exp_vertex_remap24[] = {0, 1, 2, 4, 5, -1}; 7592 const DWORD exp_new_num_vertices24 = ARRAY_SIZE(exp_vertices24); 7593 /* Test 25. Weld texture coordinates with usage index 10 (TEXCOORD10). The 7594 * usage index is capped at 7, so the epsilon for TEXCOORD7 is used instead. 7595 */ 7596 const struct vertex_texcoord vertices25[] = 7597 { 7598 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f}}, 7599 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.7f}}, 7600 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}}, 7601 7602 {{ 3.0f, 3.0f, 0.f}, {0.2f, 0.3f}}, 7603 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f}}, 7604 {{ 1.0f, 0.0f, 0.f}, {0.1f, 0.2f}} 7605 }; 7606 const DWORD indices25[] = {0, 1, 2, 3, 4, 5}; 7607 const DWORD attributes25[] = {0, 0}; 7608 const UINT num_vertices25 = ARRAY_SIZE(vertices25); 7609 const UINT num_faces25 = ARRAY_SIZE(indices25) / VERTS_PER_FACE; 7610 DWORD flags25 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7611 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}; 7612 const DWORD adjacency25[] = {-1, 1, -1, -1, -1, 0}; 7613 const struct vertex_texcoord exp_vertices25[] = 7614 { 7615 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f}}, 7616 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.7f}}, 7617 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}}, 7618 7619 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f}}, 7620 {{ 0.0f, 0.0f, 0.f}, {0.1f, 0.2f}}, 7621 }; 7622 const DWORD exp_indices25[] = {0, 1, 2, 1, 3, 4}; 7623 const DWORD exp_face_remap25[] = {0, 1}; 7624 const DWORD exp_vertex_remap25[] = {0, 1, 2, 4, 5, -1}; 7625 const DWORD exp_new_num_vertices25 = ARRAY_SIZE(exp_vertices25); 7626 /* Test 26. Weld color with usage index larger than 1. Shows that none of 7627 * the epsilon values are used. */ 7628 const struct vertex_color vertices26[] = 7629 { 7630 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF}, 7631 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF}, 7632 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF}, 7633 7634 {{ 3.0f, 3.0f, 0.f}, 0x00000000}, 7635 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF}, 7636 {{ 1.0f, 0.0f, 0.f}, 0x01010101}, 7637 }; 7638 const DWORD indices26[] = {0, 1, 2, 3, 4, 5}; 7639 const DWORD attributes26[] = {0, 0}; 7640 const UINT num_vertices26 = ARRAY_SIZE(vertices26); 7641 const UINT num_faces26 = ARRAY_SIZE(indices26) / VERTS_PER_FACE; 7642 DWORD flags26 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7643 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}; 7644 const DWORD adjacency26[] = {-1, 1, -1, -1, -1, 0}; 7645 const struct vertex_color exp_vertices26[] = 7646 { 7647 {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF}, 7648 {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF}, 7649 {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF}, 7650 7651 {{ 2.0f, 3.0f, 0.f}, 0x00000000}, 7652 {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF}, 7653 {{ 0.0f, 0.0f, 0.f}, 0x01010101}, 7654 }; 7655 const DWORD exp_indices26[] = {0, 1, 2, 3, 4, 5}; 7656 const DWORD exp_face_remap26[] = {0, 1}; 7657 const DWORD exp_vertex_remap26[] = {0, 1, 2, 3, 4, 5}; 7658 const DWORD exp_new_num_vertices26 = ARRAY_SIZE(exp_vertices26); 7659 /* Test 27. Weld color with usage index 1 (specular). */ 7660 /* Previously this test used float color values and index > 1 but that case 7661 * appears to be effectively unhandled in native so the test gave 7662 * inconsistent results. */ 7663 const struct vertex_color vertices27[] = 7664 { 7665 {{ 0.0f, 3.0f, 0.0f}, 0x00000000}, 7666 {{ 2.0f, 3.0f, 0.0f}, 0x10203040}, 7667 {{ 0.0f, 0.0f, 0.0f}, 0x50607080}, 7668 7669 {{ 3.0f, 3.0f, 0.0f}, 0x11213141}, 7670 {{ 3.0f, 0.0f, 0.0f}, 0xffffffff}, 7671 {{ 1.0f, 0.0f, 0.0f}, 0x51617181}, 7672 }; 7673 const DWORD indices27[] = {0, 1, 2, 3, 4, 5}; 7674 const DWORD attributes27[] = {0, 0}; 7675 const UINT num_vertices27 = ARRAY_SIZE(vertices27); 7676 const UINT num_faces27 = ARRAY_SIZE(indices27) / VERTS_PER_FACE; 7677 DWORD flags27 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7678 const D3DXWELDEPSILONS epsilons27 = 7679 { 7680 1.1f, 0.0f, 0.0f, 0.0f, 2.0f / 255.0f, 0.0f, 7681 {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, 0.0f, 0.0f, 0.0f 7682 }; 7683 const DWORD adjacency27[] = {-1, 1, -1, -1, -1, 0}; 7684 const struct vertex_color exp_vertices27[] = 7685 { 7686 {{ 0.0f, 3.0f, 0.0f}, 0x00000000}, 7687 {{ 2.0f, 3.0f, 0.0f}, 0x10203040}, 7688 {{ 0.0f, 0.0f, 0.0f}, 0x50607080}, 7689 7690 {{ 3.0f, 0.0f, 0.0f}, 0xffffffff}, 7691 }; 7692 const DWORD exp_indices27[] = {0, 1, 2, 1, 3, 2}; 7693 const DWORD exp_face_remap27[] = {0, 1}; 7694 const DWORD exp_vertex_remap27[] = {0, 1, 2, 4, -1, -1}; 7695 const DWORD exp_new_num_vertices27 = ARRAY_SIZE(exp_vertices27); 7696 /* Test 28. Weld one normal with UDEC3. */ 7697 const DWORD dword_udec3_zero = init_udec3_dword(0, 0, 0, 1); 7698 const DWORD dword_udec3_1023 = init_udec3_dword(1023, 1023, 1023, 1); 7699 const DWORD dword_udec3_1022 = init_udec3_dword(1022, 1022, 1022, 1); 7700 const struct vertex_normal_udec3 vertices28[] = 7701 { 7702 {{ 0.0f, 3.0f, 0.f}, dword_udec3_zero}, 7703 {{ 2.0f, 3.0f, 0.f}, dword_udec3_zero}, 7704 {{ 0.0f, 0.0f, 0.f}, dword_udec3_zero}, 7705 7706 {{ 3.0f, 3.0f, 0.f}, dword_udec3_1023}, 7707 {{ 3.0f, 0.0f, 0.f}, dword_udec3_zero}, 7708 {{ 1.0f, 0.0f, 0.f}, dword_udec3_1022}, 7709 }; 7710 const DWORD indices28[] = {0, 1, 2, 3, 4, 5}; 7711 const DWORD attributes28[] = {0, 0}; 7712 const UINT num_vertices28 = ARRAY_SIZE(vertices28); 7713 const UINT num_faces28 = ARRAY_SIZE(indices28) / VERTS_PER_FACE; 7714 DWORD flags28 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7715 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}; 7716 const DWORD adjacency28[] = {-1, 1, -1, -1, -1, 0}; 7717 const struct vertex_normal_udec3 exp_vertices28[] = 7718 { 7719 {{ 0.0f, 3.0f, 0.f}, dword_udec3_zero}, 7720 {{ 2.0f, 3.0f, 0.f}, dword_udec3_zero}, 7721 {{ 0.0f, 0.0f, 0.f}, dword_udec3_zero}, 7722 7723 {{ 2.0f, 3.0f, 0.f}, dword_udec3_1023}, 7724 {{ 3.0f, 0.0f, 0.f}, dword_udec3_zero}, 7725 }; 7726 const DWORD exp_indices28[] = {0, 1, 2, 3, 4, 2}; 7727 const DWORD exp_face_remap28[] = {0, 1}; 7728 const DWORD exp_vertex_remap28[] = {0, 1, 2, 3, 4, -1}; 7729 const DWORD exp_new_num_vertices28 = ARRAY_SIZE(exp_vertices28); 7730 /* Test 29. Weld one normal with DEC3N. */ 7731 const DWORD dword_dec3n_zero = init_dec3n_dword(0, 0, 0, 1); 7732 const DWORD dword_dec3n_511 = init_dec3n_dword(511, 511, 511, 1); 7733 const DWORD dword_dec3n_510 = init_dec3n_dword(510, 510, 510, 1); 7734 const struct vertex_normal_dec3n vertices29[] = 7735 { 7736 {{ 0.0f, 3.0f, 0.f}, dword_dec3n_zero}, 7737 {{ 2.0f, 3.0f, 0.f}, dword_dec3n_zero}, 7738 {{ 0.0f, 0.0f, 0.f}, dword_dec3n_zero}, 7739 7740 {{ 3.0f, 3.0f, 0.f}, dword_dec3n_511}, 7741 {{ 3.0f, 0.0f, 0.f}, dword_dec3n_zero}, 7742 {{ 1.0f, 0.0f, 0.f}, dword_dec3n_510}, 7743 }; 7744 const DWORD indices29[] = {0, 1, 2, 3, 4, 5}; 7745 const DWORD attributes29[] = {0, 0}; 7746 const UINT num_vertices29 = ARRAY_SIZE(vertices29); 7747 const UINT num_faces29 = ARRAY_SIZE(indices29) / VERTS_PER_FACE; 7748 DWORD flags29 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; 7749 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}; 7750 const DWORD adjacency29[] = {-1, 1, -1, -1, -1, 0}; 7751 const struct vertex_normal_dec3n exp_vertices29[] = 7752 { 7753 {{ 0.0f, 3.0f, 0.f}, dword_dec3n_zero}, 7754 {{ 2.0f, 3.0f, 0.f}, dword_dec3n_zero}, 7755 {{ 0.0f, 0.0f, 0.f}, dword_dec3n_zero}, 7756 7757 {{ 2.0f, 3.0f, 0.f}, dword_dec3n_511}, 7758 {{ 3.0f, 0.0f, 0.f}, dword_dec3n_zero}, 7759 }; 7760 const DWORD exp_indices29[] = {0, 1, 2, 3, 4, 2}; 7761 const DWORD exp_face_remap29[] = {0, 1}; 7762 const DWORD exp_vertex_remap29[] = {0, 1, 2, 3, 4, -1}; 7763 const DWORD exp_new_num_vertices29 = ARRAY_SIZE(exp_vertices29); 7764 /* All mesh data */ 7765 DWORD *adjacency_out = NULL; 7766 DWORD *face_remap = NULL; 7767 ID3DXMesh *mesh = NULL; 7768 ID3DXBuffer *vertex_remap = NULL; 7769 struct 7770 { 7771 const BYTE *vertices; 7772 const DWORD *indices; 7773 const DWORD *attributes; 7774 const DWORD num_vertices; 7775 const DWORD num_faces; 7776 const DWORD options; 7777 D3DVERTEXELEMENT9 *declaration; 7778 const UINT vertex_size; 7779 const DWORD flags; 7780 const D3DXWELDEPSILONS *epsilons; 7781 const DWORD *adjacency; 7782 const BYTE *exp_vertices; 7783 const DWORD *exp_indices; 7784 const DWORD *exp_face_remap; 7785 const DWORD *exp_vertex_remap; 7786 const DWORD exp_new_num_vertices; 7787 } 7788 tc[] = 7789 { 7790 { 7791 (BYTE*)vertices0, 7792 indices0, 7793 attributes0, 7794 num_vertices0, 7795 num_faces0, 7796 options, 7797 declaration_normal, 7798 vertex_size_normal, 7799 flags0, 7800 NULL, 7801 adjacency0, 7802 (BYTE*)exp_vertices0, 7803 exp_indices0, 7804 exp_face_remap0, 7805 exp_vertex_remap0, 7806 exp_new_num_vertices0 7807 }, 7808 { 7809 (BYTE*)vertices1, 7810 indices1, 7811 attributes1, 7812 num_vertices1, 7813 num_faces1, 7814 options, 7815 declaration_normal, 7816 vertex_size_normal, 7817 flags1, 7818 NULL, 7819 adjacency1, 7820 (BYTE*)exp_vertices1, 7821 exp_indices1, 7822 exp_face_remap1, 7823 exp_vertex_remap1, 7824 exp_new_num_vertices1 7825 }, 7826 { 7827 (BYTE*)vertices2, 7828 indices2, 7829 attributes2, 7830 num_vertices2, 7831 num_faces2, 7832 options, 7833 declaration_normal, 7834 vertex_size_normal, 7835 flags2, 7836 &epsilons2, 7837 adjacency2, 7838 (BYTE*)exp_vertices2, 7839 exp_indices2, 7840 exp_face_remap2, 7841 exp_vertex_remap2, 7842 exp_new_num_vertices2 7843 }, 7844 { 7845 (BYTE*)vertices3, 7846 indices3, 7847 attributes3, 7848 num_vertices3, 7849 num_faces3, 7850 options, 7851 declaration_normal, 7852 vertex_size_normal, 7853 flags3, 7854 &epsilons3, 7855 adjacency3, 7856 (BYTE*)exp_vertices3, 7857 exp_indices3, 7858 exp_face_remap3, 7859 exp_vertex_remap3, 7860 exp_new_num_vertices3 7861 }, 7862 { 7863 (BYTE*)vertices4, 7864 indices4, 7865 attributes4, 7866 num_vertices4, 7867 num_faces4, 7868 options, 7869 declaration_normal, 7870 vertex_size_normal, 7871 flags4, 7872 &epsilons4, 7873 adjacency4, 7874 (BYTE*)exp_vertices4, 7875 exp_indices4, 7876 exp_face_remap4, 7877 exp_vertex_remap4, 7878 exp_new_num_vertices4 7879 }, 7880 /* Unusual ordering. */ 7881 { 7882 (BYTE*)vertices5, 7883 indices5, 7884 attributes5, 7885 num_vertices5, 7886 num_faces5, 7887 options, 7888 declaration_normal, 7889 vertex_size_normal, 7890 flags5, 7891 NULL, 7892 adjacency5, 7893 (BYTE*)exp_vertices5, 7894 exp_indices5, 7895 exp_face_remap5, 7896 exp_vertex_remap5, 7897 exp_new_num_vertices5 7898 }, 7899 { 7900 (BYTE*)vertices6, 7901 indices6, 7902 attributes6, 7903 num_vertices6, 7904 num_faces6, 7905 options, 7906 declaration_normal, 7907 vertex_size_normal, 7908 flags6, 7909 &epsilons6, 7910 adjacency6, 7911 (BYTE*)exp_vertices6, 7912 exp_indices6, 7913 exp_face_remap6, 7914 exp_vertex_remap6, 7915 exp_new_num_vertices6 7916 }, 7917 { 7918 (BYTE*)vertices6, 7919 (DWORD*)indices6_16bit, 7920 attributes6, 7921 num_vertices6, 7922 num_faces6, 7923 options_16bit, 7924 declaration_normal, 7925 vertex_size_normal, 7926 flags6, 7927 &epsilons6, 7928 adjacency6, 7929 (BYTE*)exp_vertices6, 7930 exp_indices6, 7931 exp_face_remap6, 7932 exp_vertex_remap6, 7933 exp_new_num_vertices6 7934 }, 7935 { 7936 (BYTE*)vertices8, 7937 indices8, 7938 attributes8, 7939 num_vertices8, 7940 num_faces8, 7941 options, 7942 declaration_normal, 7943 vertex_size_normal, 7944 flags8, 7945 &epsilons8, 7946 adjacency8, 7947 (BYTE*)exp_vertices8, 7948 exp_indices8, 7949 exp_face_remap8, 7950 exp_vertex_remap8, 7951 exp_new_num_vertices8 7952 }, 7953 { 7954 (BYTE*)vertices9, 7955 indices9, 7956 attributes9, 7957 num_vertices9, 7958 num_faces9, 7959 options, 7960 declaration_normal, 7961 vertex_size_normal, 7962 flags9, 7963 &epsilons9, 7964 adjacency9, 7965 (BYTE*)exp_vertices9, 7966 exp_indices9, 7967 exp_face_remap9, 7968 exp_vertex_remap9, 7969 exp_new_num_vertices9 7970 }, 7971 { 7972 (BYTE*)vertices10, 7973 indices10, 7974 attributes10, 7975 num_vertices10, 7976 num_faces10, 7977 options, 7978 declaration_blendweight, 7979 vertex_size_blendweight, 7980 flags10, 7981 &epsilons10, 7982 adjacency10, 7983 (BYTE*)exp_vertices10, 7984 exp_indices10, 7985 exp_face_remap10, 7986 exp_vertex_remap10, 7987 exp_new_num_vertices10 7988 }, 7989 { 7990 (BYTE*)vertices11, 7991 indices11, 7992 attributes11, 7993 num_vertices11, 7994 num_faces11, 7995 options, 7996 declaration_texcoord, 7997 vertex_size_texcoord, 7998 flags11, 7999 &epsilons11, 8000 adjacency11, 8001 (BYTE*)exp_vertices11, 8002 exp_indices11, 8003 exp_face_remap11, 8004 exp_vertex_remap11, 8005 exp_new_num_vertices11 8006 }, 8007 { 8008 (BYTE*)vertices12, 8009 indices12, 8010 attributes12, 8011 num_vertices12, 8012 num_faces12, 8013 options, 8014 declaration_color, 8015 vertex_size_color, 8016 flags12, 8017 &epsilons12, 8018 adjacency12, 8019 (BYTE*)exp_vertices12, 8020 exp_indices12, 8021 exp_face_remap12, 8022 exp_vertex_remap12, 8023 exp_new_num_vertices12 8024 }, 8025 { 8026 (BYTE*)vertices13, 8027 indices13, 8028 attributes13, 8029 num_vertices13, 8030 num_faces13, 8031 options, 8032 declaration_normal3, 8033 vertex_size_normal, 8034 flags13, 8035 &epsilons13, 8036 adjacency13, 8037 (BYTE*)exp_vertices13, 8038 exp_indices13, 8039 exp_face_remap13, 8040 exp_vertex_remap13, 8041 exp_new_num_vertices13 8042 }, 8043 { 8044 (BYTE*)vertices14, 8045 indices14, 8046 attributes14, 8047 num_vertices14, 8048 num_faces14, 8049 options, 8050 declaration_color, 8051 vertex_size_color, 8052 flags14, 8053 &epsilons14, 8054 adjacency14, 8055 (BYTE*)exp_vertices14, 8056 exp_indices14, 8057 exp_face_remap14, 8058 exp_vertex_remap14, 8059 exp_new_num_vertices14 8060 }, 8061 { 8062 (BYTE*)vertices15, 8063 indices15, 8064 attributes15, 8065 num_vertices15, 8066 num_faces15, 8067 options, 8068 declaration_color_ubyte4n, 8069 vertex_size_color_ubyte4, /* UBYTE4 same size as UBYTE4N */ 8070 flags15, 8071 &epsilons15, 8072 adjacency15, 8073 (BYTE*)exp_vertices15, 8074 exp_indices15, 8075 exp_face_remap15, 8076 exp_vertex_remap15, 8077 exp_new_num_vertices15 8078 }, 8079 { 8080 (BYTE*)vertices16, 8081 indices16, 8082 attributes16, 8083 num_vertices16, 8084 num_faces16, 8085 options, 8086 declaration_color_ubyte4, 8087 vertex_size_color_ubyte4, 8088 flags16, 8089 &epsilons16, 8090 adjacency16, 8091 (BYTE*)exp_vertices16, 8092 exp_indices16, 8093 exp_face_remap16, 8094 exp_vertex_remap16, 8095 exp_new_num_vertices16 8096 }, 8097 { 8098 (BYTE*)vertices17, 8099 indices17, 8100 attributes17, 8101 num_vertices17, 8102 num_faces17, 8103 options, 8104 declaration_texcoord_short2, 8105 vertex_size_texcoord_short2, 8106 flags17, 8107 &epsilons17, 8108 adjacency17, 8109 (BYTE*)exp_vertices17, 8110 exp_indices17, 8111 exp_face_remap17, 8112 exp_vertex_remap17, 8113 exp_new_num_vertices17 8114 }, 8115 { 8116 (BYTE*)vertices18, 8117 indices18, 8118 attributes18, 8119 num_vertices18, 8120 num_faces18, 8121 options, 8122 declaration_texcoord_short2n, 8123 vertex_size_texcoord_short2, /* SHORT2 same size as SHORT2N */ 8124 flags18, 8125 &epsilons18, 8126 adjacency18, 8127 (BYTE*)exp_vertices18, 8128 exp_indices18, 8129 exp_face_remap18, 8130 exp_vertex_remap18, 8131 exp_new_num_vertices18 8132 }, 8133 { 8134 (BYTE*)vertices19, 8135 indices19, 8136 attributes19, 8137 num_vertices19, 8138 num_faces19, 8139 options, 8140 declaration_texcoord_ushort2n, 8141 vertex_size_texcoord_short2, /* SHORT2 same size as USHORT2N */ 8142 flags19, 8143 &epsilons19, 8144 adjacency19, 8145 (BYTE*)exp_vertices19, 8146 exp_indices19, 8147 exp_face_remap19, 8148 exp_vertex_remap19, 8149 exp_new_num_vertices19 8150 }, 8151 { 8152 (BYTE*)vertices20, 8153 indices20, 8154 attributes20, 8155 num_vertices20, 8156 num_faces20, 8157 options, 8158 declaration_normal_short4, 8159 vertex_size_normal_short4, 8160 flags20, 8161 &epsilons20, 8162 adjacency20, 8163 (BYTE*)exp_vertices20, 8164 exp_indices20, 8165 exp_face_remap20, 8166 exp_vertex_remap20, 8167 exp_new_num_vertices20 8168 }, 8169 { 8170 (BYTE*)vertices21, 8171 indices21, 8172 attributes21, 8173 num_vertices21, 8174 num_faces21, 8175 options, 8176 declaration_normal_short4n, 8177 vertex_size_normal_short4, /* SHORT4 same size as SHORT4N */ 8178 flags21, 8179 &epsilons21, 8180 adjacency21, 8181 (BYTE*)exp_vertices21, 8182 exp_indices21, 8183 exp_face_remap21, 8184 exp_vertex_remap21, 8185 exp_new_num_vertices21 8186 }, 8187 { 8188 (BYTE*)vertices22, 8189 indices22, 8190 attributes22, 8191 num_vertices22, 8192 num_faces22, 8193 options, 8194 declaration_normal_ushort4n, 8195 vertex_size_normal_short4, /* SHORT4 same size as USHORT4N */ 8196 flags22, 8197 &epsilons22, 8198 adjacency22, 8199 (BYTE*)exp_vertices22, 8200 exp_indices22, 8201 exp_face_remap22, 8202 exp_vertex_remap22, 8203 exp_new_num_vertices22 8204 }, 8205 { 8206 (BYTE*)vertices23, 8207 indices23, 8208 attributes23, 8209 num_vertices23, 8210 num_faces23, 8211 options, 8212 declaration_texcoord_float16_2, 8213 vertex_size_texcoord_float16_2, 8214 flags23, 8215 &epsilons23, 8216 adjacency23, 8217 (BYTE*)exp_vertices23, 8218 exp_indices23, 8219 exp_face_remap23, 8220 exp_vertex_remap23, 8221 exp_new_num_vertices23 8222 }, 8223 { 8224 (BYTE*)vertices24, 8225 indices24, 8226 attributes24, 8227 num_vertices24, 8228 num_faces24, 8229 options, 8230 declaration_texcoord_float16_4, 8231 vertex_size_texcoord_float16_4, 8232 flags24, 8233 &epsilons24, 8234 adjacency24, 8235 (BYTE*)exp_vertices24, 8236 exp_indices24, 8237 exp_face_remap24, 8238 exp_vertex_remap24, 8239 exp_new_num_vertices24 8240 }, 8241 { 8242 (BYTE*)vertices25, 8243 indices25, 8244 attributes25, 8245 num_vertices25, 8246 num_faces25, 8247 options, 8248 declaration_texcoord10, 8249 vertex_size_texcoord, 8250 flags25, 8251 &epsilons25, 8252 adjacency25, 8253 (BYTE*)exp_vertices25, 8254 exp_indices25, 8255 exp_face_remap25, 8256 exp_vertex_remap25, 8257 exp_new_num_vertices25 8258 }, 8259 { 8260 (BYTE*)vertices26, 8261 indices26, 8262 attributes26, 8263 num_vertices26, 8264 num_faces26, 8265 options, 8266 declaration_color2, 8267 vertex_size_color, 8268 flags26, 8269 &epsilons26, 8270 adjacency26, 8271 (BYTE*)exp_vertices26, 8272 exp_indices26, 8273 exp_face_remap26, 8274 exp_vertex_remap26, 8275 exp_new_num_vertices26 8276 }, 8277 { 8278 (BYTE*)vertices27, 8279 indices27, 8280 attributes27, 8281 num_vertices27, 8282 num_faces27, 8283 options, 8284 declaration_color1, 8285 vertex_size_color, 8286 flags27, 8287 &epsilons27, 8288 adjacency27, 8289 (BYTE*)exp_vertices27, 8290 exp_indices27, 8291 exp_face_remap27, 8292 exp_vertex_remap27, 8293 exp_new_num_vertices27 8294 }, 8295 { 8296 (BYTE*)vertices28, 8297 indices28, 8298 attributes28, 8299 num_vertices28, 8300 num_faces28, 8301 options, 8302 declaration_normal_udec3, 8303 vertex_size_normal_udec3, 8304 flags28, 8305 &epsilons28, 8306 adjacency28, 8307 (BYTE*)exp_vertices28, 8308 exp_indices28, 8309 exp_face_remap28, 8310 exp_vertex_remap28, 8311 exp_new_num_vertices28 8312 }, 8313 { 8314 (BYTE*)vertices29, 8315 indices29, 8316 attributes29, 8317 num_vertices29, 8318 num_faces29, 8319 options, 8320 declaration_normal_dec3n, 8321 vertex_size_normal_dec3n, 8322 flags29, 8323 &epsilons29, 8324 adjacency29, 8325 (BYTE*)exp_vertices29, 8326 exp_indices29, 8327 exp_face_remap29, 8328 exp_vertex_remap29, 8329 exp_new_num_vertices29 8330 } 8331 }; 8332 #ifdef __REACTOS__ 8333 #undef up 8334 #endif 8335 8336 test_context = new_test_context(); 8337 if (!test_context) 8338 { 8339 skip("Couldn't create test context\n"); 8340 goto cleanup; 8341 } 8342 8343 for (i = 0; i < ARRAY_SIZE(tc); i++) 8344 { 8345 DWORD j; 8346 DWORD *vertex_remap_ptr; 8347 DWORD new_num_vertices; 8348 8349 hr = init_test_mesh(tc[i].num_faces, tc[i].num_vertices, tc[i].options, 8350 tc[i].declaration, test_context->device, &mesh, 8351 tc[i].vertices, tc[i].vertex_size, 8352 tc[i].indices, tc[i].attributes); 8353 if (FAILED(hr)) 8354 { 8355 skip("Couldn't initialize test mesh %d.\n", i); 8356 goto cleanup; 8357 } 8358 8359 /* Allocate out parameters */ 8360 adjacency_out = HeapAlloc(GetProcessHeap(), 0, VERTS_PER_FACE * tc[i].num_faces * sizeof(*adjacency_out)); 8361 if (!adjacency_out) 8362 { 8363 skip("Couldn't allocate adjacency_out array.\n"); 8364 goto cleanup; 8365 } 8366 face_remap = HeapAlloc(GetProcessHeap(), 0, tc[i].num_faces * sizeof(*face_remap)); 8367 if (!face_remap) 8368 { 8369 skip("Couldn't allocate face_remap array.\n"); 8370 goto cleanup; 8371 } 8372 8373 hr = D3DXWeldVertices(mesh, tc[i].flags, tc[i].epsilons, tc[i].adjacency, 8374 adjacency_out, face_remap, &vertex_remap); 8375 ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); 8376 /* Check number of vertices*/ 8377 new_num_vertices = mesh->lpVtbl->GetNumVertices(mesh); 8378 ok(new_num_vertices == tc[i].exp_new_num_vertices, 8379 "Mesh %d: new_num_vertices == %d, expected %d.\n", 8380 i, new_num_vertices, tc[i].exp_new_num_vertices); 8381 /* Check index buffer */ 8382 if (tc[i].options & D3DXMESH_32BIT) 8383 { 8384 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, (void**)&indices); 8385 if (FAILED(hr)) 8386 { 8387 skip("Couldn't lock index buffer.\n"); 8388 goto cleanup; 8389 } 8390 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++) 8391 { 8392 ok(indices[j] == tc[i].exp_indices[j], 8393 "Mesh %d: indices[%d] == %d, expected %d\n", 8394 i, j, indices[j], tc[i].exp_indices[j]); 8395 } 8396 } 8397 else 8398 { 8399 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, (void**)&indices_16bit); 8400 if (FAILED(hr)) 8401 { 8402 skip("Couldn't lock index buffer.\n"); 8403 goto cleanup; 8404 } 8405 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++) 8406 { 8407 ok(indices_16bit[j] == tc[i].exp_indices[j], 8408 "Mesh %d: indices_16bit[%d] == %d, expected %d\n", 8409 i, j, indices_16bit[j], tc[i].exp_indices[j]); 8410 } 8411 } 8412 mesh->lpVtbl->UnlockIndexBuffer(mesh); 8413 indices = NULL; 8414 indices_16bit = NULL; 8415 /* Check adjacency_out */ 8416 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++) 8417 { 8418 ok(adjacency_out[j] == tc[i].adjacency[j], 8419 "Mesh %d: adjacency_out[%d] == %d, expected %d\n", 8420 i, j, adjacency_out[j], tc[i].adjacency[j]); 8421 } 8422 /* Check face_remap */ 8423 for (j = 0; j < tc[i].num_faces; j++) 8424 { 8425 ok(face_remap[j] == tc[i].exp_face_remap[j], 8426 "Mesh %d: face_remap[%d] == %d, expected %d\n", 8427 i, j, face_remap[j], tc[i].exp_face_remap[j]); 8428 } 8429 /* Check vertex_remap */ 8430 vertex_remap_ptr = vertex_remap->lpVtbl->GetBufferPointer(vertex_remap); 8431 for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++) 8432 { 8433 ok(vertex_remap_ptr[j] == tc[i].exp_vertex_remap[j], 8434 "Mesh %d: vertex_remap_ptr[%d] == %d, expected %d\n", 8435 i, j, vertex_remap_ptr[j], tc[i].exp_vertex_remap[j]); 8436 } 8437 /* Check vertex buffer */ 8438 hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, (void*)&vertices); 8439 if (FAILED(hr)) 8440 { 8441 skip("Couldn't lock vertex buffer.\n"); 8442 goto cleanup; 8443 } 8444 /* Check contents of re-ordered vertex buffer */ 8445 for (j = 0; j < tc[i].exp_new_num_vertices; j++) 8446 { 8447 int index = tc[i].vertex_size*j; 8448 check_vertex_components(__LINE__, i, j, &vertices[index], &tc[i].exp_vertices[index], tc[i].declaration); 8449 } 8450 mesh->lpVtbl->UnlockVertexBuffer(mesh); 8451 vertices = NULL; 8452 8453 /* Free mesh and output data */ 8454 HeapFree(GetProcessHeap(), 0, adjacency_out); 8455 adjacency_out = NULL; 8456 HeapFree(GetProcessHeap(), 0, face_remap); 8457 face_remap = NULL; 8458 vertex_remap->lpVtbl->Release(vertex_remap); 8459 vertex_remap = NULL; 8460 mesh->lpVtbl->Release(mesh); 8461 mesh = NULL; 8462 } 8463 8464 cleanup: 8465 HeapFree(GetProcessHeap(), 0, adjacency_out); 8466 HeapFree(GetProcessHeap(), 0, face_remap); 8467 if (indices) mesh->lpVtbl->UnlockIndexBuffer(mesh); 8468 if (indices_16bit) mesh->lpVtbl->UnlockIndexBuffer(mesh); 8469 if (mesh) mesh->lpVtbl->Release(mesh); 8470 if (vertex_remap) vertex_remap->lpVtbl->Release(vertex_remap); 8471 if (vertices) mesh->lpVtbl->UnlockVertexBuffer(mesh); 8472 free_test_context(test_context); 8473 } 8474 8475 static void test_clone_mesh(void) 8476 { 8477 HRESULT hr; 8478 struct test_context *test_context = NULL; 8479 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM; 8480 D3DVERTEXELEMENT9 declaration_pn[] = 8481 { 8482 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8483 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 8484 D3DDECL_END() 8485 }; 8486 D3DVERTEXELEMENT9 declaration_pntc[] = 8487 { 8488 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8489 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 8490 {0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 8491 D3DDECL_END() 8492 }; 8493 D3DVERTEXELEMENT9 declaration_ptcn[] = 8494 { 8495 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8496 {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 8497 {0, 20, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 8498 D3DDECL_END() 8499 }; 8500 D3DVERTEXELEMENT9 declaration_ptc[] = 8501 { 8502 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8503 {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 8504 D3DDECL_END() 8505 }; 8506 D3DVERTEXELEMENT9 declaration_ptc_float16_2[] = 8507 { 8508 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8509 {0, 12, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 8510 D3DDECL_END() 8511 }; 8512 D3DVERTEXELEMENT9 declaration_ptc_float16_4[] = 8513 { 8514 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8515 {0, 12, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 8516 D3DDECL_END() 8517 }; 8518 D3DVERTEXELEMENT9 declaration_ptc_float1[] = 8519 { 8520 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8521 {0, 12, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 8522 D3DDECL_END() 8523 }; 8524 D3DVERTEXELEMENT9 declaration_ptc_float3[] = 8525 { 8526 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8527 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 8528 D3DDECL_END() 8529 }; 8530 D3DVERTEXELEMENT9 declaration_ptc_float4[] = 8531 { 8532 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8533 {0, 12, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 8534 D3DDECL_END() 8535 }; 8536 D3DVERTEXELEMENT9 declaration_ptc_d3dcolor[] = 8537 { 8538 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8539 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 8540 D3DDECL_END() 8541 }; 8542 D3DVERTEXELEMENT9 declaration_ptc_ubyte4[] = 8543 { 8544 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8545 {0, 12, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 8546 D3DDECL_END() 8547 }; 8548 D3DVERTEXELEMENT9 declaration_ptc_ubyte4n[] = 8549 { 8550 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8551 {0, 12, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 8552 D3DDECL_END() 8553 }; 8554 D3DVERTEXELEMENT9 declaration_ptc_short2[] = 8555 { 8556 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8557 {0, 12, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 8558 D3DDECL_END() 8559 }; 8560 D3DVERTEXELEMENT9 declaration_ptc_short4[] = 8561 { 8562 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8563 {0, 12, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 8564 D3DDECL_END() 8565 }; 8566 D3DVERTEXELEMENT9 declaration_ptc_short2n[] = 8567 { 8568 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8569 {0, 12, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 8570 D3DDECL_END() 8571 }; 8572 D3DVERTEXELEMENT9 declaration_ptc_short4n[] = 8573 { 8574 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8575 {0, 12, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 8576 D3DDECL_END() 8577 }; 8578 D3DVERTEXELEMENT9 declaration_ptc_ushort2n[] = 8579 { 8580 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8581 {0, 12, D3DDECLTYPE_USHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 8582 D3DDECL_END() 8583 }; 8584 D3DVERTEXELEMENT9 declaration_ptc_ushort4n[] = 8585 { 8586 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8587 {0, 12, D3DDECLTYPE_USHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, 8588 D3DDECL_END() 8589 }; 8590 D3DVERTEXELEMENT9 declaration_ptc_float16_2_partialu[] = 8591 { 8592 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8593 {0, 12, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_PARTIALU, D3DDECLUSAGE_TEXCOORD, 0}, 8594 D3DDECL_END() 8595 }; 8596 D3DVERTEXELEMENT9 declaration_pntc1[] = 8597 { 8598 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 8599 {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 8600 {0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1}, 8601 D3DDECL_END() 8602 }; 8603 const unsigned int VERTS_PER_FACE = 3; 8604 BYTE *vertices = NULL; 8605 INT i; 8606 struct vertex_pn 8607 { 8608 D3DXVECTOR3 position; 8609 D3DXVECTOR3 normal; 8610 }; 8611 struct vertex_pntc 8612 { 8613 D3DXVECTOR3 position; 8614 D3DXVECTOR3 normal; 8615 D3DXVECTOR2 texcoords; 8616 }; 8617 struct vertex_ptcn 8618 { 8619 D3DXVECTOR3 position; 8620 D3DXVECTOR2 texcoords; 8621 D3DXVECTOR3 normal; 8622 }; 8623 struct vertex_ptc 8624 { 8625 D3DXVECTOR3 position; 8626 D3DXVECTOR2 texcoords; 8627 }; 8628 struct vertex_ptc_float16_2 8629 { 8630 D3DXVECTOR3 position; 8631 WORD texcoords[2]; /* float16_2 */ 8632 }; 8633 struct vertex_ptc_float16_4 8634 { 8635 D3DXVECTOR3 position; 8636 WORD texcoords[4]; /* float16_4 */ 8637 }; 8638 struct vertex_ptc_float1 8639 { 8640 D3DXVECTOR3 position; 8641 FLOAT texcoords; 8642 }; 8643 struct vertex_ptc_float3 8644 { 8645 D3DXVECTOR3 position; 8646 FLOAT texcoords[3]; 8647 }; 8648 struct vertex_ptc_float4 8649 { 8650 D3DXVECTOR3 position; 8651 FLOAT texcoords[4]; 8652 }; 8653 struct vertex_ptc_d3dcolor 8654 { 8655 D3DXVECTOR3 position; 8656 BYTE texcoords[4]; 8657 }; 8658 struct vertex_ptc_ubyte4 8659 { 8660 D3DXVECTOR3 position; 8661 BYTE texcoords[4]; 8662 }; 8663 struct vertex_ptc_ubyte4n 8664 { 8665 D3DXVECTOR3 position; 8666 BYTE texcoords[4]; 8667 }; 8668 struct vertex_ptc_short2 8669 { 8670 D3DXVECTOR3 position; 8671 SHORT texcoords[2]; 8672 }; 8673 struct vertex_ptc_short4 8674 { 8675 D3DXVECTOR3 position; 8676 SHORT texcoords[4]; 8677 }; 8678 struct vertex_ptc_ushort2n 8679 { 8680 D3DXVECTOR3 position; 8681 USHORT texcoords[2]; 8682 }; 8683 struct vertex_ptc_ushort4n 8684 { 8685 D3DXVECTOR3 position; 8686 USHORT texcoords[4]; 8687 }; 8688 struct vertex_ptc_udec3 8689 { 8690 D3DXVECTOR3 position; 8691 DWORD texcoords; 8692 }; 8693 struct vertex_ptc_dec3n 8694 { 8695 D3DXVECTOR3 position; 8696 DWORD texcoords; 8697 }; 8698 #ifndef __REACTOS__ 8699 D3DXVECTOR3 up = {0.0f, 0.0f, 1.0f}; 8700 D3DXVECTOR2 zero_vec2 = {0.0f, 0.0f}; 8701 #else 8702 #define up {0.0f, 0.0f, 1.0f} 8703 #define zero_vec2 {0.0f, 0.0f} 8704 #endif 8705 /* Test 0. Check that a mesh can be cloned if the new declaration is the 8706 * same as the one used to create the mesh. 8707 * 8708 * 0--1 3 8709 * | / /| 8710 * |/ / | 8711 * 2 5--4 8712 */ 8713 const struct vertex_pn vertices0[] = 8714 { 8715 {{ 0.0f, 3.0f, 0.f}, up}, 8716 {{ 2.0f, 3.0f, 0.f}, up}, 8717 {{ 0.0f, 0.0f, 0.f}, up}, 8718 8719 {{ 3.0f, 3.0f, 0.f}, up}, 8720 {{ 3.0f, 0.0f, 0.f}, up}, 8721 {{ 1.0f, 0.0f, 0.f}, up}, 8722 }; 8723 const UINT num_vertices0 = ARRAY_SIZE(vertices0); 8724 const UINT num_faces0 = ARRAY_SIZE(vertices0) / VERTS_PER_FACE; 8725 const UINT vertex_size0 = sizeof(*vertices0); 8726 /* Test 1. Check that 16-bit indices are handled. */ 8727 const DWORD options_16bit = D3DXMESH_SYSTEMMEM; 8728 /* Test 2. Check that the size of each vertex is increased and the data 8729 * moved if the new declaration adds an element after the original elements. 8730 */ 8731 const struct vertex_pntc exp_vertices2[] = 8732 { 8733 {{ 0.0f, 3.0f, 0.f}, up, zero_vec2}, 8734 {{ 2.0f, 3.0f, 0.f}, up, zero_vec2}, 8735 {{ 0.0f, 0.0f, 0.f}, up, zero_vec2}, 8736 8737 {{ 3.0f, 3.0f, 0.f}, up, zero_vec2}, 8738 {{ 3.0f, 0.0f, 0.f}, up, zero_vec2}, 8739 {{ 1.0f, 0.0f, 0.f}, up, zero_vec2}, 8740 }; 8741 const UINT exp_vertex_size2 = sizeof(*exp_vertices2); 8742 /* Test 3. Check that the size of each vertex is increased and the data 8743 * moved if the new declaration adds an element between the original 8744 * elements. 8745 */ 8746 const struct vertex_ptcn exp_vertices3[] = 8747 { 8748 {{ 0.0f, 3.0f, 0.f}, zero_vec2, up}, 8749 {{ 2.0f, 3.0f, 0.f}, zero_vec2, up}, 8750 {{ 0.0f, 0.0f, 0.f}, zero_vec2, up}, 8751 8752 {{ 3.0f, 3.0f, 0.f}, zero_vec2, up}, 8753 {{ 3.0f, 0.0f, 0.f}, zero_vec2, up}, 8754 {{ 1.0f, 0.0f, 0.f}, zero_vec2, up}, 8755 }; 8756 const UINT exp_vertex_size3 = sizeof(*exp_vertices3); 8757 /* Test 4. Test that data types can be converted, e.g. FLOAT2 to FLOAT16_2. */ 8758 const struct vertex_ptc vertices4[] = 8759 { 8760 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}}, 8761 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}}, 8762 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}}, 8763 8764 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}}, 8765 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}}, 8766 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}}, 8767 }; 8768 const UINT num_vertices4 = ARRAY_SIZE(vertices4); 8769 const UINT num_faces4 = ARRAY_SIZE(vertices4) / VERTS_PER_FACE; 8770 const UINT vertex_size4 = sizeof(*vertices4); 8771 const struct vertex_ptc_float16_2 exp_vertices4[] = 8772 { 8773 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */ 8774 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */ 8775 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */ 8776 8777 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd}}, /* {0.2f, 0.3f} */ 8778 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */ 8779 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */ 8780 }; 8781 const UINT exp_vertex_size4 = sizeof(*exp_vertices4); 8782 /* Test 5. Convert FLOAT2 to FLOAT16_4. */ 8783 const struct vertex_ptc vertices5[] = 8784 { 8785 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}}, 8786 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}}, 8787 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}}, 8788 8789 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}}, 8790 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}}, 8791 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}}, 8792 }; 8793 const UINT num_vertices5 = ARRAY_SIZE(vertices5); 8794 const UINT num_faces5 = ARRAY_SIZE(vertices5) / VERTS_PER_FACE; 8795 const UINT vertex_size5 = sizeof(*vertices5); 8796 const struct vertex_ptc_float16_4 exp_vertices5[] = 8797 { 8798 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00, 0, 0x3c00}}, /* {1.0f, 1.0f, 0.0f, 1.0f} */ 8799 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a, 0, 0x3c00}}, /* {0.5f, 0.7f, 0.0f, 1.0f} */ 8800 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd, 0, 0x3c00}}, /* {-0.2f, -0.3f, 0.0f, 1.0f} */ 8801 8802 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd, 0, 0x3c00}}, /* {0.2f, 0.3f, 0.0f, 1.0f} */ 8803 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00, 0, 0x3c00}}, /* {1.0f, 1.0f, 0.0f, 1.0f} */ 8804 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266, 0, 0x3c00}}, /* {0.1f, 0.2f, 0.0f, 1.0f} */ 8805 }; 8806 const UINT exp_vertex_size5 = sizeof(*exp_vertices5); 8807 /* Test 6. Convert FLOAT2 to FLOAT1. */ 8808 const struct vertex_ptc vertices6[] = 8809 { 8810 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}}, 8811 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}}, 8812 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}}, 8813 8814 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}}, 8815 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}}, 8816 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}}, 8817 }; 8818 const UINT num_vertices6 = ARRAY_SIZE(vertices6); 8819 const UINT num_faces6 = ARRAY_SIZE(vertices6) / VERTS_PER_FACE; 8820 const UINT vertex_size6 = sizeof(*vertices6); 8821 const struct vertex_ptc_float1 exp_vertices6[] = 8822 { 8823 {{ 0.0f, 3.0f, 0.f}, 1.0f}, 8824 {{ 2.0f, 3.0f, 0.f}, 0.5f}, 8825 {{ 0.0f, 0.0f, 0.f}, -0.2f}, 8826 8827 {{ 3.0f, 3.0f, 0.f}, 0.2f}, 8828 {{ 3.0f, 0.0f, 0.f}, 1.0f}, 8829 {{ 1.0f, 0.0f, 0.f}, 0.1f}, 8830 }; 8831 const UINT exp_vertex_size6 = sizeof(*exp_vertices6); 8832 /* Test 7. Convert FLOAT2 to FLOAT3. */ 8833 const struct vertex_ptc vertices7[] = 8834 { 8835 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}}, 8836 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}}, 8837 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}}, 8838 8839 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}}, 8840 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}}, 8841 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}}, 8842 }; 8843 const UINT num_vertices7 = ARRAY_SIZE(vertices7); 8844 const UINT num_faces7 = ARRAY_SIZE(vertices7) / VERTS_PER_FACE; 8845 const UINT vertex_size7 = sizeof(*vertices7); 8846 const struct vertex_ptc_float3 exp_vertices7[] = 8847 { 8848 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f, 0.0f}}, 8849 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f, 0.0f}}, 8850 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f, 0.0f}}, 8851 8852 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f, 0.0f}}, 8853 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f, 0.0f}}, 8854 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f, 0.0f}}, 8855 }; 8856 const UINT exp_vertex_size7 = sizeof(*exp_vertices7); 8857 /* Test 8. Convert FLOAT2 to FLOAT4. */ 8858 const struct vertex_ptc vertices8[] = 8859 { 8860 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}}, 8861 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}}, 8862 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}}, 8863 8864 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}}, 8865 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}}, 8866 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}}, 8867 }; 8868 const UINT num_vertices8 = ARRAY_SIZE(vertices8); 8869 const UINT num_faces8 = ARRAY_SIZE(vertices8) / VERTS_PER_FACE; 8870 const UINT vertex_size8 = sizeof(*vertices8); 8871 const struct vertex_ptc_float4 exp_vertices8[] = 8872 { 8873 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f, 0.0f, 1.0f}}, 8874 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f, 0.0f, 1.0f}}, 8875 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f, 0.0f, 1.0f}}, 8876 8877 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f, 0.0f, 1.0f}}, 8878 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f, 0.0f, 1.0f}}, 8879 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f, 0.0f, 1.0f}}, 8880 }; 8881 const UINT exp_vertex_size8 = sizeof(*exp_vertices8); 8882 /* Test 9. Convert FLOAT2 to D3DCOLOR. */ 8883 const struct vertex_ptc vertices9[] = 8884 { 8885 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}}, 8886 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}}, 8887 {{ 0.0f, 0.0f, 0.f}, {-0.4f, -0.6f}}, 8888 8889 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}}, 8890 {{ 3.0f, 0.0f, 0.f}, { 2.0f, 256.0f}}, 8891 {{ 1.0f, 0.0f, 0.f}, { 0.11f, 0.2f}}, 8892 }; 8893 const UINT num_vertices9 = ARRAY_SIZE(vertices9); 8894 const UINT num_faces9 = ARRAY_SIZE(vertices9) / VERTS_PER_FACE; 8895 const UINT vertex_size9 = sizeof(*vertices9); 8896 const struct vertex_ptc_d3dcolor exp_vertices9[] = 8897 { 8898 {{ 0.0f, 3.0f, 0.f}, {0, 255, 255, 255}}, 8899 {{ 2.0f, 3.0f, 0.f}, {0, 179, 128, 255}}, 8900 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 255}}, 8901 8902 {{ 3.0f, 3.0f, 0.f}, {0, 77, 51, 255}}, 8903 {{ 3.0f, 0.0f, 0.f}, {0, 255, 255, 255}}, 8904 {{ 1.0f, 0.0f, 0.f}, {0, 51, 28, 255}}, 8905 }; 8906 const UINT exp_vertex_size9 = sizeof(*exp_vertices9); 8907 /* Test 10. Convert FLOAT2 to UBYTE4. */ 8908 const struct vertex_ptc vertices10[] = 8909 { 8910 {{ 0.0f, 3.0f, 0.f}, { 0.0f, 1.0f}}, 8911 {{ 2.0f, 3.0f, 0.f}, { 2.0f, 3.0f}}, 8912 {{ 0.0f, 0.0f, 0.f}, { 254.0f, 255.0f}}, 8913 8914 {{ 3.0f, 3.0f, 0.f}, { 256.0f, 257.0f}}, 8915 {{ 3.0f, 0.0f, 0.f}, { 1.4f, 1.5f}}, 8916 {{ 1.0f, 0.0f, 0.f}, {-4.0f, -5.0f}}, 8917 }; 8918 const UINT num_vertices10 = ARRAY_SIZE(vertices10); 8919 const UINT num_faces10 = ARRAY_SIZE(vertices10) / VERTS_PER_FACE; 8920 const UINT vertex_size10 = sizeof(*vertices10); 8921 const struct vertex_ptc_ubyte4 exp_vertices10[] = 8922 { 8923 {{ 0.0f, 3.0f, 0.f}, {0, 1, 0, 1}}, 8924 {{ 2.0f, 3.0f, 0.f}, {2, 3, 0, 1}}, 8925 {{ 0.0f, 0.0f, 0.f}, {254, 255, 0, 1}}, 8926 8927 {{ 3.0f, 3.0f, 0.f}, {0, 1, 0, 1}}, 8928 {{ 3.0f, 0.0f, 0.f}, {1, 2, 0, 1}}, 8929 {{ 1.0f, 0.0f, 0.f}, {0, 0, 0, 1}}, 8930 }; 8931 const UINT exp_vertex_size10 = sizeof(*exp_vertices10); 8932 /* Test 11. Convert FLOAT2 to SHORT2. */ 8933 const struct vertex_ptc vertices11[] = 8934 { 8935 {{ 0.0f, 3.0f, 0.f}, { 1.0f, -1.0f}}, 8936 {{ 2.0f, 3.0f, 0.f}, { 0.4f, 0.5f}}, 8937 {{ 0.0f, 0.0f, 0.f}, {-0.5f, -5.0f}}, 8938 8939 {{ 3.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MIN}}, 8940 {{ 3.0f, 0.0f, 0.f}, {SHRT_MAX + 1.0f, SHRT_MIN - 1.0f}}, 8941 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX + 2.0f, SHRT_MIN - 2.0f}}, 8942 8943 {{ 4.0f, 3.0f, 0.f}, {2 * SHRT_MAX, 2 * SHRT_MIN}}, 8944 {{ 6.0f, 0.0f, 0.f}, {3 * SHRT_MAX, 3 * SHRT_MIN}}, 8945 {{ 4.0f, 0.0f, 0.f}, {4 * SHRT_MAX, 4 * SHRT_MIN}}, 8946 }; 8947 const UINT num_vertices11 = ARRAY_SIZE(vertices11); 8948 const UINT num_faces11 = ARRAY_SIZE(vertices11) / VERTS_PER_FACE; 8949 const UINT vertex_size11 = sizeof(*vertices11); 8950 const struct vertex_ptc_short2 exp_vertices11[] = 8951 { 8952 {{ 0.0f, 3.0f, 0.f}, {1, 0}}, 8953 {{ 2.0f, 3.0f, 0.f}, {0, 1}}, 8954 {{ 0.0f, 0.0f, 0.f}, {0, -4}}, 8955 8956 {{ 3.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MIN + 1}}, 8957 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MIN}}, 8958 {{ 1.0f, 0.0f, 0.f}, {SHRT_MIN + 1, SHRT_MAX}}, 8959 8960 {{ 4.0f, 3.0f, 0.f}, {-2, 1}}, 8961 {{ 6.0f, 0.0f, 0.f}, {32765, -32767}}, 8962 {{ 4.0f, 0.0f, 0.f}, {-4, 1}}, 8963 }; 8964 const UINT exp_vertex_size11 = sizeof(*exp_vertices11); 8965 /* Test 12. Convert FLOAT2 to SHORT4. */ 8966 const struct vertex_ptc vertices12[] = 8967 { 8968 {{ 0.0f, 3.0f, 0.f}, { 1.0f, -1.0f}}, 8969 {{ 2.0f, 3.0f, 0.f}, { 0.4f, 0.5f}}, 8970 {{ 0.0f, 0.0f, 0.f}, {-0.5f, -5.0f}}, 8971 8972 {{ 3.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MIN}}, 8973 {{ 3.0f, 0.0f, 0.f}, {SHRT_MAX + 1.0f, SHRT_MIN - 1.0f}}, 8974 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX + 2.0f, SHRT_MIN - 2.0f}}, 8975 8976 {{ 4.0f, 3.0f, 0.f}, {2 * SHRT_MAX, 2 * SHRT_MIN}}, 8977 {{ 6.0f, 0.0f, 0.f}, {3 * SHRT_MAX, 3 * SHRT_MIN}}, 8978 {{ 4.0f, 0.0f, 0.f}, {4 * SHRT_MAX, 4 * SHRT_MIN}}, 8979 }; 8980 const UINT num_vertices12 = ARRAY_SIZE(vertices12); 8981 const UINT num_faces12 = ARRAY_SIZE(vertices12) / VERTS_PER_FACE; 8982 const UINT vertex_size12 = sizeof(*vertices12); 8983 const struct vertex_ptc_short4 exp_vertices12[] = 8984 { 8985 {{ 0.0f, 3.0f, 0.f}, {1, 0, 0, 1}}, 8986 {{ 2.0f, 3.0f, 0.f}, {0, 1, 0, 1}}, 8987 {{ 0.0f, 0.0f, 0.f}, {0, -4, 0, 1}}, 8988 8989 {{ 3.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MIN + 1, 0, 1}}, 8990 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MIN, 0, 1}}, 8991 {{ 1.0f, 0.0f, 0.f}, {SHRT_MIN + 1, SHRT_MAX, 0, 1}}, 8992 8993 {{ 4.0f, 3.0f, 0.f}, {-2, 1, 0, 1}}, 8994 {{ 6.0f, 0.0f, 0.f}, {32765, -32767, 0, 1}}, 8995 {{ 4.0f, 0.0f, 0.f}, {-4, 1, 0, 1}}, 8996 }; 8997 const UINT exp_vertex_size12 = sizeof(*exp_vertices12); 8998 /* Test 13. Convert FLOAT2 to UBYTE4N. */ 8999 const struct vertex_ptc vertices13[] = 9000 { 9001 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 2.0f}}, 9002 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}}, 9003 {{ 0.0f, 0.0f, 0.f}, {-0.4f, -0.5f}}, 9004 9005 {{ 3.0f, 3.0f, 0.f}, {-0.6f, -1.0f}}, 9006 {{ 3.0f, 0.0f, 0.f}, {UCHAR_MAX, UCHAR_MAX + 1}}, 9007 {{ 1.0f, 0.0f, 0.f}, {2 * UCHAR_MAX, -UCHAR_MAX}}, 9008 }; 9009 const UINT num_vertices13 = ARRAY_SIZE(vertices13); 9010 const UINT num_faces13 = ARRAY_SIZE(vertices13) / VERTS_PER_FACE; 9011 const UINT vertex_size13 = sizeof(*vertices13); 9012 const struct vertex_ptc_ubyte4n exp_vertices13[] = 9013 { 9014 {{ 0.0f, 3.0f, 0.f}, {255, 255, 0, 255}}, 9015 {{ 2.0f, 3.0f, 0.f}, {128, 179, 0, 255}}, 9016 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 255}}, 9017 9018 {{ 3.0f, 3.0f, 0.f}, {0, 0, 0, 255}}, 9019 {{ 3.0f, 0.0f, 0.f}, {255, 255, 0, 255}}, 9020 {{ 1.0f, 0.0f, 0.f}, {255, 0, 0, 255}}, 9021 }; 9022 const UINT exp_vertex_size13 = sizeof(*exp_vertices13); 9023 /* Test 14. Convert FLOAT2 to SHORT2N. */ 9024 const struct vertex_ptc vertices14[] = 9025 { 9026 {{ 0.0f, 3.0f, 0.f}, {1.0f, 2.0f}}, 9027 {{ 2.0f, 3.0f, 0.f}, {0.4f, 0.5f}}, 9028 {{ 0.0f, 0.0f, 0.f}, {0.6f, -1.0f}}, 9029 9030 {{ 3.0f, 3.0f, 0.f}, {-0.4f, -0.5f}}, 9031 {{ 3.0f, 0.0f, 0.f}, {-0.9f, -0.99997}}, 9032 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX, SHRT_MIN}}, 9033 }; 9034 const UINT num_vertices14 = ARRAY_SIZE(vertices14); 9035 const UINT num_faces14 = ARRAY_SIZE(vertices14) / VERTS_PER_FACE; 9036 const UINT vertex_size14 = sizeof(*vertices14); 9037 const struct vertex_ptc_short2 exp_vertices14[] = 9038 { 9039 {{ 0.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MAX}}, 9040 {{ 2.0f, 3.0f, 0.f}, {13107, 16384}}, 9041 {{ 0.0f, 0.0f, 0.f}, {19660, SHRT_MIN + 2}}, 9042 9043 {{ 3.0f, 3.0f, 0.f}, {-13106, -16383}}, 9044 {{ 3.0f, 0.0f, 0.f}, {-29489, SHRT_MIN + 3}}, 9045 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX, SHRT_MIN + 2}}, 9046 }; 9047 const UINT exp_vertex_size14 = sizeof(*exp_vertices14); 9048 /* Test 15. Convert FLOAT2 to SHORT4N. */ 9049 const struct vertex_ptc vertices15[] = 9050 { 9051 {{ 0.0f, 3.0f, 0.f}, {1.0f, 2.0f}}, 9052 {{ 2.0f, 3.0f, 0.f}, {0.4f, 0.5f}}, 9053 {{ 0.0f, 0.0f, 0.f}, {0.6f, -1.0f}}, 9054 9055 {{ 3.0f, 3.0f, 0.f}, {-0.4f, -0.5f}}, 9056 {{ 3.0f, 0.0f, 0.f}, {-0.9f, -0.99997}}, 9057 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX, SHRT_MIN}}, 9058 }; 9059 const UINT num_vertices15 = ARRAY_SIZE(vertices15); 9060 const UINT num_faces15 = ARRAY_SIZE(vertices15) / VERTS_PER_FACE; 9061 const UINT vertex_size15 = sizeof(*vertices15); 9062 const struct vertex_ptc_short4 exp_vertices15[] = 9063 { 9064 {{ 0.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MAX, 0, SHRT_MAX}}, 9065 {{ 2.0f, 3.0f, 0.f}, {13107, 16384, 0, SHRT_MAX}}, 9066 {{ 0.0f, 0.0f, 0.f}, {19660, SHRT_MIN + 2, 0, SHRT_MAX}}, 9067 9068 {{ 3.0f, 3.0f, 0.f}, {-13106, -16383, 0, SHRT_MAX}}, 9069 {{ 3.0f, 0.0f, 0.f}, {-29489, SHRT_MIN + 3, 0, SHRT_MAX}}, 9070 {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX, SHRT_MIN + 2, 0, SHRT_MAX}}, 9071 }; 9072 const UINT exp_vertex_size15 = sizeof(*exp_vertices15); 9073 /* Test 16. Convert FLOAT2 to USHORT2N. */ 9074 const struct vertex_ptc vertices16[] = 9075 { 9076 {{ 0.0f, 3.0f, 0.f}, {1.0f, 2.0f}}, 9077 {{ 2.0f, 3.0f, 0.f}, {0.4f, 0.5f}}, 9078 {{ 0.0f, 0.0f, 0.f}, {0.6f, -1.0f}}, 9079 9080 {{ 3.0f, 3.0f, 0.f}, {-0.4f, -0.5f}}, 9081 {{ 3.0f, 0.0f, 0.f}, {-0.9f, 0.99998f}}, 9082 {{ 1.0f, 0.0f, 0.f}, {USHRT_MAX, 0.0f}}, 9083 }; 9084 const UINT num_vertices16 = ARRAY_SIZE(vertices16); 9085 const UINT num_faces16 = ARRAY_SIZE(vertices16) / VERTS_PER_FACE; 9086 const UINT vertex_size16 = sizeof(*vertices16); 9087 const struct vertex_ptc_ushort2n exp_vertices16[] = 9088 { 9089 {{ 0.0f, 3.0f, 0.f}, {USHRT_MAX, USHRT_MAX}}, 9090 {{ 2.0f, 3.0f, 0.f}, {26214, 32768}}, 9091 {{ 0.0f, 0.0f, 0.f}, {39321, 0}}, 9092 9093 {{ 3.0f, 3.0f, 0.f}, {0, 0}}, 9094 {{ 3.0f, 0.0f, 0.f}, {0, USHRT_MAX - 1}}, 9095 {{ 1.0f, 0.0f, 0.f}, {USHRT_MAX, 0}}, 9096 }; 9097 const UINT exp_vertex_size16 = sizeof(*exp_vertices16); 9098 /* Test 17. Convert FLOAT2 to USHORT4N. */ 9099 const struct vertex_ptc vertices17[] = 9100 { 9101 {{ 0.0f, 3.0f, 0.f}, {1.0f, 2.0f}}, 9102 {{ 2.0f, 3.0f, 0.f}, {0.4f, 0.5f}}, 9103 {{ 0.0f, 0.0f, 0.f}, {0.6f, -1.0f}}, 9104 9105 {{ 3.0f, 3.0f, 0.f}, {-0.4f, -0.5f}}, 9106 {{ 3.0f, 0.0f, 0.f}, {-0.9f, 0.99998f}}, 9107 {{ 1.0f, 0.0f, 0.f}, {USHRT_MAX, 0.0f}}, 9108 }; 9109 const UINT num_vertices17 = ARRAY_SIZE(vertices17); 9110 const UINT num_faces17 = ARRAY_SIZE(vertices17) / VERTS_PER_FACE; 9111 const UINT vertex_size17 = sizeof(*vertices17); 9112 const struct vertex_ptc_ushort4n exp_vertices17[] = 9113 { 9114 {{ 0.0f, 3.0f, 0.f}, {USHRT_MAX, USHRT_MAX, 0, USHRT_MAX}}, 9115 {{ 2.0f, 3.0f, 0.f}, {26214, 32768, 0, USHRT_MAX}}, 9116 {{ 0.0f, 0.0f, 0.f}, {39321, 0, 0, USHRT_MAX}}, 9117 9118 {{ 3.0f, 3.0f, 0.f}, {0, 0, 0, USHRT_MAX}}, 9119 {{ 3.0f, 0.0f, 0.f}, {0, USHRT_MAX - 1, 0, USHRT_MAX}}, 9120 {{ 1.0f, 0.0f, 0.f}, {USHRT_MAX, 0, 0, USHRT_MAX}}, 9121 }; 9122 const UINT exp_vertex_size17 = sizeof(*exp_vertices17); 9123 /* Test 18. Test that the method field is compared by converting a FLOAT2 to 9124 * FLOAT16_2. where the method field has been change from 9125 * D3DDECLMETHOD_DEFAULT to D3DDECLMETHOD_PARTIALU. */ 9126 const struct vertex_ptc vertices18[] = 9127 { 9128 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}}, 9129 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}}, 9130 {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}}, 9131 9132 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}}, 9133 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}}, 9134 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}}, 9135 }; 9136 const UINT num_vertices18 = ARRAY_SIZE(vertices18); 9137 const UINT num_faces18 = ARRAY_SIZE(vertices18) / VERTS_PER_FACE; 9138 const UINT vertex_size18 = sizeof(*vertices18); 9139 const struct vertex_ptc_float16_2 exp_vertices18[] = 9140 { 9141 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */ 9142 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */ 9143 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */ 9144 9145 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd}}, /* {0.2f, 0.3f} */ 9146 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */ 9147 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */ 9148 }; 9149 const UINT exp_vertex_size18 = sizeof(*exp_vertices18); 9150 /* Test 19. Test that data is lost if usage index changes, e.g. TEXCOORD0 9151 * TEXCOORD1. */ 9152 const struct vertex_pntc vertices19[] = 9153 { 9154 {{ 0.0f, 3.0f, 0.f}, up, { 1.0f, 1.0f}}, 9155 {{ 2.0f, 3.0f, 0.f}, up, { 0.5f, 0.7f}}, 9156 {{ 0.0f, 0.0f, 0.f}, up, {-0.2f, -0.3f}}, 9157 9158 {{ 3.0f, 3.0f, 0.f}, up, { 0.2f, 0.3f}}, 9159 {{ 3.0f, 0.0f, 0.f}, up, { 1.0f, 1.0f}}, 9160 {{ 1.0f, 0.0f, 0.f}, up, { 0.1f, 0.2f}}, 9161 }; 9162 const UINT num_vertices19 = ARRAY_SIZE(vertices19); 9163 const UINT num_faces19 = ARRAY_SIZE(vertices19) / VERTS_PER_FACE; 9164 const UINT vertex_size19 = sizeof(*vertices19); 9165 const struct vertex_pntc exp_vertices19[] = 9166 { 9167 {{ 0.0f, 3.0f, 0.f}, up, zero_vec2}, 9168 {{ 2.0f, 3.0f, 0.f}, up, zero_vec2}, 9169 {{ 0.0f, 0.0f, 0.f}, up, zero_vec2}, 9170 9171 {{ 3.0f, 3.0f, 0.f}, up, zero_vec2}, 9172 {{ 3.0f, 0.0f, 0.f}, up, zero_vec2}, 9173 {{ 1.0f, 0.0f, 0.f}, up, zero_vec2}, 9174 }; 9175 const UINT exp_vertex_size19 = sizeof(*exp_vertices19); 9176 /* Test 20. Another test that data is lost if usage index changes, e.g. 9177 * TEXCOORD1 to TEXCOORD0. */ 9178 const struct vertex_pntc vertices20[] = 9179 { 9180 {{ 0.0f, 3.0f, 0.f}, up, { 1.0f, 1.0f}}, 9181 {{ 2.0f, 3.0f, 0.f}, up, { 0.5f, 0.7f}}, 9182 {{ 0.0f, 0.0f, 0.f}, up, {-0.2f, -0.3f}}, 9183 9184 {{ 3.0f, 3.0f, 0.f}, up, { 0.2f, 0.3f}}, 9185 {{ 3.0f, 0.0f, 0.f}, up, { 1.0f, 1.0f}}, 9186 {{ 1.0f, 0.0f, 0.f}, up, { 0.1f, 0.2f}}, 9187 }; 9188 const UINT num_vertices20 = ARRAY_SIZE(vertices20); 9189 const UINT num_faces20 = ARRAY_SIZE(vertices20) / VERTS_PER_FACE; 9190 const UINT vertex_size20 = sizeof(*vertices20); 9191 const struct vertex_pntc exp_vertices20[] = 9192 { 9193 {{ 0.0f, 3.0f, 0.f}, up, zero_vec2}, 9194 {{ 2.0f, 3.0f, 0.f}, up, zero_vec2}, 9195 {{ 0.0f, 0.0f, 0.f}, up, zero_vec2}, 9196 9197 {{ 3.0f, 3.0f, 0.f}, up, zero_vec2}, 9198 {{ 3.0f, 0.0f, 0.f}, up, zero_vec2}, 9199 {{ 1.0f, 0.0f, 0.f}, up, zero_vec2}, 9200 }; 9201 const UINT exp_vertex_size20 = sizeof(*exp_vertices20); 9202 /* Test 21. Convert FLOAT1 to FLOAT2. */ 9203 const struct vertex_ptc_float1 vertices21[] = 9204 { 9205 {{ 0.0f, 3.0f, 0.f}, 1.0f}, 9206 {{ 2.0f, 3.0f, 0.f}, 0.5f}, 9207 {{ 0.0f, 0.0f, 0.f}, -0.2f}, 9208 9209 {{ 3.0f, 3.0f, 0.f}, 0.2f}, 9210 {{ 3.0f, 0.0f, 0.f}, 1.0f}, 9211 {{ 1.0f, 0.0f, 0.f}, 0.1f}, 9212 }; 9213 const UINT num_vertices21 = ARRAY_SIZE(vertices21); 9214 const UINT num_faces21 = ARRAY_SIZE(vertices21) / VERTS_PER_FACE; 9215 const UINT vertex_size21 = sizeof(*vertices21); 9216 const struct vertex_ptc exp_vertices21[] = 9217 { 9218 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 0.0f}}, 9219 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.0f}}, 9220 {{ 0.0f, 0.0f, 0.f}, {-0.2f, 0.0f}}, 9221 9222 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.0f}}, 9223 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 0.0f}}, 9224 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.0f}}, 9225 }; 9226 const UINT exp_vertex_size21 = sizeof(*exp_vertices21); 9227 /* Test 22. Convert FLOAT1 to FLOAT3. */ 9228 const struct vertex_ptc_float1 vertices22[] = 9229 { 9230 {{ 0.0f, 3.0f, 0.f}, 1.0f}, 9231 {{ 2.0f, 3.0f, 0.f}, 0.5f}, 9232 {{ 0.0f, 0.0f, 0.f}, -0.2f}, 9233 9234 {{ 3.0f, 3.0f, 0.f}, 0.2f}, 9235 {{ 3.0f, 0.0f, 0.f}, 1.0f}, 9236 {{ 1.0f, 0.0f, 0.f}, 0.1f}, 9237 }; 9238 const UINT num_vertices22 = ARRAY_SIZE(vertices22); 9239 const UINT num_faces22 = ARRAY_SIZE(vertices22) / VERTS_PER_FACE; 9240 const UINT vertex_size22 = sizeof(*vertices22); 9241 const struct vertex_ptc_float3 exp_vertices22[] = 9242 { 9243 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 0.0f, 0.0f}}, 9244 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.0f, 0.0f}}, 9245 {{ 0.0f, 0.0f, 0.f}, {-0.2f, 0.0f, 0.0f}}, 9246 9247 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.0f, 0.0f}}, 9248 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 0.0f, 0.0f}}, 9249 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.0f, 0.0f}}, 9250 }; 9251 const UINT exp_vertex_size22 = sizeof(*exp_vertices22); 9252 /* Test 23. Convert FLOAT1 to FLOAT4. */ 9253 const struct vertex_ptc_float1 vertices23[] = 9254 { 9255 {{ 0.0f, 3.0f, 0.f}, 1.0f}, 9256 {{ 2.0f, 3.0f, 0.f}, 0.5f}, 9257 {{ 0.0f, 0.0f, 0.f}, -0.2f}, 9258 9259 {{ 3.0f, 3.0f, 0.f}, 0.2f}, 9260 {{ 3.0f, 0.0f, 0.f}, 1.0f}, 9261 {{ 1.0f, 0.0f, 0.f}, 0.1f}, 9262 }; 9263 const UINT num_vertices23 = ARRAY_SIZE(vertices23); 9264 const UINT num_faces23 = ARRAY_SIZE(vertices23) / VERTS_PER_FACE; 9265 const UINT vertex_size23 = sizeof(*vertices23); 9266 const struct vertex_ptc_float4 exp_vertices23[] = 9267 { 9268 {{ 0.0f, 3.0f, 0.f}, { 1.0f, 0.0f, 0.0f, 1.0f}}, 9269 {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.0f, 0.0f, 1.0f}}, 9270 {{ 0.0f, 0.0f, 0.f}, {-0.2f, 0.0f, 0.0f, 1.0f}}, 9271 9272 {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.0f, 0.0f, 1.0f}}, 9273 {{ 3.0f, 0.0f, 0.f}, { 1.0f, 0.0f, 0.0f, 1.0f}}, 9274 {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.0f, 0.0f, 1.0f}}, 9275 }; 9276 const UINT exp_vertex_size23 = sizeof(*exp_vertices23); 9277 /* Test 24. Convert FLOAT1 to D3DCOLOR. */ 9278 const struct vertex_ptc_float1 vertices24[] = 9279 { 9280 {{ 0.0f, 3.0f, 0.f}, 1.0f}, 9281 {{ 2.0f, 3.0f, 0.f}, 0.5f}, 9282 {{ 0.0f, 0.0f, 0.f}, -0.2f}, 9283 9284 {{ 3.0f, 3.0f, 0.f}, 0.2f}, 9285 {{ 3.0f, 0.0f, 0.f}, 1.0f}, 9286 {{ 1.0f, 0.0f, 0.f}, 0.11f}, 9287 }; 9288 const UINT num_vertices24 = ARRAY_SIZE(vertices24); 9289 const UINT num_faces24 = ARRAY_SIZE(vertices24) / VERTS_PER_FACE; 9290 const UINT vertex_size24 = sizeof(*vertices24); 9291 const struct vertex_ptc_d3dcolor exp_vertices24[] = 9292 { 9293 {{ 0.0f, 3.0f, 0.f}, {0, 0, 255, 255}}, 9294 {{ 2.0f, 3.0f, 0.f}, {0, 0, 128, 255}}, 9295 {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 255}}, 9296 9297 {{ 3.0f, 3.0f, 0.f}, {0, 0, 51, 255}}, 9298 {{ 3.0f, 0.0f, 0.f}, {0, 0, 255, 255}}, 9299 {{ 1.0f, 0.0f, 0.f}, {0, 0, 28, 255}}, 9300 }; 9301 const UINT exp_vertex_size24 = sizeof(*exp_vertices24); 9302 /* Test 25. Convert FLOAT1 to ubyte4. */ 9303 const struct vertex_ptc_float1 vertices25[] = 9304 { 9305 {{ 0.0f, 3.0f, 0.f}, 0.0f}, 9306 {{ 2.0f, 3.0f, 0.f}, 1.4f}, 9307 {{ 0.0f, 0.0f, 0.f}, 1.5f}, 9308 9309 {{ 3.0f, 3.0f, 0.f}, 255.0f}, 9310 {{ 3.0f, 0.0f, 0.f}, 256.0f}, 9311 {{ 1.0f, 0.0f, 0.f}, -1.0f}, 9312 }; 9313 const UINT num_vertices25 = ARRAY_SIZE(vertices25); 9314 const UINT num_faces25 = ARRAY_SIZE(vertices25) / VERTS_PER_FACE; 9315 const UINT vertex_size25 = sizeof(*vertices25); 9316 const struct vertex_ptc_ubyte4 exp_vertices25[] = 9317 { 9318 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 1}}, 9319 {{ 2.0f, 3.0f, 0.f}, {1, 0, 0, 1}}, 9320 {{ 0.0f, 0.0f, 0.f}, {2, 0, 0, 1}}, 9321 9322 {{ 3.0f, 3.0f, 0.f}, {255, 0, 0, 1}}, 9323 {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 1}}, 9324 {{ 1.0f, 0.0f, 0.f}, {0, 0, 0, 1}}, 9325 }; 9326 const UINT exp_vertex_size25 = sizeof(*exp_vertices25); 9327 /* Test 26. Convert FLOAT4 to D3DCOLOR. */ 9328 const struct vertex_ptc_float4 vertices26[] = 9329 { 9330 {{ 0.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.4f, 0.5f}}, 9331 {{ 2.0f, 3.0f, 0.f}, {-0.4f, -0.5f, -1.0f, -2.0f}}, 9332 {{ 0.0f, 0.0f, 0.f}, {254.0f, 255.0f, 256.0f, 257.0f}}, 9333 9334 {{ 3.0f, 3.0f, 0.f}, {0.1f, 0.2f, 0.3f, 0.4f}}, 9335 {{ 3.0f, 0.0f, 0.f}, {0.5f, 0.6f, 0.7f, 0.8f}}, 9336 {{ 1.0f, 0.0f, 0.f}, {0.9f, 0.99f, 0.995f, 0.999f}}, 9337 }; 9338 const UINT num_vertices26 = ARRAY_SIZE(vertices26); 9339 const UINT num_faces26 = ARRAY_SIZE(vertices26) / VERTS_PER_FACE; 9340 const UINT vertex_size26 = sizeof(*vertices26); 9341 const struct vertex_ptc_d3dcolor exp_vertices26[] = 9342 { 9343 {{ 0.0f, 3.0f, 0.f}, {102, 255, 0, 128}}, 9344 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, 9345 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}}, 9346 9347 {{ 3.0f, 3.0f, 0.f}, {77, 51, 26, 102}}, 9348 {{ 3.0f, 0.0f, 0.f}, {179, 153, 128, 204}}, 9349 {{ 1.0f, 0.0f, 0.f}, {254, 252, 230, 255}}, 9350 }; 9351 const UINT exp_vertex_size26 = sizeof(*exp_vertices26); 9352 /* Test 27. Convert D3DCOLOR to FLOAT4. */ 9353 const struct vertex_ptc_d3dcolor vertices27[] = 9354 { 9355 {{ 0.0f, 3.0f, 0.f}, {102, 255, 0, 128}}, 9356 {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, 9357 {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}}, 9358 9359 {{ 3.0f, 3.0f, 0.f}, {77, 51, 26, 102}}, 9360 {{ 3.0f, 0.0f, 0.f}, {179, 153, 128, 204}}, 9361 {{ 1.0f, 0.0f, 0.f}, {254, 252, 230, 255}}, 9362 }; 9363 const UINT num_vertices27 = ARRAY_SIZE(vertices27); 9364 const UINT num_faces27 = ARRAY_SIZE(vertices27) / VERTS_PER_FACE; 9365 const UINT vertex_size27 = sizeof(*vertices27); 9366 const struct vertex_ptc_float4 exp_vertices27[] = 9367 { 9368 {{ 0.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.4f, 0.501961f}}, 9369 {{ 2.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}}, 9370 {{ 0.0f, 0.0f, 0.f}, {1.0f, 1.0f, 1.0f, 1.0f}}, 9371 9372 {{ 3.0f, 3.0f, 0.f}, {0.101961f, 0.2f, 0.301961f, 0.4f}}, 9373 {{ 3.0f, 0.0f, 0.f}, {0.501961f, 0.6f, 0.701961f, 0.8f}}, 9374 {{ 1.0f, 0.0f, 0.f}, {0.901961f, 0.988235f, 0.996078f, 1.0f}}, 9375 }; 9376 const UINT exp_vertex_size27 = sizeof(*exp_vertices27); 9377 /* Test 28. Convert UBYTE4 to FLOAT4. */ 9378 const struct vertex_ptc_ubyte4 vertices28[] = 9379 { 9380 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, 9381 {{ 2.0f, 3.0f, 0.f}, {1, 1, 1, 1}}, 9382 {{ 0.0f, 0.0f, 0.f}, {1, 0, 1, 0}}, 9383 9384 {{ 3.0f, 3.0f, 0.f}, {0, 1, 0, 1}}, 9385 {{ 3.0f, 0.0f, 0.f}, {10, 20, 30, 40}}, 9386 {{ 1.0f, 0.0f, 0.f}, {50, 60, 127, 255}}, 9387 }; 9388 const UINT num_vertices28 = ARRAY_SIZE(vertices28); 9389 const UINT num_faces28 = ARRAY_SIZE(vertices28) / VERTS_PER_FACE; 9390 const UINT vertex_size28 = sizeof(*vertices28); 9391 const struct vertex_ptc_float4 exp_vertices28[] = 9392 { 9393 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}}, 9394 {{ 2.0f, 3.0f, 0.f}, {1.0f, 1.0f, 1.0f, 1.0f}}, 9395 {{ 0.0f, 0.0f, 0.f}, {1.0f, 0.0f, 1.0f, 0.0f}}, 9396 9397 {{ 3.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.0f, 1.0f}}, 9398 {{ 3.0f, 0.0f, 0.f}, {10.0f, 20.0f, 30.0f, 40.0f}}, 9399 {{ 1.0f, 0.0f, 0.f}, {50.0f, 60.0f, 127.0f, 255.0f}}, 9400 }; 9401 const UINT exp_vertex_size28 = sizeof(*exp_vertices28); 9402 /* Test 29. Convert SHORT2 to FLOAT4. */ 9403 const struct vertex_ptc_short2 vertices29[] = 9404 { 9405 {{ 0.0f, 3.0f, 0.f}, {0, 0}}, 9406 {{ 2.0f, 3.0f, 0.f}, {0, 1}}, 9407 {{ 0.0f, 0.0f, 0.f}, {1, 0}}, 9408 9409 {{ 3.0f, 3.0f, 0.f}, {1, 1}}, 9410 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MAX}}, 9411 {{ 1.0f, 0.0f, 0.f}, {-42, 42}}, 9412 }; 9413 const UINT num_vertices29 = ARRAY_SIZE(vertices29); 9414 const UINT num_faces29 = ARRAY_SIZE(vertices29) / VERTS_PER_FACE; 9415 const UINT vertex_size29 = sizeof(*vertices29); 9416 const struct vertex_ptc_float4 exp_vertices29[] = 9417 { 9418 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 1.0f}}, 9419 {{ 2.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.0f, 1.0f }}, 9420 {{ 0.0f, 0.0f, 0.f}, {1.0f, 0.0f, 0.0f, 1.0f}}, 9421 9422 {{ 3.0f, 3.0f, 0.f}, {1.0f, 1.0f, 0.0f, 1.0f}}, 9423 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MAX, 0.0f, 1.0f}}, 9424 {{ 1.0f, 0.0f, 0.f}, {-42.0f, 42.0f, 0.0f, 1.0f}}, 9425 }; 9426 const UINT exp_vertex_size29 = sizeof(*exp_vertices29); 9427 /* Test 29. Convert SHORT4 to FLOAT4. */ 9428 const struct vertex_ptc_short4 vertices30[] = 9429 { 9430 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, 9431 {{ 2.0f, 3.0f, 0.f}, {0, 1, 0, 1}}, 9432 {{ 0.0f, 0.0f, 0.f}, {1, 0, 1, 0}}, 9433 9434 {{ 3.0f, 3.0f, 0.f}, {1, 1, 1, 1}}, 9435 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MAX, 1, 0}}, 9436 {{ 1.0f, 0.0f, 0.f}, {-42, 42, SHRT_MAX, SHRT_MIN}}, 9437 }; 9438 const UINT num_vertices30 = ARRAY_SIZE(vertices30); 9439 const UINT num_faces30 = ARRAY_SIZE(vertices30) / VERTS_PER_FACE; 9440 const UINT vertex_size30 = sizeof(*vertices30); 9441 const struct vertex_ptc_float4 exp_vertices30[] = 9442 { 9443 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}}, 9444 {{ 2.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.0f, 1.0f }}, 9445 {{ 0.0f, 0.0f, 0.f}, {1.0f, 0.0f, 1.0f, 0.0f}}, 9446 9447 {{ 3.0f, 3.0f, 0.f}, {1.0f, 1.0f, 1.0f, 1.0f}}, 9448 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MAX, 1.0f, 0.0f}}, 9449 {{ 1.0f, 0.0f, 0.f}, {-42.0f, 42.0f, SHRT_MAX, SHRT_MIN}}, 9450 }; 9451 const UINT exp_vertex_size30 = sizeof(*exp_vertices30); 9452 /* Test 31. Convert UBYTE4N to FLOAT4. */ 9453 const struct vertex_ptc_ubyte4n vertices31[] = 9454 { 9455 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, 9456 {{ 2.0f, 3.0f, 0.f}, {1, 1, 1, 1}}, 9457 {{ 0.0f, 0.0f, 0.f}, {1, 0, 1, 0}}, 9458 9459 {{ 3.0f, 3.0f, 0.f}, {0, 1, 0, 1}}, 9460 {{ 3.0f, 0.0f, 0.f}, {10, 20, 30, 40}}, 9461 {{ 1.0f, 0.0f, 0.f}, {50, 60, 70, UCHAR_MAX}}, 9462 }; 9463 const UINT num_vertices31 = ARRAY_SIZE(vertices31); 9464 const UINT num_faces31 = ARRAY_SIZE(vertices31) / VERTS_PER_FACE; 9465 const UINT vertex_size31 = sizeof(*vertices31); 9466 const struct vertex_ptc_float4 exp_vertices31[] = 9467 { 9468 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}}, 9469 {{ 2.0f, 3.0f, 0.f}, {(FLOAT)1/UCHAR_MAX, (FLOAT)1/UCHAR_MAX, (FLOAT)1/UCHAR_MAX, (FLOAT)1/UCHAR_MAX}}, 9470 {{ 0.0f, 0.0f, 0.f}, {(FLOAT)1/UCHAR_MAX, 0.0f, (FLOAT)1/UCHAR_MAX, 0.0f}}, 9471 9472 {{ 3.0f, 3.0f, 0.f}, {0.0f, (FLOAT)1/UCHAR_MAX, 0.0f, (FLOAT)1/UCHAR_MAX}}, 9473 {{ 3.0f, 0.0f, 0.f}, {(FLOAT)10/UCHAR_MAX, (FLOAT)20/UCHAR_MAX, (FLOAT)30/UCHAR_MAX, (FLOAT)40/UCHAR_MAX}}, 9474 {{ 1.0f, 0.0f, 0.f}, {(FLOAT)50/UCHAR_MAX, (FLOAT)60/UCHAR_MAX, (FLOAT)70/UCHAR_MAX, 1.0f}}, 9475 }; 9476 const UINT exp_vertex_size31 = sizeof(*exp_vertices31); 9477 /* Test 32. Convert SHORT2N to FLOAT4. */ 9478 const struct vertex_ptc_short2 vertices32[] = 9479 { 9480 {{ 0.0f, 3.0f, 0.f}, {0, 0}}, 9481 {{ 2.0f, 3.0f, 0.f}, {0, 1}}, 9482 {{ 0.0f, 0.0f, 0.f}, {1, 0}}, 9483 9484 {{ 3.0f, 3.0f, 0.f}, {1, 1}}, 9485 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN + 1, SHRT_MAX}}, 9486 {{ 1.0f, 0.0f, 0.f}, {-42, 42}}, 9487 }; 9488 const UINT num_vertices32 = ARRAY_SIZE(vertices32); 9489 const UINT num_faces32 = ARRAY_SIZE(vertices32) / VERTS_PER_FACE; 9490 const UINT vertex_size32 = sizeof(*vertices32); 9491 const struct vertex_ptc_float4 exp_vertices32[] = 9492 { 9493 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 1.0f}}, 9494 {{ 2.0f, 3.0f, 0.f}, {0.0f, 1.0f/SHRT_MAX, 0.0f, 1.0f}}, 9495 {{ 0.0f, 0.0f, 0.f}, {1.0f/SHRT_MAX, 0.0f, 0.0f, 1.0f}}, 9496 9497 {{ 3.0f, 3.0f, 0.f}, {1.0f/SHRT_MAX, 1.0f/SHRT_MAX, 0.0f, 1.0f}}, 9498 {{ 3.0f, 0.0f, 0.f}, {-1.0f, 1.0f, 0.0f, 1.0f}}, 9499 {{ 1.0f, 0.0f, 0.f}, {-42.0f/SHRT_MAX, 42.0f/SHRT_MAX, 0.0f, 1.0f}}, 9500 }; 9501 const UINT exp_vertex_size32 = sizeof(*exp_vertices32); 9502 /* Test 33. Convert SHORT4N to FLOAT4. */ 9503 const struct vertex_ptc_short4 vertices33[] = 9504 { 9505 {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, 9506 {{ 2.0f, 3.0f, 0.f}, {0, 1, 0, 1}}, 9507 {{ 0.0f, 0.0f, 0.f}, {1, 0, 1, 0}}, 9508 9509 {{ 3.0f, 3.0f, 0.f}, {1, 1, 1, 1}}, 9510 {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN + 1, SHRT_MAX, SHRT_MIN + 1, SHRT_MAX}}, 9511 {{ 1.0f, 0.0f, 0.f}, {-42, 42, 1, 1}}, 9512 }; 9513 const UINT num_vertices33 = ARRAY_SIZE(vertices33); 9514 const UINT num_faces33 = ARRAY_SIZE(vertices33) / VERTS_PER_FACE; 9515 const UINT vertex_size33 = sizeof(*vertices33); 9516 const struct vertex_ptc_float4 exp_vertices33[] = 9517 { 9518 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}}, 9519 {{ 2.0f, 3.0f, 0.f}, {0.0f, 1.0f/SHRT_MAX, 0.0f, 1.0f/SHRT_MAX}}, 9520 {{ 0.0f, 0.0f, 0.f}, {1.0f/SHRT_MAX, 0.0f, 1.0f/SHRT_MAX, 0.0f}}, 9521 9522 {{ 3.0f, 3.0f, 0.f}, {1.0f/SHRT_MAX, 1.0f/SHRT_MAX, 1.0f/SHRT_MAX, 1.0f/SHRT_MAX}}, 9523 {{ 3.0f, 0.0f, 0.f}, {-1.0f, 1.0f, -1.0f, 1.0f}}, 9524 {{ 1.0f, 0.0f, 0.f}, {-42.0f/SHRT_MAX, 42.0f/SHRT_MAX, 1.0f/SHRT_MAX, 1.0f/SHRT_MAX}}, 9525 }; 9526 const UINT exp_vertex_size33 = sizeof(*exp_vertices33); 9527 /* Test 34. Convert FLOAT16_2 to FLOAT4. */ 9528 const struct vertex_ptc_float16_2 vertices34[] = 9529 { 9530 {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */ 9531 {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */ 9532 {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */ 9533 9534 {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd}}, /* {0.2f, 0.3f} */ 9535 {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */ 9536 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */ 9537 }; 9538 const UINT num_vertices34 = ARRAY_SIZE(vertices34); 9539 const UINT num_faces34 = ARRAY_SIZE(vertices34) / VERTS_PER_FACE; 9540 const UINT vertex_size34 = sizeof(*vertices34); 9541 const struct vertex_ptc_float4 exp_vertices34[] = 9542 { 9543 {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f, 0.0f, 1.0f}}, 9544 {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.700195f, 0.0f, 1.0f}}, 9545 {{ 0.0f, 0.0f, 0.f}, {-0.199951f, -0.300049f, 0.0f, 1.0f}}, 9546 9547 {{ 3.0f, 3.0f, 0.f}, {0.199951f, 0.300049f, 0.0f, 1.0f}}, 9548 {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f, 0.0f, 1.0f}}, 9549 {{ 1.0f, 0.0f, 0.f}, {0.099976f, 0.199951f, 0.0f, 1.0f}}, 9550 }; 9551 const UINT exp_vertex_size34 = sizeof(*exp_vertices34); 9552 /* Test 35. Convert FLOAT16_4 to FLOAT4. */ 9553 const struct vertex_ptc_float16_4 vertices35[] = 9554 { 9555 {{ 0.0f, 3.0f, 0.f}, {0x0000, 0x0000, 0x0000, 0x0000}}, 9556 {{ 2.0f, 3.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}}, 9557 {{ 0.0f, 0.0f, 0.f}, {0x3c00, 0x0000, 0x3c00, 0x0000}}, 9558 9559 {{ 3.0f, 3.0f, 0.f}, {0x0000, 0x3c00, 0x0000, 0x3c00}}, 9560 {{ 3.0f, 0.0f, 0.f}, {0x3800, 0x399a, 0xb266, 0xb4cd}}, 9561 {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266, 0x2e66, 0x3266}}, 9562 }; 9563 const UINT num_vertices35 = ARRAY_SIZE(vertices35); 9564 const UINT num_faces35 = ARRAY_SIZE(vertices35) / VERTS_PER_FACE; 9565 const UINT vertex_size35 = sizeof(*vertices35); 9566 const struct vertex_ptc_float4 exp_vertices35[] = 9567 { 9568 {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}}, 9569 {{ 2.0f, 3.0f, 0.f}, {1.0f, 1.0f, 1.0f, 1.0f}}, 9570 {{ 0.0f, 0.0f, 0.f}, {1.0f, 0.0f, 1.0f, 0.0f}}, 9571 9572 {{ 3.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.0f, 1.0f}}, 9573 {{ 3.0f, 0.0f, 0.f}, {0.5f, 0.700195f, -0.199951f, -0.300049f}}, 9574 {{ 1.0f, 0.0f, 0.f}, {0.099976f, 0.199951f, 0.099976f, 0.199951f}}, 9575 }; 9576 const UINT exp_vertex_size35 = sizeof(*exp_vertices35); 9577 /* Test 36. Check that vertex buffer sharing is ok. */ 9578 const struct vertex_pn vertices36[] = 9579 { 9580 {{ 0.0f, 3.0f, 0.f}, up}, 9581 {{ 2.0f, 3.0f, 0.f}, up}, 9582 {{ 0.0f, 0.0f, 0.f}, up}, 9583 }; 9584 const UINT num_vertices36 = ARRAY_SIZE(vertices36); 9585 const UINT num_faces36 = ARRAY_SIZE(vertices36) / VERTS_PER_FACE; 9586 const UINT vertex_size36 = sizeof(*vertices36); 9587 const DWORD clone_options36 = options | D3DXMESH_VB_SHARE; 9588 /* Common mesh data */ 9589 ID3DXMesh *mesh = NULL; 9590 ID3DXMesh *mesh_clone = NULL; 9591 struct 9592 { 9593 const BYTE *vertices; 9594 const DWORD *indices; 9595 const DWORD *attributes; 9596 const UINT num_vertices; 9597 const UINT num_faces; 9598 const UINT vertex_size; 9599 const DWORD create_options; 9600 const DWORD clone_options; 9601 D3DVERTEXELEMENT9 *declaration; 9602 D3DVERTEXELEMENT9 *new_declaration; 9603 const BYTE *exp_vertices; 9604 const UINT exp_vertex_size; 9605 } 9606 tc[] = 9607 { 9608 { 9609 (BYTE*)vertices0, 9610 NULL, 9611 NULL, 9612 num_vertices0, 9613 num_faces0, 9614 vertex_size0, 9615 options, 9616 options, 9617 declaration_pn, 9618 declaration_pn, 9619 (BYTE*)vertices0, 9620 vertex_size0 9621 }, 9622 { 9623 (BYTE*)vertices0, 9624 NULL, 9625 NULL, 9626 num_vertices0, 9627 num_faces0, 9628 vertex_size0, 9629 options_16bit, 9630 options_16bit, 9631 declaration_pn, 9632 declaration_pn, 9633 (BYTE*)vertices0, 9634 vertex_size0 9635 }, 9636 { 9637 (BYTE*)vertices0, 9638 NULL, 9639 NULL, 9640 num_vertices0, 9641 num_faces0, 9642 vertex_size0, 9643 options, 9644 options, 9645 declaration_pn, 9646 declaration_pntc, 9647 (BYTE*)exp_vertices2, 9648 exp_vertex_size2 9649 }, 9650 { 9651 (BYTE*)vertices0, 9652 NULL, 9653 NULL, 9654 num_vertices0, 9655 num_faces0, 9656 vertex_size0, 9657 options, 9658 options, 9659 declaration_pn, 9660 declaration_ptcn, 9661 (BYTE*)exp_vertices3, 9662 exp_vertex_size3 9663 }, 9664 { 9665 (BYTE*)vertices4, 9666 NULL, 9667 NULL, 9668 num_vertices4, 9669 num_faces4, 9670 vertex_size4, 9671 options, 9672 options, 9673 declaration_ptc, 9674 declaration_ptc_float16_2, 9675 (BYTE*)exp_vertices4, 9676 exp_vertex_size4 9677 }, 9678 { 9679 (BYTE*)vertices5, 9680 NULL, 9681 NULL, 9682 num_vertices5, 9683 num_faces5, 9684 vertex_size5, 9685 options, 9686 options, 9687 declaration_ptc, 9688 declaration_ptc_float16_4, 9689 (BYTE*)exp_vertices5, 9690 exp_vertex_size5 9691 }, 9692 { 9693 (BYTE*)vertices6, 9694 NULL, 9695 NULL, 9696 num_vertices6, 9697 num_faces6, 9698 vertex_size6, 9699 options, 9700 options, 9701 declaration_ptc, 9702 declaration_ptc_float1, 9703 (BYTE*)exp_vertices6, 9704 exp_vertex_size6 9705 }, 9706 { 9707 (BYTE*)vertices7, 9708 NULL, 9709 NULL, 9710 num_vertices7, 9711 num_faces7, 9712 vertex_size7, 9713 options, 9714 options, 9715 declaration_ptc, 9716 declaration_ptc_float3, 9717 (BYTE*)exp_vertices7, 9718 exp_vertex_size7 9719 }, 9720 { 9721 (BYTE*)vertices8, 9722 NULL, 9723 NULL, 9724 num_vertices8, 9725 num_faces8, 9726 vertex_size8, 9727 options, 9728 options, 9729 declaration_ptc, 9730 declaration_ptc_float4, 9731 (BYTE*)exp_vertices8, 9732 exp_vertex_size8 9733 }, 9734 { 9735 (BYTE*)vertices9, 9736 NULL, 9737 NULL, 9738 num_vertices9, 9739 num_faces9, 9740 vertex_size9, 9741 options, 9742 options, 9743 declaration_ptc, 9744 declaration_ptc_d3dcolor, 9745 (BYTE*)exp_vertices9, 9746 exp_vertex_size9 9747 }, 9748 { 9749 (BYTE*)vertices10, 9750 NULL, 9751 NULL, 9752 num_vertices10, 9753 num_faces10, 9754 vertex_size10, 9755 options, 9756 options, 9757 declaration_ptc, 9758 declaration_ptc_ubyte4, 9759 (BYTE*)exp_vertices10, 9760 exp_vertex_size10 9761 }, 9762 { 9763 (BYTE*)vertices11, 9764 NULL, 9765 NULL, 9766 num_vertices11, 9767 num_faces11, 9768 vertex_size11, 9769 options, 9770 options, 9771 declaration_ptc, 9772 declaration_ptc_short2, 9773 (BYTE*)exp_vertices11, 9774 exp_vertex_size11 9775 }, 9776 { 9777 (BYTE*)vertices12, 9778 NULL, 9779 NULL, 9780 num_vertices12, 9781 num_faces12, 9782 vertex_size12, 9783 options, 9784 options, 9785 declaration_ptc, 9786 declaration_ptc_short4, 9787 (BYTE*)exp_vertices12, 9788 exp_vertex_size12 9789 }, 9790 { 9791 (BYTE*)vertices13, 9792 NULL, 9793 NULL, 9794 num_vertices13, 9795 num_faces13, 9796 vertex_size13, 9797 options, 9798 options, 9799 declaration_ptc, 9800 declaration_ptc_ubyte4n, 9801 (BYTE*)exp_vertices13, 9802 exp_vertex_size13 9803 }, 9804 { 9805 (BYTE*)vertices14, 9806 NULL, 9807 NULL, 9808 num_vertices14, 9809 num_faces14, 9810 vertex_size14, 9811 options, 9812 options, 9813 declaration_ptc, 9814 declaration_ptc_short2n, 9815 (BYTE*)exp_vertices14, 9816 exp_vertex_size14 9817 }, 9818 { 9819 (BYTE*)vertices15, 9820 NULL, 9821 NULL, 9822 num_vertices15, 9823 num_faces15, 9824 vertex_size15, 9825 options, 9826 options, 9827 declaration_ptc, 9828 declaration_ptc_short4n, 9829 (BYTE*)exp_vertices15, 9830 exp_vertex_size15 9831 }, 9832 { 9833 (BYTE*)vertices16, 9834 NULL, 9835 NULL, 9836 num_vertices16, 9837 num_faces16, 9838 vertex_size16, 9839 options, 9840 options, 9841 declaration_ptc, 9842 declaration_ptc_ushort2n, 9843 (BYTE*)exp_vertices16, 9844 exp_vertex_size16 9845 }, 9846 { 9847 (BYTE*)vertices17, 9848 NULL, 9849 NULL, 9850 num_vertices17, 9851 num_faces17, 9852 vertex_size17, 9853 options, 9854 options, 9855 declaration_ptc, 9856 declaration_ptc_ushort4n, 9857 (BYTE*)exp_vertices17, 9858 exp_vertex_size17 9859 }, 9860 { 9861 (BYTE*)vertices18, 9862 NULL, 9863 NULL, 9864 num_vertices18, 9865 num_faces18, 9866 vertex_size18, 9867 options, 9868 options, 9869 declaration_ptc, 9870 declaration_ptc_float16_2_partialu, 9871 (BYTE*)exp_vertices18, 9872 exp_vertex_size18 9873 }, 9874 { 9875 (BYTE*)vertices19, 9876 NULL, 9877 NULL, 9878 num_vertices19, 9879 num_faces19, 9880 vertex_size19, 9881 options, 9882 options, 9883 declaration_pntc, 9884 declaration_pntc1, 9885 (BYTE*)exp_vertices19, 9886 exp_vertex_size19 9887 }, 9888 { 9889 (BYTE*)vertices20, 9890 NULL, 9891 NULL, 9892 num_vertices20, 9893 num_faces20, 9894 vertex_size20, 9895 options, 9896 options, 9897 declaration_pntc1, 9898 declaration_pntc, 9899 (BYTE*)exp_vertices20, 9900 exp_vertex_size20 9901 }, 9902 { 9903 (BYTE*)vertices21, 9904 NULL, 9905 NULL, 9906 num_vertices21, 9907 num_faces21, 9908 vertex_size21, 9909 options, 9910 options, 9911 declaration_ptc_float1, 9912 declaration_ptc, 9913 (BYTE*)exp_vertices21, 9914 exp_vertex_size21 9915 }, 9916 { 9917 (BYTE*)vertices22, 9918 NULL, 9919 NULL, 9920 num_vertices22, 9921 num_faces22, 9922 vertex_size22, 9923 options, 9924 options, 9925 declaration_ptc_float1, 9926 declaration_ptc_float3, 9927 (BYTE*)exp_vertices22, 9928 exp_vertex_size22 9929 }, 9930 { 9931 (BYTE*)vertices23, 9932 NULL, 9933 NULL, 9934 num_vertices23, 9935 num_faces23, 9936 vertex_size23, 9937 options, 9938 options, 9939 declaration_ptc_float1, 9940 declaration_ptc_float4, 9941 (BYTE*)exp_vertices23, 9942 exp_vertex_size23 9943 }, 9944 { 9945 (BYTE*)vertices24, 9946 NULL, 9947 NULL, 9948 num_vertices24, 9949 num_faces24, 9950 vertex_size24, 9951 options, 9952 options, 9953 declaration_ptc_float1, 9954 declaration_ptc_d3dcolor, 9955 (BYTE*)exp_vertices24, 9956 exp_vertex_size24 9957 }, 9958 { 9959 (BYTE*)vertices25, 9960 NULL, 9961 NULL, 9962 num_vertices25, 9963 num_faces25, 9964 vertex_size25, 9965 options, 9966 options, 9967 declaration_ptc_float1, 9968 declaration_ptc_ubyte4, 9969 (BYTE*)exp_vertices25, 9970 exp_vertex_size25 9971 }, 9972 { 9973 (BYTE*)vertices26, 9974 NULL, 9975 NULL, 9976 num_vertices26, 9977 num_faces26, 9978 vertex_size26, 9979 options, 9980 options, 9981 declaration_ptc_float4, 9982 declaration_ptc_d3dcolor, 9983 (BYTE*)exp_vertices26, 9984 exp_vertex_size26 9985 }, 9986 { 9987 (BYTE*)vertices27, 9988 NULL, 9989 NULL, 9990 num_vertices27, 9991 num_faces27, 9992 vertex_size27, 9993 options, 9994 options, 9995 declaration_ptc_d3dcolor, 9996 declaration_ptc_float4, 9997 (BYTE*)exp_vertices27, 9998 exp_vertex_size27 9999 }, 10000 { 10001 (BYTE*)vertices28, 10002 NULL, 10003 NULL, 10004 num_vertices28, 10005 num_faces28, 10006 vertex_size28, 10007 options, 10008 options, 10009 declaration_ptc_ubyte4, 10010 declaration_ptc_float4, 10011 (BYTE*)exp_vertices28, 10012 exp_vertex_size28 10013 }, 10014 { 10015 (BYTE*)vertices29, 10016 NULL, 10017 NULL, 10018 num_vertices29, 10019 num_faces29, 10020 vertex_size29, 10021 options, 10022 options, 10023 declaration_ptc_short2, 10024 declaration_ptc_float4, 10025 (BYTE*)exp_vertices29, 10026 exp_vertex_size29 10027 }, 10028 { 10029 (BYTE*)vertices30, 10030 NULL, 10031 NULL, 10032 num_vertices30, 10033 num_faces30, 10034 vertex_size30, 10035 options, 10036 options, 10037 declaration_ptc_short4, 10038 declaration_ptc_float4, 10039 (BYTE*)exp_vertices30, 10040 exp_vertex_size30 10041 }, 10042 { 10043 (BYTE*)vertices31, 10044 NULL, 10045 NULL, 10046 num_vertices31, 10047 num_faces31, 10048 vertex_size31, 10049 options, 10050 options, 10051 declaration_ptc_ubyte4n, 10052 declaration_ptc_float4, 10053 (BYTE*)exp_vertices31, 10054 exp_vertex_size31 10055 }, 10056 { 10057 (BYTE*)vertices32, 10058 NULL, 10059 NULL, 10060 num_vertices32, 10061 num_faces32, 10062 vertex_size32, 10063 options, 10064 options, 10065 declaration_ptc_short2n, 10066 declaration_ptc_float4, 10067 (BYTE*)exp_vertices32, 10068 exp_vertex_size32 10069 }, 10070 { 10071 (BYTE*)vertices33, 10072 NULL, 10073 NULL, 10074 num_vertices33, 10075 num_faces33, 10076 vertex_size33, 10077 options, 10078 options, 10079 declaration_ptc_short4n, 10080 declaration_ptc_float4, 10081 (BYTE*)exp_vertices33, 10082 exp_vertex_size33 10083 }, 10084 { 10085 (BYTE*)vertices34, 10086 NULL, 10087 NULL, 10088 num_vertices34, 10089 num_faces34, 10090 vertex_size34, 10091 options, 10092 options, 10093 declaration_ptc_float16_2, 10094 declaration_ptc_float4, 10095 (BYTE*)exp_vertices34, 10096 exp_vertex_size34 10097 }, 10098 { 10099 (BYTE*)vertices35, 10100 NULL, 10101 NULL, 10102 num_vertices35, 10103 num_faces35, 10104 vertex_size35, 10105 options, 10106 options, 10107 declaration_ptc_float16_4, 10108 declaration_ptc_float4, 10109 (BYTE*)exp_vertices35, 10110 exp_vertex_size35 10111 }, 10112 { 10113 (BYTE*)vertices36, 10114 NULL, 10115 NULL, 10116 num_vertices36, 10117 num_faces36, 10118 vertex_size36, 10119 options, 10120 clone_options36, 10121 declaration_pn, 10122 declaration_pn, 10123 (BYTE*)vertices36, 10124 vertex_size36 10125 }, 10126 }; 10127 #ifdef __REACTOS__ 10128 #undef up 10129 #undef zero_vec2 10130 #endif 10131 10132 test_context = new_test_context(); 10133 if (!test_context) 10134 { 10135 skip("Couldn't create test context\n"); 10136 goto cleanup; 10137 } 10138 10139 for (i = 0; i < ARRAY_SIZE(tc); i++) 10140 { 10141 UINT j; 10142 D3DVERTEXELEMENT9 new_declaration[MAX_FVF_DECL_SIZE]; 10143 UINT exp_new_decl_length, new_decl_length; 10144 UINT exp_new_decl_size, new_decl_size; 10145 10146 hr = init_test_mesh(tc[i].num_faces, tc[i].num_vertices, 10147 tc[i].create_options, 10148 tc[i].declaration, 10149 test_context->device, &mesh, 10150 tc[i].vertices, tc[i].vertex_size, 10151 tc[i].indices, tc[i].attributes); 10152 if (FAILED(hr)) 10153 { 10154 skip("Couldn't initialize test mesh %d. Got %x expected D3D_OK\n", i, hr); 10155 goto cleanup; 10156 } 10157 10158 hr = mesh->lpVtbl->CloneMesh(mesh, tc[i].clone_options, tc[i].new_declaration, 10159 test_context->device, &mesh_clone); 10160 ok(hr == D3D_OK, "CloneMesh test case %d failed. Got %x\n, expected D3D_OK\n", i, hr); 10161 10162 hr = mesh_clone->lpVtbl->GetDeclaration(mesh_clone, new_declaration); 10163 ok(hr == D3D_OK, "GetDeclaration test case %d failed. Got %x\n, expected D3D_OK\n", i, hr); 10164 /* Check declaration elements */ 10165 for (j = 0; tc[i].new_declaration[j].Stream != 0xFF; j++) 10166 { 10167 ok(memcmp(&tc[i].new_declaration[j], &new_declaration[j], sizeof(*new_declaration)) == 0, 10168 "Test case %d failed. Declaration element %d did not match.\n", i, j); 10169 } 10170 10171 /* Check declaration length */ 10172 exp_new_decl_length = D3DXGetDeclLength(tc[i].new_declaration); 10173 new_decl_length = D3DXGetDeclLength(new_declaration); 10174 ok(new_decl_length == exp_new_decl_length, 10175 "Test case %d failed. Got new declaration length %d, expected %d\n", 10176 i, new_decl_length, exp_new_decl_length); 10177 10178 /* Check declaration size */ 10179 exp_new_decl_size = D3DXGetDeclVertexSize(tc[i].new_declaration, 0); 10180 new_decl_size = D3DXGetDeclVertexSize(new_declaration, 0); 10181 ok(new_decl_size == exp_new_decl_size, 10182 "Test case %d failed. Got new declaration size %d, expected %d\n", 10183 i, new_decl_size, exp_new_decl_size); 10184 10185 /* Check vertex data in cloned mesh */ 10186 hr = mesh_clone->lpVtbl->LockVertexBuffer(mesh_clone, 0, (void**)&vertices); 10187 if (FAILED(hr)) 10188 { 10189 skip("Couldn't lock cloned vertex buffer.\n"); 10190 goto cleanup; 10191 } 10192 for (j = 0; j < tc[i].num_vertices; j++) 10193 { 10194 UINT index = tc[i].exp_vertex_size * j; 10195 check_vertex_components(__LINE__, i, j, &vertices[index], &tc[i].exp_vertices[index], tc[i].new_declaration); 10196 } 10197 hr = mesh_clone->lpVtbl->UnlockVertexBuffer(mesh_clone); 10198 if (FAILED(hr)) 10199 { 10200 skip("Couldn't unlock vertex buffer.\n"); 10201 goto cleanup; 10202 } 10203 vertices = NULL; 10204 mesh->lpVtbl->Release(mesh); 10205 mesh = NULL; 10206 mesh_clone->lpVtbl->Release(mesh_clone); 10207 mesh_clone = NULL; 10208 } 10209 10210 /* The following test shows that it is not possible to share a vertex buffer 10211 * with D3DXMESH_VB_SHARE and change the vertex declaration at the same 10212 * time. It reuses the test data from test 2. 10213 */ 10214 hr = init_test_mesh(tc[2].num_faces, tc[2].num_vertices, 10215 tc[2].create_options, 10216 tc[2].declaration, 10217 test_context->device, &mesh, 10218 tc[2].vertices, tc[2].vertex_size, 10219 tc[2].indices, tc[2].attributes); 10220 if (FAILED(hr)) 10221 { 10222 skip("Couldn't initialize test mesh for D3DXMESH_VB_SHARE case." 10223 " Got %x expected D3D_OK\n", hr); 10224 goto cleanup; 10225 } 10226 10227 hr = mesh->lpVtbl->CloneMesh(mesh, tc[2].create_options | D3DXMESH_VB_SHARE, 10228 tc[2].new_declaration, test_context->device, 10229 &mesh_clone); 10230 ok(hr == D3DERR_INVALIDCALL, "CloneMesh D3DXMESH_VB_SHARE with new" 10231 " declaration. Got %x, expected D3DERR_INVALIDCALL\n", 10232 hr); 10233 mesh->lpVtbl->Release(mesh); 10234 mesh = NULL; 10235 mesh_clone = NULL; 10236 10237 cleanup: 10238 if (vertices) mesh->lpVtbl->UnlockVertexBuffer(mesh); 10239 if (mesh) mesh->lpVtbl->Release(mesh); 10240 if (mesh_clone) mesh_clone->lpVtbl->Release(mesh_clone); 10241 free_test_context(test_context); 10242 } 10243 10244 static void test_valid_mesh(void) 10245 { 10246 HRESULT hr; 10247 struct test_context *test_context = NULL; 10248 UINT i; 10249 const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM; 10250 const D3DVERTEXELEMENT9 declaration[] = 10251 { 10252 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 10253 D3DDECL_END() 10254 }; 10255 const unsigned int VERTS_PER_FACE = 3; 10256 /* mesh0 (one face) 10257 * 10258 * 0--1 10259 * | / 10260 * |/ 10261 * 2 10262 */ 10263 const D3DXVECTOR3 vertices0[] = 10264 { 10265 { 0.0f, 3.0f, 0.f}, 10266 { 2.0f, 3.0f, 0.f}, 10267 { 0.0f, 0.0f, 0.f}, 10268 }; 10269 const DWORD indices0[] = {0, 1, 2}; 10270 const unsigned int num_vertices0 = ARRAY_SIZE(vertices0); 10271 const unsigned int num_faces0 = ARRAY_SIZE(indices0) / VERTS_PER_FACE; 10272 const DWORD adjacency0[] = {-1, -1, -1}; 10273 const HRESULT exp_hr0 = D3D_OK; 10274 /* mesh1 (Simple bow-tie) 10275 * 10276 * 0--1 1--3 10277 * | / \ | 10278 * |/ \| 10279 * 2 4 10280 */ 10281 const D3DXVECTOR3 vertices1[] = 10282 { 10283 { 0.0f, 3.0f, 0.f}, 10284 { 2.0f, 3.0f, 0.f}, 10285 { 0.0f, 0.0f, 0.f}, 10286 10287 { 4.0f, 3.0f, 0.f}, 10288 { 4.0f, 0.0f, 0.f}, 10289 }; 10290 const DWORD indices1[] = {0, 1, 2, 1, 3, 4}; 10291 const unsigned int num_vertices1 = ARRAY_SIZE(vertices1); 10292 const unsigned int num_faces1 = ARRAY_SIZE(indices1) / VERTS_PER_FACE; 10293 const DWORD adjacency1[] = {-1, -1, -1, -1, -1, -1}; 10294 const HRESULT exp_hr1 = D3DXERR_INVALIDMESH; 10295 /* Common mesh data */ 10296 ID3DXMesh *mesh = NULL; 10297 UINT vertex_size = sizeof(D3DXVECTOR3); 10298 ID3DXBuffer *errors_and_warnings = NULL; 10299 struct 10300 { 10301 const D3DXVECTOR3 *vertices; 10302 const DWORD *indices; 10303 const UINT num_vertices; 10304 const UINT num_faces; 10305 const DWORD *adjacency; 10306 const HRESULT exp_hr; 10307 } 10308 tc[] = 10309 { 10310 { 10311 vertices0, 10312 indices0, 10313 num_vertices0, 10314 num_faces0, 10315 adjacency0, 10316 exp_hr0, 10317 }, 10318 { 10319 vertices1, 10320 indices1, 10321 num_vertices1, 10322 num_faces1, 10323 adjacency1, 10324 exp_hr1, 10325 }, 10326 }; 10327 10328 test_context = new_test_context(); 10329 if (!test_context) 10330 { 10331 skip("Couldn't create test context\n"); 10332 goto cleanup; 10333 } 10334 10335 for (i = 0; i < ARRAY_SIZE(tc); i++) 10336 { 10337 hr = init_test_mesh(tc[i].num_faces, tc[i].num_vertices, 10338 options, declaration, 10339 test_context->device, &mesh, 10340 tc[i].vertices, vertex_size, 10341 tc[i].indices, NULL); 10342 if (FAILED(hr)) 10343 { 10344 skip("Couldn't initialize test mesh %d. Got %x expected D3D_OK\n", i, hr); 10345 goto cleanup; 10346 } 10347 10348 hr = D3DXValidMesh(mesh, tc[i].adjacency, &errors_and_warnings); 10349 todo_wine ok(hr == tc[i].exp_hr, "D3DXValidMesh test case %d failed. " 10350 "Got %x\n, expected %x\n", i, hr, tc[i].exp_hr); 10351 10352 /* Note errors_and_warnings is deliberately not checked because that 10353 * would require copying wast amounts of the text output. */ 10354 if (errors_and_warnings) 10355 { 10356 ID3DXBuffer_Release(errors_and_warnings); 10357 errors_and_warnings = NULL; 10358 } 10359 mesh->lpVtbl->Release(mesh); 10360 mesh = NULL; 10361 } 10362 10363 cleanup: 10364 if (mesh) mesh->lpVtbl->Release(mesh); 10365 free_test_context(test_context); 10366 } 10367 10368 static void test_optimize_faces(void) 10369 { 10370 HRESULT hr; 10371 UINT i; 10372 DWORD smallest_face_remap; 10373 /* mesh0 10374 * 10375 * 0--1 10376 * | / 10377 * |/ 10378 * 2 10379 */ 10380 const DWORD indices0[] = {0, 1, 2}; 10381 const UINT num_faces0 = 1; 10382 const UINT num_vertices0 = 3; 10383 const DWORD exp_face_remap0[] = {0}; 10384 /* mesh1 10385 * 10386 * 0--1 3 10387 * | / /| 10388 * |/ / | 10389 * 2 5--4 10390 */ 10391 const DWORD indices1[] = {0, 1, 2, 3, 4, 5}; 10392 const UINT num_faces1 = 2; 10393 const UINT num_vertices1 = 6; 10394 const DWORD exp_face_remap1[] = {1, 0}; 10395 /* mesh2 10396 * 10397 * 0--1 10398 * | /| 10399 * |/ | 10400 * 2--3 10401 */ 10402 const DWORD indices2[] = {0, 1, 2, 1, 3, 2}; 10403 const UINT num_faces2 = 2; 10404 const UINT num_vertices2 = 4; 10405 const DWORD exp_face_remap2[] = {1, 0}; 10406 /* mesh3 10407 * 10408 * 0--1 10409 * | /| 10410 * |/ | 10411 * 2--3 10412 * | /| 10413 * |/ | 10414 * 4--5 10415 */ 10416 const DWORD indices3[] = {0, 1, 2, 1, 3, 2, 2, 3, 4, 3, 4, 5}; 10417 const UINT num_faces3 = 4; 10418 const UINT num_vertices3 = 6; 10419 const DWORD exp_face_remap3[] = {3, 2, 1, 0}; 10420 /* mesh4 10421 * 10422 * 0--1 10423 * | /| 10424 * |/ | 10425 * 2--3 10426 * | /| 10427 * |/ | 10428 * 4--5 10429 */ 10430 const WORD indices4[] = {0, 1, 2, 1, 3, 2, 2, 3, 4, 3, 4, 5}; 10431 const UINT num_faces4 = 4; 10432 const UINT num_vertices4 = 6; 10433 const DWORD exp_face_remap4[] = {3, 2, 1, 0}; 10434 /* Test cases are stored in the tc array */ 10435 struct 10436 { 10437 const VOID *indices; 10438 const UINT num_faces; 10439 const UINT num_vertices; 10440 const BOOL indices_are_32bit; 10441 const DWORD *exp_face_remap; 10442 } 10443 tc[] = 10444 { 10445 { 10446 indices0, 10447 num_faces0, 10448 num_vertices0, 10449 TRUE, 10450 exp_face_remap0 10451 }, 10452 { 10453 indices1, 10454 num_faces1, 10455 num_vertices1, 10456 TRUE, 10457 exp_face_remap1 10458 }, 10459 { 10460 indices2, 10461 num_faces2, 10462 num_vertices2, 10463 TRUE, 10464 exp_face_remap2 10465 }, 10466 { 10467 indices3, 10468 num_faces3, 10469 num_vertices3, 10470 TRUE, 10471 exp_face_remap3 10472 }, 10473 { 10474 indices4, 10475 num_faces4, 10476 num_vertices4, 10477 FALSE, 10478 exp_face_remap4 10479 }, 10480 }; 10481 10482 /* Go through all test cases */ 10483 for (i = 0; i < ARRAY_SIZE(tc); i++) 10484 { 10485 DWORD j; 10486 DWORD *face_remap; 10487 face_remap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 10488 tc[i].num_faces*sizeof(*face_remap)); 10489 10490 hr = D3DXOptimizeFaces(tc[i].indices, tc[i].num_faces, 10491 tc[i].num_vertices, tc[i].indices_are_32bit, 10492 face_remap); 10493 ok(hr == D3D_OK, "D3DXOptimizeFaces test case %d failed. " 10494 "Got %x\n, expected D3D_OK\n", i, hr); 10495 10496 /* Compare face remap with expected face remap */ 10497 for (j = 0; j < tc[i].num_faces; j++) 10498 { 10499 ok(tc[i].exp_face_remap[j] == face_remap[j], 10500 "Test case %d: Got face %d at %d, expected %d\n", i, 10501 face_remap[j], j, tc[i].exp_face_remap[j]); 10502 } 10503 10504 HeapFree(GetProcessHeap(), 0, face_remap); 10505 } 10506 10507 /* face_remap must not be NULL */ 10508 hr = D3DXOptimizeFaces(tc[0].indices, tc[0].num_faces, 10509 tc[0].num_vertices, tc[0].indices_are_32bit, 10510 NULL); 10511 ok(hr == D3DERR_INVALIDCALL, "D3DXOptimizeFaces passed NULL face_remap " 10512 "pointer. Got %x\n, expected D3DERR_INVALIDCALL\n", hr); 10513 10514 /* Number of faces must be smaller than 2^15 */ 10515 hr = D3DXOptimizeFaces(tc[0].indices, 2 << 15, 10516 tc[0].num_vertices, FALSE, 10517 &smallest_face_remap); 10518 ok(hr == D3DERR_INVALIDCALL, "D3DXOptimizeFaces should not accept 2^15 " 10519 "faces when using 16-bit indices. Got %x\n, expected D3DERR_INVALIDCALL\n", hr); 10520 } 10521 10522 static HRESULT clear_normals(ID3DXMesh *mesh) 10523 { 10524 HRESULT hr; 10525 BYTE *vertices; 10526 size_t normal_size; 10527 DWORD i, num_vertices, vertex_stride; 10528 const D3DXVECTOR4 normal = {NAN, NAN, NAN, NAN}; 10529 D3DVERTEXELEMENT9 *normal_declaration = NULL; 10530 D3DVERTEXELEMENT9 declaration[MAX_FVF_DECL_SIZE] = {D3DDECL_END()}; 10531 10532 if (FAILED(hr = mesh->lpVtbl->GetDeclaration(mesh, declaration))) 10533 return hr; 10534 10535 for (i = 0; declaration[i].Stream != 0xff; i++) 10536 { 10537 if (declaration[i].Usage == D3DDECLUSAGE_NORMAL && !declaration[i].UsageIndex) 10538 { 10539 normal_declaration = &declaration[i]; 10540 break; 10541 } 10542 } 10543 10544 if (!normal_declaration) 10545 return D3DERR_INVALIDCALL; 10546 10547 if (normal_declaration->Type == D3DDECLTYPE_FLOAT3) 10548 { 10549 normal_size = sizeof(D3DXVECTOR3); 10550 } 10551 else if (normal_declaration->Type == D3DDECLTYPE_FLOAT4) 10552 { 10553 normal_size = sizeof(D3DXVECTOR4); 10554 } 10555 else 10556 { 10557 trace("Cannot clear normals\n"); 10558 return E_NOTIMPL; 10559 } 10560 10561 num_vertices = mesh->lpVtbl->GetNumVertices(mesh); 10562 vertex_stride = mesh->lpVtbl->GetNumBytesPerVertex(mesh); 10563 10564 if (FAILED(hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, (void **)&vertices))) 10565 return hr; 10566 10567 vertices += normal_declaration->Offset; 10568 10569 for (i = 0; i < num_vertices; i++, vertices += vertex_stride) 10570 memcpy(vertices, &normal, normal_size); 10571 10572 return mesh->lpVtbl->UnlockVertexBuffer(mesh); 10573 } 10574 10575 static void compare_normals(unsigned int line, const char *test_name, 10576 ID3DXMesh *mesh, const D3DXVECTOR3 *normals, unsigned int num_normals) 10577 { 10578 unsigned int i; 10579 BYTE *vertices; 10580 DWORD num_vertices, vertex_stride; 10581 D3DVERTEXELEMENT9 *normal_declaration = NULL; 10582 D3DVERTEXELEMENT9 declaration[MAX_FVF_DECL_SIZE] = {D3DDECL_END()}; 10583 10584 if (FAILED(mesh->lpVtbl->GetDeclaration(mesh, declaration))) 10585 { 10586 ok_(__FILE__, line)(0, "%s: Failed to get declaration\n", test_name); 10587 return; 10588 } 10589 10590 for (i = 0; declaration[i].Stream != 0xff; i++) 10591 { 10592 if (declaration[i].Usage == D3DDECLUSAGE_NORMAL && !declaration[i].UsageIndex) 10593 { 10594 normal_declaration = &declaration[i]; 10595 break; 10596 } 10597 } 10598 10599 if (!normal_declaration) 10600 { 10601 ok_(__FILE__, line)(0, "%s: Mesh has no normals\n", test_name); 10602 return; 10603 } 10604 10605 if (normal_declaration->Type != D3DDECLTYPE_FLOAT3 && normal_declaration->Type != D3DDECLTYPE_FLOAT4) 10606 { 10607 ok_(__FILE__, line)(0, "%s: Mesh has invalid normals type\n", test_name); 10608 return; 10609 } 10610 10611 num_vertices = mesh->lpVtbl->GetNumVertices(mesh); 10612 vertex_stride = mesh->lpVtbl->GetNumBytesPerVertex(mesh); 10613 10614 ok_(__FILE__, line)(num_vertices == num_normals, "%s: Expected %u vertices, got %u\n", test_name, 10615 num_normals, num_vertices); 10616 10617 if (FAILED(mesh->lpVtbl->LockVertexBuffer(mesh, 0, (void **)&vertices))) 10618 { 10619 ok_(__FILE__, line)(0, "%s: Failed to compare normals\n", test_name); 10620 return; 10621 } 10622 10623 vertices += normal_declaration->Offset; 10624 10625 for (i = 0; i < min(num_vertices, num_normals); i++, vertices += vertex_stride) 10626 { 10627 if (normal_declaration->Type == D3DDECLTYPE_FLOAT3) 10628 { 10629 const D3DXVECTOR3 *n = (D3DXVECTOR3 *)vertices; 10630 ok_(__FILE__, line)(compare_vec3(*n, normals[i]), 10631 "%s: normal %2u, expected (%f, %f, %f), got (%f, %f, %f)\n", 10632 test_name, i, normals[i].x, normals[i].y, normals[i].z, n->x, n->y, n->z); 10633 } 10634 else 10635 { 10636 const D3DXVECTOR4 *n = (D3DXVECTOR4 *)vertices; 10637 const D3DXVECTOR4 normal = {normals[i].x, normals[i].y, normals[i].z, 1.0f}; 10638 ok_(__FILE__, line)(compare_vec4(*n, normal), 10639 "%s: normal %2u, expected (%f, %f, %f, %f), got (%f, %f, %f, %f)\n", 10640 test_name, i, normals[i].x, normals[i].y, normals[i].z, 1.0f, 10641 n->x, n->y, n->z, n->w); 10642 } 10643 } 10644 10645 mesh->lpVtbl->UnlockVertexBuffer(mesh); 10646 } 10647 10648 static HRESULT compute_normals_D3DXComputeNormals(ID3DXMesh *mesh, const DWORD *adjacency) 10649 { 10650 return D3DXComputeNormals((ID3DXBaseMesh *)mesh, adjacency); 10651 } 10652 10653 static HRESULT compute_normals_D3DXComputeTangentFrameEx(ID3DXMesh *mesh, const DWORD *adjacency) 10654 { 10655 return D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, 10656 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS, 10657 adjacency, -1.01f, -0.01f, -1.01f, NULL, NULL); 10658 } 10659 10660 static void test_compute_normals(void) 10661 { 10662 HRESULT hr; 10663 ULONG refcount; 10664 ID3DXMesh *mesh, *cloned_mesh; 10665 ID3DXBuffer *adjacency; 10666 IDirect3DDevice9 *device; 10667 struct test_context *test_context; 10668 unsigned int i; 10669 10670 static const struct compute_normals_func 10671 { 10672 const char *name; 10673 HRESULT (*apply)(ID3DXMesh *mesh, const DWORD *adjacency); 10674 } 10675 compute_normals_funcs[] = 10676 { 10677 {"D3DXComputeNormals", compute_normals_D3DXComputeNormals }, 10678 {"D3DXComputeTangentFrameEx", compute_normals_D3DXComputeTangentFrameEx} 10679 }; 10680 10681 static const D3DXVECTOR3 box_normals[24] = 10682 { 10683 {-1.0f, 0.0f, 0.0f}, {-1.0f, 0.0f, 0.0f}, {-1.0f, 0.0f, 0.0f}, {-1.0f, 0.0f, 0.0f}, 10684 { 0.0f, 1.0f, 0.0f}, { 0.0f, 1.0f, 0.0f}, { 0.0f, 1.0f, 0.0f}, { 0.0f, 1.0f, 0.0f}, 10685 { 1.0f, 0.0f, 0.0f}, { 1.0f, 0.0f, 0.0f}, { 1.0f, 0.0f, 0.0f}, { 1.0f, 0.0f, 0.0f}, 10686 { 0.0f,-1.0f, 0.0f}, { 0.0f,-1.0f, 0.0f}, { 0.0f,-1.0f, 0.0f}, { 0.0f,-1.0f, 0.0f}, 10687 { 0.0f, 0.0f, 1.0f}, { 0.0f, 0.0f, 1.0f}, { 0.0f, 0.0f, 1.0f}, { 0.0f, 0.0f, 1.0f}, 10688 { 0.0f, 0.0f,-1.0f}, { 0.0f, 0.0f,-1.0f}, { 0.0f, 0.0f,-1.0f}, { 0.0f, 0.0f,-1.0f} 10689 }; 10690 const float box_normal_component = 1.0f / sqrtf(3.0f); 10691 const D3DXVECTOR3 box_normals_adjacency[24] = 10692 { 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 {-box_normal_component, box_normal_component, -box_normal_component}, 10715 { box_normal_component, box_normal_component, -box_normal_component}, 10716 { box_normal_component, -box_normal_component, -box_normal_component} 10717 }; 10718 static const D3DXVECTOR3 box_normals_adjacency_area[24] = 10719 { 10720 {-0.666667f, -0.333333f, -0.666667f}, {-0.333333f, -0.666667f, 0.666667f}, 10721 {-0.816496f, 0.408248f, 0.408248f}, {-0.408248f, 0.816496f, -0.408248f}, 10722 {-0.408248f, 0.816496f, -0.408248f}, {-0.816496f, 0.408248f, 0.408248f}, 10723 { 0.333333f, 0.666667f, 0.666667f}, { 0.666667f, 0.333333f, -0.666667f}, 10724 { 0.666667f, 0.333333f, -0.666667f}, { 0.333333f, 0.666667f, 0.666667f}, 10725 { 0.816496f, -0.408248f, 0.408248f}, { 0.408248f, -0.816496f, -0.408248f}, 10726 {-0.333333f, -0.666667f, 0.666667f}, {-0.666667f, -0.333333f, -0.666667f}, 10727 { 0.408248f, -0.816496f, -0.408248f}, { 0.816496f, -0.408248f, 0.408248f}, 10728 {-0.333333f, -0.666667f, 0.666667f}, { 0.816497f, -0.408248f, 0.408248f}, 10729 { 0.333333f, 0.666667f, 0.666667f}, {-0.816497f, 0.408248f, 0.408248f}, 10730 {-0.666667f, -0.333333f, -0.666667f}, {-0.408248f, 0.816497f, -0.408248f}, 10731 { 0.666667f, 0.333333f, -0.666667f}, { 0.408248f, -0.816496f, -0.408248f} 10732 }; 10733 static const D3DXVECTOR3 box_normals_position1f[24] = {{0}}; 10734 static const D3DXVECTOR3 box_normals_position2f[24] = 10735 { 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 {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f}, 10742 {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}, 10743 {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, -1.0f} 10744 }; 10745 10746 static const D3DXVECTOR3 sphere_normals[22] = 10747 { 10748 { 0.000000f, -0.000000f, 1.000000f}, { 0.000000f, 0.582244f, 0.813014f}, 10749 { 0.582244f, -0.000000f, 0.813014f}, {-0.000000f, -0.582244f, 0.813014f}, 10750 {-0.582244f, 0.000000f, 0.813014f}, {-0.000000f, 0.890608f, 0.454772f}, 10751 { 0.890608f, 0.000000f, 0.454772f}, { 0.000000f, -0.890608f, 0.454772f}, 10752 {-0.890608f, -0.000000f, 0.454772f}, { 0.000000f, 1.000000f, -0.000000f}, 10753 { 1.000000f, -0.000000f, -0.000000f}, {-0.000000f, -1.000000f, -0.000000f}, 10754 {-1.000000f, 0.000000f, -0.000000f}, { 0.000000f, 0.890608f, -0.454773f}, 10755 { 0.890608f, -0.000000f, -0.454772f}, {-0.000000f, -0.890608f, -0.454773f}, 10756 {-0.890608f, 0.000000f, -0.454773f}, { 0.000000f, 0.582244f, -0.813015f}, 10757 { 0.582244f, -0.000000f, -0.813015f}, { 0.000000f, -0.582244f, -0.813015f}, 10758 {-0.582243f, 0.000000f, -0.813015f}, { 0.000000f, 0.000000f, -1.000000f} 10759 }; 10760 static const D3DXVECTOR3 sphere_normals_area[22] = 10761 { 10762 { 0.000000f, -0.000000f, 1.000000f}, {-0.215311f, 0.554931f, 0.803550f}, 10763 { 0.554931f, 0.215311f, 0.803550f}, { 0.215311f, -0.554931f, 0.803550f}, 10764 {-0.554931f, -0.215311f, 0.803550f}, {-0.126638f, 0.872121f, 0.472618f}, 10765 { 0.872121f, 0.126638f, 0.472618f}, { 0.126638f, -0.872121f, 0.472618f}, 10766 {-0.872121f, -0.126637f, 0.472618f}, { 0.000000f, 1.000000f, -0.000000f}, 10767 { 1.000000f, -0.000000f, -0.000000f}, {-0.000000f, -1.000000f, -0.000000f}, 10768 {-1.000000f, 0.000000f, -0.000000f}, { 0.126638f, 0.872121f, -0.472618f}, 10769 { 0.872121f, -0.126638f, -0.472618f}, {-0.126638f, -0.872121f, -0.472618f}, 10770 {-0.872121f, 0.126638f, -0.472618f}, { 0.215311f, 0.554931f, -0.803550f}, 10771 { 0.554931f, -0.215311f, -0.803550f}, {-0.215311f, -0.554931f, -0.803550f}, 10772 {-0.554931f, 0.215311f, -0.803550f}, { 0.000000f, 0.000000f, -1.000000f} 10773 }; 10774 static const D3DXVECTOR3 sphere_normals_equal[22] = 10775 { 10776 { 0.000000f, -0.000000f, 1.000000f}, {-0.134974f, 0.522078f, 0.842150f}, 10777 { 0.522078f, 0.134974f, 0.842150f}, { 0.134974f, -0.522078f, 0.842150f}, 10778 {-0.522078f, -0.134974f, 0.842150f}, {-0.026367f, 0.857121f, 0.514440f}, 10779 { 0.857121f, 0.026367f, 0.514440f}, { 0.026367f, -0.857121f, 0.514440f}, 10780 {-0.857121f, -0.026367f, 0.514440f}, { 0.000000f, 1.000000f, -0.000000f}, 10781 { 1.000000f, -0.000000f, -0.000000f}, {-0.000000f, -1.000000f, -0.000000f}, 10782 {-1.000000f, 0.000000f, -0.000000f}, { 0.026367f, 0.857121f, -0.514440f}, 10783 { 0.857121f, -0.026367f, -0.514440f}, {-0.026367f, -0.857121f, -0.514440f}, 10784 {-0.857121f, 0.026367f, -0.514440f}, { 0.134975f, 0.522078f, -0.842150f}, 10785 { 0.522078f, -0.134975f, -0.842150f}, {-0.134974f, -0.522078f, -0.842150f}, 10786 {-0.522078f, 0.134974f, -0.842150f}, { 0.000000f, 0.000000f, -1.000000f} 10787 }; 10788 10789 static const D3DVERTEXELEMENT9 position3f_normal1f_declaration[] = 10790 { 10791 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 10792 {0, sizeof(D3DXVECTOR3), D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 10793 D3DDECL_END() 10794 }; 10795 static const D3DVERTEXELEMENT9 position3f_normal2f_declaration[] = 10796 { 10797 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 10798 {0, sizeof(D3DXVECTOR3), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 10799 D3DDECL_END() 10800 }; 10801 static const D3DVERTEXELEMENT9 normal4f_position3f_declaration[] = 10802 { 10803 {0, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 10804 {0, sizeof(D3DXVECTOR4), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 10805 D3DDECL_END() 10806 }; 10807 static const D3DVERTEXELEMENT9 position1f_normal3f_declaration[] = 10808 { 10809 {0, 0, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 10810 {0, sizeof(float), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 10811 D3DDECL_END() 10812 }; 10813 static const D3DVERTEXELEMENT9 position2f_normal3f_declaration[] = 10814 { 10815 {0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 10816 {0, sizeof(D3DXVECTOR2), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 10817 D3DDECL_END() 10818 }; 10819 static const D3DVERTEXELEMENT9 position4f_normal3f_declaration[] = 10820 { 10821 {0, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 10822 {0, sizeof(D3DXVECTOR4), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, 10823 D3DDECL_END() 10824 }; 10825 10826 for (i = 0; i < ARRAY_SIZE(compute_normals_funcs); i++) 10827 { 10828 hr = compute_normals_funcs[i].apply(NULL, NULL); 10829 ok(hr == D3DERR_INVALIDCALL, "%s returned %#x, expected D3DERR_INVALIDCALL\n", compute_normals_funcs[i].name, hr); 10830 } 10831 10832 if (!(test_context = new_test_context())) 10833 { 10834 skip("Couldn't create test context\n"); 10835 return; 10836 } 10837 device = test_context->device; 10838 10839 hr = D3DXCreateBox(device, 1.0f, 1.0f, 1.0f, &mesh, &adjacency); 10840 ok(SUCCEEDED(hr), "D3DXCreateBox failed %#x\n", hr); 10841 10842 /* Check wrong input */ 10843 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, 10844 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE, NULL, -1.01f, -0.01f, -1.01f, NULL, NULL); 10845 todo_wine ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr); 10846 10847 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DDECLUSAGE_NORMAL, 0, 10848 D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_BY_AREA | D3DXTANGENT_WEIGHT_EQUAL, 10849 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL); 10850 ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr); 10851 10852 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, 10853 D3DDECLUSAGE_NORMAL, 0, 0, NULL, -1.01f, -0.01f, -1.01f, NULL, NULL); 10854 todo_wine ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr); 10855 10856 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, 10857 D3DDECLUSAGE_NORMAL, 1, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS, 10858 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL); 10859 ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr); 10860 10861 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, 10862 D3DX_DEFAULT, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS, 10863 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL); 10864 ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr); 10865 10866 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, 10867 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_CALCULATE_NORMALS, 10868 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL); 10869 todo_wine ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr); 10870 10871 for (i = 0; i < ARRAY_SIZE(compute_normals_funcs); i++) 10872 { 10873 const struct compute_normals_func *func = &compute_normals_funcs[i]; 10874 10875 /* Mesh without normals */ 10876 hr = mesh->lpVtbl->CloneMeshFVF(mesh, 0, D3DFVF_XYZ, device, &cloned_mesh); 10877 ok(SUCCEEDED(hr), "CloneMeshFVF failed %#x\n", hr); 10878 10879 hr = func->apply(cloned_mesh, NULL); 10880 ok(hr == D3DERR_INVALIDCALL, "%s returned %#x, expected D3DERR_INVALIDCALL\n", func->name, hr); 10881 10882 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh); 10883 ok(!refcount, "Mesh has %u references left\n", refcount); 10884 10885 /* Mesh without positions */ 10886 hr = mesh->lpVtbl->CloneMeshFVF(mesh, 0, D3DFVF_NORMAL, device, &cloned_mesh); 10887 ok(SUCCEEDED(hr), "CloneMeshFVF failed %#x\n", hr); 10888 10889 hr = func->apply(cloned_mesh, NULL); 10890 ok(hr == D3DERR_INVALIDCALL, "%s returned %#x, expected D3DERR_INVALIDCALL\n", func->name, hr); 10891 10892 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh); 10893 ok(!refcount, "Mesh has %u references left\n", refcount); 10894 10895 /* Mesh with D3DDECLTYPE_FLOAT1 normals */ 10896 hr = mesh->lpVtbl->CloneMesh(mesh, 0, position3f_normal1f_declaration, device, &cloned_mesh); 10897 ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr); 10898 10899 hr = func->apply(cloned_mesh, NULL); 10900 ok(hr == D3DERR_INVALIDCALL, "%s returned %#x, expected D3DERR_INVALIDCALL\n", func->name, hr); 10901 10902 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh); 10903 ok(!refcount, "Mesh has %u references left\n", refcount); 10904 10905 /* Mesh with D3DDECLTYPE_FLOAT2 normals */ 10906 hr = mesh->lpVtbl->CloneMesh(mesh, 0, position3f_normal2f_declaration, device, &cloned_mesh); 10907 ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr); 10908 10909 hr = func->apply(cloned_mesh, NULL); 10910 ok(hr == D3DERR_INVALIDCALL, "%s returned %#x, expected D3DERR_INVALIDCALL\n", func->name, hr); 10911 10912 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh); 10913 ok(!refcount, "Mesh has %u references left\n", refcount); 10914 10915 /* Mesh without adjacency data */ 10916 hr = clear_normals(mesh); 10917 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr); 10918 10919 hr = func->apply(mesh, NULL); 10920 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr); 10921 10922 compare_normals(__LINE__, func->name, mesh, box_normals, ARRAY_SIZE(box_normals)); 10923 10924 /* Mesh with adjacency data */ 10925 hr = clear_normals(mesh); 10926 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr); 10927 10928 hr = func->apply(mesh, ID3DXBuffer_GetBufferPointer(adjacency)); 10929 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr); 10930 10931 compare_normals(__LINE__, func->name, mesh, box_normals_adjacency, ARRAY_SIZE(box_normals_adjacency)); 10932 10933 /* Mesh with custom vertex format, D3DDECLTYPE_FLOAT4 normals and adjacency */ 10934 hr = mesh->lpVtbl->CloneMesh(mesh, 0, normal4f_position3f_declaration, device, &cloned_mesh); 10935 ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr); 10936 10937 hr = clear_normals(cloned_mesh); 10938 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr); 10939 10940 hr = func->apply(cloned_mesh, ID3DXBuffer_GetBufferPointer(adjacency)); 10941 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr); 10942 10943 compare_normals(__LINE__, func->name, cloned_mesh, box_normals_adjacency, ARRAY_SIZE(box_normals_adjacency)); 10944 10945 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh); 10946 ok(!refcount, "Mesh has %u references left\n", refcount); 10947 10948 /* Mesh with D3DDECLTYPE_FLOAT1 positions and D3DDECLTYPE_FLOAT3 normals */ 10949 hr = mesh->lpVtbl->CloneMesh(mesh, 0, position1f_normal3f_declaration, device, &cloned_mesh); 10950 ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr); 10951 10952 hr = clear_normals(cloned_mesh); 10953 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr); 10954 10955 hr = func->apply(cloned_mesh, ID3DXBuffer_GetBufferPointer(adjacency)); 10956 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr); 10957 10958 compare_normals(__LINE__, func->name, cloned_mesh, box_normals_position1f, ARRAY_SIZE(box_normals_position1f)); 10959 10960 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh); 10961 ok(!refcount, "Mesh has %u references left\n", refcount); 10962 10963 /* Mesh with D3DDECLTYPE_FLOAT2 positions and D3DDECLTYPE_FLOAT3 normals */ 10964 hr = mesh->lpVtbl->CloneMesh(mesh, 0, position2f_normal3f_declaration, device, &cloned_mesh); 10965 ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr); 10966 10967 hr = clear_normals(cloned_mesh); 10968 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr); 10969 10970 hr = func->apply(cloned_mesh, ID3DXBuffer_GetBufferPointer(adjacency)); 10971 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr); 10972 10973 compare_normals(__LINE__, func->name, cloned_mesh, box_normals_position2f, ARRAY_SIZE(box_normals_position2f)); 10974 10975 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh); 10976 ok(!refcount, "Mesh has %u references left\n", refcount); 10977 10978 /* Mesh with D3DDECLTYPE_FLOAT4 positions and D3DDECLTYPE_FLOAT3 normals */ 10979 hr = mesh->lpVtbl->CloneMesh(mesh, 0, position4f_normal3f_declaration, device, &cloned_mesh); 10980 ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr); 10981 10982 hr = clear_normals(cloned_mesh); 10983 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr); 10984 10985 hr = func->apply(cloned_mesh, ID3DXBuffer_GetBufferPointer(adjacency)); 10986 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr); 10987 10988 compare_normals(__LINE__, func->name, cloned_mesh, box_normals_adjacency, ARRAY_SIZE(box_normals_adjacency)); 10989 10990 refcount = cloned_mesh->lpVtbl->Release(cloned_mesh); 10991 ok(!refcount, "Mesh has %u references left\n", refcount); 10992 } 10993 10994 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, 10995 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_BY_AREA, 10996 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL); 10997 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr); 10998 10999 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, box_normals, ARRAY_SIZE(box_normals)); 11000 11001 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, 11002 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_BY_AREA, 11003 ID3DXBuffer_GetBufferPointer(adjacency), -1.01f, -0.01f, -1.01f, NULL, NULL); 11004 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr); 11005 11006 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, box_normals_adjacency_area, ARRAY_SIZE(box_normals_adjacency_area)); 11007 11008 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, 11009 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_EQUAL, 11010 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL); 11011 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr); 11012 11013 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, box_normals, ARRAY_SIZE(box_normals)); 11014 11015 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, 11016 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_EQUAL, 11017 ID3DXBuffer_GetBufferPointer(adjacency), -1.01f, -0.01f, -1.01f, NULL, NULL); 11018 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr); 11019 11020 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, box_normals_adjacency_area, ARRAY_SIZE(box_normals_adjacency_area)); 11021 11022 refcount = mesh->lpVtbl->Release(mesh); 11023 ok(!refcount, "Mesh has %u references left\n", refcount); 11024 refcount = ID3DXBuffer_Release(adjacency); 11025 ok(!refcount, "Buffer has %u references left\n", refcount); 11026 11027 hr = D3DXCreateSphere(device, 1.0f, 4, 6, &mesh, &adjacency); 11028 ok(SUCCEEDED(hr), "D3DXCreateSphere failed %#x\n", hr); 11029 11030 for (i = 0; i < ARRAY_SIZE(compute_normals_funcs); i++) 11031 { 11032 const struct compute_normals_func *func = &compute_normals_funcs[i]; 11033 11034 /* Sphere without adjacency data */ 11035 hr = clear_normals(mesh); 11036 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr); 11037 11038 hr = func->apply(mesh, NULL); 11039 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr); 11040 11041 compare_normals(__LINE__, func->name, mesh, sphere_normals, ARRAY_SIZE(sphere_normals)); 11042 11043 /* Sphere with adjacency data */ 11044 hr = clear_normals(mesh); 11045 ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr); 11046 11047 hr = func->apply(mesh, ID3DXBuffer_GetBufferPointer(adjacency)); 11048 ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr); 11049 11050 compare_normals(__LINE__, func->name, mesh, sphere_normals, ARRAY_SIZE(sphere_normals)); 11051 } 11052 11053 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, 11054 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_BY_AREA, 11055 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL); 11056 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr); 11057 11058 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, sphere_normals_area, ARRAY_SIZE(sphere_normals_area)); 11059 11060 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, 11061 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_BY_AREA, 11062 ID3DXBuffer_GetBufferPointer(adjacency), -1.01f, -0.01f, -1.01f, NULL, NULL); 11063 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr); 11064 11065 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, sphere_normals_area, ARRAY_SIZE(sphere_normals_area)); 11066 11067 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, 11068 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_EQUAL, 11069 NULL, -1.01f, -0.01f, -1.01f, NULL, NULL); 11070 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr); 11071 11072 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, sphere_normals_equal, ARRAY_SIZE(sphere_normals_equal)); 11073 11074 hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, 11075 D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_EQUAL, 11076 ID3DXBuffer_GetBufferPointer(adjacency), -1.01f, -0.01f, -1.01f, NULL, NULL); 11077 ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr); 11078 11079 compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, sphere_normals_equal, ARRAY_SIZE(sphere_normals_equal)); 11080 11081 refcount = mesh->lpVtbl->Release(mesh); 11082 ok(!refcount, "Mesh has %u references left\n", refcount); 11083 refcount = ID3DXBuffer_Release(adjacency); 11084 ok(!refcount, "Buffer has %u references left\n", refcount); 11085 11086 free_test_context(test_context); 11087 } 11088 11089 static void D3DXCreateAnimationControllerTest(void) 11090 { 11091 HRESULT hr; 11092 ID3DXAnimationController *animation; 11093 UINT value; 11094 11095 hr = D3DXCreateAnimationController(0, 0, 0, 0, NULL); 11096 ok(hr == D3D_OK, "Got unexpected hr returned %#x.\n", hr); 11097 11098 animation = (void*)0xdeadbeef; 11099 hr = D3DXCreateAnimationController(0, 1, 1, 1, &animation); 11100 ok(hr == D3D_OK, "Got unexpected hr returned %#x.\n", hr); 11101 ok(animation == (void*)0xdeadbeef, "Got unexpected animation %p.\n", animation); 11102 11103 animation = (void*)0xdeadbeef; 11104 hr = D3DXCreateAnimationController(1, 0, 1, 1, &animation); 11105 ok(hr == D3D_OK, "Got unexpected hr returned %#x.\n", hr); 11106 ok(animation == (void*)0xdeadbeef, "Got unexpected animation %p.\n", animation); 11107 11108 animation = (void*)0xdeadbeef; 11109 hr = D3DXCreateAnimationController(1, 1, 0, 1, &animation); 11110 ok(hr == D3D_OK, "Got unexpected hr returned %#x.\n", hr); 11111 ok(animation == (void*)0xdeadbeef, "Got unexpected animation %p.\n", animation); 11112 11113 animation = (void*)0xdeadbeef; 11114 hr = D3DXCreateAnimationController(1, 1, 1, 0, &animation); 11115 ok(hr == D3D_OK, "Got unexpected hr returned %#x.\n", hr); 11116 ok(animation == (void*)0xdeadbeef, "Got unexpected animation %p.\n", animation); 11117 11118 hr = D3DXCreateAnimationController(1, 1, 1, 1, &animation); 11119 ok(hr == D3D_OK, "Got unexpected hr returned %#x.\n", hr); 11120 11121 value = animation->lpVtbl->GetMaxNumAnimationOutputs(animation); 11122 ok(value == 1, "Got unexpected value %u.\n", value); 11123 11124 value = animation->lpVtbl->GetMaxNumAnimationSets(animation); 11125 ok(value == 1, "Got unexpected value %u.\n", value); 11126 11127 value = animation->lpVtbl->GetMaxNumTracks(animation); 11128 ok(value == 1, "Got unexpected value %u.\n", value); 11129 11130 value = animation->lpVtbl->GetMaxNumEvents(animation); 11131 ok(value == 1, "Got unexpected value %u.\n", value); 11132 11133 animation->lpVtbl->Release(animation); 11134 11135 hr = D3DXCreateAnimationController(100, 101, 102, 103, &animation); 11136 ok(hr == D3D_OK, "Got unexpected hr returned %#x.\n", hr); 11137 11138 value = animation->lpVtbl->GetMaxNumAnimationOutputs(animation); 11139 ok(value == 100, "Got unexpected value %u.\n", value); 11140 11141 value = animation->lpVtbl->GetMaxNumAnimationSets(animation); 11142 ok(value == 101, "Got unexpected value %u.\n", value); 11143 11144 value = animation->lpVtbl->GetMaxNumTracks(animation); 11145 ok(value == 102, "Got unexpected value %u.\n", value); 11146 11147 value = animation->lpVtbl->GetMaxNumEvents(animation); 11148 ok(value == 103, "Got unexpected value %u.\n", value); 11149 11150 animation->lpVtbl->Release(animation); 11151 } 11152 11153 static void test_D3DXFrameFind(void) 11154 { 11155 static char n1[] = "name1"; 11156 static char n2[] = "name2"; 11157 static char n3[] = "name3"; 11158 static char n4[] = "name4"; 11159 static char n5[] = "name5"; 11160 static char n6[] = "name6"; 11161 static char N1[] = "Name1"; 11162 D3DXFRAME root, sibling, sibling2, child, *ret; 11163 D3DXFRAME child2, child3; 11164 11165 ret = D3DXFrameFind(NULL, NULL); 11166 ok(ret == NULL, "Unexpected frame, %p.\n", ret); 11167 11168 ret = D3DXFrameFind(NULL, "test"); 11169 ok(ret == NULL, "Unexpected frame, %p.\n", ret); 11170 11171 memset(&root, 0, sizeof(root)); 11172 11173 ret = D3DXFrameFind(&root, NULL); 11174 ok(ret == &root, "Unexpected frame, %p.\n", ret); 11175 11176 root.Name = n1; 11177 ret = D3DXFrameFind(&root, NULL); 11178 ok(ret == NULL, "Unexpected frame, %p.\n", ret); 11179 11180 ret = D3DXFrameFind(&root, n1); 11181 ok(ret == &root, "Unexpected frame, %p.\n", ret); 11182 11183 ret = D3DXFrameFind(&root, N1); 11184 ok(ret == NULL, "Unexpected frame, %p.\n", ret); 11185 11186 /* Test siblings order traversal. */ 11187 memset(&sibling, 0, sizeof(sibling)); 11188 sibling.Name = n2; 11189 root.pFrameSibling = &sibling; 11190 ret = D3DXFrameFind(&root, n2); 11191 ok(ret == &sibling, "Unexpected frame, %p.\n", ret); 11192 11193 memset(&sibling2, 0, sizeof(sibling2)); 11194 sibling2.Name = n2; 11195 sibling.pFrameSibling = &sibling2; 11196 ret = D3DXFrameFind(&root, n2); 11197 ok(ret == &sibling, "Unexpected frame, %p.\n", ret); 11198 11199 sibling2.Name = n3; 11200 ret = D3DXFrameFind(&root, n3); 11201 ok(ret == &sibling2, "Unexpected frame, %p.\n", ret); 11202 11203 /* Siblings first. */ 11204 memset(&child, 0, sizeof(child)); 11205 child.Name = n2; 11206 root.pFrameFirstChild = &child; 11207 ret = D3DXFrameFind(&root, n2); 11208 ok(ret == &sibling, "Unexpected frame, %p.\n", ret); 11209 11210 child.Name = n4; 11211 ret = D3DXFrameFind(&root, n4); 11212 ok(ret == &child, "Unexpected frame, %p.\n", ret); 11213 11214 /* Link a grandchild and another one for sibling. */ 11215 memset(&child2, 0, sizeof(child2)); 11216 memset(&child3, 0, sizeof(child3)); 11217 child2.Name = child3.Name = n5; 11218 sibling.pFrameFirstChild = &child2; 11219 child.pFrameFirstChild = &child3; 11220 ret = D3DXFrameFind(&root, n5); 11221 ok(ret == &child2, "Unexpected frame, %p.\n", ret); 11222 11223 child3.Name = n6; 11224 ret = D3DXFrameFind(&root, n6); 11225 ok(ret == &child3, "Unexpected frame, %p.\n", ret); 11226 } 11227 11228 static ID3DXFileData *get_mesh_data(const void *memory, SIZE_T length) 11229 { 11230 ID3DXFileData *file_data, *ret = NULL; 11231 ID3DXFileEnumObject *enum_obj = NULL; 11232 D3DXF_FILELOADMEMORY source; 11233 ID3DXFile *file; 11234 SIZE_T i, count; 11235 GUID guid; 11236 11237 if (FAILED(D3DXFileCreate(&file))) 11238 return NULL; 11239 11240 if (FAILED(file->lpVtbl->RegisterTemplates(file, D3DRM_XTEMPLATES, D3DRM_XTEMPLATE_BYTES))) 11241 goto cleanup; 11242 11243 source.lpMemory = memory; 11244 source.dSize = length; 11245 if (FAILED(file->lpVtbl->CreateEnumObject(file, &source, D3DXF_FILELOAD_FROMMEMORY, &enum_obj))) 11246 goto cleanup; 11247 11248 if (FAILED(enum_obj->lpVtbl->GetChildren(enum_obj, &count))) 11249 goto cleanup; 11250 11251 for (i = 0; i < count; ++i) 11252 { 11253 if (FAILED(enum_obj->lpVtbl->GetChild(enum_obj, i, &file_data))) 11254 goto cleanup; 11255 11256 if (SUCCEEDED(file_data->lpVtbl->GetType(file_data, &guid)) 11257 && IsEqualGUID(&guid, &TID_D3DRMMesh)) 11258 { 11259 ret = file_data; 11260 break; 11261 } 11262 else 11263 { 11264 file_data->lpVtbl->Release(file_data); 11265 } 11266 } 11267 11268 cleanup: 11269 if (enum_obj) 11270 enum_obj->lpVtbl->Release(enum_obj); 11271 file->lpVtbl->Release(file); 11272 11273 return ret; 11274 } 11275 11276 static void test_load_skin_mesh_from_xof(void) 11277 { 11278 static const char simple_xfile[] = 11279 "xof 0303txt 0032" 11280 "Mesh {" 11281 "3;" 11282 "0.0; 0.0; 0.0;," 11283 "0.0; 1.0; 0.0;," 11284 "1.0; 1.0; 0.0;;" 11285 "1;" 11286 "3; 0, 1, 2;;" 11287 "}"; 11288 static const D3DVERTEXELEMENT9 expected_declaration[] = 11289 { 11290 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, 11291 D3DDECL_END(), 11292 }; 11293 D3DVERTEXELEMENT9 declaration[MAX_FVF_DECL_SIZE]; 11294 ID3DXBuffer *adjacency, *materials, *effects; 11295 DWORD max_influences[3], count, fvf; 11296 D3DPRESENT_PARAMETERS d3dpp; 11297 IDirect3DDevice9 *device; 11298 ID3DXSkinInfo *skin_info; 11299 ID3DXFileData *file_data; 11300 const char *bone_name; 11301 D3DXMATRIX *matrix; 11302 float influence; 11303 ID3DXMesh *mesh; 11304 IDirect3D9 *d3d; 11305 ULONG refcount; 11306 HRESULT hr; 11307 HWND hwnd; 11308 11309 if (!(hwnd = CreateWindowA("static", "d3dx9_test", WS_OVERLAPPEDWINDOW, 0, 0, 11310 640, 480, NULL, NULL, NULL, NULL))) 11311 { 11312 skip("Failed to create application window.\n"); 11313 return; 11314 } 11315 11316 d3d = Direct3DCreate9(D3D_SDK_VERSION); 11317 if (!d3d) 11318 { 11319 skip("Failed to create d3d object.\n"); 11320 DestroyWindow(hwnd); 11321 return; 11322 } 11323 11324 memset(&d3dpp, 0, sizeof(d3dpp)); 11325 d3dpp.Windowed = TRUE; 11326 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; 11327 11328 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd, 11329 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device); 11330 IDirect3D9_Release(d3d); 11331 if (FAILED(hr)) 11332 { 11333 skip("Failed to create device, hr %#x.\n", hr); 11334 DestroyWindow(hwnd); 11335 return; 11336 } 11337 11338 file_data = get_mesh_data(simple_xfile, sizeof(simple_xfile) - 1); 11339 ok(!!file_data, "Failed to load mesh data.\n"); 11340 11341 adjacency = materials = effects = (void *)0xdeadbeef; 11342 count = ~0u; 11343 skin_info = (void *)0xdeadbeef; 11344 mesh = (void *)0xdeadbeef; 11345 11346 hr = D3DXLoadSkinMeshFromXof(file_data, 0, device, &adjacency, &materials, &effects, &count, 11347 &skin_info, &mesh); 11348 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); 11349 ok(!!adjacency, "Got unexpected value %p.\n", adjacency); 11350 ok(!materials, "Got unexpected value %p.\n", materials); 11351 ok(!effects, "Got unexpected value %p.\n", effects); 11352 ok(!count, "Got unexpected value %u.\n", count); 11353 ok(!!skin_info, "Got unexpected value %p.\n", skin_info); 11354 ok(!!mesh, "Got unexpected value %p.\n", mesh); 11355 count = mesh->lpVtbl->GetNumVertices(mesh); 11356 ok(count == 3, "Got unexpected value %u.\n", count); 11357 count = mesh->lpVtbl->GetNumFaces(mesh); 11358 ok(count == 1, "Got unexpected value %u.\n", count); 11359 11360 hr = skin_info->lpVtbl->GetDeclaration(skin_info, declaration); 11361 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); 11362 compare_elements(declaration, expected_declaration, __LINE__, 0); 11363 11364 fvf = skin_info->lpVtbl->GetFVF(skin_info); 11365 ok(fvf == D3DFVF_XYZ, "Got unexpected value %u.\n", fvf); 11366 11367 count = skin_info->lpVtbl->GetNumBones(skin_info); 11368 ok(!count, "Got unexpected value %u.\n", count); 11369 11370 influence = skin_info->lpVtbl->GetMinBoneInfluence(skin_info); 11371 ok(!influence, "Got unexpected value %.8e.\n", influence); 11372 11373 memset(max_influences, 0x55, sizeof(max_influences)); 11374 hr = skin_info->lpVtbl->GetMaxVertexInfluences(skin_info, max_influences); 11375 todo_wine ok(hr == D3D_OK, "Got unexpected value %#x.\n", hr); 11376 todo_wine ok(!max_influences[0], "Got unexpected value %u.\n", max_influences[0]); 11377 ok(max_influences[1] == 0x55555555, "Got unexpected value %u.\n", max_influences[1]); 11378 ok(max_influences[2] == 0x55555555, "Got unexpected value %u.\n", max_influences[2]); 11379 11380 bone_name = skin_info->lpVtbl->GetBoneName(skin_info, 0); 11381 ok(!bone_name, "Got unexpected value %p.\n", bone_name); 11382 11383 count = skin_info->lpVtbl->GetNumBoneInfluences(skin_info, 0); 11384 ok(!count, "Got unexpected value %u.\n", count); 11385 11386 count = skin_info->lpVtbl->GetNumBoneInfluences(skin_info, 1); 11387 ok(!count, "Got unexpected value %u.\n", count); 11388 11389 matrix = skin_info->lpVtbl->GetBoneOffsetMatrix(skin_info, -1); 11390 ok(!matrix, "Got unexpected value %p.\n", matrix); 11391 11392 matrix = skin_info->lpVtbl->GetBoneOffsetMatrix(skin_info, 0); 11393 ok(!matrix, "Got unexpected value %p.\n", matrix); 11394 11395 skin_info->lpVtbl->Release(skin_info); 11396 mesh->lpVtbl->Release(mesh); 11397 adjacency->lpVtbl->Release(adjacency); 11398 file_data->lpVtbl->Release(file_data); 11399 refcount = IDirect3DDevice9_Release(device); 11400 ok(!refcount, "Device has %u references left.\n", refcount); 11401 DestroyWindow(hwnd); 11402 } 11403 11404 START_TEST(mesh) 11405 { 11406 D3DXBoundProbeTest(); 11407 D3DXComputeBoundingBoxTest(); 11408 D3DXComputeBoundingSphereTest(); 11409 D3DXGetFVFVertexSizeTest(); 11410 D3DXIntersectTriTest(); 11411 D3DXCreateMeshTest(); 11412 D3DXCreateMeshFVFTest(); 11413 D3DXLoadMeshTest(); 11414 D3DXCreateBoxTest(); 11415 D3DXCreatePolygonTest(); 11416 D3DXCreateSphereTest(); 11417 D3DXCreateCylinderTest(); 11418 D3DXCreateTextTest(); 11419 D3DXCreateTorusTest(); 11420 D3DXCreateAnimationControllerTest(); 11421 test_get_decl_length(); 11422 test_get_decl_vertex_size(); 11423 test_fvf_decl_conversion(); 11424 D3DXGenerateAdjacencyTest(); 11425 test_update_semantics(); 11426 test_create_skin_info(); 11427 test_convert_adjacency_to_point_reps(); 11428 test_convert_point_reps_to_adjacency(); 11429 test_weld_vertices(); 11430 test_clone_mesh(); 11431 test_valid_mesh(); 11432 test_optimize_faces(); 11433 test_compute_normals(); 11434 test_D3DXFrameFind(); 11435 test_load_skin_mesh_from_xof(); 11436 } 11437