2 * Copyright 2008 David Adam
3 * Copyright 2008 Luis Busquets
4 * Copyright 2009 Henri Verbeet for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #include "wine/test.h"
27 /* Set the WINETEST_DEBUG environment variable to be greater than 1 for verbose
28 * function call traces of ID3DXAllocateHierarchy callbacks. */
29 #define TRACECALLBACK if(winetest_debug > 1) trace
31 #define admitted_error 0.0001f
33 #define ARRAY_SIZE(array) (sizeof(array)/sizeof(*array))
35 #define compare_vertex_sizes(type, exp) \
36 got=D3DXGetFVFVertexSize(type); \
37 ok(got==exp, "Expected: %d, Got: %d\n", exp, got);
39 #define compare_float(got, exp) \
43 ok(_got == _exp, "Expected: %g, Got: %g\n", _exp, _got); \
46 static BOOL
compare(FLOAT u
, FLOAT v
)
48 return (fabs(u
-v
) < admitted_error
);
51 static BOOL
compare_vec3(D3DXVECTOR3 u
, D3DXVECTOR3 v
)
53 return ( compare(u
.x
, v
.x
) && compare(u
.y
, v
.y
) && compare(u
.z
, v
.z
) );
56 #define check_floats(got, exp, dim) check_floats_(__LINE__, "", got, exp, dim)
57 static void check_floats_(int line
, const char *prefix
, const float *got
, const float *exp
, int dim
)
60 char exp_buffer
[256] = "";
61 char got_buffer
[256] = "";
62 char *exp_buffer_ptr
= exp_buffer
;
63 char *got_buffer_ptr
= got_buffer
;
66 for (i
= 0; i
< dim
; i
++) {
68 exp_buffer_ptr
+= sprintf(exp_buffer_ptr
, ", ");
69 got_buffer_ptr
+= sprintf(got_buffer_ptr
, ", ");
71 equal
= equal
&& compare(*exp
, *got
);
72 exp_buffer_ptr
+= sprintf(exp_buffer_ptr
, "%g", *exp
);
73 got_buffer_ptr
+= sprintf(got_buffer_ptr
, "%g", *got
);
76 ok_(__FILE__
,line
)(equal
, "%sExpected (%s), got (%s)", prefix
, exp_buffer
, got_buffer
);
87 static BOOL
compare_face(face a
, face b
)
89 return (a
[0]==b
[0] && a
[1] == b
[1] && a
[2] == b
[2]);
94 DWORD number_of_vertices
;
95 struct vertex
*vertices
;
97 DWORD number_of_faces
;
104 static void free_mesh(struct mesh
*mesh
)
106 HeapFree(GetProcessHeap(), 0, mesh
->faces
);
107 HeapFree(GetProcessHeap(), 0, mesh
->vertices
);
110 static BOOL
new_mesh(struct mesh
*mesh
, DWORD number_of_vertices
, DWORD number_of_faces
)
112 mesh
->vertices
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, number_of_vertices
* sizeof(*mesh
->vertices
));
117 mesh
->number_of_vertices
= number_of_vertices
;
119 mesh
->faces
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, number_of_faces
* sizeof(*mesh
->faces
));
122 HeapFree(GetProcessHeap(), 0, mesh
->vertices
);
125 mesh
->number_of_faces
= number_of_faces
;
130 static void compare_mesh(const char *name
, ID3DXMesh
*d3dxmesh
, struct mesh
*mesh
)
133 DWORD number_of_vertices
, number_of_faces
;
134 IDirect3DVertexBuffer9
*vertex_buffer
;
135 IDirect3DIndexBuffer9
*index_buffer
;
136 D3DVERTEXBUFFER_DESC vertex_buffer_description
;
137 D3DINDEXBUFFER_DESC index_buffer_description
;
138 struct vertex
*vertices
;
142 number_of_vertices
= d3dxmesh
->lpVtbl
->GetNumVertices(d3dxmesh
);
143 ok(number_of_vertices
== mesh
->number_of_vertices
, "Test %s, result %u, expected %d\n",
144 name
, number_of_vertices
, mesh
->number_of_vertices
);
146 number_of_faces
= d3dxmesh
->lpVtbl
->GetNumFaces(d3dxmesh
);
147 ok(number_of_faces
== mesh
->number_of_faces
, "Test %s, result %u, expected %d\n",
148 name
, number_of_faces
, mesh
->number_of_faces
);
151 hr
= d3dxmesh
->lpVtbl
->GetVertexBuffer(d3dxmesh
, &vertex_buffer
);
152 ok(hr
== D3D_OK
, "Test %s, result %x, expected 0 (D3D_OK)\n", name
, hr
);
156 skip("Couldn't get vertex buffer\n");
160 hr
= IDirect3DVertexBuffer9_GetDesc(vertex_buffer
, &vertex_buffer_description
);
161 ok(hr
== D3D_OK
, "Test %s, result %x, expected 0 (D3D_OK)\n", name
, hr
);
165 skip("Couldn't get vertex buffer description\n");
169 ok(vertex_buffer_description
.Format
== D3DFMT_VERTEXDATA
, "Test %s, result %x, expected %x (D3DFMT_VERTEXDATA)\n",
170 name
, vertex_buffer_description
.Format
, D3DFMT_VERTEXDATA
);
171 ok(vertex_buffer_description
.Type
== D3DRTYPE_VERTEXBUFFER
, "Test %s, result %x, expected %x (D3DRTYPE_VERTEXBUFFER)\n",
172 name
, vertex_buffer_description
.Type
, D3DRTYPE_VERTEXBUFFER
);
173 ok(vertex_buffer_description
.Usage
== 0, "Test %s, result %x, expected %x\n", name
, vertex_buffer_description
.Usage
, 0);
174 ok(vertex_buffer_description
.Pool
== D3DPOOL_MANAGED
, "Test %s, result %x, expected %x (D3DPOOL_MANAGED)\n",
175 name
, vertex_buffer_description
.Pool
, D3DPOOL_MANAGED
);
176 ok(vertex_buffer_description
.FVF
== mesh
->fvf
, "Test %s, result %x, expected %x\n",
177 name
, vertex_buffer_description
.FVF
, mesh
->fvf
);
180 expected
= number_of_vertices
* mesh
->vertex_size
;
184 expected
= number_of_vertices
* D3DXGetFVFVertexSize(mesh
->fvf
);
186 ok(vertex_buffer_description
.Size
== expected
, "Test %s, result %x, expected %x\n",
187 name
, vertex_buffer_description
.Size
, expected
);
190 /* specify offset and size to avoid potential overruns */
191 hr
= IDirect3DVertexBuffer9_Lock(vertex_buffer
, 0, number_of_vertices
* sizeof(D3DXVECTOR3
) * 2,
192 (LPVOID
*)&vertices
, D3DLOCK_DISCARD
);
193 ok(hr
== D3D_OK
, "Test %s, result %x, expected 0 (D3D_OK)\n", name
, hr
);
197 skip("Couldn't lock vertex buffer\n");
201 for (i
= 0; i
< number_of_vertices
; i
++)
203 ok(compare_vec3(vertices
[i
].position
, mesh
->vertices
[i
].position
),
204 "Test %s, vertex position %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name
, i
,
205 vertices
[i
].position
.x
, vertices
[i
].position
.y
, vertices
[i
].position
.z
,
206 mesh
->vertices
[i
].position
.x
, mesh
->vertices
[i
].position
.y
, mesh
->vertices
[i
].position
.z
);
207 ok(compare_vec3(vertices
[i
].normal
, mesh
->vertices
[i
].normal
),
208 "Test %s, vertex normal %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name
, i
,
209 vertices
[i
].normal
.x
, vertices
[i
].normal
.y
, vertices
[i
].normal
.z
,
210 mesh
->vertices
[i
].normal
.x
, mesh
->vertices
[i
].normal
.y
, mesh
->vertices
[i
].normal
.z
);
213 IDirect3DVertexBuffer9_Unlock(vertex_buffer
);
216 IDirect3DVertexBuffer9_Release(vertex_buffer
);
220 hr
= d3dxmesh
->lpVtbl
->GetIndexBuffer(d3dxmesh
, &index_buffer
);
221 ok(hr
== D3D_OK
, "Test %s, result %x, expected 0 (D3D_OK)\n", name
, hr
);
225 skip("Couldn't get index buffer\n");
229 hr
= IDirect3DIndexBuffer9_GetDesc(index_buffer
, &index_buffer_description
);
230 ok(hr
== D3D_OK
, "Test %s, result %x, expected 0 (D3D_OK)\n", name
, hr
);
234 skip("Couldn't get index buffer description\n");
238 ok(index_buffer_description
.Format
== D3DFMT_INDEX16
, "Test %s, result %x, expected %x (D3DFMT_INDEX16)\n",
239 name
, index_buffer_description
.Format
, D3DFMT_INDEX16
);
240 ok(index_buffer_description
.Type
== D3DRTYPE_INDEXBUFFER
, "Test %s, result %x, expected %x (D3DRTYPE_INDEXBUFFER)\n",
241 name
, index_buffer_description
.Type
, D3DRTYPE_INDEXBUFFER
);
242 todo_wine
ok(index_buffer_description
.Usage
== 0, "Test %s, result %x, expected %x\n", name
, index_buffer_description
.Usage
, 0);
243 ok(index_buffer_description
.Pool
== D3DPOOL_MANAGED
, "Test %s, result %x, expected %x (D3DPOOL_MANAGED)\n",
244 name
, index_buffer_description
.Pool
, D3DPOOL_MANAGED
);
245 expected
= number_of_faces
* sizeof(WORD
) * 3;
246 ok(index_buffer_description
.Size
== expected
, "Test %s, result %x, expected %x\n",
247 name
, index_buffer_description
.Size
, expected
);
250 /* specify offset and size to avoid potential overruns */
251 hr
= IDirect3DIndexBuffer9_Lock(index_buffer
, 0, number_of_faces
* sizeof(WORD
) * 3,
252 (LPVOID
*)&faces
, D3DLOCK_DISCARD
);
253 ok(hr
== D3D_OK
, "Test %s, result %x, expected 0 (D3D_OK)\n", name
, hr
);
257 skip("Couldn't lock index buffer\n");
261 for (i
= 0; i
< number_of_faces
; i
++)
263 ok(compare_face(faces
[i
], mesh
->faces
[i
]),
264 "Test %s, face %d, result (%u, %u, %u), expected (%u, %u, %u)\n", name
, i
,
265 faces
[i
][0], faces
[i
][1], faces
[i
][2],
266 mesh
->faces
[i
][0], mesh
->faces
[i
][1], mesh
->faces
[i
][2]);
269 IDirect3DIndexBuffer9_Unlock(index_buffer
);
272 IDirect3DIndexBuffer9_Release(index_buffer
);
276 static void D3DXBoundProbeTest(void)
279 D3DXVECTOR3 bottom_point
, center
, top_point
, raydirection
, rayposition
;
282 /*____________Test the Box case___________________________*/
283 bottom_point
.x
= -3.0f
; bottom_point
.y
= -2.0f
; bottom_point
.z
= -1.0f
;
284 top_point
.x
= 7.0f
; top_point
.y
= 8.0f
; top_point
.z
= 9.0f
;
286 raydirection
.x
= -4.0f
; raydirection
.y
= -5.0f
; raydirection
.z
= -6.0f
;
287 rayposition
.x
= 5.0f
; rayposition
.y
= 5.0f
; rayposition
.z
= 11.0f
;
288 result
= D3DXBoxBoundProbe(&bottom_point
, &top_point
, &rayposition
, &raydirection
);
289 ok(result
== TRUE
, "expected TRUE, received FALSE\n");
291 raydirection
.x
= 4.0f
; raydirection
.y
= 5.0f
; raydirection
.z
= 6.0f
;
292 rayposition
.x
= 5.0f
; rayposition
.y
= 5.0f
; rayposition
.z
= 11.0f
;
293 result
= D3DXBoxBoundProbe(&bottom_point
, &top_point
, &rayposition
, &raydirection
);
294 ok(result
== FALSE
, "expected FALSE, received TRUE\n");
296 rayposition
.x
= -4.0f
; rayposition
.y
= 1.0f
; rayposition
.z
= -2.0f
;
297 result
= D3DXBoxBoundProbe(&bottom_point
, &top_point
, &rayposition
, &raydirection
);
298 ok(result
== TRUE
, "expected TRUE, received FALSE\n");
300 bottom_point
.x
= 1.0f
; bottom_point
.y
= 0.0f
; bottom_point
.z
= 0.0f
;
301 top_point
.x
= 1.0f
; top_point
.y
= 0.0f
; top_point
.z
= 0.0f
;
302 rayposition
.x
= 0.0f
; rayposition
.y
= 1.0f
; rayposition
.z
= 0.0f
;
303 raydirection
.x
= 0.0f
; raydirection
.y
= 3.0f
; raydirection
.z
= 0.0f
;
304 result
= D3DXBoxBoundProbe(&bottom_point
, &top_point
, &rayposition
, &raydirection
);
305 ok(result
== FALSE
, "expected FALSE, received TRUE\n");
307 bottom_point
.x
= 1.0f
; bottom_point
.y
= 2.0f
; bottom_point
.z
= 3.0f
;
308 top_point
.x
= 10.0f
; top_point
.y
= 15.0f
; top_point
.z
= 20.0f
;
310 raydirection
.x
= 7.0f
; raydirection
.y
= 8.0f
; raydirection
.z
= 9.0f
;
311 rayposition
.x
= 3.0f
; rayposition
.y
= 7.0f
; rayposition
.z
= -6.0f
;
312 result
= D3DXBoxBoundProbe(&bottom_point
, &top_point
, &rayposition
, &raydirection
);
313 ok(result
== TRUE
, "expected TRUE, received FALSE\n");
315 bottom_point
.x
= 0.0f
; bottom_point
.y
= 0.0f
; bottom_point
.z
= 0.0f
;
316 top_point
.x
= 1.0f
; top_point
.y
= 1.0f
; top_point
.z
= 1.0f
;
318 raydirection
.x
= 0.0f
; raydirection
.y
= 1.0f
; raydirection
.z
= .0f
;
319 rayposition
.x
= -3.0f
; rayposition
.y
= 0.0f
; rayposition
.z
= 0.0f
;
320 result
= D3DXBoxBoundProbe(&bottom_point
, &top_point
, &rayposition
, &raydirection
);
321 ok(result
== FALSE
, "expected FALSE, received TRUE\n");
323 raydirection
.x
= 1.0f
; raydirection
.y
= 0.0f
; raydirection
.z
= .0f
;
324 rayposition
.x
= -3.0f
; rayposition
.y
= 0.0f
; rayposition
.z
= 0.0f
;
325 result
= D3DXBoxBoundProbe(&bottom_point
, &top_point
, &rayposition
, &raydirection
);
326 ok(result
== TRUE
, "expected TRUE, received FALSE\n");
328 /*____________Test the Sphere case________________________*/
329 radius
= sqrt(77.0f
);
330 center
.x
= 1.0f
; center
.y
= 2.0f
; center
.z
= 3.0f
;
331 raydirection
.x
= 2.0f
; raydirection
.y
= -4.0f
; raydirection
.z
= 2.0f
;
333 rayposition
.x
= 5.0f
; rayposition
.y
= 5.0f
; rayposition
.z
= 9.0f
;
334 result
= D3DXSphereBoundProbe(¢er
, radius
, &rayposition
, &raydirection
);
335 ok(result
== TRUE
, "expected TRUE, received FALSE\n");
337 rayposition
.x
= 45.0f
; rayposition
.y
= -75.0f
; rayposition
.z
= 49.0f
;
338 result
= D3DXSphereBoundProbe(¢er
, radius
, &rayposition
, &raydirection
);
339 ok(result
== FALSE
, "expected FALSE, received TRUE\n");
341 rayposition
.x
= 5.0f
; rayposition
.y
= 11.0f
; rayposition
.z
= 9.0f
;
342 result
= D3DXSphereBoundProbe(¢er
, radius
, &rayposition
, &raydirection
);
343 ok(result
== FALSE
, "expected FALSE, received TRUE\n");
346 static void D3DXComputeBoundingBoxTest(void)
348 D3DXVECTOR3 exp_max
, exp_min
, got_max
, got_min
, vertex
[5];
351 vertex
[0].x
= 1.0f
; vertex
[0].y
= 1.0f
; vertex
[0].z
= 1.0f
;
352 vertex
[1].x
= 1.0f
; vertex
[1].y
= 1.0f
; vertex
[1].z
= 1.0f
;
353 vertex
[2].x
= 1.0f
; vertex
[2].y
= 1.0f
; vertex
[2].z
= 1.0f
;
354 vertex
[3].x
= 1.0f
; vertex
[3].y
= 1.0f
; vertex
[3].z
= 1.0f
;
355 vertex
[4].x
= 9.0f
; vertex
[4].y
= 9.0f
; vertex
[4].z
= 9.0f
;
357 exp_min
.x
= 1.0f
; exp_min
.y
= 1.0f
; exp_min
.z
= 1.0f
;
358 exp_max
.x
= 9.0f
; exp_max
.y
= 9.0f
; exp_max
.z
= 9.0f
;
360 hr
= D3DXComputeBoundingBox(&vertex
[3],2,D3DXGetFVFVertexSize(D3DFVF_XYZ
),&got_min
,&got_max
);
362 ok( hr
== D3D_OK
, "Expected D3D_OK, got %#x\n", hr
);
363 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
);
364 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
);
366 /*________________________*/
368 vertex
[0].x
= 2.0f
; vertex
[0].y
= 5.9f
; vertex
[0].z
= -1.2f
;
369 vertex
[1].x
= -1.87f
; vertex
[1].y
= 7.9f
; vertex
[1].z
= 7.4f
;
370 vertex
[2].x
= 7.43f
; vertex
[2].y
= -0.9f
; vertex
[2].z
= 11.9f
;
371 vertex
[3].x
= -6.92f
; vertex
[3].y
= 6.3f
; vertex
[3].z
= -3.8f
;
372 vertex
[4].x
= 11.4f
; vertex
[4].y
= -8.1f
; vertex
[4].z
= 4.5f
;
374 exp_min
.x
= -6.92f
; exp_min
.y
= -8.1f
; exp_min
.z
= -3.80f
;
375 exp_max
.x
= 11.4f
; exp_max
.y
= 7.90f
; exp_max
.z
= 11.9f
;
377 hr
= D3DXComputeBoundingBox(&vertex
[0],5,D3DXGetFVFVertexSize(D3DFVF_XYZ
),&got_min
,&got_max
);
379 ok( hr
== D3D_OK
, "Expected D3D_OK, got %#x\n", hr
);
380 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
);
381 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
);
383 /*________________________*/
385 vertex
[0].x
= 2.0f
; vertex
[0].y
= 5.9f
; vertex
[0].z
= -1.2f
;
386 vertex
[1].x
= -1.87f
; vertex
[1].y
= 7.9f
; vertex
[1].z
= 7.4f
;
387 vertex
[2].x
= 7.43f
; vertex
[2].y
= -0.9f
; vertex
[2].z
= 11.9f
;
388 vertex
[3].x
= -6.92f
; vertex
[3].y
= 6.3f
; vertex
[3].z
= -3.8f
;
389 vertex
[4].x
= 11.4f
; vertex
[4].y
= -8.1f
; vertex
[4].z
= 4.5f
;
391 exp_min
.x
= -6.92f
; exp_min
.y
= -0.9f
; exp_min
.z
= -3.8f
;
392 exp_max
.x
= 7.43f
; exp_max
.y
= 7.90f
; exp_max
.z
= 11.9f
;
394 hr
= D3DXComputeBoundingBox(&vertex
[0],4,D3DXGetFVFVertexSize(D3DFVF_XYZ
),&got_min
,&got_max
);
396 ok( hr
== D3D_OK
, "Expected D3D_OK, got %#x\n", hr
);
397 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
);
398 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
);
400 /*________________________*/
401 hr
= D3DXComputeBoundingBox(NULL
,5,D3DXGetFVFVertexSize(D3DFVF_XYZ
),&got_min
,&got_max
);
402 ok( hr
== D3DERR_INVALIDCALL
, "Expected D3DERR_INVALIDCALL, got %#x\n", hr
);
404 /*________________________*/
405 hr
= D3DXComputeBoundingBox(&vertex
[3],5,D3DXGetFVFVertexSize(D3DFVF_XYZ
),NULL
,&got_max
);
406 ok( hr
== D3DERR_INVALIDCALL
, "Expected D3DERR_INVALIDCALL, got %#x\n", hr
);
408 /*________________________*/
409 hr
= D3DXComputeBoundingBox(&vertex
[3],5,D3DXGetFVFVertexSize(D3DFVF_XYZ
),&got_min
,NULL
);
410 ok( hr
== D3DERR_INVALIDCALL
, "Expected D3DERR_INVALIDCALL, got %#x\n", hr
);
413 static void D3DXComputeBoundingSphereTest(void)
415 D3DXVECTOR3 exp_cen
, got_cen
, vertex
[5];
416 FLOAT exp_rad
, got_rad
;
419 vertex
[0].x
= 1.0f
; vertex
[0].y
= 1.0f
; vertex
[0].z
= 1.0f
;
420 vertex
[1].x
= 1.0f
; vertex
[1].y
= 1.0f
; vertex
[1].z
= 1.0f
;
421 vertex
[2].x
= 1.0f
; vertex
[2].y
= 1.0f
; vertex
[2].z
= 1.0f
;
422 vertex
[3].x
= 1.0f
; vertex
[3].y
= 1.0f
; vertex
[3].z
= 1.0f
;
423 vertex
[4].x
= 9.0f
; vertex
[4].y
= 9.0f
; vertex
[4].z
= 9.0f
;
426 exp_cen
.x
= 5.0; exp_cen
.y
= 5.0; exp_cen
.z
= 5.0;
428 hr
= D3DXComputeBoundingSphere(&vertex
[3],2,D3DXGetFVFVertexSize(D3DFVF_XYZ
),&got_cen
,&got_rad
);
430 ok( hr
== D3D_OK
, "Expected D3D_OK, got %#x\n", hr
);
431 ok( compare(exp_rad
, got_rad
), "Expected radius: %f, got radius: %f\n", exp_rad
, got_rad
);
432 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
);
434 /*________________________*/
436 vertex
[0].x
= 2.0f
; vertex
[0].y
= 5.9f
; vertex
[0].z
= -1.2f
;
437 vertex
[1].x
= -1.87f
; vertex
[1].y
= 7.9f
; vertex
[1].z
= 7.4f
;
438 vertex
[2].x
= 7.43f
; vertex
[2].y
= -0.9f
; vertex
[2].z
= 11.9f
;
439 vertex
[3].x
= -6.92f
; vertex
[3].y
= 6.3f
; vertex
[3].z
= -3.8f
;
440 vertex
[4].x
= 11.4f
; vertex
[4].y
= -8.1f
; vertex
[4].z
= 4.5f
;
442 exp_rad
= 13.707883f
;
443 exp_cen
.x
= 2.408f
; exp_cen
.y
= 2.22f
; exp_cen
.z
= 3.76f
;
445 hr
= D3DXComputeBoundingSphere(&vertex
[0],5,D3DXGetFVFVertexSize(D3DFVF_XYZ
),&got_cen
,&got_rad
);
447 ok( hr
== D3D_OK
, "Expected D3D_OK, got %#x\n", hr
);
448 ok( compare(exp_rad
, got_rad
), "Expected radius: %f, got radius: %f\n", exp_rad
, got_rad
);
449 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
);
451 /*________________________*/
452 hr
= D3DXComputeBoundingSphere(NULL
,5,D3DXGetFVFVertexSize(D3DFVF_XYZ
),&got_cen
,&got_rad
);
453 ok( hr
== D3DERR_INVALIDCALL
, "Expected D3DERR_INVALIDCALL, got %#x\n", hr
);
455 /*________________________*/
456 hr
= D3DXComputeBoundingSphere(&vertex
[3],5,D3DXGetFVFVertexSize(D3DFVF_XYZ
),NULL
,&got_rad
);
457 ok( hr
== D3DERR_INVALIDCALL
, "Expected D3DERR_INVALIDCALL, got %#x\n", hr
);
459 /*________________________*/
460 hr
= D3DXComputeBoundingSphere(&vertex
[3],5,D3DXGetFVFVertexSize(D3DFVF_XYZ
),&got_cen
,NULL
);
461 ok( hr
== D3DERR_INVALIDCALL
, "Expected D3DERR_INVALIDCALL, got %#x\n", hr
);
464 static void print_elements(const D3DVERTEXELEMENT9
*elements
)
466 D3DVERTEXELEMENT9 last
= D3DDECL_END();
467 const D3DVERTEXELEMENT9
*ptr
= elements
;
470 while (memcmp(ptr
, &last
, sizeof(D3DVERTEXELEMENT9
)))
473 "[Element %d] Stream = %d, Offset = %d, Type = %d, Method = %d, Usage = %d, UsageIndex = %d\n",
474 count
, ptr
->Stream
, ptr
->Offset
, ptr
->Type
, ptr
->Method
, ptr
->Usage
, ptr
->UsageIndex
);
480 static void compare_elements(const D3DVERTEXELEMENT9
*elements
, const D3DVERTEXELEMENT9
*expected_elements
,
481 unsigned int line
, unsigned int test_id
)
483 D3DVERTEXELEMENT9 last
= D3DDECL_END();
486 for (i
= 0; i
< MAX_FVF_DECL_SIZE
; i
++)
488 int end1
= memcmp(&elements
[i
], &last
, sizeof(last
));
489 int end2
= memcmp(&expected_elements
[i
], &last
, sizeof(last
));
492 if (!end1
&& !end2
) break;
494 status
= !end1
^ !end2
;
495 ok(!status
, "Line %u, test %u: Mismatch in size, test declaration is %s than expected.\n",
496 line
, test_id
, end1
? "shorter" : "longer");
499 print_elements(elements
);
503 status
= memcmp(&elements
[i
], &expected_elements
[i
], sizeof(D3DVERTEXELEMENT9
));
504 ok(!status
, "Line %u, test %u: Mismatch in element %u.\n", line
, test_id
, i
);
507 print_elements(elements
);
513 static void test_fvf_to_decl(DWORD test_fvf
, const D3DVERTEXELEMENT9 expected_elements
[],
514 HRESULT expected_hr
, unsigned int line
, unsigned int test_id
)
517 D3DVERTEXELEMENT9 decl
[MAX_FVF_DECL_SIZE
];
519 hr
= D3DXDeclaratorFromFVF(test_fvf
, decl
);
520 ok(hr
== expected_hr
,
521 "Line %u, test %u: D3DXDeclaratorFromFVF returned %#x, expected %#x.\n",
522 line
, test_id
, hr
, expected_hr
);
523 if (SUCCEEDED(hr
)) compare_elements(decl
, expected_elements
, line
, test_id
);
526 static void test_decl_to_fvf(const D3DVERTEXELEMENT9
*decl
, DWORD expected_fvf
,
527 HRESULT expected_hr
, unsigned int line
, unsigned int test_id
)
530 DWORD result_fvf
= 0xdeadbeef;
532 hr
= D3DXFVFFromDeclarator(decl
, &result_fvf
);
533 ok(hr
== expected_hr
,
534 "Line %u, test %u: D3DXFVFFromDeclarator returned %#x, expected %#x.\n",
535 line
, test_id
, hr
, expected_hr
);
538 ok(expected_fvf
== result_fvf
, "Line %u, test %u: Got FVF %#x, expected %#x.\n",
539 line
, test_id
, result_fvf
, expected_fvf
);
543 static void test_fvf_decl_conversion(void)
547 D3DVERTEXELEMENT9 decl
[MAXD3DDECLLENGTH
+ 1];
556 {0, 0, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_POSITION
, 0},
560 {0, 0, D3DDECLTYPE_FLOAT4
, 0, D3DDECLUSAGE_POSITIONT
, 0},
564 {0, 0, D3DDECLTYPE_FLOAT4
, 0, D3DDECLUSAGE_POSITIONT
, 0},
568 {0, 0, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_POSITION
, 0},
569 {0, 12, D3DDECLTYPE_FLOAT1
, 0, D3DDECLUSAGE_BLENDWEIGHT
, 0},
573 {0, 0, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_POSITION
, 0},
574 {0, 12, D3DDECLTYPE_UBYTE4
, 0, D3DDECLUSAGE_BLENDINDICES
, 0},
576 }, D3DFVF_XYZB1
| D3DFVF_LASTBETA_UBYTE4
},
578 {0, 0, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_POSITION
, 0},
579 {0, 12, D3DDECLTYPE_D3DCOLOR
, 0, D3DDECLUSAGE_BLENDINDICES
, 0},
581 }, D3DFVF_XYZB1
| D3DFVF_LASTBETA_D3DCOLOR
},
583 {0, 0, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_POSITION
, 0},
584 {0, 12, D3DDECLTYPE_FLOAT2
, 0, D3DDECLUSAGE_BLENDWEIGHT
, 0},
588 {0, 0, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_POSITION
, 0},
589 {0, 12, D3DDECLTYPE_FLOAT1
, 0, D3DDECLUSAGE_BLENDWEIGHT
, 0},
590 {0, 16, D3DDECLTYPE_UBYTE4
, 0, D3DDECLUSAGE_BLENDINDICES
, 0},
592 }, D3DFVF_XYZB2
| D3DFVF_LASTBETA_UBYTE4
},
594 {0, 0, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_POSITION
, 0},
595 {0, 12, D3DDECLTYPE_FLOAT1
, 0, D3DDECLUSAGE_BLENDWEIGHT
, 0},
596 {0, 16, D3DDECLTYPE_D3DCOLOR
, 0, D3DDECLUSAGE_BLENDINDICES
, 0},
598 }, D3DFVF_XYZB2
| D3DFVF_LASTBETA_D3DCOLOR
},
600 {0, 0, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_POSITION
, 0},
601 {0, 12, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_BLENDWEIGHT
, 0},
605 {0, 0, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_POSITION
, 0},
606 {0, 12, D3DDECLTYPE_FLOAT2
, 0, D3DDECLUSAGE_BLENDWEIGHT
, 0},
607 {0, 20, D3DDECLTYPE_UBYTE4
, 0, D3DDECLUSAGE_BLENDINDICES
, 0},
609 }, D3DFVF_XYZB3
| D3DFVF_LASTBETA_UBYTE4
},
611 {0, 0, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_POSITION
, 0},
612 {0, 12, D3DDECLTYPE_FLOAT2
, 0, D3DDECLUSAGE_BLENDWEIGHT
, 0},
613 {0, 20, D3DDECLTYPE_D3DCOLOR
, 0, D3DDECLUSAGE_BLENDINDICES
, 0},
615 }, D3DFVF_XYZB3
| D3DFVF_LASTBETA_D3DCOLOR
},
617 {0, 0, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_POSITION
, 0},
618 {0, 12, D3DDECLTYPE_FLOAT4
, 0, D3DDECLUSAGE_BLENDWEIGHT
, 0},
622 {0, 0, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_POSITION
, 0},
623 {0, 12, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_BLENDWEIGHT
, 0},
624 {0, 24, D3DDECLTYPE_UBYTE4
, 0, D3DDECLUSAGE_BLENDINDICES
, 0},
626 }, D3DFVF_XYZB4
| D3DFVF_LASTBETA_UBYTE4
},
628 {0, 0, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_POSITION
, 0},
629 {0, 12, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_BLENDWEIGHT
, 0},
630 {0, 24, D3DDECLTYPE_D3DCOLOR
, 0, D3DDECLUSAGE_BLENDINDICES
, 0},
632 }, D3DFVF_XYZB4
| D3DFVF_LASTBETA_D3DCOLOR
},
634 {0, 0, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_POSITION
, 0},
635 {0, 12, D3DDECLTYPE_FLOAT4
, 0, D3DDECLUSAGE_BLENDWEIGHT
, 0},
636 {0, 28, D3DDECLTYPE_UBYTE4
, 0, D3DDECLUSAGE_BLENDINDICES
, 0},
638 }, D3DFVF_XYZB5
| D3DFVF_LASTBETA_UBYTE4
},
640 {0, 0, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_POSITION
, 0},
641 {0, 12, D3DDECLTYPE_FLOAT4
, 0, D3DDECLUSAGE_BLENDWEIGHT
, 0},
642 {0, 28, D3DDECLTYPE_D3DCOLOR
, 0, D3DDECLUSAGE_BLENDINDICES
, 0},
644 }, D3DFVF_XYZB5
| D3DFVF_LASTBETA_D3DCOLOR
},
646 {0, 0, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_NORMAL
, 0},
650 {0, 0, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_NORMAL
, 0},
651 {0, 12, D3DDECLTYPE_D3DCOLOR
, 0, D3DDECLUSAGE_COLOR
, 0},
653 }, D3DFVF_NORMAL
| D3DFVF_DIFFUSE
},
655 {0, 0, D3DDECLTYPE_FLOAT1
, 0, D3DDECLUSAGE_PSIZE
, 0},
659 {0, 0, D3DDECLTYPE_D3DCOLOR
, 0, D3DDECLUSAGE_COLOR
, 0},
663 {0, 0, D3DDECLTYPE_D3DCOLOR
, 0, D3DDECLUSAGE_COLOR
, 1},
666 /* Make sure textures of different sizes work. */
668 {0, 0, D3DDECLTYPE_FLOAT1
, 0, D3DDECLUSAGE_TEXCOORD
, 0},
670 }, D3DFVF_TEXCOORDSIZE1(0) | D3DFVF_TEX1
},
672 {0, 0, D3DDECLTYPE_FLOAT2
, 0, D3DDECLUSAGE_TEXCOORD
, 0},
674 }, D3DFVF_TEXCOORDSIZE2(0) | D3DFVF_TEX1
},
676 {0, 0, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_TEXCOORD
, 0},
678 }, D3DFVF_TEXCOORDSIZE3(0) | D3DFVF_TEX1
},
680 {0, 0, D3DDECLTYPE_FLOAT4
, 0, D3DDECLUSAGE_TEXCOORD
, 0},
682 }, D3DFVF_TEXCOORDSIZE4(0) | D3DFVF_TEX1
},
683 /* Make sure the TEXCOORD index works correctly - try several textures. */
685 {0, 0, D3DDECLTYPE_FLOAT1
, 0, D3DDECLUSAGE_TEXCOORD
, 0},
686 {0, 4, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_TEXCOORD
, 1},
687 {0, 16, D3DDECLTYPE_FLOAT2
, 0, D3DDECLUSAGE_TEXCOORD
, 2},
688 {0, 24, D3DDECLTYPE_FLOAT4
, 0, D3DDECLUSAGE_TEXCOORD
, 3},
690 }, D3DFVF_TEX4
| D3DFVF_TEXCOORDSIZE1(0) | D3DFVF_TEXCOORDSIZE3(1)
691 | D3DFVF_TEXCOORDSIZE2(2) | D3DFVF_TEXCOORDSIZE4(3)},
692 /* Now try some combination tests. */
694 {0, 0, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_POSITION
, 0},
695 {0, 12, D3DDECLTYPE_FLOAT4
, 0, D3DDECLUSAGE_BLENDWEIGHT
, 0},
696 {0, 28, D3DDECLTYPE_D3DCOLOR
, 0, D3DDECLUSAGE_COLOR
, 0},
697 {0, 32, D3DDECLTYPE_D3DCOLOR
, 0, D3DDECLUSAGE_COLOR
, 1},
698 {0, 36, D3DDECLTYPE_FLOAT2
, 0, D3DDECLUSAGE_TEXCOORD
, 0},
699 {0, 44, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_TEXCOORD
, 1},
701 }, D3DFVF_XYZB4
| D3DFVF_DIFFUSE
| D3DFVF_SPECULAR
| D3DFVF_TEX2
702 | D3DFVF_TEXCOORDSIZE2(0) | D3DFVF_TEXCOORDSIZE3(1)},
704 {0, 0, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_POSITION
, 0},
705 {0, 12, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_NORMAL
, 0},
706 {0, 24, D3DDECLTYPE_FLOAT1
, 0, D3DDECLUSAGE_PSIZE
, 0},
707 {0, 28, D3DDECLTYPE_D3DCOLOR
, 0, D3DDECLUSAGE_COLOR
, 1},
708 {0, 32, D3DDECLTYPE_FLOAT1
, 0, D3DDECLUSAGE_TEXCOORD
, 0},
709 {0, 36, D3DDECLTYPE_FLOAT4
, 0, D3DDECLUSAGE_TEXCOORD
, 1},
711 }, D3DFVF_XYZ
| D3DFVF_NORMAL
| D3DFVF_PSIZE
| D3DFVF_SPECULAR
| D3DFVF_TEX2
712 | D3DFVF_TEXCOORDSIZE1(0) | D3DFVF_TEXCOORDSIZE4(1)},
716 for (i
= 0; i
< sizeof(test_data
) / sizeof(*test_data
); ++i
)
718 test_decl_to_fvf(test_data
[i
].decl
, test_data
[i
].fvf
, D3D_OK
, __LINE__
, i
);
719 test_fvf_to_decl(test_data
[i
].fvf
, test_data
[i
].decl
, D3D_OK
, __LINE__
, i
);
722 /* Usage indices for position and normal are apparently ignored. */
724 const D3DVERTEXELEMENT9 decl
[] =
726 {0, 0, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_POSITION
, 1},
729 test_decl_to_fvf(decl
, D3DFVF_XYZ
, D3D_OK
, __LINE__
, 0);
732 const D3DVERTEXELEMENT9 decl
[] =
734 {0, 0, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_NORMAL
, 1},
737 test_decl_to_fvf(decl
, D3DFVF_NORMAL
, D3D_OK
, __LINE__
, 0);
739 /* D3DFVF_LASTBETA_UBYTE4 and D3DFVF_LASTBETA_D3DCOLOR are ignored if
740 * there are no blend matrices. */
742 const D3DVERTEXELEMENT9 decl
[] =
744 {0, 0, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_POSITION
, 0},
747 test_fvf_to_decl(D3DFVF_XYZ
| D3DFVF_LASTBETA_UBYTE4
, decl
, D3D_OK
, __LINE__
, 0);
750 const D3DVERTEXELEMENT9 decl
[] =
752 {0, 0, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_POSITION
, 0},
755 test_fvf_to_decl(D3DFVF_XYZ
| D3DFVF_LASTBETA_D3DCOLOR
, decl
, D3D_OK
, __LINE__
, 0);
757 /* D3DFVF_LASTBETA_UBYTE4 takes precedence over D3DFVF_LASTBETA_D3DCOLOR. */
759 const D3DVERTEXELEMENT9 decl
[] =
761 {0, 0, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_POSITION
, 0},
762 {0, 12, D3DDECLTYPE_FLOAT4
, 0, D3DDECLUSAGE_BLENDWEIGHT
, 0},
763 {0, 28, D3DDECLTYPE_UBYTE4
, 0, D3DDECLUSAGE_BLENDINDICES
, 0},
766 test_fvf_to_decl(D3DFVF_XYZB5
| D3DFVF_LASTBETA_D3DCOLOR
| D3DFVF_LASTBETA_UBYTE4
,
767 decl
, D3D_OK
, __LINE__
, 0);
769 /* These are supposed to fail, both ways. */
771 const D3DVERTEXELEMENT9 decl
[] =
773 {0, 0, D3DDECLTYPE_FLOAT4
, 0, D3DDECLUSAGE_POSITION
, 0},
776 test_decl_to_fvf(decl
, D3DFVF_XYZW
, D3DERR_INVALIDCALL
, __LINE__
, 0);
777 test_fvf_to_decl(D3DFVF_XYZW
, decl
, D3DERR_INVALIDCALL
, __LINE__
, 0);
780 const D3DVERTEXELEMENT9 decl
[] =
782 {0, 0, D3DDECLTYPE_FLOAT4
, 0, D3DDECLUSAGE_POSITION
, 0},
783 {0, 16, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_NORMAL
, 0},
786 test_decl_to_fvf(decl
, D3DFVF_XYZW
| D3DFVF_NORMAL
, D3DERR_INVALIDCALL
, __LINE__
, 0);
787 test_fvf_to_decl(D3DFVF_XYZW
| D3DFVF_NORMAL
, decl
, D3DERR_INVALIDCALL
, __LINE__
, 0);
790 const D3DVERTEXELEMENT9 decl
[] =
792 {0, 0, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_POSITION
, 0},
793 {0, 12, D3DDECLTYPE_FLOAT4
, 0, D3DDECLUSAGE_BLENDWEIGHT
, 0},
794 {0, 28, D3DDECLTYPE_FLOAT1
, 0, D3DDECLUSAGE_BLENDINDICES
, 0},
797 test_decl_to_fvf(decl
, D3DFVF_XYZB5
, D3DERR_INVALIDCALL
, __LINE__
, 0);
798 test_fvf_to_decl(D3DFVF_XYZB5
, decl
, D3DERR_INVALIDCALL
, __LINE__
, 0);
800 /* Test a declaration that can't be converted to an FVF. */
802 const D3DVERTEXELEMENT9 decl
[] =
804 {0, 0, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_POSITION
, 0},
805 {0, 12, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_NORMAL
, 0},
806 {0, 24, D3DDECLTYPE_FLOAT1
, 0, D3DDECLUSAGE_PSIZE
, 0},
807 {0, 28, D3DDECLTYPE_D3DCOLOR
, 0, D3DDECLUSAGE_COLOR
, 1},
808 {0, 32, D3DDECLTYPE_FLOAT1
, 0, D3DDECLUSAGE_TEXCOORD
, 0},
809 /* 8 bytes padding */
810 {0, 44, D3DDECLTYPE_FLOAT4
, 0, D3DDECLUSAGE_TEXCOORD
, 1},
813 test_decl_to_fvf(decl
, 0, D3DERR_INVALIDCALL
, __LINE__
, 0);
815 /* Elements must be ordered by offset. */
817 const D3DVERTEXELEMENT9 decl
[] =
819 {0, 12, D3DDECLTYPE_D3DCOLOR
, 0, D3DDECLUSAGE_COLOR
, 0},
820 {0, 0, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_POSITION
, 0},
823 test_decl_to_fvf(decl
, 0, D3DERR_INVALIDCALL
, __LINE__
, 0);
825 /* Basic tests for element order. */
827 const D3DVERTEXELEMENT9 decl
[] =
829 {0, 0, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_POSITION
, 0},
830 {0, 12, D3DDECLTYPE_D3DCOLOR
, 0, D3DDECLUSAGE_COLOR
, 0},
831 {0, 16, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_NORMAL
, 0},
834 test_decl_to_fvf(decl
, 0, D3DERR_INVALIDCALL
, __LINE__
, 0);
837 const D3DVERTEXELEMENT9 decl
[] =
839 {0, 0, D3DDECLTYPE_D3DCOLOR
, 0, D3DDECLUSAGE_COLOR
, 0},
840 {0, 4, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_POSITION
, 0},
843 test_decl_to_fvf(decl
, 0, D3DERR_INVALIDCALL
, __LINE__
, 0);
846 const D3DVERTEXELEMENT9 decl
[] =
848 {0, 0, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_NORMAL
, 0},
849 {0, 12, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_POSITION
, 0},
852 test_decl_to_fvf(decl
, 0, D3DERR_INVALIDCALL
, __LINE__
, 0);
854 /* Textures must be ordered by texcoords. */
856 const D3DVERTEXELEMENT9 decl
[] =
858 {0, 0, D3DDECLTYPE_FLOAT1
, 0, D3DDECLUSAGE_TEXCOORD
, 0},
859 {0, 4, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_TEXCOORD
, 2},
860 {0, 16, D3DDECLTYPE_FLOAT2
, 0, D3DDECLUSAGE_TEXCOORD
, 1},
861 {0, 24, D3DDECLTYPE_FLOAT4
, 0, D3DDECLUSAGE_TEXCOORD
, 3},
864 test_decl_to_fvf(decl
, 0, D3DERR_INVALIDCALL
, __LINE__
, 0);
866 /* Duplicate elements are not allowed. */
868 const D3DVERTEXELEMENT9 decl
[] =
870 {0, 0, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_POSITION
, 0},
871 {0, 12, D3DDECLTYPE_D3DCOLOR
, 0, D3DDECLUSAGE_COLOR
, 0},
872 {0, 16, D3DDECLTYPE_D3DCOLOR
, 0, D3DDECLUSAGE_COLOR
, 0},
875 test_decl_to_fvf(decl
, 0, D3DERR_INVALIDCALL
, __LINE__
, 0);
877 /* Invalid FVFs cannot be converted to a declarator. */
878 test_fvf_to_decl(0xdeadbeef, NULL
, D3DERR_INVALIDCALL
, __LINE__
, 0);
881 static void D3DXGetFVFVertexSizeTest(void)
885 compare_vertex_sizes (D3DFVF_XYZ
, 12);
887 compare_vertex_sizes (D3DFVF_XYZB3
, 24);
889 compare_vertex_sizes (D3DFVF_XYZB5
, 32);
891 compare_vertex_sizes (D3DFVF_XYZ
| D3DFVF_NORMAL
, 24);
893 compare_vertex_sizes (D3DFVF_XYZ
| D3DFVF_DIFFUSE
, 16);
895 compare_vertex_sizes (
898 D3DFVF_TEXCOORDSIZE1(0), 16);
899 compare_vertex_sizes (
902 D3DFVF_TEXCOORDSIZE1(0) |
903 D3DFVF_TEXCOORDSIZE1(1), 20);
905 compare_vertex_sizes (
908 D3DFVF_TEXCOORDSIZE2(0), 20);
910 compare_vertex_sizes (
913 D3DFVF_TEXCOORDSIZE2(0) |
914 D3DFVF_TEXCOORDSIZE2(1), 28);
916 compare_vertex_sizes (
919 D3DFVF_TEXCOORDSIZE2(0) |
920 D3DFVF_TEXCOORDSIZE2(1) |
921 D3DFVF_TEXCOORDSIZE2(2) |
922 D3DFVF_TEXCOORDSIZE2(3) |
923 D3DFVF_TEXCOORDSIZE2(4) |
924 D3DFVF_TEXCOORDSIZE2(5), 60);
926 compare_vertex_sizes (
929 D3DFVF_TEXCOORDSIZE2(0) |
930 D3DFVF_TEXCOORDSIZE2(1) |
931 D3DFVF_TEXCOORDSIZE2(2) |
932 D3DFVF_TEXCOORDSIZE2(3) |
933 D3DFVF_TEXCOORDSIZE2(4) |
934 D3DFVF_TEXCOORDSIZE2(5) |
935 D3DFVF_TEXCOORDSIZE2(6) |
936 D3DFVF_TEXCOORDSIZE2(7), 76);
938 compare_vertex_sizes (
941 D3DFVF_TEXCOORDSIZE3(0), 24);
943 compare_vertex_sizes (
946 D3DFVF_TEXCOORDSIZE3(0) |
947 D3DFVF_TEXCOORDSIZE3(1) |
948 D3DFVF_TEXCOORDSIZE3(2) |
949 D3DFVF_TEXCOORDSIZE3(3), 60);
951 compare_vertex_sizes (
954 D3DFVF_TEXCOORDSIZE4(0), 28);
956 compare_vertex_sizes (
959 D3DFVF_TEXCOORDSIZE4(0) |
960 D3DFVF_TEXCOORDSIZE4(1), 44);
962 compare_vertex_sizes (
965 D3DFVF_TEXCOORDSIZE4(0) |
966 D3DFVF_TEXCOORDSIZE4(1) |
967 D3DFVF_TEXCOORDSIZE4(2), 60);
969 compare_vertex_sizes (
975 D3DFVF_TEXCOORDSIZE4(0) |
976 D3DFVF_TEXCOORDSIZE4(1) |
977 D3DFVF_TEXCOORDSIZE4(2) |
978 D3DFVF_TEXCOORDSIZE4(3) |
979 D3DFVF_TEXCOORDSIZE4(4) |
980 D3DFVF_TEXCOORDSIZE4(5) |
981 D3DFVF_TEXCOORDSIZE4(6) |
982 D3DFVF_TEXCOORDSIZE4(7), 180);
985 static void D3DXIntersectTriTest(void)
987 BOOL exp_res
, got_res
;
988 D3DXVECTOR3 position
, ray
, vertex
[3];
989 FLOAT exp_dist
, got_dist
, exp_u
, got_u
, exp_v
, got_v
;
991 vertex
[0].x
= 1.0f
; vertex
[0].y
= 0.0f
; vertex
[0].z
= 0.0f
;
992 vertex
[1].x
= 2.0f
; vertex
[1].y
= 0.0f
; vertex
[1].z
= 0.0f
;
993 vertex
[2].x
= 1.0f
; vertex
[2].y
= 1.0f
; vertex
[2].z
= 0.0f
;
995 position
.x
= -14.5f
; position
.y
= -23.75f
; position
.z
= -32.0f
;
997 ray
.x
= 2.0f
; ray
.y
= 3.0f
; ray
.z
= 4.0f
;
999 exp_res
= TRUE
; exp_u
= 0.5f
; exp_v
= 0.25f
; exp_dist
= 8.0f
;
1001 got_res
= D3DXIntersectTri(&vertex
[0],&vertex
[1],&vertex
[2],&position
,&ray
,&got_u
,&got_v
,&got_dist
);
1002 ok( got_res
== exp_res
, "Expected result = %d, got %d\n",exp_res
,got_res
);
1003 ok( compare(exp_u
,got_u
), "Expected u = %f, got %f\n",exp_u
,got_u
);
1004 ok( compare(exp_v
,got_v
), "Expected v = %f, got %f\n",exp_v
,got_v
);
1005 ok( compare(exp_dist
,got_dist
), "Expected distance = %f, got %f\n",exp_dist
,got_dist
);
1007 /*Only positive ray is taken in account*/
1009 vertex
[0].x
= 1.0f
; vertex
[0].y
= 0.0f
; vertex
[0].z
= 0.0f
;
1010 vertex
[1].x
= 2.0f
; vertex
[1].y
= 0.0f
; vertex
[1].z
= 0.0f
;
1011 vertex
[2].x
= 1.0f
; vertex
[2].y
= 1.0f
; vertex
[2].z
= 0.0f
;
1013 position
.x
= 17.5f
; position
.y
= 24.25f
; position
.z
= 32.0f
;
1015 ray
.x
= 2.0f
; ray
.y
= 3.0f
; ray
.z
= 4.0f
;
1019 got_res
= D3DXIntersectTri(&vertex
[0],&vertex
[1],&vertex
[2],&position
,&ray
,&got_u
,&got_v
,&got_dist
);
1020 ok( got_res
== exp_res
, "Expected result = %d, got %d\n",exp_res
,got_res
);
1022 /*Intersection between ray and triangle in a same plane is considered as empty*/
1024 vertex
[0].x
= 4.0f
; vertex
[0].y
= 0.0f
; vertex
[0].z
= 0.0f
;
1025 vertex
[1].x
= 6.0f
; vertex
[1].y
= 0.0f
; vertex
[1].z
= 0.0f
;
1026 vertex
[2].x
= 4.0f
; vertex
[2].y
= 2.0f
; vertex
[2].z
= 0.0f
;
1028 position
.x
= 1.0f
; position
.y
= 1.0f
; position
.z
= 0.0f
;
1030 ray
.x
= 1.0f
; ray
.y
= 0.0f
; ray
.z
= 0.0f
;
1034 got_res
= D3DXIntersectTri(&vertex
[0],&vertex
[1],&vertex
[2],&position
,&ray
,&got_u
,&got_v
,&got_dist
);
1035 ok( got_res
== exp_res
, "Expected result = %d, got %d\n",exp_res
,got_res
);
1038 static void D3DXCreateMeshTest(void)
1043 IDirect3DDevice9
*device
, *test_device
;
1044 D3DPRESENT_PARAMETERS d3dpp
;
1045 ID3DXMesh
*d3dxmesh
;
1047 D3DVERTEXELEMENT9 test_decl
[MAX_FVF_DECL_SIZE
];
1051 static const D3DVERTEXELEMENT9 decl1
[3] = {
1052 {0, 0, D3DDECLTYPE_FLOAT3
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
1053 {0, 12, D3DDECLTYPE_FLOAT3
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_NORMAL
, 0},
1056 static const D3DVERTEXELEMENT9 decl2
[] = {
1057 {0, 0, D3DDECLTYPE_FLOAT3
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
1058 {0, 12, D3DDECLTYPE_FLOAT3
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_NORMAL
, 0},
1059 {0, 24, D3DDECLTYPE_FLOAT1
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_PSIZE
, 0},
1060 {0, 28, D3DDECLTYPE_D3DCOLOR
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_COLOR
, 1},
1061 {0, 32, D3DDECLTYPE_FLOAT1
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_TEXCOORD
, 0},
1062 /* 8 bytes padding */
1063 {0, 44, D3DDECLTYPE_FLOAT4
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_TEXCOORD
, 1},
1067 static const D3DVERTEXELEMENT9 decl3
[] = {
1068 {0, 0, D3DDECLTYPE_FLOAT3
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
1069 {1, 0, D3DDECLTYPE_FLOAT3
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_NORMAL
, 0},
1073 hr
= D3DXCreateMesh(0, 0, 0, NULL
, NULL
, NULL
);
1074 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr
, D3DERR_INVALIDCALL
);
1076 hr
= D3DXCreateMesh(1, 3, D3DXMESH_MANAGED
, decl1
, NULL
, &d3dxmesh
);
1077 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr
, D3DERR_INVALIDCALL
);
1079 wnd
= CreateWindow("static", "d3dx9_test", 0, 0, 0, 0, 0, NULL
, NULL
, NULL
, NULL
);
1082 skip("Couldn't create application window\n");
1085 d3d
= Direct3DCreate9(D3D_SDK_VERSION
);
1088 skip("Couldn't create IDirect3D9 object\n");
1093 ZeroMemory(&d3dpp
, sizeof(d3dpp
));
1094 d3dpp
.Windowed
= TRUE
;
1095 d3dpp
.SwapEffect
= D3DSWAPEFFECT_DISCARD
;
1096 hr
= IDirect3D9_CreateDevice(d3d
, D3DADAPTER_DEFAULT
, D3DDEVTYPE_HAL
, wnd
, D3DCREATE_MIXED_VERTEXPROCESSING
, &d3dpp
, &device
);
1099 skip("Failed to create IDirect3DDevice9 object %#x\n", hr
);
1100 IDirect3D9_Release(d3d
);
1105 hr
= D3DXCreateMesh(0, 3, D3DXMESH_MANAGED
, decl1
, device
, &d3dxmesh
);
1106 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr
, D3DERR_INVALIDCALL
);
1108 hr
= D3DXCreateMesh(1, 0, D3DXMESH_MANAGED
, decl1
, device
, &d3dxmesh
);
1109 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr
, D3DERR_INVALIDCALL
);
1111 hr
= D3DXCreateMesh(1, 3, 0, decl1
, device
, &d3dxmesh
);
1112 ok(hr
== D3D_OK
, "Got result %x, expected %x (D3D_OK)\n", hr
, D3D_OK
);
1116 d3dxmesh
->lpVtbl
->Release(d3dxmesh
);
1119 hr
= D3DXCreateMesh(1, 3, D3DXMESH_MANAGED
, 0, device
, &d3dxmesh
);
1120 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr
, D3DERR_INVALIDCALL
);
1122 hr
= D3DXCreateMesh(1, 3, D3DXMESH_MANAGED
, decl1
, device
, NULL
);
1123 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr
, D3DERR_INVALIDCALL
);
1125 hr
= D3DXCreateMesh(1, 3, D3DXMESH_MANAGED
, decl1
, device
, &d3dxmesh
);
1126 ok(hr
== D3D_OK
, "Got result %x, expected 0 (D3D_OK)\n", hr
);
1131 hr
= d3dxmesh
->lpVtbl
->GetDevice(d3dxmesh
, NULL
);
1132 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr
, D3DERR_INVALIDCALL
);
1134 hr
= d3dxmesh
->lpVtbl
->GetDevice(d3dxmesh
, &test_device
);
1135 ok(hr
== D3D_OK
, "Got result %x, expected %x (D3D_OK)\n", hr
, D3D_OK
);
1136 ok(test_device
== device
, "Got result %p, expected %p\n", test_device
, device
);
1140 IDirect3DDevice9_Release(device
);
1144 hr
= d3dxmesh
->lpVtbl
->GetDeclaration(d3dxmesh
, NULL
);
1145 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr
, D3DERR_INVALIDCALL
);
1147 hr
= d3dxmesh
->lpVtbl
->GetDeclaration(d3dxmesh
, test_decl
);
1148 ok(hr
== D3D_OK
, "Got result %x, expected 0 (D3D_OK)\n", hr
);
1152 size
= sizeof(decl1
) / sizeof(decl1
[0]);
1153 for (i
= 0; i
< size
- 1; i
++)
1155 ok(test_decl
[i
].Stream
== decl1
[i
].Stream
, "Returned stream %d, expected %d\n", test_decl
[i
].Stream
, decl1
[i
].Stream
);
1156 ok(test_decl
[i
].Type
== decl1
[i
].Type
, "Returned type %d, expected %d\n", test_decl
[i
].Type
, decl1
[i
].Type
);
1157 ok(test_decl
[i
].Method
== decl1
[i
].Method
, "Returned method %d, expected %d\n", test_decl
[i
].Method
, decl1
[i
].Method
);
1158 ok(test_decl
[i
].Usage
== decl1
[i
].Usage
, "Returned usage %d, expected %d\n", test_decl
[i
].Usage
, decl1
[i
].Usage
);
1159 ok(test_decl
[i
].UsageIndex
== decl1
[i
].UsageIndex
, "Returned usage index %d, expected %d\n", test_decl
[i
].UsageIndex
, decl1
[i
].UsageIndex
);
1160 ok(test_decl
[i
].Offset
== decl1
[i
].Offset
, "Returned offset %d, expected %d\n", test_decl
[i
].Offset
, decl1
[i
].Offset
);
1162 ok(decl1
[size
-1].Stream
== 0xFF, "Returned too long vertex declaration\n"); /* end element */
1166 options
= d3dxmesh
->lpVtbl
->GetOptions(d3dxmesh
);
1167 ok(options
== D3DXMESH_MANAGED
, "Got result %x, expected %x (D3DXMESH_MANAGED)\n", options
, D3DXMESH_MANAGED
);
1170 if (!new_mesh(&mesh
, 3, 1))
1172 skip("Couldn't create mesh\n");
1176 memset(mesh
.vertices
, 0, mesh
.number_of_vertices
* sizeof(*mesh
.vertices
));
1177 memset(mesh
.faces
, 0, mesh
.number_of_faces
* sizeof(*mesh
.faces
));
1178 mesh
.fvf
= D3DFVF_XYZ
| D3DFVF_NORMAL
;
1180 compare_mesh("createmesh1", d3dxmesh
, &mesh
);
1185 d3dxmesh
->lpVtbl
->Release(d3dxmesh
);
1188 /* Test a declaration that can't be converted to an FVF. */
1189 hr
= D3DXCreateMesh(1, 3, D3DXMESH_MANAGED
, decl2
, device
, &d3dxmesh
);
1190 ok(hr
== D3D_OK
, "Got result %x, expected 0 (D3D_OK)\n", hr
);
1195 hr
= d3dxmesh
->lpVtbl
->GetDevice(d3dxmesh
, NULL
);
1196 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr
, D3DERR_INVALIDCALL
);
1198 hr
= d3dxmesh
->lpVtbl
->GetDevice(d3dxmesh
, &test_device
);
1199 ok(hr
== D3D_OK
, "Got result %x, expected %x (D3D_OK)\n", hr
, D3D_OK
);
1200 ok(test_device
== device
, "Got result %p, expected %p\n", test_device
, device
);
1204 IDirect3DDevice9_Release(device
);
1208 hr
= d3dxmesh
->lpVtbl
->GetDeclaration(d3dxmesh
, test_decl
);
1209 ok(hr
== D3D_OK
, "Got result %x, expected 0 (D3D_OK)\n", hr
);
1213 size
= sizeof(decl2
) / sizeof(decl2
[0]);
1214 for (i
= 0; i
< size
- 1; i
++)
1216 ok(test_decl
[i
].Stream
== decl2
[i
].Stream
, "Returned stream %d, expected %d\n", test_decl
[i
].Stream
, decl2
[i
].Stream
);
1217 ok(test_decl
[i
].Type
== decl2
[i
].Type
, "Returned type %d, expected %d\n", test_decl
[i
].Type
, decl2
[i
].Type
);
1218 ok(test_decl
[i
].Method
== decl2
[i
].Method
, "Returned method %d, expected %d\n", test_decl
[i
].Method
, decl2
[i
].Method
);
1219 ok(test_decl
[i
].Usage
== decl2
[i
].Usage
, "Returned usage %d, expected %d\n", test_decl
[i
].Usage
, decl2
[i
].Usage
);
1220 ok(test_decl
[i
].UsageIndex
== decl2
[i
].UsageIndex
, "Returned usage index %d, expected %d\n", test_decl
[i
].UsageIndex
, decl2
[i
].UsageIndex
);
1221 ok(test_decl
[i
].Offset
== decl2
[i
].Offset
, "Returned offset %d, expected %d\n", test_decl
[i
].Offset
, decl2
[i
].Offset
);
1223 ok(decl2
[size
-1].Stream
== 0xFF, "Returned too long vertex declaration\n"); /* end element */
1227 options
= d3dxmesh
->lpVtbl
->GetOptions(d3dxmesh
);
1228 ok(options
== D3DXMESH_MANAGED
, "Got result %x, expected %x (D3DXMESH_MANAGED)\n", options
, D3DXMESH_MANAGED
);
1231 if (!new_mesh(&mesh
, 3, 1))
1233 skip("Couldn't create mesh\n");
1237 memset(mesh
.vertices
, 0, mesh
.number_of_vertices
* sizeof(*mesh
.vertices
));
1238 memset(mesh
.faces
, 0, mesh
.number_of_faces
* sizeof(*mesh
.faces
));
1240 mesh
.vertex_size
= 60;
1242 compare_mesh("createmesh2", d3dxmesh
, &mesh
);
1247 mesh
.vertex_size
= d3dxmesh
->lpVtbl
->GetNumBytesPerVertex(d3dxmesh
);
1248 ok(mesh
.vertex_size
== 60, "Got vertex size %u, expected %u\n", mesh
.vertex_size
, 60);
1250 d3dxmesh
->lpVtbl
->Release(d3dxmesh
);
1253 /* Test a declaration with multiple streams. */
1254 hr
= D3DXCreateMesh(1, 3, D3DXMESH_MANAGED
, decl3
, device
, &d3dxmesh
);
1255 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr
, D3DERR_INVALIDCALL
);
1257 IDirect3DDevice9_Release(device
);
1258 IDirect3D9_Release(d3d
);
1262 static void D3DXCreateMeshFVFTest(void)
1267 IDirect3DDevice9
*device
, *test_device
;
1268 D3DPRESENT_PARAMETERS d3dpp
;
1269 ID3DXMesh
*d3dxmesh
;
1271 D3DVERTEXELEMENT9 test_decl
[MAX_FVF_DECL_SIZE
];
1275 static const D3DVERTEXELEMENT9 decl
[3] = {
1276 {0, 0, D3DDECLTYPE_FLOAT3
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
1277 {0, 12, D3DDECLTYPE_FLOAT3
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_NORMAL
, 0},
1280 hr
= D3DXCreateMeshFVF(0, 0, 0, 0, NULL
, NULL
);
1281 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr
, D3DERR_INVALIDCALL
);
1283 hr
= D3DXCreateMeshFVF(1, 3, D3DXMESH_MANAGED
, D3DFVF_XYZ
| D3DFVF_NORMAL
, NULL
, &d3dxmesh
);
1284 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr
, D3DERR_INVALIDCALL
);
1286 wnd
= CreateWindow("static", "d3dx9_test", 0, 0, 0, 0, 0, NULL
, NULL
, NULL
, NULL
);
1289 skip("Couldn't create application window\n");
1292 d3d
= Direct3DCreate9(D3D_SDK_VERSION
);
1295 skip("Couldn't create IDirect3D9 object\n");
1300 ZeroMemory(&d3dpp
, sizeof(d3dpp
));
1301 d3dpp
.Windowed
= TRUE
;
1302 d3dpp
.SwapEffect
= D3DSWAPEFFECT_DISCARD
;
1303 hr
= IDirect3D9_CreateDevice(d3d
, D3DADAPTER_DEFAULT
, D3DDEVTYPE_HAL
, wnd
, D3DCREATE_MIXED_VERTEXPROCESSING
, &d3dpp
, &device
);
1306 skip("Failed to create IDirect3DDevice9 object %#x\n", hr
);
1307 IDirect3D9_Release(d3d
);
1312 hr
= D3DXCreateMeshFVF(0, 3, D3DXMESH_MANAGED
, D3DFVF_XYZ
| D3DFVF_NORMAL
, device
, &d3dxmesh
);
1313 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr
, D3DERR_INVALIDCALL
);
1315 hr
= D3DXCreateMeshFVF(1, 0, D3DXMESH_MANAGED
, D3DFVF_XYZ
| D3DFVF_NORMAL
, device
, &d3dxmesh
);
1316 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr
, D3DERR_INVALIDCALL
);
1318 hr
= D3DXCreateMeshFVF(1, 3, 0, D3DFVF_XYZ
| D3DFVF_NORMAL
, device
, &d3dxmesh
);
1319 ok(hr
== D3D_OK
, "Got result %x, expected %x (D3D_OK)\n", hr
, D3D_OK
);
1323 d3dxmesh
->lpVtbl
->Release(d3dxmesh
);
1326 hr
= D3DXCreateMeshFVF(1, 3, D3DXMESH_MANAGED
, 0xdeadbeef, device
, &d3dxmesh
);
1327 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr
, D3DERR_INVALIDCALL
);
1329 hr
= D3DXCreateMeshFVF(1, 3, D3DXMESH_MANAGED
, D3DFVF_XYZ
| D3DFVF_NORMAL
, device
, NULL
);
1330 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr
, D3DERR_INVALIDCALL
);
1332 hr
= D3DXCreateMeshFVF(1, 3, D3DXMESH_MANAGED
, D3DFVF_XYZ
| D3DFVF_NORMAL
, device
, &d3dxmesh
);
1333 ok(hr
== D3D_OK
, "Got result %x, expected 0 (D3D_OK)\n", hr
);
1338 hr
= d3dxmesh
->lpVtbl
->GetDevice(d3dxmesh
, NULL
);
1339 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr
, D3DERR_INVALIDCALL
);
1341 hr
= d3dxmesh
->lpVtbl
->GetDevice(d3dxmesh
, &test_device
);
1342 ok(hr
== D3D_OK
, "Got result %x, expected %x (D3D_OK)\n", hr
, D3D_OK
);
1343 ok(test_device
== device
, "Got result %p, expected %p\n", test_device
, device
);
1347 IDirect3DDevice9_Release(device
);
1351 hr
= d3dxmesh
->lpVtbl
->GetDeclaration(d3dxmesh
, NULL
);
1352 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr
, D3DERR_INVALIDCALL
);
1354 hr
= d3dxmesh
->lpVtbl
->GetDeclaration(d3dxmesh
, test_decl
);
1355 ok(hr
== D3D_OK
, "Got result %x, expected 0 (D3D_OK)\n", hr
);
1359 size
= sizeof(decl
) / sizeof(decl
[0]);
1360 for (i
= 0; i
< size
- 1; i
++)
1362 ok(test_decl
[i
].Stream
== decl
[i
].Stream
, "Returned stream %d, expected %d\n", test_decl
[i
].Stream
, decl
[i
].Stream
);
1363 ok(test_decl
[i
].Type
== decl
[i
].Type
, "Returned type %d, expected %d\n", test_decl
[i
].Type
, decl
[i
].Type
);
1364 ok(test_decl
[i
].Method
== decl
[i
].Method
, "Returned method %d, expected %d\n", test_decl
[i
].Method
, decl
[i
].Method
);
1365 ok(test_decl
[i
].Usage
== decl
[i
].Usage
, "Returned usage %d, expected %d\n", test_decl
[i
].Usage
, decl
[i
].Usage
);
1366 ok(test_decl
[i
].UsageIndex
== decl
[i
].UsageIndex
, "Returned usage index %d, expected %d\n",
1367 test_decl
[i
].UsageIndex
, decl
[i
].UsageIndex
);
1368 ok(test_decl
[i
].Offset
== decl
[i
].Offset
, "Returned offset %d, expected %d\n", test_decl
[i
].Offset
, decl
[i
].Offset
);
1370 ok(decl
[size
-1].Stream
== 0xFF, "Returned too long vertex declaration\n"); /* end element */
1374 options
= d3dxmesh
->lpVtbl
->GetOptions(d3dxmesh
);
1375 ok(options
== D3DXMESH_MANAGED
, "Got result %x, expected %x (D3DXMESH_MANAGED)\n", options
, D3DXMESH_MANAGED
);
1378 if (!new_mesh(&mesh
, 3, 1))
1380 skip("Couldn't create mesh\n");
1384 memset(mesh
.vertices
, 0, mesh
.number_of_vertices
* sizeof(*mesh
.vertices
));
1385 memset(mesh
.faces
, 0, mesh
.number_of_faces
* sizeof(*mesh
.faces
));
1386 mesh
.fvf
= D3DFVF_XYZ
| D3DFVF_NORMAL
;
1388 compare_mesh("createmeshfvf", d3dxmesh
, &mesh
);
1393 d3dxmesh
->lpVtbl
->Release(d3dxmesh
);
1396 IDirect3DDevice9_Release(device
);
1397 IDirect3D9_Release(d3d
);
1401 #define check_vertex_buffer(mesh, vertices, num_vertices, fvf) \
1402 check_vertex_buffer_(__LINE__, mesh, vertices, num_vertices, fvf)
1403 static void check_vertex_buffer_(int line
, ID3DXMesh
*mesh
, const void *vertices
, DWORD num_vertices
, DWORD fvf
)
1405 DWORD mesh_num_vertices
= mesh
->lpVtbl
->GetNumVertices(mesh
);
1406 DWORD mesh_fvf
= mesh
->lpVtbl
->GetFVF(mesh
);
1407 const void *mesh_vertices
;
1410 ok_(__FILE__
,line
)(fvf
== mesh_fvf
, "expected FVF %x, got %x\n", fvf
, mesh_fvf
);
1411 ok_(__FILE__
,line
)(num_vertices
== mesh_num_vertices
,
1412 "Expected %u vertices, got %u\n", num_vertices
, mesh_num_vertices
);
1414 hr
= mesh
->lpVtbl
->LockVertexBuffer(mesh
, D3DLOCK_READONLY
, (void**)&mesh_vertices
);
1415 ok_(__FILE__
,line
)(hr
== D3D_OK
, "LockVertexBuffer returned %x, expected %x (D3D_OK)\n", hr
, D3D_OK
);
1419 if (mesh_fvf
== fvf
) {
1420 DWORD vertex_size
= D3DXGetFVFVertexSize(fvf
);
1422 for (i
= 0; i
< min(num_vertices
, mesh_num_vertices
); i
++)
1424 const FLOAT
*exp_float
= vertices
;
1425 const FLOAT
*got_float
= mesh_vertices
;
1429 BOOL last_beta_dword
= FALSE
;
1432 switch (fvf
& D3DFVF_POSITION_MASK
) {
1433 case D3DFVF_XYZ
: pos_dim
= 3; break;
1434 case D3DFVF_XYZRHW
: pos_dim
= 4; break;
1440 pos_dim
= (fvf
& D3DFVF_POSITION_MASK
) - D3DFVF_XYZB1
+ 1;
1441 if (fvf
& (D3DFVF_LASTBETA_UBYTE4
| D3DFVF_LASTBETA_D3DCOLOR
))
1444 last_beta_dword
= TRUE
;
1447 case D3DFVF_XYZW
: pos_dim
= 4; break;
1449 sprintf(prefix
, "vertex[%u] position, ", i
);
1450 check_floats_(line
, prefix
, got_float
, exp_float
, pos_dim
);
1451 exp_float
+= pos_dim
;
1452 got_float
+= pos_dim
;
1454 if (last_beta_dword
) {
1455 ok_(__FILE__
,line
)(*(DWORD
*)exp_float
== *(DWORD
*)got_float
,
1456 "Vertex[%u]: Expected last beta %08x, got %08x\n", i
, *(DWORD
*)exp_float
, *(DWORD
*)got_float
);
1461 if (fvf
& D3DFVF_NORMAL
) {
1462 sprintf(prefix
, "vertex[%u] normal, ", i
);
1463 check_floats_(line
, prefix
, got_float
, exp_float
, 3);
1467 if (fvf
& D3DFVF_PSIZE
) {
1468 ok_(__FILE__
,line
)(compare(*exp_float
, *got_float
),
1469 "Vertex[%u]: Expected psize %g, got %g\n", i
, *exp_float
, *got_float
);
1473 if (fvf
& D3DFVF_DIFFUSE
) {
1474 ok_(__FILE__
,line
)(*(DWORD
*)exp_float
== *(DWORD
*)got_float
,
1475 "Vertex[%u]: Expected diffuse %08x, got %08x\n", i
, *(DWORD
*)exp_float
, *(DWORD
*)got_float
);
1479 if (fvf
& D3DFVF_SPECULAR
) {
1480 ok_(__FILE__
,line
)(*(DWORD
*)exp_float
== *(DWORD
*)got_float
,
1481 "Vertex[%u]: Expected specular %08x, got %08x\n", i
, *(DWORD
*)exp_float
, *(DWORD
*)got_float
);
1486 texcount
= (fvf
& D3DFVF_TEXCOUNT_MASK
) >> D3DFVF_TEXCOUNT_SHIFT
;
1487 for (j
= 0; j
< texcount
; j
++) {
1488 DWORD dim
= (((fvf
>> (16 + 2 * j
)) + 1) & 0x03) + 1;
1489 sprintf(prefix
, "vertex[%u] texture, ", i
);
1490 check_floats_(line
, prefix
, got_float
, exp_float
, dim
);
1495 vertices
= (BYTE
*)vertices
+ vertex_size
;
1496 mesh_vertices
= (BYTE
*)mesh_vertices
+ vertex_size
;
1500 mesh
->lpVtbl
->UnlockVertexBuffer(mesh
);
1503 #define check_index_buffer(mesh, indices, num_indices, index_size) \
1504 check_index_buffer_(__LINE__, mesh, indices, num_indices, index_size)
1505 static void check_index_buffer_(int line
, ID3DXMesh
*mesh
, const void *indices
, DWORD num_indices
, DWORD index_size
)
1507 DWORD mesh_index_size
= (mesh
->lpVtbl
->GetOptions(mesh
) & D3DXMESH_32BIT
) ? 4 : 2;
1508 DWORD mesh_num_indices
= mesh
->lpVtbl
->GetNumFaces(mesh
) * 3;
1509 const void *mesh_indices
;
1513 ok_(__FILE__
,line
)(index_size
== mesh_index_size
,
1514 "Expected index size %u, got %u\n", index_size
, mesh_index_size
);
1515 ok_(__FILE__
,line
)(num_indices
== mesh_num_indices
,
1516 "Expected %u indices, got %u\n", num_indices
, mesh_num_indices
);
1518 hr
= mesh
->lpVtbl
->LockIndexBuffer(mesh
, D3DLOCK_READONLY
, (void**)&mesh_indices
);
1519 ok_(__FILE__
,line
)(hr
== D3D_OK
, "LockIndexBuffer returned %x, expected %x (D3D_OK)\n", hr
, D3D_OK
);
1523 if (mesh_index_size
== index_size
) {
1524 for (i
= 0; i
< min(num_indices
, mesh_num_indices
); i
++)
1526 if (index_size
== 4)
1527 ok_(__FILE__
,line
)(*(DWORD
*)indices
== *(DWORD
*)mesh_indices
,
1528 "Index[%u]: expected %u, got %u\n", i
, *(DWORD
*)indices
, *(DWORD
*)mesh_indices
);
1530 ok_(__FILE__
,line
)(*(WORD
*)indices
== *(WORD
*)mesh_indices
,
1531 "Index[%u]: expected %u, got %u\n", i
, *(WORD
*)indices
, *(WORD
*)mesh_indices
);
1532 indices
= (BYTE
*)indices
+ index_size
;
1533 mesh_indices
= (BYTE
*)mesh_indices
+ index_size
;
1536 mesh
->lpVtbl
->UnlockIndexBuffer(mesh
);
1539 #define check_matrix(got, expected) check_matrix_(__LINE__, got, expected)
1540 static void check_matrix_(int line
, const D3DXMATRIX
*got
, const D3DXMATRIX
*expected
)
1543 for (i
= 0; i
< 4; i
++) {
1544 for (j
= 0; j
< 4; j
++) {
1545 ok_(__FILE__
,line
)(compare(U(*expected
).m
[i
][j
], U(*got
).m
[i
][j
]),
1546 "matrix[%u][%u]: expected %g, got %g\n",
1547 i
, j
, U(*expected
).m
[i
][j
], U(*got
).m
[i
][j
]);
1552 static void check_colorvalue_(int line
, const char *prefix
, const D3DCOLORVALUE got
, const D3DCOLORVALUE expected
)
1554 ok_(__FILE__
,line
)(expected
.r
== got
.r
&& expected
.g
== got
.g
&& expected
.b
== got
.b
&& expected
.a
== got
.a
,
1555 "%sExpected (%g, %g, %g, %g), got (%g, %g, %g, %g)\n", prefix
,
1556 expected
.r
, expected
.g
, expected
.b
, expected
.a
, got
.r
, got
.g
, got
.b
, got
.a
);
1559 #define check_materials(got, got_count, expected, expected_count) \
1560 check_materials_(__LINE__, got, got_count, expected, expected_count)
1561 static void check_materials_(int line
, const D3DXMATERIAL
*got
, DWORD got_count
, const D3DXMATERIAL
*expected
, DWORD expected_count
)
1564 ok_(__FILE__
,line
)(expected_count
== got_count
, "Expected %u materials, got %u\n", expected_count
, got_count
);
1566 ok_(__FILE__
,line
)(got
== NULL
, "Expected NULL material ptr, got %p\n", got
);
1569 for (i
= 0; i
< min(expected_count
, got_count
); i
++)
1571 if (!expected
[i
].pTextureFilename
)
1572 ok_(__FILE__
,line
)(got
[i
].pTextureFilename
== NULL
,
1573 "Expected NULL pTextureFilename, got %p\n", got
[i
].pTextureFilename
);
1575 ok_(__FILE__
,line
)(!strcmp(expected
[i
].pTextureFilename
, got
[i
].pTextureFilename
),
1576 "Expected '%s' for pTextureFilename, got '%s'\n", expected
[i
].pTextureFilename
, got
[i
].pTextureFilename
);
1577 check_colorvalue_(line
, "Diffuse: ", got
[i
].MatD3D
.Diffuse
, expected
[i
].MatD3D
.Diffuse
);
1578 check_colorvalue_(line
, "Ambient: ", got
[i
].MatD3D
.Ambient
, expected
[i
].MatD3D
.Ambient
);
1579 check_colorvalue_(line
, "Specular: ", got
[i
].MatD3D
.Specular
, expected
[i
].MatD3D
.Specular
);
1580 check_colorvalue_(line
, "Emissive: ", got
[i
].MatD3D
.Emissive
, expected
[i
].MatD3D
.Emissive
);
1581 ok_(__FILE__
,line
)(expected
[i
].MatD3D
.Power
== got
[i
].MatD3D
.Power
,
1582 "Power: Expected %g, got %g\n", expected
[i
].MatD3D
.Power
, got
[i
].MatD3D
.Power
);
1586 #define check_generated_adjacency(mesh, got, epsilon) check_generated_adjacency_(__LINE__, mesh, got, epsilon)
1587 static void check_generated_adjacency_(int line
, ID3DXMesh
*mesh
, const DWORD
*got
, FLOAT epsilon
)
1590 DWORD num_faces
= mesh
->lpVtbl
->GetNumFaces(mesh
);
1593 expected
= HeapAlloc(GetProcessHeap(), 0, num_faces
* sizeof(DWORD
) * 3);
1595 skip_(__FILE__
, line
)("Out of memory\n");
1598 hr
= mesh
->lpVtbl
->GenerateAdjacency(mesh
, epsilon
, expected
);
1599 ok_(__FILE__
, line
)(hr
== D3D_OK
, "Expected D3D_OK, got %#x\n", hr
);
1603 for (i
= 0; i
< num_faces
; i
++)
1605 ok_(__FILE__
, line
)(expected
[i
* 3] == got
[i
* 3] &&
1606 expected
[i
* 3 + 1] == got
[i
* 3 + 1] &&
1607 expected
[i
* 3 + 2] == got
[i
* 3 + 2],
1608 "Face %u adjacencies: Expected (%u, %u, %u), got (%u, %u, %u)\n", i
,
1609 expected
[i
* 3], expected
[i
* 3 + 1], expected
[i
* 3 + 2],
1610 got
[i
* 3], got
[i
* 3 + 1], got
[i
* 3 + 2]);
1613 HeapFree(GetProcessHeap(), 0, expected
);
1616 #define check_generated_effects(materials, num_materials, effects) \
1617 check_generated_effects_(__LINE__, materials, num_materials, effects)
1618 static void check_generated_effects_(int line
, const D3DXMATERIAL
*materials
, DWORD num_materials
, const D3DXEFFECTINSTANCE
*effects
)
1621 static const struct {
1627 #define EFFECT_TABLE_ENTRY(str, field) \
1628 {str, sizeof(str), sizeof(materials->MatD3D.field), offsetof(D3DXMATERIAL, MatD3D.field)}
1629 EFFECT_TABLE_ENTRY("Diffuse", Diffuse
),
1630 EFFECT_TABLE_ENTRY("Power", Power
),
1631 EFFECT_TABLE_ENTRY("Specular", Specular
),
1632 EFFECT_TABLE_ENTRY("Emissive", Emissive
),
1633 EFFECT_TABLE_ENTRY("Ambient", Ambient
),
1634 #undef EFFECT_TABLE_ENTRY
1637 if (!num_materials
) {
1638 ok_(__FILE__
, line
)(effects
== NULL
, "Expected NULL effects, got %p\n", effects
);
1641 for (i
= 0; i
< num_materials
; i
++)
1644 DWORD expected_num_defaults
= ARRAY_SIZE(params
) + (materials
[i
].pTextureFilename
? 1 : 0);
1646 ok_(__FILE__
,line
)(expected_num_defaults
== effects
[i
].NumDefaults
,
1647 "effect[%u] NumDefaults: Expected %u, got %u\n", i
,
1648 expected_num_defaults
, effects
[i
].NumDefaults
);
1649 for (j
= 0; j
< min(ARRAY_SIZE(params
), effects
[i
].NumDefaults
); j
++)
1652 D3DXEFFECTDEFAULT
*got_param
= &effects
[i
].pDefaults
[j
];
1653 ok_(__FILE__
,line
)(!strcmp(params
[j
].name
, got_param
->pParamName
),
1654 "effect[%u].pDefaults[%u].pParamName: Expected '%s', got '%s'\n", i
, j
,
1655 params
[j
].name
, got_param
->pParamName
);
1656 ok_(__FILE__
,line
)(D3DXEDT_FLOATS
== got_param
->Type
,
1657 "effect[%u].pDefaults[%u].Type: Expected %u, got %u\n", i
, j
,
1658 D3DXEDT_FLOATS
, got_param
->Type
);
1659 ok_(__FILE__
,line
)(params
[j
].num_bytes
== got_param
->NumBytes
,
1660 "effect[%u].pDefaults[%u].NumBytes: Expected %u, got %u\n", i
, j
,
1661 params
[j
].num_bytes
, got_param
->NumBytes
);
1662 for (k
= 0; k
< min(params
[j
].num_bytes
, got_param
->NumBytes
) / 4; k
++)
1664 FLOAT expected
= ((FLOAT
*)((BYTE
*)&materials
[i
] + params
[j
].value_offset
))[k
];
1665 FLOAT got
= ((FLOAT
*)got_param
->pValue
)[k
];
1666 ok_(__FILE__
,line
)(compare(expected
, got
),
1667 "effect[%u].pDefaults[%u] float value %u: Expected %g, got %g\n", i
, j
, k
, expected
, got
);
1670 if (effects
[i
].NumDefaults
> ARRAY_SIZE(params
)) {
1671 D3DXEFFECTDEFAULT
*got_param
= &effects
[i
].pDefaults
[j
];
1672 static const char *expected_name
= "Texture0@Name";
1674 ok_(__FILE__
,line
)(!strcmp(expected_name
, got_param
->pParamName
),
1675 "effect[%u].pDefaults[%u].pParamName: Expected '%s', got '%s'\n", i
, j
,
1676 expected_name
, got_param
->pParamName
);
1677 ok_(__FILE__
,line
)(D3DXEDT_STRING
== got_param
->Type
,
1678 "effect[%u].pDefaults[%u].Type: Expected %u, got %u\n", i
, j
,
1679 D3DXEDT_STRING
, got_param
->Type
);
1680 if (materials
[i
].pTextureFilename
) {
1681 ok_(__FILE__
,line
)(strlen(materials
[i
].pTextureFilename
) + 1 == got_param
->NumBytes
,
1682 "effect[%u] texture filename length: Expected %u, got %u\n", i
,
1683 (DWORD
)strlen(materials
[i
].pTextureFilename
) + 1, got_param
->NumBytes
);
1684 ok_(__FILE__
,line
)(!strcmp(materials
[i
].pTextureFilename
, got_param
->pValue
),
1685 "effect[%u] texture filename: Expected '%s', got '%s'\n", i
,
1686 materials
[i
].pTextureFilename
, (char*)got_param
->pValue
);
1692 static LPSTR
strdupA(LPCSTR p
)
1695 if (!p
) return NULL
;
1696 ret
= HeapAlloc(GetProcessHeap(), 0, strlen(p
) + 1);
1697 if (ret
) strcpy(ret
, p
);
1701 static CALLBACK HRESULT
ID3DXAllocateHierarchyImpl_DestroyFrame(ID3DXAllocateHierarchy
*iface
, LPD3DXFRAME frame
)
1703 TRACECALLBACK("ID3DXAllocateHierarchyImpl_DestroyFrame(%p, %p)\n", iface
, frame
);
1705 HeapFree(GetProcessHeap(), 0, frame
->Name
);
1706 HeapFree(GetProcessHeap(), 0, frame
);
1711 static CALLBACK HRESULT
ID3DXAllocateHierarchyImpl_CreateFrame(ID3DXAllocateHierarchy
*iface
, LPCSTR name
, LPD3DXFRAME
*new_frame
)
1715 TRACECALLBACK("ID3DXAllocateHierarchyImpl_CreateFrame(%p, '%s', %p)\n", iface
, name
, new_frame
);
1716 frame
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*frame
));
1718 return E_OUTOFMEMORY
;
1720 frame
->Name
= strdupA(name
);
1722 HeapFree(GetProcessHeap(), 0, frame
);
1723 return E_OUTOFMEMORY
;
1730 static HRESULT
destroy_mesh_container(LPD3DXMESHCONTAINER mesh_container
)
1734 if (!mesh_container
)
1736 HeapFree(GetProcessHeap(), 0, mesh_container
->Name
);
1737 if (U(mesh_container
->MeshData
).pMesh
)
1738 IUnknown_Release(U(mesh_container
->MeshData
).pMesh
);
1739 if (mesh_container
->pMaterials
) {
1740 for (i
= 0; i
< mesh_container
->NumMaterials
; i
++)
1741 HeapFree(GetProcessHeap(), 0, mesh_container
->pMaterials
[i
].pTextureFilename
);
1742 HeapFree(GetProcessHeap(), 0, mesh_container
->pMaterials
);
1744 if (mesh_container
->pEffects
) {
1745 for (i
= 0; i
< mesh_container
->NumMaterials
; i
++) {
1746 HeapFree(GetProcessHeap(), 0, mesh_container
->pEffects
[i
].pEffectFilename
);
1747 if (mesh_container
->pEffects
[i
].pDefaults
) {
1749 for (j
= 0; j
< mesh_container
->pEffects
[i
].NumDefaults
; j
++) {
1750 HeapFree(GetProcessHeap(), 0, mesh_container
->pEffects
[i
].pDefaults
[j
].pParamName
);
1751 HeapFree(GetProcessHeap(), 0, mesh_container
->pEffects
[i
].pDefaults
[j
].pValue
);
1753 HeapFree(GetProcessHeap(), 0, mesh_container
->pEffects
[i
].pDefaults
);
1756 HeapFree(GetProcessHeap(), 0, mesh_container
->pEffects
);
1758 HeapFree(GetProcessHeap(), 0, mesh_container
->pAdjacency
);
1759 if (mesh_container
->pSkinInfo
)
1760 IUnknown_Release(mesh_container
->pSkinInfo
);
1761 HeapFree(GetProcessHeap(), 0, mesh_container
);
1765 static CALLBACK HRESULT
ID3DXAllocateHierarchyImpl_DestroyMeshContainer(ID3DXAllocateHierarchy
*iface
, LPD3DXMESHCONTAINER mesh_container
)
1767 TRACECALLBACK("ID3DXAllocateHierarchyImpl_DestroyMeshContainer(%p, %p)\n", iface
, mesh_container
);
1768 return destroy_mesh_container(mesh_container
);
1771 static CALLBACK HRESULT
ID3DXAllocateHierarchyImpl_CreateMeshContainer(ID3DXAllocateHierarchy
*iface
,
1772 LPCSTR name
, CONST D3DXMESHDATA
*mesh_data
, CONST D3DXMATERIAL
*materials
,
1773 CONST D3DXEFFECTINSTANCE
*effects
, DWORD num_materials
, CONST DWORD
*adjacency
,
1774 LPD3DXSKININFO skin_info
, LPD3DXMESHCONTAINER
*new_mesh_container
)
1776 LPD3DXMESHCONTAINER mesh_container
= NULL
;
1779 TRACECALLBACK("ID3DXAllocateHierarchyImpl_CreateMeshContainer(%p, '%s', %u, %p, %p, %p, %d, %p, %p, %p)\n",
1780 iface
, name
, mesh_data
->Type
, U(*mesh_data
).pMesh
, materials
, effects
,
1781 num_materials
, adjacency
, skin_info
, *new_mesh_container
);
1783 mesh_container
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*mesh_container
));
1784 if (!mesh_container
)
1785 return E_OUTOFMEMORY
;
1788 mesh_container
->Name
= strdupA(name
);
1789 if (!mesh_container
->Name
)
1793 mesh_container
->NumMaterials
= num_materials
;
1794 if (num_materials
) {
1795 mesh_container
->pMaterials
= HeapAlloc(GetProcessHeap(), 0, num_materials
* sizeof(*materials
));
1796 if (!mesh_container
->pMaterials
)
1799 memcpy(mesh_container
->pMaterials
, materials
, num_materials
* sizeof(*materials
));
1800 for (i
= 0; i
< num_materials
; i
++)
1801 mesh_container
->pMaterials
[i
].pTextureFilename
= NULL
;
1802 for (i
= 0; i
< num_materials
; i
++) {
1803 if (materials
[i
].pTextureFilename
) {
1804 mesh_container
->pMaterials
[i
].pTextureFilename
= strdupA(materials
[i
].pTextureFilename
);
1805 if (!mesh_container
->pMaterials
[i
].pTextureFilename
)
1810 mesh_container
->pEffects
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, num_materials
* sizeof(*effects
));
1811 if (!mesh_container
->pEffects
)
1813 for (i
= 0; i
< num_materials
; i
++) {
1815 const D3DXEFFECTINSTANCE
*effect_src
= &effects
[i
];
1816 D3DXEFFECTINSTANCE
*effect_dest
= &mesh_container
->pEffects
[i
];
1818 if (effect_src
->pEffectFilename
) {
1819 effect_dest
->pEffectFilename
= strdupA(effect_src
->pEffectFilename
);
1820 if (!effect_dest
->pEffectFilename
)
1823 effect_dest
->pDefaults
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
1824 effect_src
->NumDefaults
* sizeof(*effect_src
->pDefaults
));
1825 if (!effect_dest
->pDefaults
)
1827 effect_dest
->NumDefaults
= effect_src
->NumDefaults
;
1828 for (j
= 0; j
< effect_src
->NumDefaults
; j
++) {
1829 const D3DXEFFECTDEFAULT
*default_src
= &effect_src
->pDefaults
[j
];
1830 D3DXEFFECTDEFAULT
*default_dest
= &effect_dest
->pDefaults
[j
];
1832 if (default_src
->pParamName
) {
1833 default_dest
->pParamName
= strdupA(default_src
->pParamName
);
1834 if (!default_dest
->pParamName
)
1837 default_dest
->NumBytes
= default_src
->NumBytes
;
1838 default_dest
->Type
= default_src
->Type
;
1839 default_dest
->pValue
= HeapAlloc(GetProcessHeap(), 0, default_src
->NumBytes
);
1840 memcpy(default_dest
->pValue
, default_src
->pValue
, default_src
->NumBytes
);
1845 ok(adjacency
!= NULL
, "Expected non-NULL adjacency, got NULL\n");
1847 if (mesh_data
->Type
== D3DXMESHTYPE_MESH
|| mesh_data
->Type
== D3DXMESHTYPE_PMESH
) {
1848 ID3DXBaseMesh
*basemesh
= (ID3DXBaseMesh
*)U(*mesh_data
).pMesh
;
1849 DWORD num_faces
= basemesh
->lpVtbl
->GetNumFaces(basemesh
);
1850 size_t size
= num_faces
* sizeof(DWORD
) * 3;
1851 mesh_container
->pAdjacency
= HeapAlloc(GetProcessHeap(), 0, size
);
1852 if (!mesh_container
->pAdjacency
)
1854 memcpy(mesh_container
->pAdjacency
, adjacency
, size
);
1856 ok(mesh_data
->Type
== D3DXMESHTYPE_PATCHMESH
, "Unknown mesh type %u\n", mesh_data
->Type
);
1857 if (mesh_data
->Type
== D3DXMESHTYPE_PATCHMESH
)
1858 trace("FIXME: copying adjacency data for patch mesh not implemented");
1862 memcpy(&mesh_container
->MeshData
, mesh_data
, sizeof(*mesh_data
));
1863 if (U(*mesh_data
).pMesh
)
1864 IUnknown_AddRef(U(*mesh_data
).pMesh
);
1866 mesh_container
->pSkinInfo
= skin_info
;
1867 skin_info
->lpVtbl
->AddRef(skin_info
);
1869 *new_mesh_container
= mesh_container
;
1873 destroy_mesh_container(mesh_container
);
1874 return E_OUTOFMEMORY
;
1877 static ID3DXAllocateHierarchyVtbl ID3DXAllocateHierarchyImpl_Vtbl
= {
1878 ID3DXAllocateHierarchyImpl_CreateFrame
,
1879 ID3DXAllocateHierarchyImpl_CreateMeshContainer
,
1880 ID3DXAllocateHierarchyImpl_DestroyFrame
,
1881 ID3DXAllocateHierarchyImpl_DestroyMeshContainer
,
1883 static ID3DXAllocateHierarchy alloc_hier
= { &ID3DXAllocateHierarchyImpl_Vtbl
};
1885 static void D3DXLoadMeshTest(void)
1887 static const char empty_xfile
[] = "xof 0303txt 0032";
1888 /*________________________*/
1889 static const char simple_xfile
[] =
1899 static const WORD simple_index_buffer
[] = {0, 1, 2};
1900 static const D3DXVECTOR3 simple_vertex_buffer
[] = {
1901 {0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {1.0, 1.0, 0.0}
1903 const DWORD simple_fvf
= D3DFVF_XYZ
;
1904 static const char framed_xfile
[] =
1907 "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;; }"
1908 "FrameTransformMatrix {" /* translation (0.0, 0.0, 2.0) */
1909 "1.0, 0.0, 0.0, 0.0,"
1910 "0.0, 1.0, 0.0, 0.0,"
1911 "0.0, 0.0, 1.0, 0.0,"
1912 "0.0, 0.0, 2.0, 1.0;;"
1914 "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;; }"
1915 "FrameTransformMatrix {" /* translation (0.0, 0.0, 3.0) */
1916 "1.0, 0.0, 0.0, 0.0,"
1917 "0.0, 1.0, 0.0, 0.0,"
1918 "0.0, 0.0, 1.0, 0.0,"
1919 "0.0, 0.0, 3.0, 1.0;;"
1921 "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;; }"
1923 static const WORD framed_index_buffer
[] = { 0, 1, 2 };
1924 static const D3DXVECTOR3 framed_vertex_buffers
[3][3] = {
1925 {{0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {1.0, 1.0, 0.0}},
1926 {{0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {2.0, 1.0, 0.0}},
1927 {{0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {3.0, 1.0, 0.0}},
1929 const DWORD framed_fvf
= D3DFVF_XYZ
;
1930 /*________________________*/
1931 static const char box_xfile
[] =
1934 "8;" /* DWORD nVertices; */
1935 /* array Vector vertices[nVertices]; */
1944 "6;" /* DWORD nFaces; */
1945 /* array MeshFace faces[nFaces]; */
1946 "4; 0, 1, 3, 2;," /* (left side) */
1947 "4; 2, 3, 7, 6;," /* (top side) */
1948 "4; 6, 7, 5, 4;," /* (right side) */
1949 "4; 1, 0, 4, 5;," /* (bottom side) */
1950 "4; 1, 5, 7, 3;," /* (back side) */
1951 "4; 0, 2, 6, 4;;" /* (front side) */
1953 "6;" /* DWORD nNormals; */
1954 /* array Vector normals[nNormals]; */
1961 "6;" /* DWORD nFaceNormals; */
1962 /* array MeshFace faceNormals[nFaceNormals]; */
1970 "MeshMaterialList materials {"
1971 "2;" /* DWORD nMaterials; */
1972 "6;" /* DWORD nFaceIndexes; */
1973 /* array DWORD faceIndexes[nFaceIndexes]; */
1974 "0, 0, 0, 1, 1, 1;;"
1976 /* ColorRGBA faceColor; */
1977 "0.0; 0.0; 1.0; 1.0;;"
1980 /* ColorRGB specularColor; */
1982 /* ColorRGB emissiveColor; */
1986 /* ColorRGBA faceColor; */
1987 "1.0; 1.0; 1.0; 1.0;;"
1990 /* ColorRGB specularColor; */
1992 /* ColorRGB emissiveColor; */
1994 "TextureFilename { \"texture.jpg\"; }"
1998 static const WORD box_index_buffer
[] = {
2012 static const struct {
2013 D3DXVECTOR3 position
;
2015 } box_vertex_buffer
[] = {
2016 {{0.0, 0.0, 0.0}, {-1.0, 0.0, 0.0}},
2017 {{0.0, 0.0, 1.0}, {-1.0, 0.0, 0.0}},
2018 {{0.0, 1.0, 0.0}, {-1.0, 0.0, 0.0}},
2019 {{0.0, 1.0, 1.0}, {-1.0, 0.0, 0.0}},
2020 {{1.0, 0.0, 0.0}, {1.0, 0.0, 0.0}},
2021 {{1.0, 0.0, 1.0}, {1.0, 0.0, 0.0}},
2022 {{1.0, 1.0, 0.0}, {0.0, 1.0, 0.0}},
2023 {{1.0, 1.0, 1.0}, {0.0, 1.0, 0.0}},
2024 {{0.0, 1.0, 0.0}, {0.0, 1.0, 0.0}},
2025 {{0.0, 1.0, 1.0}, {0.0, 1.0, 0.0}},
2026 {{1.0, 1.0, 0.0}, {1.0, 0.0, 0.0}},
2027 {{1.0, 1.0, 1.0}, {1.0, 0.0, 0.0}},
2028 {{0.0, 0.0, 1.0}, {0.0, -1.0, 0.0}},
2029 {{0.0, 0.0, 0.0}, {0.0, -1.0, 0.0}},
2030 {{1.0, 0.0, 0.0}, {0.0, -1.0, 0.0}},
2031 {{1.0, 0.0, 1.0}, {0.0, -1.0, 0.0}},
2032 {{0.0, 0.0, 1.0}, {0.0, 0.0, 1.0}},
2033 {{1.0, 0.0, 1.0}, {0.0, 0.0, 1.0}},
2034 {{1.0, 1.0, 1.0}, {0.0, 0.0, 1.0}},
2035 {{0.0, 1.0, 1.0}, {0.0, 0.0, 1.0}},
2036 {{0.0, 0.0, 0.0}, {0.0, 0.0, -1.0}},
2037 {{0.0, 1.0, 0.0}, {0.0, 0.0, -1.0}},
2038 {{1.0, 1.0, 0.0}, {0.0, 0.0, -1.0}},
2039 {{1.0, 0.0, 0.0}, {0.0, 0.0, -1.0}},
2041 static const D3DXMATERIAL box_materials
[] = {
2044 {0.0, 0.0, 1.0, 1.0}, /* Diffuse */
2045 {0.0, 0.0, 0.0, 1.0}, /* Ambient */
2046 {1.0, 1.0, 1.0, 1.0}, /* Specular */
2047 {0.0, 0.0, 0.0, 1.0}, /* Emissive */
2050 NULL
, /* pTextureFilename */
2054 {1.0, 1.0, 1.0, 1.0}, /* Diffuse */
2055 {0.0, 0.0, 0.0, 1.0}, /* Ambient */
2056 {1.0, 1.0, 1.0, 1.0}, /* Specular */
2057 {0.0, 0.0, 0.0, 1.0}, /* Emissive */
2060 (char *)"texture.jpg", /* pTextureFilename */
2063 const DWORD box_fvf
= D3DFVF_XYZ
| D3DFVF_NORMAL
;
2064 /*________________________*/
2067 IDirect3D9
*d3d
= NULL
;
2068 IDirect3DDevice9
*device
= NULL
;
2069 D3DPRESENT_PARAMETERS d3dpp
;
2070 ID3DXMesh
*mesh
= NULL
;
2071 D3DXFRAME
*frame_hier
= NULL
;
2072 D3DXMATRIX transform
;
2074 wnd
= CreateWindow("static", "d3dx9_test", WS_POPUP
, 0, 0, 1000, 1000, NULL
, NULL
, NULL
, NULL
);
2077 skip("Couldn't create application window\n");
2080 d3d
= Direct3DCreate9(D3D_SDK_VERSION
);
2083 skip("Couldn't create IDirect3D9 object\n");
2087 ZeroMemory(&d3dpp
, sizeof(d3dpp
));
2088 d3dpp
.Windowed
= TRUE
;
2089 d3dpp
.SwapEffect
= D3DSWAPEFFECT_DISCARD
;
2090 hr
= IDirect3D9_CreateDevice(d3d
, D3DADAPTER_DEFAULT
, D3DDEVTYPE_HAL
, wnd
, D3DCREATE_MIXED_VERTEXPROCESSING
, &d3dpp
, &device
);
2093 skip("Failed to create IDirect3DDevice9 object %#x\n", hr
);
2097 hr
= D3DXLoadMeshHierarchyFromXInMemory(NULL
, sizeof(simple_xfile
) - 1,
2098 D3DXMESH_MANAGED
, device
, &alloc_hier
, NULL
, &frame_hier
, NULL
);
2099 ok(hr
== D3DERR_INVALIDCALL
, "Expected D3DERR_INVALIDCALL, got %#x\n", hr
);
2101 hr
= D3DXLoadMeshHierarchyFromXInMemory(simple_xfile
, 0,
2102 D3DXMESH_MANAGED
, device
, &alloc_hier
, NULL
, &frame_hier
, NULL
);
2103 ok(hr
== D3DERR_INVALIDCALL
, "Expected D3DERR_INVALIDCALL, got %#x\n", hr
);
2105 hr
= D3DXLoadMeshHierarchyFromXInMemory(simple_xfile
, sizeof(simple_xfile
) - 1,
2106 D3DXMESH_MANAGED
, NULL
, &alloc_hier
, NULL
, &frame_hier
, NULL
);
2107 ok(hr
== D3DERR_INVALIDCALL
, "Expected D3DERR_INVALIDCALL, got %#x\n", hr
);
2109 hr
= D3DXLoadMeshHierarchyFromXInMemory(simple_xfile
, sizeof(simple_xfile
) - 1,
2110 D3DXMESH_MANAGED
, device
, NULL
, NULL
, &frame_hier
, NULL
);
2111 ok(hr
== D3DERR_INVALIDCALL
, "Expected D3DERR_INVALIDCALL, got %#x\n", hr
);
2113 hr
= D3DXLoadMeshHierarchyFromXInMemory(empty_xfile
, sizeof(empty_xfile
) - 1,
2114 D3DXMESH_MANAGED
, device
, &alloc_hier
, NULL
, &frame_hier
, NULL
);
2115 ok(hr
== E_FAIL
, "Expected E_FAIL, got %#x\n", hr
);
2117 hr
= D3DXLoadMeshHierarchyFromXInMemory(simple_xfile
, sizeof(simple_xfile
) - 1,
2118 D3DXMESH_MANAGED
, device
, &alloc_hier
, NULL
, NULL
, NULL
);
2119 ok(hr
== D3DERR_INVALIDCALL
, "Expected D3DERR_INVALIDCALL, got %#x\n", hr
);
2121 hr
= D3DXLoadMeshHierarchyFromXInMemory(simple_xfile
, sizeof(simple_xfile
) - 1,
2122 D3DXMESH_MANAGED
, device
, &alloc_hier
, NULL
, &frame_hier
, NULL
);
2123 ok(hr
== D3D_OK
, "Expected D3D_OK, got %#x\n", hr
);
2124 if (SUCCEEDED(hr
)) {
2125 D3DXMESHCONTAINER
*container
= frame_hier
->pMeshContainer
;
2127 ok(frame_hier
->Name
== NULL
, "Expected NULL, got '%s'\n", frame_hier
->Name
);
2128 D3DXMatrixIdentity(&transform
);
2129 check_matrix(&frame_hier
->TransformationMatrix
, &transform
);
2131 ok(!strcmp(container
->Name
, ""), "Expected '', got '%s'\n", container
->Name
);
2132 ok(container
->MeshData
.Type
== D3DXMESHTYPE_MESH
, "Expected %d, got %d\n",
2133 D3DXMESHTYPE_MESH
, container
->MeshData
.Type
);
2134 mesh
= U(container
->MeshData
).pMesh
;
2135 check_vertex_buffer(mesh
, simple_vertex_buffer
, ARRAY_SIZE(simple_vertex_buffer
), simple_fvf
);
2136 check_index_buffer(mesh
, simple_index_buffer
, ARRAY_SIZE(simple_index_buffer
), sizeof(*simple_index_buffer
));
2137 check_materials(container
->pMaterials
, container
->NumMaterials
, NULL
, 0);
2138 check_generated_effects(container
->pMaterials
, container
->NumMaterials
, container
->pEffects
);
2139 check_generated_adjacency(mesh
, container
->pAdjacency
, 0.0f
);
2140 hr
= D3DXFrameDestroy(frame_hier
, &alloc_hier
);
2141 ok(hr
== D3D_OK
, "Expected D3D_OK, got %#x\n", hr
);
2145 hr
= D3DXLoadMeshHierarchyFromXInMemory(box_xfile
, sizeof(box_xfile
) - 1,
2146 D3DXMESH_MANAGED
, device
, &alloc_hier
, NULL
, &frame_hier
, NULL
);
2147 ok(hr
== D3D_OK
, "Expected D3D_OK, got %#x\n", hr
);
2148 if (SUCCEEDED(hr
)) {
2149 D3DXMESHCONTAINER
*container
= frame_hier
->pMeshContainer
;
2151 ok(frame_hier
->Name
== NULL
, "Expected NULL, got '%s'\n", frame_hier
->Name
);
2152 D3DXMatrixIdentity(&transform
);
2153 check_matrix(&frame_hier
->TransformationMatrix
, &transform
);
2155 ok(!strcmp(container
->Name
, ""), "Expected '', got '%s'\n", container
->Name
);
2156 ok(container
->MeshData
.Type
== D3DXMESHTYPE_MESH
, "Expected %d, got %d\n",
2157 D3DXMESHTYPE_MESH
, container
->MeshData
.Type
);
2158 mesh
= U(container
->MeshData
).pMesh
;
2159 check_vertex_buffer(mesh
, box_vertex_buffer
, ARRAY_SIZE(box_vertex_buffer
), box_fvf
);
2160 check_index_buffer(mesh
, box_index_buffer
, ARRAY_SIZE(box_index_buffer
), sizeof(*box_index_buffer
));
2161 check_materials(container
->pMaterials
, container
->NumMaterials
, box_materials
, ARRAY_SIZE(box_materials
));
2162 check_generated_effects(container
->pMaterials
, container
->NumMaterials
, container
->pEffects
);
2163 check_generated_adjacency(mesh
, container
->pAdjacency
, 0.0f
);
2164 hr
= D3DXFrameDestroy(frame_hier
, &alloc_hier
);
2165 ok(hr
== D3D_OK
, "Expected D3D_OK, got %#x\n", hr
);
2169 hr
= D3DXLoadMeshHierarchyFromXInMemory(framed_xfile
, sizeof(framed_xfile
) - 1,
2170 D3DXMESH_MANAGED
, device
, &alloc_hier
, NULL
, &frame_hier
, NULL
);
2171 ok(hr
== D3D_OK
, "Expected D3D_OK, got %#x\n", hr
);
2172 if (SUCCEEDED(hr
)) {
2173 D3DXMESHCONTAINER
*container
= frame_hier
->pMeshContainer
;
2176 ok(!strcmp(frame_hier
->Name
, ""), "Expected '', got '%s'\n", frame_hier
->Name
);
2177 /* last frame transform replaces the first */
2178 D3DXMatrixIdentity(&transform
);
2179 U(transform
).m
[3][2] = 3.0;
2180 check_matrix(&frame_hier
->TransformationMatrix
, &transform
);
2182 for (i
= 0; i
< 3; i
++) {
2183 ok(!strcmp(container
->Name
, ""), "Expected '', got '%s'\n", container
->Name
);
2184 ok(container
->MeshData
.Type
== D3DXMESHTYPE_MESH
, "Expected %d, got %d\n",
2185 D3DXMESHTYPE_MESH
, container
->MeshData
.Type
);
2186 mesh
= U(container
->MeshData
).pMesh
;
2187 check_vertex_buffer(mesh
, framed_vertex_buffers
[i
], ARRAY_SIZE(framed_vertex_buffers
[0]), framed_fvf
);
2188 check_index_buffer(mesh
, framed_index_buffer
, ARRAY_SIZE(framed_index_buffer
), sizeof(*framed_index_buffer
));
2189 check_materials(container
->pMaterials
, container
->NumMaterials
, NULL
, 0);
2190 check_generated_effects(container
->pMaterials
, container
->NumMaterials
, container
->pEffects
);
2191 check_generated_adjacency(mesh
, container
->pAdjacency
, 0.0f
);
2192 container
= container
->pNextMeshContainer
;
2194 ok(container
== NULL
, "Expected NULL, got %p\n", container
);
2195 hr
= D3DXFrameDestroy(frame_hier
, &alloc_hier
);
2196 ok(hr
== D3D_OK
, "Expected D3D_OK, got %#x\n", hr
);
2201 if (device
) IDirect3DDevice9_Release(device
);
2202 if (d3d
) IDirect3D9_Release(d3d
);
2203 if (wnd
) DestroyWindow(wnd
);
2206 static void D3DXCreateBoxTest(void)
2212 IDirect3DDevice9
* device
;
2213 D3DPRESENT_PARAMETERS d3dpp
;
2215 ID3DXBuffer
* ppBuffer
;
2217 static const DWORD adjacency
[36]=
2223 1, 3, 11, 5, 6, 10};
2226 wc
.lpfnWndProc
= DefWindowProcA
;
2227 wc
.lpszClassName
= "d3dx9_test_wc";
2228 if (!RegisterClass(&wc
))
2230 skip("RegisterClass failed\n");
2234 wnd
= CreateWindow("d3dx9_test_wc", "d3dx9_test",
2235 WS_SYSMENU
| WS_POPUP
, 0, 0, 640, 480, 0, 0, 0, 0);
2236 ok(wnd
!= NULL
, "Expected to have a window, received NULL\n");
2239 skip("Couldn't create application window\n");
2243 d3d
= Direct3DCreate9(D3D_SDK_VERSION
);
2246 skip("Couldn't create IDirect3D9 object\n");
2251 memset(&d3dpp
, 0, sizeof(d3dpp
));
2252 d3dpp
.Windowed
= TRUE
;
2253 d3dpp
.SwapEffect
= D3DSWAPEFFECT_DISCARD
;
2254 hr
= IDirect3D9_CreateDevice(d3d
, D3DADAPTER_DEFAULT
, D3DDEVTYPE_HAL
, wnd
, D3DCREATE_MIXED_VERTEXPROCESSING
, &d3dpp
, &device
);
2257 skip("Failed to create IDirect3DDevice9 object %#x\n", hr
);
2258 IDirect3D9_Release(d3d
);
2263 hr
= D3DXCreateBuffer(36 * sizeof(DWORD
), &ppBuffer
);
2264 ok(hr
==D3D_OK
, "Expected D3D_OK, received %#x\n", hr
);
2265 if (FAILED(hr
)) goto end
;
2267 hr
= D3DXCreateBox(device
,2.0f
,20.0f
,4.9f
,NULL
, &ppBuffer
);
2268 todo_wine
ok(hr
==D3DERR_INVALIDCALL
, "Expected D3DERR_INVALIDCALL, received %#x\n", hr
);
2270 hr
= D3DXCreateBox(NULL
,22.0f
,20.0f
,4.9f
,&box
, &ppBuffer
);
2271 todo_wine
ok(hr
==D3DERR_INVALIDCALL
, "Expected D3DERR_INVALIDCALL, received %#x\n", hr
);
2273 hr
= D3DXCreateBox(device
,-2.0f
,20.0f
,4.9f
,&box
, &ppBuffer
);
2274 todo_wine
ok(hr
==D3DERR_INVALIDCALL
, "Expected D3DERR_INVALIDCALL, received %#x\n", hr
);
2276 hr
= D3DXCreateBox(device
,22.0f
,-20.0f
,4.9f
,&box
, &ppBuffer
);
2277 todo_wine
ok(hr
==D3DERR_INVALIDCALL
, "Expected D3DERR_INVALIDCALL, received %#x\n", hr
);
2279 hr
= D3DXCreateBox(device
,22.0f
,20.0f
,-4.9f
,&box
, &ppBuffer
);
2280 todo_wine
ok(hr
==D3DERR_INVALIDCALL
, "Expected D3DERR_INVALIDCALL, received %#x\n", hr
);
2282 hr
= D3DXCreateBox(device
,10.9f
,20.0f
,4.9f
,&box
, &ppBuffer
);
2283 todo_wine
ok(hr
==D3D_OK
, "Expected D3D_OK, received %#x\n", hr
);
2287 skip("D3DXCreateBox failed\n");
2291 buffer
= ID3DXBuffer_GetBufferPointer(ppBuffer
);
2293 todo_wine
ok(adjacency
[i
]==buffer
[i
], "expected adjacency %d: %#x, received %#x\n",i
,adjacency
[i
], buffer
[i
]);
2295 box
->lpVtbl
->Release(box
);
2298 IDirect3DDevice9_Release(device
);
2299 IDirect3D9_Release(d3d
);
2300 ID3DXBuffer_Release(ppBuffer
);
2310 static void free_sincos_table(struct sincos_table
*sincos_table
)
2312 HeapFree(GetProcessHeap(), 0, sincos_table
->cos
);
2313 HeapFree(GetProcessHeap(), 0, sincos_table
->sin
);
2316 /* pre compute sine and cosine tables; caller must free */
2317 static BOOL
compute_sincos_table(struct sincos_table
*sincos_table
, float angle_start
, float angle_step
, int n
)
2322 sincos_table
->sin
= HeapAlloc(GetProcessHeap(), 0, n
* sizeof(*sincos_table
->sin
));
2323 if (!sincos_table
->sin
)
2327 sincos_table
->cos
= HeapAlloc(GetProcessHeap(), 0, n
* sizeof(*sincos_table
->cos
));
2328 if (!sincos_table
->cos
)
2330 HeapFree(GetProcessHeap(), 0, sincos_table
->sin
);
2334 angle
= angle_start
;
2335 for (i
= 0; i
< n
; i
++)
2337 sincos_table
->sin
[i
] = sin(angle
);
2338 sincos_table
->cos
[i
] = cos(angle
);
2339 angle
+= angle_step
;
2345 static WORD
vertex_index(UINT slices
, int slice
, int stack
)
2347 return stack
*slices
+slice
+1;
2350 /* slices = subdivisions along xy plane, stacks = subdivisions along z axis */
2351 static BOOL
compute_sphere(struct mesh
*mesh
, FLOAT radius
, UINT slices
, UINT stacks
)
2353 float theta_step
, theta_start
;
2354 struct sincos_table theta
;
2355 float phi_step
, phi_start
;
2356 struct sincos_table phi
;
2357 DWORD number_of_vertices
, number_of_faces
;
2361 /* theta = angle on xy plane wrt x axis */
2362 theta_step
= M_PI
/ stacks
;
2363 theta_start
= theta_step
;
2365 /* phi = angle on xz plane wrt z axis */
2366 phi_step
= -2 * M_PI
/ slices
;
2367 phi_start
= M_PI
/ 2;
2369 if (!compute_sincos_table(&theta
, theta_start
, theta_step
, stacks
))
2373 if (!compute_sincos_table(&phi
, phi_start
, phi_step
, slices
))
2375 free_sincos_table(&theta
);
2379 number_of_vertices
= 2 + slices
* (stacks
-1);
2380 number_of_faces
= 2 * slices
+ (stacks
- 2) * (2 * slices
);
2382 if (!new_mesh(mesh
, number_of_vertices
, number_of_faces
))
2384 free_sincos_table(&phi
);
2385 free_sincos_table(&theta
);
2392 mesh
->vertices
[vertex
].normal
.x
= 0.0f
;
2393 mesh
->vertices
[vertex
].normal
.y
= 0.0f
;
2394 mesh
->vertices
[vertex
].normal
.z
= 1.0f
;
2395 mesh
->vertices
[vertex
].position
.x
= 0.0f
;
2396 mesh
->vertices
[vertex
].position
.y
= 0.0f
;
2397 mesh
->vertices
[vertex
].position
.z
= radius
;
2400 for (stack
= 0; stack
< stacks
- 1; stack
++)
2402 for (slice
= 0; slice
< slices
; slice
++)
2404 mesh
->vertices
[vertex
].normal
.x
= theta
.sin
[stack
] * phi
.cos
[slice
];
2405 mesh
->vertices
[vertex
].normal
.y
= theta
.sin
[stack
] * phi
.sin
[slice
];
2406 mesh
->vertices
[vertex
].normal
.z
= theta
.cos
[stack
];
2407 mesh
->vertices
[vertex
].position
.x
= radius
* theta
.sin
[stack
] * phi
.cos
[slice
];
2408 mesh
->vertices
[vertex
].position
.y
= radius
* theta
.sin
[stack
] * phi
.sin
[slice
];
2409 mesh
->vertices
[vertex
].position
.z
= radius
* theta
.cos
[stack
];
2416 /* top stack is triangle fan */
2417 mesh
->faces
[face
][0] = 0;
2418 mesh
->faces
[face
][1] = slice
+ 1;
2419 mesh
->faces
[face
][2] = slice
;
2424 /* stacks in between top and bottom are quad strips */
2425 mesh
->faces
[face
][0] = vertex_index(slices
, slice
-1, stack
-1);
2426 mesh
->faces
[face
][1] = vertex_index(slices
, slice
, stack
-1);
2427 mesh
->faces
[face
][2] = vertex_index(slices
, slice
-1, stack
);
2430 mesh
->faces
[face
][0] = vertex_index(slices
, slice
, stack
-1);
2431 mesh
->faces
[face
][1] = vertex_index(slices
, slice
, stack
);
2432 mesh
->faces
[face
][2] = vertex_index(slices
, slice
-1, stack
);
2440 mesh
->faces
[face
][0] = 0;
2441 mesh
->faces
[face
][1] = 1;
2442 mesh
->faces
[face
][2] = slice
;
2447 mesh
->faces
[face
][0] = vertex_index(slices
, slice
-1, stack
-1);
2448 mesh
->faces
[face
][1] = vertex_index(slices
, 0, stack
-1);
2449 mesh
->faces
[face
][2] = vertex_index(slices
, slice
-1, stack
);
2452 mesh
->faces
[face
][0] = vertex_index(slices
, 0, stack
-1);
2453 mesh
->faces
[face
][1] = vertex_index(slices
, 0, stack
);
2454 mesh
->faces
[face
][2] = vertex_index(slices
, slice
-1, stack
);
2459 mesh
->vertices
[vertex
].position
.x
= 0.0f
;
2460 mesh
->vertices
[vertex
].position
.y
= 0.0f
;
2461 mesh
->vertices
[vertex
].position
.z
= -radius
;
2462 mesh
->vertices
[vertex
].normal
.x
= 0.0f
;
2463 mesh
->vertices
[vertex
].normal
.y
= 0.0f
;
2464 mesh
->vertices
[vertex
].normal
.z
= -1.0f
;
2466 /* bottom stack is triangle fan */
2467 for (slice
= 1; slice
< slices
; slice
++)
2469 mesh
->faces
[face
][0] = vertex_index(slices
, slice
-1, stack
-1);
2470 mesh
->faces
[face
][1] = vertex_index(slices
, slice
, stack
-1);
2471 mesh
->faces
[face
][2] = vertex
;
2475 mesh
->faces
[face
][0] = vertex_index(slices
, slice
-1, stack
-1);
2476 mesh
->faces
[face
][1] = vertex_index(slices
, 0, stack
-1);
2477 mesh
->faces
[face
][2] = vertex
;
2479 free_sincos_table(&phi
);
2480 free_sincos_table(&theta
);
2485 static void test_sphere(IDirect3DDevice9
*device
, FLOAT radius
, UINT slices
, UINT stacks
)
2492 hr
= D3DXCreateSphere(device
, radius
, slices
, stacks
, &sphere
, NULL
);
2493 ok(hr
== D3D_OK
, "Got result %x, expected 0 (D3D_OK)\n", hr
);
2496 skip("Couldn't create sphere\n");
2500 if (!compute_sphere(&mesh
, radius
, slices
, stacks
))
2502 skip("Couldn't create mesh\n");
2503 sphere
->lpVtbl
->Release(sphere
);
2507 mesh
.fvf
= D3DFVF_XYZ
| D3DFVF_NORMAL
;
2509 sprintf(name
, "sphere (%g, %u, %u)", radius
, slices
, stacks
);
2510 compare_mesh(name
, sphere
, &mesh
);
2514 sphere
->lpVtbl
->Release(sphere
);
2517 static void D3DXCreateSphereTest(void)
2522 IDirect3DDevice9
* device
;
2523 D3DPRESENT_PARAMETERS d3dpp
;
2524 ID3DXMesh
* sphere
= NULL
;
2526 hr
= D3DXCreateSphere(NULL
, 0.0f
, 0, 0, NULL
, NULL
);
2527 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr
,D3DERR_INVALIDCALL
);
2529 hr
= D3DXCreateSphere(NULL
, 0.1f
, 0, 0, NULL
, NULL
);
2530 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr
,D3DERR_INVALIDCALL
);
2532 hr
= D3DXCreateSphere(NULL
, 0.0f
, 1, 0, NULL
, NULL
);
2533 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr
,D3DERR_INVALIDCALL
);
2535 hr
= D3DXCreateSphere(NULL
, 0.0f
, 0, 1, NULL
, NULL
);
2536 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr
,D3DERR_INVALIDCALL
);
2538 wnd
= CreateWindow("static", "d3dx9_test", 0, 0, 0, 0, 0, NULL
, NULL
, NULL
, NULL
);
2539 d3d
= Direct3DCreate9(D3D_SDK_VERSION
);
2542 skip("Couldn't create application window\n");
2547 skip("Couldn't create IDirect3D9 object\n");
2552 ZeroMemory(&d3dpp
, sizeof(d3dpp
));
2553 d3dpp
.Windowed
= TRUE
;
2554 d3dpp
.SwapEffect
= D3DSWAPEFFECT_DISCARD
;
2555 hr
= IDirect3D9_CreateDevice(d3d
, D3DADAPTER_DEFAULT
, D3DDEVTYPE_HAL
, wnd
, D3DCREATE_MIXED_VERTEXPROCESSING
, &d3dpp
, &device
);
2558 skip("Failed to create IDirect3DDevice9 object %#x\n", hr
);
2559 IDirect3D9_Release(d3d
);
2564 hr
= D3DXCreateSphere(device
, 1.0f
, 1, 1, &sphere
, NULL
);
2565 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr
,D3DERR_INVALIDCALL
);
2567 hr
= D3DXCreateSphere(device
, 1.0f
, 2, 1, &sphere
, NULL
);
2568 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr
, D3DERR_INVALIDCALL
);
2570 hr
= D3DXCreateSphere(device
, 1.0f
, 1, 2, &sphere
, NULL
);
2571 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr
, D3DERR_INVALIDCALL
);
2573 hr
= D3DXCreateSphere(device
, -0.1f
, 1, 2, &sphere
, NULL
);
2574 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr
, D3DERR_INVALIDCALL
);
2576 test_sphere(device
, 0.0f
, 2, 2);
2577 test_sphere(device
, 1.0f
, 2, 2);
2578 test_sphere(device
, 1.0f
, 3, 2);
2579 test_sphere(device
, 1.0f
, 4, 4);
2580 test_sphere(device
, 1.0f
, 3, 4);
2581 test_sphere(device
, 5.0f
, 6, 7);
2582 test_sphere(device
, 10.0f
, 11, 12);
2584 IDirect3DDevice9_Release(device
);
2585 IDirect3D9_Release(d3d
);
2589 static BOOL
compute_cylinder(struct mesh
*mesh
, FLOAT radius1
, FLOAT radius2
, FLOAT length
, UINT slices
, UINT stacks
)
2591 float theta_step
, theta_start
;
2592 struct sincos_table theta
;
2593 FLOAT delta_radius
, radius
, radius_step
;
2594 FLOAT z
, z_step
, z_normal
;
2595 DWORD number_of_vertices
, number_of_faces
;
2599 /* theta = angle on xy plane wrt x axis */
2600 theta_step
= -2 * M_PI
/ slices
;
2601 theta_start
= M_PI
/ 2;
2603 if (!compute_sincos_table(&theta
, theta_start
, theta_step
, slices
))
2608 number_of_vertices
= 2 + (slices
* (3 + stacks
));
2609 number_of_faces
= 2 * slices
+ stacks
* (2 * slices
);
2611 if (!new_mesh(mesh
, number_of_vertices
, number_of_faces
))
2613 free_sincos_table(&theta
);
2620 delta_radius
= radius1
- radius2
;
2622 radius_step
= delta_radius
/ stacks
;
2625 z_step
= length
/ stacks
;
2626 z_normal
= delta_radius
/ length
;
2627 if (isnan(z_normal
))
2632 mesh
->vertices
[vertex
].normal
.x
= 0.0f
;
2633 mesh
->vertices
[vertex
].normal
.y
= 0.0f
;
2634 mesh
->vertices
[vertex
].normal
.z
= -1.0f
;
2635 mesh
->vertices
[vertex
].position
.x
= 0.0f
;
2636 mesh
->vertices
[vertex
].position
.y
= 0.0f
;
2637 mesh
->vertices
[vertex
++].position
.z
= z
;
2639 for (slice
= 0; slice
< slices
; slice
++, vertex
++)
2641 mesh
->vertices
[vertex
].normal
.x
= 0.0f
;
2642 mesh
->vertices
[vertex
].normal
.y
= 0.0f
;
2643 mesh
->vertices
[vertex
].normal
.z
= -1.0f
;
2644 mesh
->vertices
[vertex
].position
.x
= radius
* theta
.cos
[slice
];
2645 mesh
->vertices
[vertex
].position
.y
= radius
* theta
.sin
[slice
];
2646 mesh
->vertices
[vertex
].position
.z
= z
;
2650 mesh
->faces
[face
][0] = 0;
2651 mesh
->faces
[face
][1] = slice
;
2652 mesh
->faces
[face
++][2] = slice
+ 1;
2656 mesh
->faces
[face
][0] = 0;
2657 mesh
->faces
[face
][1] = slice
;
2658 mesh
->faces
[face
++][2] = 1;
2660 for (stack
= 1; stack
<= stacks
+1; stack
++)
2662 for (slice
= 0; slice
< slices
; slice
++, vertex
++)
2664 mesh
->vertices
[vertex
].normal
.x
= theta
.cos
[slice
];
2665 mesh
->vertices
[vertex
].normal
.y
= theta
.sin
[slice
];
2666 mesh
->vertices
[vertex
].normal
.z
= z_normal
;
2667 D3DXVec3Normalize(&mesh
->vertices
[vertex
].normal
, &mesh
->vertices
[vertex
].normal
);
2668 mesh
->vertices
[vertex
].position
.x
= radius
* theta
.cos
[slice
];
2669 mesh
->vertices
[vertex
].position
.y
= radius
* theta
.sin
[slice
];
2670 mesh
->vertices
[vertex
].position
.z
= z
;
2672 if (stack
> 1 && slice
> 0)
2674 mesh
->faces
[face
][0] = vertex_index(slices
, slice
-1, stack
-1);
2675 mesh
->faces
[face
][1] = vertex_index(slices
, slice
-1, stack
);
2676 mesh
->faces
[face
++][2] = vertex_index(slices
, slice
, stack
-1);
2678 mesh
->faces
[face
][0] = vertex_index(slices
, slice
, stack
-1);
2679 mesh
->faces
[face
][1] = vertex_index(slices
, slice
-1, stack
);
2680 mesh
->faces
[face
++][2] = vertex_index(slices
, slice
, stack
);
2686 mesh
->faces
[face
][0] = vertex_index(slices
, slice
-1, stack
-1);
2687 mesh
->faces
[face
][1] = vertex_index(slices
, slice
-1, stack
);
2688 mesh
->faces
[face
++][2] = vertex_index(slices
, 0, stack
-1);
2690 mesh
->faces
[face
][0] = vertex_index(slices
, 0, stack
-1);
2691 mesh
->faces
[face
][1] = vertex_index(slices
, slice
-1, stack
);
2692 mesh
->faces
[face
++][2] = vertex_index(slices
, 0, stack
);
2695 if (stack
< stacks
+ 1)
2698 radius
-= radius_step
;
2702 for (slice
= 0; slice
< slices
; slice
++, vertex
++)
2704 mesh
->vertices
[vertex
].normal
.x
= 0.0f
;
2705 mesh
->vertices
[vertex
].normal
.y
= 0.0f
;
2706 mesh
->vertices
[vertex
].normal
.z
= 1.0f
;
2707 mesh
->vertices
[vertex
].position
.x
= radius
* theta
.cos
[slice
];
2708 mesh
->vertices
[vertex
].position
.y
= radius
* theta
.sin
[slice
];
2709 mesh
->vertices
[vertex
].position
.z
= z
;
2713 mesh
->faces
[face
][0] = vertex_index(slices
, slice
-1, stack
);
2714 mesh
->faces
[face
][1] = number_of_vertices
- 1;
2715 mesh
->faces
[face
++][2] = vertex_index(slices
, slice
, stack
);
2719 mesh
->vertices
[vertex
].position
.x
= 0.0f
;
2720 mesh
->vertices
[vertex
].position
.y
= 0.0f
;
2721 mesh
->vertices
[vertex
].position
.z
= z
;
2722 mesh
->vertices
[vertex
].normal
.x
= 0.0f
;
2723 mesh
->vertices
[vertex
].normal
.y
= 0.0f
;
2724 mesh
->vertices
[vertex
].normal
.z
= 1.0f
;
2726 mesh
->faces
[face
][0] = vertex_index(slices
, slice
-1, stack
);
2727 mesh
->faces
[face
][1] = number_of_vertices
- 1;
2728 mesh
->faces
[face
][2] = vertex_index(slices
, 0, stack
);
2730 free_sincos_table(&theta
);
2735 static void test_cylinder(IDirect3DDevice9
*device
, FLOAT radius1
, FLOAT radius2
, FLOAT length
, UINT slices
, UINT stacks
)
2738 ID3DXMesh
*cylinder
;
2742 hr
= D3DXCreateCylinder(device
, radius1
, radius2
, length
, slices
, stacks
, &cylinder
, NULL
);
2743 ok(hr
== D3D_OK
, "Got result %x, expected 0 (D3D_OK)\n", hr
);
2746 skip("Couldn't create cylinder\n");
2750 if (!compute_cylinder(&mesh
, radius1
, radius2
, length
, slices
, stacks
))
2752 skip("Couldn't create mesh\n");
2753 cylinder
->lpVtbl
->Release(cylinder
);
2757 mesh
.fvf
= D3DFVF_XYZ
| D3DFVF_NORMAL
;
2759 sprintf(name
, "cylinder (%g, %g, %g, %u, %u)", radius1
, radius2
, length
, slices
, stacks
);
2760 compare_mesh(name
, cylinder
, &mesh
);
2764 cylinder
->lpVtbl
->Release(cylinder
);
2767 static void D3DXCreateCylinderTest(void)
2772 IDirect3DDevice9
* device
;
2773 D3DPRESENT_PARAMETERS d3dpp
;
2774 ID3DXMesh
* cylinder
= NULL
;
2776 hr
= D3DXCreateCylinder(NULL
, 0.0f
, 0.0f
, 0.0f
, 0, 0, NULL
, NULL
);
2777 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr
,D3DERR_INVALIDCALL
);
2779 hr
= D3DXCreateCylinder(NULL
, 1.0f
, 1.0f
, 1.0f
, 2, 1, &cylinder
, NULL
);
2780 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr
,D3DERR_INVALIDCALL
);
2782 wnd
= CreateWindow("static", "d3dx9_test", 0, 0, 0, 0, 0, NULL
, NULL
, NULL
, NULL
);
2783 d3d
= Direct3DCreate9(D3D_SDK_VERSION
);
2786 skip("Couldn't create application window\n");
2791 skip("Couldn't create IDirect3D9 object\n");
2796 ZeroMemory(&d3dpp
, sizeof(d3dpp
));
2797 d3dpp
.Windowed
= TRUE
;
2798 d3dpp
.SwapEffect
= D3DSWAPEFFECT_DISCARD
;
2799 hr
= IDirect3D9_CreateDevice(d3d
, D3DADAPTER_DEFAULT
, D3DDEVTYPE_HAL
, wnd
, D3DCREATE_MIXED_VERTEXPROCESSING
, &d3dpp
, &device
);
2802 skip("Failed to create IDirect3DDevice9 object %#x\n", hr
);
2803 IDirect3D9_Release(d3d
);
2808 hr
= D3DXCreateCylinder(device
, -0.1f
, 1.0f
, 1.0f
, 2, 1, &cylinder
, NULL
);
2809 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr
,D3DERR_INVALIDCALL
);
2811 hr
= D3DXCreateCylinder(device
, 0.0f
, 1.0f
, 1.0f
, 2, 1, &cylinder
, NULL
);
2812 ok(hr
== D3D_OK
, "Got result %x, expected 0 (D3D_OK)\n",hr
);
2814 if (SUCCEEDED(hr
) && cylinder
)
2816 cylinder
->lpVtbl
->Release(cylinder
);
2819 hr
= D3DXCreateCylinder(device
, 1.0f
, -0.1f
, 1.0f
, 2, 1, &cylinder
, NULL
);
2820 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr
,D3DERR_INVALIDCALL
);
2822 hr
= D3DXCreateCylinder(device
, 1.0f
, 0.0f
, 1.0f
, 2, 1, &cylinder
, NULL
);
2823 ok(hr
== D3D_OK
, "Got result %x, expected 0 (D3D_OK)\n",hr
);
2825 if (SUCCEEDED(hr
) && cylinder
)
2827 cylinder
->lpVtbl
->Release(cylinder
);
2830 hr
= D3DXCreateCylinder(device
, 1.0f
, 1.0f
, -0.1f
, 2, 1, &cylinder
, NULL
);
2831 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr
,D3DERR_INVALIDCALL
);
2833 /* Test with length == 0.0f succeeds */
2834 hr
= D3DXCreateCylinder(device
, 1.0f
, 1.0f
, 0.0f
, 2, 1, &cylinder
, NULL
);
2835 ok(hr
== D3D_OK
, "Got result %x, expected 0 (D3D_OK)\n",hr
);
2837 if (SUCCEEDED(hr
) && cylinder
)
2839 cylinder
->lpVtbl
->Release(cylinder
);
2842 hr
= D3DXCreateCylinder(device
, 1.0f
, 1.0f
, 1.0f
, 1, 1, &cylinder
, NULL
);
2843 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr
,D3DERR_INVALIDCALL
);
2845 hr
= D3DXCreateCylinder(device
, 1.0f
, 1.0f
, 1.0f
, 2, 0, &cylinder
, NULL
);
2846 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr
,D3DERR_INVALIDCALL
);
2848 hr
= D3DXCreateCylinder(device
, 1.0f
, 1.0f
, 1.0f
, 2, 1, NULL
, NULL
);
2849 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr
,D3DERR_INVALIDCALL
);
2851 test_cylinder(device
, 0.0f
, 0.0f
, 0.0f
, 2, 1);
2852 test_cylinder(device
, 1.0f
, 1.0f
, 1.0f
, 2, 1);
2853 test_cylinder(device
, 1.0f
, 1.0f
, 2.0f
, 3, 4);
2854 test_cylinder(device
, 3.0f
, 2.0f
, 4.0f
, 3, 4);
2855 test_cylinder(device
, 2.0f
, 3.0f
, 4.0f
, 3, 4);
2856 test_cylinder(device
, 3.0f
, 4.0f
, 5.0f
, 11, 20);
2858 IDirect3DDevice9_Release(device
);
2859 IDirect3D9_Release(d3d
);
2863 struct dynamic_array
2865 int count
, capacity
;
2870 POINTTYPE_CURVE
= 0,
2872 POINTTYPE_CURVE_START
,
2873 POINTTYPE_CURVE_END
,
2874 POINTTYPE_CURVE_MIDDLE
,
2880 enum pointtype corner
;
2883 /* is a dynamic_array */
2886 int count
, capacity
;
2887 struct point2d
*items
;
2890 /* is a dynamic_array */
2891 struct outline_array
2893 int count
, capacity
;
2894 struct outline
*items
;
2899 struct outline_array outlines
;
2903 static BOOL
reserve(struct dynamic_array
*array
, int count
, int itemsize
)
2905 if (count
> array
->capacity
) {
2908 if (array
->items
&& array
->capacity
) {
2909 new_capacity
= max(array
->capacity
* 2, count
);
2910 new_buffer
= HeapReAlloc(GetProcessHeap(), 0, array
->items
, new_capacity
* itemsize
);
2912 new_capacity
= max(16, count
);
2913 new_buffer
= HeapAlloc(GetProcessHeap(), 0, new_capacity
* itemsize
);
2917 array
->items
= new_buffer
;
2918 array
->capacity
= new_capacity
;
2923 static struct point2d
*add_point(struct outline
*array
)
2925 struct point2d
*item
;
2927 if (!reserve((struct dynamic_array
*)array
, array
->count
+ 1, sizeof(array
->items
[0])))
2930 item
= &array
->items
[array
->count
++];
2931 ZeroMemory(item
, sizeof(*item
));
2935 static struct outline
*add_outline(struct outline_array
*array
)
2937 struct outline
*item
;
2939 if (!reserve((struct dynamic_array
*)array
, array
->count
+ 1, sizeof(array
->items
[0])))
2942 item
= &array
->items
[array
->count
++];
2943 ZeroMemory(item
, sizeof(*item
));
2947 static inline D3DXVECTOR2
*convert_fixed_to_float(POINTFX
*pt
, int count
, float emsquare
)
2949 D3DXVECTOR2
*ret
= (D3DXVECTOR2
*)pt
;
2951 D3DXVECTOR2
*pt_flt
= (D3DXVECTOR2
*)pt
;
2952 pt_flt
->x
= (pt
->x
.value
+ pt
->x
.fract
/ (float)0x10000) / emsquare
;
2953 pt_flt
->y
= (pt
->y
.value
+ pt
->y
.fract
/ (float)0x10000) / emsquare
;
2959 static HRESULT
add_bezier_points(struct outline
*outline
, const D3DXVECTOR2
*p1
,
2960 const D3DXVECTOR2
*p2
, const D3DXVECTOR2
*p3
,
2961 float max_deviation
)
2963 D3DXVECTOR2 split1
= {0, 0}, split2
= {0, 0}, middle
, vec
;
2966 D3DXVec2Scale(&split1
, D3DXVec2Add(&split1
, p1
, p2
), 0.5f
);
2967 D3DXVec2Scale(&split2
, D3DXVec2Add(&split2
, p2
, p3
), 0.5f
);
2968 D3DXVec2Scale(&middle
, D3DXVec2Add(&middle
, &split1
, &split2
), 0.5f
);
2970 deviation
= D3DXVec2Length(D3DXVec2Subtract(&vec
, &middle
, p2
));
2971 if (deviation
< max_deviation
) {
2972 struct point2d
*pt
= add_point(outline
);
2973 if (!pt
) return E_OUTOFMEMORY
;
2975 pt
->corner
= POINTTYPE_CURVE
;
2976 /* the end point is omitted because the end line merges into the next segment of
2977 * the split bezier curve, and the end of the split bezier curve is added outside
2978 * this recursive function. */
2980 HRESULT hr
= add_bezier_points(outline
, p1
, &split1
, &middle
, max_deviation
);
2981 if (hr
!= S_OK
) return hr
;
2982 hr
= add_bezier_points(outline
, &middle
, &split2
, p3
, max_deviation
);
2983 if (hr
!= S_OK
) return hr
;
2989 static inline BOOL
is_direction_similar(D3DXVECTOR2
*dir1
, D3DXVECTOR2
*dir2
, float cos_theta
)
2991 /* dot product = cos(theta) */
2992 return D3DXVec2Dot(dir1
, dir2
) > cos_theta
;
2995 static inline D3DXVECTOR2
*unit_vec2(D3DXVECTOR2
*dir
, const D3DXVECTOR2
*pt1
, const D3DXVECTOR2
*pt2
)
2997 return D3DXVec2Normalize(D3DXVec2Subtract(dir
, pt2
, pt1
), dir
);
3000 static BOOL
attempt_line_merge(struct outline
*outline
,
3002 const D3DXVECTOR2
*nextpt
,
3005 D3DXVECTOR2 curdir
, lastdir
;
3006 struct point2d
*prevpt
, *pt
;
3008 const float cos_half
= cos(D3DXToRadian(0.5f
));
3010 pt
= &outline
->items
[pt_index
];
3011 pt_index
= (pt_index
- 1 + outline
->count
) % outline
->count
;
3012 prevpt
= &outline
->items
[pt_index
];
3015 pt
->corner
= pt
->corner
!= POINTTYPE_CORNER
? POINTTYPE_CURVE_MIDDLE
: POINTTYPE_CURVE_START
;
3017 if (outline
->count
< 2)
3020 /* remove last point if the next line continues the last line */
3021 unit_vec2(&lastdir
, &prevpt
->pos
, &pt
->pos
);
3022 unit_vec2(&curdir
, &pt
->pos
, nextpt
);
3023 if (is_direction_similar(&lastdir
, &curdir
, cos_half
))
3026 if (pt
->corner
== POINTTYPE_CURVE_END
)
3027 prevpt
->corner
= pt
->corner
;
3028 if (prevpt
->corner
== POINTTYPE_CURVE_END
&& to_curve
)
3029 prevpt
->corner
= POINTTYPE_CURVE_MIDDLE
;
3033 if (outline
->count
< 2)
3036 pt_index
= (pt_index
- 1 + outline
->count
) % outline
->count
;
3037 prevpt
= &outline
->items
[pt_index
];
3038 unit_vec2(&lastdir
, &prevpt
->pos
, &pt
->pos
);
3039 unit_vec2(&curdir
, &pt
->pos
, nextpt
);
3044 static HRESULT
create_outline(struct glyphinfo
*glyph
, void *raw_outline
, int datasize
,
3045 float max_deviation
, float emsquare
)
3047 const float cos_45
= cos(D3DXToRadian(45.0f
));
3048 const float cos_90
= cos(D3DXToRadian(90.0f
));
3049 TTPOLYGONHEADER
*header
= (TTPOLYGONHEADER
*)raw_outline
;
3051 while ((char *)header
< (char *)raw_outline
+ datasize
)
3053 TTPOLYCURVE
*curve
= (TTPOLYCURVE
*)(header
+ 1);
3054 struct point2d
*lastpt
, *pt
;
3055 D3DXVECTOR2 lastdir
;
3056 D3DXVECTOR2
*pt_flt
;
3058 struct outline
*outline
= add_outline(&glyph
->outlines
);
3061 return E_OUTOFMEMORY
;
3063 pt
= add_point(outline
);
3065 return E_OUTOFMEMORY
;
3066 pt_flt
= convert_fixed_to_float(&header
->pfxStart
, 1, emsquare
);
3068 pt
->corner
= POINTTYPE_CORNER
;
3070 if (header
->dwType
!= TT_POLYGON_TYPE
)
3071 trace("Unknown header type %d\n", header
->dwType
);
3073 while ((char *)curve
< (char *)header
+ header
->cb
)
3075 D3DXVECTOR2 bezier_start
= outline
->items
[outline
->count
- 1].pos
;
3076 BOOL to_curve
= curve
->wType
!= TT_PRIM_LINE
&& curve
->cpfx
> 1;
3079 curve
= (TTPOLYCURVE
*)&curve
->apfx
[curve
->cpfx
];
3083 pt_flt
= convert_fixed_to_float(curve
->apfx
, curve
->cpfx
, emsquare
);
3085 attempt_line_merge(outline
, outline
->count
- 1, &pt_flt
[0], to_curve
);
3090 int count
= curve
->cpfx
;
3095 D3DXVECTOR2 bezier_end
;
3097 D3DXVec2Scale(&bezier_end
, D3DXVec2Add(&bezier_end
, &pt_flt
[j
], &pt_flt
[j
+1]), 0.5f
);
3098 hr
= add_bezier_points(outline
, &bezier_start
, &pt_flt
[j
], &bezier_end
, max_deviation
);
3101 bezier_start
= bezier_end
;
3105 hr
= add_bezier_points(outline
, &bezier_start
, &pt_flt
[j
], &pt_flt
[j
+1], max_deviation
);
3109 pt
= add_point(outline
);
3111 return E_OUTOFMEMORY
;
3113 pt
->pos
= pt_flt
[j
];
3114 pt
->corner
= POINTTYPE_CURVE_END
;
3116 for (j
= 0; j
< curve
->cpfx
; j
++)
3118 pt
= add_point(outline
);
3120 return E_OUTOFMEMORY
;
3121 pt
->pos
= pt_flt
[j
];
3122 pt
->corner
= POINTTYPE_CORNER
;
3126 curve
= (TTPOLYCURVE
*)&curve
->apfx
[curve
->cpfx
];
3129 /* remove last point if the next line continues the last line */
3130 if (outline
->count
>= 3) {
3133 lastpt
= &outline
->items
[outline
->count
- 1];
3134 pt
= &outline
->items
[0];
3135 if (pt
->pos
.x
== lastpt
->pos
.x
&& pt
->pos
.y
== lastpt
->pos
.y
) {
3136 if (lastpt
->corner
== POINTTYPE_CURVE_END
)
3138 if (pt
->corner
== POINTTYPE_CURVE_START
)
3139 pt
->corner
= POINTTYPE_CURVE_MIDDLE
;
3141 pt
->corner
= POINTTYPE_CURVE_END
;
3144 lastpt
= &outline
->items
[outline
->count
- 1];
3146 /* outline closed with a line from end to start point */
3147 attempt_line_merge(outline
, outline
->count
- 1, &pt
->pos
, FALSE
);
3149 lastpt
= &outline
->items
[0];
3150 to_curve
= lastpt
->corner
!= POINTTYPE_CORNER
&& lastpt
->corner
!= POINTTYPE_CURVE_END
;
3151 if (lastpt
->corner
== POINTTYPE_CURVE_START
)
3152 lastpt
->corner
= POINTTYPE_CORNER
;
3153 pt
= &outline
->items
[1];
3154 if (attempt_line_merge(outline
, 0, &pt
->pos
, to_curve
))
3155 *lastpt
= outline
->items
[outline
->count
];
3158 lastpt
= &outline
->items
[outline
->count
- 1];
3159 pt
= &outline
->items
[0];
3160 unit_vec2(&lastdir
, &lastpt
->pos
, &pt
->pos
);
3161 for (j
= 0; j
< outline
->count
; j
++)
3166 pt
= &outline
->items
[(j
+ 1) % outline
->count
];
3167 unit_vec2(&curdir
, &lastpt
->pos
, &pt
->pos
);
3169 switch (lastpt
->corner
)
3171 case POINTTYPE_CURVE_START
:
3172 case POINTTYPE_CURVE_END
:
3173 if (!is_direction_similar(&lastdir
, &curdir
, cos_45
))
3174 lastpt
->corner
= POINTTYPE_CORNER
;
3176 case POINTTYPE_CURVE_MIDDLE
:
3177 if (!is_direction_similar(&lastdir
, &curdir
, cos_90
))
3178 lastpt
->corner
= POINTTYPE_CORNER
;
3180 lastpt
->corner
= POINTTYPE_CURVE
;
3188 header
= (TTPOLYGONHEADER
*)((char *)header
+ header
->cb
);
3193 static BOOL
compute_text_mesh(struct mesh
*mesh
, HDC hdc
, LPCSTR text
, FLOAT deviation
, FLOAT extrusion
, FLOAT otmEMSquare
)
3195 HRESULT hr
= E_FAIL
;
3196 DWORD nb_vertices
, nb_faces
;
3197 DWORD nb_corners
, nb_outline_points
;
3200 char *raw_outline
= NULL
;
3201 struct glyphinfo
*glyphs
= NULL
;
3204 struct vertex
*vertex_ptr
;
3207 if (deviation
== 0.0f
)
3208 deviation
= 1.0f
/ otmEMSquare
;
3210 textlen
= strlen(text
);
3211 glyphs
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, textlen
* sizeof(*glyphs
));
3218 for (i
= 0; i
< textlen
; i
++)
3220 /* get outline points from data returned from GetGlyphOutline */
3221 const MAT2 identity
= {{0, 1}, {0, 0}, {0, 0}, {0, 1}};
3224 glyphs
[i
].offset_x
= offset_x
;
3226 datasize
= GetGlyphOutline(hdc
, text
[i
], GGO_NATIVE
, &gm
, 0, NULL
, &identity
);
3231 HeapFree(GetProcessHeap(), 0, raw_outline
);
3232 raw_outline
= HeapAlloc(GetProcessHeap(), 0, datasize
);
3237 datasize
= GetGlyphOutline(hdc
, text
[i
], GGO_NATIVE
, &gm
, datasize
, raw_outline
, &identity
);
3239 create_outline(&glyphs
[i
], raw_outline
, datasize
, deviation
, otmEMSquare
);
3241 offset_x
+= gm
.gmCellIncX
/ (float)otmEMSquare
;
3244 /* corner points need an extra vertex for the different side faces normals */
3246 nb_outline_points
= 0;
3247 for (i
= 0; i
< textlen
; i
++)
3250 for (j
= 0; j
< glyphs
[i
].outlines
.count
; j
++)
3253 struct outline
*outline
= &glyphs
[i
].outlines
.items
[j
];
3254 nb_outline_points
+= outline
->count
;
3255 nb_corners
++; /* first outline point always repeated as a corner */
3256 for (k
= 1; k
< outline
->count
; k
++)
3257 if (outline
->items
[k
].corner
)
3262 nb_vertices
= (nb_outline_points
+ nb_corners
) * 2 + textlen
;
3263 nb_faces
= nb_outline_points
* 2;
3265 if (!new_mesh(mesh
, nb_vertices
, nb_faces
))
3268 /* convert 2D vertices and faces into 3D mesh */
3269 vertex_ptr
= mesh
->vertices
;
3270 face_ptr
= mesh
->faces
;
3271 for (i
= 0; i
< textlen
; i
++)
3275 /* side vertices and faces */
3276 for (j
= 0; j
< glyphs
[i
].outlines
.count
; j
++)
3278 struct vertex
*outline_vertices
= vertex_ptr
;
3279 struct outline
*outline
= &glyphs
[i
].outlines
.items
[j
];
3281 struct point2d
*prevpt
= &outline
->items
[outline
->count
- 1];
3282 struct point2d
*pt
= &outline
->items
[0];
3284 for (k
= 1; k
<= outline
->count
; k
++)
3287 struct point2d
*nextpt
= &outline
->items
[k
% outline
->count
];
3288 WORD vtx_idx
= vertex_ptr
- mesh
->vertices
;
3291 if (pt
->corner
== POINTTYPE_CURVE_START
)
3292 D3DXVec2Subtract(&vec
, &pt
->pos
, &prevpt
->pos
);
3293 else if (pt
->corner
)
3294 D3DXVec2Subtract(&vec
, &nextpt
->pos
, &pt
->pos
);
3296 D3DXVec2Subtract(&vec
, &nextpt
->pos
, &prevpt
->pos
);
3297 D3DXVec2Normalize(&vec
, &vec
);
3298 vtx
.normal
.x
= -vec
.y
;
3299 vtx
.normal
.y
= vec
.x
;
3302 vtx
.position
.x
= pt
->pos
.x
+ glyphs
[i
].offset_x
;
3303 vtx
.position
.y
= pt
->pos
.y
;
3305 *vertex_ptr
++ = vtx
;
3307 vtx
.position
.z
= -extrusion
;
3308 *vertex_ptr
++ = vtx
;
3310 vtx
.position
.x
= nextpt
->pos
.x
+ glyphs
[i
].offset_x
;
3311 vtx
.position
.y
= nextpt
->pos
.y
;
3312 if (pt
->corner
&& nextpt
->corner
&& nextpt
->corner
!= POINTTYPE_CURVE_END
) {
3313 vtx
.position
.z
= -extrusion
;
3314 *vertex_ptr
++ = vtx
;
3316 *vertex_ptr
++ = vtx
;
3318 (*face_ptr
)[0] = vtx_idx
;
3319 (*face_ptr
)[1] = vtx_idx
+ 2;
3320 (*face_ptr
)[2] = vtx_idx
+ 1;
3323 (*face_ptr
)[0] = vtx_idx
;
3324 (*face_ptr
)[1] = vtx_idx
+ 3;
3325 (*face_ptr
)[2] = vtx_idx
+ 2;
3328 if (nextpt
->corner
) {
3329 if (nextpt
->corner
== POINTTYPE_CURVE_END
) {
3330 struct point2d
*nextpt2
= &outline
->items
[(k
+ 1) % outline
->count
];
3331 D3DXVec2Subtract(&vec
, &nextpt2
->pos
, &nextpt
->pos
);
3333 D3DXVec2Subtract(&vec
, &nextpt
->pos
, &pt
->pos
);
3335 D3DXVec2Normalize(&vec
, &vec
);
3336 vtx
.normal
.x
= -vec
.y
;
3337 vtx
.normal
.y
= vec
.x
;
3340 *vertex_ptr
++ = vtx
;
3341 vtx
.position
.z
= -extrusion
;
3342 *vertex_ptr
++ = vtx
;
3345 (*face_ptr
)[0] = vtx_idx
;
3346 (*face_ptr
)[1] = vtx_idx
+ 3;
3347 (*face_ptr
)[2] = vtx_idx
+ 1;
3350 (*face_ptr
)[0] = vtx_idx
;
3351 (*face_ptr
)[1] = vtx_idx
+ 2;
3352 (*face_ptr
)[2] = vtx_idx
+ 3;
3360 *vertex_ptr
++ = *outline_vertices
++;
3361 *vertex_ptr
++ = *outline_vertices
++;
3365 /* FIXME: compute expected faces */
3366 /* Add placeholder to separate glyph outlines */
3367 vertex_ptr
->position
.x
= 0;
3368 vertex_ptr
->position
.y
= 0;
3369 vertex_ptr
->position
.z
= 0;
3370 vertex_ptr
->normal
.x
= 0;
3371 vertex_ptr
->normal
.y
= 0;
3372 vertex_ptr
->normal
.z
= 1;
3379 for (i
= 0; i
< textlen
; i
++)
3382 for (j
= 0; j
< glyphs
[i
].outlines
.count
; j
++)
3383 HeapFree(GetProcessHeap(), 0, glyphs
[i
].outlines
.items
[j
].items
);
3384 HeapFree(GetProcessHeap(), 0, glyphs
[i
].outlines
.items
);
3386 HeapFree(GetProcessHeap(), 0, glyphs
);
3388 HeapFree(GetProcessHeap(), 0, raw_outline
);
3390 return hr
== D3D_OK
;
3393 static void compare_text_outline_mesh(const char *name
, ID3DXMesh
*d3dxmesh
, struct mesh
*mesh
, int textlen
, float extrusion
)
3396 DWORD number_of_vertices
, number_of_faces
;
3397 IDirect3DVertexBuffer9
*vertex_buffer
= NULL
;
3398 IDirect3DIndexBuffer9
*index_buffer
= NULL
;
3399 D3DVERTEXBUFFER_DESC vertex_buffer_description
;
3400 D3DINDEXBUFFER_DESC index_buffer_description
;
3401 struct vertex
*vertices
= NULL
;
3404 int vtx_idx1
, face_idx1
, vtx_idx2
, face_idx2
;
3406 number_of_vertices
= d3dxmesh
->lpVtbl
->GetNumVertices(d3dxmesh
);
3407 number_of_faces
= d3dxmesh
->lpVtbl
->GetNumFaces(d3dxmesh
);
3410 hr
= d3dxmesh
->lpVtbl
->GetVertexBuffer(d3dxmesh
, &vertex_buffer
);
3411 ok(hr
== D3D_OK
, "Test %s, result %x, expected 0 (D3D_OK)\n", name
, hr
);
3414 skip("Couldn't get vertex buffers\n");
3418 hr
= IDirect3DVertexBuffer9_GetDesc(vertex_buffer
, &vertex_buffer_description
);
3419 ok(hr
== D3D_OK
, "Test %s, result %x, expected 0 (D3D_OK)\n", name
, hr
);
3423 skip("Couldn't get vertex buffer description\n");
3427 ok(vertex_buffer_description
.Format
== D3DFMT_VERTEXDATA
, "Test %s, result %x, expected %x (D3DFMT_VERTEXDATA)\n",
3428 name
, vertex_buffer_description
.Format
, D3DFMT_VERTEXDATA
);
3429 ok(vertex_buffer_description
.Type
== D3DRTYPE_VERTEXBUFFER
, "Test %s, result %x, expected %x (D3DRTYPE_VERTEXBUFFER)\n",
3430 name
, vertex_buffer_description
.Type
, D3DRTYPE_VERTEXBUFFER
);
3431 ok(vertex_buffer_description
.Usage
== 0, "Test %s, result %x, expected %x\n", name
, vertex_buffer_description
.Usage
, 0);
3432 ok(vertex_buffer_description
.Pool
== D3DPOOL_MANAGED
, "Test %s, result %x, expected %x (D3DPOOL_MANAGED)\n",
3433 name
, vertex_buffer_description
.Pool
, D3DPOOL_MANAGED
);
3434 ok(vertex_buffer_description
.FVF
== mesh
->fvf
, "Test %s, result %x, expected %x\n",
3435 name
, vertex_buffer_description
.FVF
, mesh
->fvf
);
3438 expected
= number_of_vertices
* mesh
->vertex_size
;
3442 expected
= number_of_vertices
* D3DXGetFVFVertexSize(mesh
->fvf
);
3444 ok(vertex_buffer_description
.Size
== expected
, "Test %s, result %x, expected %x\n",
3445 name
, vertex_buffer_description
.Size
, expected
);
3448 hr
= d3dxmesh
->lpVtbl
->GetIndexBuffer(d3dxmesh
, &index_buffer
);
3449 ok(hr
== D3D_OK
, "Test %s, result %x, expected 0 (D3D_OK)\n", name
, hr
);
3452 skip("Couldn't get index buffer\n");
3456 hr
= IDirect3DIndexBuffer9_GetDesc(index_buffer
, &index_buffer_description
);
3457 ok(hr
== D3D_OK
, "Test %s, result %x, expected 0 (D3D_OK)\n", name
, hr
);
3461 skip("Couldn't get index buffer description\n");
3465 ok(index_buffer_description
.Format
== D3DFMT_INDEX16
, "Test %s, result %x, expected %x (D3DFMT_INDEX16)\n",
3466 name
, index_buffer_description
.Format
, D3DFMT_INDEX16
);
3467 ok(index_buffer_description
.Type
== D3DRTYPE_INDEXBUFFER
, "Test %s, result %x, expected %x (D3DRTYPE_INDEXBUFFER)\n",
3468 name
, index_buffer_description
.Type
, D3DRTYPE_INDEXBUFFER
);
3469 todo_wine
ok(index_buffer_description
.Usage
== 0, "Test %s, result %x, expected %x\n", name
, index_buffer_description
.Usage
, 0);
3470 ok(index_buffer_description
.Pool
== D3DPOOL_MANAGED
, "Test %s, result %x, expected %x (D3DPOOL_MANAGED)\n",
3471 name
, index_buffer_description
.Pool
, D3DPOOL_MANAGED
);
3472 expected
= number_of_faces
* sizeof(WORD
) * 3;
3473 ok(index_buffer_description
.Size
== expected
, "Test %s, result %x, expected %x\n",
3474 name
, index_buffer_description
.Size
, expected
);
3477 /* specify offset and size to avoid potential overruns */
3478 hr
= IDirect3DVertexBuffer9_Lock(vertex_buffer
, 0, number_of_vertices
* sizeof(D3DXVECTOR3
) * 2,
3479 (LPVOID
*)&vertices
, D3DLOCK_DISCARD
);
3480 ok(hr
== D3D_OK
, "Test %s, result %x, expected 0 (D3D_OK)\n", name
, hr
);
3483 skip("Couldn't lock vertex buffer\n");
3486 hr
= IDirect3DIndexBuffer9_Lock(index_buffer
, 0, number_of_faces
* sizeof(WORD
) * 3,
3487 (LPVOID
*)&faces
, D3DLOCK_DISCARD
);
3488 ok(hr
== D3D_OK
, "Test %s, result %x, expected 0 (D3D_OK)\n", name
, hr
);
3491 skip("Couldn't lock index buffer\n");
3499 for (i
= 0; i
< textlen
; i
++)
3501 int nb_outline_vertices1
, nb_outline_faces1
;
3502 int nb_outline_vertices2
, nb_outline_faces2
;
3503 int nb_back_vertices
, nb_back_faces
;
3504 int first_vtx1
, first_vtx2
;
3505 int first_face1
, first_face2
;
3508 first_vtx1
= vtx_idx1
;
3509 first_vtx2
= vtx_idx2
;
3510 for (; vtx_idx1
< number_of_vertices
; vtx_idx1
++) {
3511 if (vertices
[vtx_idx1
].normal
.z
!= 0)
3514 for (; vtx_idx2
< mesh
->number_of_vertices
; vtx_idx2
++) {
3515 if (mesh
->vertices
[vtx_idx2
].normal
.z
!= 0)
3518 nb_outline_vertices1
= vtx_idx1
- first_vtx1
;
3519 nb_outline_vertices2
= vtx_idx2
- first_vtx2
;
3520 ok(nb_outline_vertices1
== nb_outline_vertices2
,
3521 "Test %s, glyph %d, outline vertex count result %d, expected %d\n", name
, i
,
3522 nb_outline_vertices1
, nb_outline_vertices2
);
3524 for (j
= 0; j
< min(nb_outline_vertices1
, nb_outline_vertices2
); j
++)
3526 vtx_idx1
= first_vtx1
+ j
;
3527 vtx_idx2
= first_vtx2
+ j
;
3528 ok(compare_vec3(vertices
[vtx_idx1
].position
, mesh
->vertices
[vtx_idx2
].position
),
3529 "Test %s, glyph %d, vertex position %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name
, i
, vtx_idx1
,
3530 vertices
[vtx_idx1
].position
.x
, vertices
[vtx_idx1
].position
.y
, vertices
[vtx_idx1
].position
.z
,
3531 mesh
->vertices
[vtx_idx2
].position
.x
, mesh
->vertices
[vtx_idx2
].position
.y
, mesh
->vertices
[vtx_idx2
].position
.z
);
3532 ok(compare_vec3(vertices
[vtx_idx1
].normal
, mesh
->vertices
[first_vtx2
+ j
].normal
),
3533 "Test %s, glyph %d, vertex normal %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name
, i
, vtx_idx1
,
3534 vertices
[vtx_idx1
].normal
.x
, vertices
[vtx_idx1
].normal
.y
, vertices
[vtx_idx1
].normal
.z
,
3535 mesh
->vertices
[vtx_idx2
].normal
.x
, mesh
->vertices
[vtx_idx2
].normal
.y
, mesh
->vertices
[vtx_idx2
].normal
.z
);
3537 vtx_idx1
= first_vtx1
+ nb_outline_vertices1
;
3538 vtx_idx2
= first_vtx2
+ nb_outline_vertices2
;
3540 first_face1
= face_idx1
;
3541 first_face2
= face_idx2
;
3542 for (; face_idx1
< number_of_faces
; face_idx1
++)
3544 if (faces
[face_idx1
][0] >= vtx_idx1
||
3545 faces
[face_idx1
][1] >= vtx_idx1
||
3546 faces
[face_idx1
][2] >= vtx_idx1
)
3549 for (; face_idx2
< mesh
->number_of_faces
; face_idx2
++)
3551 if (mesh
->faces
[face_idx2
][0] >= vtx_idx2
||
3552 mesh
->faces
[face_idx2
][1] >= vtx_idx2
||
3553 mesh
->faces
[face_idx2
][2] >= vtx_idx2
)
3556 nb_outline_faces1
= face_idx1
- first_face1
;
3557 nb_outline_faces2
= face_idx2
- first_face2
;
3558 ok(nb_outline_faces1
== nb_outline_faces2
,
3559 "Test %s, glyph %d, outline face count result %d, expected %d\n", name
, i
,
3560 nb_outline_faces1
, nb_outline_faces2
);
3562 for (j
= 0; j
< min(nb_outline_faces1
, nb_outline_faces2
); j
++)
3564 face_idx1
= first_face1
+ j
;
3565 face_idx2
= first_face2
+ j
;
3566 ok(faces
[face_idx1
][0] - first_vtx1
== mesh
->faces
[face_idx2
][0] - first_vtx2
&&
3567 faces
[face_idx1
][1] - first_vtx1
== mesh
->faces
[face_idx2
][1] - first_vtx2
&&
3568 faces
[face_idx1
][2] - first_vtx1
== mesh
->faces
[face_idx2
][2] - first_vtx2
,
3569 "Test %s, glyph %d, face %d, result (%d, %d, %d), expected (%d, %d, %d)\n", name
, i
, face_idx1
,
3570 faces
[face_idx1
][0], faces
[face_idx1
][1], faces
[face_idx1
][2],
3571 mesh
->faces
[face_idx2
][0] - first_vtx2
+ first_vtx1
,
3572 mesh
->faces
[face_idx2
][1] - first_vtx2
+ first_vtx1
,
3573 mesh
->faces
[face_idx2
][2] - first_vtx2
+ first_vtx1
);
3575 face_idx1
= first_face1
+ nb_outline_faces1
;
3576 face_idx2
= first_face2
+ nb_outline_faces2
;
3578 /* partial test on back vertices and faces */
3579 first_vtx1
= vtx_idx1
;
3580 for (; vtx_idx1
< number_of_vertices
; vtx_idx1
++) {
3583 if (vertices
[vtx_idx1
].normal
.z
!= 1.0f
)
3586 vtx
.position
.z
= 0.0f
;
3587 vtx
.normal
.x
= 0.0f
;
3588 vtx
.normal
.y
= 0.0f
;
3589 vtx
.normal
.z
= 1.0f
;
3590 ok(compare(vertices
[vtx_idx1
].position
.z
, vtx
.position
.z
),
3591 "Test %s, glyph %d, vertex position.z %d, result %g, expected %g\n", name
, i
, vtx_idx1
,
3592 vertices
[vtx_idx1
].position
.z
, vtx
.position
.z
);
3593 ok(compare_vec3(vertices
[vtx_idx1
].normal
, vtx
.normal
),
3594 "Test %s, glyph %d, vertex normal %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name
, i
, vtx_idx1
,
3595 vertices
[vtx_idx1
].normal
.x
, vertices
[vtx_idx1
].normal
.y
, vertices
[vtx_idx1
].normal
.z
,
3596 vtx
.normal
.x
, vtx
.normal
.y
, vtx
.normal
.z
);
3598 nb_back_vertices
= vtx_idx1
- first_vtx1
;
3599 first_face1
= face_idx1
;
3600 for (; face_idx1
< number_of_faces
; face_idx1
++)
3602 const D3DXVECTOR3
*vtx1
, *vtx2
, *vtx3
;
3604 D3DXVECTOR3 v1
= {0, 0, 0};
3605 D3DXVECTOR3 v2
= {0, 0, 0};
3606 D3DXVECTOR3 forward
= {0.0f
, 0.0f
, 1.0f
};
3608 if (faces
[face_idx1
][0] >= vtx_idx1
||
3609 faces
[face_idx1
][1] >= vtx_idx1
||
3610 faces
[face_idx1
][2] >= vtx_idx1
)
3613 vtx1
= &vertices
[faces
[face_idx1
][0]].position
;
3614 vtx2
= &vertices
[faces
[face_idx1
][1]].position
;
3615 vtx3
= &vertices
[faces
[face_idx1
][2]].position
;
3617 D3DXVec3Subtract(&v1
, vtx2
, vtx1
);
3618 D3DXVec3Subtract(&v2
, vtx3
, vtx2
);
3619 D3DXVec3Cross(&normal
, &v1
, &v2
);
3620 D3DXVec3Normalize(&normal
, &normal
);
3621 ok(!D3DXVec3Length(&normal
) || compare_vec3(normal
, forward
),
3622 "Test %s, glyph %d, face %d normal, result (%g, %g, %g), expected (%g, %g, %g)\n", name
, i
, face_idx1
,
3623 normal
.x
, normal
.y
, normal
.z
, forward
.x
, forward
.y
, forward
.z
);
3625 nb_back_faces
= face_idx1
- first_face1
;
3627 /* compare front and back faces & vertices */
3628 if (extrusion
== 0.0f
) {
3629 /* Oddly there are only back faces in this case */
3630 nb_back_vertices
/= 2;
3632 face_idx1
-= nb_back_faces
;
3633 vtx_idx1
-= nb_back_vertices
;
3635 for (j
= 0; j
< nb_back_vertices
; j
++)
3637 struct vertex vtx
= vertices
[first_vtx1
];
3638 vtx
.position
.z
= -extrusion
;
3639 vtx
.normal
.x
= 0.0f
;
3640 vtx
.normal
.y
= 0.0f
;
3641 vtx
.normal
.z
= extrusion
== 0.0f
? 1.0f
: -1.0f
;
3642 ok(compare_vec3(vertices
[vtx_idx1
].position
, vtx
.position
),
3643 "Test %s, glyph %d, vertex position %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name
, i
, vtx_idx1
,
3644 vertices
[vtx_idx1
].position
.x
, vertices
[vtx_idx1
].position
.y
, vertices
[vtx_idx1
].position
.z
,
3645 vtx
.position
.x
, vtx
.position
.y
, vtx
.position
.z
);
3646 ok(compare_vec3(vertices
[vtx_idx1
].normal
, vtx
.normal
),
3647 "Test %s, glyph %d, vertex normal %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name
, i
, vtx_idx1
,
3648 vertices
[vtx_idx1
].normal
.x
, vertices
[vtx_idx1
].normal
.y
, vertices
[vtx_idx1
].normal
.z
,
3649 vtx
.normal
.x
, vtx
.normal
.y
, vtx
.normal
.z
);
3653 for (j
= 0; j
< nb_back_faces
; j
++)
3656 if (extrusion
== 0.0f
) {
3663 ok(faces
[face_idx1
][0] == faces
[first_face1
][0] + nb_back_vertices
&&
3664 faces
[face_idx1
][1] == faces
[first_face1
][f1
] + nb_back_vertices
&&
3665 faces
[face_idx1
][2] == faces
[first_face1
][f2
] + nb_back_vertices
,
3666 "Test %s, glyph %d, face %d, result (%d, %d, %d), expected (%d, %d, %d)\n", name
, i
, face_idx1
,
3667 faces
[face_idx1
][0], faces
[face_idx1
][1], faces
[face_idx1
][2],
3668 faces
[first_face1
][0] - nb_back_faces
,
3669 faces
[first_face1
][f1
] - nb_back_faces
,
3670 faces
[first_face1
][f2
] - nb_back_faces
);
3675 /* skip to the outline for the next glyph */
3676 for (; vtx_idx2
< mesh
->number_of_vertices
; vtx_idx2
++) {
3677 if (mesh
->vertices
[vtx_idx2
].normal
.z
== 0)
3680 for (; face_idx2
< mesh
->number_of_faces
; face_idx2
++)
3682 if (mesh
->faces
[face_idx2
][0] >= vtx_idx2
||
3683 mesh
->faces
[face_idx2
][1] >= vtx_idx2
||
3684 mesh
->faces
[face_idx2
][2] >= vtx_idx2
) break;
3689 if (vertices
) IDirect3DVertexBuffer9_Unlock(vertex_buffer
);
3690 if (faces
) IDirect3DIndexBuffer9_Unlock(index_buffer
);
3691 if (index_buffer
) IDirect3DIndexBuffer9_Release(index_buffer
);
3692 if (vertex_buffer
) IDirect3DVertexBuffer9_Release(vertex_buffer
);
3695 static void test_createtext(IDirect3DDevice9
*device
, HDC hdc
, LPCSTR text
, FLOAT deviation
, FLOAT extrusion
)
3698 ID3DXMesh
*d3dxmesh
;
3701 OUTLINETEXTMETRIC otm
;
3703 GLYPHMETRICSFLOAT
*glyphmetrics_float
= HeapAlloc(GetProcessHeap(), 0, sizeof(GLYPHMETRICSFLOAT
) * strlen(text
));
3706 HFONT font
= NULL
, oldfont
= NULL
;
3708 sprintf(name
, "text ('%s', %f, %f)", text
, deviation
, extrusion
);
3710 hr
= D3DXCreateText(device
, hdc
, text
, deviation
, extrusion
, &d3dxmesh
, NULL
, glyphmetrics_float
);
3711 ok(hr
== D3D_OK
, "Got result %x, expected 0 (D3D_OK)\n", hr
);
3714 skip("Couldn't create text with D3DXCreateText\n");
3718 /* must select a modified font having lfHeight = otm.otmEMSquare before
3719 * calling GetGlyphOutline to get the expected values */
3720 if (!GetObject(GetCurrentObject(hdc
, OBJ_FONT
), sizeof(lf
), &lf
) ||
3721 !GetOutlineTextMetrics(hdc
, sizeof(otm
), &otm
))
3723 d3dxmesh
->lpVtbl
->Release(d3dxmesh
);
3724 skip("Couldn't get text outline\n");
3727 lf
.lfHeight
= otm
.otmEMSquare
;
3729 font
= CreateFontIndirect(&lf
);
3731 d3dxmesh
->lpVtbl
->Release(d3dxmesh
);
3732 skip("Couldn't create the modified font\n");
3735 oldfont
= SelectObject(hdc
, font
);
3737 for (i
= 0; i
< strlen(text
); i
++)
3739 const MAT2 identity
= {{0, 1}, {0, 0}, {0, 0}, {0, 1}};
3740 GetGlyphOutlineA(hdc
, text
[i
], GGO_NATIVE
, &gm
, 0, NULL
, &identity
);
3741 compare_float(glyphmetrics_float
[i
].gmfBlackBoxX
, gm
.gmBlackBoxX
/ (float)otm
.otmEMSquare
);
3742 compare_float(glyphmetrics_float
[i
].gmfBlackBoxY
, gm
.gmBlackBoxY
/ (float)otm
.otmEMSquare
);
3743 compare_float(glyphmetrics_float
[i
].gmfptGlyphOrigin
.x
, gm
.gmptGlyphOrigin
.x
/ (float)otm
.otmEMSquare
);
3744 compare_float(glyphmetrics_float
[i
].gmfptGlyphOrigin
.y
, gm
.gmptGlyphOrigin
.y
/ (float)otm
.otmEMSquare
);
3745 compare_float(glyphmetrics_float
[i
].gmfCellIncX
, gm
.gmCellIncX
/ (float)otm
.otmEMSquare
);
3746 compare_float(glyphmetrics_float
[i
].gmfCellIncY
, gm
.gmCellIncY
/ (float)otm
.otmEMSquare
);
3749 ZeroMemory(&mesh
, sizeof(mesh
));
3750 if (!compute_text_mesh(&mesh
, hdc
, text
, deviation
, extrusion
, otm
.otmEMSquare
))
3752 skip("Couldn't create mesh\n");
3753 d3dxmesh
->lpVtbl
->Release(d3dxmesh
);
3756 mesh
.fvf
= D3DFVF_XYZ
| D3DFVF_NORMAL
;
3758 compare_text_outline_mesh(name
, d3dxmesh
, &mesh
, strlen(text
), extrusion
);
3762 d3dxmesh
->lpVtbl
->Release(d3dxmesh
);
3763 SelectObject(hdc
, oldfont
);
3764 HeapFree(GetProcessHeap(), 0, glyphmetrics_float
);
3767 static void D3DXCreateTextTest(void)
3773 IDirect3DDevice9
* device
;
3774 D3DPRESENT_PARAMETERS d3dpp
;
3775 ID3DXMesh
* d3dxmesh
= NULL
;
3777 OUTLINETEXTMETRIC otm
;
3778 int number_of_vertices
;
3779 int number_of_faces
;
3781 wnd
= CreateWindow("static", "d3dx9_test", WS_POPUP
, 0, 0, 1000, 1000, NULL
, NULL
, NULL
, NULL
);
3782 d3d
= Direct3DCreate9(D3D_SDK_VERSION
);
3785 skip("Couldn't create application window\n");
3790 skip("Couldn't create IDirect3D9 object\n");
3795 ZeroMemory(&d3dpp
, sizeof(d3dpp
));
3796 d3dpp
.Windowed
= TRUE
;
3797 d3dpp
.SwapEffect
= D3DSWAPEFFECT_DISCARD
;
3798 hr
= IDirect3D9_CreateDevice(d3d
, D3DADAPTER_DEFAULT
, D3DDEVTYPE_HAL
, wnd
, D3DCREATE_MIXED_VERTEXPROCESSING
, &d3dpp
, &device
);
3801 skip("Failed to create IDirect3DDevice9 object %#x\n", hr
);
3802 IDirect3D9_Release(d3d
);
3807 hdc
= CreateCompatibleDC(NULL
);
3809 hFont
= CreateFont(12, 0, 0, 0, FW_NORMAL
, FALSE
, FALSE
, FALSE
, DEFAULT_CHARSET
,
3810 OUT_DEFAULT_PRECIS
, CLIP_DEFAULT_PRECIS
, DEFAULT_QUALITY
, DEFAULT_PITCH
| FF_DONTCARE
,
3812 SelectObject(hdc
, hFont
);
3813 GetOutlineTextMetrics(hdc
, sizeof(otm
), &otm
);
3815 hr
= D3DXCreateText(device
, hdc
, "wine", 0.001f
, 0.4f
, NULL
, NULL
, NULL
);
3816 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr
, D3DERR_INVALIDCALL
);
3818 /* D3DXCreateTextA page faults from passing NULL text */
3820 hr
= D3DXCreateTextW(device
, hdc
, NULL
, 0.001f
, 0.4f
, &d3dxmesh
, NULL
, NULL
);
3821 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr
, D3DERR_INVALIDCALL
);
3823 hr
= D3DXCreateText(device
, hdc
, "", 0.001f
, 0.4f
, &d3dxmesh
, NULL
, NULL
);
3824 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr
, D3DERR_INVALIDCALL
);
3826 hr
= D3DXCreateText(device
, hdc
, " ", 0.001f
, 0.4f
, &d3dxmesh
, NULL
, NULL
);
3827 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr
, D3DERR_INVALIDCALL
);
3829 hr
= D3DXCreateText(NULL
, hdc
, "wine", 0.001f
, 0.4f
, &d3dxmesh
, NULL
, NULL
);
3830 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr
, D3DERR_INVALIDCALL
);
3832 hr
= D3DXCreateText(device
, NULL
, "wine", 0.001f
, 0.4f
, &d3dxmesh
, NULL
, NULL
);
3833 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr
, D3DERR_INVALIDCALL
);
3835 hr
= D3DXCreateText(device
, hdc
, "wine", -FLT_MIN
, 0.4f
, &d3dxmesh
, NULL
, NULL
);
3836 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr
, D3DERR_INVALIDCALL
);
3838 hr
= D3DXCreateText(device
, hdc
, "wine", 0.001f
, -FLT_MIN
, &d3dxmesh
, NULL
, NULL
);
3839 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr
, D3DERR_INVALIDCALL
);
3841 /* deviation = 0.0f treated as if deviation = 1.0f / otm.otmEMSquare */
3842 hr
= D3DXCreateText(device
, hdc
, "wine", 1.0f
/ otm
.otmEMSquare
, 0.4f
, &d3dxmesh
, NULL
, NULL
);
3843 ok(hr
== D3D_OK
, "Got result %x, expected %x (D3D_OK)\n", hr
, D3D_OK
);
3844 number_of_vertices
= d3dxmesh
->lpVtbl
->GetNumVertices(d3dxmesh
);
3845 number_of_faces
= d3dxmesh
->lpVtbl
->GetNumFaces(d3dxmesh
);
3846 if (SUCCEEDED(hr
) && d3dxmesh
) d3dxmesh
->lpVtbl
->Release(d3dxmesh
);
3848 hr
= D3DXCreateText(device
, hdc
, "wine", 0.0f
, 0.4f
, &d3dxmesh
, NULL
, NULL
);
3849 ok(hr
== D3D_OK
, "Got result %x, expected %x (D3D_OK)\n", hr
, D3D_OK
);
3850 ok(number_of_vertices
== d3dxmesh
->lpVtbl
->GetNumVertices(d3dxmesh
),
3851 "Got %d vertices, expected %d\n",
3852 d3dxmesh
->lpVtbl
->GetNumVertices(d3dxmesh
), number_of_vertices
);
3853 ok(number_of_faces
== d3dxmesh
->lpVtbl
->GetNumFaces(d3dxmesh
),
3854 "Got %d faces, expected %d\n",
3855 d3dxmesh
->lpVtbl
->GetNumVertices(d3dxmesh
), number_of_faces
);
3856 if (SUCCEEDED(hr
) && d3dxmesh
) d3dxmesh
->lpVtbl
->Release(d3dxmesh
);
3859 /* too much detail requested, so will appear to hang */
3860 trace("Waiting for D3DXCreateText to finish with deviation = FLT_MIN ...\n");
3861 hr
= D3DXCreateText(device
, hdc
, "wine", FLT_MIN
, 0.4f
, &d3dxmesh
, NULL
, NULL
);
3862 ok(hr
== D3D_OK
, "Got result %x, expected %x (D3D_OK)\n", hr
, D3D_OK
);
3863 if (SUCCEEDED(hr
) && d3dxmesh
) d3dxmesh
->lpVtbl
->Release(d3dxmesh
);
3864 trace("D3DXCreateText finish with deviation = FLT_MIN\n");
3867 hr
= D3DXCreateText(device
, hdc
, "wine", 0.001f
, 0.4f
, &d3dxmesh
, NULL
, NULL
);
3868 ok(hr
== D3D_OK
, "Got result %x, expected %x (D3D_OK)\n", hr
, D3D_OK
);
3869 if (SUCCEEDED(hr
) && d3dxmesh
) d3dxmesh
->lpVtbl
->Release(d3dxmesh
);
3871 test_createtext(device
, hdc
, "wine", FLT_MAX
, 0.4f
);
3872 test_createtext(device
, hdc
, "wine", 0.001f
, FLT_MIN
);
3873 test_createtext(device
, hdc
, "wine", 0.001f
, 0.0f
);
3874 test_createtext(device
, hdc
, "wine", 0.001f
, FLT_MAX
);
3875 test_createtext(device
, hdc
, "wine", 0.0f
, 1.0f
);
3879 IDirect3DDevice9_Release(device
);
3880 IDirect3D9_Release(d3d
);
3884 static void test_get_decl_length(void)
3886 static const D3DVERTEXELEMENT9 declaration1
[] =
3888 {0, 0, D3DDECLTYPE_FLOAT1
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3889 {1, 0, D3DDECLTYPE_FLOAT2
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3890 {2, 0, D3DDECLTYPE_FLOAT3
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3891 {3, 0, D3DDECLTYPE_FLOAT4
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3892 {4, 0, D3DDECLTYPE_D3DCOLOR
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3893 {5, 0, D3DDECLTYPE_UBYTE4
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3894 {6, 0, D3DDECLTYPE_SHORT2
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3895 {7, 0, D3DDECLTYPE_SHORT4
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3896 {8, 0, D3DDECLTYPE_UBYTE4N
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3897 {9, 0, D3DDECLTYPE_SHORT2N
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3898 {10, 0, D3DDECLTYPE_SHORT4N
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3899 {11, 0, D3DDECLTYPE_UDEC3
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3900 {12, 0, D3DDECLTYPE_DEC3N
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3901 {13, 0, D3DDECLTYPE_FLOAT16_2
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3902 {14, 0, D3DDECLTYPE_FLOAT16_4
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3905 static const D3DVERTEXELEMENT9 declaration2
[] =
3907 {0, 8, D3DDECLTYPE_FLOAT1
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3908 {1, 8, D3DDECLTYPE_FLOAT2
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3909 {2, 8, D3DDECLTYPE_FLOAT3
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3910 {3, 8, D3DDECLTYPE_FLOAT4
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3911 {4, 8, D3DDECLTYPE_D3DCOLOR
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3912 {5, 8, D3DDECLTYPE_UBYTE4
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3913 {6, 8, D3DDECLTYPE_SHORT2
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3914 {7, 8, D3DDECLTYPE_SHORT4
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3915 {0, 8, D3DDECLTYPE_UBYTE4N
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3916 {1, 8, D3DDECLTYPE_SHORT2N
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3917 {2, 8, D3DDECLTYPE_SHORT4N
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3918 {3, 8, D3DDECLTYPE_UDEC3
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3919 {4, 8, D3DDECLTYPE_DEC3N
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3920 {5, 8, D3DDECLTYPE_FLOAT16_2
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3921 {6, 8, D3DDECLTYPE_FLOAT16_4
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3922 {7, 8, D3DDECLTYPE_FLOAT1
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3927 size
= D3DXGetDeclLength(declaration1
);
3928 ok(size
== 15, "Got size %u, expected 15.\n", size
);
3930 size
= D3DXGetDeclLength(declaration2
);
3931 ok(size
== 16, "Got size %u, expected 16.\n", size
);
3934 static void test_get_decl_vertex_size(void)
3936 static const D3DVERTEXELEMENT9 declaration1
[] =
3938 {0, 0, D3DDECLTYPE_FLOAT1
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3939 {1, 0, D3DDECLTYPE_FLOAT2
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3940 {2, 0, D3DDECLTYPE_FLOAT3
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3941 {3, 0, D3DDECLTYPE_FLOAT4
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3942 {4, 0, D3DDECLTYPE_D3DCOLOR
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3943 {5, 0, D3DDECLTYPE_UBYTE4
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3944 {6, 0, D3DDECLTYPE_SHORT2
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3945 {7, 0, D3DDECLTYPE_SHORT4
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3946 {8, 0, D3DDECLTYPE_UBYTE4N
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3947 {9, 0, D3DDECLTYPE_SHORT2N
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3948 {10, 0, D3DDECLTYPE_SHORT4N
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3949 {11, 0, D3DDECLTYPE_UDEC3
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3950 {12, 0, D3DDECLTYPE_DEC3N
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3951 {13, 0, D3DDECLTYPE_FLOAT16_2
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3952 {14, 0, D3DDECLTYPE_FLOAT16_4
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3955 static const D3DVERTEXELEMENT9 declaration2
[] =
3957 {0, 8, D3DDECLTYPE_FLOAT1
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3958 {1, 8, D3DDECLTYPE_FLOAT2
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3959 {2, 8, D3DDECLTYPE_FLOAT3
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3960 {3, 8, D3DDECLTYPE_FLOAT4
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3961 {4, 8, D3DDECLTYPE_D3DCOLOR
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3962 {5, 8, D3DDECLTYPE_UBYTE4
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3963 {6, 8, D3DDECLTYPE_SHORT2
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3964 {7, 8, D3DDECLTYPE_SHORT4
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3965 {0, 8, D3DDECLTYPE_UBYTE4N
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3966 {1, 8, D3DDECLTYPE_SHORT2N
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3967 {2, 8, D3DDECLTYPE_SHORT4N
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3968 {3, 8, D3DDECLTYPE_UDEC3
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3969 {4, 8, D3DDECLTYPE_DEC3N
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3970 {5, 8, D3DDECLTYPE_FLOAT16_2
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3971 {6, 8, D3DDECLTYPE_FLOAT16_4
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3972 {7, 8, D3DDECLTYPE_FLOAT1
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3975 static const UINT sizes1
[] =
3982 static const UINT sizes2
[] =
3990 size
= D3DXGetDeclVertexSize(NULL
, 0);
3991 ok(size
== 0, "Got size %#x, expected 0.\n", size
);
3993 for (i
= 0; i
< 16; ++i
)
3995 size
= D3DXGetDeclVertexSize(declaration1
, i
);
3996 ok(size
== sizes1
[i
], "Got size %u for stream %u, expected %u.\n", size
, i
, sizes1
[i
]);
3999 for (i
= 0; i
< 8; ++i
)
4001 size
= D3DXGetDeclVertexSize(declaration2
, i
);
4002 ok(size
== sizes2
[i
], "Got size %u for stream %u, expected %u.\n", size
, i
, sizes2
[i
]);
4006 static void D3DXGenerateAdjacencyTest(void)
4011 IDirect3DDevice9
*device
;
4012 D3DPRESENT_PARAMETERS d3dpp
;
4013 ID3DXMesh
*d3dxmesh
= NULL
;
4014 D3DXVECTOR3
*vertices
= NULL
;
4015 WORD
*indices
= NULL
;
4019 D3DXVECTOR3 vertices
[6];
4021 WORD indices
[3 * 3];
4023 DWORD adjacency
[3 * 3];
4025 { /* for epsilon < 0, indices must match for faces to be adjacent */
4026 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}},
4027 2, {0, 1, 2, 0, 2, 3},
4029 {-1, -1, 1, 0, -1, -1},
4032 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}},
4033 2, {0, 1, 2, 3, 4, 5},
4035 {-1, -1, -1, -1, -1, -1},
4037 { /* for epsilon == 0, indices or vertices must match for faces to be adjacent */
4038 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}},
4039 2, {0, 1, 2, 3, 4, 5},
4041 {-1, -1, 1, 0, -1, -1},
4043 { /* for epsilon > 0, vertices must be less than (but NOT equal to) epsilon distance away */
4044 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}},
4045 2, {0, 1, 2, 3, 4, 5},
4047 {-1, -1, -1, -1, -1, -1},
4049 { /* for epsilon > 0, vertices must be less than (but NOT equal to) epsilon distance away */
4050 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}},
4051 2, {0, 1, 2, 3, 4, 5},
4053 {-1, -1, 1, 0, -1, -1},
4055 { /* length between vertices are compared to epsilon, not the individual dimension deltas */
4056 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}},
4057 2, {0, 1, 2, 3, 4, 5},
4058 0.353, /* < sqrt(0.25*0.25 + 0.25*0.25) */
4059 {-1, -1, -1, -1, -1, -1},
4062 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}},
4063 2, {0, 1, 2, 3, 4, 5},
4064 0.354, /* > sqrt(0.25*0.25 + 0.25*0.25) */
4065 {-1, -1, 1, 0, -1, -1},
4067 { /* adjacent faces must have opposite winding orders at the shared edge */
4068 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}},
4069 2, {0, 1, 2, 0, 3, 2},
4071 {-1, -1, -1, -1, -1, -1},
4075 wnd
= CreateWindow("static", "d3dx9_test", 0, 0, 0, 0, 0, NULL
, NULL
, NULL
, NULL
);
4078 skip("Couldn't create application window\n");
4081 d3d
= Direct3DCreate9(D3D_SDK_VERSION
);
4084 skip("Couldn't create IDirect3D9 object\n");
4089 ZeroMemory(&d3dpp
, sizeof(d3dpp
));
4090 d3dpp
.Windowed
= TRUE
;
4091 d3dpp
.SwapEffect
= D3DSWAPEFFECT_DISCARD
;
4092 hr
= IDirect3D9_CreateDevice(d3d
, D3DADAPTER_DEFAULT
, D3DDEVTYPE_HAL
, wnd
, D3DCREATE_MIXED_VERTEXPROCESSING
, &d3dpp
, &device
);
4095 skip("Failed to create IDirect3DDevice9 object %#x\n", hr
);
4096 IDirect3D9_Release(d3d
);
4101 for (i
= 0; i
< ARRAY_SIZE(test_data
); i
++)
4103 DWORD adjacency
[ARRAY_SIZE(test_data
[0].adjacency
)];
4106 if (d3dxmesh
) d3dxmesh
->lpVtbl
->Release(d3dxmesh
);
4109 hr
= D3DXCreateMeshFVF(test_data
[i
].num_faces
, test_data
[i
].num_vertices
, 0, D3DFVF_XYZ
, device
, &d3dxmesh
);
4110 ok(hr
== D3D_OK
, "Got result %x, expected %x (D3D_OK)\n", hr
, D3D_OK
);
4112 hr
= d3dxmesh
->lpVtbl
->LockVertexBuffer(d3dxmesh
, D3DLOCK_DISCARD
, (void**)&vertices
);
4113 ok(hr
== D3D_OK
, "test %d: Got result %x, expected %x (D3D_OK)\n", i
, hr
, D3D_OK
);
4114 if (FAILED(hr
)) continue;
4115 CopyMemory(vertices
, test_data
[i
].vertices
, test_data
[i
].num_vertices
* sizeof(test_data
[0].vertices
[0]));
4116 d3dxmesh
->lpVtbl
->UnlockVertexBuffer(d3dxmesh
);
4118 hr
= d3dxmesh
->lpVtbl
->LockIndexBuffer(d3dxmesh
, D3DLOCK_DISCARD
, (void**)&indices
);
4119 ok(hr
== D3D_OK
, "test %d: Got result %x, expected %x (D3D_OK)\n", i
, hr
, D3D_OK
);
4120 if (FAILED(hr
)) continue;
4121 CopyMemory(indices
, test_data
[i
].indices
, test_data
[i
].num_faces
* 3 * sizeof(test_data
[0].indices
[0]));
4122 d3dxmesh
->lpVtbl
->UnlockIndexBuffer(d3dxmesh
);
4125 hr
= d3dxmesh
->lpVtbl
->GenerateAdjacency(d3dxmesh
, 0.0f
, NULL
);
4126 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr
, D3DERR_INVALIDCALL
);
4129 hr
= d3dxmesh
->lpVtbl
->GenerateAdjacency(d3dxmesh
, test_data
[i
].epsilon
, adjacency
);
4130 ok(hr
== D3D_OK
, "Got result %x, expected %x (D3D_OK)\n", hr
, D3D_OK
);
4131 if (FAILED(hr
)) continue;
4133 for (j
= 0; j
< test_data
[i
].num_faces
* 3; j
++)
4134 ok(adjacency
[j
] == test_data
[i
].adjacency
[j
],
4135 "Test %d adjacency %d: Got result %u, expected %u\n", i
, j
,
4136 adjacency
[j
], test_data
[i
].adjacency
[j
]);
4138 if (d3dxmesh
) d3dxmesh
->lpVtbl
->Release(d3dxmesh
);
4143 D3DXBoundProbeTest();
4144 D3DXComputeBoundingBoxTest();
4145 D3DXComputeBoundingSphereTest();
4146 D3DXGetFVFVertexSizeTest();
4147 D3DXIntersectTriTest();
4148 D3DXCreateMeshTest();
4149 D3DXCreateMeshFVFTest();
4151 D3DXCreateBoxTest();
4152 D3DXCreateSphereTest();
4153 D3DXCreateCylinderTest();
4154 D3DXCreateTextTest();
4155 test_get_decl_length();
4156 test_get_decl_vertex_size();
4157 test_fvf_decl_conversion();
4158 D3DXGenerateAdjacencyTest();