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
23 #include "wine/test.h"
26 #define admitted_error 0.0001f
28 #define ARRAY_SIZE(array) (sizeof(array)/sizeof(*array))
30 #define compare_vertex_sizes(type, exp) \
31 got=D3DXGetFVFVertexSize(type); \
32 ok(got==exp, "Expected: %d, Got: %d\n", exp, got);
34 #define compare_float(got, exp) \
38 ok(_got == _exp, "Expected: %g, Got: %g\n", _exp, _got); \
41 static BOOL
compare(FLOAT u
, FLOAT v
)
43 return (fabs(u
-v
) < admitted_error
);
46 static BOOL
compare_vec3(D3DXVECTOR3 u
, D3DXVECTOR3 v
)
48 return ( compare(u
.x
, v
.x
) && compare(u
.y
, v
.y
) && compare(u
.z
, v
.z
) );
59 static BOOL
compare_face(face a
, face b
)
61 return (a
[0]==b
[0] && a
[1] == b
[1] && a
[2] == b
[2]);
66 DWORD number_of_vertices
;
67 struct vertex
*vertices
;
69 DWORD number_of_faces
;
76 static void free_mesh(struct mesh
*mesh
)
78 HeapFree(GetProcessHeap(), 0, mesh
->faces
);
79 HeapFree(GetProcessHeap(), 0, mesh
->vertices
);
82 static BOOL
new_mesh(struct mesh
*mesh
, DWORD number_of_vertices
, DWORD number_of_faces
)
84 mesh
->vertices
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, number_of_vertices
* sizeof(*mesh
->vertices
));
89 mesh
->number_of_vertices
= number_of_vertices
;
91 mesh
->faces
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, number_of_faces
* sizeof(*mesh
->faces
));
94 HeapFree(GetProcessHeap(), 0, mesh
->vertices
);
97 mesh
->number_of_faces
= number_of_faces
;
102 static void compare_mesh(const char *name
, ID3DXMesh
*d3dxmesh
, struct mesh
*mesh
)
105 DWORD number_of_vertices
, number_of_faces
;
106 IDirect3DVertexBuffer9
*vertex_buffer
;
107 IDirect3DIndexBuffer9
*index_buffer
;
108 D3DVERTEXBUFFER_DESC vertex_buffer_description
;
109 D3DINDEXBUFFER_DESC index_buffer_description
;
110 struct vertex
*vertices
;
114 number_of_vertices
= d3dxmesh
->lpVtbl
->GetNumVertices(d3dxmesh
);
115 ok(number_of_vertices
== mesh
->number_of_vertices
, "Test %s, result %u, expected %d\n",
116 name
, number_of_vertices
, mesh
->number_of_vertices
);
118 number_of_faces
= d3dxmesh
->lpVtbl
->GetNumFaces(d3dxmesh
);
119 ok(number_of_faces
== mesh
->number_of_faces
, "Test %s, result %u, expected %d\n",
120 name
, number_of_faces
, mesh
->number_of_faces
);
123 hr
= d3dxmesh
->lpVtbl
->GetVertexBuffer(d3dxmesh
, &vertex_buffer
);
124 ok(hr
== D3D_OK
, "Test %s, result %x, expected 0 (D3D_OK)\n", name
, hr
);
128 skip("Couldn't get vertex buffer\n");
132 hr
= IDirect3DVertexBuffer9_GetDesc(vertex_buffer
, &vertex_buffer_description
);
133 ok(hr
== D3D_OK
, "Test %s, result %x, expected 0 (D3D_OK)\n", name
, hr
);
137 skip("Couldn't get vertex buffer description\n");
141 ok(vertex_buffer_description
.Format
== D3DFMT_VERTEXDATA
, "Test %s, result %x, expected %x (D3DFMT_VERTEXDATA)\n",
142 name
, vertex_buffer_description
.Format
, D3DFMT_VERTEXDATA
);
143 ok(vertex_buffer_description
.Type
== D3DRTYPE_VERTEXBUFFER
, "Test %s, result %x, expected %x (D3DRTYPE_VERTEXBUFFER)\n",
144 name
, vertex_buffer_description
.Type
, D3DRTYPE_VERTEXBUFFER
);
145 ok(vertex_buffer_description
.Usage
== 0, "Test %s, result %x, expected %x\n", name
, vertex_buffer_description
.Usage
, 0);
146 ok(vertex_buffer_description
.Pool
== D3DPOOL_MANAGED
, "Test %s, result %x, expected %x (D3DPOOL_DEFAULT)\n",
147 name
, vertex_buffer_description
.Pool
, D3DPOOL_DEFAULT
);
148 ok(vertex_buffer_description
.FVF
== mesh
->fvf
, "Test %s, result %x, expected %x\n",
149 name
, vertex_buffer_description
.FVF
, mesh
->fvf
);
152 expected
= number_of_vertices
* mesh
->vertex_size
;
156 expected
= number_of_vertices
* D3DXGetFVFVertexSize(mesh
->fvf
);
158 ok(vertex_buffer_description
.Size
== expected
, "Test %s, result %x, expected %x\n",
159 name
, vertex_buffer_description
.Size
, expected
);
162 /* specify offset and size to avoid potential overruns */
163 hr
= IDirect3DVertexBuffer9_Lock(vertex_buffer
, 0, number_of_vertices
* sizeof(D3DXVECTOR3
) * 2,
164 (LPVOID
*)&vertices
, D3DLOCK_DISCARD
);
165 ok(hr
== D3D_OK
, "Test %s, result %x, expected 0 (D3D_OK)\n", name
, hr
);
169 skip("Couldn't lock vertex buffer\n");
173 for (i
= 0; i
< number_of_vertices
; i
++)
175 ok(compare_vec3(vertices
[i
].position
, mesh
->vertices
[i
].position
),
176 "Test %s, vertex position %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name
, i
,
177 vertices
[i
].position
.x
, vertices
[i
].position
.y
, vertices
[i
].position
.z
,
178 mesh
->vertices
[i
].position
.x
, mesh
->vertices
[i
].position
.y
, mesh
->vertices
[i
].position
.z
);
179 ok(compare_vec3(vertices
[i
].normal
, mesh
->vertices
[i
].normal
),
180 "Test %s, vertex normal %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name
, i
,
181 vertices
[i
].normal
.x
, vertices
[i
].normal
.y
, vertices
[i
].normal
.z
,
182 mesh
->vertices
[i
].normal
.x
, mesh
->vertices
[i
].normal
.y
, mesh
->vertices
[i
].normal
.z
);
185 IDirect3DVertexBuffer9_Unlock(vertex_buffer
);
188 IDirect3DVertexBuffer9_Release(vertex_buffer
);
192 hr
= d3dxmesh
->lpVtbl
->GetIndexBuffer(d3dxmesh
, &index_buffer
);
193 ok(hr
== D3D_OK
, "Test %s, result %x, expected 0 (D3D_OK)\n", name
, hr
);
197 skip("Couldn't get index buffer\n");
201 hr
= IDirect3DIndexBuffer9_GetDesc(index_buffer
, &index_buffer_description
);
202 ok(hr
== D3D_OK
, "Test %s, result %x, expected 0 (D3D_OK)\n", name
, hr
);
206 skip("Couldn't get index buffer description\n");
210 ok(index_buffer_description
.Format
== D3DFMT_INDEX16
, "Test %s, result %x, expected %x (D3DFMT_INDEX16)\n",
211 name
, index_buffer_description
.Format
, D3DFMT_INDEX16
);
212 ok(index_buffer_description
.Type
== D3DRTYPE_INDEXBUFFER
, "Test %s, result %x, expected %x (D3DRTYPE_INDEXBUFFER)\n",
213 name
, index_buffer_description
.Type
, D3DRTYPE_INDEXBUFFER
);
214 todo_wine
ok(index_buffer_description
.Usage
== 0, "Test %s, result %x, expected %x\n", name
, index_buffer_description
.Usage
, 0);
215 ok(index_buffer_description
.Pool
== D3DPOOL_MANAGED
, "Test %s, result %x, expected %x (D3DPOOL_DEFAULT)\n",
216 name
, index_buffer_description
.Pool
, D3DPOOL_DEFAULT
);
217 expected
= number_of_faces
* sizeof(WORD
) * 3;
218 ok(index_buffer_description
.Size
== expected
, "Test %s, result %x, expected %x\n",
219 name
, index_buffer_description
.Size
, expected
);
222 /* specify offset and size to avoid potential overruns */
223 hr
= IDirect3DIndexBuffer9_Lock(index_buffer
, 0, number_of_faces
* sizeof(WORD
) * 3,
224 (LPVOID
*)&faces
, D3DLOCK_DISCARD
);
225 ok(hr
== D3D_OK
, "Test %s, result %x, expected 0 (D3D_OK)\n", name
, hr
);
229 skip("Couldn't lock index buffer\n");
233 for (i
= 0; i
< number_of_faces
; i
++)
235 ok(compare_face(faces
[i
], mesh
->faces
[i
]),
236 "Test %s, face %d, result (%u, %u, %u), expected (%u, %u, %u)\n", name
, i
,
237 faces
[i
][0], faces
[i
][1], faces
[i
][2],
238 mesh
->faces
[i
][0], mesh
->faces
[i
][1], mesh
->faces
[i
][2]);
241 IDirect3DIndexBuffer9_Unlock(index_buffer
);
244 IDirect3DIndexBuffer9_Release(index_buffer
);
248 static void D3DXBoundProbeTest(void)
251 D3DXVECTOR3 bottom_point
, center
, top_point
, raydirection
, rayposition
;
254 /*____________Test the Box case___________________________*/
255 bottom_point
.x
= -3.0f
; bottom_point
.y
= -2.0f
; bottom_point
.z
= -1.0f
;
256 top_point
.x
= 7.0f
; top_point
.y
= 8.0f
; top_point
.z
= 9.0f
;
258 raydirection
.x
= -4.0f
; raydirection
.y
= -5.0f
; raydirection
.z
= -6.0f
;
259 rayposition
.x
= 5.0f
; rayposition
.y
= 5.0f
; rayposition
.z
= 11.0f
;
260 result
= D3DXBoxBoundProbe(&bottom_point
, &top_point
, &rayposition
, &raydirection
);
261 ok(result
== TRUE
, "expected TRUE, received FALSE\n");
263 raydirection
.x
= 4.0f
; raydirection
.y
= 5.0f
; raydirection
.z
= 6.0f
;
264 rayposition
.x
= 5.0f
; rayposition
.y
= 5.0f
; rayposition
.z
= 11.0f
;
265 result
= D3DXBoxBoundProbe(&bottom_point
, &top_point
, &rayposition
, &raydirection
);
266 ok(result
== FALSE
, "expected FALSE, received TRUE\n");
268 rayposition
.x
= -4.0f
; rayposition
.y
= 1.0f
; rayposition
.z
= -2.0f
;
269 result
= D3DXBoxBoundProbe(&bottom_point
, &top_point
, &rayposition
, &raydirection
);
270 ok(result
== TRUE
, "expected TRUE, received FALSE\n");
272 bottom_point
.x
= 1.0f
; bottom_point
.y
= 0.0f
; bottom_point
.z
= 0.0f
;
273 top_point
.x
= 1.0f
; top_point
.y
= 0.0f
; top_point
.z
= 0.0f
;
274 rayposition
.x
= 0.0f
; rayposition
.y
= 1.0f
; rayposition
.z
= 0.0f
;
275 raydirection
.x
= 0.0f
; raydirection
.y
= 3.0f
; raydirection
.z
= 0.0f
;
276 result
= D3DXBoxBoundProbe(&bottom_point
, &top_point
, &rayposition
, &raydirection
);
277 ok(result
== FALSE
, "expected FALSE, received TRUE\n");
279 bottom_point
.x
= 1.0f
; bottom_point
.y
= 2.0f
; bottom_point
.z
= 3.0f
;
280 top_point
.x
= 10.0f
; top_point
.y
= 15.0f
; top_point
.z
= 20.0f
;
282 raydirection
.x
= 7.0f
; raydirection
.y
= 8.0f
; raydirection
.z
= 9.0f
;
283 rayposition
.x
= 3.0f
; rayposition
.y
= 7.0f
; rayposition
.z
= -6.0f
;
284 result
= D3DXBoxBoundProbe(&bottom_point
, &top_point
, &rayposition
, &raydirection
);
285 ok(result
== TRUE
, "expected TRUE, received FALSE\n");
287 bottom_point
.x
= 0.0f
; bottom_point
.y
= 0.0f
; bottom_point
.z
= 0.0f
;
288 top_point
.x
= 1.0f
; top_point
.y
= 1.0f
; top_point
.z
= 1.0f
;
290 raydirection
.x
= 0.0f
; raydirection
.y
= 1.0f
; raydirection
.z
= .0f
;
291 rayposition
.x
= -3.0f
; rayposition
.y
= 0.0f
; rayposition
.z
= 0.0f
;
292 result
= D3DXBoxBoundProbe(&bottom_point
, &top_point
, &rayposition
, &raydirection
);
293 ok(result
== FALSE
, "expected FALSE, received TRUE\n");
295 raydirection
.x
= 1.0f
; raydirection
.y
= 0.0f
; raydirection
.z
= .0f
;
296 rayposition
.x
= -3.0f
; rayposition
.y
= 0.0f
; rayposition
.z
= 0.0f
;
297 result
= D3DXBoxBoundProbe(&bottom_point
, &top_point
, &rayposition
, &raydirection
);
298 ok(result
== TRUE
, "expected TRUE, received FALSE\n");
300 /*____________Test the Sphere case________________________*/
301 radius
= sqrt(77.0f
);
302 center
.x
= 1.0f
; center
.y
= 2.0f
; center
.z
= 3.0f
;
303 raydirection
.x
= 2.0f
; raydirection
.y
= -4.0f
; raydirection
.z
= 2.0f
;
305 rayposition
.x
= 5.0f
; rayposition
.y
= 5.0f
; rayposition
.z
= 9.0f
;
306 result
= D3DXSphereBoundProbe(¢er
, radius
, &rayposition
, &raydirection
);
307 ok(result
== TRUE
, "expected TRUE, received FALSE\n");
309 rayposition
.x
= 45.0f
; rayposition
.y
= -75.0f
; rayposition
.z
= 49.0f
;
310 result
= D3DXSphereBoundProbe(¢er
, radius
, &rayposition
, &raydirection
);
311 ok(result
== FALSE
, "expected FALSE, received TRUE\n");
313 rayposition
.x
= 5.0f
; rayposition
.y
= 11.0f
; rayposition
.z
= 9.0f
;
314 result
= D3DXSphereBoundProbe(¢er
, radius
, &rayposition
, &raydirection
);
315 ok(result
== FALSE
, "expected FALSE, received TRUE\n");
318 static void D3DXComputeBoundingBoxTest(void)
320 D3DXVECTOR3 exp_max
, exp_min
, got_max
, got_min
, vertex
[5];
323 vertex
[0].x
= 1.0f
; vertex
[0].y
= 1.0f
; vertex
[0].z
= 1.0f
;
324 vertex
[1].x
= 1.0f
; vertex
[1].y
= 1.0f
; vertex
[1].z
= 1.0f
;
325 vertex
[2].x
= 1.0f
; vertex
[2].y
= 1.0f
; vertex
[2].z
= 1.0f
;
326 vertex
[3].x
= 1.0f
; vertex
[3].y
= 1.0f
; vertex
[3].z
= 1.0f
;
327 vertex
[4].x
= 9.0f
; vertex
[4].y
= 9.0f
; vertex
[4].z
= 9.0f
;
329 exp_min
.x
= 1.0f
; exp_min
.y
= 1.0f
; exp_min
.z
= 1.0f
;
330 exp_max
.x
= 9.0f
; exp_max
.y
= 9.0f
; exp_max
.z
= 9.0f
;
332 hr
= D3DXComputeBoundingBox(&vertex
[3],2,D3DXGetFVFVertexSize(D3DFVF_XYZ
),&got_min
,&got_max
);
334 ok( hr
== D3D_OK
, "Expected D3D_OK, got %#x\n", hr
);
335 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
);
336 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
);
338 /*________________________*/
340 vertex
[0].x
= 2.0f
; vertex
[0].y
= 5.9f
; vertex
[0].z
= -1.2f
;
341 vertex
[1].x
= -1.87f
; vertex
[1].y
= 7.9f
; vertex
[1].z
= 7.4f
;
342 vertex
[2].x
= 7.43f
; vertex
[2].y
= -0.9f
; vertex
[2].z
= 11.9f
;
343 vertex
[3].x
= -6.92f
; vertex
[3].y
= 6.3f
; vertex
[3].z
= -3.8f
;
344 vertex
[4].x
= 11.4f
; vertex
[4].y
= -8.1f
; vertex
[4].z
= 4.5f
;
346 exp_min
.x
= -6.92f
; exp_min
.y
= -8.1f
; exp_min
.z
= -3.80f
;
347 exp_max
.x
= 11.4f
; exp_max
.y
= 7.90f
; exp_max
.z
= 11.9f
;
349 hr
= D3DXComputeBoundingBox(&vertex
[0],5,D3DXGetFVFVertexSize(D3DFVF_XYZ
),&got_min
,&got_max
);
351 ok( hr
== D3D_OK
, "Expected D3D_OK, got %#x\n", hr
);
352 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
);
353 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
);
355 /*________________________*/
357 vertex
[0].x
= 2.0f
; vertex
[0].y
= 5.9f
; vertex
[0].z
= -1.2f
;
358 vertex
[1].x
= -1.87f
; vertex
[1].y
= 7.9f
; vertex
[1].z
= 7.4f
;
359 vertex
[2].x
= 7.43f
; vertex
[2].y
= -0.9f
; vertex
[2].z
= 11.9f
;
360 vertex
[3].x
= -6.92f
; vertex
[3].y
= 6.3f
; vertex
[3].z
= -3.8f
;
361 vertex
[4].x
= 11.4f
; vertex
[4].y
= -8.1f
; vertex
[4].z
= 4.5f
;
363 exp_min
.x
= -6.92f
; exp_min
.y
= -0.9f
; exp_min
.z
= -3.8f
;
364 exp_max
.x
= 7.43f
; exp_max
.y
= 7.90f
; exp_max
.z
= 11.9f
;
366 hr
= D3DXComputeBoundingBox(&vertex
[0],4,D3DXGetFVFVertexSize(D3DFVF_XYZ
),&got_min
,&got_max
);
368 ok( hr
== D3D_OK
, "Expected D3D_OK, got %#x\n", hr
);
369 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
);
370 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
);
372 /*________________________*/
373 hr
= D3DXComputeBoundingBox(NULL
,5,D3DXGetFVFVertexSize(D3DFVF_XYZ
),&got_min
,&got_max
);
374 ok( hr
== D3DERR_INVALIDCALL
, "Expected D3DERR_INVALIDCALL, got %#x\n", hr
);
376 /*________________________*/
377 hr
= D3DXComputeBoundingBox(&vertex
[3],5,D3DXGetFVFVertexSize(D3DFVF_XYZ
),NULL
,&got_max
);
378 ok( hr
== D3DERR_INVALIDCALL
, "Expected D3DERR_INVALIDCALL, got %#x\n", hr
);
380 /*________________________*/
381 hr
= D3DXComputeBoundingBox(&vertex
[3],5,D3DXGetFVFVertexSize(D3DFVF_XYZ
),&got_min
,NULL
);
382 ok( hr
== D3DERR_INVALIDCALL
, "Expected D3DERR_INVALIDCALL, got %#x\n", hr
);
385 static void D3DXComputeBoundingSphereTest(void)
387 D3DXVECTOR3 exp_cen
, got_cen
, vertex
[5];
388 FLOAT exp_rad
, got_rad
;
391 vertex
[0].x
= 1.0f
; vertex
[0].y
= 1.0f
; vertex
[0].z
= 1.0f
;
392 vertex
[1].x
= 1.0f
; vertex
[1].y
= 1.0f
; vertex
[1].z
= 1.0f
;
393 vertex
[2].x
= 1.0f
; vertex
[2].y
= 1.0f
; vertex
[2].z
= 1.0f
;
394 vertex
[3].x
= 1.0f
; vertex
[3].y
= 1.0f
; vertex
[3].z
= 1.0f
;
395 vertex
[4].x
= 9.0f
; vertex
[4].y
= 9.0f
; vertex
[4].z
= 9.0f
;
398 exp_cen
.x
= 5.0; exp_cen
.y
= 5.0; exp_cen
.z
= 5.0;
400 hr
= D3DXComputeBoundingSphere(&vertex
[3],2,D3DXGetFVFVertexSize(D3DFVF_XYZ
),&got_cen
,&got_rad
);
402 ok( hr
== D3D_OK
, "Expected D3D_OK, got %#x\n", hr
);
403 ok( compare(exp_rad
, got_rad
), "Expected radius: %f, got radius: %f\n", exp_rad
, got_rad
);
404 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
);
406 /*________________________*/
408 vertex
[0].x
= 2.0f
; vertex
[0].y
= 5.9f
; vertex
[0].z
= -1.2f
;
409 vertex
[1].x
= -1.87f
; vertex
[1].y
= 7.9f
; vertex
[1].z
= 7.4f
;
410 vertex
[2].x
= 7.43f
; vertex
[2].y
= -0.9f
; vertex
[2].z
= 11.9f
;
411 vertex
[3].x
= -6.92f
; vertex
[3].y
= 6.3f
; vertex
[3].z
= -3.8f
;
412 vertex
[4].x
= 11.4f
; vertex
[4].y
= -8.1f
; vertex
[4].z
= 4.5f
;
414 exp_rad
= 13.707883f
;
415 exp_cen
.x
= 2.408f
; exp_cen
.y
= 2.22f
; exp_cen
.z
= 3.76f
;
417 hr
= D3DXComputeBoundingSphere(&vertex
[0],5,D3DXGetFVFVertexSize(D3DFVF_XYZ
),&got_cen
,&got_rad
);
419 ok( hr
== D3D_OK
, "Expected D3D_OK, got %#x\n", hr
);
420 ok( compare(exp_rad
, got_rad
), "Expected radius: %f, got radius: %f\n", exp_rad
, got_rad
);
421 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
);
423 /*________________________*/
424 hr
= D3DXComputeBoundingSphere(NULL
,5,D3DXGetFVFVertexSize(D3DFVF_XYZ
),&got_cen
,&got_rad
);
425 ok( hr
== D3DERR_INVALIDCALL
, "Expected D3DERR_INVALIDCALL, got %#x\n", hr
);
427 /*________________________*/
428 hr
= D3DXComputeBoundingSphere(&vertex
[3],5,D3DXGetFVFVertexSize(D3DFVF_XYZ
),NULL
,&got_rad
);
429 ok( hr
== D3DERR_INVALIDCALL
, "Expected D3DERR_INVALIDCALL, got %#x\n", hr
);
431 /*________________________*/
432 hr
= D3DXComputeBoundingSphere(&vertex
[3],5,D3DXGetFVFVertexSize(D3DFVF_XYZ
),&got_cen
,NULL
);
433 ok( hr
== D3DERR_INVALIDCALL
, "Expected D3DERR_INVALIDCALL, got %#x\n", hr
);
436 static void print_elements(const D3DVERTEXELEMENT9
*elements
)
438 D3DVERTEXELEMENT9 last
= D3DDECL_END();
439 const D3DVERTEXELEMENT9
*ptr
= elements
;
442 while (memcmp(ptr
, &last
, sizeof(D3DVERTEXELEMENT9
)))
445 "[Element %d] Stream = %d, Offset = %d, Type = %d, Method = %d, Usage = %d, UsageIndex = %d\n",
446 count
, ptr
->Stream
, ptr
->Offset
, ptr
->Type
, ptr
->Method
, ptr
->Usage
, ptr
->UsageIndex
);
452 static void compare_elements(const D3DVERTEXELEMENT9
*elements
, const D3DVERTEXELEMENT9
*expected_elements
,
453 unsigned int line
, unsigned int test_id
)
455 D3DVERTEXELEMENT9 last
= D3DDECL_END();
458 for (i
= 0; i
< MAX_FVF_DECL_SIZE
; i
++)
460 int end1
= memcmp(&elements
[i
], &last
, sizeof(last
));
461 int end2
= memcmp(&expected_elements
[i
], &last
, sizeof(last
));
464 if (!end1
&& !end2
) break;
466 status
= !end1
^ !end2
;
467 ok(!status
, "Line %u, test %u: Mismatch in size, test declaration is %s than expected.\n",
468 line
, test_id
, end1
? "shorter" : "longer");
471 print_elements(elements
);
475 status
= memcmp(&elements
[i
], &expected_elements
[i
], sizeof(D3DVERTEXELEMENT9
));
476 ok(!status
, "Line %u, test %u: Mismatch in element %u.\n", line
, test_id
, i
);
479 print_elements(elements
);
485 static void test_fvf_to_decl(DWORD test_fvf
, const D3DVERTEXELEMENT9 expected_elements
[],
486 HRESULT expected_hr
, unsigned int line
, unsigned int test_id
)
489 D3DVERTEXELEMENT9 decl
[MAX_FVF_DECL_SIZE
];
491 hr
= D3DXDeclaratorFromFVF(test_fvf
, decl
);
492 ok(hr
== expected_hr
,
493 "Line %u, test %u: D3DXDeclaratorFromFVF returned %#x, expected %#x.\n",
494 line
, test_id
, hr
, expected_hr
);
495 if (SUCCEEDED(hr
)) compare_elements(decl
, expected_elements
, line
, test_id
);
498 static void test_decl_to_fvf(const D3DVERTEXELEMENT9
*decl
, DWORD expected_fvf
,
499 HRESULT expected_hr
, unsigned int line
, unsigned int test_id
)
502 DWORD result_fvf
= 0xdeadbeef;
504 hr
= D3DXFVFFromDeclarator(decl
, &result_fvf
);
505 ok(hr
== expected_hr
,
506 "Line %u, test %u: D3DXFVFFromDeclarator returned %#x, expected %#x.\n",
507 line
, test_id
, hr
, expected_hr
);
510 ok(expected_fvf
== result_fvf
, "Line %u, test %u: Got FVF %#x, expected %#x.\n",
511 line
, test_id
, result_fvf
, expected_fvf
);
515 static void test_fvf_decl_conversion(void)
519 D3DVERTEXELEMENT9 decl
[MAXD3DDECLLENGTH
+ 1];
528 {0, 0, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_POSITION
, 0},
532 {0, 0, D3DDECLTYPE_FLOAT4
, 0, D3DDECLUSAGE_POSITIONT
, 0},
536 {0, 0, D3DDECLTYPE_FLOAT4
, 0, D3DDECLUSAGE_POSITIONT
, 0},
540 {0, 0, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_POSITION
, 0},
541 {0, 12, D3DDECLTYPE_FLOAT1
, 0, D3DDECLUSAGE_BLENDWEIGHT
, 0},
545 {0, 0, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_POSITION
, 0},
546 {0, 12, D3DDECLTYPE_UBYTE4
, 0, D3DDECLUSAGE_BLENDINDICES
, 0},
548 }, D3DFVF_XYZB1
| D3DFVF_LASTBETA_UBYTE4
},
550 {0, 0, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_POSITION
, 0},
551 {0, 12, D3DDECLTYPE_D3DCOLOR
, 0, D3DDECLUSAGE_BLENDINDICES
, 0},
553 }, D3DFVF_XYZB1
| D3DFVF_LASTBETA_D3DCOLOR
},
555 {0, 0, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_POSITION
, 0},
556 {0, 12, D3DDECLTYPE_FLOAT2
, 0, D3DDECLUSAGE_BLENDWEIGHT
, 0},
560 {0, 0, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_POSITION
, 0},
561 {0, 12, D3DDECLTYPE_FLOAT1
, 0, D3DDECLUSAGE_BLENDWEIGHT
, 0},
562 {0, 16, D3DDECLTYPE_UBYTE4
, 0, D3DDECLUSAGE_BLENDINDICES
, 0},
564 }, D3DFVF_XYZB2
| D3DFVF_LASTBETA_UBYTE4
},
566 {0, 0, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_POSITION
, 0},
567 {0, 12, D3DDECLTYPE_FLOAT1
, 0, D3DDECLUSAGE_BLENDWEIGHT
, 0},
568 {0, 16, D3DDECLTYPE_D3DCOLOR
, 0, D3DDECLUSAGE_BLENDINDICES
, 0},
570 }, D3DFVF_XYZB2
| D3DFVF_LASTBETA_D3DCOLOR
},
572 {0, 0, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_POSITION
, 0},
573 {0, 12, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_BLENDWEIGHT
, 0},
577 {0, 0, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_POSITION
, 0},
578 {0, 12, D3DDECLTYPE_FLOAT2
, 0, D3DDECLUSAGE_BLENDWEIGHT
, 0},
579 {0, 20, D3DDECLTYPE_UBYTE4
, 0, D3DDECLUSAGE_BLENDINDICES
, 0},
581 }, D3DFVF_XYZB3
| D3DFVF_LASTBETA_UBYTE4
},
583 {0, 0, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_POSITION
, 0},
584 {0, 12, D3DDECLTYPE_FLOAT2
, 0, D3DDECLUSAGE_BLENDWEIGHT
, 0},
585 {0, 20, D3DDECLTYPE_D3DCOLOR
, 0, D3DDECLUSAGE_BLENDINDICES
, 0},
587 }, D3DFVF_XYZB3
| D3DFVF_LASTBETA_D3DCOLOR
},
589 {0, 0, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_POSITION
, 0},
590 {0, 12, D3DDECLTYPE_FLOAT4
, 0, D3DDECLUSAGE_BLENDWEIGHT
, 0},
594 {0, 0, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_POSITION
, 0},
595 {0, 12, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_BLENDWEIGHT
, 0},
596 {0, 24, D3DDECLTYPE_UBYTE4
, 0, D3DDECLUSAGE_BLENDINDICES
, 0},
598 }, D3DFVF_XYZB4
| D3DFVF_LASTBETA_UBYTE4
},
600 {0, 0, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_POSITION
, 0},
601 {0, 12, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_BLENDWEIGHT
, 0},
602 {0, 24, D3DDECLTYPE_D3DCOLOR
, 0, D3DDECLUSAGE_BLENDINDICES
, 0},
604 }, D3DFVF_XYZB4
| D3DFVF_LASTBETA_D3DCOLOR
},
606 {0, 0, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_POSITION
, 0},
607 {0, 12, D3DDECLTYPE_FLOAT4
, 0, D3DDECLUSAGE_BLENDWEIGHT
, 0},
608 {0, 28, D3DDECLTYPE_UBYTE4
, 0, D3DDECLUSAGE_BLENDINDICES
, 0},
610 }, D3DFVF_XYZB5
| D3DFVF_LASTBETA_UBYTE4
},
612 {0, 0, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_POSITION
, 0},
613 {0, 12, D3DDECLTYPE_FLOAT4
, 0, D3DDECLUSAGE_BLENDWEIGHT
, 0},
614 {0, 28, D3DDECLTYPE_D3DCOLOR
, 0, D3DDECLUSAGE_BLENDINDICES
, 0},
616 }, D3DFVF_XYZB5
| D3DFVF_LASTBETA_D3DCOLOR
},
618 {0, 0, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_NORMAL
, 0},
622 {0, 0, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_NORMAL
, 0},
623 {0, 12, D3DDECLTYPE_D3DCOLOR
, 0, D3DDECLUSAGE_COLOR
, 0},
625 }, D3DFVF_NORMAL
| D3DFVF_DIFFUSE
},
627 {0, 0, D3DDECLTYPE_FLOAT1
, 0, D3DDECLUSAGE_PSIZE
, 0},
631 {0, 0, D3DDECLTYPE_D3DCOLOR
, 0, D3DDECLUSAGE_COLOR
, 0},
635 {0, 0, D3DDECLTYPE_D3DCOLOR
, 0, D3DDECLUSAGE_COLOR
, 1},
638 /* Make sure textures of different sizes work. */
640 {0, 0, D3DDECLTYPE_FLOAT1
, 0, D3DDECLUSAGE_TEXCOORD
, 0},
642 }, D3DFVF_TEXCOORDSIZE1(0) | D3DFVF_TEX1
},
644 {0, 0, D3DDECLTYPE_FLOAT2
, 0, D3DDECLUSAGE_TEXCOORD
, 0},
646 }, D3DFVF_TEXCOORDSIZE2(0) | D3DFVF_TEX1
},
648 {0, 0, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_TEXCOORD
, 0},
650 }, D3DFVF_TEXCOORDSIZE3(0) | D3DFVF_TEX1
},
652 {0, 0, D3DDECLTYPE_FLOAT4
, 0, D3DDECLUSAGE_TEXCOORD
, 0},
654 }, D3DFVF_TEXCOORDSIZE4(0) | D3DFVF_TEX1
},
655 /* Make sure the TEXCOORD index works correctly - try several textures. */
657 {0, 0, D3DDECLTYPE_FLOAT1
, 0, D3DDECLUSAGE_TEXCOORD
, 0},
658 {0, 4, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_TEXCOORD
, 1},
659 {0, 16, D3DDECLTYPE_FLOAT2
, 0, D3DDECLUSAGE_TEXCOORD
, 2},
660 {0, 24, D3DDECLTYPE_FLOAT4
, 0, D3DDECLUSAGE_TEXCOORD
, 3},
662 }, D3DFVF_TEX4
| D3DFVF_TEXCOORDSIZE1(0) | D3DFVF_TEXCOORDSIZE3(1)
663 | D3DFVF_TEXCOORDSIZE2(2) | D3DFVF_TEXCOORDSIZE4(3)},
664 /* Now try some combination tests. */
666 {0, 0, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_POSITION
, 0},
667 {0, 12, D3DDECLTYPE_FLOAT4
, 0, D3DDECLUSAGE_BLENDWEIGHT
, 0},
668 {0, 28, D3DDECLTYPE_D3DCOLOR
, 0, D3DDECLUSAGE_COLOR
, 0},
669 {0, 32, D3DDECLTYPE_D3DCOLOR
, 0, D3DDECLUSAGE_COLOR
, 1},
670 {0, 36, D3DDECLTYPE_FLOAT2
, 0, D3DDECLUSAGE_TEXCOORD
, 0},
671 {0, 44, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_TEXCOORD
, 1},
673 }, D3DFVF_XYZB4
| D3DFVF_DIFFUSE
| D3DFVF_SPECULAR
| D3DFVF_TEX2
674 | D3DFVF_TEXCOORDSIZE2(0) | D3DFVF_TEXCOORDSIZE3(1)},
676 {0, 0, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_POSITION
, 0},
677 {0, 12, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_NORMAL
, 0},
678 {0, 24, D3DDECLTYPE_FLOAT1
, 0, D3DDECLUSAGE_PSIZE
, 0},
679 {0, 28, D3DDECLTYPE_D3DCOLOR
, 0, D3DDECLUSAGE_COLOR
, 1},
680 {0, 32, D3DDECLTYPE_FLOAT1
, 0, D3DDECLUSAGE_TEXCOORD
, 0},
681 {0, 36, D3DDECLTYPE_FLOAT4
, 0, D3DDECLUSAGE_TEXCOORD
, 1},
683 }, D3DFVF_XYZ
| D3DFVF_NORMAL
| D3DFVF_PSIZE
| D3DFVF_SPECULAR
| D3DFVF_TEX2
684 | D3DFVF_TEXCOORDSIZE1(0) | D3DFVF_TEXCOORDSIZE4(1)},
688 for (i
= 0; i
< sizeof(test_data
) / sizeof(*test_data
); ++i
)
690 test_decl_to_fvf(test_data
[i
].decl
, test_data
[i
].fvf
, D3D_OK
, __LINE__
, i
);
691 test_fvf_to_decl(test_data
[i
].fvf
, test_data
[i
].decl
, D3D_OK
, __LINE__
, i
);
694 /* Usage indices for position and normal are apparently ignored. */
696 const D3DVERTEXELEMENT9 decl
[] =
698 {0, 0, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_POSITION
, 1},
701 test_decl_to_fvf(decl
, D3DFVF_XYZ
, D3D_OK
, __LINE__
, 0);
704 const D3DVERTEXELEMENT9 decl
[] =
706 {0, 0, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_NORMAL
, 1},
709 test_decl_to_fvf(decl
, D3DFVF_NORMAL
, D3D_OK
, __LINE__
, 0);
711 /* D3DFVF_LASTBETA_UBYTE4 and D3DFVF_LASTBETA_D3DCOLOR are ignored if
712 * there are no blend matrices. */
714 const D3DVERTEXELEMENT9 decl
[] =
716 {0, 0, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_POSITION
, 0},
719 test_fvf_to_decl(D3DFVF_XYZ
| D3DFVF_LASTBETA_UBYTE4
, decl
, D3D_OK
, __LINE__
, 0);
722 const D3DVERTEXELEMENT9 decl
[] =
724 {0, 0, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_POSITION
, 0},
727 test_fvf_to_decl(D3DFVF_XYZ
| D3DFVF_LASTBETA_D3DCOLOR
, decl
, D3D_OK
, __LINE__
, 0);
729 /* D3DFVF_LASTBETA_UBYTE4 takes precedence over D3DFVF_LASTBETA_D3DCOLOR. */
731 const D3DVERTEXELEMENT9 decl
[] =
733 {0, 0, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_POSITION
, 0},
734 {0, 12, D3DDECLTYPE_FLOAT4
, 0, D3DDECLUSAGE_BLENDWEIGHT
, 0},
735 {0, 28, D3DDECLTYPE_UBYTE4
, 0, D3DDECLUSAGE_BLENDINDICES
, 0},
738 test_fvf_to_decl(D3DFVF_XYZB5
| D3DFVF_LASTBETA_D3DCOLOR
| D3DFVF_LASTBETA_UBYTE4
,
739 decl
, D3D_OK
, __LINE__
, 0);
741 /* These are supposed to fail, both ways. */
743 const D3DVERTEXELEMENT9 decl
[] =
745 {0, 0, D3DDECLTYPE_FLOAT4
, 0, D3DDECLUSAGE_POSITION
, 0},
748 test_decl_to_fvf(decl
, D3DFVF_XYZW
, D3DERR_INVALIDCALL
, __LINE__
, 0);
749 test_fvf_to_decl(D3DFVF_XYZW
, decl
, D3DERR_INVALIDCALL
, __LINE__
, 0);
752 const D3DVERTEXELEMENT9 decl
[] =
754 {0, 0, D3DDECLTYPE_FLOAT4
, 0, D3DDECLUSAGE_POSITION
, 0},
755 {0, 16, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_NORMAL
, 0},
758 test_decl_to_fvf(decl
, D3DFVF_XYZW
| D3DFVF_NORMAL
, D3DERR_INVALIDCALL
, __LINE__
, 0);
759 test_fvf_to_decl(D3DFVF_XYZW
| D3DFVF_NORMAL
, decl
, D3DERR_INVALIDCALL
, __LINE__
, 0);
762 const D3DVERTEXELEMENT9 decl
[] =
764 {0, 0, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_POSITION
, 0},
765 {0, 12, D3DDECLTYPE_FLOAT4
, 0, D3DDECLUSAGE_BLENDWEIGHT
, 0},
766 {0, 28, D3DDECLTYPE_FLOAT1
, 0, D3DDECLUSAGE_BLENDINDICES
, 0},
769 test_decl_to_fvf(decl
, D3DFVF_XYZB5
, D3DERR_INVALIDCALL
, __LINE__
, 0);
770 test_fvf_to_decl(D3DFVF_XYZB5
, decl
, D3DERR_INVALIDCALL
, __LINE__
, 0);
772 /* Test a declaration that can't be converted to an FVF. */
774 const D3DVERTEXELEMENT9 decl
[] =
776 {0, 0, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_POSITION
, 0},
777 {0, 12, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_NORMAL
, 0},
778 {0, 24, D3DDECLTYPE_FLOAT1
, 0, D3DDECLUSAGE_PSIZE
, 0},
779 {0, 28, D3DDECLTYPE_D3DCOLOR
, 0, D3DDECLUSAGE_COLOR
, 1},
780 {0, 32, D3DDECLTYPE_FLOAT1
, 0, D3DDECLUSAGE_TEXCOORD
, 0},
781 /* 8 bytes padding */
782 {0, 44, D3DDECLTYPE_FLOAT4
, 0, D3DDECLUSAGE_TEXCOORD
, 1},
785 test_decl_to_fvf(decl
, 0, D3DERR_INVALIDCALL
, __LINE__
, 0);
787 /* Elements must be ordered by offset. */
789 const D3DVERTEXELEMENT9 decl
[] =
791 {0, 12, D3DDECLTYPE_D3DCOLOR
, 0, D3DDECLUSAGE_COLOR
, 0},
792 {0, 0, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_POSITION
, 0},
795 test_decl_to_fvf(decl
, 0, D3DERR_INVALIDCALL
, __LINE__
, 0);
797 /* Basic tests for element order. */
799 const D3DVERTEXELEMENT9 decl
[] =
801 {0, 0, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_POSITION
, 0},
802 {0, 12, D3DDECLTYPE_D3DCOLOR
, 0, D3DDECLUSAGE_COLOR
, 0},
803 {0, 16, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_NORMAL
, 0},
806 test_decl_to_fvf(decl
, 0, D3DERR_INVALIDCALL
, __LINE__
, 0);
809 const D3DVERTEXELEMENT9 decl
[] =
811 {0, 0, D3DDECLTYPE_D3DCOLOR
, 0, D3DDECLUSAGE_COLOR
, 0},
812 {0, 4, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_POSITION
, 0},
815 test_decl_to_fvf(decl
, 0, D3DERR_INVALIDCALL
, __LINE__
, 0);
818 const D3DVERTEXELEMENT9 decl
[] =
820 {0, 0, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_NORMAL
, 0},
821 {0, 12, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_POSITION
, 0},
824 test_decl_to_fvf(decl
, 0, D3DERR_INVALIDCALL
, __LINE__
, 0);
826 /* Textures must be ordered by texcoords. */
828 const D3DVERTEXELEMENT9 decl
[] =
830 {0, 0, D3DDECLTYPE_FLOAT1
, 0, D3DDECLUSAGE_TEXCOORD
, 0},
831 {0, 4, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_TEXCOORD
, 2},
832 {0, 16, D3DDECLTYPE_FLOAT2
, 0, D3DDECLUSAGE_TEXCOORD
, 1},
833 {0, 24, D3DDECLTYPE_FLOAT4
, 0, D3DDECLUSAGE_TEXCOORD
, 3},
836 test_decl_to_fvf(decl
, 0, D3DERR_INVALIDCALL
, __LINE__
, 0);
838 /* Duplicate elements are not allowed. */
840 const D3DVERTEXELEMENT9 decl
[] =
842 {0, 0, D3DDECLTYPE_FLOAT3
, 0, D3DDECLUSAGE_POSITION
, 0},
843 {0, 12, D3DDECLTYPE_D3DCOLOR
, 0, D3DDECLUSAGE_COLOR
, 0},
844 {0, 16, D3DDECLTYPE_D3DCOLOR
, 0, D3DDECLUSAGE_COLOR
, 0},
847 test_decl_to_fvf(decl
, 0, D3DERR_INVALIDCALL
, __LINE__
, 0);
849 /* Invalid FVFs cannot be converted to a declarator. */
850 test_fvf_to_decl(0xdeadbeef, NULL
, D3DERR_INVALIDCALL
, __LINE__
, 0);
853 static void D3DXGetFVFVertexSizeTest(void)
857 compare_vertex_sizes (D3DFVF_XYZ
, 12);
859 compare_vertex_sizes (D3DFVF_XYZB3
, 24);
861 compare_vertex_sizes (D3DFVF_XYZB5
, 32);
863 compare_vertex_sizes (D3DFVF_XYZ
| D3DFVF_NORMAL
, 24);
865 compare_vertex_sizes (D3DFVF_XYZ
| D3DFVF_DIFFUSE
, 16);
867 compare_vertex_sizes (
870 D3DFVF_TEXCOORDSIZE1(0), 16);
871 compare_vertex_sizes (
874 D3DFVF_TEXCOORDSIZE1(0) |
875 D3DFVF_TEXCOORDSIZE1(1), 20);
877 compare_vertex_sizes (
880 D3DFVF_TEXCOORDSIZE2(0), 20);
882 compare_vertex_sizes (
885 D3DFVF_TEXCOORDSIZE2(0) |
886 D3DFVF_TEXCOORDSIZE2(1), 28);
888 compare_vertex_sizes (
891 D3DFVF_TEXCOORDSIZE2(0) |
892 D3DFVF_TEXCOORDSIZE2(1) |
893 D3DFVF_TEXCOORDSIZE2(2) |
894 D3DFVF_TEXCOORDSIZE2(3) |
895 D3DFVF_TEXCOORDSIZE2(4) |
896 D3DFVF_TEXCOORDSIZE2(5), 60);
898 compare_vertex_sizes (
901 D3DFVF_TEXCOORDSIZE2(0) |
902 D3DFVF_TEXCOORDSIZE2(1) |
903 D3DFVF_TEXCOORDSIZE2(2) |
904 D3DFVF_TEXCOORDSIZE2(3) |
905 D3DFVF_TEXCOORDSIZE2(4) |
906 D3DFVF_TEXCOORDSIZE2(5) |
907 D3DFVF_TEXCOORDSIZE2(6) |
908 D3DFVF_TEXCOORDSIZE2(7), 76);
910 compare_vertex_sizes (
913 D3DFVF_TEXCOORDSIZE3(0), 24);
915 compare_vertex_sizes (
918 D3DFVF_TEXCOORDSIZE3(0) |
919 D3DFVF_TEXCOORDSIZE3(1) |
920 D3DFVF_TEXCOORDSIZE3(2) |
921 D3DFVF_TEXCOORDSIZE3(3), 60);
923 compare_vertex_sizes (
926 D3DFVF_TEXCOORDSIZE4(0), 28);
928 compare_vertex_sizes (
931 D3DFVF_TEXCOORDSIZE4(0) |
932 D3DFVF_TEXCOORDSIZE4(1), 44);
934 compare_vertex_sizes (
937 D3DFVF_TEXCOORDSIZE4(0) |
938 D3DFVF_TEXCOORDSIZE4(1) |
939 D3DFVF_TEXCOORDSIZE4(2), 60);
941 compare_vertex_sizes (
947 D3DFVF_TEXCOORDSIZE4(0) |
948 D3DFVF_TEXCOORDSIZE4(1) |
949 D3DFVF_TEXCOORDSIZE4(2) |
950 D3DFVF_TEXCOORDSIZE4(3) |
951 D3DFVF_TEXCOORDSIZE4(4) |
952 D3DFVF_TEXCOORDSIZE4(5) |
953 D3DFVF_TEXCOORDSIZE4(6) |
954 D3DFVF_TEXCOORDSIZE4(7), 180);
957 static void D3DXIntersectTriTest(void)
959 BOOL exp_res
, got_res
;
960 D3DXVECTOR3 position
, ray
, vertex
[3];
961 FLOAT exp_dist
, got_dist
, exp_u
, got_u
, exp_v
, got_v
;
963 vertex
[0].x
= 1.0f
; vertex
[0].y
= 0.0f
; vertex
[0].z
= 0.0f
;
964 vertex
[1].x
= 2.0f
; vertex
[1].y
= 0.0f
; vertex
[1].z
= 0.0f
;
965 vertex
[2].x
= 1.0f
; vertex
[2].y
= 1.0f
; vertex
[2].z
= 0.0f
;
967 position
.x
= -14.5f
; position
.y
= -23.75f
; position
.z
= -32.0f
;
969 ray
.x
= 2.0f
; ray
.y
= 3.0f
; ray
.z
= 4.0f
;
971 exp_res
= TRUE
; exp_u
= 0.5f
; exp_v
= 0.25f
; exp_dist
= 8.0f
;
973 got_res
= D3DXIntersectTri(&vertex
[0],&vertex
[1],&vertex
[2],&position
,&ray
,&got_u
,&got_v
,&got_dist
);
974 ok( got_res
== exp_res
, "Expected result = %d, got %d\n",exp_res
,got_res
);
975 ok( compare(exp_u
,got_u
), "Expected u = %f, got %f\n",exp_u
,got_u
);
976 ok( compare(exp_v
,got_v
), "Expected v = %f, got %f\n",exp_v
,got_v
);
977 ok( compare(exp_dist
,got_dist
), "Expected distance = %f, got %f\n",exp_dist
,got_dist
);
979 /*Only positive ray is taken in account*/
981 vertex
[0].x
= 1.0f
; vertex
[0].y
= 0.0f
; vertex
[0].z
= 0.0f
;
982 vertex
[1].x
= 2.0f
; vertex
[1].y
= 0.0f
; vertex
[1].z
= 0.0f
;
983 vertex
[2].x
= 1.0f
; vertex
[2].y
= 1.0f
; vertex
[2].z
= 0.0f
;
985 position
.x
= 17.5f
; position
.y
= 24.25f
; position
.z
= 32.0f
;
987 ray
.x
= 2.0f
; ray
.y
= 3.0f
; ray
.z
= 4.0f
;
991 got_res
= D3DXIntersectTri(&vertex
[0],&vertex
[1],&vertex
[2],&position
,&ray
,&got_u
,&got_v
,&got_dist
);
992 ok( got_res
== exp_res
, "Expected result = %d, got %d\n",exp_res
,got_res
);
994 /*Intersection between ray and triangle in a same plane is considered as empty*/
996 vertex
[0].x
= 4.0f
; vertex
[0].y
= 0.0f
; vertex
[0].z
= 0.0f
;
997 vertex
[1].x
= 6.0f
; vertex
[1].y
= 0.0f
; vertex
[1].z
= 0.0f
;
998 vertex
[2].x
= 4.0f
; vertex
[2].y
= 2.0f
; vertex
[2].z
= 0.0f
;
1000 position
.x
= 1.0f
; position
.y
= 1.0f
; position
.z
= 0.0f
;
1002 ray
.x
= 1.0f
; ray
.y
= 0.0f
; ray
.z
= 0.0f
;
1006 got_res
= D3DXIntersectTri(&vertex
[0],&vertex
[1],&vertex
[2],&position
,&ray
,&got_u
,&got_v
,&got_dist
);
1007 ok( got_res
== exp_res
, "Expected result = %d, got %d\n",exp_res
,got_res
);
1010 static void D3DXCreateMeshTest(void)
1015 IDirect3DDevice9
*device
, *test_device
;
1016 D3DPRESENT_PARAMETERS d3dpp
;
1017 ID3DXMesh
*d3dxmesh
;
1019 D3DVERTEXELEMENT9 test_decl
[MAX_FVF_DECL_SIZE
];
1023 static const D3DVERTEXELEMENT9 decl1
[3] = {
1024 {0, 0, D3DDECLTYPE_FLOAT3
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
1025 {0, 12, D3DDECLTYPE_FLOAT3
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_NORMAL
, 0},
1028 static const D3DVERTEXELEMENT9 decl2
[] = {
1029 {0, 0, D3DDECLTYPE_FLOAT3
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
1030 {0, 12, D3DDECLTYPE_FLOAT3
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_NORMAL
, 0},
1031 {0, 24, D3DDECLTYPE_FLOAT1
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_PSIZE
, 0},
1032 {0, 28, D3DDECLTYPE_D3DCOLOR
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_COLOR
, 1},
1033 {0, 32, D3DDECLTYPE_FLOAT1
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_TEXCOORD
, 0},
1034 /* 8 bytes padding */
1035 {0, 44, D3DDECLTYPE_FLOAT4
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_TEXCOORD
, 1},
1039 static const D3DVERTEXELEMENT9 decl3
[] = {
1040 {0, 0, D3DDECLTYPE_FLOAT3
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
1041 {1, 0, D3DDECLTYPE_FLOAT3
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_NORMAL
, 0},
1045 hr
= D3DXCreateMesh(0, 0, 0, NULL
, NULL
, NULL
);
1046 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr
, D3DERR_INVALIDCALL
);
1048 hr
= D3DXCreateMesh(1, 3, D3DXMESH_MANAGED
, decl1
, NULL
, &d3dxmesh
);
1049 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr
, D3DERR_INVALIDCALL
);
1051 wnd
= CreateWindow("static", "d3dx9_test", 0, 0, 0, 0, 0, NULL
, NULL
, NULL
, NULL
);
1054 skip("Couldn't create application window\n");
1057 d3d
= Direct3DCreate9(D3D_SDK_VERSION
);
1060 skip("Couldn't create IDirect3D9 object\n");
1065 ZeroMemory(&d3dpp
, sizeof(d3dpp
));
1066 d3dpp
.Windowed
= TRUE
;
1067 d3dpp
.SwapEffect
= D3DSWAPEFFECT_DISCARD
;
1068 hr
= IDirect3D9_CreateDevice(d3d
, D3DADAPTER_DEFAULT
, D3DDEVTYPE_HAL
, wnd
, D3DCREATE_MIXED_VERTEXPROCESSING
, &d3dpp
, &device
);
1071 skip("Failed to create IDirect3DDevice9 object %#x\n", hr
);
1072 IDirect3D9_Release(d3d
);
1077 hr
= D3DXCreateMesh(0, 3, D3DXMESH_MANAGED
, decl1
, device
, &d3dxmesh
);
1078 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr
, D3DERR_INVALIDCALL
);
1080 hr
= D3DXCreateMesh(1, 0, D3DXMESH_MANAGED
, decl1
, device
, &d3dxmesh
);
1081 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr
, D3DERR_INVALIDCALL
);
1083 hr
= D3DXCreateMesh(1, 3, 0, decl1
, device
, &d3dxmesh
);
1084 ok(hr
== D3D_OK
, "Got result %x, expected %x (D3D_OK)\n", hr
, D3D_OK
);
1088 d3dxmesh
->lpVtbl
->Release(d3dxmesh
);
1091 hr
= D3DXCreateMesh(1, 3, D3DXMESH_MANAGED
, 0, device
, &d3dxmesh
);
1092 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr
, D3DERR_INVALIDCALL
);
1094 hr
= D3DXCreateMesh(1, 3, D3DXMESH_MANAGED
, decl1
, device
, NULL
);
1095 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr
, D3DERR_INVALIDCALL
);
1097 hr
= D3DXCreateMesh(1, 3, D3DXMESH_MANAGED
, decl1
, device
, &d3dxmesh
);
1098 ok(hr
== D3D_OK
, "Got result %x, expected 0 (D3D_OK)\n", hr
);
1103 hr
= d3dxmesh
->lpVtbl
->GetDevice(d3dxmesh
, NULL
);
1104 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr
, D3DERR_INVALIDCALL
);
1106 hr
= d3dxmesh
->lpVtbl
->GetDevice(d3dxmesh
, &test_device
);
1107 ok(hr
== D3D_OK
, "Got result %x, expected %x (D3D_OK)\n", hr
, D3D_OK
);
1108 ok(test_device
== device
, "Got result %p, expected %p\n", test_device
, device
);
1112 IDirect3DDevice9_Release(device
);
1116 hr
= d3dxmesh
->lpVtbl
->GetDeclaration(d3dxmesh
, NULL
);
1117 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr
, D3DERR_INVALIDCALL
);
1119 hr
= d3dxmesh
->lpVtbl
->GetDeclaration(d3dxmesh
, test_decl
);
1120 ok(hr
== D3D_OK
, "Got result %x, expected 0 (D3D_OK)\n", hr
);
1124 size
= sizeof(decl1
) / sizeof(decl1
[0]);
1125 for (i
= 0; i
< size
- 1; i
++)
1127 ok(test_decl
[i
].Stream
== decl1
[i
].Stream
, "Returned stream %d, expected %d\n", test_decl
[i
].Stream
, decl1
[i
].Stream
);
1128 ok(test_decl
[i
].Type
== decl1
[i
].Type
, "Returned type %d, expected %d\n", test_decl
[i
].Type
, decl1
[i
].Type
);
1129 ok(test_decl
[i
].Method
== decl1
[i
].Method
, "Returned method %d, expected %d\n", test_decl
[i
].Method
, decl1
[i
].Method
);
1130 ok(test_decl
[i
].Usage
== decl1
[i
].Usage
, "Returned usage %d, expected %d\n", test_decl
[i
].Usage
, decl1
[i
].Usage
);
1131 ok(test_decl
[i
].UsageIndex
== decl1
[i
].UsageIndex
, "Returned usage index %d, expected %d\n", test_decl
[i
].UsageIndex
, decl1
[i
].UsageIndex
);
1132 ok(test_decl
[i
].Offset
== decl1
[i
].Offset
, "Returned offset %d, expected %d\n", test_decl
[i
].Offset
, decl1
[i
].Offset
);
1134 ok(decl1
[size
-1].Stream
== 0xFF, "Returned too long vertex declaration\n"); /* end element */
1138 options
= d3dxmesh
->lpVtbl
->GetOptions(d3dxmesh
);
1139 ok(options
== D3DXMESH_MANAGED
, "Got result %x, expected %x (D3DXMESH_MANAGED)\n", options
, D3DXMESH_MANAGED
);
1142 if (!new_mesh(&mesh
, 3, 1))
1144 skip("Couldn't create mesh\n");
1148 memset(mesh
.vertices
, 0, mesh
.number_of_vertices
* sizeof(*mesh
.vertices
));
1149 memset(mesh
.faces
, 0, mesh
.number_of_faces
* sizeof(*mesh
.faces
));
1150 mesh
.fvf
= D3DFVF_XYZ
| D3DFVF_NORMAL
;
1152 compare_mesh("createmesh1", d3dxmesh
, &mesh
);
1157 d3dxmesh
->lpVtbl
->Release(d3dxmesh
);
1160 /* Test a declaration that can't be converted to an FVF. */
1161 hr
= D3DXCreateMesh(1, 3, D3DXMESH_MANAGED
, decl2
, device
, &d3dxmesh
);
1162 ok(hr
== D3D_OK
, "Got result %x, expected 0 (D3D_OK)\n", hr
);
1167 hr
= d3dxmesh
->lpVtbl
->GetDevice(d3dxmesh
, NULL
);
1168 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr
, D3DERR_INVALIDCALL
);
1170 hr
= d3dxmesh
->lpVtbl
->GetDevice(d3dxmesh
, &test_device
);
1171 ok(hr
== D3D_OK
, "Got result %x, expected %x (D3D_OK)\n", hr
, D3D_OK
);
1172 ok(test_device
== device
, "Got result %p, expected %p\n", test_device
, device
);
1176 IDirect3DDevice9_Release(device
);
1180 hr
= d3dxmesh
->lpVtbl
->GetDeclaration(d3dxmesh
, test_decl
);
1181 ok(hr
== D3D_OK
, "Got result %x, expected 0 (D3D_OK)\n", hr
);
1185 size
= sizeof(decl2
) / sizeof(decl2
[0]);
1186 for (i
= 0; i
< size
- 1; i
++)
1188 ok(test_decl
[i
].Stream
== decl2
[i
].Stream
, "Returned stream %d, expected %d\n", test_decl
[i
].Stream
, decl2
[i
].Stream
);
1189 ok(test_decl
[i
].Type
== decl2
[i
].Type
, "Returned type %d, expected %d\n", test_decl
[i
].Type
, decl2
[i
].Type
);
1190 ok(test_decl
[i
].Method
== decl2
[i
].Method
, "Returned method %d, expected %d\n", test_decl
[i
].Method
, decl2
[i
].Method
);
1191 ok(test_decl
[i
].Usage
== decl2
[i
].Usage
, "Returned usage %d, expected %d\n", test_decl
[i
].Usage
, decl2
[i
].Usage
);
1192 ok(test_decl
[i
].UsageIndex
== decl2
[i
].UsageIndex
, "Returned usage index %d, expected %d\n", test_decl
[i
].UsageIndex
, decl2
[i
].UsageIndex
);
1193 ok(test_decl
[i
].Offset
== decl2
[i
].Offset
, "Returned offset %d, expected %d\n", test_decl
[i
].Offset
, decl2
[i
].Offset
);
1195 ok(decl2
[size
-1].Stream
== 0xFF, "Returned too long vertex declaration\n"); /* end element */
1199 options
= d3dxmesh
->lpVtbl
->GetOptions(d3dxmesh
);
1200 ok(options
== D3DXMESH_MANAGED
, "Got result %x, expected %x (D3DXMESH_MANAGED)\n", options
, D3DXMESH_MANAGED
);
1203 if (!new_mesh(&mesh
, 3, 1))
1205 skip("Couldn't create mesh\n");
1209 memset(mesh
.vertices
, 0, mesh
.number_of_vertices
* sizeof(*mesh
.vertices
));
1210 memset(mesh
.faces
, 0, mesh
.number_of_faces
* sizeof(*mesh
.faces
));
1212 mesh
.vertex_size
= 60;
1214 compare_mesh("createmesh2", d3dxmesh
, &mesh
);
1219 d3dxmesh
->lpVtbl
->Release(d3dxmesh
);
1222 /* Test a declaration with multiple streams. */
1223 hr
= D3DXCreateMesh(1, 3, D3DXMESH_MANAGED
, decl3
, device
, &d3dxmesh
);
1224 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr
, D3DERR_INVALIDCALL
);
1226 IDirect3DDevice9_Release(device
);
1227 IDirect3D9_Release(d3d
);
1231 static void D3DXCreateMeshFVFTest(void)
1236 IDirect3DDevice9
*device
, *test_device
;
1237 D3DPRESENT_PARAMETERS d3dpp
;
1238 ID3DXMesh
*d3dxmesh
;
1240 D3DVERTEXELEMENT9 test_decl
[MAX_FVF_DECL_SIZE
];
1244 static const D3DVERTEXELEMENT9 decl
[3] = {
1245 {0, 0, D3DDECLTYPE_FLOAT3
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
1246 {0, 12, D3DDECLTYPE_FLOAT3
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_NORMAL
, 0},
1249 hr
= D3DXCreateMeshFVF(0, 0, 0, 0, NULL
, NULL
);
1250 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr
, D3DERR_INVALIDCALL
);
1252 hr
= D3DXCreateMeshFVF(1, 3, D3DXMESH_MANAGED
, D3DFVF_XYZ
| D3DFVF_NORMAL
, NULL
, &d3dxmesh
);
1253 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr
, D3DERR_INVALIDCALL
);
1255 wnd
= CreateWindow("static", "d3dx9_test", 0, 0, 0, 0, 0, NULL
, NULL
, NULL
, NULL
);
1258 skip("Couldn't create application window\n");
1261 d3d
= Direct3DCreate9(D3D_SDK_VERSION
);
1264 skip("Couldn't create IDirect3D9 object\n");
1269 ZeroMemory(&d3dpp
, sizeof(d3dpp
));
1270 d3dpp
.Windowed
= TRUE
;
1271 d3dpp
.SwapEffect
= D3DSWAPEFFECT_DISCARD
;
1272 hr
= IDirect3D9_CreateDevice(d3d
, D3DADAPTER_DEFAULT
, D3DDEVTYPE_HAL
, wnd
, D3DCREATE_MIXED_VERTEXPROCESSING
, &d3dpp
, &device
);
1275 skip("Failed to create IDirect3DDevice9 object %#x\n", hr
);
1276 IDirect3D9_Release(d3d
);
1281 hr
= D3DXCreateMeshFVF(0, 3, D3DXMESH_MANAGED
, D3DFVF_XYZ
| D3DFVF_NORMAL
, device
, &d3dxmesh
);
1282 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr
, D3DERR_INVALIDCALL
);
1284 hr
= D3DXCreateMeshFVF(1, 0, D3DXMESH_MANAGED
, D3DFVF_XYZ
| D3DFVF_NORMAL
, device
, &d3dxmesh
);
1285 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr
, D3DERR_INVALIDCALL
);
1287 hr
= D3DXCreateMeshFVF(1, 3, 0, D3DFVF_XYZ
| D3DFVF_NORMAL
, device
, &d3dxmesh
);
1288 ok(hr
== D3D_OK
, "Got result %x, expected %x (D3D_OK)\n", hr
, D3D_OK
);
1292 d3dxmesh
->lpVtbl
->Release(d3dxmesh
);
1295 hr
= D3DXCreateMeshFVF(1, 3, D3DXMESH_MANAGED
, 0xdeadbeef, device
, &d3dxmesh
);
1296 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr
, D3DERR_INVALIDCALL
);
1298 hr
= D3DXCreateMeshFVF(1, 3, D3DXMESH_MANAGED
, D3DFVF_XYZ
| D3DFVF_NORMAL
, device
, NULL
);
1299 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr
, D3DERR_INVALIDCALL
);
1301 hr
= D3DXCreateMeshFVF(1, 3, D3DXMESH_MANAGED
, D3DFVF_XYZ
| D3DFVF_NORMAL
, device
, &d3dxmesh
);
1302 ok(hr
== D3D_OK
, "Got result %x, expected 0 (D3D_OK)\n", hr
);
1307 hr
= d3dxmesh
->lpVtbl
->GetDevice(d3dxmesh
, NULL
);
1308 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr
, D3DERR_INVALIDCALL
);
1310 hr
= d3dxmesh
->lpVtbl
->GetDevice(d3dxmesh
, &test_device
);
1311 ok(hr
== D3D_OK
, "Got result %x, expected %x (D3D_OK)\n", hr
, D3D_OK
);
1312 ok(test_device
== device
, "Got result %p, expected %p\n", test_device
, device
);
1316 IDirect3DDevice9_Release(device
);
1320 hr
= d3dxmesh
->lpVtbl
->GetDeclaration(d3dxmesh
, NULL
);
1321 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr
, D3DERR_INVALIDCALL
);
1323 hr
= d3dxmesh
->lpVtbl
->GetDeclaration(d3dxmesh
, test_decl
);
1324 ok(hr
== D3D_OK
, "Got result %x, expected 0 (D3D_OK)\n", hr
);
1328 size
= sizeof(decl
) / sizeof(decl
[0]);
1329 for (i
= 0; i
< size
- 1; i
++)
1331 ok(test_decl
[i
].Stream
== decl
[i
].Stream
, "Returned stream %d, expected %d\n", test_decl
[i
].Stream
, decl
[i
].Stream
);
1332 ok(test_decl
[i
].Type
== decl
[i
].Type
, "Returned type %d, expected %d\n", test_decl
[i
].Type
, decl
[i
].Type
);
1333 ok(test_decl
[i
].Method
== decl
[i
].Method
, "Returned method %d, expected %d\n", test_decl
[i
].Method
, decl
[i
].Method
);
1334 ok(test_decl
[i
].Usage
== decl
[i
].Usage
, "Returned usage %d, expected %d\n", test_decl
[i
].Usage
, decl
[i
].Usage
);
1335 ok(test_decl
[i
].UsageIndex
== decl
[i
].UsageIndex
, "Returned usage index %d, expected %d\n",
1336 test_decl
[i
].UsageIndex
, decl
[i
].UsageIndex
);
1337 ok(test_decl
[i
].Offset
== decl
[i
].Offset
, "Returned offset %d, expected %d\n", test_decl
[i
].Offset
, decl
[i
].Offset
);
1339 ok(decl
[size
-1].Stream
== 0xFF, "Returned too long vertex declaration\n"); /* end element */
1343 options
= d3dxmesh
->lpVtbl
->GetOptions(d3dxmesh
);
1344 ok(options
== D3DXMESH_MANAGED
, "Got result %x, expected %x (D3DXMESH_MANAGED)\n", options
, D3DXMESH_MANAGED
);
1347 if (!new_mesh(&mesh
, 3, 1))
1349 skip("Couldn't create mesh\n");
1353 memset(mesh
.vertices
, 0, mesh
.number_of_vertices
* sizeof(*mesh
.vertices
));
1354 memset(mesh
.faces
, 0, mesh
.number_of_faces
* sizeof(*mesh
.faces
));
1355 mesh
.fvf
= D3DFVF_XYZ
| D3DFVF_NORMAL
;
1357 compare_mesh("createmeshfvf", d3dxmesh
, &mesh
);
1362 d3dxmesh
->lpVtbl
->Release(d3dxmesh
);
1365 IDirect3DDevice9_Release(device
);
1366 IDirect3D9_Release(d3d
);
1370 static void D3DXCreateBoxTest(void)
1376 IDirect3DDevice9
* device
;
1377 D3DPRESENT_PARAMETERS d3dpp
;
1379 ID3DXBuffer
* ppBuffer
;
1381 static const DWORD adjacency
[36]=
1387 1, 3, 11, 5, 6, 10};
1390 wc
.lpfnWndProc
= DefWindowProcA
;
1391 wc
.lpszClassName
= "d3dx9_test_wc";
1392 if (!RegisterClass(&wc
))
1394 skip("RegisterClass failed\n");
1398 wnd
= CreateWindow("d3dx9_test_wc", "d3dx9_test",
1399 WS_SYSMENU
| WS_POPUP
, 0, 0, 640, 480, 0, 0, 0, 0);
1400 ok(wnd
!= NULL
, "Expected to have a window, received NULL\n");
1403 skip("Couldn't create application window\n");
1407 d3d
= Direct3DCreate9(D3D_SDK_VERSION
);
1410 skip("Couldn't create IDirect3D9 object\n");
1415 memset(&d3dpp
, 0, sizeof(d3dpp
));
1416 d3dpp
.Windowed
= TRUE
;
1417 d3dpp
.SwapEffect
= D3DSWAPEFFECT_DISCARD
;
1418 hr
= IDirect3D9_CreateDevice(d3d
, D3DADAPTER_DEFAULT
, D3DDEVTYPE_HAL
, wnd
, D3DCREATE_MIXED_VERTEXPROCESSING
, &d3dpp
, &device
);
1421 skip("Failed to create IDirect3DDevice9 object %#x\n", hr
);
1422 IDirect3D9_Release(d3d
);
1427 hr
= D3DXCreateBuffer(36 * sizeof(DWORD
), &ppBuffer
);
1428 ok(hr
==D3D_OK
, "Expected D3D_OK, received %#x\n", hr
);
1429 if (FAILED(hr
)) goto end
;
1431 hr
= D3DXCreateBox(device
,2.0f
,20.0f
,4.9f
,NULL
, &ppBuffer
);
1432 todo_wine
ok(hr
==D3DERR_INVALIDCALL
, "Expected D3DERR_INVALIDCALL, received %#x\n", hr
);
1434 hr
= D3DXCreateBox(NULL
,22.0f
,20.0f
,4.9f
,&box
, &ppBuffer
);
1435 todo_wine
ok(hr
==D3DERR_INVALIDCALL
, "Expected D3DERR_INVALIDCALL, received %#x\n", hr
);
1437 hr
= D3DXCreateBox(device
,-2.0f
,20.0f
,4.9f
,&box
, &ppBuffer
);
1438 todo_wine
ok(hr
==D3DERR_INVALIDCALL
, "Expected D3DERR_INVALIDCALL, received %#x\n", hr
);
1440 hr
= D3DXCreateBox(device
,22.0f
,-20.0f
,4.9f
,&box
, &ppBuffer
);
1441 todo_wine
ok(hr
==D3DERR_INVALIDCALL
, "Expected D3DERR_INVALIDCALL, received %#x\n", hr
);
1443 hr
= D3DXCreateBox(device
,22.0f
,20.0f
,-4.9f
,&box
, &ppBuffer
);
1444 todo_wine
ok(hr
==D3DERR_INVALIDCALL
, "Expected D3DERR_INVALIDCALL, received %#x\n", hr
);
1446 hr
= D3DXCreateBox(device
,10.9f
,20.0f
,4.9f
,&box
, &ppBuffer
);
1447 todo_wine
ok(hr
==D3D_OK
, "Expected D3D_OK, received %#x\n", hr
);
1451 skip("D3DXCreateBox failed\n");
1455 buffer
= ID3DXBuffer_GetBufferPointer(ppBuffer
);
1457 todo_wine
ok(adjacency
[i
]==buffer
[i
], "expected adjacency %d: %#x, received %#x\n",i
,adjacency
[i
], buffer
[i
]);
1459 box
->lpVtbl
->Release(box
);
1462 IDirect3DDevice9_Release(device
);
1463 IDirect3D9_Release(d3d
);
1464 ID3DXBuffer_Release(ppBuffer
);
1474 static void free_sincos_table(struct sincos_table
*sincos_table
)
1476 HeapFree(GetProcessHeap(), 0, sincos_table
->cos
);
1477 HeapFree(GetProcessHeap(), 0, sincos_table
->sin
);
1480 /* pre compute sine and cosine tables; caller must free */
1481 static BOOL
compute_sincos_table(struct sincos_table
*sincos_table
, float angle_start
, float angle_step
, int n
)
1486 sincos_table
->sin
= HeapAlloc(GetProcessHeap(), 0, n
* sizeof(*sincos_table
->sin
));
1487 if (!sincos_table
->sin
)
1491 sincos_table
->cos
= HeapAlloc(GetProcessHeap(), 0, n
* sizeof(*sincos_table
->cos
));
1492 if (!sincos_table
->cos
)
1494 HeapFree(GetProcessHeap(), 0, sincos_table
->sin
);
1498 angle
= angle_start
;
1499 for (i
= 0; i
< n
; i
++)
1501 sincos_table
->sin
[i
] = sin(angle
);
1502 sincos_table
->cos
[i
] = cos(angle
);
1503 angle
+= angle_step
;
1509 static WORD
vertex_index(UINT slices
, int slice
, int stack
)
1511 return stack
*slices
+slice
+1;
1514 /* slices = subdivisions along xy plane, stacks = subdivisions along z axis */
1515 static BOOL
compute_sphere(struct mesh
*mesh
, FLOAT radius
, UINT slices
, UINT stacks
)
1517 float theta_step
, theta_start
;
1518 struct sincos_table theta
;
1519 float phi_step
, phi_start
;
1520 struct sincos_table phi
;
1521 DWORD number_of_vertices
, number_of_faces
;
1525 /* theta = angle on xy plane wrt x axis */
1526 theta_step
= M_PI
/ stacks
;
1527 theta_start
= theta_step
;
1529 /* phi = angle on xz plane wrt z axis */
1530 phi_step
= -2 * M_PI
/ slices
;
1531 phi_start
= M_PI
/ 2;
1533 if (!compute_sincos_table(&theta
, theta_start
, theta_step
, stacks
))
1537 if (!compute_sincos_table(&phi
, phi_start
, phi_step
, slices
))
1539 free_sincos_table(&theta
);
1543 number_of_vertices
= 2 + slices
* (stacks
-1);
1544 number_of_faces
= 2 * slices
+ (stacks
- 2) * (2 * slices
);
1546 if (!new_mesh(mesh
, number_of_vertices
, number_of_faces
))
1548 free_sincos_table(&phi
);
1549 free_sincos_table(&theta
);
1556 mesh
->vertices
[vertex
].normal
.x
= 0.0f
;
1557 mesh
->vertices
[vertex
].normal
.y
= 0.0f
;
1558 mesh
->vertices
[vertex
].normal
.z
= 1.0f
;
1559 mesh
->vertices
[vertex
].position
.x
= 0.0f
;
1560 mesh
->vertices
[vertex
].position
.y
= 0.0f
;
1561 mesh
->vertices
[vertex
].position
.z
= radius
;
1564 for (stack
= 0; stack
< stacks
- 1; stack
++)
1566 for (slice
= 0; slice
< slices
; slice
++)
1568 mesh
->vertices
[vertex
].normal
.x
= theta
.sin
[stack
] * phi
.cos
[slice
];
1569 mesh
->vertices
[vertex
].normal
.y
= theta
.sin
[stack
] * phi
.sin
[slice
];
1570 mesh
->vertices
[vertex
].normal
.z
= theta
.cos
[stack
];
1571 mesh
->vertices
[vertex
].position
.x
= radius
* theta
.sin
[stack
] * phi
.cos
[slice
];
1572 mesh
->vertices
[vertex
].position
.y
= radius
* theta
.sin
[stack
] * phi
.sin
[slice
];
1573 mesh
->vertices
[vertex
].position
.z
= radius
* theta
.cos
[stack
];
1580 /* top stack is triangle fan */
1581 mesh
->faces
[face
][0] = 0;
1582 mesh
->faces
[face
][1] = slice
+ 1;
1583 mesh
->faces
[face
][2] = slice
;
1588 /* stacks in between top and bottom are quad strips */
1589 mesh
->faces
[face
][0] = vertex_index(slices
, slice
-1, stack
-1);
1590 mesh
->faces
[face
][1] = vertex_index(slices
, slice
, stack
-1);
1591 mesh
->faces
[face
][2] = vertex_index(slices
, slice
-1, stack
);
1594 mesh
->faces
[face
][0] = vertex_index(slices
, slice
, stack
-1);
1595 mesh
->faces
[face
][1] = vertex_index(slices
, slice
, stack
);
1596 mesh
->faces
[face
][2] = vertex_index(slices
, slice
-1, stack
);
1604 mesh
->faces
[face
][0] = 0;
1605 mesh
->faces
[face
][1] = 1;
1606 mesh
->faces
[face
][2] = slice
;
1611 mesh
->faces
[face
][0] = vertex_index(slices
, slice
-1, stack
-1);
1612 mesh
->faces
[face
][1] = vertex_index(slices
, 0, stack
-1);
1613 mesh
->faces
[face
][2] = vertex_index(slices
, slice
-1, stack
);
1616 mesh
->faces
[face
][0] = vertex_index(slices
, 0, stack
-1);
1617 mesh
->faces
[face
][1] = vertex_index(slices
, 0, stack
);
1618 mesh
->faces
[face
][2] = vertex_index(slices
, slice
-1, stack
);
1623 mesh
->vertices
[vertex
].position
.x
= 0.0f
;
1624 mesh
->vertices
[vertex
].position
.y
= 0.0f
;
1625 mesh
->vertices
[vertex
].position
.z
= -radius
;
1626 mesh
->vertices
[vertex
].normal
.x
= 0.0f
;
1627 mesh
->vertices
[vertex
].normal
.y
= 0.0f
;
1628 mesh
->vertices
[vertex
].normal
.z
= -1.0f
;
1630 /* bottom stack is triangle fan */
1631 for (slice
= 1; slice
< slices
; slice
++)
1633 mesh
->faces
[face
][0] = vertex_index(slices
, slice
-1, stack
-1);
1634 mesh
->faces
[face
][1] = vertex_index(slices
, slice
, stack
-1);
1635 mesh
->faces
[face
][2] = vertex
;
1639 mesh
->faces
[face
][0] = vertex_index(slices
, slice
-1, stack
-1);
1640 mesh
->faces
[face
][1] = vertex_index(slices
, 0, stack
-1);
1641 mesh
->faces
[face
][2] = vertex
;
1643 free_sincos_table(&phi
);
1644 free_sincos_table(&theta
);
1649 static void test_sphere(IDirect3DDevice9
*device
, FLOAT radius
, UINT slices
, UINT stacks
)
1656 hr
= D3DXCreateSphere(device
, radius
, slices
, stacks
, &sphere
, NULL
);
1657 ok(hr
== D3D_OK
, "Got result %x, expected 0 (D3D_OK)\n", hr
);
1660 skip("Couldn't create sphere\n");
1664 if (!compute_sphere(&mesh
, radius
, slices
, stacks
))
1666 skip("Couldn't create mesh\n");
1667 sphere
->lpVtbl
->Release(sphere
);
1671 mesh
.fvf
= D3DFVF_XYZ
| D3DFVF_NORMAL
;
1673 sprintf(name
, "sphere (%g, %u, %u)", radius
, slices
, stacks
);
1674 compare_mesh(name
, sphere
, &mesh
);
1678 sphere
->lpVtbl
->Release(sphere
);
1681 static void D3DXCreateSphereTest(void)
1686 IDirect3DDevice9
* device
;
1687 D3DPRESENT_PARAMETERS d3dpp
;
1688 ID3DXMesh
* sphere
= NULL
;
1690 hr
= D3DXCreateSphere(NULL
, 0.0f
, 0, 0, NULL
, NULL
);
1691 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr
,D3DERR_INVALIDCALL
);
1693 hr
= D3DXCreateSphere(NULL
, 0.1f
, 0, 0, NULL
, NULL
);
1694 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr
,D3DERR_INVALIDCALL
);
1696 hr
= D3DXCreateSphere(NULL
, 0.0f
, 1, 0, NULL
, NULL
);
1697 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr
,D3DERR_INVALIDCALL
);
1699 hr
= D3DXCreateSphere(NULL
, 0.0f
, 0, 1, NULL
, NULL
);
1700 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr
,D3DERR_INVALIDCALL
);
1702 wnd
= CreateWindow("static", "d3dx9_test", 0, 0, 0, 0, 0, NULL
, NULL
, NULL
, NULL
);
1703 d3d
= Direct3DCreate9(D3D_SDK_VERSION
);
1706 skip("Couldn't create application window\n");
1711 skip("Couldn't create IDirect3D9 object\n");
1716 ZeroMemory(&d3dpp
, sizeof(d3dpp
));
1717 d3dpp
.Windowed
= TRUE
;
1718 d3dpp
.SwapEffect
= D3DSWAPEFFECT_DISCARD
;
1719 hr
= IDirect3D9_CreateDevice(d3d
, D3DADAPTER_DEFAULT
, D3DDEVTYPE_HAL
, wnd
, D3DCREATE_MIXED_VERTEXPROCESSING
, &d3dpp
, &device
);
1722 skip("Failed to create IDirect3DDevice9 object %#x\n", hr
);
1723 IDirect3D9_Release(d3d
);
1728 hr
= D3DXCreateSphere(device
, 1.0f
, 1, 1, &sphere
, NULL
);
1729 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr
,D3DERR_INVALIDCALL
);
1731 hr
= D3DXCreateSphere(device
, 1.0f
, 2, 1, &sphere
, NULL
);
1732 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr
, D3DERR_INVALIDCALL
);
1734 hr
= D3DXCreateSphere(device
, 1.0f
, 1, 2, &sphere
, NULL
);
1735 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr
, D3DERR_INVALIDCALL
);
1737 hr
= D3DXCreateSphere(device
, -0.1f
, 1, 2, &sphere
, NULL
);
1738 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr
, D3DERR_INVALIDCALL
);
1740 test_sphere(device
, 0.0f
, 2, 2);
1741 test_sphere(device
, 1.0f
, 2, 2);
1742 test_sphere(device
, 1.0f
, 3, 2);
1743 test_sphere(device
, 1.0f
, 4, 4);
1744 test_sphere(device
, 1.0f
, 3, 4);
1745 test_sphere(device
, 5.0f
, 6, 7);
1746 test_sphere(device
, 10.0f
, 11, 12);
1748 IDirect3DDevice9_Release(device
);
1749 IDirect3D9_Release(d3d
);
1753 static BOOL
compute_cylinder(struct mesh
*mesh
, FLOAT radius1
, FLOAT radius2
, FLOAT length
, UINT slices
, UINT stacks
)
1755 float theta_step
, theta_start
;
1756 struct sincos_table theta
;
1757 FLOAT delta_radius
, radius
, radius_step
;
1758 FLOAT z
, z_step
, z_normal
;
1759 DWORD number_of_vertices
, number_of_faces
;
1763 /* theta = angle on xy plane wrt x axis */
1764 theta_step
= -2 * M_PI
/ slices
;
1765 theta_start
= M_PI
/ 2;
1767 if (!compute_sincos_table(&theta
, theta_start
, theta_step
, slices
))
1772 number_of_vertices
= 2 + (slices
* (3 + stacks
));
1773 number_of_faces
= 2 * slices
+ stacks
* (2 * slices
);
1775 if (!new_mesh(mesh
, number_of_vertices
, number_of_faces
))
1777 free_sincos_table(&theta
);
1784 delta_radius
= radius1
- radius2
;
1786 radius_step
= delta_radius
/ stacks
;
1789 z_step
= length
/ stacks
;
1790 z_normal
= delta_radius
/ length
;
1791 if (isnan(z_normal
))
1796 mesh
->vertices
[vertex
].normal
.x
= 0.0f
;
1797 mesh
->vertices
[vertex
].normal
.y
= 0.0f
;
1798 mesh
->vertices
[vertex
].normal
.z
= -1.0f
;
1799 mesh
->vertices
[vertex
].position
.x
= 0.0f
;
1800 mesh
->vertices
[vertex
].position
.y
= 0.0f
;
1801 mesh
->vertices
[vertex
++].position
.z
= z
;
1803 for (slice
= 0; slice
< slices
; slice
++, vertex
++)
1805 mesh
->vertices
[vertex
].normal
.x
= 0.0f
;
1806 mesh
->vertices
[vertex
].normal
.y
= 0.0f
;
1807 mesh
->vertices
[vertex
].normal
.z
= -1.0f
;
1808 mesh
->vertices
[vertex
].position
.x
= radius
* theta
.cos
[slice
];
1809 mesh
->vertices
[vertex
].position
.y
= radius
* theta
.sin
[slice
];
1810 mesh
->vertices
[vertex
].position
.z
= z
;
1814 mesh
->faces
[face
][0] = 0;
1815 mesh
->faces
[face
][1] = slice
;
1816 mesh
->faces
[face
++][2] = slice
+ 1;
1820 mesh
->faces
[face
][0] = 0;
1821 mesh
->faces
[face
][1] = slice
;
1822 mesh
->faces
[face
++][2] = 1;
1824 for (stack
= 1; stack
<= stacks
+1; stack
++)
1826 for (slice
= 0; slice
< slices
; slice
++, vertex
++)
1828 mesh
->vertices
[vertex
].normal
.x
= theta
.cos
[slice
];
1829 mesh
->vertices
[vertex
].normal
.y
= theta
.sin
[slice
];
1830 mesh
->vertices
[vertex
].normal
.z
= z_normal
;
1831 D3DXVec3Normalize(&mesh
->vertices
[vertex
].normal
, &mesh
->vertices
[vertex
].normal
);
1832 mesh
->vertices
[vertex
].position
.x
= radius
* theta
.cos
[slice
];
1833 mesh
->vertices
[vertex
].position
.y
= radius
* theta
.sin
[slice
];
1834 mesh
->vertices
[vertex
].position
.z
= z
;
1836 if (stack
> 1 && slice
> 0)
1838 mesh
->faces
[face
][0] = vertex_index(slices
, slice
-1, stack
-1);
1839 mesh
->faces
[face
][1] = vertex_index(slices
, slice
-1, stack
);
1840 mesh
->faces
[face
++][2] = vertex_index(slices
, slice
, stack
-1);
1842 mesh
->faces
[face
][0] = vertex_index(slices
, slice
, stack
-1);
1843 mesh
->faces
[face
][1] = vertex_index(slices
, slice
-1, stack
);
1844 mesh
->faces
[face
++][2] = vertex_index(slices
, slice
, stack
);
1850 mesh
->faces
[face
][0] = vertex_index(slices
, slice
-1, stack
-1);
1851 mesh
->faces
[face
][1] = vertex_index(slices
, slice
-1, stack
);
1852 mesh
->faces
[face
++][2] = vertex_index(slices
, 0, stack
-1);
1854 mesh
->faces
[face
][0] = vertex_index(slices
, 0, stack
-1);
1855 mesh
->faces
[face
][1] = vertex_index(slices
, slice
-1, stack
);
1856 mesh
->faces
[face
++][2] = vertex_index(slices
, 0, stack
);
1859 if (stack
< stacks
+ 1)
1862 radius
-= radius_step
;
1866 for (slice
= 0; slice
< slices
; slice
++, vertex
++)
1868 mesh
->vertices
[vertex
].normal
.x
= 0.0f
;
1869 mesh
->vertices
[vertex
].normal
.y
= 0.0f
;
1870 mesh
->vertices
[vertex
].normal
.z
= 1.0f
;
1871 mesh
->vertices
[vertex
].position
.x
= radius
* theta
.cos
[slice
];
1872 mesh
->vertices
[vertex
].position
.y
= radius
* theta
.sin
[slice
];
1873 mesh
->vertices
[vertex
].position
.z
= z
;
1877 mesh
->faces
[face
][0] = vertex_index(slices
, slice
-1, stack
);
1878 mesh
->faces
[face
][1] = number_of_vertices
- 1;
1879 mesh
->faces
[face
++][2] = vertex_index(slices
, slice
, stack
);
1883 mesh
->vertices
[vertex
].position
.x
= 0.0f
;
1884 mesh
->vertices
[vertex
].position
.y
= 0.0f
;
1885 mesh
->vertices
[vertex
].position
.z
= z
;
1886 mesh
->vertices
[vertex
].normal
.x
= 0.0f
;
1887 mesh
->vertices
[vertex
].normal
.y
= 0.0f
;
1888 mesh
->vertices
[vertex
].normal
.z
= 1.0f
;
1890 mesh
->faces
[face
][0] = vertex_index(slices
, slice
-1, stack
);
1891 mesh
->faces
[face
][1] = number_of_vertices
- 1;
1892 mesh
->faces
[face
][2] = vertex_index(slices
, 0, stack
);
1894 free_sincos_table(&theta
);
1899 static void test_cylinder(IDirect3DDevice9
*device
, FLOAT radius1
, FLOAT radius2
, FLOAT length
, UINT slices
, UINT stacks
)
1902 ID3DXMesh
*cylinder
;
1906 hr
= D3DXCreateCylinder(device
, radius1
, radius2
, length
, slices
, stacks
, &cylinder
, NULL
);
1907 ok(hr
== D3D_OK
, "Got result %x, expected 0 (D3D_OK)\n", hr
);
1910 skip("Couldn't create cylinder\n");
1914 if (!compute_cylinder(&mesh
, radius1
, radius2
, length
, slices
, stacks
))
1916 skip("Couldn't create mesh\n");
1917 cylinder
->lpVtbl
->Release(cylinder
);
1921 mesh
.fvf
= D3DFVF_XYZ
| D3DFVF_NORMAL
;
1923 sprintf(name
, "cylinder (%g, %g, %g, %u, %u)", radius1
, radius2
, length
, slices
, stacks
);
1924 compare_mesh(name
, cylinder
, &mesh
);
1928 cylinder
->lpVtbl
->Release(cylinder
);
1931 static void D3DXCreateCylinderTest(void)
1936 IDirect3DDevice9
* device
;
1937 D3DPRESENT_PARAMETERS d3dpp
;
1938 ID3DXMesh
* cylinder
= NULL
;
1940 hr
= D3DXCreateCylinder(NULL
, 0.0f
, 0.0f
, 0.0f
, 0, 0, NULL
, NULL
);
1941 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr
,D3DERR_INVALIDCALL
);
1943 hr
= D3DXCreateCylinder(NULL
, 1.0f
, 1.0f
, 1.0f
, 2, 1, &cylinder
, NULL
);
1944 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr
,D3DERR_INVALIDCALL
);
1946 wnd
= CreateWindow("static", "d3dx9_test", 0, 0, 0, 0, 0, NULL
, NULL
, NULL
, NULL
);
1947 d3d
= Direct3DCreate9(D3D_SDK_VERSION
);
1950 skip("Couldn't create application window\n");
1955 skip("Couldn't create IDirect3D9 object\n");
1960 ZeroMemory(&d3dpp
, sizeof(d3dpp
));
1961 d3dpp
.Windowed
= TRUE
;
1962 d3dpp
.SwapEffect
= D3DSWAPEFFECT_DISCARD
;
1963 hr
= IDirect3D9_CreateDevice(d3d
, D3DADAPTER_DEFAULT
, D3DDEVTYPE_HAL
, wnd
, D3DCREATE_MIXED_VERTEXPROCESSING
, &d3dpp
, &device
);
1966 skip("Failed to create IDirect3DDevice9 object %#x\n", hr
);
1967 IDirect3D9_Release(d3d
);
1972 hr
= D3DXCreateCylinder(device
, -0.1f
, 1.0f
, 1.0f
, 2, 1, &cylinder
, NULL
);
1973 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr
,D3DERR_INVALIDCALL
);
1975 hr
= D3DXCreateCylinder(device
, 0.0f
, 1.0f
, 1.0f
, 2, 1, &cylinder
, NULL
);
1976 ok(hr
== D3D_OK
, "Got result %x, expected 0 (D3D_OK)\n",hr
);
1978 if (SUCCEEDED(hr
) && cylinder
)
1980 cylinder
->lpVtbl
->Release(cylinder
);
1983 hr
= D3DXCreateCylinder(device
, 1.0f
, -0.1f
, 1.0f
, 2, 1, &cylinder
, NULL
);
1984 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr
,D3DERR_INVALIDCALL
);
1986 hr
= D3DXCreateCylinder(device
, 1.0f
, 0.0f
, 1.0f
, 2, 1, &cylinder
, NULL
);
1987 ok(hr
== D3D_OK
, "Got result %x, expected 0 (D3D_OK)\n",hr
);
1989 if (SUCCEEDED(hr
) && cylinder
)
1991 cylinder
->lpVtbl
->Release(cylinder
);
1994 hr
= D3DXCreateCylinder(device
, 1.0f
, 1.0f
, -0.1f
, 2, 1, &cylinder
, NULL
);
1995 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr
,D3DERR_INVALIDCALL
);
1997 /* Test with length == 0.0f succeeds */
1998 hr
= D3DXCreateCylinder(device
, 1.0f
, 1.0f
, 0.0f
, 2, 1, &cylinder
, NULL
);
1999 ok(hr
== D3D_OK
, "Got result %x, expected 0 (D3D_OK)\n",hr
);
2001 if (SUCCEEDED(hr
) && cylinder
)
2003 cylinder
->lpVtbl
->Release(cylinder
);
2006 hr
= D3DXCreateCylinder(device
, 1.0f
, 1.0f
, 1.0f
, 1, 1, &cylinder
, NULL
);
2007 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr
,D3DERR_INVALIDCALL
);
2009 hr
= D3DXCreateCylinder(device
, 1.0f
, 1.0f
, 1.0f
, 2, 0, &cylinder
, NULL
);
2010 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr
,D3DERR_INVALIDCALL
);
2012 hr
= D3DXCreateCylinder(device
, 1.0f
, 1.0f
, 1.0f
, 2, 1, NULL
, NULL
);
2013 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr
,D3DERR_INVALIDCALL
);
2015 test_cylinder(device
, 0.0f
, 0.0f
, 0.0f
, 2, 1);
2016 test_cylinder(device
, 1.0f
, 1.0f
, 1.0f
, 2, 1);
2017 test_cylinder(device
, 1.0f
, 1.0f
, 2.0f
, 3, 4);
2018 test_cylinder(device
, 3.0f
, 2.0f
, 4.0f
, 3, 4);
2019 test_cylinder(device
, 2.0f
, 3.0f
, 4.0f
, 3, 4);
2020 test_cylinder(device
, 3.0f
, 4.0f
, 5.0f
, 11, 20);
2022 IDirect3DDevice9_Release(device
);
2023 IDirect3D9_Release(d3d
);
2027 struct dynamic_array
2029 int count
, capacity
;
2034 POINTTYPE_CURVE
= 0,
2036 POINTTYPE_CURVE_START
,
2037 POINTTYPE_CURVE_END
,
2038 POINTTYPE_CURVE_MIDDLE
,
2044 enum pointtype corner
;
2047 /* is a dynamic_array */
2050 int count
, capacity
;
2051 struct point2d
*items
;
2054 /* is a dynamic_array */
2055 struct outline_array
2057 int count
, capacity
;
2058 struct outline
*items
;
2063 struct outline_array outlines
;
2067 static BOOL
reserve(struct dynamic_array
*array
, int count
, int itemsize
)
2069 if (count
> array
->capacity
) {
2072 if (array
->items
&& array
->capacity
) {
2073 new_capacity
= max(array
->capacity
* 2, count
);
2074 new_buffer
= HeapReAlloc(GetProcessHeap(), 0, array
->items
, new_capacity
* itemsize
);
2076 new_capacity
= max(16, count
);
2077 new_buffer
= HeapAlloc(GetProcessHeap(), 0, new_capacity
* itemsize
);
2081 array
->items
= new_buffer
;
2082 array
->capacity
= new_capacity
;
2087 static struct point2d
*add_point(struct outline
*array
)
2089 struct point2d
*item
;
2091 if (!reserve((struct dynamic_array
*)array
, array
->count
+ 1, sizeof(array
->items
[0])))
2094 item
= &array
->items
[array
->count
++];
2095 ZeroMemory(item
, sizeof(*item
));
2099 static struct outline
*add_outline(struct outline_array
*array
)
2101 struct outline
*item
;
2103 if (!reserve((struct dynamic_array
*)array
, array
->count
+ 1, sizeof(array
->items
[0])))
2106 item
= &array
->items
[array
->count
++];
2107 ZeroMemory(item
, sizeof(*item
));
2111 static inline D3DXVECTOR2
*convert_fixed_to_float(POINTFX
*pt
, int count
, float emsquare
)
2113 D3DXVECTOR2
*ret
= (D3DXVECTOR2
*)pt
;
2115 D3DXVECTOR2
*pt_flt
= (D3DXVECTOR2
*)pt
;
2116 pt_flt
->x
= (pt
->x
.value
+ pt
->x
.fract
/ (float)0x10000) / emsquare
;
2117 pt_flt
->y
= (pt
->y
.value
+ pt
->y
.fract
/ (float)0x10000) / emsquare
;
2123 static HRESULT
add_bezier_points(struct outline
*outline
, const D3DXVECTOR2
*p1
,
2124 const D3DXVECTOR2
*p2
, const D3DXVECTOR2
*p3
,
2125 float max_deviation
)
2127 D3DXVECTOR2 split1
= {0, 0}, split2
= {0, 0}, middle
, vec
;
2130 D3DXVec2Scale(&split1
, D3DXVec2Add(&split1
, p1
, p2
), 0.5f
);
2131 D3DXVec2Scale(&split2
, D3DXVec2Add(&split2
, p2
, p3
), 0.5f
);
2132 D3DXVec2Scale(&middle
, D3DXVec2Add(&middle
, &split1
, &split2
), 0.5f
);
2134 deviation
= D3DXVec2Length(D3DXVec2Subtract(&vec
, &middle
, p2
));
2135 if (deviation
< max_deviation
) {
2136 struct point2d
*pt
= add_point(outline
);
2137 if (!pt
) return E_OUTOFMEMORY
;
2139 pt
->corner
= POINTTYPE_CURVE
;
2140 /* the end point is omitted because the end line merges into the next segment of
2141 * the split bezier curve, and the end of the split bezier curve is added outside
2142 * this recursive function. */
2144 HRESULT hr
= add_bezier_points(outline
, p1
, &split1
, &middle
, max_deviation
);
2145 if (hr
!= S_OK
) return hr
;
2146 hr
= add_bezier_points(outline
, &middle
, &split2
, p3
, max_deviation
);
2147 if (hr
!= S_OK
) return hr
;
2153 static inline BOOL
is_direction_similar(D3DXVECTOR2
*dir1
, D3DXVECTOR2
*dir2
, float cos_theta
)
2155 /* dot product = cos(theta) */
2156 return D3DXVec2Dot(dir1
, dir2
) > cos_theta
;
2159 static inline D3DXVECTOR2
*unit_vec2(D3DXVECTOR2
*dir
, const D3DXVECTOR2
*pt1
, const D3DXVECTOR2
*pt2
)
2161 return D3DXVec2Normalize(D3DXVec2Subtract(dir
, pt2
, pt1
), dir
);
2164 static BOOL
attempt_line_merge(struct outline
*outline
,
2166 const D3DXVECTOR2
*nextpt
,
2169 D3DXVECTOR2 curdir
, lastdir
;
2170 struct point2d
*prevpt
, *pt
;
2172 const float cos_half
= cos(D3DXToRadian(0.5f
));
2174 pt
= &outline
->items
[pt_index
];
2175 pt_index
= (pt_index
- 1 + outline
->count
) % outline
->count
;
2176 prevpt
= &outline
->items
[pt_index
];
2179 pt
->corner
= pt
->corner
!= POINTTYPE_CORNER
? POINTTYPE_CURVE_MIDDLE
: POINTTYPE_CURVE_START
;
2181 if (outline
->count
< 2)
2184 /* remove last point if the next line continues the last line */
2185 unit_vec2(&lastdir
, &prevpt
->pos
, &pt
->pos
);
2186 unit_vec2(&curdir
, &pt
->pos
, nextpt
);
2187 if (is_direction_similar(&lastdir
, &curdir
, cos_half
))
2190 if (pt
->corner
== POINTTYPE_CURVE_END
)
2191 prevpt
->corner
= pt
->corner
;
2192 if (prevpt
->corner
== POINTTYPE_CURVE_END
&& to_curve
)
2193 prevpt
->corner
= POINTTYPE_CURVE_MIDDLE
;
2197 if (outline
->count
< 2)
2200 pt_index
= (pt_index
- 1 + outline
->count
) % outline
->count
;
2201 prevpt
= &outline
->items
[pt_index
];
2202 unit_vec2(&lastdir
, &prevpt
->pos
, &pt
->pos
);
2203 unit_vec2(&curdir
, &pt
->pos
, nextpt
);
2208 static HRESULT
create_outline(struct glyphinfo
*glyph
, void *raw_outline
, int datasize
,
2209 float max_deviation
, float emsquare
)
2211 const float cos_45
= cos(D3DXToRadian(45.0f
));
2212 const float cos_90
= cos(D3DXToRadian(90.0f
));
2213 TTPOLYGONHEADER
*header
= (TTPOLYGONHEADER
*)raw_outline
;
2215 while ((char *)header
< (char *)raw_outline
+ datasize
)
2217 TTPOLYCURVE
*curve
= (TTPOLYCURVE
*)(header
+ 1);
2218 struct point2d
*lastpt
, *pt
;
2219 D3DXVECTOR2 lastdir
;
2220 D3DXVECTOR2
*pt_flt
;
2222 struct outline
*outline
= add_outline(&glyph
->outlines
);
2225 return E_OUTOFMEMORY
;
2227 pt
= add_point(outline
);
2229 return E_OUTOFMEMORY
;
2230 pt_flt
= convert_fixed_to_float(&header
->pfxStart
, 1, emsquare
);
2232 pt
->corner
= POINTTYPE_CORNER
;
2234 if (header
->dwType
!= TT_POLYGON_TYPE
)
2235 trace("Unknown header type %d\n", header
->dwType
);
2237 while ((char *)curve
< (char *)header
+ header
->cb
)
2239 D3DXVECTOR2 bezier_start
= outline
->items
[outline
->count
- 1].pos
;
2240 BOOL to_curve
= curve
->wType
!= TT_PRIM_LINE
&& curve
->cpfx
> 1;
2243 curve
= (TTPOLYCURVE
*)&curve
->apfx
[curve
->cpfx
];
2247 pt_flt
= convert_fixed_to_float(curve
->apfx
, curve
->cpfx
, emsquare
);
2249 attempt_line_merge(outline
, outline
->count
- 1, &pt_flt
[0], to_curve
);
2254 int count
= curve
->cpfx
;
2259 D3DXVECTOR2 bezier_end
;
2261 D3DXVec2Scale(&bezier_end
, D3DXVec2Add(&bezier_end
, &pt_flt
[j
], &pt_flt
[j
+1]), 0.5f
);
2262 hr
= add_bezier_points(outline
, &bezier_start
, &pt_flt
[j
], &bezier_end
, max_deviation
);
2265 bezier_start
= bezier_end
;
2269 hr
= add_bezier_points(outline
, &bezier_start
, &pt_flt
[j
], &pt_flt
[j
+1], max_deviation
);
2273 pt
= add_point(outline
);
2275 return E_OUTOFMEMORY
;
2277 pt
->pos
= pt_flt
[j
];
2278 pt
->corner
= POINTTYPE_CURVE_END
;
2280 for (j
= 0; j
< curve
->cpfx
; j
++)
2282 pt
= add_point(outline
);
2284 return E_OUTOFMEMORY
;
2285 pt
->pos
= pt_flt
[j
];
2286 pt
->corner
= POINTTYPE_CORNER
;
2290 curve
= (TTPOLYCURVE
*)&curve
->apfx
[curve
->cpfx
];
2293 /* remove last point if the next line continues the last line */
2294 if (outline
->count
>= 3) {
2297 lastpt
= &outline
->items
[outline
->count
- 1];
2298 pt
= &outline
->items
[0];
2299 if (pt
->pos
.x
== lastpt
->pos
.x
&& pt
->pos
.y
== lastpt
->pos
.y
) {
2300 if (lastpt
->corner
== POINTTYPE_CURVE_END
)
2302 if (pt
->corner
== POINTTYPE_CURVE_START
)
2303 pt
->corner
= POINTTYPE_CURVE_MIDDLE
;
2305 pt
->corner
= POINTTYPE_CURVE_END
;
2308 lastpt
= &outline
->items
[outline
->count
- 1];
2310 /* outline closed with a line from end to start point */
2311 attempt_line_merge(outline
, outline
->count
- 1, &pt
->pos
, FALSE
);
2313 lastpt
= &outline
->items
[0];
2314 to_curve
= lastpt
->corner
!= POINTTYPE_CORNER
&& lastpt
->corner
!= POINTTYPE_CURVE_END
;
2315 if (lastpt
->corner
== POINTTYPE_CURVE_START
)
2316 lastpt
->corner
= POINTTYPE_CORNER
;
2317 pt
= &outline
->items
[1];
2318 if (attempt_line_merge(outline
, 0, &pt
->pos
, to_curve
))
2319 *lastpt
= outline
->items
[outline
->count
];
2322 lastpt
= &outline
->items
[outline
->count
- 1];
2323 pt
= &outline
->items
[0];
2324 unit_vec2(&lastdir
, &lastpt
->pos
, &pt
->pos
);
2325 for (j
= 0; j
< outline
->count
; j
++)
2330 pt
= &outline
->items
[(j
+ 1) % outline
->count
];
2331 unit_vec2(&curdir
, &lastpt
->pos
, &pt
->pos
);
2333 switch (lastpt
->corner
)
2335 case POINTTYPE_CURVE_START
:
2336 case POINTTYPE_CURVE_END
:
2337 if (!is_direction_similar(&lastdir
, &curdir
, cos_45
))
2338 lastpt
->corner
= POINTTYPE_CORNER
;
2340 case POINTTYPE_CURVE_MIDDLE
:
2341 if (!is_direction_similar(&lastdir
, &curdir
, cos_90
))
2342 lastpt
->corner
= POINTTYPE_CORNER
;
2344 lastpt
->corner
= POINTTYPE_CURVE
;
2352 header
= (TTPOLYGONHEADER
*)((char *)header
+ header
->cb
);
2357 static BOOL
compute_text_mesh(struct mesh
*mesh
, HDC hdc
, LPCSTR text
, FLOAT deviation
, FLOAT extrusion
, FLOAT otmEMSquare
)
2359 HRESULT hr
= E_FAIL
;
2360 DWORD nb_vertices
, nb_faces
;
2361 DWORD nb_corners
, nb_outline_points
;
2364 char *raw_outline
= NULL
;
2365 struct glyphinfo
*glyphs
= NULL
;
2368 struct vertex
*vertex_ptr
;
2371 if (deviation
== 0.0f
)
2372 deviation
= 1.0f
/ otmEMSquare
;
2374 textlen
= strlen(text
);
2375 glyphs
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, textlen
* sizeof(*glyphs
));
2382 for (i
= 0; i
< textlen
; i
++)
2384 /* get outline points from data returned from GetGlyphOutline */
2385 const MAT2 identity
= {{0, 1}, {0, 0}, {0, 0}, {0, 1}};
2388 glyphs
[i
].offset_x
= offset_x
;
2390 datasize
= GetGlyphOutline(hdc
, text
[i
], GGO_NATIVE
, &gm
, 0, NULL
, &identity
);
2395 HeapFree(GetProcessHeap(), 0, raw_outline
);
2396 raw_outline
= HeapAlloc(GetProcessHeap(), 0, datasize
);
2401 datasize
= GetGlyphOutline(hdc
, text
[i
], GGO_NATIVE
, &gm
, datasize
, raw_outline
, &identity
);
2403 create_outline(&glyphs
[i
], raw_outline
, datasize
, deviation
, otmEMSquare
);
2405 offset_x
+= gm
.gmCellIncX
/ (float)otmEMSquare
;
2408 /* corner points need an extra vertex for the different side faces normals */
2410 nb_outline_points
= 0;
2411 for (i
= 0; i
< textlen
; i
++)
2414 for (j
= 0; j
< glyphs
[i
].outlines
.count
; j
++)
2417 struct outline
*outline
= &glyphs
[i
].outlines
.items
[j
];
2418 nb_outline_points
+= outline
->count
;
2419 nb_corners
++; /* first outline point always repeated as a corner */
2420 for (k
= 1; k
< outline
->count
; k
++)
2421 if (outline
->items
[k
].corner
)
2426 nb_vertices
= (nb_outline_points
+ nb_corners
) * 2 + textlen
;
2427 nb_faces
= nb_outline_points
* 2;
2429 if (!new_mesh(mesh
, nb_vertices
, nb_faces
))
2432 /* convert 2D vertices and faces into 3D mesh */
2433 vertex_ptr
= mesh
->vertices
;
2434 face_ptr
= mesh
->faces
;
2435 for (i
= 0; i
< textlen
; i
++)
2439 /* side vertices and faces */
2440 for (j
= 0; j
< glyphs
[i
].outlines
.count
; j
++)
2442 struct vertex
*outline_vertices
= vertex_ptr
;
2443 struct outline
*outline
= &glyphs
[i
].outlines
.items
[j
];
2445 struct point2d
*prevpt
= &outline
->items
[outline
->count
- 1];
2446 struct point2d
*pt
= &outline
->items
[0];
2448 for (k
= 1; k
<= outline
->count
; k
++)
2451 struct point2d
*nextpt
= &outline
->items
[k
% outline
->count
];
2452 WORD vtx_idx
= vertex_ptr
- mesh
->vertices
;
2455 if (pt
->corner
== POINTTYPE_CURVE_START
)
2456 D3DXVec2Subtract(&vec
, &pt
->pos
, &prevpt
->pos
);
2457 else if (pt
->corner
)
2458 D3DXVec2Subtract(&vec
, &nextpt
->pos
, &pt
->pos
);
2460 D3DXVec2Subtract(&vec
, &nextpt
->pos
, &prevpt
->pos
);
2461 D3DXVec2Normalize(&vec
, &vec
);
2462 vtx
.normal
.x
= -vec
.y
;
2463 vtx
.normal
.y
= vec
.x
;
2466 vtx
.position
.x
= pt
->pos
.x
+ glyphs
[i
].offset_x
;
2467 vtx
.position
.y
= pt
->pos
.y
;
2469 *vertex_ptr
++ = vtx
;
2471 vtx
.position
.z
= -extrusion
;
2472 *vertex_ptr
++ = vtx
;
2474 vtx
.position
.x
= nextpt
->pos
.x
+ glyphs
[i
].offset_x
;
2475 vtx
.position
.y
= nextpt
->pos
.y
;
2476 if (pt
->corner
&& nextpt
->corner
&& nextpt
->corner
!= POINTTYPE_CURVE_END
) {
2477 vtx
.position
.z
= -extrusion
;
2478 *vertex_ptr
++ = vtx
;
2480 *vertex_ptr
++ = vtx
;
2482 (*face_ptr
)[0] = vtx_idx
;
2483 (*face_ptr
)[1] = vtx_idx
+ 2;
2484 (*face_ptr
)[2] = vtx_idx
+ 1;
2487 (*face_ptr
)[0] = vtx_idx
;
2488 (*face_ptr
)[1] = vtx_idx
+ 3;
2489 (*face_ptr
)[2] = vtx_idx
+ 2;
2492 if (nextpt
->corner
) {
2493 if (nextpt
->corner
== POINTTYPE_CURVE_END
) {
2494 struct point2d
*nextpt2
= &outline
->items
[(k
+ 1) % outline
->count
];
2495 D3DXVec2Subtract(&vec
, &nextpt2
->pos
, &nextpt
->pos
);
2497 D3DXVec2Subtract(&vec
, &nextpt
->pos
, &pt
->pos
);
2499 D3DXVec2Normalize(&vec
, &vec
);
2500 vtx
.normal
.x
= -vec
.y
;
2501 vtx
.normal
.y
= vec
.x
;
2504 *vertex_ptr
++ = vtx
;
2505 vtx
.position
.z
= -extrusion
;
2506 *vertex_ptr
++ = vtx
;
2509 (*face_ptr
)[0] = vtx_idx
;
2510 (*face_ptr
)[1] = vtx_idx
+ 3;
2511 (*face_ptr
)[2] = vtx_idx
+ 1;
2514 (*face_ptr
)[0] = vtx_idx
;
2515 (*face_ptr
)[1] = vtx_idx
+ 2;
2516 (*face_ptr
)[2] = vtx_idx
+ 3;
2524 *vertex_ptr
++ = *outline_vertices
++;
2525 *vertex_ptr
++ = *outline_vertices
++;
2529 /* FIXME: compute expected faces */
2530 /* Add placeholder to seperate glyph outlines */
2531 vertex_ptr
->position
.x
= 0;
2532 vertex_ptr
->position
.y
= 0;
2533 vertex_ptr
->position
.z
= 0;
2534 vertex_ptr
->normal
.x
= 0;
2535 vertex_ptr
->normal
.y
= 0;
2536 vertex_ptr
->normal
.z
= 1;
2543 for (i
= 0; i
< textlen
; i
++)
2546 for (j
= 0; j
< glyphs
[i
].outlines
.count
; j
++)
2547 HeapFree(GetProcessHeap(), 0, glyphs
[i
].outlines
.items
[j
].items
);
2548 HeapFree(GetProcessHeap(), 0, glyphs
[i
].outlines
.items
);
2550 HeapFree(GetProcessHeap(), 0, glyphs
);
2552 HeapFree(GetProcessHeap(), 0, raw_outline
);
2554 return hr
== D3D_OK
;
2557 static void compare_text_outline_mesh(const char *name
, ID3DXMesh
*d3dxmesh
, struct mesh
*mesh
, int textlen
, float extrusion
)
2560 DWORD number_of_vertices
, number_of_faces
;
2561 IDirect3DVertexBuffer9
*vertex_buffer
= NULL
;
2562 IDirect3DIndexBuffer9
*index_buffer
= NULL
;
2563 D3DVERTEXBUFFER_DESC vertex_buffer_description
;
2564 D3DINDEXBUFFER_DESC index_buffer_description
;
2565 struct vertex
*vertices
= NULL
;
2568 int vtx_idx1
, face_idx1
, vtx_idx2
, face_idx2
;
2570 number_of_vertices
= d3dxmesh
->lpVtbl
->GetNumVertices(d3dxmesh
);
2571 number_of_faces
= d3dxmesh
->lpVtbl
->GetNumFaces(d3dxmesh
);
2574 hr
= d3dxmesh
->lpVtbl
->GetVertexBuffer(d3dxmesh
, &vertex_buffer
);
2575 ok(hr
== D3D_OK
, "Test %s, result %x, expected 0 (D3D_OK)\n", name
, hr
);
2578 skip("Couldn't get vertex buffers\n");
2582 hr
= IDirect3DVertexBuffer9_GetDesc(vertex_buffer
, &vertex_buffer_description
);
2583 ok(hr
== D3D_OK
, "Test %s, result %x, expected 0 (D3D_OK)\n", name
, hr
);
2587 skip("Couldn't get vertex buffer description\n");
2591 ok(vertex_buffer_description
.Format
== D3DFMT_VERTEXDATA
, "Test %s, result %x, expected %x (D3DFMT_VERTEXDATA)\n",
2592 name
, vertex_buffer_description
.Format
, D3DFMT_VERTEXDATA
);
2593 ok(vertex_buffer_description
.Type
== D3DRTYPE_VERTEXBUFFER
, "Test %s, result %x, expected %x (D3DRTYPE_VERTEXBUFFER)\n",
2594 name
, vertex_buffer_description
.Type
, D3DRTYPE_VERTEXBUFFER
);
2595 ok(vertex_buffer_description
.Usage
== 0, "Test %s, result %x, expected %x\n", name
, vertex_buffer_description
.Usage
, 0);
2596 ok(vertex_buffer_description
.Pool
== D3DPOOL_MANAGED
, "Test %s, result %x, expected %x (D3DPOOL_DEFAULT)\n",
2597 name
, vertex_buffer_description
.Pool
, D3DPOOL_DEFAULT
);
2598 ok(vertex_buffer_description
.FVF
== mesh
->fvf
, "Test %s, result %x, expected %x\n",
2599 name
, vertex_buffer_description
.FVF
, mesh
->fvf
);
2602 expected
= number_of_vertices
* mesh
->vertex_size
;
2606 expected
= number_of_vertices
* D3DXGetFVFVertexSize(mesh
->fvf
);
2608 ok(vertex_buffer_description
.Size
== expected
, "Test %s, result %x, expected %x\n",
2609 name
, vertex_buffer_description
.Size
, expected
);
2612 hr
= d3dxmesh
->lpVtbl
->GetIndexBuffer(d3dxmesh
, &index_buffer
);
2613 ok(hr
== D3D_OK
, "Test %s, result %x, expected 0 (D3D_OK)\n", name
, hr
);
2616 skip("Couldn't get index buffer\n");
2620 hr
= IDirect3DIndexBuffer9_GetDesc(index_buffer
, &index_buffer_description
);
2621 ok(hr
== D3D_OK
, "Test %s, result %x, expected 0 (D3D_OK)\n", name
, hr
);
2625 skip("Couldn't get index buffer description\n");
2629 ok(index_buffer_description
.Format
== D3DFMT_INDEX16
, "Test %s, result %x, expected %x (D3DFMT_INDEX16)\n",
2630 name
, index_buffer_description
.Format
, D3DFMT_INDEX16
);
2631 ok(index_buffer_description
.Type
== D3DRTYPE_INDEXBUFFER
, "Test %s, result %x, expected %x (D3DRTYPE_INDEXBUFFER)\n",
2632 name
, index_buffer_description
.Type
, D3DRTYPE_INDEXBUFFER
);
2633 todo_wine
ok(index_buffer_description
.Usage
== 0, "Test %s, result %x, expected %x\n", name
, index_buffer_description
.Usage
, 0);
2634 ok(index_buffer_description
.Pool
== D3DPOOL_MANAGED
, "Test %s, result %x, expected %x (D3DPOOL_DEFAULT)\n",
2635 name
, index_buffer_description
.Pool
, D3DPOOL_DEFAULT
);
2636 expected
= number_of_faces
* sizeof(WORD
) * 3;
2637 ok(index_buffer_description
.Size
== expected
, "Test %s, result %x, expected %x\n",
2638 name
, index_buffer_description
.Size
, expected
);
2641 /* specify offset and size to avoid potential overruns */
2642 hr
= IDirect3DVertexBuffer9_Lock(vertex_buffer
, 0, number_of_vertices
* sizeof(D3DXVECTOR3
) * 2,
2643 (LPVOID
*)&vertices
, D3DLOCK_DISCARD
);
2644 ok(hr
== D3D_OK
, "Test %s, result %x, expected 0 (D3D_OK)\n", name
, hr
);
2647 skip("Couldn't lock vertex buffer\n");
2650 hr
= IDirect3DIndexBuffer9_Lock(index_buffer
, 0, number_of_faces
* sizeof(WORD
) * 3,
2651 (LPVOID
*)&faces
, D3DLOCK_DISCARD
);
2652 ok(hr
== D3D_OK
, "Test %s, result %x, expected 0 (D3D_OK)\n", name
, hr
);
2655 skip("Couldn't lock index buffer\n");
2663 for (i
= 0; i
< textlen
; i
++)
2665 int nb_outline_vertices1
, nb_outline_faces1
;
2666 int nb_outline_vertices2
, nb_outline_faces2
;
2667 int nb_back_vertices
, nb_back_faces
;
2668 int first_vtx1
, first_vtx2
;
2669 int first_face1
, first_face2
;
2672 first_vtx1
= vtx_idx1
;
2673 first_vtx2
= vtx_idx2
;
2674 for (; vtx_idx1
< number_of_vertices
; vtx_idx1
++) {
2675 if (vertices
[vtx_idx1
].normal
.z
!= 0)
2678 for (; vtx_idx2
< mesh
->number_of_vertices
; vtx_idx2
++) {
2679 if (mesh
->vertices
[vtx_idx2
].normal
.z
!= 0)
2682 nb_outline_vertices1
= vtx_idx1
- first_vtx1
;
2683 nb_outline_vertices2
= vtx_idx2
- first_vtx2
;
2684 ok(nb_outline_vertices1
== nb_outline_vertices2
,
2685 "Test %s, glyph %d, outline vertex count result %d, expected %d\n", name
, i
,
2686 nb_outline_vertices1
, nb_outline_vertices2
);
2688 for (j
= 0; j
< min(nb_outline_vertices1
, nb_outline_vertices2
); j
++)
2690 vtx_idx1
= first_vtx1
+ j
;
2691 vtx_idx2
= first_vtx2
+ j
;
2692 ok(compare_vec3(vertices
[vtx_idx1
].position
, mesh
->vertices
[vtx_idx2
].position
),
2693 "Test %s, glyph %d, vertex position %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name
, i
, vtx_idx1
,
2694 vertices
[vtx_idx1
].position
.x
, vertices
[vtx_idx1
].position
.y
, vertices
[vtx_idx1
].position
.z
,
2695 mesh
->vertices
[vtx_idx2
].position
.x
, mesh
->vertices
[vtx_idx2
].position
.y
, mesh
->vertices
[vtx_idx2
].position
.z
);
2696 ok(compare_vec3(vertices
[vtx_idx1
].normal
, mesh
->vertices
[first_vtx2
+ j
].normal
),
2697 "Test %s, glyph %d, vertex normal %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name
, i
, vtx_idx1
,
2698 vertices
[vtx_idx1
].normal
.x
, vertices
[vtx_idx1
].normal
.y
, vertices
[vtx_idx1
].normal
.z
,
2699 mesh
->vertices
[vtx_idx2
].normal
.x
, mesh
->vertices
[vtx_idx2
].normal
.y
, mesh
->vertices
[vtx_idx2
].normal
.z
);
2701 vtx_idx1
= first_vtx1
+ nb_outline_vertices1
;
2702 vtx_idx2
= first_vtx2
+ nb_outline_vertices2
;
2704 first_face1
= face_idx1
;
2705 first_face2
= face_idx2
;
2706 for (; face_idx1
< number_of_faces
; face_idx1
++)
2708 if (faces
[face_idx1
][0] >= vtx_idx1
||
2709 faces
[face_idx1
][1] >= vtx_idx1
||
2710 faces
[face_idx1
][2] >= vtx_idx1
)
2713 for (; face_idx2
< mesh
->number_of_faces
; face_idx2
++)
2715 if (mesh
->faces
[face_idx2
][0] >= vtx_idx2
||
2716 mesh
->faces
[face_idx2
][1] >= vtx_idx2
||
2717 mesh
->faces
[face_idx2
][2] >= vtx_idx2
)
2720 nb_outline_faces1
= face_idx1
- first_face1
;
2721 nb_outline_faces2
= face_idx2
- first_face2
;
2722 ok(nb_outline_faces1
== nb_outline_faces2
,
2723 "Test %s, glyph %d, outline face count result %d, expected %d\n", name
, i
,
2724 nb_outline_faces1
, nb_outline_faces2
);
2726 for (j
= 0; j
< min(nb_outline_faces1
, nb_outline_faces2
); j
++)
2728 face_idx1
= first_face1
+ j
;
2729 face_idx2
= first_face2
+ j
;
2730 ok(faces
[face_idx1
][0] - first_vtx1
== mesh
->faces
[face_idx2
][0] - first_vtx2
&&
2731 faces
[face_idx1
][1] - first_vtx1
== mesh
->faces
[face_idx2
][1] - first_vtx2
&&
2732 faces
[face_idx1
][2] - first_vtx1
== mesh
->faces
[face_idx2
][2] - first_vtx2
,
2733 "Test %s, glyph %d, face %d, result (%d, %d, %d), expected (%d, %d, %d)\n", name
, i
, face_idx1
,
2734 faces
[face_idx1
][0], faces
[face_idx1
][1], faces
[face_idx1
][2],
2735 mesh
->faces
[face_idx2
][0] - first_vtx2
+ first_vtx1
,
2736 mesh
->faces
[face_idx2
][1] - first_vtx2
+ first_vtx1
,
2737 mesh
->faces
[face_idx2
][2] - first_vtx2
+ first_vtx1
);
2739 face_idx1
= first_face1
+ nb_outline_faces1
;
2740 face_idx2
= first_face2
+ nb_outline_faces2
;
2742 /* partial test on back vertices and faces */
2743 first_vtx1
= vtx_idx1
;
2744 for (; vtx_idx1
< number_of_vertices
; vtx_idx1
++) {
2747 if (vertices
[vtx_idx1
].normal
.z
!= 1.0f
)
2750 vtx
.position
.z
= 0.0f
;
2751 vtx
.normal
.x
= 0.0f
;
2752 vtx
.normal
.y
= 0.0f
;
2753 vtx
.normal
.z
= 1.0f
;
2754 ok(compare(vertices
[vtx_idx1
].position
.z
, vtx
.position
.z
),
2755 "Test %s, glyph %d, vertex position.z %d, result %g, expected %g\n", name
, i
, vtx_idx1
,
2756 vertices
[vtx_idx1
].position
.z
, vtx
.position
.z
);
2757 ok(compare_vec3(vertices
[vtx_idx1
].normal
, vtx
.normal
),
2758 "Test %s, glyph %d, vertex normal %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name
, i
, vtx_idx1
,
2759 vertices
[vtx_idx1
].normal
.x
, vertices
[vtx_idx1
].normal
.y
, vertices
[vtx_idx1
].normal
.z
,
2760 vtx
.normal
.x
, vtx
.normal
.y
, vtx
.normal
.z
);
2762 nb_back_vertices
= vtx_idx1
- first_vtx1
;
2763 first_face1
= face_idx1
;
2764 for (; face_idx1
< number_of_faces
; face_idx1
++)
2766 const D3DXVECTOR3
*vtx1
, *vtx2
, *vtx3
;
2768 D3DXVECTOR3 v1
= {0, 0, 0};
2769 D3DXVECTOR3 v2
= {0, 0, 0};
2770 D3DXVECTOR3 forward
= {0.0f
, 0.0f
, 1.0f
};
2772 if (faces
[face_idx1
][0] >= vtx_idx1
||
2773 faces
[face_idx1
][1] >= vtx_idx1
||
2774 faces
[face_idx1
][2] >= vtx_idx1
)
2777 vtx1
= &vertices
[faces
[face_idx1
][0]].position
;
2778 vtx2
= &vertices
[faces
[face_idx1
][1]].position
;
2779 vtx3
= &vertices
[faces
[face_idx1
][2]].position
;
2781 D3DXVec3Subtract(&v1
, vtx2
, vtx1
);
2782 D3DXVec3Subtract(&v2
, vtx3
, vtx2
);
2783 D3DXVec3Cross(&normal
, &v1
, &v2
);
2784 D3DXVec3Normalize(&normal
, &normal
);
2785 ok(compare_vec3(normal
, forward
),
2786 "Test %s, glyph %d, face %d normal, result (%g, %g, %g), expected (%g, %g, %g)\n", name
, i
, face_idx1
,
2787 normal
.x
, normal
.y
, normal
.z
, forward
.x
, forward
.y
, forward
.z
);
2789 nb_back_faces
= face_idx1
- first_face1
;
2791 /* compare front and back faces & vertices */
2792 if (extrusion
== 0.0f
) {
2793 /* Oddly there are only back faces in this case */
2794 nb_back_vertices
/= 2;
2796 face_idx1
-= nb_back_faces
;
2797 vtx_idx1
-= nb_back_vertices
;
2799 for (j
= 0; j
< nb_back_vertices
; j
++)
2801 struct vertex vtx
= vertices
[first_vtx1
];
2802 vtx
.position
.z
= -extrusion
;
2803 vtx
.normal
.x
= 0.0f
;
2804 vtx
.normal
.y
= 0.0f
;
2805 vtx
.normal
.z
= extrusion
== 0.0f
? 1.0f
: -1.0f
;
2806 ok(compare_vec3(vertices
[vtx_idx1
].position
, vtx
.position
),
2807 "Test %s, glyph %d, vertex position %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name
, i
, vtx_idx1
,
2808 vertices
[vtx_idx1
].position
.x
, vertices
[vtx_idx1
].position
.y
, vertices
[vtx_idx1
].position
.z
,
2809 vtx
.position
.x
, vtx
.position
.y
, vtx
.position
.z
);
2810 ok(compare_vec3(vertices
[vtx_idx1
].normal
, vtx
.normal
),
2811 "Test %s, glyph %d, vertex normal %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name
, i
, vtx_idx1
,
2812 vertices
[vtx_idx1
].normal
.x
, vertices
[vtx_idx1
].normal
.y
, vertices
[vtx_idx1
].normal
.z
,
2813 vtx
.normal
.x
, vtx
.normal
.y
, vtx
.normal
.z
);
2817 for (j
= 0; j
< nb_back_faces
; j
++)
2820 if (extrusion
== 0.0f
) {
2827 ok(faces
[face_idx1
][0] == faces
[first_face1
][0] + nb_back_vertices
&&
2828 faces
[face_idx1
][1] == faces
[first_face1
][f1
] + nb_back_vertices
&&
2829 faces
[face_idx1
][2] == faces
[first_face1
][f2
] + nb_back_vertices
,
2830 "Test %s, glyph %d, face %d, result (%d, %d, %d), expected (%d, %d, %d)\n", name
, i
, face_idx1
,
2831 faces
[face_idx1
][0], faces
[face_idx1
][1], faces
[face_idx1
][2],
2832 faces
[first_face1
][0] - nb_back_faces
,
2833 faces
[first_face1
][f1
] - nb_back_faces
,
2834 faces
[first_face1
][f2
] - nb_back_faces
);
2839 /* skip to the outline for the next glyph */
2840 for (; vtx_idx2
< mesh
->number_of_vertices
; vtx_idx2
++) {
2841 if (mesh
->vertices
[vtx_idx2
].normal
.z
== 0)
2844 for (; face_idx2
< mesh
->number_of_faces
; face_idx2
++)
2846 if (mesh
->faces
[face_idx2
][0] >= vtx_idx2
||
2847 mesh
->faces
[face_idx2
][1] >= vtx_idx2
||
2848 mesh
->faces
[face_idx2
][2] >= vtx_idx2
) break;
2853 if (vertices
) IDirect3DVertexBuffer9_Unlock(vertex_buffer
);
2854 if (faces
) IDirect3DIndexBuffer9_Unlock(index_buffer
);
2855 if (index_buffer
) IDirect3DIndexBuffer9_Release(index_buffer
);
2856 if (vertex_buffer
) IDirect3DVertexBuffer9_Release(vertex_buffer
);
2859 static void test_createtext(IDirect3DDevice9
*device
, HDC hdc
, LPCSTR text
, FLOAT deviation
, FLOAT extrusion
)
2862 ID3DXMesh
*d3dxmesh
;
2865 OUTLINETEXTMETRIC otm
;
2867 GLYPHMETRICSFLOAT
*glyphmetrics_float
= HeapAlloc(GetProcessHeap(), 0, sizeof(GLYPHMETRICSFLOAT
) * strlen(text
));
2870 HFONT font
= NULL
, oldfont
= NULL
;
2872 sprintf(name
, "text ('%s', %f, %f)", text
, deviation
, extrusion
);
2874 hr
= D3DXCreateText(device
, hdc
, text
, deviation
, extrusion
, &d3dxmesh
, NULL
, glyphmetrics_float
);
2875 ok(hr
== D3D_OK
, "Got result %x, expected 0 (D3D_OK)\n", hr
);
2878 skip("Couldn't create text with D3DXCreateText\n");
2882 /* must select a modified font having lfHeight = otm.otmEMSquare before
2883 * calling GetGlyphOutline to get the expected values */
2884 if (!GetObject(GetCurrentObject(hdc
, OBJ_FONT
), sizeof(lf
), &lf
) ||
2885 !GetOutlineTextMetrics(hdc
, sizeof(otm
), &otm
))
2887 d3dxmesh
->lpVtbl
->Release(d3dxmesh
);
2888 skip("Couldn't get text outline\n");
2891 lf
.lfHeight
= otm
.otmEMSquare
;
2893 font
= CreateFontIndirect(&lf
);
2895 d3dxmesh
->lpVtbl
->Release(d3dxmesh
);
2896 skip("Couldn't create the modified font\n");
2899 oldfont
= SelectObject(hdc
, font
);
2901 for (i
= 0; i
< strlen(text
); i
++)
2903 const MAT2 identity
= {{0, 1}, {0, 0}, {0, 0}, {0, 1}};
2904 GetGlyphOutlineA(hdc
, text
[i
], GGO_NATIVE
, &gm
, 0, NULL
, &identity
);
2905 compare_float(glyphmetrics_float
[i
].gmfBlackBoxX
, gm
.gmBlackBoxX
/ (float)otm
.otmEMSquare
);
2906 compare_float(glyphmetrics_float
[i
].gmfBlackBoxY
, gm
.gmBlackBoxY
/ (float)otm
.otmEMSquare
);
2907 compare_float(glyphmetrics_float
[i
].gmfptGlyphOrigin
.x
, gm
.gmptGlyphOrigin
.x
/ (float)otm
.otmEMSquare
);
2908 compare_float(glyphmetrics_float
[i
].gmfptGlyphOrigin
.y
, gm
.gmptGlyphOrigin
.y
/ (float)otm
.otmEMSquare
);
2909 compare_float(glyphmetrics_float
[i
].gmfCellIncX
, gm
.gmCellIncX
/ (float)otm
.otmEMSquare
);
2910 compare_float(glyphmetrics_float
[i
].gmfCellIncY
, gm
.gmCellIncY
/ (float)otm
.otmEMSquare
);
2913 ZeroMemory(&mesh
, sizeof(mesh
));
2914 if (!compute_text_mesh(&mesh
, hdc
, text
, deviation
, extrusion
, otm
.otmEMSquare
))
2916 skip("Couldn't create mesh\n");
2917 d3dxmesh
->lpVtbl
->Release(d3dxmesh
);
2920 mesh
.fvf
= D3DFVF_XYZ
| D3DFVF_NORMAL
;
2922 compare_text_outline_mesh(name
, d3dxmesh
, &mesh
, strlen(text
), extrusion
);
2926 d3dxmesh
->lpVtbl
->Release(d3dxmesh
);
2927 SelectObject(hdc
, oldfont
);
2928 HeapFree(GetProcessHeap(), 0, glyphmetrics_float
);
2931 static void D3DXCreateTextTest(void)
2937 IDirect3DDevice9
* device
;
2938 D3DPRESENT_PARAMETERS d3dpp
;
2939 ID3DXMesh
* d3dxmesh
= NULL
;
2941 OUTLINETEXTMETRIC otm
;
2942 int number_of_vertices
;
2943 int number_of_faces
;
2945 wnd
= CreateWindow("static", "d3dx9_test", WS_POPUP
, 0, 0, 1000, 1000, NULL
, NULL
, NULL
, NULL
);
2946 d3d
= Direct3DCreate9(D3D_SDK_VERSION
);
2949 skip("Couldn't create application window\n");
2954 skip("Couldn't create IDirect3D9 object\n");
2959 ZeroMemory(&d3dpp
, sizeof(d3dpp
));
2960 d3dpp
.Windowed
= TRUE
;
2961 d3dpp
.SwapEffect
= D3DSWAPEFFECT_DISCARD
;
2962 hr
= IDirect3D9_CreateDevice(d3d
, D3DADAPTER_DEFAULT
, D3DDEVTYPE_HAL
, wnd
, D3DCREATE_MIXED_VERTEXPROCESSING
, &d3dpp
, &device
);
2965 skip("Failed to create IDirect3DDevice9 object %#x\n", hr
);
2966 IDirect3D9_Release(d3d
);
2971 hdc
= CreateCompatibleDC(NULL
);
2973 hFont
= CreateFont(12, 0, 0, 0, FW_NORMAL
, FALSE
, FALSE
, FALSE
, DEFAULT_CHARSET
,
2974 OUT_DEFAULT_PRECIS
, CLIP_DEFAULT_PRECIS
, DEFAULT_QUALITY
, DEFAULT_PITCH
| FF_DONTCARE
,
2976 SelectObject(hdc
, hFont
);
2977 GetOutlineTextMetrics(hdc
, sizeof(otm
), &otm
);
2979 hr
= D3DXCreateText(device
, hdc
, "wine", 0.001f
, 0.4f
, NULL
, NULL
, NULL
);
2980 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr
, D3DERR_INVALIDCALL
);
2982 /* D3DXCreateTextA page faults from passing NULL text */
2984 hr
= D3DXCreateTextW(device
, hdc
, NULL
, 0.001f
, 0.4f
, &d3dxmesh
, NULL
, NULL
);
2985 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr
, D3DERR_INVALIDCALL
);
2987 hr
= D3DXCreateText(device
, hdc
, "", 0.001f
, 0.4f
, &d3dxmesh
, NULL
, NULL
);
2988 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr
, D3DERR_INVALIDCALL
);
2990 hr
= D3DXCreateText(device
, hdc
, " ", 0.001f
, 0.4f
, &d3dxmesh
, NULL
, NULL
);
2991 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr
, D3DERR_INVALIDCALL
);
2993 hr
= D3DXCreateText(NULL
, hdc
, "wine", 0.001f
, 0.4f
, &d3dxmesh
, NULL
, NULL
);
2994 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr
, D3DERR_INVALIDCALL
);
2996 hr
= D3DXCreateText(device
, NULL
, "wine", 0.001f
, 0.4f
, &d3dxmesh
, NULL
, NULL
);
2997 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr
, D3DERR_INVALIDCALL
);
2999 hr
= D3DXCreateText(device
, hdc
, "wine", -FLT_MIN
, 0.4f
, &d3dxmesh
, NULL
, NULL
);
3000 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr
, D3DERR_INVALIDCALL
);
3002 hr
= D3DXCreateText(device
, hdc
, "wine", 0.001f
, -FLT_MIN
, &d3dxmesh
, NULL
, NULL
);
3003 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr
, D3DERR_INVALIDCALL
);
3005 /* deviation = 0.0f treated as if deviation = 1.0f / otm.otmEMSquare */
3006 hr
= D3DXCreateText(device
, hdc
, "wine", 1.0f
/ otm
.otmEMSquare
, 0.4f
, &d3dxmesh
, NULL
, NULL
);
3007 ok(hr
== D3D_OK
, "Got result %x, expected %x (D3D_OK)\n", hr
, D3D_OK
);
3008 number_of_vertices
= d3dxmesh
->lpVtbl
->GetNumVertices(d3dxmesh
);
3009 number_of_faces
= d3dxmesh
->lpVtbl
->GetNumFaces(d3dxmesh
);
3010 if (SUCCEEDED(hr
) && d3dxmesh
) d3dxmesh
->lpVtbl
->Release(d3dxmesh
);
3012 hr
= D3DXCreateText(device
, hdc
, "wine", 0.0f
, 0.4f
, &d3dxmesh
, NULL
, NULL
);
3013 ok(hr
== D3D_OK
, "Got result %x, expected %x (D3D_OK)\n", hr
, D3D_OK
);
3014 ok(number_of_vertices
== d3dxmesh
->lpVtbl
->GetNumVertices(d3dxmesh
),
3015 "Got %d vertices, expected %d\n",
3016 d3dxmesh
->lpVtbl
->GetNumVertices(d3dxmesh
), number_of_vertices
);
3017 ok(number_of_faces
== d3dxmesh
->lpVtbl
->GetNumFaces(d3dxmesh
),
3018 "Got %d faces, expected %d\n",
3019 d3dxmesh
->lpVtbl
->GetNumVertices(d3dxmesh
), number_of_faces
);
3020 if (SUCCEEDED(hr
) && d3dxmesh
) d3dxmesh
->lpVtbl
->Release(d3dxmesh
);
3023 /* too much detail requested, so will appear to hang */
3024 trace("Waiting for D3DXCreateText to finish with deviation = FLT_MIN ...\n");
3025 hr
= D3DXCreateText(device
, hdc
, "wine", FLT_MIN
, 0.4f
, &d3dxmesh
, NULL
, NULL
);
3026 ok(hr
== D3D_OK
, "Got result %x, expected %x (D3D_OK)\n", hr
, D3D_OK
);
3027 if (SUCCEEDED(hr
) && d3dxmesh
) d3dxmesh
->lpVtbl
->Release(d3dxmesh
);
3028 trace("D3DXCreateText finish with deviation = FLT_MIN\n");
3031 hr
= D3DXCreateText(device
, hdc
, "wine", 0.001f
, 0.4f
, &d3dxmesh
, NULL
, NULL
);
3032 ok(hr
== D3D_OK
, "Got result %x, expected %x (D3D_OK)\n", hr
, D3D_OK
);
3033 if (SUCCEEDED(hr
) && d3dxmesh
) d3dxmesh
->lpVtbl
->Release(d3dxmesh
);
3035 test_createtext(device
, hdc
, "wine", FLT_MAX
, 0.4f
);
3036 test_createtext(device
, hdc
, "wine", 0.001f
, FLT_MIN
);
3037 test_createtext(device
, hdc
, "wine", 0.001f
, 0.0f
);
3038 test_createtext(device
, hdc
, "wine", 0.001f
, FLT_MAX
);
3039 test_createtext(device
, hdc
, "wine", 0.0f
, 1.0f
);
3043 IDirect3DDevice9_Release(device
);
3044 IDirect3D9_Release(d3d
);
3048 static void test_get_decl_length(void)
3050 static const D3DVERTEXELEMENT9 declaration1
[] =
3052 {0, 0, D3DDECLTYPE_FLOAT1
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3053 {1, 0, D3DDECLTYPE_FLOAT2
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3054 {2, 0, D3DDECLTYPE_FLOAT3
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3055 {3, 0, D3DDECLTYPE_FLOAT4
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3056 {4, 0, D3DDECLTYPE_D3DCOLOR
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3057 {5, 0, D3DDECLTYPE_UBYTE4
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3058 {6, 0, D3DDECLTYPE_SHORT2
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3059 {7, 0, D3DDECLTYPE_SHORT4
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3060 {8, 0, D3DDECLTYPE_UBYTE4N
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3061 {9, 0, D3DDECLTYPE_SHORT2N
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3062 {10, 0, D3DDECLTYPE_SHORT4N
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3063 {11, 0, D3DDECLTYPE_UDEC3
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3064 {12, 0, D3DDECLTYPE_DEC3N
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3065 {13, 0, D3DDECLTYPE_FLOAT16_2
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3066 {14, 0, D3DDECLTYPE_FLOAT16_4
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3069 static const D3DVERTEXELEMENT9 declaration2
[] =
3071 {0, 8, D3DDECLTYPE_FLOAT1
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3072 {1, 8, D3DDECLTYPE_FLOAT2
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3073 {2, 8, D3DDECLTYPE_FLOAT3
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3074 {3, 8, D3DDECLTYPE_FLOAT4
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3075 {4, 8, D3DDECLTYPE_D3DCOLOR
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3076 {5, 8, D3DDECLTYPE_UBYTE4
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3077 {6, 8, D3DDECLTYPE_SHORT2
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3078 {7, 8, D3DDECLTYPE_SHORT4
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3079 {0, 8, D3DDECLTYPE_UBYTE4N
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3080 {1, 8, D3DDECLTYPE_SHORT2N
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3081 {2, 8, D3DDECLTYPE_SHORT4N
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3082 {3, 8, D3DDECLTYPE_UDEC3
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3083 {4, 8, D3DDECLTYPE_DEC3N
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3084 {5, 8, D3DDECLTYPE_FLOAT16_2
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3085 {6, 8, D3DDECLTYPE_FLOAT16_4
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3086 {7, 8, D3DDECLTYPE_FLOAT1
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3091 size
= D3DXGetDeclLength(declaration1
);
3092 ok(size
== 15, "Got size %u, expected 15.\n", size
);
3094 size
= D3DXGetDeclLength(declaration2
);
3095 ok(size
== 16, "Got size %u, expected 16.\n", size
);
3098 static void test_get_decl_vertex_size(void)
3100 static const D3DVERTEXELEMENT9 declaration1
[] =
3102 {0, 0, D3DDECLTYPE_FLOAT1
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3103 {1, 0, D3DDECLTYPE_FLOAT2
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3104 {2, 0, D3DDECLTYPE_FLOAT3
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3105 {3, 0, D3DDECLTYPE_FLOAT4
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3106 {4, 0, D3DDECLTYPE_D3DCOLOR
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3107 {5, 0, D3DDECLTYPE_UBYTE4
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3108 {6, 0, D3DDECLTYPE_SHORT2
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3109 {7, 0, D3DDECLTYPE_SHORT4
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3110 {8, 0, D3DDECLTYPE_UBYTE4N
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3111 {9, 0, D3DDECLTYPE_SHORT2N
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3112 {10, 0, D3DDECLTYPE_SHORT4N
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3113 {11, 0, D3DDECLTYPE_UDEC3
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3114 {12, 0, D3DDECLTYPE_DEC3N
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3115 {13, 0, D3DDECLTYPE_FLOAT16_2
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3116 {14, 0, D3DDECLTYPE_FLOAT16_4
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3119 static const D3DVERTEXELEMENT9 declaration2
[] =
3121 {0, 8, D3DDECLTYPE_FLOAT1
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3122 {1, 8, D3DDECLTYPE_FLOAT2
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3123 {2, 8, D3DDECLTYPE_FLOAT3
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3124 {3, 8, D3DDECLTYPE_FLOAT4
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3125 {4, 8, D3DDECLTYPE_D3DCOLOR
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3126 {5, 8, D3DDECLTYPE_UBYTE4
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3127 {6, 8, D3DDECLTYPE_SHORT2
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3128 {7, 8, D3DDECLTYPE_SHORT4
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3129 {0, 8, D3DDECLTYPE_UBYTE4N
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3130 {1, 8, D3DDECLTYPE_SHORT2N
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3131 {2, 8, D3DDECLTYPE_SHORT4N
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3132 {3, 8, D3DDECLTYPE_UDEC3
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3133 {4, 8, D3DDECLTYPE_DEC3N
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3134 {5, 8, D3DDECLTYPE_FLOAT16_2
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3135 {6, 8, D3DDECLTYPE_FLOAT16_4
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3136 {7, 8, D3DDECLTYPE_FLOAT1
, D3DDECLMETHOD_DEFAULT
, D3DDECLUSAGE_POSITION
, 0},
3139 static const UINT sizes1
[] =
3146 static const UINT sizes2
[] =
3154 size
= D3DXGetDeclVertexSize(NULL
, 0);
3155 ok(size
== 0, "Got size %#x, expected 0.\n", size
);
3157 for (i
= 0; i
< 16; ++i
)
3159 size
= D3DXGetDeclVertexSize(declaration1
, i
);
3160 ok(size
== sizes1
[i
], "Got size %u for stream %u, expected %u.\n", size
, i
, sizes1
[i
]);
3163 for (i
= 0; i
< 8; ++i
)
3165 size
= D3DXGetDeclVertexSize(declaration2
, i
);
3166 ok(size
== sizes2
[i
], "Got size %u for stream %u, expected %u.\n", size
, i
, sizes2
[i
]);
3170 static void D3DXGenerateAdjacencyTest(void)
3175 IDirect3DDevice9
*device
;
3176 D3DPRESENT_PARAMETERS d3dpp
;
3177 ID3DXMesh
*d3dxmesh
= NULL
;
3178 D3DXVECTOR3
*vertices
= NULL
;
3179 WORD
*indices
= NULL
;
3183 D3DXVECTOR3 vertices
[6];
3185 WORD indices
[3 * 3];
3187 DWORD adjacency
[3 * 3];
3189 { /* for epsilon < 0, indices must match for faces to be adjacent */
3190 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}},
3191 2, {0, 1, 2, 0, 2, 3},
3193 {-1, -1, 1, 0, -1, -1},
3196 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}},
3197 2, {0, 1, 2, 3, 4, 5},
3199 {-1, -1, -1, -1, -1, -1},
3201 { /* for epsilon == 0, indices or vertices must match for faces to be adjacent */
3202 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}},
3203 2, {0, 1, 2, 3, 4, 5},
3205 {-1, -1, 1, 0, -1, -1},
3207 { /* for epsilon > 0, vertices must be less than (but NOT equal to) epsilon distance away */
3208 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}},
3209 2, {0, 1, 2, 3, 4, 5},
3211 {-1, -1, -1, -1, -1, -1},
3213 { /* for epsilon > 0, vertices must be less than (but NOT equal to) epsilon distance away */
3214 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}},
3215 2, {0, 1, 2, 3, 4, 5},
3217 {-1, -1, 1, 0, -1, -1},
3219 { /* length between vertices are compared to epsilon, not the individual dimension deltas */
3220 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}},
3221 2, {0, 1, 2, 3, 4, 5},
3222 0.353, /* < sqrt(0.25*0.25 + 0.25*0.25) */
3223 {-1, -1, -1, -1, -1, -1},
3226 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}},
3227 2, {0, 1, 2, 3, 4, 5},
3228 0.354, /* > sqrt(0.25*0.25 + 0.25*0.25) */
3229 {-1, -1, 1, 0, -1, -1},
3231 { /* adjacent faces must have opposite winding orders at the shared edge */
3232 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}},
3233 2, {0, 1, 2, 0, 3, 2},
3235 {-1, -1, -1, -1, -1, -1},
3239 wnd
= CreateWindow("static", "d3dx9_test", 0, 0, 0, 0, 0, NULL
, NULL
, NULL
, NULL
);
3242 skip("Couldn't create application window\n");
3245 d3d
= Direct3DCreate9(D3D_SDK_VERSION
);
3248 skip("Couldn't create IDirect3D9 object\n");
3253 ZeroMemory(&d3dpp
, sizeof(d3dpp
));
3254 d3dpp
.Windowed
= TRUE
;
3255 d3dpp
.SwapEffect
= D3DSWAPEFFECT_DISCARD
;
3256 hr
= IDirect3D9_CreateDevice(d3d
, D3DADAPTER_DEFAULT
, D3DDEVTYPE_HAL
, wnd
, D3DCREATE_MIXED_VERTEXPROCESSING
, &d3dpp
, &device
);
3259 skip("Failed to create IDirect3DDevice9 object %#x\n", hr
);
3260 IDirect3D9_Release(d3d
);
3265 for (i
= 0; i
< ARRAY_SIZE(test_data
); i
++)
3267 DWORD adjacency
[ARRAY_SIZE(test_data
[0].adjacency
)];
3270 if (d3dxmesh
) d3dxmesh
->lpVtbl
->Release(d3dxmesh
);
3273 hr
= D3DXCreateMeshFVF(test_data
[i
].num_faces
, test_data
[i
].num_vertices
, 0, D3DFVF_XYZ
, device
, &d3dxmesh
);
3274 ok(hr
== D3D_OK
, "Got result %x, expected %x (D3D_OK)\n", hr
, D3D_OK
);
3276 hr
= d3dxmesh
->lpVtbl
->LockVertexBuffer(d3dxmesh
, D3DLOCK_DISCARD
, (void**)&vertices
);
3277 ok(hr
== D3D_OK
, "test %d: Got result %x, expected %x (D3D_OK)\n", i
, hr
, D3D_OK
);
3278 if (FAILED(hr
)) continue;
3279 CopyMemory(vertices
, test_data
[i
].vertices
, test_data
[i
].num_vertices
* sizeof(test_data
[0].vertices
[0]));
3280 d3dxmesh
->lpVtbl
->UnlockVertexBuffer(d3dxmesh
);
3282 hr
= d3dxmesh
->lpVtbl
->LockIndexBuffer(d3dxmesh
, D3DLOCK_DISCARD
, (void**)&indices
);
3283 ok(hr
== D3D_OK
, "test %d: Got result %x, expected %x (D3D_OK)\n", i
, hr
, D3D_OK
);
3284 if (FAILED(hr
)) continue;
3285 CopyMemory(indices
, test_data
[i
].indices
, test_data
[i
].num_faces
* 3 * sizeof(test_data
[0].indices
[0]));
3286 d3dxmesh
->lpVtbl
->UnlockIndexBuffer(d3dxmesh
);
3289 hr
= d3dxmesh
->lpVtbl
->GenerateAdjacency(d3dxmesh
, 0.0f
, NULL
);
3290 ok(hr
== D3DERR_INVALIDCALL
, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr
, D3DERR_INVALIDCALL
);
3293 hr
= d3dxmesh
->lpVtbl
->GenerateAdjacency(d3dxmesh
, test_data
[i
].epsilon
, adjacency
);
3294 ok(hr
== D3D_OK
, "Got result %x, expected %x (D3D_OK)\n", hr
, D3D_OK
);
3295 if (FAILED(hr
)) continue;
3297 for (j
= 0; j
< test_data
[i
].num_faces
* 3; j
++)
3298 ok(adjacency
[j
] == test_data
[i
].adjacency
[j
],
3299 "Test %d adjacency %d: Got result %u, expected %u\n", i
, j
,
3300 adjacency
[j
], test_data
[i
].adjacency
[j
]);
3302 if (d3dxmesh
) d3dxmesh
->lpVtbl
->Release(d3dxmesh
);
3307 D3DXBoundProbeTest();
3308 D3DXComputeBoundingBoxTest();
3309 D3DXComputeBoundingSphereTest();
3310 D3DXGetFVFVertexSizeTest();
3311 D3DXIntersectTriTest();
3312 D3DXCreateMeshTest();
3313 D3DXCreateMeshFVFTest();
3314 D3DXCreateBoxTest();
3315 D3DXCreateSphereTest();
3316 D3DXCreateCylinderTest();
3317 D3DXCreateTextTest();
3318 test_get_decl_length();
3319 test_get_decl_vertex_size();
3320 test_fvf_decl_conversion();
3321 D3DXGenerateAdjacencyTest();