ReactOS 0.4.15-dev-7958-gcd0bb1a
mesh.c
Go to the documentation of this file.
1#ifdef __REACTOS__
2#include "precomp.h"
3#include <rmxftmpl.h>
4#else
5 /*
6 * Mesh operations specific to D3DX9.
7 *
8 * Copyright (C) 2005 Henri Verbeet
9 * Copyright (C) 2006 Ivan Gyurdiev
10 * Copyright (C) 2009 David Adam
11 * Copyright (C) 2010 Tony Wasserka
12 * Copyright (C) 2011 Dylan Smith
13 * Copyright (C) 2011 Michael Mc Donnell
14 * Copyright (C) 2013 Christian Costa
15 *
16 * This library is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU Lesser General Public
18 * License as published by the Free Software Foundation; either
19 * version 2.1 of the License, or (at your option) any later version.
20 *
21 * This library is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 * Lesser General Public License for more details.
25 *
26 * You should have received a copy of the GNU Lesser General Public
27 * License along with this library; if not, write to the Free Software
28 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
29 */
30
31
32#include <assert.h>
33#include <float.h>
34
35#include "d3dx9_private.h"
36#undef MAKE_DDHRESULT
37#include "dxfile.h"
38#include "rmxfguid.h"
39#include "rmxftmpl.h"
40#include "wine/list.h"
41#endif /* __REACTOS__ */
42
44
46{
47 ID3DXMesh ID3DXMesh_iface;
49
54 IDirect3DDevice9 *device;
56 IDirect3DVertexDeclaration9 *vertex_declaration;
59 IDirect3DVertexBuffer9 *vertex_buffer;
60 IDirect3DIndexBuffer9 *index_buffer;
65};
66
67static const UINT d3dx_decltype_size[] =
68{
69 /* D3DDECLTYPE_FLOAT1 */ sizeof(FLOAT),
70 /* D3DDECLTYPE_FLOAT2 */ sizeof(D3DXVECTOR2),
71 /* D3DDECLTYPE_FLOAT3 */ sizeof(D3DXVECTOR3),
72 /* D3DDECLTYPE_FLOAT4 */ sizeof(D3DXVECTOR4),
73 /* D3DDECLTYPE_D3DCOLOR */ sizeof(D3DCOLOR),
74 /* D3DDECLTYPE_UBYTE4 */ 4 * sizeof(BYTE),
75 /* D3DDECLTYPE_SHORT2 */ 2 * sizeof(SHORT),
76 /* D3DDECLTYPE_SHORT4 */ 4 * sizeof(SHORT),
77 /* D3DDECLTYPE_UBYTE4N */ 4 * sizeof(BYTE),
78 /* D3DDECLTYPE_SHORT2N */ 2 * sizeof(SHORT),
79 /* D3DDECLTYPE_SHORT4N */ 4 * sizeof(SHORT),
80 /* D3DDECLTYPE_USHORT2N */ 2 * sizeof(USHORT),
81 /* D3DDECLTYPE_USHORT4N */ 4 * sizeof(USHORT),
82 /* D3DDECLTYPE_UDEC3 */ 4, /* 3 * 10 bits + 2 padding */
83 /* D3DDECLTYPE_DEC3N */ 4,
84 /* D3DDECLTYPE_FLOAT16_2 */ 2 * sizeof(D3DXFLOAT16),
85 /* D3DDECLTYPE_FLOAT16_4 */ 4 * sizeof(D3DXFLOAT16),
86};
87
88static inline struct d3dx9_mesh *impl_from_ID3DXMesh(ID3DXMesh *iface)
89{
90 return CONTAINING_RECORD(iface, struct d3dx9_mesh, ID3DXMesh_iface);
91}
92
93static HRESULT WINAPI d3dx9_mesh_QueryInterface(ID3DXMesh *iface, REFIID riid, void **out)
94{
95 TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
96
98 IsEqualGUID(riid, &IID_ID3DXBaseMesh) ||
99 IsEqualGUID(riid, &IID_ID3DXMesh))
100 {
101 iface->lpVtbl->AddRef(iface);
102 *out = iface;
103 return S_OK;
104 }
105
106 WARN("Interface %s not found.\n", debugstr_guid(riid));
107
108 return E_NOINTERFACE;
109}
110
111static ULONG WINAPI d3dx9_mesh_AddRef(ID3DXMesh *iface)
112{
113 struct d3dx9_mesh *mesh = impl_from_ID3DXMesh(iface);
114 ULONG refcount = InterlockedIncrement(&mesh->ref);
115
116 TRACE("%p increasing refcount to %u.\n", mesh, refcount);
117
118 return refcount;
119}
120
121static ULONG WINAPI d3dx9_mesh_Release(ID3DXMesh *iface)
122{
123 struct d3dx9_mesh *mesh = impl_from_ID3DXMesh(iface);
124 ULONG refcount = InterlockedDecrement(&mesh->ref);
125
126 TRACE("%p decreasing refcount to %u.\n", mesh, refcount);
127
128 if (!refcount)
129 {
130 IDirect3DIndexBuffer9_Release(mesh->index_buffer);
131 IDirect3DVertexBuffer9_Release(mesh->vertex_buffer);
132 if (mesh->vertex_declaration)
133 IDirect3DVertexDeclaration9_Release(mesh->vertex_declaration);
135 HeapFree(GetProcessHeap(), 0, mesh->attrib_buffer);
136 HeapFree(GetProcessHeap(), 0, mesh->attrib_table);
138 }
139
140 return refcount;
141}
142
143static HRESULT WINAPI d3dx9_mesh_DrawSubset(ID3DXMesh *iface, DWORD attrib_id)
144{
145 struct d3dx9_mesh *This = impl_from_ID3DXMesh(iface);
146 HRESULT hr;
147 DWORD face_start;
148 DWORD face_end = 0;
149 DWORD vertex_size;
150
151 TRACE("iface %p, attrib_id %u.\n", iface, attrib_id);
152
153 if (!This->vertex_declaration)
154 {
155 WARN("Can't draw a mesh with an invalid vertex declaration.\n");
156 return E_FAIL;
157 }
158
159 vertex_size = iface->lpVtbl->GetNumBytesPerVertex(iface);
160
161 hr = IDirect3DDevice9_SetVertexDeclaration(This->device, This->vertex_declaration);
162 if (FAILED(hr)) return hr;
163 hr = IDirect3DDevice9_SetStreamSource(This->device, 0, This->vertex_buffer, 0, vertex_size);
164 if (FAILED(hr)) return hr;
165 hr = IDirect3DDevice9_SetIndices(This->device, This->index_buffer);
166 if (FAILED(hr)) return hr;
167
168 while (face_end < This->numfaces)
169 {
170 for (face_start = face_end; face_start < This->numfaces; face_start++)
171 {
172 if (This->attrib_buffer[face_start] == attrib_id)
173 break;
174 }
175 if (face_start >= This->numfaces)
176 break;
177 for (face_end = face_start + 1; face_end < This->numfaces; face_end++)
178 {
179 if (This->attrib_buffer[face_end] != attrib_id)
180 break;
181 }
182
184 0, 0, This->numvertices, face_start * 3, face_end - face_start);
185 if (FAILED(hr)) return hr;
186 }
187
188 return D3D_OK;
189}
190
191static DWORD WINAPI d3dx9_mesh_GetNumFaces(ID3DXMesh *iface)
192{
193 struct d3dx9_mesh *mesh = impl_from_ID3DXMesh(iface);
194
195 TRACE("iface %p.\n", iface);
196
197 return mesh->numfaces;
198}
199
200static DWORD WINAPI d3dx9_mesh_GetNumVertices(ID3DXMesh *iface)
201{
202 struct d3dx9_mesh *mesh = impl_from_ID3DXMesh(iface);
203
204 TRACE("iface %p.\n", iface);
205
206 return mesh->numvertices;
207}
208
209static DWORD WINAPI d3dx9_mesh_GetFVF(ID3DXMesh *iface)
210{
211 struct d3dx9_mesh *mesh = impl_from_ID3DXMesh(iface);
212
213 TRACE("iface %p.\n", iface);
214
215 return mesh->fvf;
216}
217
219{
220 memcpy(dst, src, num_elem * sizeof(*src));
221}
222
224{
225 struct d3dx9_mesh *mesh = impl_from_ID3DXMesh(iface);
226
227 TRACE("iface %p, declaration %p.\n", iface, declaration);
228
229 if (!declaration)
230 return D3DERR_INVALIDCALL;
231
232 copy_declaration(declaration, mesh->cached_declaration, mesh->num_elem);
233
234 return D3D_OK;
235}
236
238{
239 struct d3dx9_mesh *mesh = impl_from_ID3DXMesh(iface);
240
241 TRACE("iface %p.\n", iface);
242
243 return mesh->vertex_declaration_size;
244}
245
246static DWORD WINAPI d3dx9_mesh_GetOptions(ID3DXMesh *iface)
247{
248 struct d3dx9_mesh *mesh = impl_from_ID3DXMesh(iface);
249
250 TRACE("iface %p.\n", iface);
251
252 return mesh->options;
253}
254
255static HRESULT WINAPI d3dx9_mesh_GetDevice(struct ID3DXMesh *iface, struct IDirect3DDevice9 **device)
256{
257 struct d3dx9_mesh *mesh = impl_from_ID3DXMesh(iface);
258
259 TRACE("iface %p, device %p.\n", iface, device);
260
261 if (!device)
262 return D3DERR_INVALIDCALL;
263 *device = mesh->device;
265
266 return D3D_OK;
267}
268
269static HRESULT WINAPI d3dx9_mesh_CloneMeshFVF(struct ID3DXMesh *iface, DWORD options, DWORD fvf,
270 struct IDirect3DDevice9 *device, struct ID3DXMesh **clone_mesh)
271{
272 HRESULT hr;
274
275 TRACE("iface %p, options %#x, fvf %#x, device %p, clone_mesh %p.\n",
276 iface, options, fvf, device, clone_mesh);
277
279 return hr;
280
281 return iface->lpVtbl->CloneMesh(iface, options, declaration, device, clone_mesh);
282}
283
285{
287
288 if (value < 0.0f)
289 {
290 return 0.0f;
291 }
292 else
293 {
294 if (value > UCHAR_MAX) /* Clamp at 255 */
295 return UCHAR_MAX;
296 else
297 return value;
298 }
299}
300
302{
303 value = value * SHRT_MAX;
304
305 /* The tests show that the range is SHRT_MIN + 1 to SHRT_MAX. */
306 if (value <= SHRT_MIN)
307 {
308 return SHRT_MIN + 1;
309 }
310 else if (value > SHRT_MAX)
311 {
312 return SHRT_MAX;
313 }
314 else
315 {
316 return value;
317 }
318}
319
321{
323
324 if (value < 0.0f)
325 {
326 return 0.0f;
327 }
328 else
329 {
330 if (value > USHRT_MAX) /* Clamp at 65535 */
331 return USHRT_MAX;
332 else
333 return value;
334 }
335}
336
338{
339 int res = (INT)(value + 0.5f);
340
341 return res;
342}
343
344static void convert_float4(BYTE *dst, const D3DXVECTOR4 *src, D3DDECLTYPE type_dst)
345{
346 BOOL fixme_once = FALSE;
347
348 switch (type_dst)
349 {
351 {
352 FLOAT *dst_ptr = (FLOAT*)dst;
353 *dst_ptr = src->x;
354 break;
355 }
357 {
358 D3DXVECTOR2 *dst_ptr = (D3DXVECTOR2*)dst;
359 dst_ptr->x = src->x;
360 dst_ptr->y = src->y;
361 break;
362 }
364 {
365 D3DXVECTOR3 *dst_ptr = (D3DXVECTOR3*)dst;
366 dst_ptr->x = src->x;
367 dst_ptr->y = src->y;
368 dst_ptr->z = src->z;
369 break;
370 }
372 {
373 D3DXVECTOR4 *dst_ptr = (D3DXVECTOR4*)dst;
374 dst_ptr->x = src->x;
375 dst_ptr->y = src->y;
376 dst_ptr->z = src->z;
377 dst_ptr->w = src->w;
378 break;
379 }
381 {
386 break;
387 }
389 {
390 dst[0] = src->x < 0.0f ? 0 : (BYTE)simple_round(src->x);
391 dst[1] = src->y < 0.0f ? 0 : (BYTE)simple_round(src->y);
392 dst[2] = src->z < 0.0f ? 0 : (BYTE)simple_round(src->z);
393 dst[3] = src->w < 0.0f ? 0 : (BYTE)simple_round(src->w);
394 break;
395 }
397 {
398 SHORT *dst_ptr = (SHORT*)dst;
399 dst_ptr[0] = (SHORT)simple_round(src->x);
400 dst_ptr[1] = (SHORT)simple_round(src->y);
401 break;
402 }
404 {
405 SHORT *dst_ptr = (SHORT*)dst;
406 dst_ptr[0] = (SHORT)simple_round(src->x);
407 dst_ptr[1] = (SHORT)simple_round(src->y);
408 dst_ptr[2] = (SHORT)simple_round(src->z);
409 dst_ptr[3] = (SHORT)simple_round(src->w);
410 break;
411 }
413 {
418 break;
419 }
421 {
422 SHORT *dst_ptr = (SHORT*)dst;
423 dst_ptr[0] = (SHORT)simple_round(scale_clamp_shortn(src->x));
424 dst_ptr[1] = (SHORT)simple_round(scale_clamp_shortn(src->y));
425 break;
426 }
428 {
429 SHORT *dst_ptr = (SHORT*)dst;
430 dst_ptr[0] = (SHORT)simple_round(scale_clamp_shortn(src->x));
431 dst_ptr[1] = (SHORT)simple_round(scale_clamp_shortn(src->y));
432 dst_ptr[2] = (SHORT)simple_round(scale_clamp_shortn(src->z));
433 dst_ptr[3] = (SHORT)simple_round(scale_clamp_shortn(src->w));
434 break;
435 }
437 {
438 USHORT *dst_ptr = (USHORT*)dst;
439 dst_ptr[0] = (USHORT)simple_round(scale_clamp_ushortn(src->x));
440 dst_ptr[1] = (USHORT)simple_round(scale_clamp_ushortn(src->y));
441 break;
442 }
444 {
445 USHORT *dst_ptr = (USHORT*)dst;
446 dst_ptr[0] = (USHORT)simple_round(scale_clamp_ushortn(src->x));
447 dst_ptr[1] = (USHORT)simple_round(scale_clamp_ushortn(src->y));
448 dst_ptr[2] = (USHORT)simple_round(scale_clamp_ushortn(src->z));
449 dst_ptr[3] = (USHORT)simple_round(scale_clamp_ushortn(src->w));
450 break;
451 }
453 {
455 break;
456 }
458 {
460 break;
461 }
462 default:
463 if (!fixme_once++)
464 FIXME("Conversion from D3DDECLTYPE_FLOAT4 to %d not implemented.\n", type_dst);
465 break;
466 }
467}
468
469static void convert_component(BYTE *dst, BYTE *src, D3DDECLTYPE type_dst, D3DDECLTYPE type_src)
470{
471 BOOL fixme_once = FALSE;
472
473 switch (type_src)
474 {
476 {
477 FLOAT *src_ptr = (FLOAT*)src;
478 D3DXVECTOR4 src_float4 = {*src_ptr, 0.0f, 0.0f, 1.0f};
479 convert_float4(dst, &src_float4, type_dst);
480 break;
481 }
483 {
484 D3DXVECTOR2 *src_ptr = (D3DXVECTOR2*)src;
485 D3DXVECTOR4 src_float4 = {src_ptr->x, src_ptr->y, 0.0f, 1.0f};
486 convert_float4(dst, &src_float4, type_dst);
487 break;
488 }
490 {
491 D3DXVECTOR3 *src_ptr = (D3DXVECTOR3*)src;
492 D3DXVECTOR4 src_float4 = {src_ptr->x, src_ptr->y, src_ptr->z, 1.0f};
493 convert_float4(dst, &src_float4, type_dst);
494 break;
495 }
497 {
498 D3DXVECTOR4 *src_ptr = (D3DXVECTOR4*)src;
499 D3DXVECTOR4 src_float4 = {src_ptr->x, src_ptr->y, src_ptr->z, src_ptr->w};
500 convert_float4(dst, &src_float4, type_dst);
501 break;
502 }
504 {
505 D3DXVECTOR4 src_float4 =
506 {
507 (FLOAT)src[2]/UCHAR_MAX,
508 (FLOAT)src[1]/UCHAR_MAX,
509 (FLOAT)src[0]/UCHAR_MAX,
511 };
512 convert_float4(dst, &src_float4, type_dst);
513 break;
514 }
516 {
517 D3DXVECTOR4 src_float4 = {src[0], src[1], src[2], src[3]};
518 convert_float4(dst, &src_float4, type_dst);
519 break;
520 }
522 {
523 SHORT *src_ptr = (SHORT*)src;
524 D3DXVECTOR4 src_float4 = {src_ptr[0], src_ptr[1], 0.0f, 1.0f};
525 convert_float4(dst, &src_float4, type_dst);
526 break;
527 }
529 {
530 SHORT *src_ptr = (SHORT*)src;
531 D3DXVECTOR4 src_float4 = {src_ptr[0], src_ptr[1], src_ptr[2], src_ptr[3]};
532 convert_float4(dst, &src_float4, type_dst);
533 break;
534 }
536 {
537 D3DXVECTOR4 src_float4 =
538 {
539 (FLOAT)src[0]/UCHAR_MAX,
540 (FLOAT)src[1]/UCHAR_MAX,
541 (FLOAT)src[2]/UCHAR_MAX,
543 };
544 convert_float4(dst, &src_float4, type_dst);
545 break;
546 }
548 {
549 SHORT *src_ptr = (SHORT*)src;
550 D3DXVECTOR4 src_float4 = {(FLOAT)src_ptr[0]/SHRT_MAX, (FLOAT)src_ptr[1]/SHRT_MAX, 0.0f, 1.0f};
551 convert_float4(dst, &src_float4, type_dst);
552 break;
553 }
555 {
556 SHORT *src_ptr = (SHORT*)src;
557 D3DXVECTOR4 src_float4 =
558 {
559 (FLOAT)src_ptr[0]/SHRT_MAX,
560 (FLOAT)src_ptr[1]/SHRT_MAX,
561 (FLOAT)src_ptr[2]/SHRT_MAX,
562 (FLOAT)src_ptr[3]/SHRT_MAX
563 };
564 convert_float4(dst, &src_float4, type_dst);
565 break;
566 }
568 {
569 D3DXVECTOR4 src_float4 = {0.0f, 0.0f, 0.0f, 1.0f};
570 D3DXFloat16To32Array((FLOAT*)&src_float4, (D3DXFLOAT16*)src, 2);
571 convert_float4(dst, &src_float4, type_dst);
572 break;
573 }
575 {
576 D3DXVECTOR4 src_float4;
577 D3DXFloat16To32Array((FLOAT*)&src_float4, (D3DXFLOAT16*)src, 4);
578 convert_float4(dst, &src_float4, type_dst);
579 break;
580 }
581 default:
582 if (!fixme_once++)
583 FIXME("Conversion of D3DDECLTYPE %d to %d not implemented.\n", type_src, type_dst);
584 break;
585 }
586}
587
589{
590 INT i;
591
592 for (i = 0; declaration[i].Stream != 0xff; i++)
593 {
594 if (orig_declaration.Usage == declaration[i].Usage
595 && orig_declaration.UsageIndex == declaration[i].UsageIndex)
596 {
597 return i;
598 }
599 }
600
601 return -1;
602}
603
604static HRESULT convert_vertex_buffer(ID3DXMesh *mesh_dst, ID3DXMesh *mesh_src)
605{
606 HRESULT hr;
607 D3DVERTEXELEMENT9 orig_declaration[MAX_FVF_DECL_SIZE] = {D3DDECL_END()};
609 BYTE *vb_dst = NULL;
610 BYTE *vb_src = NULL;
611 UINT i;
612 UINT num_vertices = mesh_src->lpVtbl->GetNumVertices(mesh_src);
613 UINT dst_vertex_size = mesh_dst->lpVtbl->GetNumBytesPerVertex(mesh_dst);
614 UINT src_vertex_size = mesh_src->lpVtbl->GetNumBytesPerVertex(mesh_src);
615
616 hr = mesh_src->lpVtbl->GetDeclaration(mesh_src, orig_declaration);
617 if (FAILED(hr)) return hr;
618 hr = mesh_dst->lpVtbl->GetDeclaration(mesh_dst, declaration);
619 if (FAILED(hr)) return hr;
620
621 hr = mesh_src->lpVtbl->LockVertexBuffer(mesh_src, D3DLOCK_READONLY, (void**)&vb_src);
622 if (FAILED(hr)) goto cleanup;
623 hr = mesh_dst->lpVtbl->LockVertexBuffer(mesh_dst, 0, (void**)&vb_dst);
624 if (FAILED(hr)) goto cleanup;
625
626 /* Clear all new fields by clearing the entire vertex buffer. */
627 memset(vb_dst, 0, num_vertices * dst_vertex_size);
628
629 for (i = 0; orig_declaration[i].Stream != 0xff; i++)
630 {
631 INT eq_idx = get_equivalent_declaration_index(orig_declaration[i], declaration);
632
633 if (eq_idx >= 0)
634 {
635 UINT j;
636 for (j = 0; j < num_vertices; j++)
637 {
638 UINT idx_dst = dst_vertex_size * j + declaration[eq_idx].Offset;
639 UINT idx_src = src_vertex_size * j + orig_declaration[i].Offset;
640 UINT type_size = d3dx_decltype_size[orig_declaration[i].Type];
641
642 if (orig_declaration[i].Type == declaration[eq_idx].Type)
643 memcpy(&vb_dst[idx_dst], &vb_src[idx_src], type_size);
644 else
645 convert_component(&vb_dst[idx_dst], &vb_src[idx_src], declaration[eq_idx].Type, orig_declaration[i].Type);
646 }
647 }
648 }
649
650 hr = D3D_OK;
651cleanup:
652 if (vb_dst) mesh_dst->lpVtbl->UnlockVertexBuffer(mesh_dst);
653 if (vb_src) mesh_src->lpVtbl->UnlockVertexBuffer(mesh_src);
654
655 return hr;
656}
657
658static BOOL declaration_equals(const D3DVERTEXELEMENT9 *declaration1, const D3DVERTEXELEMENT9 *declaration2)
659{
660 UINT size1 = 0, size2 = 0;
661
662 /* Find the size of each declaration */
663 while (declaration1[size1].Stream != 0xff) size1++;
664 while (declaration2[size2].Stream != 0xff) size2++;
665
666 /* If not same size then they are definitely not equal */
667 if (size1 != size2)
668 return FALSE;
669
670 /* Check that all components are the same */
671 if (memcmp(declaration1, declaration2, size1*sizeof(*declaration1)) == 0)
672 return TRUE;
673
674 return FALSE;
675}
676
677static HRESULT WINAPI d3dx9_mesh_CloneMesh(struct ID3DXMesh *iface, DWORD options,
678 const D3DVERTEXELEMENT9 *declaration, struct IDirect3DDevice9 *device, struct ID3DXMesh **clone_mesh_out)
679{
680 struct d3dx9_mesh *This = impl_from_ID3DXMesh(iface);
681 struct d3dx9_mesh *cloned_this;
682 ID3DXMesh *clone_mesh;
683 D3DVERTEXELEMENT9 orig_declaration[MAX_FVF_DECL_SIZE] = { D3DDECL_END() };
684 void *data_in, *data_out;
685 DWORD vertex_size;
686 HRESULT hr;
687 BOOL same_declaration;
688
689 TRACE("iface %p, options %#x, declaration %p, device %p, clone_mesh_out %p.\n",
690 iface, options, declaration, device, clone_mesh_out);
691
692 if (!clone_mesh_out)
693 return D3DERR_INVALIDCALL;
694
695 hr = iface->lpVtbl->GetDeclaration(iface, orig_declaration);
696 if (FAILED(hr)) return hr;
697
698 hr = D3DXCreateMesh(This->numfaces, This->numvertices, options & ~D3DXMESH_VB_SHARE,
699 declaration, device, &clone_mesh);
700 if (FAILED(hr)) return hr;
701
702 cloned_this = impl_from_ID3DXMesh(clone_mesh);
703 vertex_size = clone_mesh->lpVtbl->GetNumBytesPerVertex(clone_mesh);
704 same_declaration = declaration_equals(declaration, orig_declaration);
705
707 if (!same_declaration) {
709 goto error;
710 }
711 IDirect3DVertexBuffer9_AddRef(This->vertex_buffer);
712 /* FIXME: refactor to avoid creating a new vertex buffer */
714 cloned_this->vertex_buffer = This->vertex_buffer;
715 } else if (same_declaration) {
716 hr = iface->lpVtbl->LockVertexBuffer(iface, D3DLOCK_READONLY, &data_in);
717 if (FAILED(hr)) goto error;
718 hr = clone_mesh->lpVtbl->LockVertexBuffer(clone_mesh, 0, &data_out);
719 if (FAILED(hr)) {
720 iface->lpVtbl->UnlockVertexBuffer(iface);
721 goto error;
722 }
723 memcpy(data_out, data_in, This->numvertices * vertex_size);
724 clone_mesh->lpVtbl->UnlockVertexBuffer(clone_mesh);
725 iface->lpVtbl->UnlockVertexBuffer(iface);
726 } else {
727 hr = convert_vertex_buffer(clone_mesh, iface);
728 if (FAILED(hr)) goto error;
729 }
730
731 hr = iface->lpVtbl->LockIndexBuffer(iface, D3DLOCK_READONLY, &data_in);
732 if (FAILED(hr)) goto error;
733 hr = clone_mesh->lpVtbl->LockIndexBuffer(clone_mesh, 0, &data_out);
734 if (FAILED(hr)) {
735 iface->lpVtbl->UnlockIndexBuffer(iface);
736 goto error;
737 }
738 if ((options ^ This->options) & D3DXMESH_32BIT) {
739 DWORD i;
740 if (options & D3DXMESH_32BIT) {
741 for (i = 0; i < This->numfaces * 3; i++)
742 ((DWORD*)data_out)[i] = ((WORD*)data_in)[i];
743 } else {
744 for (i = 0; i < This->numfaces * 3; i++)
745 ((WORD*)data_out)[i] = ((DWORD*)data_in)[i];
746 }
747 } else {
748 memcpy(data_out, data_in, This->numfaces * 3 * (options & D3DXMESH_32BIT ? 4 : 2));
749 }
750 clone_mesh->lpVtbl->UnlockIndexBuffer(clone_mesh);
751 iface->lpVtbl->UnlockIndexBuffer(iface);
752
753 memcpy(cloned_this->attrib_buffer, This->attrib_buffer, This->numfaces * sizeof(*This->attrib_buffer));
754
755 if (This->attrib_table_size)
756 {
757 cloned_this->attrib_table_size = This->attrib_table_size;
758 cloned_this->attrib_table = HeapAlloc(GetProcessHeap(), 0, This->attrib_table_size * sizeof(*This->attrib_table));
759 if (!cloned_this->attrib_table) {
761 goto error;
762 }
763 memcpy(cloned_this->attrib_table, This->attrib_table, This->attrib_table_size * sizeof(*This->attrib_table));
764 }
765
766 *clone_mesh_out = clone_mesh;
767
768 return D3D_OK;
769error:
770 IUnknown_Release(clone_mesh);
771 return hr;
772}
773
774static HRESULT WINAPI d3dx9_mesh_GetVertexBuffer(struct ID3DXMesh *iface,
775 struct IDirect3DVertexBuffer9 **vertex_buffer)
776{
777 struct d3dx9_mesh *mesh = impl_from_ID3DXMesh(iface);
778
779 TRACE("iface %p, vertex_buffer %p.\n", iface, vertex_buffer);
780
781 if (!vertex_buffer)
782 return D3DERR_INVALIDCALL;
783 *vertex_buffer = mesh->vertex_buffer;
784 IDirect3DVertexBuffer9_AddRef(mesh->vertex_buffer);
785
786 return D3D_OK;
787}
788
789static HRESULT WINAPI d3dx9_mesh_GetIndexBuffer(struct ID3DXMesh *iface,
790 struct IDirect3DIndexBuffer9 **index_buffer)
791{
792 struct d3dx9_mesh *mesh = impl_from_ID3DXMesh(iface);
793
794 TRACE("iface %p, index_buffer %p.\n", iface, index_buffer);
795
796 if (!index_buffer)
797 return D3DERR_INVALIDCALL;
798 *index_buffer = mesh->index_buffer;
799 IDirect3DIndexBuffer9_AddRef(mesh->index_buffer);
800
801 return D3D_OK;
802}
803
804static HRESULT WINAPI d3dx9_mesh_LockVertexBuffer(ID3DXMesh *iface, DWORD flags, void **data)
805{
806 struct d3dx9_mesh *mesh = impl_from_ID3DXMesh(iface);
807
808 TRACE("iface %p, flags %#x, data %p.\n", iface, flags, data);
809
810 return IDirect3DVertexBuffer9_Lock(mesh->vertex_buffer, 0, 0, data, flags);
811}
812
814{
815 struct d3dx9_mesh *mesh = impl_from_ID3DXMesh(iface);
816
817 TRACE("iface %p.\n", iface);
818
819 return IDirect3DVertexBuffer9_Unlock(mesh->vertex_buffer);
820}
821
822static HRESULT WINAPI d3dx9_mesh_LockIndexBuffer(ID3DXMesh *iface, DWORD flags, void **data)
823{
824 struct d3dx9_mesh *mesh = impl_from_ID3DXMesh(iface);
825
826 TRACE("iface %p, flags %#x, data %p.\n", iface, flags, data);
827
828 return IDirect3DIndexBuffer9_Lock(mesh->index_buffer, 0, 0, data, flags);
829}
830
832{
833 struct d3dx9_mesh *mesh = impl_from_ID3DXMesh(iface);
834
835 TRACE("iface %p.\n", iface);
836
837 return IDirect3DIndexBuffer9_Unlock(mesh->index_buffer);
838}
839
840/* FIXME: This looks just wrong, we never check *attrib_table_size before
841 * copying the data. */
844{
845 struct d3dx9_mesh *mesh = impl_from_ID3DXMesh(iface);
846
847 TRACE("iface %p, attrib_table %p, attrib_table_size %p.\n",
849
851 *attrib_table_size = mesh->attrib_table_size;
852
853 if (attrib_table)
854 memcpy(attrib_table, mesh->attrib_table, mesh->attrib_table_size * sizeof(*attrib_table));
855
856 return D3D_OK;
857}
858
860{
861 struct list entry;
864};
865
867{
868 struct list *lists;
870};
871
872/* Builds up a map of which face a new edge belongs to. That way the adjacency
873 * of another edge can be looked up. An edge has an adjacent face if there
874 * is an edge going in the opposite direction in the map. For example if the
875 * edge (v1, v2) belongs to face 4, and there is a mapping (v2, v1)->7, then
876 * face 4 and 7 are adjacent.
877 *
878 * Each edge might have been replaced with another edge, or none at all. There
879 * is at most one edge to face mapping, i.e. an edge can only belong to one
880 * face.
881 */
882static HRESULT init_edge_face_map(struct edge_face_map *edge_face_map, const DWORD *index_buffer,
883 const DWORD *point_reps, DWORD num_faces)
884{
885 DWORD face, edge;
886 DWORD i;
887
888 edge_face_map->lists = HeapAlloc(GetProcessHeap(), 0, 3 * num_faces * sizeof(*edge_face_map->lists));
889 if (!edge_face_map->lists) return E_OUTOFMEMORY;
890
891 edge_face_map->entries = HeapAlloc(GetProcessHeap(), 0, 3 * num_faces * sizeof(*edge_face_map->entries));
892 if (!edge_face_map->entries) return E_OUTOFMEMORY;
893
894
895 /* Initialize all lists */
896 for (i = 0; i < 3 * num_faces; i++)
897 {
899 }
900 /* Build edge face mapping */
901 for (face = 0; face < num_faces; face++)
902 {
903 for (edge = 0; edge < 3; edge++)
904 {
905 DWORD v1 = index_buffer[3*face + edge];
906 DWORD v2 = index_buffer[3*face + (edge+1)%3];
907 DWORD new_v1 = point_reps[v1]; /* What v1 has been replaced with */
908 DWORD new_v2 = point_reps[v2];
909
910 if (v1 != v2) /* Only map non-collapsed edges */
911 {
912 i = 3*face + edge;
913 edge_face_map->entries[i].v2 = new_v2;
914 edge_face_map->entries[i].face = face;
916 }
917 }
918 }
919
920 return D3D_OK;
921}
922
923static DWORD find_adjacent_face(struct edge_face_map *edge_face_map, DWORD vertex1, DWORD vertex2, DWORD num_faces)
924{
925 struct edge_face *edge_face_ptr;
926
927 LIST_FOR_EACH_ENTRY(edge_face_ptr, &edge_face_map->lists[vertex2], struct edge_face, entry)
928 {
929 if (edge_face_ptr->v2 == vertex1)
930 return edge_face_ptr->face;
931 }
932
933 return -1;
934}
935
937{
938 DWORD *id_point_reps;
939 DWORD i;
940
941 id_point_reps = HeapAlloc(GetProcessHeap(), 0, num_vertices * sizeof(*id_point_reps));
942 if (!id_point_reps)
943 return NULL;
944
945 for (i = 0; i < num_vertices; i++)
946 {
947 id_point_reps[i] = i;
948 }
949
950 return id_point_reps;
951}
952
954 const DWORD *point_reps, DWORD *adjacency)
955{
956 HRESULT hr;
957 DWORD num_faces = iface->lpVtbl->GetNumFaces(iface);
958 DWORD num_vertices = iface->lpVtbl->GetNumVertices(iface);
959 DWORD options = iface->lpVtbl->GetOptions(iface);
960 BOOL indices_are_16_bit = !(options & D3DXMESH_32BIT);
961 DWORD *ib = NULL;
962 void *ib_ptr = NULL;
963 DWORD face;
964 DWORD edge;
965 struct edge_face_map edge_face_map = {0};
966 const DWORD *point_reps_ptr = NULL;
967 DWORD *id_point_reps = NULL;
968
969 TRACE("iface %p, point_reps %p, adjacency %p.\n", iface, point_reps, adjacency);
970
971 if (!adjacency) return D3DERR_INVALIDCALL;
972
973 if (!point_reps) /* Identity point reps */
974 {
975 id_point_reps = generate_identity_point_reps(num_vertices);
976 if (!id_point_reps)
977 {
979 goto cleanup;
980 }
981
982 point_reps_ptr = id_point_reps;
983 }
984 else
985 {
986 point_reps_ptr = point_reps;
987 }
988
989 hr = iface->lpVtbl->LockIndexBuffer(iface, D3DLOCK_READONLY, &ib_ptr);
990 if (FAILED(hr)) goto cleanup;
991
992 if (indices_are_16_bit)
993 {
994 /* Widen 16 bit to 32 bit */
995 DWORD i;
996 WORD *ib_16bit = ib_ptr;
997 ib = HeapAlloc(GetProcessHeap(), 0, 3 * num_faces * sizeof(DWORD));
998 if (!ib)
999 {
1000 hr = E_OUTOFMEMORY;
1001 goto cleanup;
1002 }
1003 for (i = 0; i < 3 * num_faces; i++)
1004 {
1005 ib[i] = ib_16bit[i];
1006 }
1007 }
1008 else
1009 {
1010 ib = ib_ptr;
1011 }
1012
1013 hr = init_edge_face_map(&edge_face_map, ib, point_reps_ptr, num_faces);
1014 if (FAILED(hr)) goto cleanup;
1015
1016 /* Create adjacency */
1017 for (face = 0; face < num_faces; face++)
1018 {
1019 for (edge = 0; edge < 3; edge++)
1020 {
1021 DWORD v1 = ib[3*face + edge];
1022 DWORD v2 = ib[3*face + (edge+1)%3];
1023 DWORD new_v1 = point_reps_ptr[v1];
1024 DWORD new_v2 = point_reps_ptr[v2];
1025 DWORD adj_face;
1026
1027 adj_face = find_adjacent_face(&edge_face_map, new_v1, new_v2, num_faces);
1028 adjacency[3*face + edge] = adj_face;
1029 }
1030 }
1031
1032 hr = D3D_OK;
1033cleanup:
1034 HeapFree(GetProcessHeap(), 0, id_point_reps);
1035 if (indices_are_16_bit) HeapFree(GetProcessHeap(), 0, ib);
1038 if(ib_ptr) iface->lpVtbl->UnlockIndexBuffer(iface);
1039 return hr;
1040}
1041
1042/* ConvertAdjacencyToPointReps helper function.
1043 *
1044 * Goes around the edges of each face and replaces the vertices in any adjacent
1045 * face's edge with its own vertices(if its vertices have a lower index). This
1046 * way as few as possible low index vertices are shared among the faces. The
1047 * re-ordered index buffer is stored in new_indices.
1048 *
1049 * The vertices in a point representation must be ordered sequentially, e.g.
1050 * index 5 holds the index of the vertex that replaces vertex 5, i.e. if
1051 * vertex 5 is replaced by vertex 3 then index 5 would contain 3. If no vertex
1052 * replaces it, then it contains the same number as the index itself, e.g.
1053 * index 5 would contain 5. */
1054static HRESULT propagate_face_vertices(const DWORD *adjacency, DWORD *point_reps,
1055 const DWORD *indices, DWORD *new_indices, DWORD face, DWORD numfaces)
1056{
1057 const unsigned int VERTS_PER_FACE = 3;
1058 DWORD edge, opp_edge;
1059 DWORD face_base = VERTS_PER_FACE * face;
1060
1061 for (edge = 0; edge < VERTS_PER_FACE; edge++)
1062 {
1063 DWORD adj_face = adjacency[face_base + edge];
1064 DWORD adj_face_base;
1065 DWORD i;
1066 if (adj_face == -1) /* No adjacent face. */
1067 continue;
1068 else if (adj_face >= numfaces)
1069 {
1070 /* This throws exception on Windows */
1071 WARN("Index out of bounds. Got %d expected less than %d.\n",
1072 adj_face, numfaces);
1073 return D3DERR_INVALIDCALL;
1074 }
1075 adj_face_base = 3 * adj_face;
1076
1077 /* Find opposite edge in adjacent face. */
1078 for (opp_edge = 0; opp_edge < VERTS_PER_FACE; opp_edge++)
1079 {
1080 DWORD opp_edge_index = adj_face_base + opp_edge;
1081 if (adjacency[opp_edge_index] == face)
1082 break; /* Found opposite edge. */
1083 }
1084
1085 /* Replaces vertices in opposite edge with vertices from current edge. */
1086 for (i = 0; i < 2; i++)
1087 {
1088 DWORD from = face_base + (edge + (1 - i)) % VERTS_PER_FACE;
1089 DWORD to = adj_face_base + (opp_edge + i) % VERTS_PER_FACE;
1090
1091 /* Propagate lowest index. */
1092 if (new_indices[to] > new_indices[from])
1093 {
1094 new_indices[to] = new_indices[from];
1095 point_reps[indices[to]] = new_indices[from];
1096 }
1097 }
1098 }
1099
1100 return D3D_OK;
1101}
1102
1104 const DWORD *adjacency, DWORD *point_reps)
1105{
1106 struct d3dx9_mesh *This = impl_from_ID3DXMesh(iface);
1107 HRESULT hr;
1108 DWORD face;
1109 DWORD i;
1110 DWORD *indices = NULL;
1111 WORD *indices_16bit = NULL;
1112 DWORD *new_indices = NULL;
1113 const unsigned int VERTS_PER_FACE = 3;
1114
1115 TRACE("iface %p, adjacency %p, point_reps %p.\n", iface, adjacency, point_reps);
1116
1117 if (!adjacency)
1118 {
1119 WARN("NULL adjacency.\n");
1121 goto cleanup;
1122 }
1123
1124 if (!point_reps)
1125 {
1126 WARN("NULL point_reps.\n");
1128 goto cleanup;
1129 }
1130
1131 /* Should never happen as CreateMesh does not allow meshes with 0 faces */
1132 if (This->numfaces == 0)
1133 {
1134 ERR("Number of faces was zero.\n");
1136 goto cleanup;
1137 }
1138
1139 new_indices = HeapAlloc(GetProcessHeap(), 0, VERTS_PER_FACE * This->numfaces * sizeof(*indices));
1140 if (!new_indices)
1141 {
1142 hr = E_OUTOFMEMORY;
1143 goto cleanup;
1144 }
1145
1146 if (This->options & D3DXMESH_32BIT)
1147 {
1148 hr = iface->lpVtbl->LockIndexBuffer(iface, D3DLOCK_READONLY, (void**)&indices);
1149 if (FAILED(hr)) goto cleanup;
1150 memcpy(new_indices, indices, VERTS_PER_FACE * This->numfaces * sizeof(*indices));
1151 }
1152 else
1153 {
1154 /* Make a widening copy of indices_16bit into indices and new_indices
1155 * in order to re-use the helper function */
1156 hr = iface->lpVtbl->LockIndexBuffer(iface, D3DLOCK_READONLY, (void**)&indices_16bit);
1157 if (FAILED(hr)) goto cleanup;
1158 indices = HeapAlloc(GetProcessHeap(), 0, VERTS_PER_FACE * This->numfaces * sizeof(*indices));
1159 if (!indices)
1160 {
1161 hr = E_OUTOFMEMORY;
1162 goto cleanup;
1163 }
1164 for (i = 0; i < VERTS_PER_FACE * This->numfaces; i++)
1165 {
1166 new_indices[i] = indices_16bit[i];
1167 indices[i] = indices_16bit[i];
1168 }
1169 }
1170
1171 /* Vertices are ordered sequentially in the point representation. */
1172 for (i = 0; i < This->numvertices; i++)
1173 {
1174 point_reps[i] = i;
1175 }
1176
1177 /* Propagate vertices with low indices so as few vertices as possible
1178 * are used in the mesh.
1179 */
1180 for (face = 0; face < This->numfaces; face++)
1181 {
1182 hr = propagate_face_vertices(adjacency, point_reps, indices, new_indices, face, This->numfaces);
1183 if (FAILED(hr)) goto cleanup;
1184 }
1185 /* Go in opposite direction to catch all face orderings */
1186 for (face = 0; face < This->numfaces; face++)
1187 {
1188 hr = propagate_face_vertices(adjacency, point_reps,
1189 indices, new_indices,
1190 (This->numfaces - 1) - face, This->numfaces);
1191 if (FAILED(hr)) goto cleanup;
1192 }
1193
1194 hr = D3D_OK;
1195cleanup:
1196 if (This->options & D3DXMESH_32BIT)
1197 {
1198 if (indices) iface->lpVtbl->UnlockIndexBuffer(iface);
1199 }
1200 else
1201 {
1202 if (indices_16bit) iface->lpVtbl->UnlockIndexBuffer(iface);
1204 }
1205 HeapFree(GetProcessHeap(), 0, new_indices);
1206 return hr;
1207}
1208
1210 float key;
1213};
1214
1215static int __cdecl compare_vertex_keys(const void *a, const void *b)
1216{
1217 const struct vertex_metadata *left = a;
1218 const struct vertex_metadata *right = b;
1219 if (left->key == right->key)
1220 return 0;
1221 return left->key < right->key ? -1 : 1;
1222}
1223
1224static HRESULT WINAPI d3dx9_mesh_GenerateAdjacency(ID3DXMesh *iface, float epsilon, DWORD *adjacency)
1225{
1226 struct d3dx9_mesh *This = impl_from_ID3DXMesh(iface);
1227 HRESULT hr;
1228 BYTE *vertices = NULL;
1229 const DWORD *indices = NULL;
1230 DWORD vertex_size;
1232 /* sort the vertices by (x + y + z) to quickly find coincident vertices */
1233 struct vertex_metadata *sorted_vertices;
1234 /* shared_indices links together identical indices in the index buffer so
1235 * that adjacency checks can be limited to faces sharing a vertex */
1236 DWORD *shared_indices = NULL;
1237 const FLOAT epsilon_sq = epsilon * epsilon;
1238 DWORD i;
1239
1240 TRACE("iface %p, epsilon %.8e, adjacency %p.\n", iface, epsilon, adjacency);
1241
1242 if (!adjacency)
1243 return D3DERR_INVALIDCALL;
1244
1245 buffer_size = This->numfaces * 3 * sizeof(*shared_indices) + This->numvertices * sizeof(*sorted_vertices);
1246 if (!(This->options & D3DXMESH_32BIT))
1247 buffer_size += This->numfaces * 3 * sizeof(*indices);
1248 shared_indices = HeapAlloc(GetProcessHeap(), 0, buffer_size);
1249 if (!shared_indices)
1250 return E_OUTOFMEMORY;
1251 sorted_vertices = (struct vertex_metadata*)(shared_indices + This->numfaces * 3);
1252
1253 hr = iface->lpVtbl->LockVertexBuffer(iface, D3DLOCK_READONLY, (void**)&vertices);
1254 if (FAILED(hr)) goto cleanup;
1255 hr = iface->lpVtbl->LockIndexBuffer(iface, D3DLOCK_READONLY, (void**)&indices);
1256 if (FAILED(hr)) goto cleanup;
1257
1258 if (!(This->options & D3DXMESH_32BIT)) {
1259 const WORD *word_indices = (const WORD*)indices;
1260 DWORD *dword_indices = (DWORD*)(sorted_vertices + This->numvertices);
1261 indices = dword_indices;
1262 for (i = 0; i < This->numfaces * 3; i++)
1263 *dword_indices++ = *word_indices++;
1264 }
1265
1266 vertex_size = iface->lpVtbl->GetNumBytesPerVertex(iface);
1267 for (i = 0; i < This->numvertices; i++) {
1268 D3DXVECTOR3 *vertex = (D3DXVECTOR3*)(vertices + vertex_size * i);
1269 sorted_vertices[i].first_shared_index = -1;
1270 sorted_vertices[i].key = vertex->x + vertex->y + vertex->z;
1271 sorted_vertices[i].vertex_index = i;
1272 }
1273 for (i = 0; i < This->numfaces * 3; i++) {
1274 DWORD *first_shared_index = &sorted_vertices[indices[i]].first_shared_index;
1275 shared_indices[i] = *first_shared_index;
1277 adjacency[i] = -1;
1278 }
1279 qsort(sorted_vertices, This->numvertices, sizeof(*sorted_vertices), compare_vertex_keys);
1280
1281 for (i = 0; i < This->numvertices; i++) {
1282 struct vertex_metadata *sorted_vertex_a = &sorted_vertices[i];
1283 D3DXVECTOR3 *vertex_a = (D3DXVECTOR3*)(vertices + sorted_vertex_a->vertex_index * vertex_size);
1284 DWORD shared_index_a = sorted_vertex_a->first_shared_index;
1285
1286 while (shared_index_a != -1) {
1287 DWORD j = i;
1288 DWORD shared_index_b = shared_indices[shared_index_a];
1289 struct vertex_metadata *sorted_vertex_b = sorted_vertex_a;
1290
1291 while (TRUE) {
1292 while (shared_index_b != -1) {
1293 /* faces are adjacent if they have another coincident vertex */
1294 DWORD base_a = (shared_index_a / 3) * 3;
1295 DWORD base_b = (shared_index_b / 3) * 3;
1296 BOOL adjacent = FALSE;
1297 int k;
1298
1299 for (k = 0; k < 3; k++) {
1300 if (adjacency[base_b + k] == shared_index_a / 3) {
1301 adjacent = TRUE;
1302 break;
1303 }
1304 }
1305 if (!adjacent) {
1306 for (k = 1; k <= 2; k++) {
1307 DWORD vertex_index_a = base_a + (shared_index_a + k) % 3;
1308 DWORD vertex_index_b = base_b + (shared_index_b + (3 - k)) % 3;
1309 adjacent = indices[vertex_index_a] == indices[vertex_index_b];
1310 if (!adjacent && epsilon >= 0.0f) {
1311 D3DXVECTOR3 delta = {0.0f, 0.0f, 0.0f};
1312 FLOAT length_sq;
1313
1314 D3DXVec3Subtract(&delta,
1315 (D3DXVECTOR3*)(vertices + indices[vertex_index_a] * vertex_size),
1316 (D3DXVECTOR3*)(vertices + indices[vertex_index_b] * vertex_size));
1317 length_sq = D3DXVec3LengthSq(&delta);
1318 adjacent = epsilon == 0.0f ? length_sq == 0.0f : length_sq < epsilon_sq;
1319 }
1320 if (adjacent) {
1321 DWORD adj_a = base_a + 2 - (vertex_index_a + shared_index_a + 1) % 3;
1322 DWORD adj_b = base_b + 2 - (vertex_index_b + shared_index_b + 1) % 3;
1323 if (adjacency[adj_a] == -1 && adjacency[adj_b] == -1) {
1324 adjacency[adj_a] = base_b / 3;
1325 adjacency[adj_b] = base_a / 3;
1326 break;
1327 }
1328 }
1329 }
1330 }
1331
1332 shared_index_b = shared_indices[shared_index_b];
1333 }
1334 while (++j < This->numvertices) {
1335 D3DXVECTOR3 *vertex_b;
1336
1337 sorted_vertex_b++;
1338 if (sorted_vertex_b->key - sorted_vertex_a->key > epsilon * 3.0f) {
1339 /* no more coincident vertices to try */
1340 j = This->numvertices;
1341 break;
1342 }
1343 /* check for coincidence */
1344 vertex_b = (D3DXVECTOR3*)(vertices + sorted_vertex_b->vertex_index * vertex_size);
1345 if (fabsf(vertex_a->x - vertex_b->x) <= epsilon &&
1346 fabsf(vertex_a->y - vertex_b->y) <= epsilon &&
1347 fabsf(vertex_a->z - vertex_b->z) <= epsilon)
1348 {
1349 break;
1350 }
1351 }
1352 if (j >= This->numvertices)
1353 break;
1354 shared_index_b = sorted_vertex_b->first_shared_index;
1355 }
1356
1357 sorted_vertex_a->first_shared_index = shared_indices[sorted_vertex_a->first_shared_index];
1358 shared_index_a = sorted_vertex_a->first_shared_index;
1359 }
1360 }
1361
1362 hr = D3D_OK;
1363cleanup:
1364 if (indices) iface->lpVtbl->UnlockIndexBuffer(iface);
1365 if (vertices) iface->lpVtbl->UnlockVertexBuffer(iface);
1366 HeapFree(GetProcessHeap(), 0, shared_indices);
1367 return hr;
1368}
1369
1371{
1372 struct d3dx9_mesh *This = impl_from_ID3DXMesh(iface);
1373 HRESULT hr;
1375 int i;
1376
1377 TRACE("iface %p, declaration %p.\n", iface, declaration);
1378
1379 if (!declaration)
1380 {
1381 WARN("Invalid declaration. Can't use NULL declaration.\n");
1382 return D3DERR_INVALIDCALL;
1383 }
1384
1385 /* New declaration must be same size as original */
1387 if (vertex_declaration_size != This->vertex_declaration_size)
1388 {
1389 WARN("Invalid declaration. New vertex size does not match the original vertex size.\n");
1390 return D3DERR_INVALIDCALL;
1391 }
1392
1393 /* New declaration must not contain non-zero Stream value */
1394 for (i = 0; declaration[i].Stream != 0xff; i++)
1395 {
1396 if (declaration[i].Stream != 0)
1397 {
1398 WARN("Invalid declaration. New declaration contains non-zero Stream value.\n");
1399 return D3DERR_INVALIDCALL;
1400 }
1401 }
1402
1403 This->num_elem = i + 1;
1404 copy_declaration(This->cached_declaration, declaration, This->num_elem);
1405
1406 if (This->vertex_declaration)
1407 IDirect3DVertexDeclaration9_Release(This->vertex_declaration);
1408
1409 /* An application can pass an invalid declaration to UpdateSemantics and
1410 * still expect D3D_OK (see tests). If the declaration is invalid, then
1411 * subsequent calls to DrawSubset will fail. This is handled by setting the
1412 * vertex declaration to NULL.
1413 * GetDeclaration, GetNumBytesPerVertex must, however, use the new
1414 * invalid declaration. This is handled by them using the cached vertex
1415 * declaration instead of the actual vertex declaration.
1416 */
1419 &This->vertex_declaration);
1420 if (FAILED(hr))
1421 {
1422 WARN("Using invalid declaration. Calls to DrawSubset will fail.\n");
1423 This->vertex_declaration = NULL;
1424 }
1425
1426 return D3D_OK;
1427}
1428
1430{
1431 struct d3dx9_mesh *mesh = impl_from_ID3DXMesh(iface);
1432
1433 TRACE("iface %p, flags %#x, data %p.\n", iface, flags, data);
1434
1435 InterlockedIncrement(&mesh->attrib_buffer_lock_count);
1436
1437 if (!(flags & D3DLOCK_READONLY))
1438 {
1439 D3DXATTRIBUTERANGE *attrib_table = mesh->attrib_table;
1440 mesh->attrib_table_size = 0;
1441 mesh->attrib_table = NULL;
1443 }
1444
1445 *data = mesh->attrib_buffer;
1446
1447 return D3D_OK;
1448}
1449
1451{
1452 struct d3dx9_mesh *mesh = impl_from_ID3DXMesh(iface);
1453 int lock_count;
1454
1455 TRACE("iface %p.\n", iface);
1456
1457 lock_count = InterlockedDecrement(&mesh->attrib_buffer_lock_count);
1458 if (lock_count < 0)
1459 {
1460 InterlockedIncrement(&mesh->attrib_buffer_lock_count);
1461 return D3DERR_INVALIDCALL;
1462 }
1463
1464 return D3D_OK;
1465}
1466
1467static HRESULT WINAPI d3dx9_mesh_Optimize(ID3DXMesh *iface, DWORD flags, const DWORD *adjacency_in,
1468 DWORD *adjacency_out, DWORD *face_remap, ID3DXBuffer **vertex_remap, ID3DXMesh **opt_mesh)
1469{
1470 struct d3dx9_mesh *mesh = impl_from_ID3DXMesh(iface);
1471 HRESULT hr;
1473 ID3DXMesh *optimized_mesh;
1474
1475 TRACE("iface %p, flags %#x, adjacency_in %p, adjacency_out %p, face_remap %p, vertex_remap %p, opt_mesh %p.\n",
1476 iface, flags, adjacency_in, adjacency_out, face_remap, vertex_remap, opt_mesh);
1477
1478 if (!opt_mesh)
1479 return D3DERR_INVALIDCALL;
1480
1481 hr = iface->lpVtbl->GetDeclaration(iface, declaration);
1482 if (FAILED(hr)) return hr;
1483
1484 if (FAILED(hr = iface->lpVtbl->CloneMesh(iface, mesh->options, declaration, mesh->device, &optimized_mesh)))
1485 return hr;
1486
1487 hr = optimized_mesh->lpVtbl->OptimizeInplace(optimized_mesh, flags, adjacency_in, adjacency_out, face_remap, vertex_remap);
1488 if (SUCCEEDED(hr))
1489 *opt_mesh = optimized_mesh;
1490 else
1491 IUnknown_Release(optimized_mesh);
1492 return hr;
1493}
1494
1495/* Creates a vertex_remap that removes unused vertices.
1496 * Indices are updated according to the vertex_remap. */
1498 DWORD *new_num_vertices, ID3DXBuffer **vertex_remap)
1499{
1500 HRESULT hr;
1501 DWORD *vertex_remap_ptr;
1502 DWORD num_used_vertices;
1503 DWORD i;
1504
1505 hr = D3DXCreateBuffer(This->numvertices * sizeof(DWORD), vertex_remap);
1506 if (FAILED(hr)) return hr;
1507 vertex_remap_ptr = ID3DXBuffer_GetBufferPointer(*vertex_remap);
1508
1509 for (i = 0; i < This->numfaces * 3; i++)
1510 vertex_remap_ptr[indices[i]] = 1;
1511
1512 /* create old->new vertex mapping */
1513 num_used_vertices = 0;
1514 for (i = 0; i < This->numvertices; i++) {
1515 if (vertex_remap_ptr[i])
1516 vertex_remap_ptr[i] = num_used_vertices++;
1517 else
1518 vertex_remap_ptr[i] = -1;
1519 }
1520 /* convert indices */
1521 for (i = 0; i < This->numfaces * 3; i++)
1522 indices[i] = vertex_remap_ptr[indices[i]];
1523
1524 /* create new->old vertex mapping */
1525 num_used_vertices = 0;
1526 for (i = 0; i < This->numvertices; i++) {
1527 if (vertex_remap_ptr[i] != -1)
1528 vertex_remap_ptr[num_used_vertices++] = i;
1529 }
1530 for (i = num_used_vertices; i < This->numvertices; i++)
1531 vertex_remap_ptr[i] = -1;
1532
1533 *new_num_vertices = num_used_vertices;
1534
1535 return D3D_OK;
1536}
1537
1538/* count the number of unique attribute values in a sorted attribute buffer */
1540{
1541 DWORD last_attribute = attrib_buffer[0];
1543 DWORD i;
1544 for (i = 1; i < numfaces; i++) {
1545 if (attrib_buffer[i] != last_attribute) {
1546 last_attribute = attrib_buffer[i];
1548 }
1549 }
1550 return attrib_table_size;
1551}
1552
1554 BOOL is_32bit_indices, D3DXATTRIBUTERANGE *attrib_table)
1555{
1557 DWORD last_attribute = attrib_buffer[0];
1558 DWORD min_vertex, max_vertex;
1559 DWORD i;
1560
1561 attrib_table[0].AttribId = last_attribute;
1562 attrib_table[0].FaceStart = 0;
1563 min_vertex = (DWORD)-1;
1564 max_vertex = 0;
1565 for (i = 0; i < numfaces; i++) {
1566 DWORD j;
1567
1568 if (attrib_buffer[i] != last_attribute) {
1569 last_attribute = attrib_buffer[i];
1572 attrib_table[attrib_table_size].VertexCount = max_vertex - min_vertex + 1;
1576 min_vertex = (DWORD)-1;
1577 max_vertex = 0;
1578 }
1579 for (j = 0; j < 3; j++) {
1580 DWORD vertex_index = is_32bit_indices ? ((DWORD*)indices)[i * 3 + j] : ((WORD*)indices)[i * 3 + j];
1581 if (vertex_index < min_vertex)
1582 min_vertex = vertex_index;
1583 if (vertex_index > max_vertex)
1584 max_vertex = vertex_index;
1585 }
1586 }
1589 attrib_table[attrib_table_size].VertexCount = max_vertex - min_vertex + 1;
1591}
1592
1593static int __cdecl attrib_entry_compare(const void *a, const void *b)
1594{
1595 const DWORD *ptr_a = *(const DWORD **)a;
1596 const DWORD *ptr_b = *(const DWORD **)b;
1597 int delta = *ptr_a - *ptr_b;
1598
1599 if (delta)
1600 return delta;
1601
1602 delta = ptr_a - ptr_b; /* for stable sort */
1603 return delta;
1604}
1605
1606/* Create face_remap, a new attribute buffer for attribute sort optimization. */
1608 DWORD *attrib_buffer, DWORD **sorted_attrib_buffer, DWORD **face_remap)
1609{
1610 DWORD **sorted_attrib_ptr_buffer = NULL;
1611 DWORD i;
1612
1613 sorted_attrib_ptr_buffer = HeapAlloc(GetProcessHeap(), 0, This->numfaces * sizeof(*sorted_attrib_ptr_buffer));
1614 if (!sorted_attrib_ptr_buffer)
1615 return E_OUTOFMEMORY;
1616
1617 *face_remap = HeapAlloc(GetProcessHeap(), 0, This->numfaces * sizeof(**face_remap));
1618 if (!*face_remap)
1619 {
1620 HeapFree(GetProcessHeap(), 0, sorted_attrib_ptr_buffer);
1621 return E_OUTOFMEMORY;
1622 }
1623
1624 for (i = 0; i < This->numfaces; i++)
1625 sorted_attrib_ptr_buffer[i] = &attrib_buffer[i];
1626 qsort(sorted_attrib_ptr_buffer, This->numfaces, sizeof(*sorted_attrib_ptr_buffer), attrib_entry_compare);
1627
1628 for (i = 0; i < This->numfaces; i++)
1629 {
1630 DWORD old_face = sorted_attrib_ptr_buffer[i] - attrib_buffer;
1631 (*face_remap)[old_face] = i;
1632 }
1633
1634 /* overwrite sorted_attrib_ptr_buffer with the values themselves */
1635 *sorted_attrib_buffer = (DWORD*)sorted_attrib_ptr_buffer;
1636 for (i = 0; i < This->numfaces; i++)
1637 (*sorted_attrib_buffer)[(*face_remap)[i]] = attrib_buffer[i];
1638
1639 return D3D_OK;
1640}
1641
1642static HRESULT WINAPI d3dx9_mesh_OptimizeInplace(ID3DXMesh *iface, DWORD flags, const DWORD *adjacency_in,
1643 DWORD *adjacency_out, DWORD *face_remap_out, ID3DXBuffer **vertex_remap_out)
1644{
1645 struct d3dx9_mesh *This = impl_from_ID3DXMesh(iface);
1646 void *indices = NULL;
1648 HRESULT hr;
1649 ID3DXBuffer *vertex_remap = NULL;
1650 DWORD *face_remap = NULL; /* old -> new mapping */
1651 DWORD *dword_indices = NULL;
1652 DWORD new_num_vertices = 0;
1653 DWORD new_num_alloc_vertices = 0;
1654 IDirect3DVertexBuffer9 *vertex_buffer = NULL;
1655 DWORD *sorted_attrib_buffer = NULL;
1656 DWORD i;
1657
1658 TRACE("iface %p, flags %#x, adjacency_in %p, adjacency_out %p, face_remap_out %p, vertex_remap_out %p.\n",
1659 iface, flags, adjacency_in, adjacency_out, face_remap_out, vertex_remap_out);
1660
1661 if (!flags)
1662 return D3DERR_INVALIDCALL;
1663 if (!adjacency_in && (flags & (D3DXMESHOPT_VERTEXCACHE | D3DXMESHOPT_STRIPREORDER)))
1664 return D3DERR_INVALIDCALL;
1666 return D3DERR_INVALIDCALL;
1667
1669 {
1671 FIXME("D3DXMESHOPT_VERTEXCACHE not implemented.\n");
1673 FIXME("D3DXMESHOPT_STRIPREORDER not implemented.\n");
1674 return E_NOTIMPL;
1675 }
1676
1677 hr = iface->lpVtbl->LockIndexBuffer(iface, 0, &indices);
1678 if (FAILED(hr)) goto cleanup;
1679
1680 dword_indices = HeapAlloc(GetProcessHeap(), 0, This->numfaces * 3 * sizeof(DWORD));
1681 if (!dword_indices) return E_OUTOFMEMORY;
1682 if (This->options & D3DXMESH_32BIT) {
1683 memcpy(dword_indices, indices, This->numfaces * 3 * sizeof(DWORD));
1684 } else {
1685 WORD *word_indices = indices;
1686 for (i = 0; i < This->numfaces * 3; i++)
1687 dword_indices[i] = *word_indices++;
1688 }
1689
1691 {
1692 new_num_alloc_vertices = This->numvertices;
1693 hr = compact_mesh(This, dword_indices, &new_num_vertices, &vertex_remap);
1694 if (FAILED(hr)) goto cleanup;
1695 } else if (flags & D3DXMESHOPT_ATTRSORT) {
1697 FIXME("D3DXMESHOPT_ATTRSORT vertex reordering not implemented.\n");
1698
1699 hr = iface->lpVtbl->LockAttributeBuffer(iface, 0, &attrib_buffer);
1700 if (FAILED(hr)) goto cleanup;
1701
1702 hr = remap_faces_for_attrsort(This, dword_indices, attrib_buffer, &sorted_attrib_buffer, &face_remap);
1703 if (FAILED(hr)) goto cleanup;
1704 }
1705
1706 if (vertex_remap)
1707 {
1708 /* reorder the vertices using vertex_remap */
1709 D3DVERTEXBUFFER_DESC vertex_desc;
1710 DWORD *vertex_remap_ptr = ID3DXBuffer_GetBufferPointer(vertex_remap);
1711 DWORD vertex_size = iface->lpVtbl->GetNumBytesPerVertex(iface);
1712 BYTE *orig_vertices;
1713 BYTE *new_vertices;
1714
1715 hr = IDirect3DVertexBuffer9_GetDesc(This->vertex_buffer, &vertex_desc);
1716 if (FAILED(hr)) goto cleanup;
1717
1718 hr = IDirect3DDevice9_CreateVertexBuffer(This->device, new_num_alloc_vertices * vertex_size,
1719 vertex_desc.Usage, This->fvf, vertex_desc.Pool, &vertex_buffer, NULL);
1720 if (FAILED(hr)) goto cleanup;
1721
1722 hr = IDirect3DVertexBuffer9_Lock(This->vertex_buffer, 0, 0, (void**)&orig_vertices, D3DLOCK_READONLY);
1723 if (FAILED(hr)) goto cleanup;
1724
1725 hr = IDirect3DVertexBuffer9_Lock(vertex_buffer, 0, 0, (void**)&new_vertices, 0);
1726 if (FAILED(hr)) {
1727 IDirect3DVertexBuffer9_Unlock(This->vertex_buffer);
1728 goto cleanup;
1729 }
1730
1731 for (i = 0; i < new_num_vertices; i++)
1732 memcpy(new_vertices + i * vertex_size, orig_vertices + vertex_remap_ptr[i] * vertex_size, vertex_size);
1733
1734 IDirect3DVertexBuffer9_Unlock(This->vertex_buffer);
1736 } else if (vertex_remap_out) {
1737 DWORD *vertex_remap_ptr;
1738
1739 hr = D3DXCreateBuffer(This->numvertices * sizeof(DWORD), &vertex_remap);
1740 if (FAILED(hr)) goto cleanup;
1741 vertex_remap_ptr = ID3DXBuffer_GetBufferPointer(vertex_remap);
1742 for (i = 0; i < This->numvertices; i++)
1743 *vertex_remap_ptr++ = i;
1744 }
1745
1747 {
1750
1751 attrib_table_size = count_attributes(sorted_attrib_buffer, This->numfaces);
1753 if (!attrib_table) {
1754 hr = E_OUTOFMEMORY;
1755 goto cleanup;
1756 }
1757
1758 memcpy(attrib_buffer, sorted_attrib_buffer, This->numfaces * sizeof(*attrib_buffer));
1759
1760 /* reorder the indices using face_remap */
1761 if (This->options & D3DXMESH_32BIT) {
1762 for (i = 0; i < This->numfaces; i++)
1763 memcpy((DWORD*)indices + face_remap[i] * 3, dword_indices + i * 3, 3 * sizeof(DWORD));
1764 } else {
1765 WORD *word_indices = indices;
1766 for (i = 0; i < This->numfaces; i++) {
1767 DWORD new_pos = face_remap[i] * 3;
1768 DWORD old_pos = i * 3;
1769 word_indices[new_pos++] = dword_indices[old_pos++];
1770 word_indices[new_pos++] = dword_indices[old_pos++];
1771 word_indices[new_pos] = dword_indices[old_pos];
1772 }
1773 }
1774
1776 This->options & D3DXMESH_32BIT, attrib_table);
1777
1778 HeapFree(GetProcessHeap(), 0, This->attrib_table);
1779 This->attrib_table = attrib_table;
1780 This->attrib_table_size = attrib_table_size;
1781 } else {
1782 if (This->options & D3DXMESH_32BIT) {
1783 memcpy(indices, dword_indices, This->numfaces * 3 * sizeof(DWORD));
1784 } else {
1785 WORD *word_indices = indices;
1786 for (i = 0; i < This->numfaces * 3; i++)
1787 *word_indices++ = dword_indices[i];
1788 }
1789 }
1790
1791 if (adjacency_out) {
1792 if (face_remap) {
1793 for (i = 0; i < This->numfaces; i++) {
1794 DWORD old_pos = i * 3;
1795 DWORD new_pos = face_remap[i] * 3;
1796 adjacency_out[new_pos++] = face_remap[adjacency_in[old_pos++]];
1797 adjacency_out[new_pos++] = face_remap[adjacency_in[old_pos++]];
1798 adjacency_out[new_pos++] = face_remap[adjacency_in[old_pos++]];
1799 }
1800 } else {
1801 memcpy(adjacency_out, adjacency_in, This->numfaces * 3 * sizeof(*adjacency_out));
1802 }
1803 }
1804 if (face_remap_out) {
1805 if (face_remap) {
1806 for (i = 0; i < This->numfaces; i++)
1807 face_remap_out[face_remap[i]] = i;
1808 } else {
1809 for (i = 0; i < This->numfaces; i++)
1810 face_remap_out[i] = i;
1811 }
1812 }
1813 if (vertex_remap_out)
1814 *vertex_remap_out = vertex_remap;
1815 vertex_remap = NULL;
1816
1817 if (vertex_buffer) {
1818 IDirect3DVertexBuffer9_Release(This->vertex_buffer);
1819 This->vertex_buffer = vertex_buffer;
1821 This->numvertices = new_num_vertices;
1822 }
1823
1824 hr = D3D_OK;
1825cleanup:
1826 HeapFree(GetProcessHeap(), 0, sorted_attrib_buffer);
1827 HeapFree(GetProcessHeap(), 0, face_remap);
1828 HeapFree(GetProcessHeap(), 0, dword_indices);
1829 if (vertex_remap) ID3DXBuffer_Release(vertex_remap);
1831 if (attrib_buffer) iface->lpVtbl->UnlockAttributeBuffer(iface);
1832 if (indices) iface->lpVtbl->UnlockIndexBuffer(iface);
1833 return hr;
1834}
1835
1838{
1839 struct d3dx9_mesh *mesh = impl_from_ID3DXMesh(iface);
1840 D3DXATTRIBUTERANGE *new_table = NULL;
1841
1842 TRACE("iface %p, attrib_table %p, attrib_table_size %u.\n", iface, attrib_table, attrib_table_size);
1843
1844 if (attrib_table_size) {
1845 size_t size = attrib_table_size * sizeof(*attrib_table);
1846
1847 new_table = HeapAlloc(GetProcessHeap(), 0, size);
1848 if (!new_table)
1849 return E_OUTOFMEMORY;
1850
1851 CopyMemory(new_table, attrib_table, size);
1852 } else if (attrib_table) {
1853 return D3DERR_INVALIDCALL;
1854 }
1855 HeapFree(GetProcessHeap(), 0, mesh->attrib_table);
1856 mesh->attrib_table = new_table;
1857 mesh->attrib_table_size = attrib_table_size;
1858
1859 return D3D_OK;
1860}
1861
1862static const struct ID3DXMeshVtbl D3DXMesh_Vtbl =
1863{
1893};
1894
1895
1896/* Algorithm taken from the article: An Efficient and Robust Ray-Box Intersection Algorithm
1897Amy Williams University of Utah
1898Steve Barrus University of Utah
1899R. Keith Morley University of Utah
1900Peter Shirley University of Utah
1901
1902International Conference on Computer Graphics and Interactive Techniques archive
1903ACM SIGGRAPH 2005 Courses
1904Los Angeles, California
1905
1906This algorithm is free of patents or of copyrights, as confirmed by Peter Shirley himself.
1907
1908Algorithm: Consider the box as the intersection of three slabs. Clip the ray
1909against each slab, if there's anything left of the ray after we're
1910done we've got an intersection of the ray with the box. */
1912 const D3DXVECTOR3 *prayposition, const D3DXVECTOR3 *praydirection)
1913{
1914 FLOAT div, tmin, tmax, tymin, tymax, tzmin, tzmax;
1915
1916 div = 1.0f / praydirection->x;
1917 if ( div >= 0.0f )
1918 {
1919 tmin = ( pmin->x - prayposition->x ) * div;
1920 tmax = ( pmax->x - prayposition->x ) * div;
1921 }
1922 else
1923 {
1924 tmin = ( pmax->x - prayposition->x ) * div;
1925 tmax = ( pmin->x - prayposition->x ) * div;
1926 }
1927
1928 if ( tmax < 0.0f ) return FALSE;
1929
1930 div = 1.0f / praydirection->y;
1931 if ( div >= 0.0f )
1932 {
1933 tymin = ( pmin->y - prayposition->y ) * div;
1934 tymax = ( pmax->y - prayposition->y ) * div;
1935 }
1936 else
1937 {
1938 tymin = ( pmax->y - prayposition->y ) * div;
1939 tymax = ( pmin->y - prayposition->y ) * div;
1940 }
1941
1942 if ( ( tymax < 0.0f ) || ( tmin > tymax ) || ( tymin > tmax ) ) return FALSE;
1943
1944 if ( tymin > tmin ) tmin = tymin;
1945 if ( tymax < tmax ) tmax = tymax;
1946
1947 div = 1.0f / praydirection->z;
1948 if ( div >= 0.0f )
1949 {
1950 tzmin = ( pmin->z - prayposition->z ) * div;
1951 tzmax = ( pmax->z - prayposition->z ) * div;
1952 }
1953 else
1954 {
1955 tzmin = ( pmax->z - prayposition->z ) * div;
1956 tzmax = ( pmin->z - prayposition->z ) * div;
1957 }
1958
1959 if ( (tzmax < 0.0f ) || ( tmin > tzmax ) || ( tzmin > tmax ) ) return FALSE;
1960
1961 return TRUE;
1962}
1963
1965 DWORD numvertices, DWORD dwstride, D3DXVECTOR3 *pmin, D3DXVECTOR3 *pmax)
1966{
1968 unsigned int i;
1969
1970 if( !pfirstposition || !pmin || !pmax ) return D3DERR_INVALIDCALL;
1971
1972 *pmin = *pfirstposition;
1973 *pmax = *pmin;
1974
1975 for(i=0; i<numvertices; i++)
1976 {
1977 vec = *( (const D3DXVECTOR3*)((const char*)pfirstposition + dwstride * i) );
1978
1979 if ( vec.x < pmin->x ) pmin->x = vec.x;
1980 if ( vec.x > pmax->x ) pmax->x = vec.x;
1981
1982 if ( vec.y < pmin->y ) pmin->y = vec.y;
1983 if ( vec.y > pmax->y ) pmax->y = vec.y;
1984
1985 if ( vec.z < pmin->z ) pmin->z = vec.z;
1986 if ( vec.z > pmax->z ) pmax->z = vec.z;
1987 }
1988
1989 return D3D_OK;
1990}
1991
1993 DWORD numvertices, DWORD dwstride, D3DXVECTOR3 *pcenter, float *pradius)
1994{
1996 FLOAT d;
1997 unsigned int i;
1998
1999 if( !pfirstposition || !pcenter || !pradius ) return D3DERR_INVALIDCALL;
2000
2001 temp.x = 0.0f;
2002 temp.y = 0.0f;
2003 temp.z = 0.0f;
2004 *pradius = 0.0f;
2005
2006 for(i=0; i<numvertices; i++)
2007 D3DXVec3Add(&temp, &temp, (const D3DXVECTOR3*)((const char*)pfirstposition + dwstride * i));
2008
2009 D3DXVec3Scale(pcenter, &temp, 1.0f / numvertices);
2010
2011 for(i=0; i<numvertices; i++)
2012 {
2013 d = D3DXVec3Length(D3DXVec3Subtract(&temp, (const D3DXVECTOR3*)((const char*)pfirstposition + dwstride * i), pcenter));
2014 if ( d > *pradius ) *pradius = d;
2015 }
2016 return D3D_OK;
2017}
2018
2021{
2022 declaration[*idx].Stream = 0;
2023 declaration[*idx].Offset = *offset;
2024 declaration[*idx].Type = type;
2026 declaration[*idx].Usage = usage;
2027 declaration[*idx].UsageIndex = usage_idx;
2028
2030 ++(*idx);
2031}
2032
2033/*************************************************************************
2034 * D3DXDeclaratorFromFVF
2035 */
2037{
2038 static const D3DVERTEXELEMENT9 end_element = D3DDECL_END();
2039 DWORD tex_count = (fvf & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
2040 unsigned int offset = 0;
2041 unsigned int idx = 0;
2042 unsigned int i;
2043
2044 TRACE("fvf %#x, declaration %p.\n", fvf, declaration);
2045
2047
2048 if (fvf & D3DFVF_POSITION_MASK)
2049 {
2050 BOOL has_blend = (fvf & D3DFVF_XYZB5) >= D3DFVF_XYZB1;
2051 DWORD blend_count = 1 + (((fvf & D3DFVF_XYZB5) - D3DFVF_XYZB1) >> 1);
2052 BOOL has_blend_idx = (fvf & D3DFVF_LASTBETA_D3DCOLOR) || (fvf & D3DFVF_LASTBETA_UBYTE4);
2053
2054 if (has_blend_idx) --blend_count;
2055
2056 if ((fvf & D3DFVF_POSITION_MASK) == D3DFVF_XYZW
2057 || (has_blend && blend_count > 4))
2058 return D3DERR_INVALIDCALL;
2059
2060 if ((fvf & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW)
2062 else
2064
2065 if (has_blend)
2066 {
2067 switch (blend_count)
2068 {
2069 case 0:
2070 break;
2071 case 1:
2073 break;
2074 case 2:
2076 break;
2077 case 3:
2079 break;
2080 case 4:
2082 break;
2083 default:
2084 ERR("Invalid blend count %u.\n", blend_count);
2085 break;
2086 }
2087
2088 if (has_blend_idx)
2089 {
2090 if (fvf & D3DFVF_LASTBETA_UBYTE4)
2092 else if (fvf & D3DFVF_LASTBETA_D3DCOLOR)
2094 }
2095 }
2096 }
2097
2098 if (fvf & D3DFVF_NORMAL)
2100 if (fvf & D3DFVF_PSIZE)
2102 if (fvf & D3DFVF_DIFFUSE)
2104 if (fvf & D3DFVF_SPECULAR)
2106
2107 for (i = 0; i < tex_count; ++i)
2108 {
2109 switch ((fvf >> (16 + 2 * i)) & 0x03)
2110 {
2113 break;
2116 break;
2119 break;
2122 break;
2123 }
2124 }
2125
2126 declaration[idx] = end_element;
2127
2128 return D3D_OK;
2129}
2130
2131/*************************************************************************
2132 * D3DXFVFFromDeclarator
2133 */
2135{
2136 unsigned int i = 0, texture, offset;
2137
2138 TRACE("(%p, %p)\n", declaration, fvf);
2139
2140 *fvf = 0;
2142 {
2144 declaration[1].UsageIndex == 0) &&
2146 declaration[2].UsageIndex == 0))
2147 {
2148 return D3DERR_INVALIDCALL;
2149 }
2151 declaration[1].Usage == D3DDECLUSAGE_BLENDINDICES && declaration[1].UsageIndex == 0)
2152 {
2154 {
2156 }
2157 else
2158 {
2160 }
2161 i = 2;
2162 }
2164 declaration[1].UsageIndex == 0)
2165 {
2167 declaration[2].Usage == D3DDECLUSAGE_BLENDINDICES && declaration[2].UsageIndex == 0)
2168 {
2170 {
2171 *fvf |= D3DFVF_LASTBETA_UBYTE4;
2172 }
2173 else
2174 {
2176 }
2177 switch (declaration[1].Type)
2178 {
2179 case D3DDECLTYPE_FLOAT1: *fvf |= D3DFVF_XYZB2; break;
2180 case D3DDECLTYPE_FLOAT2: *fvf |= D3DFVF_XYZB3; break;
2181 case D3DDECLTYPE_FLOAT3: *fvf |= D3DFVF_XYZB4; break;
2182 case D3DDECLTYPE_FLOAT4: *fvf |= D3DFVF_XYZB5; break;
2183 }
2184 i = 3;
2185 }
2186 else
2187 {
2188 switch (declaration[1].Type)
2189 {
2190 case D3DDECLTYPE_FLOAT1: *fvf |= D3DFVF_XYZB1; break;
2191 case D3DDECLTYPE_FLOAT2: *fvf |= D3DFVF_XYZB2; break;
2192 case D3DDECLTYPE_FLOAT3: *fvf |= D3DFVF_XYZB3; break;
2193 case D3DDECLTYPE_FLOAT4: *fvf |= D3DFVF_XYZB4; break;
2194 }
2195 i = 2;
2196 }
2197 }
2198 else
2199 {
2200 *fvf |= D3DFVF_XYZ;
2201 i = 1;
2202 }
2203 }
2205 declaration[0].UsageIndex == 0)
2206 {
2207 *fvf |= D3DFVF_XYZRHW;
2208 i = 1;
2209 }
2210
2212 {
2213 *fvf |= D3DFVF_NORMAL;
2214 i++;
2215 }
2217 declaration[i].UsageIndex == 0)
2218 {
2219 *fvf |= D3DFVF_PSIZE;
2220 i++;
2221 }
2223 declaration[i].UsageIndex == 0)
2224 {
2225 *fvf |= D3DFVF_DIFFUSE;
2226 i++;
2227 }
2229 declaration[i].UsageIndex == 1)
2230 {
2231 *fvf |= D3DFVF_SPECULAR;
2232 i++;
2233 }
2234
2235 for (texture = 0; texture < D3DDP_MAXTEXCOORD; i++, texture++)
2236 {
2237 if (declaration[i].Stream == 0xFF)
2238 {
2239 break;
2240 }
2242 declaration[i].UsageIndex == texture)
2243 {
2244 *fvf |= D3DFVF_TEXCOORDSIZE1(declaration[i].UsageIndex);
2245 }
2247 declaration[i].UsageIndex == texture)
2248 {
2249 *fvf |= D3DFVF_TEXCOORDSIZE2(declaration[i].UsageIndex);
2250 }
2252 declaration[i].UsageIndex == texture)
2253 {
2254 *fvf |= D3DFVF_TEXCOORDSIZE3(declaration[i].UsageIndex);
2255 }
2257 declaration[i].UsageIndex == texture)
2258 {
2259 *fvf |= D3DFVF_TEXCOORDSIZE4(declaration[i].UsageIndex);
2260 }
2261 else
2262 {
2263 return D3DERR_INVALIDCALL;
2264 }
2265 }
2266
2267 *fvf |= (texture << D3DFVF_TEXCOUNT_SHIFT);
2268
2269 for (offset = 0, i = 0; declaration[i].Stream != 0xFF;
2271 {
2272 if (declaration[i].Offset != offset)
2273 {
2274 return D3DERR_INVALIDCALL;
2275 }
2276 }
2277
2278 return D3D_OK;
2279}
2280
2281/*************************************************************************
2282 * D3DXGetFVFVertexSize
2283 */
2284static UINT Get_TexCoord_Size_From_FVF(DWORD FVF, int tex_num)
2285{
2286 return (((((FVF) >> (16 + (2 * (tex_num)))) + 1) & 0x03) + 1);
2287}
2288
2290{
2291 DWORD size = 0;
2292 UINT i;
2293 UINT numTextures = (FVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
2294
2295 if (FVF & D3DFVF_NORMAL) size += sizeof(D3DXVECTOR3);
2296 if (FVF & D3DFVF_DIFFUSE) size += sizeof(DWORD);
2297 if (FVF & D3DFVF_SPECULAR) size += sizeof(DWORD);
2298 if (FVF & D3DFVF_PSIZE) size += sizeof(DWORD);
2299
2300 switch (FVF & D3DFVF_POSITION_MASK)
2301 {
2302 case D3DFVF_XYZ: size += sizeof(D3DXVECTOR3); break;
2303 case D3DFVF_XYZRHW: size += 4 * sizeof(FLOAT); break;
2304 case D3DFVF_XYZB1: size += 4 * sizeof(FLOAT); break;
2305 case D3DFVF_XYZB2: size += 5 * sizeof(FLOAT); break;
2306 case D3DFVF_XYZB3: size += 6 * sizeof(FLOAT); break;
2307 case D3DFVF_XYZB4: size += 7 * sizeof(FLOAT); break;
2308 case D3DFVF_XYZB5: size += 8 * sizeof(FLOAT); break;
2309 case D3DFVF_XYZW: size += 4 * sizeof(FLOAT); break;
2310 }
2311
2312 for (i = 0; i < numTextures; i++)
2313 {
2314 size += Get_TexCoord_Size_From_FVF(FVF, i) * sizeof(FLOAT);
2315 }
2316
2317 return size;
2318}
2319
2320/*************************************************************************
2321 * D3DXGetDeclVertexSize
2322 */
2324{
2326 UINT size = 0;
2327
2328 TRACE("decl %p, stream_idx %u\n", decl, stream_idx);
2329
2330 if (!decl) return 0;
2331
2332 for (element = decl; element->Stream != 0xff; ++element)
2333 {
2334 UINT type_size;
2335
2336 if (element->Stream != stream_idx) continue;
2337
2339 {
2340 FIXME("Unhandled element type %#x, size will be incorrect.\n", element->Type);
2341 continue;
2342 }
2343
2344 type_size = d3dx_decltype_size[element->Type];
2345 if (element->Offset + type_size > size) size = element->Offset + type_size;
2346 }
2347
2348 return size;
2349}
2350
2351/*************************************************************************
2352 * D3DXGetDeclLength
2353 */
2355{
2357
2358 TRACE("decl %p\n", decl);
2359
2360 /* null decl results in exception on Windows XP */
2361
2362 for (element = decl; element->Stream != 0xff; ++element);
2363
2364 return element - decl;
2365}
2366
2368 const D3DXVECTOR3 *praypos, const D3DXVECTOR3 *praydir, float *pu, float *pv, float *pdist)
2369{
2370 D3DXMATRIX m;
2372
2373 TRACE("p0 %p, p1 %p, p2 %p, praypos %p, praydir %p, pu %p, pv %p, pdist %p.\n",
2374 p0, p1, p2, praypos, praydir, pu, pv, pdist);
2375
2376 m.u.m[0][0] = p1->x - p0->x;
2377 m.u.m[1][0] = p2->x - p0->x;
2378 m.u.m[2][0] = -praydir->x;
2379 m.u.m[3][0] = 0.0f;
2380 m.u.m[0][1] = p1->y - p0->y;
2381 m.u.m[1][1] = p2->y - p0->y;
2382 m.u.m[2][1] = -praydir->y;
2383 m.u.m[3][1] = 0.0f;
2384 m.u.m[0][2] = p1->z - p0->z;
2385 m.u.m[1][2] = p2->z - p0->z;
2386 m.u.m[2][2] = -praydir->z;
2387 m.u.m[3][2] = 0.0f;
2388 m.u.m[0][3] = 0.0f;
2389 m.u.m[1][3] = 0.0f;
2390 m.u.m[2][3] = 0.0f;
2391 m.u.m[3][3] = 1.0f;
2392
2393 vec.x = praypos->x - p0->x;
2394 vec.y = praypos->y - p0->y;
2395 vec.z = praypos->z - p0->z;
2396 vec.w = 0.0f;
2397
2398 if ( D3DXMatrixInverse(&m, NULL, &m) )
2399 {
2400 D3DXVec4Transform(&vec, &vec, &m);
2401 if ( (vec.x >= 0.0f) && (vec.y >= 0.0f) && (vec.x + vec.y <= 1.0f) && (vec.z >= 0.0f) )
2402 {
2403 if (pu) *pu = vec.x;
2404 if (pv) *pv = vec.y;
2405 if (pdist) *pdist = fabsf( vec.z );
2406 return TRUE;
2407 }
2408 }
2409
2410 return FALSE;
2411}
2412
2413BOOL WINAPI D3DXSphereBoundProbe(const D3DXVECTOR3 *center, float radius,
2414 const D3DXVECTOR3 *ray_position, const D3DXVECTOR3 *ray_direction)
2415{
2416 D3DXVECTOR3 difference = {0};
2417 float a, b, c, d;
2418
2419 D3DXVec3Subtract(&difference, ray_position, center);
2420 c = D3DXVec3LengthSq(&difference) - radius * radius;
2421 if (c < 0.0f)
2422 return TRUE;
2423 a = D3DXVec3LengthSq(ray_direction);
2424 b = D3DXVec3Dot(&difference, ray_direction);
2425 d = b * b - a * c;
2426
2427 return d >= 0.0f && (b <= 0.0f || d > b * b);
2428}
2429
2430/*************************************************************************
2431 * D3DXCreateMesh
2432 */
2434 const D3DVERTEXELEMENT9 *declaration, struct IDirect3DDevice9 *device, struct ID3DXMesh **mesh)
2435{
2436 HRESULT hr;
2437 DWORD fvf;
2438 IDirect3DVertexDeclaration9 *vertex_declaration;
2439 UINT vertex_declaration_size;
2440 UINT num_elem;
2441 IDirect3DVertexBuffer9 *vertex_buffer;
2442 IDirect3DIndexBuffer9 *index_buffer;
2443 DWORD *attrib_buffer;
2444 struct d3dx9_mesh *object;
2445 DWORD index_usage = 0;
2446 D3DPOOL index_pool = D3DPOOL_DEFAULT;
2447 D3DFORMAT index_format = D3DFMT_INDEX16;
2448 DWORD vertex_usage = 0;
2449 D3DPOOL vertex_pool = D3DPOOL_DEFAULT;
2450 int i;
2451
2452 TRACE("numfaces %u, numvertices %u, options %#x, declaration %p, device %p, mesh %p.\n",
2454
2455 if (numfaces == 0 || numvertices == 0 || declaration == NULL || device == NULL || mesh == NULL ||
2456 /* D3DXMESH_VB_SHARE is for cloning, and D3DXMESH_USEHWONLY is for ConvertToBlendedMesh */
2457 (options & (D3DXMESH_VB_SHARE | D3DXMESH_USEHWONLY | 0xfffe0000)))
2458 {
2459 return D3DERR_INVALIDCALL;
2460 }
2461 for (i = 0; declaration[i].Stream != 0xff; i++)
2462 if (declaration[i].Stream != 0)
2463 return D3DERR_INVALIDCALL;
2464 num_elem = i + 1;
2465
2466 if (options & D3DXMESH_32BIT)
2467 index_format = D3DFMT_INDEX32;
2468
2470 index_usage |= D3DUSAGE_DONOTCLIP;
2471 vertex_usage |= D3DUSAGE_DONOTCLIP;
2472 }
2473 if (options & D3DXMESH_POINTS) {
2474 index_usage |= D3DUSAGE_POINTS;
2475 vertex_usage |= D3DUSAGE_POINTS;
2476 }
2478 index_usage |= D3DUSAGE_RTPATCHES;
2479 vertex_usage |= D3DUSAGE_RTPATCHES;
2480 }
2481 if (options & D3DXMESH_NPATCHES) {
2482 index_usage |= D3DUSAGE_NPATCHES;
2483 vertex_usage |= D3DUSAGE_NPATCHES;
2484 }
2485
2487 vertex_pool = D3DPOOL_SYSTEMMEM;
2488 else if (options & D3DXMESH_VB_MANAGED)
2489 vertex_pool = D3DPOOL_MANAGED;
2490
2492 vertex_usage |= D3DUSAGE_WRITEONLY;
2494 vertex_usage |= D3DUSAGE_DYNAMIC;
2496 vertex_usage |= D3DUSAGE_SOFTWAREPROCESSING;
2497
2499 index_pool = D3DPOOL_SYSTEMMEM;
2500 else if (options & D3DXMESH_IB_MANAGED)
2501 index_pool = D3DPOOL_MANAGED;
2502
2504 index_usage |= D3DUSAGE_WRITEONLY;
2506 index_usage |= D3DUSAGE_DYNAMIC;
2508 index_usage |= D3DUSAGE_SOFTWAREPROCESSING;
2509
2511 if (hr != D3D_OK)
2512 {
2513 fvf = 0;
2514 }
2515
2516 /* Create vertex declaration */
2520 if (FAILED(hr))
2521 {
2522 WARN("Unexpected return value %x from IDirect3DDevice9_CreateVertexDeclaration.\n",hr);
2523 return hr;
2524 }
2526
2527 /* Create vertex buffer */
2530 vertex_usage,
2531 fvf,
2532 vertex_pool,
2534 NULL);
2535 if (FAILED(hr))
2536 {
2537 WARN("Unexpected return value %x from IDirect3DDevice9_CreateVertexBuffer.\n",hr);
2539 return hr;
2540 }
2541
2542 /* Create index buffer */
2544 numfaces * 3 * ((index_format == D3DFMT_INDEX16) ? 2 : 4),
2545 index_usage,
2546 index_format,
2547 index_pool,
2548 &index_buffer,
2549 NULL);
2550 if (FAILED(hr))
2551 {
2552 WARN("Unexpected return value %x from IDirect3DDevice9_CreateVertexBuffer.\n",hr);
2555 return hr;
2556 }
2557
2559 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
2560 if (object == NULL || attrib_buffer == NULL)
2561 {
2562 HeapFree(GetProcessHeap(), 0, object);
2567 *mesh = NULL;
2568 return E_OUTOFMEMORY;
2569 }
2570 object->ID3DXMesh_iface.lpVtbl = &D3DXMesh_Vtbl;
2571 object->ref = 1;
2572
2573 object->numfaces = numfaces;
2574 object->numvertices = numvertices;
2575 object->options = options;
2576 object->fvf = fvf;
2577 object->device = device;
2579
2580 copy_declaration(object->cached_declaration, declaration, num_elem);
2581 object->vertex_declaration = vertex_declaration;
2582 object->vertex_declaration_size = vertex_declaration_size;
2583 object->num_elem = num_elem;
2584 object->vertex_buffer = vertex_buffer;
2585 object->index_buffer = index_buffer;
2586 object->attrib_buffer = attrib_buffer;
2587
2588 *mesh = &object->ID3DXMesh_iface;
2589
2590 return D3D_OK;
2591}
2592
2593/*************************************************************************
2594 * D3DXCreateMeshFVF
2595 */
2597 DWORD fvf, struct IDirect3DDevice9 *device, struct ID3DXMesh **mesh)
2598{
2599 HRESULT hr;
2601
2602 TRACE("(%u, %u, %u, %u, %p, %p)\n", numfaces, numvertices, options, fvf, device, mesh);
2603
2605 if (FAILED(hr)) return hr;
2606
2608}
2609
2610
2618
2620
2621 /* optional mesh data */
2622
2626
2628
2630
2634
2635 struct ID3DXSkinInfo *skin_info;
2637};
2638
2639static HRESULT parse_texture_filename(ID3DXFileData *filedata, char **filename_out)
2640{
2641 HRESULT hr;
2642 SIZE_T data_size;
2643 BYTE *data;
2644 char *filename_in;
2645 char *filename = NULL;
2646
2647 /* template TextureFilename {
2648 * STRING filename;
2649 * }
2650 */
2651
2652 HeapFree(GetProcessHeap(), 0, *filename_out);
2653 *filename_out = NULL;
2654
2655 hr = filedata->lpVtbl->Lock(filedata, &data_size, (const void**)&data);
2656 if (FAILED(hr)) return hr;
2657
2658 /* FIXME: String must be retrieved directly instead of through a pointer once ID3DXFILE is fixed */
2659 if (data_size < sizeof(filename_in))
2660 {
2661 WARN("truncated data (%lu bytes)\n", data_size);
2662 filedata->lpVtbl->Unlock(filedata);
2663 return E_FAIL;
2664 }
2665 filename_in = *(char **)data;
2666
2667 filename = HeapAlloc(GetProcessHeap(), 0, strlen(filename_in) + 1);
2668 if (!filename) {
2669 filedata->lpVtbl->Unlock(filedata);
2670 return E_OUTOFMEMORY;
2671 }
2672
2673 strcpy(filename, filename_in);
2674 *filename_out = filename;
2675
2676 filedata->lpVtbl->Unlock(filedata);
2677
2678 return D3D_OK;
2679}
2680
2681static HRESULT parse_material(ID3DXFileData *filedata, D3DXMATERIAL *material)
2682{
2683 HRESULT hr;
2684 SIZE_T data_size;
2685 const BYTE *data;
2686 GUID type;
2687 ID3DXFileData *child;
2688 SIZE_T i, nb_children;
2689
2690 material->pTextureFilename = NULL;
2691
2692 hr = filedata->lpVtbl->Lock(filedata, &data_size, (const void**)&data);
2693 if (FAILED(hr)) return hr;
2694
2695 /*
2696 * template ColorRGBA {
2697 * FLOAT red;
2698 * FLOAT green;
2699 * FLOAT blue;
2700 * FLOAT alpha;
2701 * }
2702 * template ColorRGB {
2703 * FLOAT red;
2704 * FLOAT green;
2705 * FLOAT blue;
2706 * }
2707 * template Material {
2708 * ColorRGBA faceColor;
2709 * FLOAT power;
2710 * ColorRGB specularColor;
2711 * ColorRGB emissiveColor;
2712 * [ ... ]
2713 * }
2714 */
2715 if (data_size != sizeof(FLOAT) * 11) {
2716 WARN("incorrect data size (%ld bytes)\n", data_size);
2717 filedata->lpVtbl->Unlock(filedata);
2718 return E_FAIL;
2719 }
2720
2721 memcpy(&material->MatD3D.Diffuse, data, sizeof(D3DCOLORVALUE));
2722 data += sizeof(D3DCOLORVALUE);
2723 material->MatD3D.Power = *(FLOAT*)data;
2724 data += sizeof(FLOAT);
2725 memcpy(&material->MatD3D.Specular, data, sizeof(FLOAT) * 3);
2726 material->MatD3D.Specular.a = 1.0f;
2727 data += 3 * sizeof(FLOAT);
2728 memcpy(&material->MatD3D.Emissive, data, sizeof(FLOAT) * 3);
2729 material->MatD3D.Emissive.a = 1.0f;
2730 material->MatD3D.Ambient.r = 0.0f;
2731 material->MatD3D.Ambient.g = 0.0f;
2732 material->MatD3D.Ambient.b = 0.0f;
2733 material->MatD3D.Ambient.a = 1.0f;
2734
2735 filedata->lpVtbl->Unlock(filedata);
2736
2737 hr = filedata->lpVtbl->GetChildren(filedata, &nb_children);
2738 if (FAILED(hr))
2739 return hr;
2740
2741 for (i = 0; i < nb_children; i++)
2742 {
2743 hr = filedata->lpVtbl->GetChild(filedata, i, &child);
2744 if (FAILED(hr))
2745 return hr;
2746 hr = child->lpVtbl->GetType(child, &type);
2747 if (FAILED(hr))
2748 goto err;
2749
2750 if (IsEqualGUID(&type, &TID_D3DRMTextureFilename)) {
2752 if (FAILED(hr))
2753 goto err;
2754 }
2755 IUnknown_Release(child);
2756 }
2757 return D3D_OK;
2758
2759err:
2760 IUnknown_Release(child);
2761 return hr;
2762}
2763
2765{
2766 DWORD i;
2767 for (i = 0; i < mesh->num_materials; i++)
2768 HeapFree(GetProcessHeap(), 0, mesh->materials[i].pTextureFilename);
2769 HeapFree(GetProcessHeap(), 0, mesh->materials);
2770 HeapFree(GetProcessHeap(), 0, mesh->material_indices);
2771 mesh->num_materials = 0;
2772 mesh->materials = NULL;
2773 mesh->material_indices = NULL;
2774}
2775
2776static HRESULT parse_material_list(ID3DXFileData *filedata, struct mesh_data *mesh)
2777{
2778 HRESULT hr;
2779 SIZE_T data_size;
2780 const DWORD *data, *in_ptr;
2781 GUID type;
2782 ID3DXFileData *child = NULL;
2783 DWORD num_materials;
2784 DWORD i;
2785 SIZE_T nb_children;
2786
2788
2789 hr = filedata->lpVtbl->Lock(filedata, &data_size, (const void**)&data);
2790 if (FAILED(hr)) return hr;
2791
2792 /* template MeshMaterialList {
2793 * DWORD nMaterials;
2794 * DWORD nFaceIndexes;
2795 * array DWORD faceIndexes[nFaceIndexes];
2796 * [ Material ]
2797 * }
2798 */
2799
2800 in_ptr = data;
2801 hr = E_FAIL;
2802
2803 if (data_size < sizeof(DWORD)) {
2804 WARN("truncated data (%ld bytes)\n", data_size);
2805 goto end;
2806 }
2807 num_materials = *in_ptr++;
2808 if (!num_materials) {
2809 hr = D3D_OK;
2810 goto end;
2811 }
2812
2813 if (data_size < 2 * sizeof(DWORD)) {
2814 WARN("truncated data (%ld bytes)\n", data_size);
2815 goto end;
2816 }
2817 if (*in_ptr++ != mesh->num_poly_faces) {
2818 WARN("number of material face indices (%u) doesn't match number of faces (%u)\n",
2819 *(in_ptr - 1), mesh->num_poly_faces);
2820 goto end;
2821 }
2822 if (data_size < 2 * sizeof(DWORD) + mesh->num_poly_faces * sizeof(DWORD)) {
2823 WARN("truncated data (%ld bytes)\n", data_size);
2824 goto end;
2825 }
2826 for (i = 0; i < mesh->num_poly_faces; i++) {
2827 if (*in_ptr++ >= num_materials) {
2828 WARN("face %u: reference to undefined material %u (only %u materials)\n",
2829 i, *(in_ptr - 1), num_materials);
2830 goto end;
2831 }
2832 }
2833
2834 mesh->materials = HeapAlloc(GetProcessHeap(), 0, num_materials * sizeof(*mesh->materials));
2835 mesh->material_indices = HeapAlloc(GetProcessHeap(), 0, mesh->num_poly_faces * sizeof(*mesh->material_indices));
2836 if (!mesh->materials || !mesh->material_indices) {
2837 hr = E_OUTOFMEMORY;
2838 goto end;
2839 }
2840 memcpy(mesh->material_indices, data + 2, mesh->num_poly_faces * sizeof(DWORD));
2841
2842 hr = filedata->lpVtbl->GetChildren(filedata, &nb_children);
2843 if (FAILED(hr))
2844 goto end;
2845
2846 for (i = 0; i < nb_children; i++)
2847 {
2848 hr = filedata->lpVtbl->GetChild(filedata, i, &child);
2849 if (FAILED(hr))
2850 goto end;
2851 hr = child->lpVtbl->GetType(child, &type);
2852 if (FAILED(hr))
2853 goto end;
2854
2855 if (IsEqualGUID(&type, &TID_D3DRMMaterial)) {
2856 if (mesh->num_materials >= num_materials) {
2857 WARN("more materials defined than declared\n");
2858 hr = E_FAIL;
2859 goto end;
2860 }
2861 hr = parse_material(child, &mesh->materials[mesh->num_materials++]);
2862 if (FAILED(hr))
2863 goto end;
2864 }
2865
2866 IUnknown_Release(child);
2867 child = NULL;
2868 }
2869 if (num_materials != mesh->num_materials) {
2870 WARN("only %u of %u materials defined\n", num_materials, mesh->num_materials);
2871 hr = E_FAIL;
2872 }
2873
2874end:
2875 if (child)
2876 IUnknown_Release(child);
2877 filedata->lpVtbl->Unlock(filedata);
2878 return hr;
2879}
2880
2881static HRESULT parse_texture_coords(ID3DXFileData *filedata, struct mesh_data *mesh)
2882{
2883 HRESULT hr;
2884 SIZE_T data_size;
2885 const BYTE *data;
2886
2887 HeapFree(GetProcessHeap(), 0, mesh->tex_coords);
2888 mesh->tex_coords = NULL;
2889
2890 hr = filedata->lpVtbl->Lock(filedata, &data_size, (const void**)&data);
2891 if (FAILED(hr)) return hr;
2892
2893 /* template Coords2d {
2894 * FLOAT u;
2895 * FLOAT v;
2896 * }
2897 * template MeshTextureCoords {
2898 * DWORD nTextureCoords;
2899 * array Coords2d textureCoords[nTextureCoords];
2900 * }
2901 */
2902
2903 hr = E_FAIL;
2904
2905 if (data_size < sizeof(DWORD)) {
2906 WARN("truncated data (%ld bytes)\n", data_size);
2907 goto end;
2908 }
2909 if (*(DWORD*)data != mesh->num_vertices) {
2910 WARN("number of texture coordinates (%u) doesn't match number of vertices (%u)\n",
2911 *(DWORD*)data, mesh->num_vertices);
2912 goto end;
2913 }
2914 data += sizeof(DWORD);
2915 if (data_size < sizeof(DWORD) + mesh->num_vertices * sizeof(*mesh->tex_coords)) {
2916 WARN("truncated data (%ld bytes)\n", data_size);
2917 goto end;
2918 }
2919
2920 mesh->tex_coords = HeapAlloc(GetProcessHeap(), 0, mesh->num_vertices * sizeof(*mesh->tex_coords));
2921 if (!mesh->tex_coords) {
2922 hr = E_OUTOFMEMORY;
2923 goto end;
2924 }
2925 memcpy(mesh->tex_coords, data, mesh->num_vertices * sizeof(*mesh->tex_coords));
2926
2927 mesh->fvf |= D3DFVF_TEX1;
2928
2929 hr = D3D_OK;
2930
2931end:
2932 filedata->lpVtbl->Unlock(filedata);
2933 return hr;
2934}
2935
2936static HRESULT parse_vertex_colors(ID3DXFileData *filedata, struct mesh_data *mesh)
2937{
2938 HRESULT hr;
2939 SIZE_T data_size;
2940 const BYTE *data;
2941 DWORD num_colors;
2942 DWORD i;
2943
2944 HeapFree(GetProcessHeap(), 0, mesh->vertex_colors);
2945 mesh->vertex_colors = NULL;
2946
2947 hr = filedata->lpVtbl->Lock(filedata, &data_size, (const void**)&data);
2948 if (FAILED(hr)) return hr;
2949
2950 /* template IndexedColor {
2951 * DWORD index;
2952 * ColorRGBA indexColor;
2953 * }
2954 * template MeshVertexColors {
2955 * DWORD nVertexColors;
2956 * array IndexedColor vertexColors[nVertexColors];
2957 * }
2958 */
2959
2960 hr = E_FAIL;
2961
2962 if (data_size < sizeof(DWORD)) {
2963 WARN("truncated data (%ld bytes)\n", data_size);
2964 goto end;
2965 }
2966 num_colors = *(DWORD*)data;
2967 data += sizeof(DWORD);
2968 if (data_size < sizeof(DWORD) + num_colors * (sizeof(DWORD) + sizeof(D3DCOLORVALUE))) {
2969 WARN("truncated data (%ld bytes)\n", data_size);
2970 goto end;
2971 }
2972
2973 mesh->vertex_colors = HeapAlloc(GetProcessHeap(), 0, mesh->num_vertices * sizeof(DWORD));
2974 if (!mesh->vertex_colors) {
2975 hr = E_OUTOFMEMORY;
2976 goto end;
2977 }
2978
2979 for (i = 0; i < mesh->num_vertices; i++)
2980 mesh->vertex_colors[i] = D3DCOLOR_ARGB(0, 0xff, 0xff, 0xff);
2981 for (i = 0; i < num_colors; i++)
2982 {
2984 DWORD index = *(DWORD*)data;
2985 data += sizeof(DWORD);
2986 if (index >= mesh->num_vertices) {
2987 WARN("vertex color %u references undefined vertex %u (only %u vertices)\n",
2988 i, index, mesh->num_vertices);
2989 goto end;
2990 }
2991 memcpy(&color, data, sizeof(color));
2992 data += sizeof(color);
2993 color.r = min(1.0f, max(0.0f, color.r));
2994 color.g = min(1.0f, max(0.0f, color.g));
2995 color.b = min(1.0f, max(0.0f, color.b));
2996 color.a = min(1.0f, max(0.0f, color.a));
2997 mesh->vertex_colors[index] = D3DCOLOR_ARGB((BYTE)(color.a * 255.0f + 0.5f),
2998 (BYTE)(color.r * 255.0f + 0.5f),
2999 (BYTE)(color.g * 255.0f + 0.5f),
3000 (BYTE)(color.b * 255.0f + 0.5f));
3001 }
3002
3004
3005 hr = D3D_OK;
3006
3007end:
3008 filedata->lpVtbl->Unlock(filedata);
3009 return hr;
3010}
3011
3012static HRESULT parse_normals(ID3DXFileData *filedata, struct mesh_data *mesh)
3013{
3014 HRESULT hr;
3015 SIZE_T data_size;
3016 const BYTE *data;
3017 DWORD *index_out_ptr;
3018 DWORD i;
3019 DWORD num_face_indices = mesh->num_poly_faces * 2 + mesh->num_tri_faces;
3020
3021 HeapFree(GetProcessHeap(), 0, mesh->normals);
3022 mesh->num_normals = 0;
3023 mesh->normals = NULL;
3024 mesh->normal_indices = NULL;
3026
3027 hr = filedata->lpVtbl->Lock(filedata, &data_size, (const void**)&data);
3028 if (FAILED(hr)) return hr;
3029
3030 /* template Vector {
3031 * FLOAT x;
3032 * FLOAT y;
3033 * FLOAT z;
3034 * }
3035 * template MeshFace {
3036 * DWORD nFaceVertexIndices;
3037 * array DWORD faceVertexIndices[nFaceVertexIndices];
3038 * }
3039 * template MeshNormals {
3040 * DWORD nNormals;
3041 * array Vector normals[nNormals];
3042 * DWORD nFaceNormals;
3043 * array MeshFace faceNormals[nFaceNormals];
3044 * }
3045 */
3046
3047 hr = E_FAIL;
3048
3049 if (data_size < sizeof(DWORD) * 2) {
3050 WARN("truncated data (%ld bytes)\n", data_size);
3051 goto end;
3052 }
3053 mesh->num_normals = *(DWORD*)data;
3054 data += sizeof(DWORD);
3055 if (data_size < sizeof(DWORD) * 2 + mesh->num_normals * sizeof(D3DXVECTOR3) +
3056 num_face_indices * sizeof(DWORD)) {
3057 WARN("truncated data (%ld bytes)\n", data_size);
3058 goto end;
3059 }
3060
3061 mesh->normals = HeapAlloc(GetProcessHeap(), 0, mesh->num_normals * sizeof(D3DXVECTOR3));
3062 mesh->normal_indices = HeapAlloc(GetProcessHeap(), 0, num_face_indices * sizeof(DWORD));
3063 if (!mesh->normals || !mesh->normal_indices) {
3064 hr = E_OUTOFMEMORY;
3065 goto end;
3066 }
3067
3068 memcpy(mesh->normals, data, mesh->num_normals * sizeof(D3DXVECTOR3));
3069 data += mesh->num_normals * sizeof(D3DXVECTOR3);
3070 for (i = 0; i < mesh->num_normals; i++)
3071 D3DXVec3Normalize(&mesh->normals[i], &mesh->normals[i]);
3072
3073 if (*(DWORD*)data != mesh->num_poly_faces) {
3074 WARN("number of face normals (%u) doesn't match number of faces (%u)\n",
3075 *(DWORD*)data, mesh->num_poly_faces);
3076 goto end;
3077 }
3078 data += sizeof(DWORD);
3079 index_out_ptr = mesh->normal_indices;
3080 for (i = 0; i < mesh->num_poly_faces; i++)
3081 {
3082 DWORD j;
3083 DWORD count = *(DWORD*)data;
3084 if (count != mesh->num_tri_per_face[i] + 2) {
3085 WARN("face %u: number of normals (%u) doesn't match number of vertices (%u)\n",
3086 i, count, mesh->num_tri_per_face[i] + 2);
3087 goto end;
3088 }
3089 data += sizeof(DWORD);
3090
3091 for (j = 0; j < count; j++) {
3092 DWORD normal_index = *(DWORD*)data;
3093 if (normal_index >= mesh->num_normals) {
3094 WARN("face %u, normal index %u: reference to undefined normal %u (only %u normals)\n",
3095 i, j, normal_index, mesh->num_normals);
3096 goto end;
3097 }
3098 *index_out_ptr++ = normal_index;
3099 data += sizeof(DWORD);
3100 }
3101 }
3102
3103 hr = D3D_OK;
3104
3105end:
3106 filedata->lpVtbl->Unlock(filedata);
3107 return hr;
3108}
3109
3110static HRESULT parse_skin_mesh_info(ID3DXFileData *filedata, struct mesh_data *mesh_data, DWORD index)
3111{
3112 HRESULT hr;
3113 SIZE_T data_size;
3114 const BYTE *data;
3115
3116 TRACE("(%p, %p, %u)\n", filedata, mesh_data, index);
3117
3118 hr = filedata->lpVtbl->Lock(filedata, &data_size, (const void**)&data);
3119 if (FAILED(hr)) return hr;
3120
3121 hr = E_FAIL;
3122
3123 if (!mesh_data->skin_info) {
3124 if (data_size < sizeof(WORD) * 3) {
3125 WARN("truncated data (%ld bytes)\n", data_size);
3126 goto end;
3127 }
3128 /* Skip nMaxSkinWeightsPerVertex and nMaxSkinWeightsPerFace */
3129 data += 2 * sizeof(WORD);
3132 } else {
3133 const char *name;
3134 DWORD nb_influences;
3135
3136 /* FIXME: String must be retrieved directly instead of through a pointer once ID3DXFILE is fixed */
3137 name = *(const char**)data;
3138 data += sizeof(char*);
3139
3140 nb_influences = *(DWORD*)data;
3141 data += sizeof(DWORD);
3142
3143 if (data_size < (sizeof(char*) + sizeof(DWORD) + nb_influences * (sizeof(DWORD) + sizeof(FLOAT)) + 16 * sizeof(FLOAT))) {
3144 WARN("truncated data (%ld bytes)\n", data_size);
3145 goto end;
3146 }
3147
3148 hr = mesh_data->skin_info->lpVtbl->SetBoneName(mesh_data->skin_info, index, name);
3149 if (SUCCEEDED(hr))
3150 hr = mesh_data->skin_info->lpVtbl->SetBoneInfluence(mesh_data->skin_info, index, nb_influences,
3151 (const DWORD*)data, (const FLOAT*)(data + nb_influences * sizeof(DWORD)));
3152 if (SUCCEEDED(hr))
3153 hr = mesh_data->skin_info->lpVtbl->SetBoneOffsetMatrix(mesh_data->skin_info, index,
3154 (const D3DMATRIX*)(data + nb_influences * (sizeof(DWORD) + sizeof(FLOAT))));
3155 }
3156
3157end:
3158 filedata->lpVtbl->Unlock(filedata);
3159 return hr;
3160}
3161
3162/* for provide_flags parameters */
3163#define PROVIDE_MATERIALS 0x1
3164#define PROVIDE_SKININFO 0x2
3165#define PROVIDE_ADJACENCY 0x4
3166
3167static HRESULT parse_mesh(ID3DXFileData *filedata, struct mesh_data *mesh_data, DWORD provide_flags)
3168{
3169 HRESULT hr;
3170 SIZE_T data_size;
3171 const BYTE *data, *in_ptr;
3172 DWORD *index_out_ptr;
3173 GUID type;
3174 ID3DXFileData *child = NULL;
3175 DWORD i;
3176 SIZE_T nb_children;
3177 DWORD nb_skin_weights_info = 0;
3178
3179 /*
3180 * template Mesh {
3181 * DWORD nVertices;
3182 * array Vector vertices[nVertices];
3183 * DWORD nFaces;
3184 * array MeshFace faces[nFaces];
3185 * [ ... ]
3186 * }
3187 */
3188
3189 hr = filedata->lpVtbl->Lock(filedata, &data_size, (const void**)&data);
3190 if (FAILED(hr)) return hr;
3191
3192 in_ptr = data;
3193 hr = E_FAIL;
3194
3195 if (data_size < sizeof(DWORD) * 2) {
3196 WARN("truncated data (%ld bytes)\n", data_size);
3197 goto end;
3198 }
3199 mesh_data->num_vertices = *(DWORD*)in_ptr;
3200 if (data_size < sizeof(DWORD) * 2 + mesh_data->num_vertices * sizeof(D3DXVECTOR3)) {
3201 WARN("truncated data (%ld bytes)\n", data_size);
3202 goto end;
3203 }
3204 in_ptr += sizeof(DWORD) + mesh_data->num_vertices * sizeof(D3DXVECTOR3);
3205
3206 mesh_data->num_poly_faces = *(DWORD*)in_ptr;
3207 in_ptr += sizeof(DWORD);
3208
3210 for (i = 0; i < mesh_data->num_poly_faces; i++)
3211 {
3212 DWORD num_poly_vertices;
3213 DWORD j;
3214
3215 if (data_size - (in_ptr - data) < sizeof(DWORD)) {
3216 WARN("truncated data (%ld bytes)\n", data_size);
3217 goto end;
3218 }
3219 num_poly_vertices = *(DWORD*)in_ptr;
3220 in_ptr += sizeof(DWORD);
3221 if (data_size - (in_ptr - data) < num_poly_vertices * sizeof(DWORD)) {
3222 WARN("truncated data (%ld bytes)\n", data_size);
3223 goto end;
3224 }
3225 if (num_poly_vertices < 3) {
3226 WARN("face %u has only %u vertices\n", i, num_poly_vertices);
3227 goto end;
3228 }
3229 for (j = 0; j < num_poly_vertices; j++) {
3230 if (*(DWORD*)in_ptr >= mesh_data->num_vertices) {
3231 WARN("face %u, index %u: undefined vertex %u (only %u vertices)\n",
3232 i, j, *(DWORD*)in_ptr, mesh_data->num_vertices);
3233 goto end;
3234 }
3235 in_ptr += sizeof(DWORD);
3236 }
3237 mesh_data->num_tri_faces += num_poly_vertices - 2;
3238 }
3239
3241
3249 hr = E_OUTOFMEMORY;
3250 goto end;
3251 }
3252
3253 in_ptr = data + sizeof(DWORD);
3255 in_ptr += mesh_data->num_vertices * sizeof(D3DXVECTOR3) + sizeof(DWORD);
3256
3257 index_out_ptr = mesh_data->indices;
3258 for (i = 0; i < mesh_data->num_poly_faces; i++)
3259 {
3260 DWORD count;
3261
3262 count = *(DWORD*)in_ptr;
3263 in_ptr += sizeof(DWORD);
3265
3266 while (count--) {
3267 *index_out_ptr++ = *(DWORD*)in_ptr;
3268 in_ptr += sizeof(DWORD);
3269 }
3270 }
3271
3272 hr = filedata->lpVtbl->GetChildren(filedata, &nb_children);
3273 if (FAILED(hr))
3274 goto end;
3275
3276 for (i = 0; i < nb_children; i++)
3277 {
3278 hr = filedata->lpVtbl->GetChild(filedata, i, &child);
3279 if (FAILED(hr))
3280 goto end;
3281 hr = child->lpVtbl->GetType(child, &type);
3282 if (FAILED(hr))
3283 goto end;
3284
3285 if (IsEqualGUID(&type, &TID_D3DRMMeshNormals)) {
3287 } else if (IsEqualGUID(&type, &TID_D3DRMMeshVertexColors)) {
3289 } else if (IsEqualGUID(&type, &TID_D3DRMMeshTextureCoords)) {
3291 } else if (IsEqualGUID(&type, &TID_D3DRMMeshMaterialList) &&
3292 (provide_flags & PROVIDE_MATERIALS))
3293 {
3295 } else if (provide_flags & PROVIDE_SKININFO) {
3296 if (IsEqualGUID(&type, &DXFILEOBJ_XSkinMeshHeader)) {
3297 if (mesh_data->skin_info) {
3298 WARN("Skin mesh header already encountered\n");
3299 hr = E_FAIL;
3300 goto end;
3301 }
3303 if (FAILED(hr))
3304 goto end;
3305 } else if (IsEqualGUID(&type, &DXFILEOBJ_SkinWeights)) {
3306 if (!mesh_data->skin_info) {
3307 WARN("Skin weights found but skin mesh header not encountered yet\n");
3308 hr = E_FAIL;
3309 goto end;
3310 }
3311 hr = parse_skin_mesh_info(child, mesh_data, nb_skin_weights_info);
3312 if (FAILED(hr))
3313 goto end;
3314 nb_skin_weights_info++;
3315 }
3316 }
3317 if (FAILED(hr))
3318 goto end;
3319
3320 IUnknown_Release(child);
3321 child = NULL;
3322 }
3323
3324 if (mesh_data->skin_info && (nb_skin_weights_info != mesh_data->nb_bones)) {
3325 WARN("Mismatch between nb skin weights info %u encountered and nb bones %u from skin mesh header\n",
3326 nb_skin_weights_info, mesh_data->nb_bones);
3327 hr = E_FAIL;
3328 goto end;
3329 }
3330
3331 if ((provide_flags & PROVIDE_SKININFO) && !mesh_data->skin_info)
3332 {
3335 goto end;
3336 }
3337
3338 hr = D3D_OK;
3339
3340end:
3341 if (child)
3342 IUnknown_Release(child);
3343 filedata->lpVtbl->Unlock(filedata);
3344 return hr;
3345}
3346
3347static HRESULT generate_effects(ID3DXBuffer *materials, DWORD num_materials,
3348 ID3DXBuffer **effects)
3349{
3350 HRESULT hr;
3351 D3DXEFFECTINSTANCE *effect_ptr;
3352 BYTE *out_ptr;
3353 const D3DXMATERIAL *material_ptr = ID3DXBuffer_GetBufferPointer(materials);
3354 static const struct {
3355 const char *param_name;
3356 DWORD name_size;
3357 DWORD num_bytes;
3358 DWORD value_offset;
3359 } material_effects[] = {
3360#define EFFECT_TABLE_ENTRY(str, field) \
3361 {str, sizeof(str), sizeof(material_ptr->MatD3D.field), offsetof(D3DXMATERIAL, MatD3D.field)}
3362 EFFECT_TABLE_ENTRY("Diffuse", Diffuse),
3363 EFFECT_TABLE_ENTRY("Power", Power),
3364 EFFECT_TABLE_ENTRY("Specular", Specular),
3365 EFFECT_TABLE_ENTRY("Emissive", Emissive),
3366 EFFECT_TABLE_ENTRY("Ambient", Ambient),
3367#undef EFFECT_TABLE_ENTRY
3368 };
3369 static const char texture_paramname[] = "Texture0@Name";
3371 DWORD i;
3372
3373 /* effects buffer layout:
3374 *
3375 * D3DXEFFECTINSTANCE effects[num_materials];
3376 * for (effect in effects)
3377 * {
3378 * D3DXEFFECTDEFAULT defaults[effect.NumDefaults];
3379 * for (default in defaults)
3380 * {
3381 * *default.pParamName;
3382 * *default.pValue;
3383 * }
3384 * }
3385 */
3387 buffer_size += sizeof(D3DXEFFECTDEFAULT) * ARRAY_SIZE(material_effects);
3388 for (i = 0; i < ARRAY_SIZE(material_effects); i++) {
3389 buffer_size += material_effects[i].name_size;
3390 buffer_size += material_effects[i].num_bytes;
3391 }
3392 buffer_size *= num_materials;
3393 for (i = 0; i < num_materials; i++) {
3394 if (material_ptr[i].pTextureFilename) {
3395 buffer_size += sizeof(D3DXEFFECTDEFAULT);
3396 buffer_size += sizeof(texture_paramname);
3397 buffer_size += strlen(material_ptr[i].pTextureFilename) + 1;
3398 }
3399 }
3400
3401 hr = D3DXCreateBuffer(buffer_size, effects);
3402 if (FAILED(hr)) return hr;
3403 effect_ptr = ID3DXBuffer_GetBufferPointer(*effects);
3404 out_ptr = (BYTE*)(effect_ptr + num_materials);
3405
3406 for (i = 0; i < num_materials; i++)
3407 {
3408 DWORD j;
3410
3411 effect_ptr->pDefaults = defaults;
3412 effect_ptr->NumDefaults = material_ptr->pTextureFilename ? 6 : 5;
3413 out_ptr = (BYTE*)(effect_ptr->pDefaults + effect_ptr->NumDefaults);
3414
3415 for (j = 0; j < ARRAY_SIZE(material_effects); j++)
3416 {
3417 defaults->pParamName = (char *)out_ptr;
3418 strcpy(defaults->pParamName, material_effects[j].param_name);
3419 defaults->pValue = defaults->pParamName + material_effects[j].name_size;
3420 defaults->Type = D3DXEDT_FLOATS;
3421 defaults->NumBytes = material_effects[j].num_bytes;
3422 memcpy(defaults->pValue, (BYTE*)material_ptr + material_effects[j].value_offset, defaults->NumBytes);
3423 out_ptr = (BYTE*)defaults->pValue + defaults->NumBytes;
3424 defaults++;
3425 }
3426
3427 if (material_ptr->pTextureFilename)
3428 {
3429 defaults->pParamName = (char *)out_ptr;
3430 strcpy(defaults->pParamName, texture_paramname);
3431 defaults->pValue = defaults->pParamName + sizeof(texture_paramname);
3432 defaults->Type = D3DXEDT_STRING;
3433 defaults->NumBytes = strlen(material_ptr->pTextureFilename) + 1;
3434 strcpy(defaults->pValue, material_ptr->pTextureFilename);
3435 out_ptr = (BYTE*)defaults->pValue + defaults->NumBytes;
3436 }
3437 material_ptr++;
3438 effect_ptr++;
3439 }
3440 assert(out_ptr - (BYTE*)ID3DXBuffer_GetBufferPointer(*effects) == buffer_size);
3441
3442 return D3D_OK;
3443}
3444
3445HRESULT WINAPI D3DXLoadSkinMeshFromXof(struct ID3DXFileData *filedata, DWORD options,
3446 struct IDirect3DDevice9 *device, struct ID3DXBuffer **adjacency_out, struct ID3DXBuffer **materials_out,
3447 struct ID3DXBuffer **effects_out, DWORD *num_materials_out, struct ID3DXSkinInfo **skin_info_out,
3448 struct ID3DXMesh **mesh_out)
3449{
3450 HRESULT hr;
3451 DWORD *index_in_ptr;
3452 struct mesh_data mesh_data;
3453 DWORD total_vertices;
3454 ID3DXMesh *d3dxmesh = NULL;
3455 ID3DXBuffer *adjacency = NULL;
3457 ID3DXBuffer *effects = NULL;
3458 struct vertex_duplication {
3459 DWORD normal_index;
3460 struct list entry;
3461 } *duplications = NULL;
3462 DWORD i;
3463 void *vertices = NULL;
3464 void *indices = NULL;
3465 BYTE *out_ptr;
3466 DWORD provide_flags = 0;
3467
3468 TRACE("(%p, %x, %p, %p, %p, %p, %p, %p, %p)\n", filedata, options, device, adjacency_out, materials_out,
3469 effects_out, num_materials_out, skin_info_out, mesh_out);
3470
3471 ZeroMemory(&mesh_data, sizeof(mesh_data));
3472
3473 if (num_materials_out || materials_out || effects_out)
3474 provide_flags |= PROVIDE_MATERIALS;
3475 if (skin_info_out)
3476 provide_flags |= PROVIDE_SKININFO;
3477
3478 hr = parse_mesh(filedata, &mesh_data, provide_flags);
3479 if (FAILED(hr)) goto cleanup;
3480
3481 total_vertices = mesh_data.num_vertices;
3482 if (mesh_data.fvf & D3DFVF_NORMAL) {
3483 /* duplicate vertices with multiple normals */
3484 DWORD num_face_indices = mesh_data.num_poly_faces * 2 + mesh_data.num_tri_faces;
3485 duplications = HeapAlloc(GetProcessHeap(), 0, (mesh_data.num_vertices + num_face_indices) * sizeof(*duplications));
3486 if (!duplications) {
3487 hr = E_OUTOFMEMORY;
3488 goto cleanup;
3489 }
3490 for (i = 0; i < total_vertices; i++)
3491 {
3492 duplications[i].normal_index = -1;
3493 list_init(&duplications[i].entry);
3494 }
3495 for (i = 0; i < num_face_indices; i++) {
3497 DWORD normal_index = mesh_data.normal_indices[i];
3498 struct vertex_duplication *dup_ptr = &duplications[vertex_index];
3499
3500 if (dup_ptr->normal_index == -1) {
3501 dup_ptr->normal_index = normal_index;
3502 } else {
3503 D3DXVECTOR3 *new_normal = &mesh_data.normals[normal_index];
3504 struct list *dup_list = &dup_ptr->entry;
3505 while (TRUE) {
3506 D3DXVECTOR3 *cur_normal = &mesh_data.normals[dup_ptr->normal_index];
3507 if (new_normal->x == cur_normal->x &&
3508 new_normal->y == cur_normal->y &&
3509 new_normal->z == cur_normal->z)
3510 {
3511 mesh_data.indices[i] = dup_ptr - duplications;
3512 break;
3513 } else if (!list_next(dup_list, &dup_ptr->entry)) {
3514 dup_ptr = &duplications[total_vertices++];
3515 dup_ptr->normal_index = normal_index;
3516 list_add_tail(dup_list, &dup_ptr->entry);
3517 mesh_data.indices[i] = dup_ptr - duplications;
3518 break;
3519 } else {
3520 dup_ptr = LIST_ENTRY(list_next(dup_list, &dup_ptr->entry),
3521 struct vertex_duplication, entry);
3522 }
3523 }
3524 }
3525 }
3526 }
3527
3528 hr = D3DXCreateMeshFVF(mesh_data.num_tri_faces, total_vertices, options, mesh_data.fvf, device, &d3dxmesh);
3529 if (FAILED(hr)) goto cleanup;
3530
3531 hr = d3dxmesh->lpVtbl->LockVertexBuffer(d3dxmesh, 0, &vertices);
3532 if (FAILED(hr)) goto cleanup;
3533
3534 out_ptr = vertices;
3535 for (i = 0; i < mesh_data.num_vertices; i++) {
3536 *(D3DXVECTOR3*)out_ptr = mesh_data.vertices[i];
3537 out_ptr += sizeof(D3DXVECTOR3);
3538 if (mesh_data.fvf & D3DFVF_NORMAL) {
3539 if (duplications[i].normal_index == -1)
3540 ZeroMemory(out_ptr, sizeof(D3DXVECTOR3));
3541 else
3542 *(D3DXVECTOR3*)out_ptr = mesh_data.normals[duplications[i].normal_index];
3543 out_ptr += sizeof(D3DXVECTOR3);
3544 }
3546 *(DWORD*)out_ptr = mesh_data.vertex_colors[i];
3547 out_ptr += sizeof(DWORD);
3548 }
3549 if (mesh_data.fvf & D3DFVF_TEX1) {
3550 *(D3DXVECTOR2*)out_ptr = mesh_data.tex_coords[i];
3551 out_ptr += sizeof(D3DXVECTOR2);
3552 }
3553 }
3554 if (mesh_data.fvf & D3DFVF_NORMAL) {
3555 DWORD vertex_size = D3DXGetFVFVertexSize(mesh_data.fvf);
3556 out_ptr = vertices;
3557 for (i = 0; i < mesh_data.num_vertices; i++) {
3558 struct vertex_duplication *dup_ptr;
3559 LIST_FOR_EACH_ENTRY(dup_ptr, &duplications[i].entry, struct vertex_duplication, entry)
3560 {
3561 int j = dup_ptr - duplications;
3562 BYTE *dest_vertex = (BYTE*)vertices + j * vertex_size;
3563
3564 memcpy(dest_vertex, out_ptr, vertex_size);
3565 dest_vertex += sizeof(D3DXVECTOR3);
3566 *(D3DXVECTOR3*)dest_vertex = mesh_data.normals[dup_ptr->normal_index];
3567 }
3568 out_ptr += vertex_size;
3569 }
3570 }
3571 d3dxmesh->lpVtbl->UnlockVertexBuffer(d3dxmesh);
3572
3573 hr = d3dxmesh->lpVtbl->LockIndexBuffer(d3dxmesh, 0, &indices);
3574 if (FAILED(hr)) goto cleanup;
3575
3576 index_in_ptr = mesh_data.indices;
3577#define FILL_INDEX_BUFFER(indices_var) \
3578 for (i = 0; i < mesh_data.num_poly_faces; i++) \
3579 { \
3580 DWORD count = mesh_data.num_tri_per_face[i]; \
3581 WORD first_index = *index_in_ptr++; \
3582 while (count--) { \
3583 *indices_var++ = first_index; \
3584 *indices_var++ = *index_in_ptr; \
3585 index_in_ptr++; \
3586 *indices_var++ = *index_in_ptr; \
3587 } \
3588 index_in_ptr++; \
3589 }
3590 if (options & D3DXMESH_32BIT) {
3591 DWORD *dword_indices = indices;
3592 FILL_INDEX_BUFFER(dword_indices)
3593 } else {
3594 WORD *word_indices = indices;
3595 FILL_INDEX_BUFFER(word_indices)
3596 }
3597#undef FILL_INDEX_BUFFER
3598 d3dxmesh->lpVtbl->UnlockIndexBuffer(d3dxmesh);
3599
3601 DWORD *attrib_buffer = NULL;
3602 hr = d3dxmesh->lpVtbl->LockAttributeBuffer(d3dxmesh, 0, &attrib_buffer);
3603 if (FAILED(hr)) goto cleanup;
3604 for (i = 0; i < mesh_data.num_poly_faces; i++)
3605 {
3607 while (count--)
3608 *attrib_buffer++ = mesh_data.material_indices[i];
3609 }
3610 d3dxmesh->lpVtbl->UnlockAttributeBuffer(d3dxmesh);
3611
3612 hr = d3dxmesh->lpVtbl->OptimizeInplace(d3dxmesh,
3614 NULL, NULL, NULL, NULL);
3615 if (FAILED(hr)) goto cleanup;
3616 }
3617
3618 if (mesh_data.num_materials && (materials_out || effects_out)) {
3620 char *strings_out_ptr;
3621 D3DXMATERIAL *materials_ptr;
3622
3623 for (i = 0; i < mesh_data.num_materials; i++) {
3626 }
3627
3628 hr = D3DXCreateBuffer(buffer_size, &materials);
3629 if (FAILED(hr)) goto cleanup;
3630
3631 materials_ptr = ID3DXBuffer_GetBufferPointer(materials);
3632 memcpy(materials_ptr, mesh_data.materials, mesh_data.num_materials * sizeof(D3DXMATERIAL));
3633 strings_out_ptr = (char*)(materials_ptr + mesh_data.num_materials);
3634 for (i = 0; i < mesh_data.num_materials; i++) {
3635 if (materials_ptr[i].pTextureFilename) {
3636 strcpy(strings_out_ptr, mesh_data.materials[i].pTextureFilename);
3637 materials_ptr[i].pTextureFilename = strings_out_ptr;
3638 strings_out_ptr += strlen(mesh_data.materials[i].pTextureFilename) + 1;
3639 }
3640 }
3641 }
3642
3643 if (mesh_data.num_materials && effects_out) {
3644 hr = generate_effects(materials, mesh_data.num_materials, &effects);
3645 if (FAILED(hr)) goto cleanup;
3646
3647 if (!materials_out) {
3648 ID3DXBuffer_Release(materials);
3649 materials = NULL;
3650 }
3651 }
3652
3653 if (adjacency_out) {
3654 hr = D3DXCreateBuffer(mesh_data.num_tri_faces * 3 * sizeof(DWORD), &adjacency);
3655 if (FAILED(hr)) goto cleanup;
3656 hr = d3dxmesh->lpVtbl->GenerateAdjacency(d3dxmesh, 0.0f, ID3DXBuffer_GetBufferPointer(adjacency));
3657 if (FAILED(hr)) goto cleanup;
3658 }
3659
3660 *mesh_out = d3dxmesh;
3661 if (adjacency_out) *adjacency_out = adjacency;
3662 if (num_materials_out) *num_materials_out = mesh_data.num_materials;
3663 if (materials_out) *materials_out = materials;
3664 if (effects_out) *effects_out = effects;
3665 if (skin_info_out) *skin_info_out = mesh_data.skin_info;
3666
3667 hr = D3D_OK;
3668cleanup:
3669 if (FAILED(hr)) {
3670 if (d3dxmesh) IUnknown_Release(d3dxmesh);
3671 if (adjacency) ID3DXBuffer_Release(adjacency);
3672 if (materials) ID3DXBuffer_Release(materials);
3673 if (effects) ID3DXBuffer_Release(effects);
3675 if (skin_info_out) *skin_info_out = NULL;
3676 }
3685 HeapFree(GetProcessHeap(), 0, duplications);
3686 return hr;
3687}
3688
3690 struct ID3DXAllocateHierarchy *alloc_hier, struct ID3DXLoadUserData *load_user_data,
3691 D3DXFRAME **frame_hierarchy, struct ID3DXAnimationController **anim_controller)
3692{
3694 HRESULT hr;
3695 int len;
3696
3697 TRACE("filename %s, options %#x, device %p, alloc_hier %p, "
3698 "load_user_data %p, frame_hierarchy %p, anim_controller %p.\n",
3700 load_user_data, frame_hierarchy, anim_controller);
3701
3702 if (!filename)
3703 return D3DERR_INVALIDCALL;
3704
3706 filenameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3707 if (!filenameW) return E_OUTOFMEMORY;
3709
3711 alloc_hier, load_user_data, frame_hierarchy, anim_controller);
3713
3714 return hr;
3715}
3716
3718 struct ID3DXAllocateHierarchy *alloc_hier, struct ID3DXLoadUserData *load_user_data,
3719 D3DXFRAME **frame_hierarchy, struct ID3DXAnimationController **anim_controller)
3720{
3721 void *buffer;
3722 HRESULT hr;
3723 DWORD size;
3724
3725 TRACE("filename %s, options %#x, device %p, alloc_hier %p, "
3726 "load_user_data %p, frame_hierarchy %p, anim_controller %p.\n",
3728 load_user_data, frame_hierarchy, anim_controller);
3729
3730 if (!filename)
3731 return D3DERR_INVALIDCALL;
3732
3734 if (FAILED(hr))
3735 return D3DXERR_INVALIDDATA;
3736
3738 alloc_hier, load_user_data, frame_hierarchy, anim_controller);
3739
3741
3742 return hr;
3743}
3744
3745static HRESULT filedata_get_name(ID3DXFileData *filedata, char **name)
3746{
3747 HRESULT hr;
3748 SIZE_T name_len;
3749
3750 hr = filedata->lpVtbl->GetName(filedata, NULL, &name_len);
3751 if (FAILED(hr)) return hr;
3752
3753 if (!name_len)
3754 name_len++;
3755 *name = HeapAlloc(GetProcessHeap(), 0, name_len);
3756 if (!*name) return E_OUTOFMEMORY;
3757
3758 hr = filedata->lpVtbl->GetName(filedata, *name, &name_len);
3759 if (FAILED(hr))
3761 else if (!name_len)
3762 (*name)[0] = 0;
3763
3764 return hr;
3765}
3766
3767static HRESULT load_mesh_container(struct ID3DXFileData *filedata, DWORD options, struct IDirect3DDevice9 *device,
3768 struct ID3DXAllocateHierarchy *alloc_hier, D3DXMESHCONTAINER **mesh_container)
3769{
3770 HRESULT hr;
3771 ID3DXBuffer *adjacency = NULL;
3772 ID3DXBuffer *materials = NULL;
3773 ID3DXBuffer *effects = NULL;
3774 ID3DXSkinInfo *skin_info = NULL;
3776 DWORD num_materials = 0;
3777 char *name = NULL;
3778
3780 mesh_data.u.pMesh = NULL;
3781
3783 &adjacency, &materials, &effects, &num_materials,
3784 &skin_info, &mesh_data.u.pMesh);
3785 if (FAILED(hr)) return hr;
3786
3787 hr = filedata_get_name(filedata, &name);
3788 if (FAILED(hr)) goto cleanup;
3789
3790 hr = alloc_hier->lpVtbl->CreateMeshContainer(alloc_hier, name, &mesh_data,
3791 materials ? ID3DXBuffer_GetBufferPointer(materials) : NULL,
3792 effects ? ID3DXBuffer_GetBufferPointer(effects) : NULL,
3793 num_materials,
3794 adjacency ? ID3DXBuffer_GetBufferPointer(adjacency) : NULL,
3795 skin_info, mesh_container);
3796
3797cleanup:
3798 if (materials) ID3DXBuffer_Release(materials);
3799 if (effects) ID3DXBuffer_Release(effects);
3800 if (adjacency) ID3DXBuffer_Release(adjacency);
3801 if (skin_info) IUnknown_Release(skin_info);
3802 if (mesh_data.u.pMesh) IUnknown_Release(mesh_data.u.pMesh);
3804 return hr;
3805}
3806
3807static HRESULT parse_transform_matrix(ID3DXFileData *filedata, D3DXMATRIX *transform)
3808{
3809 HRESULT hr;
3810 SIZE_T data_size;
3811 const BYTE *data;
3812
3813 /* template Matrix4x4 {
3814 * array FLOAT matrix[16];
3815 * }
3816 * template FrameTransformMatrix {
3817 * Matrix4x4 frameMatrix;
3818 * }
3819 */
3820
3821 hr = filedata->lpVtbl->Lock(filedata, &data_size, (const void**)&data);
3822 if (FAILED(hr)) return hr;
3823
3824 if (data_size != sizeof(D3DXMATRIX)) {
3825 WARN("incorrect data size (%ld bytes)\n", data_size);
3826 filedata->lpVtbl->Unlock(filedata);
3827 return E_FAIL;
3828 }
3829
3830 memcpy(transform, data, sizeof(D3DXMATRIX));
3831
3832 filedata->lpVtbl->Unlock(filedata);
3833 return D3D_OK;
3834}
3835
3836static HRESULT load_frame(struct ID3DXFileData *filedata, DWORD options, struct IDirect3DDevice9 *device,
3837 struct ID3DXAllocateHierarchy *alloc_hier, D3DXFRAME **frame_out)
3838{
3839 HRESULT hr;
3840 GUID type;
3841 ID3DXFileData *child;
3842 char *name = NULL;
3843 D3DXFRAME *frame = NULL;
3844 D3DXMESHCONTAINER **next_container;
3845 D3DXFRAME **next_child;
3846 SIZE_T i, nb_children;
3847
3848 hr = filedata_get_name(filedata, &name);
3849 if (FAILED(hr)) return hr;
3850
3851 hr = alloc_hier->lpVtbl->CreateFrame(alloc_hier, name, frame_out);
3853 if (FAILED(hr)) return E_FAIL;
3854
3855 frame = *frame_out;
3856 D3DXMatrixIdentity(&frame->TransformationMatrix);
3857 next_child = &frame->pFrameFirstChild;
3858 next_container = &frame->pMeshContainer;
3859
3860 hr = filedata->lpVtbl->GetChildren(filedata, &nb_children);
3861 if (FAILED(hr))
3862 return hr;
3863
3864 for (i = 0; i < nb_children; i++)
3865 {
3866 hr = filedata->lpVtbl->GetChild(filedata, i, &child);
3867 if (FAILED(hr))
3868 return hr;
3869 hr = child->lpVtbl->GetType(child, &type);
3870 if (FAILED(hr))
3871 goto err;
3872
3873 if (IsEqualGUID(&type, &TID_D3DRMMesh)) {
3874 hr = load_mesh_container(child, options, device, alloc_hier, next_container);
3875 if (SUCCEEDED(hr))
3876 next_container = &(*next_container)->pNextMeshContainer;
3877 } else if (IsEqualGUID(&type, &TID_D3DRMFrameTransformMatrix)) {
3879 } else if (IsEqualGUID(&type, &TID_D3DRMFrame)) {
3880 hr = load_frame(child, options, device, alloc_hier, next_child);
3881 if (SUCCEEDED(hr))
3882 next_child = &(*next_child)->pFrameSibling;
3883 }
3884 if (FAILED(hr))
3885 goto err;
3886
3887 IUnknown_Release(child);
3888 }
3889 return D3D_OK;
3890
3891err:
3892 IUnknown_Release(child);
3893 return hr;
3894}
3895
3897 struct IDirect3DDevice9 *device, struct ID3DXAllocateHierarchy *alloc_hier,
3898 struct ID3DXLoadUserData *load_user_data, D3DXFRAME **frame_hierarchy,
3899 struct ID3DXAnimationController **anim_controller)
3900{
3901 HRESULT hr;
3902 ID3DXFile *d3dxfile = NULL;
3903 ID3DXFileEnumObject *enumobj = NULL;
3904 ID3DXFileData *filedata = NULL;
3906 D3DXFRAME *first_frame = NULL;
3907 D3DXFRAME **next_frame = &first_frame;
3908 SIZE_T i, nb_children;
3909 GUID guid;
3910
3911 TRACE("(%p, %u, %x, %p, %p, %p, %p, %p)\n", memory, memory_size, options,
3912 device, alloc_hier, load_user_data, frame_hierarchy, anim_controller);
3913
3914 if (!memory || !memory_size || !device || !frame_hierarchy || !alloc_hier)
3915 return D3DERR_INVALIDCALL;
3916 if (load_user_data)
3917 {
3918 FIXME("Loading user data not implemented.\n");
3919 return E_NOTIMPL;
3920 }
3921
3922 hr = D3DXFileCreate(&d3dxfile);
3923 if (FAILED(hr)) goto cleanup;
3924
3925 hr = d3dxfile->lpVtbl->RegisterTemplates(d3dxfile, D3DRM_XTEMPLATES, D3DRM_XTEMPLATE_BYTES);
3926 if (FAILED(hr)) goto cleanup;
3927
3928 source.lpMemory = (void*)memory;
3929 source.dSize = memory_size;
3930 hr = d3dxfile->lpVtbl->CreateEnumObject(d3dxfile, &source, D3DXF_FILELOAD_FROMMEMORY, &enumobj);
3931 if (FAILED(hr)) goto cleanup;
3932
3933 hr = enumobj->lpVtbl->GetChildren(enumobj, &nb_children);
3934 if (FAILED(hr))
3935 goto cleanup;
3936
3937 for (i = 0; i < nb_children; i++)
3938 {
3939 hr = enumobj->lpVtbl->GetChild(enumobj, i, &filedata);
3940 if (FAILED(hr))
3941 goto cleanup;
3942
3943 hr = filedata->lpVtbl->GetType(filedata, &guid);
3944 if (SUCCEEDED(hr)) {
3945 if (IsEqualGUID(&guid, &TID_D3DRMMesh)) {
3946 hr = alloc_hier->lpVtbl->CreateFrame(alloc_hier, NULL, next_frame);
3947 if (FAILED(hr)) {
3948 hr = E_FAIL;
3949 goto cleanup;
3950 }
3951
3952 D3DXMatrixIdentity(&(*next_frame)->TransformationMatrix);
3953
3954 hr = load_mesh_container(filedata, options, device, alloc_hier, &(*next_frame)->pMeshContainer);
3955 if (FAILED(hr)) goto cleanup;
3956 } else if (IsEqualGUID(&guid, &TID_D3DRMFrame)) {
3958 if (FAILED(hr)) goto cleanup;
3959 }
3960 while (*next_frame)
3961 next_frame = &(*next_frame)->pFrameSibling;
3962 }
3963
3964 filedata->lpVtbl->Release(filedata);
3965 filedata = NULL;
3966 if (FAILED(hr))
3967 goto cleanup;
3968 }
3969
3970 if (!first_frame) {
3971 hr = E_FAIL;
3972 } else if (first_frame->pFrameSibling) {
3973 D3DXFRAME *root_frame = NULL;
3974 hr = alloc_hier->lpVtbl->CreateFrame(alloc_hier, NULL, &root_frame);
3975 if (FAILED(hr)) {
3976 hr = E_FAIL;
3977 goto cleanup;
3978 }
3979 D3DXMatrixIdentity(&root_frame->TransformationMatrix);
3980 root_frame->pFrameFirstChild = first_frame;
3981 *frame_hierarchy = root_frame;
3982 hr = D3D_OK;
3983 } else {
3984 *frame_hierarchy = first_frame;
3985 hr = D3D_OK;
3986 }
3987
3988 if (anim_controller)
3989 {
3990 *anim_controller = NULL;
3991 FIXME("Animation controller creation not implemented.\n");
3992 }
3993
3994cleanup:
3995 if (FAILED(hr) && first_frame) D3DXFrameDestroy(first_frame, alloc_hier);
3996 if (filedata) filedata->lpVtbl->Release(filedata);
3997 if (enumobj) enumobj->lpVtbl->Release(enumobj);
3998 if (d3dxfile) d3dxfile->lpVtbl->Release(d3dxfile);
3999 return hr;
4000}
4001
4002HRESULT WINAPI D3DXCleanMesh(D3DXCLEANTYPE clean_type, ID3DXMesh *mesh_in, const DWORD *adjacency_in,
4003 ID3DXMesh **mesh_out, DWORD *adjacency_out, ID3DXBuffer **errors_and_warnings)
4004{
4005 FIXME("(%u, %p, %p, %p, %p, %p)\n", clean_type, mesh_in, adjacency_in, mesh_out, adjacency_out, errors_and_warnings);
4006
4007 return E_NOTIMPL;
4008}
4009
4010HRESULT WINAPI D3DXFrameDestroy(D3DXFRAME *frame, ID3DXAllocateHierarchy *alloc_hier)
4011{
4012 HRESULT hr;
4013 BOOL last = FALSE;
4014
4015 TRACE("(%p, %p)\n", frame, alloc_hier);
4016
4017 if (!frame || !alloc_hier)
4018 return D3DERR_INVALIDCALL;
4019
4020 while (!last) {
4022 D3DXFRAME *current_frame;
4023
4024 if (frame->pFrameSibling) {
4025 current_frame = frame->pFrameSibling;
4026 frame->pFrameSibling = current_frame->pFrameSibling;
4027 current_frame->pFrameSibling = NULL;
4028 } else {
4029 current_frame = frame;
4030 last = TRUE;
4031 }
4032
4033 if (current_frame->pFrameFirstChild) {
4035 if (FAILED(hr)) return hr;
4036 current_frame->pFrameFirstChild = NULL;
4037 }
4038
4039 container = current_frame->pMeshContainer;
4040 while (container) {
4041 D3DXMESHCONTAINER *next_container = container->pNextMeshContainer;
4042 hr = alloc_hier->lpVtbl->DestroyMeshContainer(alloc_hier, container);
4043 if (FAILED(hr)) return hr;
4044 container = next_container;
4045 }
4046 hr = alloc_hier->lpVtbl->DestroyFrame(alloc_hier, current_frame);
4047 if (FAILED(hr)) return hr;
4048 }
4049 return D3D_OK;
4050}
4051
4052HRESULT WINAPI D3DXLoadMeshFromXA(const char *filename, DWORD options, struct IDirect3DDevice9 *device,
4053 struct ID3DXBuffer **adjacency, struct ID3DXBuffer **materials, struct ID3DXBuffer **effect_instances,
4054 DWORD *num_materials, struct ID3DXMesh **mesh)
4055{
4057 HRESULT hr;
4058 int len;
4059
4060 TRACE("filename %s, options %#x, device %p, adjacency %p, materials %p, "
4061 "effect_instances %p, num_materials %p, mesh %p.\n",
4062 debugstr_a(filename), options, device, adjacency, materials,
4063 effect_instances, num_materials, mesh);
4064
4065 if (!filename)
4066 return D3DERR_INVALIDCALL;
4067
4069 filenameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
4070 if (!filenameW) return E_OUTOFMEMORY;
4072
4073 hr = D3DXLoadMeshFromXW(filenameW, options, device, adjacency, materials,
4074 effect_instances, num_materials, mesh);
4076
4077 return hr;
4078}
4079
4081 struct ID3DXBuffer **adjacency, struct ID3DXBuffer **materials, struct ID3DXBuffer **effect_instances,
4082 DWORD *num_materials, struct ID3DXMesh **mesh)
4083{
4084 void *buffer;
4085 HRESULT hr;
4086 DWORD size;
4087
4088 TRACE("filename %s, options %#x, device %p, adjacency %p, materials %p, "
4089 "effect_instances %p, num_materials %p, mesh %p.\n",
4090 debugstr_w(filename), options, device, adjacency, materials,
4091 effect_instances, num_materials, mesh);
4092
4093 if (!filename)
4094 return D3DERR_INVALIDCALL;
4095
4097 if (FAILED(hr))
4098 return D3DXERR_INVALIDDATA;
4099
4101 materials, effect_instances, num_materials, mesh);
4102
4104
4105 return hr;
4106}
4107
4109 struct IDirect3DDevice9 *device, struct ID3DXBuffer **adjacency, struct ID3DXBuffer **materials,
4110 struct ID3DXBuffer **effect_instances, DWORD *num_materials, struct ID3DXMesh **mesh)
4111{
4112 HRESULT hr;
4113 HRSRC resinfo;
4114 void *buffer;
4115 DWORD size;
4116
4117 TRACE("module %p, name %s, type %s, options %#x, device %p, adjacency %p, "
4118 "materials %p, effect_instances %p, num_materials %p, mesh %p.\n",
4120 materials, effect_instances, num_materials, mesh);
4121
4122 resinfo = FindResourceA(module, name, type);
4123 if (!resinfo) return D3DXERR_INVALIDDATA;
4124
4126 if (FAILED(hr)) return D3DXERR_INVALIDDATA;
4127
4128 return D3DXLoadMeshFromXInMemory(buffer, size, options, device, adjacency,
4129 materials, effect_instances, num_materials, mesh);
4130}
4131
4133{
4134 struct list entry;
4135 ID3DXMesh *mesh;
4141};
4142
4143static HRESULT parse_frame(struct ID3DXFileData *filedata, DWORD options, struct IDirect3DDevice9 *device,
4144 const D3DXMATRIX *parent_transform, struct list *container_list, DWORD provide_flags)
4145{
4146 HRESULT hr;
4147 D3DXMATRIX transform = *parent_transform;
4148 ID3DXFileData *child;
4149 GUID type;
4150 SIZE_T i, nb_children;
4151
4152 hr = filedata->lpVtbl->GetChildren(filedata, &nb_children);
4153 if (FAILED(hr))
4154 return hr;
4155
4156 for (i = 0; i < nb_children; i++)
4157 {
4158 hr = filedata->lpVtbl->GetChild(filedata, i, &child);
4159 if (FAILED(hr))
4160 return hr;
4161 hr = child->lpVtbl->GetType(child, &type);
4162 if (FAILED(hr))
4163 goto err;
4164
4165 if (IsEqualGUID(&type, &TID_D3DRMMesh)) {
4167 if (!container)
4168 {
4169 hr = E_OUTOFMEMORY;
4170 goto err;
4171 }
4172 list_add_tail(container_list, &container->entry);
4173 container->transform = transform;
4174
4176 (provide_flags & PROVIDE_ADJACENCY) ? &container->adjacency : NULL,
4177 (provide_flags & PROVIDE_MATERIALS) ? &container->materials : NULL,
4178 NULL, &container->num_materials, NULL, &container->mesh);
4179 } else if (IsEqualGUID(&type, &TID_D3DRMFrameTransformMatrix)) {
4180 D3DXMATRIX new_transform;
4181 hr = parse_transform_matrix(child, &new_transform);
4182 D3DXMatrixMultiply(&transform, &transform, &new_transform);
4183 } else if (IsEqualGUID(&type, &TID_D3DRMFrame)) {
4184 hr = parse_frame(child, options, device, &transform, container_list, provide_flags);
4185 }
4186 if (FAILED(hr))
4187 goto err;
4188
4189 IUnknown_Release(child);
4190 }
4191 return D3D_OK;
4192
4193err:
4194 IUnknown_Release(child);
4195 return hr;
4196}
4197
4199 struct IDirect3DDevice9 *device, struct ID3DXBuffer **adjacency_out, struct ID3DXBuffer **materials_out,
4200 struct ID3DXBuffer **effects_out, DWORD *num_materials_out, struct ID3DXMesh **mesh_out)
4201{
4202 HRESULT hr;
4203 ID3DXFile *d3dxfile = NULL;
4204 ID3DXFileEnumObject *enumobj = NULL;
4205 ID3DXFileData *filedata = NULL;
4210 struct list container_list = LIST_INIT(container_list);
4211 struct mesh_container *container_ptr, *next_container_ptr;
4213 DWORD num_faces, num_vertices;
4215 DWORD provide_flags = 0;
4216 DWORD fvf;
4217 ID3DXMesh *concat_mesh = NULL;
4219 BYTE *concat_vertices = NULL;
4220 void *concat_indices = NULL;
4221 DWORD index_offset;
4222 DWORD concat_vertex_size;
4223 SIZE_T i, nb_children;
4224 GUID guid;
4225
4226 TRACE("(%p, %u, %x, %p, %p, %p, %p, %p, %p)\n", memory, memory_size, options,
4227 device, adjacency_out, materials_out, effects_out, num_materials_out, mesh_out);
4228
4229 if (!memory || !memory_size || !device || !mesh_out)
4230 return D3DERR_INVALIDCALL;
4231
4232 hr = D3DXFileCreate(&d3dxfile);
4233 if (FAILED(hr)) goto cleanup;
4234
4235 hr = d3dxfile->lpVtbl->RegisterTemplates(d3dxfile, D3DRM_XTEMPLATES, D3DRM_XTEMPLATE_BYTES);
4236 if (FAILED(hr)) goto cleanup;
4237
4238 source.lpMemory = (void*)memory;
4239 source.dSize = memory_size;
4240 hr = d3dxfile->lpVtbl->CreateEnumObject(d3dxfile, &source, D3DXF_FILELOAD_FROMMEMORY, &enumobj);
4241 if (FAILED(hr)) goto cleanup;
4242
4243 D3DXMatrixIdentity(&identity);
4244 if (adjacency_out) provide_flags |= PROVIDE_ADJACENCY;
4245 if (materials_out || effects_out) provide_flags |= PROVIDE_MATERIALS;
4246
4247 hr = enumobj->lpVtbl->GetChildren(enumobj, &nb_children);
4248 if (FAILED(hr))
4249 goto cleanup;
4250
4251 for (i = 0; i < nb_children; i++)
4252 {
4253 hr = enumobj->lpVtbl->GetChild(enumobj, i, &filedata);
4254 if (FAILED(hr))
4255 goto cleanup;
4256
4257 hr = filedata->lpVtbl->GetType(filedata, &guid);
4258 if (SUCCEEDED(hr)) {
4259 if (IsEqualGUID(&guid, &TID_D3DRMMesh)) {
4260 container_ptr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*container_ptr));
4261 if (!container_ptr) {
4262 hr = E_OUTOFMEMORY;
4263 goto cleanup;
4264 }
4265 list_add_tail(&container_list, &container_ptr->entry);
4266 D3DXMatrixIdentity(&container_ptr->transform);
4267
4269 (provide_flags & PROVIDE_ADJACENCY) ? &container_ptr->adjacency : NULL,
4270 (provide_flags & PROVIDE_MATERIALS) ? &container_ptr->materials : NULL,
4271 NULL, &container_ptr->num_materials, NULL, &container_ptr->mesh);
4272 } else if (IsEqualGUID(&guid, &TID_D3DRMFrame)) {
4273 hr = parse_frame(filedata, options, device, &identity, &container_list, provide_flags);
4274 }
4275 if (FAILED(hr)) goto cleanup;
4276 }
4277 filedata->lpVtbl->Release(filedata);
4278 filedata = NULL;
4279 if (FAILED(hr))
4280 goto cleanup;
4281 }
4282
4283 enumobj->lpVtbl->Release(enumobj);
4284 enumobj = NULL;
4285 d3dxfile->lpVtbl->Release(d3dxfile);
4286 d3dxfile = NULL;
4287
4288 if (list_empty(&container_list)) {
4289 hr = E_FAIL;
4290 goto cleanup;
4291 }
4292
4293 fvf = D3DFVF_XYZ;
4294 num_faces = 0;
4295 num_vertices = 0;
4296 num_materials = 0;
4297 LIST_FOR_EACH_ENTRY(container_ptr, &container_list, struct mesh_container, entry)
4298 {
4299 ID3DXMesh *mesh = container_ptr->mesh;
4300 fvf |= mesh->lpVtbl->GetFVF(mesh);
4301 num_faces += mesh->lpVtbl->GetNumFaces(mesh);
4302 num_vertices += mesh->lpVtbl->GetNumVertices(mesh);
4303 num_materials += container_ptr->num_materials;
4304 }
4305
4306 hr = D3DXCreateMeshFVF(num_faces, num_vertices, options, fvf, device, &concat_mesh);
4307 if (FAILED(hr)) goto cleanup;
4308
4309 hr = concat_mesh->lpVtbl->GetDeclaration(concat_mesh, concat_decl);
4310 if (FAILED(hr)) goto cleanup;
4311
4312 concat_vertex_size = D3DXGetDeclVertexSize(concat_decl, 0);
4313
4314 hr = concat_mesh->lpVtbl->LockVertexBuffer(concat_mesh, 0, (void**)&concat_vertices);
4315 if (FAILED(hr)) goto cleanup;
4316
4317 LIST_FOR_EACH_ENTRY(container_ptr, &container_list, struct mesh_container, entry)
4318 {
4320 ID3DXMesh *mesh = container_ptr->mesh;
4321 DWORD num_mesh_vertices = mesh->lpVtbl->GetNumVertices(mesh);
4322 DWORD mesh_vertex_size;
4323 const BYTE *mesh_vertices;
4324 DWORD i;
4325
4326 hr = mesh->lpVtbl->GetDeclaration(mesh, mesh_decl);
4327 if (FAILED(hr)) goto cleanup;
4328
4329 mesh_vertex_size = D3DXGetDeclVertexSize(mesh_decl, 0);
4330
4331 hr = mesh->lpVtbl->LockVertexBuffer(mesh, D3DLOCK_READONLY, (void**)&mesh_vertices);
4332 if (FAILED(hr)) goto cleanup;
4333
4334 for (i = 0; i < num_mesh_vertices; i++) {
4335 int j;
4336 int k = 1;
4337
4338 D3DXVec3TransformCoord((D3DXVECTOR3*)concat_vertices,
4339 (D3DXVECTOR3*)mesh_vertices,
4340 &container_ptr->transform);
4341 for (j = 1; concat_decl[j].Stream != 0xff; j++)
4342 {
4343 if (concat_decl[j].Usage == mesh_decl[k].Usage &&
4344 concat_decl[j].UsageIndex == mesh_decl[k].UsageIndex)
4345 {
4346 if (concat_decl[j].Usage == D3DDECLUSAGE_NORMAL) {
4347 D3DXVec3TransformCoord((D3DXVECTOR3*)(concat_vertices + concat_decl[j].Offset),
4348 (D3DXVECTOR3*)(mesh_vertices + mesh_decl[k].Offset),
4349 &container_ptr->transform);
4350 } else {
4351 memcpy(concat_vertices + concat_decl[j].Offset,
4352 mesh_vertices + mesh_decl[k].Offset,
4353 d3dx_decltype_size[mesh_decl[k].Type]);
4354 }
4355 k++;
4356 }
4357 }
4358 mesh_vertices += mesh_vertex_size;
4359 concat_vertices += concat_vertex_size;
4360 }
4361
4362 mesh->lpVtbl->UnlockVertexBuffer(mesh);
4363 }
4364
4365 concat_mesh->lpVtbl->UnlockVertexBuffer(concat_mesh);
4366 concat_vertices = NULL;
4367
4368 hr = concat_mesh->lpVtbl->LockIndexBuffer(concat_mesh, 0, &concat_indices);
4369 if (FAILED(hr)) goto cleanup;
4370
4371 index_offset = 0;
4372 LIST_FOR_EACH_ENTRY(container_ptr, &container_list, struct mesh_container, entry)
4373 {
4374 ID3DXMesh *mesh = container_ptr->mesh;
4375 const void *mesh_indices;
4376 DWORD num_mesh_faces = mesh->lpVtbl->GetNumFaces(mesh);
4377 DWORD i;
4378
4379 hr = mesh->lpVtbl->LockIndexBuffer(mesh, D3DLOCK_READONLY, (void**)&mesh_indices);
4380 if (FAILED(hr)) goto cleanup;
4381
4382 if (options & D3DXMESH_32BIT) {
4383 DWORD *dest = concat_indices;
4384 const DWORD *src = mesh_indices;
4385 for (i = 0; i < num_mesh_faces * 3; i++)
4386 *dest++ = index_offset + *src++;
4387 concat_indices = dest;
4388 } else {
4389 WORD *dest = concat_indices;
4390 const WORD *src = mesh_indices;
4391 for (i = 0; i < num_mesh_faces * 3; i++)
4392 *dest++ = index_offset + *src++;
4393 concat_indices = dest;
4394 }
4395 mesh->lpVtbl->UnlockIndexBuffer(mesh);
4396
4397 index_offset += num_mesh_faces * 3;
4398 }
4399
4400 concat_mesh->lpVtbl->UnlockIndexBuffer(concat_mesh);
4401 concat_indices = NULL;
4402
4403 if (num_materials) {
4404 DWORD *concat_attrib_buffer = NULL;
4405 DWORD offset = 0;
4406
4407 hr = concat_mesh->lpVtbl->LockAttributeBuffer(concat_mesh, 0, &concat_attrib_buffer);
4408 if (FAILED(hr)) goto cleanup;
4409
4410 LIST_FOR_EACH_ENTRY(container_ptr, &container_list, struct mesh_container, entry)
4411 {
4412 ID3DXMesh *mesh = container_ptr->mesh;
4413 const DWORD *mesh_attrib_buffer = NULL;
4414 DWORD count = mesh->lpVtbl->GetNumFaces(mesh);
4415
4416 hr = mesh->lpVtbl->LockAttributeBuffer(mesh, D3DLOCK_READONLY, (DWORD**)&mesh_attrib_buffer);
4417 if (FAILED(hr)) {
4418 concat_mesh->lpVtbl->UnlockAttributeBuffer(concat_mesh);
4419 goto cleanup;
4420 }
4421
4422 while (count--)
4423 *concat_attrib_buffer++ = offset + *mesh_attrib_buffer++;
4424
4425 mesh->lpVtbl->UnlockAttributeBuffer(mesh);
4426 offset += container_ptr->num_materials;
4427 }
4428 concat_mesh->lpVtbl->UnlockAttributeBuffer(concat_mesh);
4429 }
4430
4431 if (materials_out || effects_out) {
4432 D3DXMATERIAL *out_ptr;
4433 if (!num_materials) {
4434 /* create default material */
4436 if (FAILED(hr)) goto cleanup;
4437
4439 out_ptr->MatD3D.Diffuse.r = 0.5f;
4440 out_ptr->MatD3D.Diffuse.g = 0.5f;
4441 out_ptr->MatD3D.Diffuse.b = 0.5f;
4442 out_ptr->MatD3D.Specular.r = 0.5f;
4443 out_ptr->MatD3D.Specular.g = 0.5f;
4444 out_ptr->MatD3D.Specular.b = 0.5f;
4445 /* D3DXCreateBuffer initializes the rest to zero */
4446 } else {
4448 char *strings_out_ptr;
4449
4450 LIST_FOR_EACH_ENTRY(container_ptr, &container_list, struct mesh_container, entry)
4451 {
4452 if (container_ptr->materials) {
4453 DWORD i;
4454 const D3DXMATERIAL *in_ptr = ID3DXBuffer_GetBufferPointer(container_ptr->materials);
4455 for (i = 0; i < container_ptr->num_materials; i++)
4456 {
4457 if (in_ptr->pTextureFilename)
4458 buffer_size += strlen(in_ptr->pTextureFilename) + 1;
4459 in_ptr++;
4460 }
4461 }
4462 }
4463
4465 if (FAILED(hr)) goto cleanup;
4467 strings_out_ptr = (char*)(out_ptr + num_materials);
4468
4469 LIST_FOR_EACH_ENTRY(container_ptr, &container_list, struct mesh_container, entry)
4470 {
4471 if (container_ptr->materials) {
4472 DWORD i;
4473 const D3DXMATERIAL *in_ptr = ID3DXBuffer_GetBufferPointer(container_ptr->materials);
4474 for (i = 0; i < container_ptr->num_materials; i++)
4475 {
4476 out_ptr->MatD3D = in_ptr->MatD3D;
4477 if (in_ptr->pTextureFilename) {
4478 out_ptr->pTextureFilename = strings_out_ptr;
4479 strcpy(out_ptr->pTextureFilename, in_ptr->pTextureFilename);
4480 strings_out_ptr += strlen(in_ptr->pTextureFilename) + 1;
4481 }
4482 in_ptr++;
4483 out_ptr++;
4484 }
4485 }
4486 }
4487 }
4488 }
4489 if (!num_materials)
4490 num_materials = 1;
4491
4492 if (effects_out) {
4494 if (!materials_out) {
4496 materials = NULL;
4497 }
4498 }
4499
4500 if (adjacency_out) {
4501 if (!list_next(&container_list, list_head(&container_list))) {
4502 container_ptr = LIST_ENTRY(list_head(&container_list), struct mesh_container, entry);
4503 adjacency = container_ptr->adjacency;
4504 container_ptr->adjacency = NULL;
4505 } else {
4506 DWORD offset = 0;
4507 DWORD *out_ptr;
4508
4509 hr = D3DXCreateBuffer(num_faces * 3 * sizeof(DWORD), &adjacency);
4510 if (FAILED(hr)) goto cleanup;
4511
4513 LIST_FOR_EACH_ENTRY(container_ptr, &container_list, struct mesh_container, entry)
4514 {
4515 DWORD i;
4516 DWORD count = 3 * container_ptr->mesh->lpVtbl->GetNumFaces(container_ptr->mesh);
4517 DWORD *in_ptr = ID3DXBuffer_GetBufferPointer(container_ptr->adjacency);
4518
4519 for (i = 0; i < count; i++)
4520 *out_ptr++ = offset + *in_ptr++;
4521
4522 offset += count;
4523 }
4524 }
4525 }
4526
4527 *mesh_out = concat_mesh;
4528 if (adjacency_out) *adjacency_out = adjacency;
4529 if (materials_out) *materials_out = materials;
4530 if (effects_out) *effects_out = effects;
4531 if (num_materials_out) *num_materials_out = num_materials;
4532
4533 hr = D3D_OK;
4534cleanup:
4535 if (concat_indices) concat_mesh->lpVtbl->UnlockIndexBuffer(concat_mesh);
4536 if (concat_vertices) concat_mesh->lpVtbl->UnlockVertexBuffer(concat_mesh);
4537 if (filedata) filedata->lpVtbl->Release(filedata);
4538 if (enumobj) enumobj->lpVtbl->Release(enumobj);
4539 if (d3dxfile) d3dxfile->lpVtbl->Release(d3dxfile);
4540 if (FAILED(hr)) {
4541 if (concat_mesh) IUnknown_Release(concat_mesh);
4545 }
4546 LIST_FOR_EACH_ENTRY_SAFE(container_ptr, next_container_ptr, &container_list, struct mesh_container, entry)
4547 {
4548 if (container_ptr->mesh) IUnknown_Release(container_ptr->mesh);
4549 if (container_ptr->adjacency) ID3DXBuffer_Release(container_ptr->adjacency);
4550 if (container_ptr->materials) ID3DXBuffer_Release(container_ptr->materials);
4551 if (container_ptr->effects) ID3DXBuffer_Release(container_ptr->effects);
4552 HeapFree(GetProcessHeap(), 0, container_ptr);
4553 }
4554 return hr;
4555}
4556
4558{
4561};
4562
4563HRESULT WINAPI D3DXCreatePolygon(struct IDirect3DDevice9 *device, float length, UINT sides,
4564 struct ID3DXMesh **mesh, struct ID3DXBuffer **adjacency)
4565{
4566 HRESULT hr;
4567 ID3DXMesh *polygon;
4568 struct vertex *vertices;
4569 WORD (*faces)[3];
4570 DWORD (*adjacency_buf)[3];
4571 float angle, scale;
4572 unsigned int i;
4573
4574 TRACE("device %p, length %f, sides %u, mesh %p, adjacency %p.\n",
4575 device, length, sides, mesh, adjacency);
4576
4577 if (!device || length < 0.0f || sides < 3 || !mesh)
4578 return D3DERR_INVALIDCALL;
4579
4580 if (FAILED(hr = D3DXCreateMeshFVF(sides, sides + 1, D3DXMESH_MANAGED,
4581 D3DFVF_XYZ | D3DFVF_NORMAL, device, &polygon)))
4582 {
4583 return hr;
4584 }
4585
4586 if (FAILED(hr = polygon->lpVtbl->LockVertexBuffer(polygon, 0, (void **)&vertices)))
4587 {
4588 polygon->lpVtbl->Release(polygon);
4589 return hr;
4590 }
4591
4592 if (FAILED(hr = polygon->lpVtbl->LockIndexBuffer(polygon, 0, (void **)&faces)))
4593 {
4594 polygon->lpVtbl->UnlockVertexBuffer(polygon);
4595 polygon->lpVtbl->Release(polygon);
4596 return hr;
4597 }
4598
4599 angle = D3DX_PI / sides;
4600 scale = 0.5f * length / sinf(angle);
4601 angle *= 2.0f;
4602
4603 vertices[0].position.x = 0.0f;
4604 vertices[0].position.y = 0.0f;
4605 vertices[0].position.z = 0.0f;
4606 vertices[0].normal.x = 0.0f;
4607 vertices[0].normal.y = 0.0f;
4608 vertices[0].normal.z = 1.0f;
4609
4610 for (i = 0; i < sides; ++i)
4611 {
4612 vertices[i + 1].position.x = cosf(angle * i) * scale;
4613 vertices[i + 1].position.y = sinf(angle * i) * scale;
4614 vertices[i + 1].position.z = 0.0f;
4615 vertices[i + 1].normal.x = 0.0f;
4616 vertices[i + 1].normal.y = 0.0f;
4617 vertices[i + 1].normal.z = 1.0f;
4618
4619 faces[i][0] = 0;
4620 faces[i][1] = i + 1;
4621 faces[i][2] = i + 2;
4622 }
4623
4624 faces[sides - 1][2] = 1;
4625
4626 polygon->lpVtbl->UnlockVertexBuffer(polygon);
4627 polygon->lpVtbl->UnlockIndexBuffer(polygon);
4628
4629 if (adjacency)
4630 {
4631 if (FAILED(hr = D3DXCreateBuffer(sides * sizeof(DWORD) * 3, adjacency)))
4632 {
4633 polygon->lpVtbl->Release(polygon);
4634 return hr;
4635 }
4636
4637 adjacency_buf = ID3DXBuffer_GetBufferPointer(*adjacency);
4638 for (i = 0; i < sides; ++i)
4639 {
4640 adjacency_buf[i][0] = i - 1;
4641 adjacency_buf[i][1] = ~0U;
4642 adjacency_buf[i][2] = i + 1;
4643 }
4644 adjacency_buf[0][0] = sides - 1;
4645 adjacency_buf[sides - 1][2] = 0;
4646 }
4647
4648 *mesh = polygon;
4649
4650 return D3D_OK;
4651}
4652
4653HRESULT WINAPI D3DXCreateBox(struct IDirect3DDevice9 *device, float width, float height,
4654 float depth, struct ID3DXMesh **mesh, struct ID3DXBuffer **adjacency)
4655{
4656 HRESULT hr;
4657 ID3DXMesh *box;
4658 struct vertex *vertices;
4659 WORD (*faces)[3];
4660 DWORD *adjacency_buf;
4661 unsigned int i, face;
4662 static const D3DXVECTOR3 unit_box[] =
4663 {
4664 {-0.5f, -0.5f, -0.5f}, {-0.5f, -0.5f, 0.5f}, {-0.5f, 0.5f, 0.5f}, {-0.5f, 0.5f, -0.5f},
4665 {-0.5f, 0.5f, -0.5f}, {-0.5f, 0.5f, 0.5f}, { 0.5f, 0.5f, 0.5f}, { 0.5f, 0.5f, -0.5f},
4666 { 0.5f, 0.5f, -0.5f}, { 0.5f, 0.5f, 0.5f}, { 0.5f, -0.5f, 0.5f}, { 0.5f, -0.5f, -0.5f},
4667 {-0.5f, -0.5f, 0.5f}, {-0.5f, -0.5f, -0.5f}, { 0.5f, -0.5f, -0.5f}, { 0.5f, -0.5f, 0.5f},
4668 {-0.5f, -0.5f, 0.5f}, { 0.5f, -0.5f, 0.5f}, { 0.5f, 0.5f, 0.5f}, {-0.5f, 0.5f, 0.5f},
4669 {-0.5f, -0.5f, -0.5f}, {-0.5f, 0.5f, -0.5f}, { 0.5f, 0.5f, -0.5f}, { 0.5f, -0.5f, -0.5f}
4670 };
4671 static const D3DXVECTOR3 normals[] =
4672 {
4673 {-1.0f, 0.0f, 0.0f}, { 0.0f, 1.0f, 0.0f}, { 1.0f, 0.0f, 0.0f},
4674 { 0.0f, -1.0f, 0.0f}, { 0.0f, 0.0f, 1.0f}, { 0.0f, 0.0f, -1.0f}
4675 };
4676 static const DWORD adjacency_table[] =
4677 {
4678 6, 9, 1, 2, 10, 0, 1, 9, 3, 4, 10, 2,
4679 3, 8, 5, 7, 11, 4, 0, 11, 7, 5, 8, 6,
4680 7, 4, 9, 2, 0, 8, 1, 3, 11, 5, 6, 10
4681 };
4682
4683 TRACE("device %p, width %f, height %f, depth %f, mesh %p, adjacency %p\n",
4684 device, width, height, depth, mesh, adjacency);
4685
4686 if (!device || width < 0.0f || height < 0.0f || depth < 0.0f || !mesh)
4687 {
4688 return D3DERR_INVALIDCALL;
4689 }
4690
4692 {
4693 return hr;
4694 }
4695
4696 if (FAILED(hr = box->lpVtbl->LockVertexBuffer(box, 0, (void **)&vertices)))
4697 {
4698 box->lpVtbl->Release(box);
4699 return hr;
4700 }
4701
4702 if (FAILED(hr = box->lpVtbl->LockIndexBuffer(box, 0, (void **)&faces)))
4703 {
4704 box->lpVtbl->UnlockVertexBuffer(box);
4705 box->lpVtbl->Release(box);
4706 return hr;
4707 }
4708
4709 for (i = 0; i < 24; i++)
4710 {
4711 vertices[i].position.x = width * unit_box[i].x;
4712 vertices[i].position.y = height * unit_box[i].y;
4713 vertices[i].position.z = depth * unit_box[i].z;
4714 vertices[i].normal.x = normals[i / 4].x;
4715 vertices[i].normal.y = normals[i / 4].y;
4716 vertices[i].normal.z = normals[i / 4].z;
4717 }
4718
4719 face = 0;
4720 for (i = 0; i < 12; i++)
4721 {
4722 faces[i][0] = face++;
4723 faces[i][1] = face++;
4724 faces[i][2] = (i % 2) ? face - 4 : face;
4725 }
4726
4727 box->lpVtbl->UnlockIndexBuffer(box);
4728 box->lpVtbl->UnlockVertexBuffer(box);
4729
4730 if (adjacency)
4731 {
4732 if (FAILED(hr = D3DXCreateBuffer(sizeof(adjacency_table), adjacency)))
4733 {
4734 box->lpVtbl->Release(box);
4735 return hr;
4736 }
4737
4738 adjacency_buf = ID3DXBuffer_GetBufferPointer(*adjacency);
4739 memcpy(adjacency_buf, adjacency_table, sizeof(adjacency_table));
4740 }
4741
4742 *mesh = box;
4743
4744 return D3D_OK;
4745}
4746
4747typedef WORD face[3];
4748
4750{
4751 float *sin;
4752 float *cos;
4753};
4754
4756{
4759}
4760
4761/* pre compute sine and cosine tables; caller must free */
4762static BOOL compute_sincos_table(struct sincos_table *sincos_table, float angle_start, float angle_step, int n)
4763{
4764 float angle;
4765 int i;
4766
4768 if (!sincos_table->sin)
4769 {
4770 return FALSE;
4771 }
4773 if (!sincos_table->cos)
4774 {
4776 return FALSE;
4777 }
4778
4779 angle = angle_start;
4780 for (i = 0; i < n; i++)
4781 {
4784 angle += angle_step;
4785 }
4786
4787 return TRUE;
4788}
4789
4790static WORD vertex_index(UINT slices, int slice, int stack)
4791{
4792 return stack*slices+slice+1;
4793}
4794
4795HRESULT WINAPI D3DXCreateSphere(struct IDirect3DDevice9 *device, float radius, UINT slices,
4796 UINT stacks, struct ID3DXMesh **mesh, struct ID3DXBuffer **adjacency)
4797{
4798 DWORD number_of_vertices, number_of_faces;
4799 HRESULT hr;
4800 ID3DXMesh *sphere;
4801 struct vertex *vertices;
4802 face *faces;
4803 float phi_step, phi_start;
4804 struct sincos_table phi;
4805 float theta_step, theta, sin_theta, cos_theta;
4807
4808 TRACE("(%p, %f, %u, %u, %p, %p)\n", device, radius, slices, stacks, mesh, adjacency);
4809
4810 if (!device || radius < 0.0f || slices < 2 || stacks < 2 || !mesh)
4811 {
4812 return D3DERR_INVALIDCALL;
4813 }
4814
4815 number_of_vertices = 2 + slices * (stacks-1);
4816 number_of_faces = 2 * slices + (stacks - 2) * (2 * slices);
4817
4818 hr = D3DXCreateMeshFVF(number_of_faces, number_of_vertices, D3DXMESH_MANAGED,
4819 D3DFVF_XYZ | D3DFVF_NORMAL, device, &sphere);
4820 if (FAILED(hr))
4821 {
4822 return hr;
4823 }
4824
4825 if (FAILED(hr = sphere->lpVtbl->LockVertexBuffer(sphere, 0, (void **)&vertices)))
4826 {
4827 sphere->lpVtbl->Release(sphere);
4828 return hr;
4829 }
4830
4831 if (FAILED(hr = sphere->lpVtbl->LockIndexBuffer(sphere, 0, (void **)&faces)))
4832 {
4833 sphere->lpVtbl->UnlockVertexBuffer(sphere);
4834 sphere->lpVtbl->Release(sphere);
4835 return hr;
4836 }
4837
4838 /* phi = angle on xz plane wrt z axis */
4839 phi_step = -2.0f * D3DX_PI / slices;
4840 phi_start = D3DX_PI / 2.0f;
4841
4842 if (!compute_sincos_table(&phi, phi_start, phi_step, slices))
4843 {
4844 sphere->lpVtbl->UnlockIndexBuffer(sphere);
4845 sphere->lpVtbl->UnlockVertexBuffer(sphere);
4846 sphere->lpVtbl->Release(sphere);
4847 return E_OUTOFMEMORY;
4848 }
4849
4850 /* theta = angle on xy plane wrt x axis */
4851 theta_step = D3DX_PI / stacks;
4852 theta = theta_step;
4853
4854 vertex = 0;
4855 face = 0;
4856
4857 vertices[vertex].normal.x = 0.0f;
4858 vertices[vertex].normal.y = 0.0f;
4859 vertices[vertex].normal.z = 1.0f;
4860 vertices[vertex].position.x = 0.0f;
4861 vertices[vertex].position.y = 0.0f;
4862 vertices[vertex].position.z = radius;
4863 vertex++;
4864
4865 for (stack = 0; stack < stacks - 1; stack++)
4866 {
4867 sin_theta = sinf(theta);
4868 cos_theta = cosf(theta);
4869
4870 for (slice = 0; slice < slices; slice++)
4871 {
4872 vertices[vertex].normal.x = sin_theta * phi.cos[slice];
4873 vertices[vertex].normal.y = sin_theta * phi.sin[slice];
4874 vertices[vertex].normal.z = cos_theta;
4875 vertices[vertex].position.x = radius * sin_theta * phi.cos[slice];
4876 vertices[vertex].position.y = radius * sin_theta * phi.sin[slice];
4877 vertices[vertex].position.z = radius * cos_theta;
4878 vertex++;
4879
4880 if (slice > 0)
4881 {
4882 if (stack == 0)
4883 {
4884 /* top stack is triangle fan */
4885 faces[face][0] = 0;
4886 faces[face][1] = slice + 1;
4887 faces[face][2] = slice;
4888 face++;
4889 }
4890 else
4891 {
4892 /* stacks in between top and bottom are quad strips */
4893 faces[face][0] = vertex_index(slices, slice-1, stack-1);
4894 faces[face][1] = vertex_index(slices, slice, stack-1);
4895 faces[face][2] = vertex_index(slices, slice-1, stack);
4896 face++;
4897
4898 faces[face][0] = vertex_index(slices, slice, stack-1);
4899 faces[face][1] = vertex_index(slices, slice, stack);
4900 faces[face][2] = vertex_index(slices, slice-1, stack);
4901 face++;
4902 }
4903 }
4904 }
4905
4906 theta += theta_step;
4907
4908 if (stack == 0)
4909 {
4910 faces[face][0] = 0;
4911 faces[face][1] = 1;
4912 faces[face][2] = slice;
4913 face++;
4914 }
4915 else
4916 {
4917 faces[face][0] = vertex_index(slices, slice-1, stack-1);
4918 faces[face][1] = vertex_index(slices, 0, stack-1);
4919 faces[face][2] = vertex_index(slices, slice-1, stack);
4920 face++;
4921
4922 faces[face][0] = vertex_index(slices, 0, stack-1);
4923 faces[face][1] = vertex_index(slices, 0, stack);
4924 faces[face][2] = vertex_index(slices, slice-1, stack);
4925 face++;
4926 }
4927 }
4928
4929 vertices[vertex].position.x = 0.0f;
4930 vertices[vertex].position.y = 0.0f;
4931 vertices[vertex].position.z = -radius;
4932 vertices[vertex].normal.x = 0.0f;
4933 vertices[vertex].normal.y = 0.0f;
4934 vertices[vertex].normal.z = -1.0f;
4935
4936 /* bottom stack is triangle fan */
4937 for (slice = 1; slice < slices; slice++)
4938 {
4939 faces[face][0] = vertex_index(slices, slice-1, stack-1);
4940 faces[face][1] = vertex_index(slices, slice, stack-1);
4941 faces[face][2] = vertex;
4942 face++;
4943 }
4944
4945 faces[face][0] = vertex_index(slices, slice-1, stack-1);
4946 faces[face][1] = vertex_index(slices, 0, stack-1);
4947 faces[face][2] = vertex;
4948
4949 free_sincos_table(&phi);
4950 sphere->lpVtbl->UnlockIndexBuffer(sphere);
4951 sphere->lpVtbl->UnlockVertexBuffer(sphere);
4952
4953
4954 if (adjacency)
4955 {
4956 if (FAILED(hr = D3DXCreateBuffer(number_of_faces * sizeof(DWORD) * 3, adjacency)))
4957 {
4958 sphere->lpVtbl->Release(sphere);
4959 return hr;
4960 }
4961
4962 if (FAILED(hr = sphere->lpVtbl->GenerateAdjacency(sphere, 0.0f, (*adjacency)->lpVtbl->GetBufferPointer(*adjacency))))
4963 {
4964 (*adjacency)->lpVtbl->Release(*adjacency);
4965 sphere->lpVtbl->Release(sphere);
4966 return hr;
4967 }
4968 }
4969
4970 *mesh = sphere;
4971
4972 return D3D_OK;
4973}
4974
4975HRESULT WINAPI D3DXCreateCylinder(struct IDirect3DDevice9 *device, float radius1, float radius2,
4976 float length, UINT slices, UINT stacks, struct ID3DXMesh **mesh, struct ID3DXBuffer **adjacency)
4977{
4978 DWORD number_of_vertices, number_of_faces;
4979 HRESULT hr;
4980 ID3DXMesh *cylinder;
4981 struct vertex *vertices;
4982 face *faces;
4983 float theta_step, theta_start;
4984 struct sincos_table theta;
4985 float delta_radius, radius, radius_step;
4986 float z, z_step, z_normal;
4988
4989 TRACE("(%p, %f, %f, %f, %u, %u, %p, %p)\n", device, radius1, radius2, length, slices, stacks, mesh, adjacency);
4990
4991 if (device == NULL || radius1 < 0.0f || radius2 < 0.0f || length < 0.0f || slices < 2 || stacks < 1 || mesh == NULL)
4992 {
4993 return D3DERR_INVALIDCALL;
4994 }
4995
4996 number_of_vertices = 2 + (slices * (3 + stacks));
4997 number_of_faces = 2 * slices + stacks * (2 * slices);
4998
4999 hr = D3DXCreateMeshFVF(number_of_faces, number_of_vertices, D3DXMESH_MANAGED,
5001 if (FAILED(hr))
5002 {
5003 return hr;
5004 }
5005
5006 if (FAILED(hr = cylinder->lpVtbl->LockVertexBuffer(cylinder, 0, (void **)&vertices)))
5007 {
5008 cylinder->lpVtbl->Release(cylinder);
5009 return hr;
5010 }
5011
5012 if (FAILED(hr = cylinder->lpVtbl->LockIndexBuffer(cylinder, 0, (void **)&faces)))
5013 {
5014 cylinder->lpVtbl->UnlockVertexBuffer(cylinder);
5015 cylinder->lpVtbl->Release(cylinder);
5016 return hr;
5017 }
5018
5019 /* theta = angle on xy plane wrt x axis */
5020 theta_step = -2.0f * D3DX_PI / slices;
5021 theta_start = D3DX_PI / 2.0f;
5022
5023 if (!compute_sincos_table(&theta, theta_start, theta_step, slices))
5024 {
5025 cylinder->lpVtbl->UnlockIndexBuffer(cylinder);
5026 cylinder->lpVtbl->UnlockVertexBuffer(cylinder);
5027 cylinder->lpVtbl->Release(cylinder);
5028 return E_OUTOFMEMORY;
5029 }
5030
5031 vertex = 0;
5032 face = 0;
5033
5034 delta_radius = radius1 - radius2;
5035 radius = radius1;
5036 radius_step = delta_radius / stacks;
5037
5038 z = -length / 2;
5039 z_step = length / stacks;
5040 z_normal = delta_radius / length;
5041 if (isnan(z_normal))
5042 {
5043 z_normal = 0.0f;
5044 }
5045
5046 vertices[vertex].normal.x = 0.0f;
5047 vertices[vertex].normal.y = 0.0f;
5048 vertices[vertex].normal.z = -1.0f;
5049 vertices[vertex].position.x = 0.0f;
5050 vertices[vertex].position.y = 0.0f;
5051 vertices[vertex++].position.z = z;
5052
5053 for (slice = 0; slice < slices; slice++, vertex++)
5054 {
5055 vertices[vertex].normal.x = 0.0f;
5056 vertices[vertex].normal.y = 0.0f;
5057 vertices[vertex].normal.z = -1.0f;
5058 vertices[vertex].position.x = radius * theta.cos[slice];
5059 vertices[vertex].position.y = radius * theta.sin[slice];
5060 vertices[vertex].position.z = z;
5061
5062 if (slice > 0)
5063 {
5064 faces[face][0] = 0;
5065 faces[face][1] = slice;
5066 faces[face++][2] = slice + 1;
5067 }
5068 }
5069
5070 faces[face][0] = 0;
5071 faces[face][1] = slice;
5072 faces[face++][2] = 1;
5073
5074 for (stack = 1; stack <= stacks+1; stack++)
5075 {
5076 for (slice = 0; slice < slices; slice++, vertex++)
5077 {
5078 vertices[vertex].normal.x = theta.cos[slice];
5079 vertices[vertex].normal.y = theta.sin[slice];
5080 vertices[vertex].normal.z = z_normal;
5081 D3DXVec3Normalize(&vertices[vertex].normal, &vertices[vertex].normal);
5082 vertices[vertex].position.x = radius * theta.cos[slice];
5083 vertices[vertex].position.y = radius * theta.sin[slice];
5084 vertices[vertex].position.z = z;
5085
5086 if (stack > 1 && slice > 0)
5087 {
5088 faces[face][0] = vertex_index(slices, slice-1, stack-1);
5089 faces[face][1] = vertex_index(slices, slice-1, stack);
5090 faces[face++][2] = vertex_index(slices, slice, stack-1);
5091
5092 faces[face][0] = vertex_index(slices, slice, stack-1);
5093 faces[face][1] = vertex_index(slices, slice-1, stack);
5094 faces[face++][2] = vertex_index(slices, slice, stack);
5095 }
5096 }
5097
5098 if (stack > 1)
5099 {
5100 faces[face][0] = vertex_index(slices, slice-1, stack-1);
5101 faces[face][1] = vertex_index(slices, slice-1, stack);
5102 faces[face++][2] = vertex_index(slices, 0, stack-1);
5103
5104 faces[face][0] = vertex_index(slices, 0, stack-1);
5105 faces[face][1] = vertex_index(slices, slice-1, stack);
5106 faces[face++][2] = vertex_index(slices, 0, stack);
5107 }
5108
5109 if (stack < stacks + 1)
5110 {
5111 z += z_step;
5112 radius -= radius_step;
5113 }
5114 }
5115
5116 for (slice = 0; slice < slices; slice++, vertex++)
5117 {
5118 vertices[vertex].normal.x = 0.0f;
5119 vertices[vertex].normal.y = 0.0f;
5120 vertices[vertex].normal.z = 1.0f;
5121 vertices[vertex].position.x = radius * theta.cos[slice];
5122 vertices[vertex].position.y = radius * theta.sin[slice];
5123 vertices[vertex].position.z = z;
5124
5125 if (slice > 0)
5126 {
5127 faces[face][0] = vertex_index(slices, slice-1, stack);
5128 faces[face][1] = number_of_vertices - 1;
5129 faces[face++][2] = vertex_index(slices, slice, stack);
5130 }
5131 }
5132
5133 vertices[vertex].position.x = 0.0f;
5134 vertices[vertex].position.y = 0.0f;
5135 vertices[vertex].position.z = z;
5136 vertices[vertex].normal.x = 0.0f;
5137 vertices[vertex].normal.y = 0.0f;
5138 vertices[vertex].normal.z = 1.0f;
5139
5140 faces[face][0] = vertex_index(slices, slice-1, stack);
5141 faces[face][1] = number_of_vertices - 1;
5142 faces[face][2] = vertex_index(slices, 0, stack);
5143
5144 free_sincos_table(&theta);
5145 cylinder->lpVtbl->UnlockIndexBuffer(cylinder);
5146 cylinder->lpVtbl->UnlockVertexBuffer(cylinder);
5147
5148 if (adjacency)
5149 {
5150 if (FAILED(hr = D3DXCreateBuffer(number_of_faces * sizeof(DWORD) * 3, adjacency)))
5151 {
5152 cylinder->lpVtbl->Release(cylinder);
5153 return hr;
5154 }
5155
5156 if (FAILED(hr = cylinder->lpVtbl->GenerateAdjacency(cylinder, 0.0f, (*adjacency)->lpVtbl->GetBufferPointer(*adjacency))))
5157 {
5158 (*adjacency)->lpVtbl->Release(*adjacency);
5159 cylinder->lpVtbl->Release(cylinder);
5160 return hr;
5161 }
5162 }
5163
5164 *mesh = cylinder;
5165
5166 return D3D_OK;
5167}
5168
5169HRESULT WINAPI D3DXCreateTeapot(struct IDirect3DDevice9 *device,
5170 struct ID3DXMesh **mesh, struct ID3DXBuffer **adjacency)
5171{
5172 FIXME("device %p, mesh %p, adjacency %p semi-stub.\n", device, mesh, adjacency);
5173
5174 return D3DXCreateSphere(device, 1.0f, 4, 4, mesh, adjacency);
5175}
5176
5177HRESULT WINAPI D3DXCreateTextA(struct IDirect3DDevice9 *device, HDC hdc, const char *text, float deviation,
5178 float extrusion, struct ID3DXMesh **mesh, struct ID3DXBuffer **adjacency, GLYPHMETRICSFLOAT *glyphmetrics)
5179{
5180 WCHAR *textW;
5181 HRESULT hr;
5182 int len;
5183
5184 TRACE("device %p, hdc %p, text %s, deviation %.8e, extrusion %.8e, mesh %p, adjacency %p, glyphmetrics %p.\n",
5185 device, hdc, debugstr_a(text), deviation, extrusion, mesh, adjacency, glyphmetrics);
5186
5187 if (!text)
5188 return D3DERR_INVALIDCALL;
5189
5190 len = MultiByteToWideChar(CP_ACP, 0, text, -1, NULL, 0);
5191 textW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
5193
5194 hr = D3DXCreateTextW(device, hdc, textW, deviation, extrusion,
5195 mesh, adjacency, glyphmetrics);
5197
5198 return hr;
5199}
5200
5201HRESULT WINAPI D3DXCreateTorus(struct IDirect3DDevice9 *device,
5202 float innerradius, float outerradius, UINT sides, UINT rings, struct ID3DXMesh **mesh, ID3DXBuffer **adjacency)
5203{
5204 HRESULT hr;
5205 ID3DXMesh *torus;
5206 WORD (*faces)[3];
5207 struct vertex *vertices;
5208 float phi, phi_step, sin_phi, cos_phi;
5209 float theta, theta_step, sin_theta, cos_theta;
5210 unsigned int i, j, numvert, numfaces;
5211
5212 TRACE("device %p, innerradius %.8e, outerradius %.8e, sides %u, rings %u, mesh %p, adjacency %p.\n",
5213 device, innerradius, outerradius, sides, rings, mesh, adjacency);
5214
5215 numvert = sides * rings;
5216 numfaces = numvert * 2;
5217
5218 if (!device || innerradius < 0.0f || outerradius < 0.0f || sides < 3 || rings < 3 || !mesh)
5219 {
5220 WARN("Invalid arguments.\n");
5221 return D3DERR_INVALIDCALL;
5222 }
5223
5224 if (FAILED(hr = D3DXCreateMeshFVF(numfaces, numvert, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, device, &torus)))
5225 return hr;
5226
5227 if (FAILED(hr = torus->lpVtbl->LockVertexBuffer(torus, 0, (void **)&vertices)))
5228 {
5229 torus->lpVtbl->Release(torus);
5230 return hr;
5231 }
5232
5233 if (FAILED(hr = torus->lpVtbl->LockIndexBuffer(torus, 0, (void **)&faces)))
5234 {
5235 torus->lpVtbl->UnlockVertexBuffer(torus);
5236 torus->lpVtbl->Release(torus);
5237 return hr;
5238 }
5239
5240 phi_step = D3DX_PI / sides * 2.0f;
5241 theta_step = D3DX_PI / rings * -2.0f;
5242
5243 theta = 0.0f;
5244
5245 for (i = 0; i < rings; ++i)
5246 {
5247 phi = 0.0f;
5248
5249 sin_theta = sinf(theta);
5250 cos_theta = cosf(theta);
5251
5252 for (j = 0; j < sides; ++j)
5253 {
5254 sin_phi = sinf(phi);
5255 cos_phi = cosf(phi);
5256
5257 vertices[i * sides + j].position.x = (innerradius * cos_phi + outerradius) * cos_theta;
5258 vertices[i * sides + j].position.y = (innerradius * cos_phi + outerradius) * sin_theta;
5259 vertices[i * sides + j].position.z = innerradius * sin_phi;
5260 vertices[i * sides + j].normal.x = cos_phi * cos_theta;
5261 vertices[i * sides + j].normal.y = cos_phi * sin_theta;
5262 vertices[i * sides + j].normal.z = sin_phi;
5263
5264 phi += phi_step;
5265 }
5266
5267 theta += theta_step;
5268 }
5269
5270 for (i = 0; i < numfaces - sides * 2; ++i)
5271 {
5272 faces[i][0] = i % 2 ? i / 2 + sides : i / 2;
5273 faces[i][1] = (i / 2 + 1) % sides ? i / 2 + 1 : i / 2 + 1 - sides;
5274 faces[i][2] = (i + 1) % (sides * 2) ? (i + 1) / 2 + sides : (i + 1) / 2;
5275 }
5276
5277 for (j = 0; i < numfaces; ++i, ++j)
5278 {
5279 faces[i][0] = i % 2 ? j / 2 : i / 2;
5280 faces[i][1] = (i / 2 + 1) % sides ? i / 2 + 1 : i / 2 + 1 - sides;
5281 faces[i][2] = i == numfaces - 1 ? 0 : (j + 1) / 2;
5282 }
5283
5284 torus->lpVtbl->UnlockIndexBuffer(torus);
5285 torus->lpVtbl->UnlockVertexBuffer(torus);
5286
5287 if (adjacency)
5288 {
5289 if (FAILED(hr = D3DXCreateBuffer(numfaces * sizeof(DWORD) * 3, adjacency)))
5290 {
5291 torus->lpVtbl->Release(torus);
5292 return hr;
5293 }
5294
5295 if (FAILED(hr = torus->lpVtbl->GenerateAdjacency(torus, 0.0f, (*adjacency)->lpVtbl->GetBufferPointer(*adjacency))))
5296 {
5297 (*adjacency)->lpVtbl->Release(*adjacency);
5298 torus->lpVtbl->Release(torus);
5299 return hr;
5300 }
5301 }
5302
5303 *mesh = torus;
5304
5305 return D3D_OK;
5306}
5307
5314};
5315
5317{
5320};
5321
5323{
5325 void *items;
5326};
5327
5328/* is a dynamic_array */
5330{
5333};
5334
5335/* is a dynamic_array */
5337{
5340};
5341
5343{
5346};
5347
5349{
5352};
5353
5355{
5358};
5359
5361{
5366};
5367
5368/* is an dynamic_array */
5370{
5373};
5374
5375/* complex polygons are split into monotone polygons, which have
5376 * at most 2 intersections with the vertical sweep line */
5378{
5381};
5382
5383/* is an dynamic_array */
5385{
5388
5390};
5391
5392static BOOL reserve(struct dynamic_array *array, int count, int itemsize)
5393{
5394 if (count > array->capacity) {
5395 void *new_buffer;
5396 int new_capacity;
5397 if (array->items && array->capacity) {
5398 new_capacity = max(array->capacity * 2, count);
5399 new_buffer = HeapReAlloc(GetProcessHeap(), 0, array->items, new_capacity * itemsize);
5400 } else {
5401 new_capacity = max(16, count);
5402 new_buffer = HeapAlloc(GetProcessHeap(), 0, new_capacity * itemsize);
5403 }
5404 if (!new_buffer)
5405 return FALSE;
5406 array->items = new_buffer;
5407 array->capacity = new_capacity;
5408 }
5409 return TRUE;
5410}
5411
5412static struct point2d *add_points(struct outline *array, int num)
5413{
5414 struct point2d *item;
5415
5416 if (!reserve((struct dynamic_array *)array, array->count + num, sizeof(array->items[0])))
5417 return NULL;
5418
5419 item = &array->items[array->count];
5420 array->count += num;
5421 return item;
5422}
5423
5425{
5426 struct outline *item;
5427
5428 if (!reserve((struct dynamic_array *)array, array->count + 1, sizeof(array->items[0])))
5429 return NULL;
5430
5431 item = &array->items[array->count++];
5432 ZeroMemory(item, sizeof(*item));
5433 return item;
5434}
5435
5436static inline face *add_face(struct face_array *array)
5437{
5438 return &array->items[array->count++];
5439}
5440
5442{
5443 struct triangulation *item;
5444
5445 if (!reserve((struct dynamic_array *)array, array->count + 1, sizeof(array->items[0])))
5446 return NULL;
5447
5448 item = &array->items[array->count++];
5449 ZeroMemory(item, sizeof(*item));
5450 return item;
5451}
5452
5454{
5455 if (!reserve((struct dynamic_array *)array, array->count + 1, sizeof(array->items[0])))
5456 return E_OUTOFMEMORY;
5457
5458 array->items[array->count++] = vertex_index;
5459 return S_OK;
5460}
5461
5462/* assume fixed point numbers can be converted to float point in place */
5463C_ASSERT(sizeof(FIXED) == sizeof(float));
5464C_ASSERT(sizeof(POINTFX) == sizeof(D3DXVECTOR2));
5465
5466static inline D3DXVECTOR2 *convert_fixed_to_float(POINTFX *pt, int count, unsigned int emsquare)
5467{
5469 while (count--) {
5470 D3DXVECTOR2 *pt_flt = (D3DXVECTOR2*)pt;
5471 pt_flt->x = (pt->x.value + pt->x.fract / (float)0x10000) / emsquare;
5472 pt_flt->y = (pt->y.value + pt->y.fract / (float)0x10000) / emsquare;
5473 pt++;
5474 }
5475 return ret;
5476}
5477
5479 const D3DXVECTOR2 *p2, const D3DXVECTOR2 *p3,
5480 float max_deviation_sq)
5481{
5482 D3DXVECTOR2 split1 = {0, 0}, split2 = {0, 0}, middle, vec;
5483 float deviation_sq;
5484
5485 D3DXVec2Scale(&split1, D3DXVec2Add(&split1, p1, p2), 0.5f);
5486 D3DXVec2Scale(&split2, D3DXVec2Add(&split2, p2, p3), 0.5f);
5487 D3DXVec2Scale(&middle, D3DXVec2Add(&middle, &split1, &split2), 0.5f);
5488
5489 deviation_sq = D3DXVec2LengthSq(D3DXVec2Subtract(&vec, &middle, p2));
5490 if (deviation_sq < max_deviation_sq) {
5491 struct point2d *pt = add_points(outline, 1);
5492 if (!pt) return E_OUTOFMEMORY;
5493 pt->pos = *p2;
5494 pt->corner = POINTTYPE_CURVE;
5495 /* the end point is omitted because the end line merges into the next segment of
5496 * the split bezier curve, and the end of the split bezier curve is added outside
5497 * this recursive function. */
5498 } else {
5499 HRESULT hr = add_bezier_points(outline, p1, &split1, &middle, max_deviation_sq);
5500 if (hr != S_OK) return hr;
5501 hr = add_bezier_points(outline, &middle, &split2, p3, max_deviation_sq);
5502 if (hr != S_OK) return hr;
5503 }
5504
5505 return S_OK;
5506}
5507
5508static inline BOOL is_direction_similar(D3DXVECTOR2 *dir1, D3DXVECTOR2 *dir2, float cos_theta)
5509{
5510 /* dot product = cos(theta) */
5511 return D3DXVec2Dot(dir1, dir2) > cos_theta;
5512}
5513
5514static inline D3DXVECTOR2 *unit_vec2(D3DXVECTOR2 *dir, const D3DXVECTOR2 *pt1, const D3DXVECTOR2 *pt2)
5515{
5516 return D3DXVec2Normalize(D3DXVec2Subtract(dir, pt2, pt1), dir);
5517}
5518
5520{
5522 float cos_45;
5523 float cos_90;
5524};
5525
5527 int pt_index,
5528 const D3DXVECTOR2 *nextpt,
5529 BOOL to_curve,
5530 const struct cos_table *table)
5531{
5532 D3DXVECTOR2 curdir, lastdir;
5533 struct point2d *prevpt, *pt;
5534 BOOL ret = FALSE;
5535
5536 pt = &outline->items[pt_index];
5537 pt_index = (pt_index - 1 + outline->count) % outline->count;
5538 prevpt = &outline->items[pt_index];
5539
5540 if (to_curve)
5542
5543 if (outline->count < 2)
5544 return FALSE;
5545
5546 /* remove last point if the next line continues the last line */
5547 unit_vec2(&lastdir, &prevpt->pos, &pt->pos);
5548 unit_vec2(&curdir, &pt->pos, nextpt);
5549 if (is_direction_similar(&lastdir, &curdir, table->cos_half))
5550 {
5551 outline->count--;
5552 if (pt->corner == POINTTYPE_CURVE_END)
5553 prevpt->corner = pt->corner;
5554 if (prevpt->corner == POINTTYPE_CURVE_END && to_curve)
5556 pt = prevpt;
5557
5558 ret = TRUE;
5559 if (outline->count < 2)
5560 return ret;
5561
5562 pt_index = (pt_index - 1 + outline->count) % outline->count;
5563 prevpt = &outline->items[pt_index];
5564 unit_vec2(&lastdir, &prevpt->pos, &pt->pos);
5565 unit_vec2(&curdir, &pt->pos, nextpt);
5566 }
5567 return ret;
5568}
5569
5570static HRESULT create_outline(struct glyphinfo *glyph, void *raw_outline, int datasize,
5571 float max_deviation_sq, unsigned int emsquare,
5572 const struct cos_table *cos_table)
5573{
5574 TTPOLYGONHEADER *header = (TTPOLYGONHEADER *)raw_outline;
5575
5576 while ((char *)header < (char *)raw_outline + datasize)
5577 {
5578 TTPOLYCURVE *curve = (TTPOLYCURVE *)(header + 1);
5579 struct point2d *lastpt, *pt;
5580 D3DXVECTOR2 lastdir;
5581 D3DXVECTOR2 *pt_flt;
5582 int j;
5583 struct outline *outline = add_outline(&glyph->outlines);
5584
5585 if (!outline)
5586 return E_OUTOFMEMORY;
5587
5588 pt = add_points(outline, 1);
5589 if (!pt)
5590 return E_OUTOFMEMORY;
5591 pt_flt = convert_fixed_to_float(&header->pfxStart, 1, emsquare);
5592 pt->pos = *pt_flt;
5593 pt->corner = POINTTYPE_CORNER;
5594
5595 if (header->dwType != TT_POLYGON_TYPE)
5596 FIXME("Unknown header type %d\n", header->dwType);
5597
5598 while ((char *)curve < (char *)header + header->cb)
5599 {
5600 D3DXVECTOR2 bezier_start = outline->items[outline->count - 1].pos;
5601 BOOL to_curve = curve->wType != TT_PRIM_LINE && curve->cpfx > 1;
5602 unsigned int j2 = 0;
5603
5604 if (!curve->cpfx) {
5605 curve = (TTPOLYCURVE *)&curve->apfx[curve->cpfx];
5606 continue;
5607 }
5608
5609 pt_flt = convert_fixed_to_float(curve->apfx, curve->cpfx, emsquare);
5610
5611 attempt_line_merge(outline, outline->count - 1, &pt_flt[0], to_curve, cos_table);
5612
5613 if (to_curve)
5614 {
5615 HRESULT hr;
5616 int count = curve->cpfx;
5617
5618 while (count > 2)
5619 {
5620 D3DXVECTOR2 bezier_end;
5621
5622 D3DXVec2Scale(&bezier_end, D3DXVec2Add(&bezier_end, &pt_flt[j2], &pt_flt[j2+1]), 0.5f);
5623 hr = add_bezier_points(outline, &bezier_start, &pt_flt[j2], &bezier_end, max_deviation_sq);
5624 if (hr != S_OK)
5625 return hr;
5626 bezier_start = bezier_end;
5627 count--;
5628 j2++;
5629 }
5630 hr = add_bezier_points(outline, &bezier_start, &pt_flt[j2], &pt_flt[j2+1], max_deviation_sq);
5631 if (hr != S_OK)
5632 return hr;
5633
5634 pt = add_points(outline, 1);
5635 if (!pt)
5636 return E_OUTOFMEMORY;
5637 j2++;
5638 pt->pos = pt_flt[j2];
5639 pt->corner = POINTTYPE_CURVE_END;
5640 } else {
5641 pt = add_points(outline, curve->cpfx);
5642 if (!pt)
5643 return E_OUTOFMEMORY;
5644 for (j2 = 0; j2 < curve->cpfx; j2++)
5645 {
5646 pt->pos = pt_flt[j2];
5647 pt->corner = POINTTYPE_CORNER;
5648 pt++;
5649 }
5650 }
5651
5652 curve = (TTPOLYCURVE *)&curve->apfx[curve->cpfx];
5653 }
5654
5655 /* remove last point if the next line continues the last line */
5656 if (outline->count >= 3) {
5657 BOOL to_curve;
5658
5659 lastpt = &outline->items[outline->count - 1];
5660 pt = &outline->items[0];
5661 if (pt->pos.x == lastpt->pos.x && pt->pos.y == lastpt->pos.y) {
5662 if (lastpt->corner == POINTTYPE_CURVE_END)
5663 {
5664 if (pt->corner == POINTTYPE_CURVE_START)
5665 pt->corner = POINTTYPE_CURVE_MIDDLE;
5666 else
5667 pt->corner = POINTTYPE_CURVE_END;
5668 }
5669 outline->count--;
5670 } else {
5671 /* outline closed with a line from end to start point */
5673 }
5674 lastpt = &outline->items[0];
5675 to_curve = lastpt->corner != POINTTYPE_CORNER && lastpt->corner != POINTTYPE_CURVE_END;
5676 if (lastpt->corner == POINTTYPE_CURVE_START)
5677 lastpt->corner = POINTTYPE_CORNER;
5678 pt = &outline->items[1];
5679 if (attempt_line_merge(outline, 0, &pt->pos, to_curve, cos_table))
5680 *lastpt = outline->items[outline->count];
5681 }
5682
5683 lastpt = &outline->items[outline->count - 1];
5684 pt = &outline->items[0];
5685 unit_vec2(&lastdir, &lastpt->pos, &pt->pos);
5686 for (j = 0; j < outline->count; j++)
5687 {
5688 D3DXVECTOR2 curdir;
5689
5690 lastpt = pt;
5691 pt = &outline->items[(j + 1) % outline->count];
5692 unit_vec2(&curdir, &lastpt->pos, &pt->pos);
5693
5694 switch (lastpt->corner)
5695 {
5698 if (!is_direction_similar(&lastdir, &curdir, cos_table->cos_45))
5699 lastpt->corner = POINTTYPE_CORNER;
5700 break;
5702 if (!is_direction_similar(&lastdir, &curdir, cos_table->cos_90))
5703 lastpt->corner = POINTTYPE_CORNER;
5704 else
5705 lastpt->corner = POINTTYPE_CURVE;
5706 break;
5707 default:
5708 break;
5709 }
5710 lastdir = curdir;
5711 }
5712
5713 header = (TTPOLYGONHEADER *)((char *)header + header->cb);
5714 }
5715 return S_OK;
5716}
5717
5718/* Get the y-distance from a line to a point */
5720 D3DXVECTOR2 *line_pt2,
5722{
5723 D3DXVECTOR2 line_vec = {0, 0};
5724 float line_pt_dx;
5725 float line_y;
5726
5727 D3DXVec2Subtract(&line_vec, line_pt2, line_pt1);
5728 line_pt_dx = point->x - line_pt1->x;
5729 line_y = line_pt1->y + (line_vec.y * line_pt_dx) / line_vec.x;
5730 return point->y - line_y;
5731}
5732
5734{
5735 return &pt_idx->outline->items[pt_idx->vertex].pos;
5736}
5737
5739{
5740 return get_indexed_point(&glyph->ordered_vertices.items[index]);
5741}
5742
5744{
5745 HeapFree(GetProcessHeap(), 0, item->vertex_stack.items);
5746 MoveMemory(item, item + 1, (char*)&array->items[array->count] - (char*)(item + 1));
5747 array->count--;
5748}
5749
5751 struct triangulation_array *triangulations,
5752 WORD vtx_idx,
5753 BOOL to_top)
5754{
5755 struct glyphinfo *glyph = triangulations->glyph;
5756 struct triangulation *t = *t_ptr;
5757 HRESULT hr;
5758 face *face;
5759 int f1, f2;
5760
5761 if (t->last_on_top) {
5762 f1 = 1;
5763 f2 = 2;
5764 } else {
5765 f1 = 2;
5766 f2 = 1;
5767 }
5768
5769 if (t->last_on_top != to_top && t->vertex_stack.count > 1) {
5770 /* consume all vertices on the stack */
5771 WORD last_pt = t->vertex_stack.items[0];
5772 int i;
5773 for (i = 1; i < t->vertex_stack.count; i++)
5774 {
5775 face = add_face(&glyph->faces);
5776 if (!face) return E_OUTOFMEMORY;
5777 (*face)[0] = vtx_idx;
5778 (*face)[f1] = last_pt;
5779 (*face)[f2] = last_pt = t->vertex_stack.items[i];
5780 }
5781 t->vertex_stack.items[0] = last_pt;
5782 t->vertex_stack.count = 1;
5783 } else if (t->vertex_stack.count > 1) {
5784 int i = t->vertex_stack.count - 1;
5785 D3DXVECTOR2 *point = get_ordered_vertex(glyph, vtx_idx);
5786 WORD top_idx = t->vertex_stack.items[i--];
5787 D3DXVECTOR2 *top_pt = get_ordered_vertex(glyph, top_idx);
5788
5789 while (i >= 0)
5790 {
5791 WORD prev_idx = t->vertex_stack.items[i--];
5792 D3DXVECTOR2 *prev_pt = get_ordered_vertex(glyph, prev_idx);
5793
5794 if (prev_pt->x != top_pt->x &&
5795 ((to_top && get_line_to_point_y_distance(prev_pt, top_pt, point) > 0) ||
5796 (!to_top && get_line_to_point_y_distance(prev_pt, top_pt, point) < 0)))
5797 break;
5798
5799 face = add_face(&glyph->faces);
5800 if (!face) return E_OUTOFMEMORY;
5801 (*face)[0] = vtx_idx;
5802 (*face)[f1] = prev_idx;
5803 (*face)[f2] = top_idx;
5804
5805 top_pt = prev_pt;
5806 top_idx = prev_idx;
5807 t->vertex_stack.count--;
5808 }
5809 }
5810 t->last_on_top = to_top;
5811
5812 hr = add_vertex_index(&t->vertex_stack, vtx_idx);
5813
5814 if (hr == S_OK && t->merging) {
5815 struct triangulation *t2;
5816
5817 t2 = to_top ? t - 1 : t + 1;
5818 t2->merging = FALSE;
5819 hr = triangulation_add_point(&t2, triangulations, vtx_idx, to_top);
5820 if (hr != S_OK) return hr;
5821 remove_triangulation(triangulations, t);
5822 if (t2 > t)
5823 t2--;
5824 *t_ptr = t2;
5825 }
5826 return hr;
5827}
5828
5829/* check if the point is next on the outline for either the top or bottom */
5831{
5832 int i = t->last_on_top == on_top ? t->vertex_stack.count - 1 : 0;
5833 WORD idx = t->vertex_stack.items[i];
5834 struct point2d_index *pt_idx = &glyph->ordered_vertices.items[idx];
5835 struct outline *outline = pt_idx->outline;
5836
5837 if (on_top)
5838 i = (pt_idx->vertex + outline->count - 1) % outline->count;
5839 else
5840 i = (pt_idx->vertex + 1) % outline->count;
5841
5842 return &outline->items[i].pos;
5843}
5844
5845static int __cdecl compare_vertex_indices(const void *a, const void *b)
5846{
5847 const struct point2d_index *idx1 = a, *idx2 = b;
5848 const D3DXVECTOR2 *p1 = &idx1->outline->items[idx1->vertex].pos;
5849 const D3DXVECTOR2 *p2 = &idx2->outline->items[idx2->vertex].pos;
5850 float diff = p1->x - p2->x;
5851
5852 if (diff == 0.0f)
5853 diff = p1->y - p2->y;
5854
5855 return diff == 0.0f ? 0 : (diff > 0.0f ? -1 : 1);
5856}
5857
5858static HRESULT triangulate(struct triangulation_array *triangulations)
5859{
5860 int sweep_idx;
5861 HRESULT hr;
5862 struct glyphinfo *glyph = triangulations->glyph;
5863 int nb_vertices = 0;
5864 int i;
5865 struct point2d_index *idx_ptr;
5866
5867 /* Glyphs without outlines do not generate any vertices. */
5868 if (!glyph->outlines.count)
5869 return D3D_OK;
5870
5871 for (i = 0; i < glyph->outlines.count; i++)
5872 nb_vertices += glyph->outlines.items[i].count;
5873
5874 glyph->ordered_vertices.items = HeapAlloc(GetProcessHeap(), 0,
5875 nb_vertices * sizeof(*glyph->ordered_vertices.items));
5876 if (!glyph->ordered_vertices.items)
5877 return E_OUTOFMEMORY;
5878
5879 idx_ptr = glyph->ordered_vertices.items;
5880 for (i = 0; i < glyph->outlines.count; i++)
5881 {
5882 struct outline *outline = &glyph->outlines.items[i];
5883 int j;
5884
5885 idx_ptr->outline = outline;
5886 idx_ptr->vertex = 0;
5887 idx_ptr++;
5888 for (j = outline->count - 1; j > 0; j--)
5889 {
5890 idx_ptr->outline = outline;
5891 idx_ptr->vertex = j;
5892 idx_ptr++;
5893 }
5894 }
5895 glyph->ordered_vertices.count = nb_vertices;
5896
5897 /* Native implementation seems to try to create a triangle fan from
5898 * the first outline point if the glyph only has one outline. */
5899 if (glyph->outlines.count == 1)
5900 {
5901 struct outline *outline = glyph->outlines.items;
5902 D3DXVECTOR2 *base = &outline->items[0].pos;
5903 D3DXVECTOR2 *last = &outline->items[1].pos;
5904 float ccw = 0;
5905
5906 for (i = 2; i < outline->count; i++)
5907 {
5908 D3DXVECTOR2 *next = &outline->items[i].pos;
5909 D3DXVECTOR2 v1 = {0.0f, 0.0f};
5910 D3DXVECTOR2 v2 = {0.0f, 0.0f};
5911
5912 D3DXVec2Subtract(&v1, base, last);
5913 D3DXVec2Subtract(&v2, last, next);
5914 ccw = D3DXVec2CCW(&v1, &v2);
5915 if (ccw > 0.0f)
5916 break;
5917
5918 last = next;
5919 }
5920 if (ccw <= 0)
5921 {
5922 glyph->faces.items = HeapAlloc(GetProcessHeap(), 0,
5923 (outline->count - 2) * sizeof(glyph->faces.items[0]));
5924 if (!glyph->faces.items)
5925 return E_OUTOFMEMORY;
5926
5927 glyph->faces.count = outline->count - 2;
5928 for (i = 0; i < glyph->faces.count; i++)
5929 {
5930 glyph->faces.items[i][0] = 0;
5931 glyph->faces.items[i][1] = i + 1;
5932 glyph->faces.items[i][2] = i + 2;
5933 }
5934 return S_OK;
5935 }
5936 }
5937
5938 /* Perform 2D polygon triangulation for complex glyphs.
5939 * Triangulation is performed using a sweep line concept, from right to left,
5940 * by processing vertices in sorted order. Complex polygons are split into
5941 * monotone polygons which are triangulated separately. */
5942 /* FIXME: The order of the faces is not consistent with the native implementation. */
5943
5944 /* Reserve space for maximum possible faces from triangulation.
5945 * # faces for outer outlines = outline->count - 2
5946 * # faces for inner outlines = outline->count + 2
5947 * There must be at least 1 outer outline. */
5948 glyph->faces.items = HeapAlloc(GetProcessHeap(), 0,
5949 (nb_vertices + glyph->outlines.count * 2 - 4) * sizeof(glyph->faces.items[0]));
5950 if (!glyph->faces.items)
5951 return E_OUTOFMEMORY;
5952
5953 qsort(glyph->ordered_vertices.items, nb_vertices,
5954 sizeof(glyph->ordered_vertices.items[0]), compare_vertex_indices);
5955 for (sweep_idx = 0; sweep_idx < glyph->ordered_vertices.count; sweep_idx++)
5956 {
5957 int start = 0;
5958 int end = triangulations->count;
5959
5960 while (start < end)
5961 {
5962 D3DXVECTOR2 *sweep_vtx = get_ordered_vertex(glyph, sweep_idx);
5963 int current = (start + end) / 2;
5964 struct triangulation *t = &triangulations->items[current];
5965 BOOL on_top_outline = FALSE;
5966 D3DXVECTOR2 *top_next, *bottom_next;
5967 WORD top_idx, bottom_idx;
5968
5969 if (t->merging && t->last_on_top)
5970 top_next = triangulation_get_next_point(t + 1, glyph, TRUE);
5971 else
5972 top_next = triangulation_get_next_point(t, glyph, TRUE);
5973 if (sweep_vtx == top_next)
5974 {
5975 if (t->merging && t->last_on_top)
5976 t++;
5977 hr = triangulation_add_point(&t, triangulations, sweep_idx, TRUE);
5978 if (hr != S_OK) return hr;
5979
5980 if (t + 1 < &triangulations->items[triangulations->count] &&
5981 triangulation_get_next_point(t + 1, glyph, FALSE) == sweep_vtx)
5982 {
5983 /* point also on bottom outline of higher triangulation */
5984 struct triangulation *t2 = t + 1;
5985 hr = triangulation_add_point(&t2, triangulations, sweep_idx, FALSE);
5986 if (hr != S_OK) return hr;
5987
5988 t->merging = TRUE;
5989 t2->merging = TRUE;
5990 }
5991 on_top_outline = TRUE;
5992 }
5993
5994 if (t->merging && !t->last_on_top)
5995 bottom_next = triangulation_get_next_point(t - 1, glyph, FALSE);
5996 else
5997 bottom_next = triangulation_get_next_point(t, glyph, FALSE);
5998 if (sweep_vtx == bottom_next)
5999 {
6000 if (t->merging && !t->last_on_top)
6001 t--;
6002 if (on_top_outline) {
6003 /* outline finished */
6004 remove_triangulation(triangulations, t);
6005 break;
6006 }
6007
6008 hr = triangulation_add_point(&t, triangulations, sweep_idx, FALSE);
6009 if (hr != S_OK) return hr;
6010
6011 if (t > triangulations->items &&
6012 triangulation_get_next_point(t - 1, glyph, TRUE) == sweep_vtx)
6013 {
6014 struct triangulation *t2 = t - 1;
6015 /* point also on top outline of lower triangulation */
6016 hr = triangulation_add_point(&t2, triangulations, sweep_idx, TRUE);
6017 if (hr != S_OK) return hr;
6018 t = t2 + 1; /* t may be invalidated by triangulation merging */
6019
6020 t->merging = TRUE;
6021 t2->merging = TRUE;
6022 }
6023 break;
6024 }
6025 if (on_top_outline)
6026 break;
6027
6028 if (t->last_on_top) {
6029 top_idx = t->vertex_stack.items[t->vertex_stack.count - 1];
6030 bottom_idx = t->vertex_stack.items[0];
6031 } else {
6032 top_idx = t->vertex_stack.items[0];
6033 bottom_idx = t->vertex_stack.items[t->vertex_stack.count - 1];
6034 }
6035
6036 /* check if the point is inside or outside this polygon */
6038 top_next, sweep_vtx) > 0)
6039 { /* above */
6040 start = current + 1;
6041 } else if (get_line_to_point_y_distance(get_ordered_vertex(glyph, bottom_idx),
6042 bottom_next, sweep_vtx) < 0)
6043 { /* below */
6044 end = current;
6045 } else if (t->merging) {
6046 /* inside, so cancel merging */
6047 struct triangulation *t2 = t->last_on_top ? t + 1 : t - 1;
6048 t->merging = FALSE;
6049 t2->merging = FALSE;
6050 hr = triangulation_add_point(&t, triangulations, sweep_idx, t->last_on_top);
6051 if (hr != S_OK) return hr;
6052 hr = triangulation_add_point(&t2, triangulations, sweep_idx, t2->last_on_top);
6053 if (hr != S_OK) return hr;
6054 break;
6055 } else {
6056 /* inside, so split polygon into two monotone parts */
6057 struct triangulation *t2 = add_triangulation(triangulations);
6058 if (!t2) return E_OUTOFMEMORY;
6059 MoveMemory(t + 1, t, (char*)(t2 + 1) - (char*)t);
6060 if (t->last_on_top) {
6061 t2 = t + 1;
6062 } else {
6063 t2 = t;
6064 t++;
6065 }
6066
6067 ZeroMemory(&t2->vertex_stack, sizeof(t2->vertex_stack));
6068 hr = add_vertex_index(&t2->vertex_stack, t->vertex_stack.items[t->vertex_stack.count - 1]);
6069 if (hr != S_OK) return hr;
6070 hr = add_vertex_index(&t2->vertex_stack, sweep_idx);
6071 if (hr != S_OK) return hr;
6072 t2->last_on_top = !t->last_on_top;
6073
6074 hr = triangulation_add_point(&t, triangulations, sweep_idx, t->last_on_top);
6075 if (hr != S_OK) return hr;
6076 break;
6077 }
6078 }
6079 if (start >= end)
6080 {
6081 struct triangulation *t;
6082 struct triangulation *t2 = add_triangulation(triangulations);
6083 if (!t2) return E_OUTOFMEMORY;
6084 t = &triangulations->items[start];
6085 MoveMemory(t + 1, t, (char*)(t2 + 1) - (char*)t);
6086 ZeroMemory(t, sizeof(*t));
6087 hr = add_vertex_index(&t->vertex_stack, sweep_idx);
6088 if (hr != S_OK) return hr;
6089 }
6090 }
6091 return S_OK;
6092}
6093
6094HRESULT WINAPI D3DXCreateTextW(struct IDirect3DDevice9 *device, HDC hdc, const WCHAR *text, float deviation,
6095 float extrusion, struct ID3DXMesh **mesh_ptr, struct ID3DXBuffer **adjacency, GLYPHMETRICSFLOAT *glyphmetrics)
6096{
6097 HRESULT hr;
6098 ID3DXMesh *mesh = NULL;
6099 DWORD nb_vertices, nb_faces;
6100 DWORD nb_front_faces, nb_corners, nb_outline_points;
6101 struct vertex *vertices = NULL;
6102 face *faces = NULL;
6103 int textlen = 0;
6104 float offset_x;
6105 LOGFONTW lf;
6107 HFONT font = NULL, oldfont = NULL;
6108 const MAT2 identity = {{0, 1}, {0, 0}, {0, 0}, {0, 1}};
6109 void *raw_outline = NULL;
6110 int bufsize = 0;
6111 struct glyphinfo *glyphs = NULL;
6112 GLYPHMETRICS gm;
6113 struct triangulation_array triangulations = {0, 0, NULL};
6114 int i;
6115 struct vertex *vertex_ptr;
6116 face *face_ptr;
6117 float max_deviation_sq;
6118 const struct cos_table cos_table = {
6119 cosf(D3DXToRadian(0.5f)),
6120 cosf(D3DXToRadian(45.0f)),
6121 cosf(D3DXToRadian(90.0f)),
6122 };
6123 int f1, f2;
6124
6125 TRACE("(%p, %p, %s, %f, %f, %p, %p, %p)\n", device, hdc,
6126 debugstr_w(text), deviation, extrusion, mesh_ptr, adjacency, glyphmetrics);
6127
6128 if (!device || !hdc || !text || !*text || deviation < 0.0f || extrusion < 0.0f || !mesh_ptr)
6129 return D3DERR_INVALIDCALL;
6130
6131 if (adjacency)
6132 {
6133 FIXME("Case of adjacency != NULL not implemented.\n");
6134 return E_NOTIMPL;
6135 }
6136
6137 if (!GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf) ||
6138 !GetOutlineTextMetricsW(hdc, sizeof(otm), &otm))
6139 {
6140 return D3DERR_INVALIDCALL;
6141 }
6142
6143 if (deviation == 0.0f)
6144 deviation = 1.0f / otm.otmEMSquare;
6145 max_deviation_sq = deviation * deviation;
6146
6147 lf.lfHeight = otm.otmEMSquare;
6148 lf.lfWidth = 0;
6150 if (!font) {
6151 hr = E_OUTOFMEMORY;
6152 goto error;
6153 }
6154 oldfont = SelectObject(hdc, font);
6155
6156 textlen = lstrlenW(text);
6157 for (i = 0; i < textlen; i++)
6158 {
6160 if (datasize < 0)
6161 return D3DERR_INVALIDCALL;
6162 if (bufsize < datasize)
6163 bufsize = datasize;
6164 }
6165 if (!bufsize) { /* e.g. text == " " */
6167 goto error;
6168 }
6169
6170 glyphs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, textlen * sizeof(*glyphs));
6171 raw_outline = HeapAlloc(GetProcessHeap(), 0, bufsize);
6172 if (!glyphs || !raw_outline) {
6173 hr = E_OUTOFMEMORY;
6174 goto error;
6175 }
6176
6177 offset_x = 0.0f;
6178 for (i = 0; i < textlen; i++)
6179 {
6180 /* get outline points from data returned from GetGlyphOutline */
6181 int datasize;
6182
6183 glyphs[i].offset_x = offset_x;
6184
6185 datasize = GetGlyphOutlineW(hdc, text[i], GGO_NATIVE, &gm, bufsize, raw_outline, &identity);
6186 hr = create_outline(&glyphs[i], raw_outline, datasize,
6187 max_deviation_sq, otm.otmEMSquare, &cos_table);
6188 if (hr != S_OK) goto error;
6189
6190 triangulations.glyph = &glyphs[i];
6191 hr = triangulate(&triangulations);
6192 if (hr != S_OK) goto error;
6193 if (triangulations.count) {
6194 ERR("%d incomplete triangulations of glyph (%u).\n", triangulations.count, text[i]);
6195 triangulations.count = 0;
6196 }
6197
6198 if (glyphmetrics)
6199 {
6200 glyphmetrics[i].gmfBlackBoxX = gm.gmBlackBoxX / (float)otm.otmEMSquare;
6201 glyphmetrics[i].gmfBlackBoxY = gm.gmBlackBoxY / (float)otm.otmEMSquare;
6202 glyphmetrics[i].gmfptGlyphOrigin.x = gm.gmptGlyphOrigin.x / (float)otm.otmEMSquare;
6203 glyphmetrics[i].gmfptGlyphOrigin.y = gm.gmptGlyphOrigin.y / (float)otm.otmEMSquare;
6204 glyphmetrics[i].gmfCellIncX = gm.gmCellIncX / (float)otm.otmEMSquare;
6205 glyphmetrics[i].gmfCellIncY = gm.gmCellIncY / (float)otm.otmEMSquare;
6206 }
6207 offset_x += gm.gmCellIncX / (float)otm.otmEMSquare;
6208 }
6209
6210 /* corner points need an extra vertex for the different side faces normals */
6211 nb_corners = 0;
6212 nb_outline_points = 0;
6213 nb_front_faces = 0;
6214 for (i = 0; i < textlen; i++)
6215 {
6216 int j;
6217 nb_outline_points += glyphs[i].ordered_vertices.count;
6218 nb_front_faces += glyphs[i].faces.count;
6219 for (j = 0; j < glyphs[i].outlines.count; j++)
6220 {
6221 int k;
6222 struct outline *outline = &glyphs[i].outlines.items[j];
6223 nb_corners++; /* first outline point always repeated as a corner */
6224 for (k = 1; k < outline->count; k++)
6225 if (outline->items[k].corner)
6226 nb_corners++;
6227 }
6228 }
6229
6230 nb_vertices = (nb_outline_points + nb_corners) * 2 + nb_outline_points * 2;
6231 nb_faces = nb_outline_points * 2 + nb_front_faces * 2;
6232
6233
6234 hr = D3DXCreateMeshFVF(nb_faces, nb_vertices, D3DXMESH_MANAGED,
6236 if (FAILED(hr))
6237 goto error;
6238
6239 if (FAILED(hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, (void **)&vertices)))
6240 goto error;
6241
6242 if (FAILED(hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, (void **)&faces)))
6243 goto error;
6244
6245 /* convert 2D vertices and faces into 3D mesh */
6246 vertex_ptr = vertices;
6247 face_ptr = faces;
6248 if (extrusion == 0.0f) {
6249 f1 = 1;
6250 f2 = 2;
6251 } else {
6252 f1 = 2;
6253 f2 = 1;
6254 }
6255 for (i = 0; i < textlen; i++)
6256 {
6257 int j;
6258 int count;
6259 struct vertex *back_vertices;
6260 face *back_faces;
6261
6262 /* side vertices and faces */
6263 for (j = 0; j < glyphs[i].outlines.count; j++)
6264 {
6265 struct vertex *outline_vertices = vertex_ptr;
6266 struct outline *outline = &glyphs[i].outlines.items[j];
6267 int k;
6268 struct point2d *prevpt = &outline->items[outline->count - 1];
6269 struct point2d *pt = &outline->items[0];
6270
6271 for (k = 1; k <= outline->count; k++)
6272 {
6273 struct vertex vtx;
6274 struct point2d *nextpt = &outline->items[k % outline->count];
6275 WORD vtx_idx = vertex_ptr - vertices;
6277
6278 if (pt->corner == POINTTYPE_CURVE_START)
6279 D3DXVec2Subtract(&vec, &pt->pos, &prevpt->pos);
6280 else if (pt->corner)
6281 D3DXVec2Subtract(&vec, &nextpt->pos, &pt->pos);
6282 else
6283 D3DXVec2Subtract(&vec, &nextpt->pos, &prevpt->pos);
6285 vtx.normal.x = -vec.y;
6286 vtx.normal.y = vec.x;
6287 vtx.normal.z = 0;
6288
6289 vtx.position.x = pt->pos.x + glyphs[i].offset_x;
6290 vtx.position.y = pt->pos.y;
6291 vtx.position.z = 0;
6292 *vertex_ptr++ = vtx;
6293
6294 vtx.position.z = -extrusion;
6295 *vertex_ptr++ = vtx;
6296
6297 vtx.position.x = nextpt->pos.x + glyphs[i].offset_x;
6298 vtx.position.y = nextpt->pos.y;
6299 if (pt->corner && nextpt->corner && nextpt->corner != POINTTYPE_CURVE_END) {
6300 vtx.position.z = -extrusion;
6301 *vertex_ptr++ = vtx;
6302 vtx.position.z = 0;
6303 *vertex_ptr++ = vtx;
6304
6305 (*face_ptr)[0] = vtx_idx;
6306 (*face_ptr)[1] = vtx_idx + 2;
6307 (*face_ptr)[2] = vtx_idx + 1;
6308 face_ptr++;
6309
6310 (*face_ptr)[0] = vtx_idx;
6311 (*face_ptr)[1] = vtx_idx + 3;
6312 (*face_ptr)[2] = vtx_idx + 2;
6313 face_ptr++;
6314 } else {
6315 if (nextpt->corner) {
6316 if (nextpt->corner == POINTTYPE_CURVE_END) {
6317 D3DXVECTOR2 *nextpt2 = &outline->items[(k + 1) % outline->count].pos;
6318 D3DXVec2Subtract(&vec, nextpt2, &nextpt->pos);
6319 } else {
6320 D3DXVec2Subtract(&vec, &nextpt->pos, &pt->pos);
6321 }
6323 vtx.normal.x = -vec.y;
6324 vtx.normal.y = vec.x;
6325
6326 vtx.position.z = 0;
6327 *vertex_ptr++ = vtx;
6328 vtx.position.z = -extrusion;
6329 *vertex_ptr++ = vtx;
6330 }
6331
6332 (*face_ptr)[0] = vtx_idx;
6333 (*face_ptr)[1] = vtx_idx + 3;
6334 (*face_ptr)[2] = vtx_idx + 1;
6335 face_ptr++;
6336
6337 (*face_ptr)[0] = vtx_idx;
6338 (*face_ptr)[1] = vtx_idx + 2;
6339 (*face_ptr)[2] = vtx_idx + 3;
6340 face_ptr++;
6341 }
6342
6343 prevpt = pt;
6344 pt = nextpt;
6345 }
6346 if (!pt->corner) {
6347 *vertex_ptr++ = *outline_vertices++;
6348 *vertex_ptr++ = *outline_vertices++;
6349 }
6350 }
6351
6352 /* back vertices and faces */
6353 back_faces = face_ptr;
6354 back_vertices = vertex_ptr;
6355 for (j = 0; j < glyphs[i].ordered_vertices.count; j++)
6356 {
6358 vertex_ptr->position.x = pt->x + glyphs[i].offset_x;
6359 vertex_ptr->position.y = pt->y;
6360 vertex_ptr->position.z = 0;
6361 vertex_ptr->normal.x = 0;
6362 vertex_ptr->normal.y = 0;
6363 vertex_ptr->normal.z = 1;
6364 vertex_ptr++;
6365 }
6366 count = back_vertices - vertices;
6367 for (j = 0; j < glyphs[i].faces.count; j++)
6368 {
6369 face *f = &glyphs[i].faces.items[j];
6370 (*face_ptr)[0] = (*f)[0] + count;
6371 (*face_ptr)[1] = (*f)[1] + count;
6372 (*face_ptr)[2] = (*f)[2] + count;
6373 face_ptr++;
6374 }
6375
6376 /* front vertices and faces */
6377 j = count = vertex_ptr - back_vertices;
6378 while (j--)
6379 {
6380 vertex_ptr->position.x = back_vertices->position.x;
6381 vertex_ptr->position.y = back_vertices->position.y;
6382 vertex_ptr->position.z = -extrusion;
6383 vertex_ptr->normal.x = 0;
6384 vertex_ptr->normal.y = 0;
6385 vertex_ptr->normal.z = extrusion == 0.0f ? 1.0f : -1.0f;
6386 vertex_ptr++;
6387 back_vertices++;
6388 }
6389 j = face_ptr - back_faces;
6390 while (j--)
6391 {
6392 (*face_ptr)[0] = (*back_faces)[0] + count;
6393 (*face_ptr)[1] = (*back_faces)[f1] + count;
6394 (*face_ptr)[2] = (*back_faces)[f2] + count;
6395 face_ptr++;
6396 back_faces++;
6397 }
6398 }
6399
6400 *mesh_ptr = mesh;
6401 hr = D3D_OK;
6402error:
6403 if (mesh) {
6404 if (faces) mesh->lpVtbl->UnlockIndexBuffer(mesh);
6405 if (vertices) mesh->lpVtbl->UnlockVertexBuffer(mesh);
6406 if (hr != D3D_OK) mesh->lpVtbl->Release(mesh);
6407 }
6408 if (glyphs) {
6409 for (i = 0; i < textlen; i++)
6410 {
6411 int j;
6412 for (j = 0; j < glyphs[i].outlines.count; j++)
6413 HeapFree(GetProcessHeap(), 0, glyphs[i].outlines.items[j].items);
6414 HeapFree(GetProcessHeap(), 0, glyphs[i].outlines.items);
6415 HeapFree(GetProcessHeap(), 0, glyphs[i].faces.items);
6416 HeapFree(GetProcessHeap(), 0, glyphs[i].ordered_vertices.items);
6417 }
6419 }
6420 if (triangulations.items) {
6421 int i;
6422 for (i = 0; i < triangulations.count; i++)
6423 HeapFree(GetProcessHeap(), 0, triangulations.items[i].vertex_stack.items);
6424 HeapFree(GetProcessHeap(), 0, triangulations.items);
6425 }
6426 HeapFree(GetProcessHeap(), 0, raw_outline);
6427 if (oldfont) SelectObject(hdc, oldfont);
6428 if (font) DeleteObject(font);
6429
6430 return hr;
6431}
6432
6433HRESULT WINAPI D3DXValidMesh(ID3DXMesh *mesh, const DWORD *adjacency, ID3DXBuffer **errors_and_warnings)
6434{
6435 FIXME("(%p, %p, %p): stub\n", mesh, adjacency, *errors_and_warnings);
6436
6437 return E_NOTIMPL;
6438}
6439
6440static BOOL weld_float1(void *to, void *from, FLOAT epsilon)
6441{
6442 FLOAT *v1 = to;
6443 FLOAT *v2 = from;
6444
6445 if (fabsf(*v1 - *v2) <= epsilon)
6446 {
6447 *v1 = *v2;
6448
6449 return TRUE;
6450 }
6451
6452 return FALSE;
6453}
6454
6455static BOOL weld_float2(void *to, void *from, FLOAT epsilon)
6456{
6457 D3DXVECTOR2 *v1 = to;
6458 D3DXVECTOR2 *v2 = from;
6459 FLOAT diff_x = fabsf(v1->x - v2->x);
6460 FLOAT diff_y = fabsf(v1->y - v2->y);
6461 FLOAT max_abs_diff = max(diff_x, diff_y);
6462
6463 if (max_abs_diff <= epsilon)
6464 {
6465 memcpy(to, from, sizeof(D3DXVECTOR2));
6466
6467 return TRUE;
6468 }
6469
6470 return FALSE;
6471}
6472
6473static BOOL weld_float3(void *to, void *from, FLOAT epsilon)
6474{
6475 D3DXVECTOR3 *v1 = to;
6476 D3DXVECTOR3 *v2 = from;
6477 FLOAT diff_x = fabsf(v1->x - v2->x);
6478 FLOAT diff_y = fabsf(v1->y - v2->y);
6479 FLOAT diff_z = fabsf(v1->z - v2->z);
6480 FLOAT max_abs_diff = max(diff_x, diff_y);
6481 max_abs_diff = max(diff_z, max_abs_diff);
6482
6483 if (max_abs_diff <= epsilon)
6484 {
6485 memcpy(to, from, sizeof(D3DXVECTOR3));
6486
6487 return TRUE;
6488 }
6489
6490 return FALSE;
6491}
6492
6493static BOOL weld_float4(void *to, void *from, FLOAT epsilon)
6494{
6495 D3DXVECTOR4 *v1 = to;
6496 D3DXVECTOR4 *v2 = from;
6497 FLOAT diff_x = fabsf(v1->x - v2->x);
6498 FLOAT diff_y = fabsf(v1->y - v2->y);
6499 FLOAT diff_z = fabsf(v1->z - v2->z);
6500 FLOAT diff_w = fabsf(v1->w - v2->w);
6501 FLOAT max_abs_diff = max(diff_x, diff_y);
6502 max_abs_diff = max(diff_z, max_abs_diff);
6503 max_abs_diff = max(diff_w, max_abs_diff);
6504
6505 if (max_abs_diff <= epsilon)
6506 {
6507 memcpy(to, from, sizeof(D3DXVECTOR4));
6508
6509 return TRUE;
6510 }
6511
6512 return FALSE;
6513}
6514
6515static BOOL weld_ubyte4(void *to, void *from, FLOAT epsilon)
6516{
6517 BYTE *b1 = to;
6518 BYTE *b2 = from;
6519 BYTE truncated_epsilon = (BYTE)epsilon;
6520 BYTE diff_x = b1[0] > b2[0] ? b1[0] - b2[0] : b2[0] - b1[0];
6521 BYTE diff_y = b1[1] > b2[1] ? b1[1] - b2[1] : b2[1] - b1[1];
6522 BYTE diff_z = b1[2] > b2[2] ? b1[2] - b2[2] : b2[2] - b1[2];
6523 BYTE diff_w = b1[3] > b2[3] ? b1[3] - b2[3] : b2[3] - b1[3];
6524 BYTE max_diff = max(diff_x, diff_y);
6525 max_diff = max(diff_z, max_diff);
6526 max_diff = max(diff_w, max_diff);
6527
6528 if (max_diff <= truncated_epsilon)
6529 {
6530 memcpy(to, from, 4 * sizeof(BYTE));
6531
6532 return TRUE;
6533 }
6534
6535 return FALSE;
6536}
6537
6538static BOOL weld_ubyte4n(void *to, void *from, FLOAT epsilon)
6539{
6540 return weld_ubyte4(to, from, epsilon * UCHAR_MAX);
6541}
6542
6543static BOOL weld_d3dcolor(void *to, void *from, FLOAT epsilon)
6544{
6545 return weld_ubyte4n(to, from, epsilon);
6546}
6547
6548static BOOL weld_short2(void *to, void *from, FLOAT epsilon)
6549{
6550 SHORT *s1 = to;
6551 SHORT *s2 = from;
6552 SHORT truncated_epsilon = (SHORT)epsilon;
6553 SHORT diff_x = abs(s1[0] - s2[0]);
6554 SHORT diff_y = abs(s1[1] - s2[1]);
6555 SHORT max_abs_diff = max(diff_x, diff_y);
6556
6557 if (max_abs_diff <= truncated_epsilon)
6558 {
6559 memcpy(to, from, 2 * sizeof(SHORT));
6560
6561 return TRUE;
6562 }
6563
6564 return FALSE;
6565}
6566
6567static BOOL weld_short2n(void *to, void *from, FLOAT epsilon)
6568{
6569 return weld_short2(to, from, epsilon * SHRT_MAX);
6570}
6571
6572static BOOL weld_short4(void *to, void *from, FLOAT epsilon)
6573{
6574 SHORT *s1 = to;
6575 SHORT *s2 = from;
6576 SHORT truncated_epsilon = (SHORT)epsilon;
6577 SHORT diff_x = abs(s1[0] - s2[0]);
6578 SHORT diff_y = abs(s1[1] - s2[1]);
6579 SHORT diff_z = abs(s1[2] - s2[2]);
6580 SHORT diff_w = abs(s1[3] - s2[3]);
6581 SHORT max_abs_diff = max(diff_x, diff_y);
6582 max_abs_diff = max(diff_z, max_abs_diff);
6583 max_abs_diff = max(diff_w, max_abs_diff);
6584
6585 if (max_abs_diff <= truncated_epsilon)
6586 {
6587 memcpy(to, from, 4 * sizeof(SHORT));
6588
6589 return TRUE;
6590 }
6591
6592 return FALSE;
6593}
6594
6595static BOOL weld_short4n(void *to, void *from, FLOAT epsilon)
6596{
6597 return weld_short4(to, from, epsilon * SHRT_MAX);
6598}
6599
6600static BOOL weld_ushort2n(void *to, void *from, FLOAT epsilon)
6601{
6602 USHORT *s1 = to;
6603 USHORT *s2 = from;
6604 USHORT scaled_epsilon = (USHORT)(epsilon * USHRT_MAX);
6605 USHORT diff_x = s1[0] > s2[0] ? s1[0] - s2[0] : s2[0] - s1[0];
6606 USHORT diff_y = s1[1] > s2[1] ? s1[1] - s2[1] : s2[1] - s1[1];
6607 USHORT max_diff = max(diff_x, diff_y);
6608
6609 if (max_diff <= scaled_epsilon)
6610 {
6611 memcpy(to, from, 2 * sizeof(USHORT));
6612
6613 return TRUE;
6614 }
6615
6616 return FALSE;
6617}
6618
6619static BOOL weld_ushort4n(void *to, void *from, FLOAT epsilon)
6620{
6621 USHORT *s1 = to;
6622 USHORT *s2 = from;
6623 USHORT scaled_epsilon = (USHORT)(epsilon * USHRT_MAX);
6624 USHORT diff_x = s1[0] > s2[0] ? s1[0] - s2[0] : s2[0] - s1[0];
6625 USHORT diff_y = s1[1] > s2[1] ? s1[1] - s2[1] : s2[1] - s1[1];
6626 USHORT diff_z = s1[2] > s2[2] ? s1[2] - s2[2] : s2[2] - s1[2];
6627 USHORT diff_w = s1[3] > s2[3] ? s1[3] - s2[3] : s2[3] - s1[3];
6628 USHORT max_diff = max(diff_x, diff_y);
6629 max_diff = max(diff_z, max_diff);
6630 max_diff = max(diff_w, max_diff);
6631
6632 if (max_diff <= scaled_epsilon)
6633 {
6634 memcpy(to, from, 4 * sizeof(USHORT));
6635
6636 return TRUE;
6637 }
6638
6639 return FALSE;
6640}
6641
6642struct udec3
6643{
6648};
6649
6651{
6652 struct udec3 v;
6653
6654 v.x = d & 0x3ff;
6655 v.y = (d & 0xffc00) >> 10;
6656 v.z = (d & 0x3ff00000) >> 20;
6657 v.w = (d & 0xc0000000) >> 30;
6658
6659 return v;
6660}
6661
6662static BOOL weld_udec3(void *to, void *from, FLOAT epsilon)
6663{
6664 DWORD *d1 = to;
6665 DWORD *d2 = from;
6666 struct udec3 v1 = dword_to_udec3(*d1);
6667 struct udec3 v2 = dword_to_udec3(*d2);
6668 UINT truncated_epsilon = (UINT)epsilon;
6669 UINT diff_x = v1.x > v2.x ? v1.x - v2.x : v2.x - v1.x;
6670 UINT diff_y = v1.y > v2.y ? v1.y - v2.y : v2.y - v1.y;
6671 UINT diff_z = v1.z > v2.z ? v1.z - v2.z : v2.z - v1.z;
6672 UINT diff_w = v1.w > v2.w ? v1.w - v2.w : v2.w - v1.w;
6673 UINT max_diff = max(diff_x, diff_y);
6674 max_diff = max(diff_z, max_diff);
6675 max_diff = max(diff_w, max_diff);
6676
6677 if (max_diff <= truncated_epsilon)
6678 {
6679 memcpy(to, from, sizeof(DWORD));
6680
6681 return TRUE;
6682 }
6683
6684 return FALSE;
6685}
6686
6687struct dec3n
6688{
6693};
6694
6696{
6697 struct dec3n v;
6698
6699 v.x = d & 0x3ff;
6700 v.y = (d & 0xffc00) >> 10;
6701 v.z = (d & 0x3ff00000) >> 20;
6702 v.w = (d & 0xc0000000) >> 30;
6703
6704 return v;
6705}
6706
6707static BOOL weld_dec3n(void *to, void *from, FLOAT epsilon)
6708{
6709 const UINT MAX_DEC3N = 511;
6710 DWORD *d1 = to;
6711 DWORD *d2 = from;
6712 struct dec3n v1 = dword_to_dec3n(*d1);
6713 struct dec3n v2 = dword_to_dec3n(*d2);
6714 INT scaled_epsilon = (INT)(epsilon * MAX_DEC3N);
6715 INT diff_x = abs(v1.x - v2.x);
6716 INT diff_y = abs(v1.y - v2.y);
6717 INT diff_z = abs(v1.z - v2.z);
6718 INT diff_w = abs(v1.w - v2.w);
6719 INT max_abs_diff = max(diff_x, diff_y);
6720 max_abs_diff = max(diff_z, max_abs_diff);
6721 max_abs_diff = max(diff_w, max_abs_diff);
6722
6723 if (max_abs_diff <= scaled_epsilon)
6724 {
6725 memcpy(to, from, sizeof(DWORD));
6726
6727 return TRUE;
6728 }
6729
6730 return FALSE;
6731}
6732
6733static BOOL weld_float16_2(void *to, void *from, FLOAT epsilon)
6734{
6735 D3DXFLOAT16 *v1_float16 = to;
6736 D3DXFLOAT16 *v2_float16 = from;
6737 FLOAT diff_x;
6738 FLOAT diff_y;
6739 FLOAT max_abs_diff;
6740#define NUM_ELEM 2
6741 FLOAT v1[NUM_ELEM];
6742 FLOAT v2[NUM_ELEM];
6743
6744 D3DXFloat16To32Array(v1, v1_float16, NUM_ELEM);
6745 D3DXFloat16To32Array(v2, v2_float16, NUM_ELEM);
6746
6747 diff_x = fabsf(v1[0] - v2[0]);
6748 diff_y = fabsf(v1[1] - v2[1]);
6749 max_abs_diff = max(diff_x, diff_y);
6750
6751 if (max_abs_diff <= epsilon)
6752 {
6753 memcpy(to, from, NUM_ELEM * sizeof(D3DXFLOAT16));
6754
6755 return TRUE;
6756 }
6757
6758 return FALSE;
6759#undef NUM_ELEM
6760}
6761
6762static BOOL weld_float16_4(void *to, void *from, FLOAT epsilon)
6763{
6764 D3DXFLOAT16 *v1_float16 = to;
6765 D3DXFLOAT16 *v2_float16 = from;
6766 FLOAT diff_x;
6767 FLOAT diff_y;
6768 FLOAT diff_z;
6769 FLOAT diff_w;
6770 FLOAT max_abs_diff;
6771#define NUM_ELEM 4
6772 FLOAT v1[NUM_ELEM];
6773 FLOAT v2[NUM_ELEM];
6774
6775 D3DXFloat16To32Array(v1, v1_float16, NUM_ELEM);
6776 D3DXFloat16To32Array(v2, v2_float16, NUM_ELEM);
6777
6778 diff_x = fabsf(v1[0] - v2[0]);
6779 diff_y = fabsf(v1[1] - v2[1]);
6780 diff_z = fabsf(v1[2] - v2[2]);
6781 diff_w = fabsf(v1[3] - v2[3]);
6782 max_abs_diff = max(diff_x, diff_y);
6783 max_abs_diff = max(diff_z, max_abs_diff);
6784 max_abs_diff = max(diff_w, max_abs_diff);
6785
6786 if (max_abs_diff <= epsilon)
6787 {
6788 memcpy(to, from, NUM_ELEM * sizeof(D3DXFLOAT16));
6789
6790 return TRUE;
6791 }
6792
6793 return FALSE;
6794#undef NUM_ELEM
6795}
6796
6797/* Sets the vertex components to the same value if they are within epsilon. */
6798static BOOL weld_component(void *to, void *from, D3DDECLTYPE type, FLOAT epsilon)
6799{
6800 /* Quiet FIXMEs as this is in a loop with potentially thousand of iterations. */
6801 BOOL fixme_once_unused = FALSE;
6802 BOOL fixme_once_unknown = FALSE;
6803
6804 switch (type)
6805 {
6806 case D3DDECLTYPE_FLOAT1:
6807 return weld_float1(to, from, epsilon);
6808
6809 case D3DDECLTYPE_FLOAT2:
6810 return weld_float2(to, from, epsilon);
6811
6812 case D3DDECLTYPE_FLOAT3:
6813 return weld_float3(to, from, epsilon);
6814
6815 case D3DDECLTYPE_FLOAT4:
6816 return weld_float4(to, from, epsilon);
6817
6819 return weld_d3dcolor(to, from, epsilon);
6820
6821 case D3DDECLTYPE_UBYTE4:
6822 return weld_ubyte4(to, from, epsilon);
6823
6824 case D3DDECLTYPE_SHORT2:
6825 return weld_short2(to, from, epsilon);
6826
6827 case D3DDECLTYPE_SHORT4:
6828 return weld_short4(to, from, epsilon);
6829
6831 return weld_ubyte4n(to, from, epsilon);
6832
6834 return weld_short2n(to, from, epsilon);
6835
6837 return weld_short4n(to, from, epsilon);
6838
6840 return weld_ushort2n(to, from, epsilon);
6841
6843 return weld_ushort4n(to, from, epsilon);
6844
6845 case D3DDECLTYPE_UDEC3:
6846 return weld_udec3(to, from, epsilon);
6847
6848 case D3DDECLTYPE_DEC3N:
6849 return weld_dec3n(to, from, epsilon);
6850
6852 return weld_float16_2(to, from, epsilon);
6853
6855 return weld_float16_4(to, from, epsilon);
6856
6857 case D3DDECLTYPE_UNUSED:
6858 if (!fixme_once_unused++)
6859 FIXME("D3DDECLTYPE_UNUSED welding not implemented.\n");
6860 break;
6861
6862 default:
6863 if (!fixme_once_unknown++)
6864 FIXME("Welding of unknown declaration type %d is not implemented.\n", type);
6865 break;
6866 }
6867
6868 return FALSE;
6869}
6870
6871static FLOAT get_component_epsilon(const D3DVERTEXELEMENT9 *decl_ptr, const D3DXWELDEPSILONS *epsilons)
6872{
6873 FLOAT epsilon = 0.0f;
6874 /* Quiet FIXMEs as this is in a loop with potentially thousand of iterations. */
6875 static BOOL fixme_once_blendindices = FALSE;
6876 static BOOL fixme_once_positiont = FALSE;
6877 static BOOL fixme_once_fog = FALSE;
6878 static BOOL fixme_once_depth = FALSE;
6879 static BOOL fixme_once_sample = FALSE;
6880 static BOOL fixme_once_unknown = FALSE;
6881
6882 switch (decl_ptr->Usage)
6883 {
6885 epsilon = epsilons->Position;
6886 break;
6888 epsilon = epsilons->BlendWeights;
6889 break;
6891 epsilon = epsilons->Normals;
6892 break;
6893 case D3DDECLUSAGE_PSIZE:
6894 epsilon = epsilons->PSize;
6895 break;
6897 {
6898 BYTE usage_index = decl_ptr->UsageIndex;
6899 if (usage_index > 7)
6900 usage_index = 7;
6901 epsilon = epsilons->Texcoords[usage_index];
6902 break;
6903 }
6905 epsilon = epsilons->Tangent;
6906 break;
6908 epsilon = epsilons->Binormal;
6909 break;
6911 epsilon = epsilons->TessFactor;
6912 break;
6913 case D3DDECLUSAGE_COLOR:
6914 if (decl_ptr->UsageIndex == 0)
6915 epsilon = epsilons->Diffuse;
6916 else if (decl_ptr->UsageIndex == 1)
6917 epsilon = epsilons->Specular;
6918 else
6919 epsilon = 1e-6f;
6920 break;
6922 if (!fixme_once_blendindices++)
6923 FIXME("D3DDECLUSAGE_BLENDINDICES welding not implemented.\n");
6924 break;
6926 if (!fixme_once_positiont++)
6927 FIXME("D3DDECLUSAGE_POSITIONT welding not implemented.\n");
6928 break;
6929 case D3DDECLUSAGE_FOG:
6930 if (!fixme_once_fog++)
6931 FIXME("D3DDECLUSAGE_FOG welding not implemented.\n");
6932 break;
6933 case D3DDECLUSAGE_DEPTH:
6934 if (!fixme_once_depth++)
6935 FIXME("D3DDECLUSAGE_DEPTH welding not implemented.\n");
6936 break;
6938 if (!fixme_once_sample++)
6939 FIXME("D3DDECLUSAGE_SAMPLE welding not implemented.\n");
6940 break;
6941 default:
6942 if (!fixme_once_unknown++)
6943 FIXME("Unknown usage %x\n", decl_ptr->Usage);
6944 break;
6945 }
6946
6947 return epsilon;
6948}
6949
6950/* Helper function for reading a 32-bit index buffer. */
6951static inline DWORD read_ib(void *index_buffer, BOOL indices_are_32bit,
6952 DWORD index)
6953{
6954 if (indices_are_32bit)
6955 {
6956 DWORD *indices = index_buffer;
6957 return indices[index];
6958 }
6959 else
6960 {
6961 WORD *indices = index_buffer;
6962 return indices[index];
6963 }
6964}
6965
6966/* Helper function for writing to a 32-bit index buffer. */
6967static inline void write_ib(void *index_buffer, BOOL indices_are_32bit,
6969{
6970 if (indices_are_32bit)
6971 {
6972 DWORD *indices = index_buffer;
6973 indices[index] = value;
6974 }
6975 else
6976 {
6977 WORD *indices = index_buffer;
6978 indices[index] = value;
6979 }
6980}
6981
6982/*************************************************************************
6983 * D3DXWeldVertices (D3DX9_36.@)
6984 *
6985 * Welds together similar vertices. The similarity between vert-
6986 * ices can be the position and other components such as
6987 * normal and color.
6988 *
6989 * PARAMS
6990 * mesh [I] Mesh which vertices will be welded together.
6991 * flags [I] D3DXWELDEPSILONSFLAGS specifying how to weld.
6992 * epsilons [I] How similar a component needs to be for welding.
6993 * adjacency [I] Which faces are adjacent to other faces.
6994 * adjacency_out [O] Updated adjacency after welding.
6995 * face_remap_out [O] Which faces the old faces have been mapped to.
6996 * vertex_remap_out [O] Which vertices the old vertices have been mapped to.
6997 *
6998 * RETURNS
6999 * Success: D3D_OK.
7000 * Failure: D3DERR_INVALIDCALL, E_OUTOFMEMORY.
7001 *
7002 * BUGS
7003 * Attribute sorting not implemented.
7004 *
7005 */
7007 const DWORD *adjacency, DWORD *adjacency_out, DWORD *face_remap_out, ID3DXBuffer **vertex_remap_out)
7008{
7009 DWORD *adjacency_generated = NULL;
7010 const DWORD *adjacency_ptr;
7011 DWORD *attributes = NULL;
7012 const FLOAT DEFAULT_EPSILON = 1.0e-6f;
7013 HRESULT hr;
7014 DWORD i;
7015 void *indices = NULL;
7016 BOOL indices_are_32bit = mesh->lpVtbl->GetOptions(mesh) & D3DXMESH_32BIT;
7017 DWORD optimize_flags;
7018 DWORD *point_reps = NULL;
7020 DWORD *vertex_face_map = NULL;
7021 BYTE *vertices = NULL;
7022
7023 TRACE("mesh %p, flags %#x, epsilons %p, adjacency %p, adjacency_out %p, face_remap_out %p, vertex_remap_out %p.\n",
7024 mesh, flags, epsilons, adjacency, adjacency_out, face_remap_out, vertex_remap_out);
7025
7026 if (flags == 0)
7027 {
7028 WARN("No flags are undefined. Using D3DXWELDEPSILONS_WELDPARTIALMATCHES instead.\n");
7030 }
7031
7032 if (adjacency) /* Use supplied adjacency. */
7033 {
7034 adjacency_ptr = adjacency;
7035 }
7036 else /* Adjacency has to be generated. */
7037 {
7038 adjacency_generated = HeapAlloc(GetProcessHeap(), 0, 3 * This->numfaces * sizeof(*adjacency_generated));
7039 if (!adjacency_generated)
7040 {
7041 ERR("Couldn't allocate memory for adjacency_generated.\n");
7042 hr = E_OUTOFMEMORY;
7043 goto cleanup;
7044 }
7045 hr = mesh->lpVtbl->GenerateAdjacency(mesh, DEFAULT_EPSILON, adjacency_generated);
7046 if (FAILED(hr))
7047 {
7048 ERR("Couldn't generate adjacency.\n");
7049 goto cleanup;
7050 }
7051 adjacency_ptr = adjacency_generated;
7052 }
7053
7054 /* Point representation says which vertices can be replaced. */
7055 point_reps = HeapAlloc(GetProcessHeap(), 0, This->numvertices * sizeof(*point_reps));
7056 if (!point_reps)
7057 {
7058 hr = E_OUTOFMEMORY;
7059 ERR("Couldn't allocate memory for point_reps.\n");
7060 goto cleanup;
7061 }
7062 hr = mesh->lpVtbl->ConvertAdjacencyToPointReps(mesh, adjacency_ptr, point_reps);
7063 if (FAILED(hr))
7064 {
7065 ERR("ConvertAdjacencyToPointReps failed.\n");
7066 goto cleanup;
7067 }
7068
7069 hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, &indices);
7070 if (FAILED(hr))
7071 {
7072 ERR("Couldn't lock index buffer.\n");
7073 goto cleanup;
7074 }
7075
7076 hr = mesh->lpVtbl->LockAttributeBuffer(mesh, 0, &attributes);
7077 if (FAILED(hr))
7078 {
7079 ERR("Couldn't lock attribute buffer.\n");
7080 goto cleanup;
7081 }
7082 vertex_face_map = HeapAlloc(GetProcessHeap(), 0, This->numvertices * sizeof(*vertex_face_map));
7083 if (!vertex_face_map)
7084 {
7085 hr = E_OUTOFMEMORY;
7086 ERR("Couldn't allocate memory for vertex_face_map.\n");
7087 goto cleanup;
7088 }
7089 /* Build vertex face map, so that a vertex's face can be looked up. */
7090 for (i = 0; i < This->numfaces; i++)
7091 {
7092 DWORD j;
7093 for (j = 0; j < 3; j++)
7094 {
7095 DWORD index = read_ib(indices, indices_are_32bit, 3*i + j);
7096 vertex_face_map[index] = i;
7097 }
7098 }
7099
7101 {
7102 hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, (void**)&vertices);
7103 if (FAILED(hr))
7104 {
7105 ERR("Couldn't lock vertex buffer.\n");
7106 goto cleanup;
7107 }
7108 /* For each vertex that can be removed, compare its vertex components
7109 * with the vertex components from the vertex that can replace it. A
7110 * vertex is only fully replaced if all the components match and the
7111 * flag D3DXWELDEPSILONS_DONOTREMOVEVERTICES is not set, and they
7112 * belong to the same attribute group. Otherwise the vertex components
7113 * that are within epsilon are set to the same value.
7114 */
7115 for (i = 0; i < 3 * This->numfaces; i++)
7116 {
7117 D3DVERTEXELEMENT9 *decl_ptr;
7118 DWORD vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
7119 DWORD num_vertex_components;
7120 INT matches = 0;
7121 BOOL all_match;
7122 DWORD index = read_ib(indices, indices_are_32bit, i);
7123
7124 for (decl_ptr = This->cached_declaration, num_vertex_components = 0; decl_ptr->Stream != 0xFF; decl_ptr++, num_vertex_components++)
7125 {
7126 BYTE *to = &vertices[vertex_size*index + decl_ptr->Offset];
7127 BYTE *from = &vertices[vertex_size*point_reps[index] + decl_ptr->Offset];
7128 FLOAT epsilon = get_component_epsilon(decl_ptr, epsilons);
7129
7130 /* Don't weld self */
7131 if (index == point_reps[index])
7132 {
7133 matches++;
7134 continue;
7135 }
7136
7137 if (weld_component(to, from, decl_ptr->Type, epsilon))
7138 matches++;
7139 }
7140
7141 all_match = (num_vertex_components == matches);
7142 if (all_match && !(flags & D3DXWELDEPSILONS_DONOTREMOVEVERTICES))
7143 {
7144 DWORD to_face = vertex_face_map[index];
7145 DWORD from_face = vertex_face_map[point_reps[index]];
7146 if(attributes[to_face] != attributes[from_face] && !(flags & D3DXWELDEPSILONS_DONOTSPLIT))
7147 continue;
7148 write_ib(indices, indices_are_32bit, i, point_reps[index]);
7149 }
7150 }
7151 mesh->lpVtbl->UnlockVertexBuffer(mesh);
7152 vertices = NULL;
7153 }
7155 {
7156 for (i = 0; i < 3 * This->numfaces; i++)
7157 {
7158 DWORD index = read_ib(indices, indices_are_32bit, i);
7159 DWORD to_face = vertex_face_map[index];
7160 DWORD from_face = vertex_face_map[point_reps[index]];
7161 if(attributes[to_face] != attributes[from_face] && !(flags & D3DXWELDEPSILONS_DONOTSPLIT))
7162 continue;
7163 write_ib(indices, indices_are_32bit, i, point_reps[index]);
7164 }
7165 }
7166 mesh->lpVtbl->UnlockAttributeBuffer(mesh);
7167 attributes = NULL;
7168 mesh->lpVtbl->UnlockIndexBuffer(mesh);
7169 indices = NULL;
7170
7171 /* Compact mesh using OptimizeInplace */
7172 optimize_flags = D3DXMESHOPT_COMPACT;
7173 hr = mesh->lpVtbl->OptimizeInplace(mesh, optimize_flags, adjacency_ptr, adjacency_out, face_remap_out, vertex_remap_out);
7174 if (FAILED(hr))
7175 {
7176 ERR("Couldn't compact mesh.\n");
7177 goto cleanup;
7178 }
7179
7180 hr = D3D_OK;
7181cleanup:
7182 HeapFree(GetProcessHeap(), 0, adjacency_generated);
7183 HeapFree(GetProcessHeap(), 0, point_reps);
7184 HeapFree(GetProcessHeap(), 0, vertex_face_map);
7185 if (attributes) mesh->lpVtbl->UnlockAttributeBuffer(mesh);
7186 if (indices) mesh->lpVtbl->UnlockIndexBuffer(mesh);
7187 if (vertices) mesh->lpVtbl->UnlockVertexBuffer(mesh);
7188
7189 return hr;
7190}
7191
7192
7193/*************************************************************************
7194 * D3DXOptimizeVertices (D3DX9_36.@)
7195 */
7197 UINT num_vertices, BOOL indices_are_32bit, DWORD *vertex_remap)
7198{
7199 UINT i;
7200
7201 FIXME("indices %p, num_faces %u, num_vertices %u, indices_are_32bit %#x, vertex_remap %p semi-stub.\n",
7202 indices, num_faces, num_vertices, indices_are_32bit, vertex_remap);
7203
7204 if (!vertex_remap)
7205 {
7206 WARN("vertex remap pointer is NULL.\n");
7207 return D3DERR_INVALIDCALL;
7208 }
7209
7210 for (i = 0; i < num_vertices; i++)
7211 {
7212 vertex_remap[i] = i;
7213 }
7214
7215 return D3D_OK;
7216}
7217
7218
7219/*************************************************************************
7220 * D3DXOptimizeFaces (D3DX9_36.@)
7221 *
7222 * Re-orders the faces so the vertex cache is used optimally.
7223 *
7224 * PARAMS
7225 * indices [I] Pointer to an index buffer belonging to a mesh.
7226 * num_faces [I] Number of faces in the mesh.
7227 * num_vertices [I] Number of vertices in the mesh.
7228 * indices_are_32bit [I] Specifies whether indices are 32- or 16-bit.
7229 * face_remap [I/O] The new order the faces should be drawn in.
7230 *
7231 * RETURNS
7232 * Success: D3D_OK.
7233 * Failure: D3DERR_INVALIDCALL.
7234 *
7235 * BUGS
7236 * The face re-ordering does not use the vertex cache optimally.
7237 *
7238 */
7240 UINT num_vertices, BOOL indices_are_32bit, DWORD *face_remap)
7241{
7242 UINT i;
7243 UINT j = num_faces - 1;
7244 UINT limit_16_bit = 2 << 15; /* According to MSDN */
7245 HRESULT hr = D3D_OK;
7246
7247 FIXME("indices %p, num_faces %u, num_vertices %u, indices_are_32bit %#x, face_remap %p semi-stub. "
7248 "Face order will not be optimal.\n",
7249 indices, num_faces, num_vertices, indices_are_32bit, face_remap);
7250
7251 if (!indices_are_32bit && num_faces >= limit_16_bit)
7252 {
7253 WARN("Number of faces must be less than %d when using 16-bit indices.\n",
7254 limit_16_bit);
7256 goto error;
7257 }
7258
7259 if (!face_remap)
7260 {
7261 WARN("Face remap pointer is NULL.\n");
7263 goto error;
7264 }
7265
7266 /* The faces are drawn in reverse order for simple meshes. This ordering
7267 * is not optimal for complicated meshes, but will not break anything
7268 * either. The ordering should be changed to take advantage of the vertex
7269 * cache on the graphics card.
7270 *
7271 * TODO Re-order to take advantage of vertex cache.
7272 */
7273 for (i = 0; i < num_faces; i++)
7274 {
7275 face_remap[i] = j--;
7276 }
7277
7278 return D3D_OK;
7279
7280error:
7281 return hr;
7282}
7283
7285 DWORD vertex_stride, DWORD index)
7286{
7287 return (D3DXVECTOR3 *)(vertices + declaration->Offset + index * vertex_stride);
7288}
7289
7291 DWORD vertex_stride, DWORD index)
7292{
7293 D3DXVECTOR3 vec3 = {0};
7294 const D3DXVECTOR3 *src = vertex_element_vec3(vertices, declaration, vertex_stride, index);
7295
7296 switch (declaration->Type)
7297 {
7298 case D3DDECLTYPE_FLOAT1:
7299 vec3.x = src->x;
7300 break;
7301 case D3DDECLTYPE_FLOAT2:
7302 vec3.x = src->x;
7303 vec3.y = src->y;
7304 break;
7305 case D3DDECLTYPE_FLOAT3:
7306 case D3DDECLTYPE_FLOAT4:
7307 vec3 = *src;
7308 break;
7309 default:
7310 ERR("Cannot read vec3\n");
7311 break;
7312 }
7313
7314 return vec3;
7315}
7316
7317/*************************************************************************
7318 * D3DXComputeTangentFrameEx (D3DX9_36.@)
7319 */
7320HRESULT WINAPI D3DXComputeTangentFrameEx(ID3DXMesh *mesh, DWORD texture_in_semantic, DWORD texture_in_index,
7321 DWORD u_partial_out_semantic, DWORD u_partial_out_index, DWORD v_partial_out_semantic,
7322 DWORD v_partial_out_index, DWORD normal_out_semantic, DWORD normal_out_index, DWORD options,
7323 const DWORD *adjacency, float partial_edge_threshold, float singular_point_threshold,
7324 float normal_edge_threshold, ID3DXMesh **mesh_out, ID3DXBuffer **vertex_mapping)
7325{
7326 HRESULT hr;
7327 void *indices = NULL;
7328 BYTE *vertices = NULL;
7329 DWORD *point_reps = NULL;
7330 size_t normal_size;
7331 BOOL indices_are_32bit;
7332 DWORD i, j, num_faces, num_vertices, vertex_stride;
7334 D3DVERTEXELEMENT9 *position_declaration = NULL, *normal_declaration = NULL;
7336
7337 TRACE("mesh %p, texture_in_semantic %u, texture_in_index %u, u_partial_out_semantic %u, u_partial_out_index %u, "
7338 "v_partial_out_semantic %u, v_partial_out_index %u, normal_out_semantic %u, normal_out_index %u, "
7339 "options %#x, adjacency %p, partial_edge_threshold %f, singular_point_threshold %f, "
7340 "normal_edge_threshold %f, mesh_out %p, vertex_mapping %p\n",
7341 mesh, texture_in_semantic, texture_in_index, u_partial_out_semantic, u_partial_out_index,
7342 v_partial_out_semantic, v_partial_out_index, normal_out_semantic, normal_out_index, options, adjacency,
7343 partial_edge_threshold, singular_point_threshold, normal_edge_threshold, mesh_out, vertex_mapping);
7344
7345 if (!mesh)
7346 {
7347 WARN("mesh is NULL\n");
7348 return D3DERR_INVALIDCALL;
7349 }
7350
7351 if (weighting_method == (D3DXTANGENT_WEIGHT_EQUAL | D3DXTANGENT_WEIGHT_BY_AREA))
7352 {
7353 WARN("D3DXTANGENT_WEIGHT_BY_AREA and D3DXTANGENT_WEIGHT_EQUAL are mutally exclusive\n");
7354 return D3DERR_INVALIDCALL;
7355 }
7356
7357 if (u_partial_out_semantic != D3DX_DEFAULT)
7358 {
7359 FIXME("tangent vectors computation is not supported\n");
7360 return E_NOTIMPL;
7361 }
7362
7363 if (v_partial_out_semantic != D3DX_DEFAULT)
7364 {
7365 FIXME("binormal vectors computation is not supported\n");
7366 return E_NOTIMPL;
7367 }
7368
7370 {
7371 FIXME("unsupported options %#x\n", options);
7372 return E_NOTIMPL;
7373 }
7374
7376 {
7377 FIXME("only normals computation is supported\n");
7378 return E_NOTIMPL;
7379 }
7380
7381 if (!(options & D3DXTANGENT_GENERATE_IN_PLACE) || mesh_out || vertex_mapping)
7382 {
7383 FIXME("only D3DXTANGENT_GENERATE_IN_PLACE is supported\n");
7384 return E_NOTIMPL;
7385 }
7386
7387 if (FAILED(hr = mesh->lpVtbl->GetDeclaration(mesh, declaration)))
7388 return hr;
7389
7390 for (i = 0; declaration[i].Stream != 0xff; i++)
7391 {
7392 if (declaration[i].Usage == D3DDECLUSAGE_POSITION && !declaration[i].UsageIndex)
7393 position_declaration = &declaration[i];
7394 if (declaration[i].Usage == normal_out_semantic && declaration[i].UsageIndex == normal_out_index)
7395 normal_declaration = &declaration[i];
7396 }
7397
7398 if (!position_declaration || !normal_declaration)
7399 return D3DERR_INVALIDCALL;
7400
7401 if (normal_declaration->Type == D3DDECLTYPE_FLOAT3)
7402 {
7403 normal_size = sizeof(D3DXVECTOR3);
7404 }
7405 else if (normal_declaration->Type == D3DDECLTYPE_FLOAT4)
7406 {
7407 normal_size = sizeof(D3DXVECTOR4);
7408 }
7409 else
7410 {
7411 WARN("unsupported normals type %u\n", normal_declaration->Type);
7412 return D3DERR_INVALIDCALL;
7413 }
7414
7415 num_faces = mesh->lpVtbl->GetNumFaces(mesh);
7416 num_vertices = mesh->lpVtbl->GetNumVertices(mesh);
7417 vertex_stride = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
7418 indices_are_32bit = mesh->lpVtbl->GetOptions(mesh) & D3DXMESH_32BIT;
7419
7420 point_reps = HeapAlloc(GetProcessHeap(), 0, num_vertices * sizeof(*point_reps));
7421 if (!point_reps)
7422 {
7423 hr = E_OUTOFMEMORY;
7424 goto done;
7425 }
7426
7427 if (adjacency)
7428 {
7429 if (FAILED(hr = mesh->lpVtbl->ConvertAdjacencyToPointReps(mesh, adjacency, point_reps)))
7430 goto done;
7431 }
7432 else
7433 {
7434 for (i = 0; i < num_vertices; i++)
7435 point_reps[i] = i;
7436 }
7437
7438 if (FAILED(hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, &indices)))
7439 goto done;
7440
7441 if (FAILED(hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, (void **)&vertices)))
7442 goto done;
7443
7444 for (i = 0; i < num_vertices; i++)
7445 {
7446 static const D3DXVECTOR4 default_vector = {0.0f, 0.0f, 0.0f, 1.0f};
7447 void *normal = vertices + normal_declaration->Offset + i * vertex_stride;
7448
7449 memcpy(normal, &default_vector, normal_size);
7450 }
7451
7452 for (i = 0; i < num_faces; i++)
7453 {
7454 float denominator, weights[3];
7455 D3DXVECTOR3 a, b, cross, face_normal;
7456 const DWORD face_indices[3] =
7457 {
7458 read_ib(indices, indices_are_32bit, 3 * i + 0),
7459 read_ib(indices, indices_are_32bit, 3 * i + 1),
7460 read_ib(indices, indices_are_32bit, 3 * i + 2)
7461 };
7462 const D3DXVECTOR3 v0 = read_vec3(vertices, position_declaration, vertex_stride, face_indices[0]);
7463 const D3DXVECTOR3 v1 = read_vec3(vertices, position_declaration, vertex_stride, face_indices[1]);
7464 const D3DXVECTOR3 v2 = read_vec3(vertices, position_declaration, vertex_stride, face_indices[2]);
7465
7466 D3DXVec3Cross(&cross, D3DXVec3Subtract(&a, &v0, &v1), D3DXVec3Subtract(&b, &v0, &v2));
7467
7468 switch (weighting_method)
7469 {
7471 weights[0] = weights[1] = weights[2] = 1.0f;
7472 break;
7474 weights[0] = weights[1] = weights[2] = D3DXVec3Length(&cross);
7475 break;
7476 default:
7477 /* weight by angle */
7478 denominator = D3DXVec3Length(&a) * D3DXVec3Length(&b);
7479 if (!denominator)
7480 weights[0] = 0.0f;
7481 else
7482 weights[0] = acosf(D3DXVec3Dot(&a, &b) / denominator);
7483
7484 D3DXVec3Subtract(&a, &v1, &v0);
7485 D3DXVec3Subtract(&b, &v1, &v2);
7486 denominator = D3DXVec3Length(&a) * D3DXVec3Length(&b);
7487 if (!denominator)
7488 weights[1] = 0.0f;
7489 else
7490 weights[1] = acosf(D3DXVec3Dot(&a, &b) / denominator);
7491
7492 D3DXVec3Subtract(&a, &v2, &v0);
7493 D3DXVec3Subtract(&b, &v2, &v1);
7494 denominator = D3DXVec3Length(&a) * D3DXVec3Length(&b);
7495 if (!denominator)
7496 weights[2] = 0.0f;
7497 else
7498 weights[2] = acosf(D3DXVec3Dot(&a, &b) / denominator);
7499
7500 break;
7501 }
7502
7503 D3DXVec3Normalize(&face_normal, &cross);
7504
7505 for (j = 0; j < 3; j++)
7506 {
7508 DWORD rep_index = point_reps[face_indices[j]];
7509 D3DXVECTOR3 *rep_normal = vertex_element_vec3(vertices, normal_declaration, vertex_stride, rep_index);
7510
7511 D3DXVec3Scale(&normal, &face_normal, weights[j]);
7512 D3DXVec3Add(rep_normal, rep_normal, &normal);
7513 }
7514 }
7515
7516 for (i = 0; i < num_vertices; i++)
7517 {
7518 DWORD rep_index = point_reps[i];
7519 D3DXVECTOR3 *normal = vertex_element_vec3(vertices, normal_declaration, vertex_stride, i);
7520 D3DXVECTOR3 *rep_normal = vertex_element_vec3(vertices, normal_declaration, vertex_stride, rep_index);
7521
7522 if (i == rep_index)
7523 D3DXVec3Normalize(rep_normal, rep_normal);
7524 else
7525 *normal = *rep_normal;
7526 }
7527
7528 hr = D3D_OK;
7529
7530done:
7531 if (vertices)
7532 mesh->lpVtbl->UnlockVertexBuffer(mesh);
7533
7534 if (indices)
7535 mesh->lpVtbl->UnlockIndexBuffer(mesh);
7536
7537 HeapFree(GetProcessHeap(), 0, point_reps);
7538
7539 return hr;
7540}
7541
7542/*************************************************************************
7543 * D3DXComputeTangent (D3DX9_36.@)
7544 */
7545HRESULT WINAPI D3DXComputeTangent(ID3DXMesh *mesh, DWORD stage_idx, DWORD tangent_idx,
7546 DWORD binorm_idx, DWORD wrap, const DWORD *adjacency)
7547{
7548 TRACE("mesh %p, stage_idx %d, tangent_idx %d, binorm_idx %d, wrap %d, adjacency %p.\n",
7549 mesh, stage_idx, tangent_idx, binorm_idx, wrap, adjacency);
7550
7552 ( binorm_idx == D3DX_DEFAULT ) ? D3DX_DEFAULT : D3DDECLUSAGE_BINORMAL,
7553 binorm_idx,
7554 ( tangent_idx == D3DX_DEFAULT ) ? D3DX_DEFAULT : D3DDECLUSAGE_TANGENT,
7555 tangent_idx, D3DX_DEFAULT, 0,
7557 adjacency, -1.01f, -0.01f, -1.01f, NULL, NULL);
7558}
7559
7560/*************************************************************************
7561 * D3DXComputeNormals (D3DX9_36.@)
7562 */
7563HRESULT WINAPI D3DXComputeNormals(struct ID3DXBaseMesh *mesh, const DWORD *adjacency)
7564{
7565 TRACE("mesh %p, adjacency %p\n", mesh, adjacency);
7566
7567 if (mesh && (ID3DXMeshVtbl *)mesh->lpVtbl != &D3DXMesh_Vtbl)
7568 {
7569 ERR("Invalid virtual table\n");
7570 return D3DERR_INVALIDCALL;
7571 }
7572
7573 return D3DXComputeTangentFrameEx((ID3DXMesh *)mesh, D3DX_DEFAULT, 0,
7576 adjacency, -1.01f, -0.01f, -1.01f, NULL, NULL);
7577}
7578
7579/*************************************************************************
7580 * D3DXIntersect (D3DX9_36.@)
7581 */
7582HRESULT WINAPI D3DXIntersect(ID3DXBaseMesh *mesh, const D3DXVECTOR3 *ray_pos, const D3DXVECTOR3 *ray_dir,
7583 BOOL *hit, DWORD *face_index, float *u, float *v, float *distance, ID3DXBuffer **all_hits, DWORD *count_of_hits)
7584{
7585 FIXME("mesh %p, ray_pos %p, ray_dir %p, hit %p, face_index %p, u %p, v %p, distance %p, all_hits %p, "
7586 "count_of_hits %p stub!\n", mesh, ray_pos, ray_dir, hit, face_index, u, v, distance, all_hits, count_of_hits);
7587
7588 return E_NOTIMPL;
7589}
7590
7591HRESULT WINAPI D3DXTessellateNPatches(ID3DXMesh *mesh, const DWORD *adjacency_in, float num_segs,
7592 BOOL quadratic_normals, ID3DXMesh **mesh_out, ID3DXBuffer **adjacency_out)
7593{
7594 FIXME("mesh %p, adjacency_in %p, num_segs %f, quadratic_normals %d, mesh_out %p, adjacency_out %p stub.\n",
7595 mesh, adjacency_in, num_segs, quadratic_normals, mesh_out, adjacency_out);
7596
7597 return E_NOTIMPL;
7598}
7599
7600HRESULT WINAPI D3DXConvertMeshSubsetToSingleStrip(struct ID3DXBaseMesh *mesh_in, DWORD attribute_id,
7601 DWORD ib_flags, struct IDirect3DIndexBuffer9 **index_buffer, DWORD *index_count)
7602{
7603 FIXME("mesh_in %p, attribute_id %u, ib_flags %u, index_buffer %p, index_count %p stub.\n",
7604 mesh_in, attribute_id, ib_flags, index_buffer, index_count);
7605
7606 return E_NOTIMPL;
7607}
7608
7610{
7611 struct list entry;
7613};
7614
7616{
7617 struct frame_node *node;
7618
7619 if (!frame->pFrameFirstChild)
7620 return TRUE;
7621
7622 node = HeapAlloc(GetProcessHeap(), 0, sizeof(*node));
7623 if (!node)
7624 return FALSE;
7625
7626 node->frame = frame;
7627 list_add_tail(queue, &node->entry);
7628
7629 return TRUE;
7630}
7631
7632static void empty_frame_queue(struct list *queue)
7633{
7634 struct frame_node *cur, *cur2;
7636 {
7637 list_remove(&cur->entry);
7639 }
7640}
7641
7643{
7644 D3DXFRAME *found = NULL, *frame;
7645 struct list queue;
7646
7647 TRACE("root frame %p, name %s.\n", root, debugstr_a(name));
7648
7649 if (!root)
7650 return NULL;
7651
7652 list_init(&queue);
7653
7654 frame = (D3DXFRAME *)root;
7655
7656 for (;;)
7657 {
7658 struct frame_node *node;
7659
7660 while (frame)
7661 {
7662 if ((name && frame->Name && !strcmp(frame->Name, name)) || (!name && !frame->Name))
7663 {
7664 found = frame;
7665 goto cleanup;
7666 }
7667
7669 goto cleanup;
7670
7672 }
7673
7674 if (list_empty(&queue))
7675 break;
7676
7678 list_remove(&node->entry);
7679 frame = node->frame->pFrameFirstChild;
7681 }
7682
7683cleanup:
7685
7686 return found;
7687}
Type
Definition: Type.h:7
_STLP_VENDOR_CSTD::ldiv_t div(long __x, long __y)
Definition: _cstdlib.h:137
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
#define __cdecl
Definition: accygwin.h:79
unsigned int dir
Definition: maze.c:112
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedDecrement
Definition: armddk.h:52
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define index(s, c)
Definition: various.h:29
#define ARRAY_SIZE(A)
Definition: main.h:33
#define U(x)
Definition: wordpad.c:45
static void list_remove(struct list_entry *entry)
Definition: list.h:90
static int list_empty(struct list_entry *head)
Definition: list.h:58
static void list_add_tail(struct list_entry *head, struct list_entry *entry)
Definition: list.h:83
static void list_add_head(struct list_entry *head, struct list_entry *entry)
Definition: list.h:76
static void list_init(struct list_entry *head)
Definition: list.h:51
const GUID IID_IUnknown
#define FIXME(fmt,...)
Definition: debug.h:111
#define WARN(fmt,...)
Definition: debug.h:112
#define ERR(fmt,...)
Definition: debug.h:110
Definition: list.h:37
Definition: _queue.h:67
Definition: _stack.h:55
#define D3DXERR_INVALIDDATA
Definition: compiler.c:30
GLUquadricObj * cylinder
Definition: cylfrac.c:44
BYTE usage_idx
#define D3DFVF_DIFFUSE
Definition: d3d8types.h:122
#define D3DFVF_RESERVED2
Definition: d3d8types.h:136
#define D3DFVF_XYZ
Definition: d3d8types.h:113
#define D3DFVF_TEXCOUNT_SHIFT
Definition: d3d8types.h:125
#define D3DFVF_XYZB1
Definition: d3d8types.h:115
#define D3DFVF_LASTBETA_UBYTE4
Definition: d3d8types.h:135
#define D3DFVF_XYZB5
Definition: d3d8types.h:119
#define D3DFVF_XYZRHW
Definition: d3d8types.h:114
#define D3DUSAGE_NPATCHES
Definition: d3d8types.h:98
#define D3DFVF_XYZB4
Definition: d3d8types.h:118
#define D3DFVF_NORMAL
Definition: d3d8types.h:120
#define D3DFVF_XYZB3
Definition: d3d8types.h:117
#define D3DDP_MAXTEXCOORD
Definition: d3d8types.h:303
#define D3DUSAGE_POINTS
Definition: d3d8types.h:96
#define D3DUSAGE_DONOTCLIP
Definition: d3d8types.h:95
#define D3DCOLOR_ARGB(a, r, g, b)
Definition: d3d8types.h:41
@ D3DFMT_INDEX16
Definition: d3d8types.h:649
@ D3DFMT_INDEX32
Definition: d3d8types.h:650
#define D3DUSAGE_DYNAMIC
Definition: d3d8types.h:99
#define D3DFVF_TEXTUREFORMAT4
Definition: d3d8types.h:63
#define D3DFVF_XYZB2
Definition: d3d8types.h:116
#define D3DFVF_TEXTUREFORMAT3
Definition: d3d8types.h:62
#define D3DFVF_TEXCOUNT_MASK
Definition: d3d8types.h:124
#define D3DUSAGE_WRITEONLY
Definition: d3d8types.h:93
#define D3DFVF_TEXCOORDSIZE4(CoordIndex)
Definition: d3d8types.h:67
#define D3DFVF_TEXCOORDSIZE3(CoordIndex)
Definition: d3d8types.h:66
enum _D3DPOOL D3DPOOL
@ D3DPT_TRIANGLELIST
Definition: d3d8types.h:721
struct _D3DCOLORVALUE D3DCOLORVALUE
#define D3DFVF_TEXTUREFORMAT1
Definition: d3d8types.h:60
#define D3DFVF_PSIZE
Definition: d3d8types.h:121
#define D3DFVF_TEXTUREFORMAT2
Definition: d3d8types.h:61
#define D3DFVF_TEXCOORDSIZE2(CoordIndex)
Definition: d3d8types.h:65
#define D3DFVF_TEXCOORDSIZE1(CoordIndex)
Definition: d3d8types.h:64
@ D3DPOOL_DEFAULT
Definition: d3d8types.h:709
@ D3DPOOL_SYSTEMMEM
Definition: d3d8types.h:711
@ D3DPOOL_MANAGED
Definition: d3d8types.h:710
enum _D3DFORMAT D3DFORMAT
#define D3DFVF_TEX1
Definition: d3d8types.h:127
#define D3DUSAGE_SOFTWAREPROCESSING
Definition: d3d8types.h:94
#define D3DFVF_SPECULAR
Definition: d3d8types.h:123
#define D3DUSAGE_RTPATCHES
Definition: d3d8types.h:97
#define D3DFVF_POSITION_MASK
Definition: d3d8types.h:112
#define D3DFVF_RESERVED0
Definition: d3d8types.h:111
#define D3DLOCK_READONLY
Definition: d3d8types.h:69
#define IDirect3DIndexBuffer9_Unlock(p)
Definition: d3d9.h:776
#define IDirect3DVertexBuffer9_Unlock(p)
Definition: d3d9.h:708
#define IDirect3DDevice9_CreateIndexBuffer(p, a, b, c, d, e, f)
Definition: d3d9.h:1534
#define IDirect3DDevice9_SetIndices(p, a)
Definition: d3d9.h:1611
#define IDirect3DDevice9_DrawIndexedPrimitive(p, a, b, c, d, e, f)
Definition: d3d9.h:1589
#define IDirect3DDevice9_CreateVertexDeclaration(p, a, b)
Definition: d3d9.h:1593
#define IDirect3DVertexBuffer9_Release(p)
Definition: d3d9.h:696
#define IDirect3DIndexBuffer9_AddRef(p)
Definition: d3d9.h:763
#define IDirect3DVertexBuffer9_Lock(p, a, b, c, d)
Definition: d3d9.h:707
#define IDirect3DVertexBuffer9_GetDesc(p, a)
Definition: d3d9.h:709
#define IDirect3DVertexDeclaration9_Release(p)
Definition: d3d9.h:1185
#define IDirect3DVertexBuffer9_AddRef(p)
Definition: d3d9.h:695
#define IDirect3DDevice9_SetStreamSource(p, a, b, c, d)
Definition: d3d9.h:1607
#define IDirect3DDevice9_Release(p)
Definition: d3d9.h:1508
#define IDirect3DIndexBuffer9_Lock(p, a, b, c, d)
Definition: d3d9.h:775
#define IDirect3DDevice9_CreateVertexBuffer(p, a, b, c, d, e, f)
Definition: d3d9.h:1533
#define IDirect3DIndexBuffer9_Release(p)
Definition: d3d9.h:764
#define IDirect3DDevice9_AddRef(p)
Definition: d3d9.h:1507
#define IDirect3DDevice9_SetVertexDeclaration(p, a)
Definition: d3d9.h:1594
@ D3DDECLUSAGE_BLENDWEIGHT
Definition: d3d9types.h:221
@ D3DDECLUSAGE_BLENDINDICES
Definition: d3d9types.h:222
@ D3DDECLUSAGE_POSITIONT
Definition: d3d9types.h:229
@ D3DDECLUSAGE_TANGENT
Definition: d3d9types.h:226
@ D3DDECLUSAGE_TESSFACTOR
Definition: d3d9types.h:228
@ D3DDECLUSAGE_NORMAL
Definition: d3d9types.h:223
@ D3DDECLUSAGE_FOG
Definition: d3d9types.h:231
@ D3DDECLUSAGE_BINORMAL
Definition: d3d9types.h:227
@ D3DDECLUSAGE_TEXCOORD
Definition: d3d9types.h:225
@ D3DDECLUSAGE_DEPTH
Definition: d3d9types.h:232
@ D3DDECLUSAGE_POSITION
Definition: d3d9types.h:220
@ D3DDECLUSAGE_SAMPLE
Definition: d3d9types.h:233
@ D3DDECLUSAGE_PSIZE
Definition: d3d9types.h:224
@ D3DDECLUSAGE_COLOR
Definition: d3d9types.h:230
#define D3DFVF_LASTBETA_D3DCOLOR
Definition: d3d9types.h:160
@ D3DDECLTYPE_UBYTE4
Definition: d3d9types.h:260
@ D3DDECLTYPE_SHORT2
Definition: d3d9types.h:261
@ D3DDECLTYPE_FLOAT3
Definition: d3d9types.h:257
@ D3DDECLTYPE_UNUSED
Definition: d3d9types.h:273
@ D3DDECLTYPE_FLOAT1
Definition: d3d9types.h:255
@ D3DDECLTYPE_SHORT2N
Definition: d3d9types.h:265
@ D3DDECLTYPE_FLOAT16_4
Definition: d3d9types.h:272
@ D3DDECLTYPE_FLOAT16_2
Definition: d3d9types.h:271
@ D3DDECLTYPE_D3DCOLOR
Definition: d3d9types.h:259
@ D3DDECLTYPE_UDEC3
Definition: d3d9types.h:269
@ D3DDECLTYPE_SHORT4
Definition: d3d9types.h:262
@ D3DDECLTYPE_UBYTE4N
Definition: d3d9types.h:264
@ D3DDECLTYPE_USHORT4N
Definition: d3d9types.h:268
@ D3DDECLTYPE_DEC3N
Definition: d3d9types.h:270
@ D3DDECLTYPE_SHORT4N
Definition: d3d9types.h:266
@ D3DDECLTYPE_FLOAT2
Definition: d3d9types.h:256
@ D3DDECLTYPE_FLOAT4
Definition: d3d9types.h:258
@ D3DDECLTYPE_USHORT2N
Definition: d3d9types.h:267
#define D3DDECL_END()
Definition: d3d9types.h:311
#define D3DFVF_XYZW
Definition: d3d9types.h:143
enum _D3DDECLTYPE D3DDECLTYPE
enum _D3DDECLUSAGE D3DDECLUSAGE
@ D3DDECLMETHOD_DEFAULT
Definition: d3d9types.h:242
#define D3D_OK
Definition: d3d.h:106
static SIZE_T datasize
Definition: asm.c:30
#define D3DERR_INVALIDCALL
struct ID3DXBuffer ID3DXBuffer
Definition: d3dx8core.h:51
#define D3DX_DEFAULT
Definition: d3dx9.h:24
HRESULT map_view_of_file(const WCHAR *filename, void **buffer, DWORD *length) DECLSPEC_HIDDEN
Definition: util.c:120
HRESULT load_resource_into_memory(HMODULE module, HRSRC resinfo, void **buffer, DWORD *length) DECLSPEC_HIDDEN
Definition: util.c:170
@ D3DXMESHTYPE_MESH
Definition: d3dx9anim.h:29
#define ID3DXBuffer_GetBufferPointer(p)
Definition: d3dx9core.h:85
#define ID3DXBuffer_Release(p)
Definition: d3dx9core.h:83
#define D3DX_PI
Definition: d3dx9math.h:27
struct _D3DVECTOR D3DXVECTOR3
Definition: d3dx9math.h:97
#define D3DXToRadian(degree)
Definition: d3dx9math.h:33
@ D3DXTANGENT_WEIGHT_BY_AREA
Definition: d3dx9mesh.h:118
@ D3DXTANGENT_CALCULATE_NORMALS
Definition: d3dx9mesh.h:121
@ D3DXTANGENT_WEIGHT_EQUAL
Definition: d3dx9mesh.h:119
@ D3DXTANGENT_GENERATE_IN_PLACE
Definition: d3dx9mesh.h:122
@ D3DXTANGENT_ORTHOGONALIZE_FROM_U
Definition: d3dx9mesh.h:117
@ D3DXTANGENT_WRAP_UV
Definition: d3dx9mesh.h:113
@ MAX_FVF_DECL_SIZE
Definition: d3dx9mesh.h:41
@ D3DXEDT_FLOATS
Definition: d3dx9mesh.h:142
@ D3DXEDT_STRING
Definition: d3dx9mesh.h:141
struct _D3DXEFFECTDEFAULT D3DXEFFECTDEFAULT
@ D3DXMESHOPT_DONOTSPLIT
Definition: d3dx9mesh.h:78
@ D3DXMESHOPT_STRIPREORDER
Definition: d3dx9mesh.h:76
@ D3DXMESHOPT_IGNOREVERTS
Definition: d3dx9mesh.h:77
@ D3DXMESHOPT_ATTRSORT
Definition: d3dx9mesh.h:74
@ D3DXMESHOPT_VERTEXCACHE
Definition: d3dx9mesh.h:75
@ D3DXMESHOPT_COMPACT
Definition: d3dx9mesh.h:73
D3DXCLEANTYPE
Definition: d3dx9mesh.h:100
@ D3DXWELDEPSILONS_DONOTREMOVEVERTICES
Definition: d3dx9mesh.h:151
@ D3DXWELDEPSILONS_DONOTSPLIT
Definition: d3dx9mesh.h:152
@ D3DXWELDEPSILONS_WELDALL
Definition: d3dx9mesh.h:149
@ D3DXWELDEPSILONS_WELDPARTIALMATCHES
Definition: d3dx9mesh.h:150
struct _D3DXMATERIAL D3DXMATERIAL
@ D3DXMESH_NPATCHES
Definition: d3dx9mesh.h:50
@ D3DXMESH_VB_MANAGED
Definition: d3dx9mesh.h:52
@ D3DXMESH_USEHWONLY
Definition: d3dx9mesh.h:62
@ D3DXMESH_32BIT
Definition: d3dx9mesh.h:46
@ D3DXMESH_DONOTCLIP
Definition: d3dx9mesh.h:47
@ D3DXMESH_VB_SOFTWAREPROCESSING
Definition: d3dx9mesh.h:55
@ D3DXMESH_VB_WRITEONLY
Definition: d3dx9mesh.h:53
@ D3DXMESH_POINTS
Definition: d3dx9mesh.h:48
@ D3DXMESH_IB_MANAGED
Definition: d3dx9mesh.h:57
@ D3DXMESH_IB_WRITEONLY
Definition: d3dx9mesh.h:58
@ D3DXMESH_VB_SYSTEMMEM
Definition: d3dx9mesh.h:51
@ D3DXMESH_RTPATCHES
Definition: d3dx9mesh.h:49
@ D3DXMESH_IB_SYSTEMMEM
Definition: d3dx9mesh.h:56
@ D3DXMESH_IB_SOFTWAREPROCESSING
Definition: d3dx9mesh.h:60
@ D3DXMESH_MANAGED
Definition: d3dx9mesh.h:64
@ D3DXMESH_VB_SHARE
Definition: d3dx9mesh.h:61
@ D3DXMESH_IB_DYNAMIC
Definition: d3dx9mesh.h:59
@ D3DXMESH_VB_DYNAMIC
Definition: d3dx9mesh.h:54
struct _D3DXEFFECTINSTANCE D3DXEFFECTINSTANCE
#define D3DXF_FILELOAD_FROMMEMORY
Definition: d3dx9xof.h:41
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
#define E_NOTIMPL
Definition: ddrawi.h:99
#define E_FAIL
Definition: ddrawi.h:102
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
HRESULT WINAPI D3DXCreateBuffer(DWORD size, ID3DXBuffer **buffer)
Definition: core.c:131
D3DXVECTOR4 *WINAPI D3DXVec4Transform(D3DXVECTOR4 *pout, const D3DXVECTOR4 *pv, const D3DXMATRIX *pm)
Definition: math.c:2073
FLOAT *WINAPI D3DXFloat16To32Array(FLOAT *pout, const D3DXFLOAT16 *pin, UINT n)
Definition: math.c:2221
D3DXVECTOR3 *WINAPI D3DXVec3TransformCoord(D3DXVECTOR3 *pout, const D3DXVECTOR3 *pv, const D3DXMATRIX *pm)
Definition: math.c:1895
D3DXMATRIX *WINAPI D3DXMatrixMultiply(D3DXMATRIX *pout, const D3DXMATRIX *pm1, const D3DXMATRIX *pm2)
Definition: math.c:397
D3DXMATRIX *WINAPI D3DXMatrixInverse(D3DXMATRIX *pout, FLOAT *pdeterminant, const D3DXMATRIX *pm)
Definition: math.c:258
D3DXVECTOR2 *WINAPI D3DXVec2Normalize(D3DXVECTOR2 *pout, const D3DXVECTOR2 *pv)
Definition: math.c:1659
D3DXVECTOR3 *WINAPI D3DXVec3Normalize(D3DXVECTOR3 *pout, const D3DXVECTOR3 *pv)
Definition: math.c:1805
D3DXFLOAT16 *WINAPI D3DXFloat32To16Array(D3DXFLOAT16 *pout, const FLOAT *pin, UINT n)
Definition: math.c:2187
static void write_ib(void *index_buffer, BOOL indices_are_32bit, DWORD index, DWORD value)
Definition: mesh.c:6967
BOOL WINAPI D3DXIntersectTri(const D3DXVECTOR3 *p0, const D3DXVECTOR3 *p1, const D3DXVECTOR3 *p2, const D3DXVECTOR3 *praypos, const D3DXVECTOR3 *praydir, float *pu, float *pv, float *pdist)
Definition: mesh.c:2367
HRESULT WINAPI D3DXCreateBox(struct IDirect3DDevice9 *device, float width, float height, float depth, struct ID3DXMesh **mesh, struct ID3DXBuffer **adjacency)
Definition: mesh.c:4653
static DWORD find_adjacent_face(struct edge_face_map *edge_face_map, DWORD vertex1, DWORD vertex2, DWORD num_faces)
Definition: mesh.c:923
static DWORD WINAPI d3dx9_mesh_GetNumFaces(ID3DXMesh *iface)
Definition: mesh.c:191
static FLOAT scale_clamp_ushortn(FLOAT value)
Definition: mesh.c:320
static HRESULT init_edge_face_map(struct edge_face_map *edge_face_map, const DWORD *index_buffer, const DWORD *point_reps, DWORD num_faces)
Definition: mesh.c:882
static HRESULT WINAPI d3dx9_mesh_GetDeclaration(ID3DXMesh *iface, D3DVERTEXELEMENT9 declaration[MAX_FVF_DECL_SIZE])
Definition: mesh.c:223
static FLOAT scale_clamp_shortn(FLOAT value)
Definition: mesh.c:301
HRESULT WINAPI D3DXLoadMeshFromXResource(HMODULE module, const char *name, const char *type, DWORD options, struct IDirect3DDevice9 *device, struct ID3DXBuffer **adjacency, struct ID3DXBuffer **materials, struct ID3DXBuffer **effect_instances, DWORD *num_materials, struct ID3DXMesh **mesh)
Definition: mesh.c:4108
static BOOL is_direction_similar(D3DXVECTOR2 *dir1, D3DXVECTOR2 *dir2, float cos_theta)
Definition: mesh.c:5508
static HRESULT WINAPI d3dx9_mesh_DrawSubset(ID3DXMesh *iface, DWORD attrib_id)
Definition: mesh.c:143
static FLOAT scale_clamp_ubyten(FLOAT value)
Definition: mesh.c:284
UINT WINAPI D3DXGetDeclLength(const D3DVERTEXELEMENT9 *decl)
Definition: mesh.c:2354
HRESULT WINAPI D3DXCreatePolygon(struct IDirect3DDevice9 *device, float length, UINT sides, struct ID3DXMesh **mesh, struct ID3DXBuffer **adjacency)
Definition: mesh.c:4563
UINT WINAPI D3DXGetFVFVertexSize(DWORD FVF)
Definition: mesh.c:2289
static HRESULT create_outline(struct glyphinfo *glyph, void *raw_outline, int datasize, float max_deviation_sq, unsigned int emsquare, const struct cos_table *cos_table)
Definition: mesh.c:5570
static HRESULT triangulation_add_point(struct triangulation **t_ptr, struct triangulation_array *triangulations, WORD vtx_idx, BOOL to_top)
Definition: mesh.c:5750
static HRESULT convert_vertex_buffer(ID3DXMesh *mesh_dst, ID3DXMesh *mesh_src)
Definition: mesh.c:604
static HRESULT WINAPI d3dx9_mesh_CloneMesh(struct ID3DXMesh *iface, DWORD options, const D3DVERTEXELEMENT9 *declaration, struct IDirect3DDevice9 *device, struct ID3DXMesh **clone_mesh_out)
Definition: mesh.c:677
static HRESULT triangulate(struct triangulation_array *triangulations)
Definition: mesh.c:5858
static HRESULT WINAPI d3dx9_mesh_UnlockVertexBuffer(ID3DXMesh *iface)
Definition: mesh.c:813
static void copy_declaration(D3DVERTEXELEMENT9 *dst, const D3DVERTEXELEMENT9 *src, UINT num_elem)
Definition: mesh.c:218
HRESULT WINAPI D3DXDeclaratorFromFVF(DWORD fvf, D3DVERTEXELEMENT9 declaration[MAX_FVF_DECL_SIZE])
Definition: mesh.c:2036
#define NUM_ELEM
static HRESULT WINAPI d3dx9_mesh_GetVertexBuffer(struct ID3DXMesh *iface, struct IDirect3DVertexBuffer9 **vertex_buffer)
Definition: mesh.c:774
static face * add_face(struct face_array *array)
Definition: mesh.c:5436
static HRESULT WINAPI d3dx9_mesh_UpdateSemantics(ID3DXMesh *iface, D3DVERTEXELEMENT9 declaration[MAX_FVF_DECL_SIZE])
Definition: mesh.c:1370
HRESULT WINAPI D3DXCreateCylinder(struct IDirect3DDevice9 *device, float radius1, float radius2, float length, UINT slices, UINT stacks, struct ID3DXMesh **mesh, struct ID3DXBuffer **adjacency)
Definition: mesh.c:4975
static HRESULT WINAPI d3dx9_mesh_GetIndexBuffer(struct ID3DXMesh *iface, struct IDirect3DIndexBuffer9 **index_buffer)
Definition: mesh.c:789
static D3DXVECTOR2 * convert_fixed_to_float(POINTFX *pt, int count, unsigned int emsquare)
Definition: mesh.c:5466
HRESULT WINAPI D3DXComputeTangentFrameEx(ID3DXMesh *mesh, DWORD texture_in_semantic, DWORD texture_in_index, DWORD u_partial_out_semantic, DWORD u_partial_out_index, DWORD v_partial_out_semantic, DWORD v_partial_out_index, DWORD normal_out_semantic, DWORD normal_out_index, DWORD options, const DWORD *adjacency, float partial_edge_threshold, float singular_point_threshold, float normal_edge_threshold, ID3DXMesh **mesh_out, ID3DXBuffer **vertex_mapping)
Definition: mesh.c:7320
HRESULT WINAPI D3DXOptimizeVertices(const void *indices, UINT num_faces, UINT num_vertices, BOOL indices_are_32bit, DWORD *vertex_remap)
Definition: mesh.c:7196
static struct point2d * add_points(struct outline *array, int num)
Definition: mesh.c:5412
static HRESULT add_bezier_points(struct outline *outline, const D3DXVECTOR2 *p1, const D3DXVECTOR2 *p2, const D3DXVECTOR2 *p3, float max_deviation_sq)
Definition: mesh.c:5478
#define EFFECT_TABLE_ENTRY(str, field)
HRESULT WINAPI D3DXLoadMeshHierarchyFromXInMemory(const void *memory, DWORD memory_size, DWORD options, struct IDirect3DDevice9 *device, struct ID3DXAllocateHierarchy *alloc_hier, struct ID3DXLoadUserData *load_user_data, D3DXFRAME **frame_hierarchy, struct ID3DXAnimationController **anim_controller)
Definition: mesh.c:3896
static HRESULT parse_normals(ID3DXFileData *filedata, struct mesh_data *mesh)
Definition: mesh.c:3012
static FLOAT get_component_epsilon(const D3DVERTEXELEMENT9 *decl_ptr, const D3DXWELDEPSILONS *epsilons)
Definition: mesh.c:6871
static BOOL weld_float2(void *to, void *from, FLOAT epsilon)
Definition: mesh.c:6455
static HRESULT WINAPI d3dx9_mesh_SetAttributeTable(ID3DXMesh *iface, const D3DXATTRIBUTERANGE *attrib_table, DWORD attrib_table_size)
Definition: mesh.c:1836
static HRESULT parse_material_list(ID3DXFileData *filedata, struct mesh_data *mesh)
Definition: mesh.c:2776
static BOOL weld_d3dcolor(void *to, void *from, FLOAT epsilon)
Definition: mesh.c:6543
static void free_sincos_table(struct sincos_table *sincos_table)
Definition: mesh.c:4755
static DWORD WINAPI d3dx9_mesh_GetNumVertices(ID3DXMesh *iface)
Definition: mesh.c:200
static UINT Get_TexCoord_Size_From_FVF(DWORD FVF, int tex_num)
Definition: mesh.c:2284
static HRESULT parse_material(ID3DXFileData *filedata, D3DXMATERIAL *material)
Definition: mesh.c:2681
static void remove_triangulation(struct triangulation_array *array, struct triangulation *item)
Definition: mesh.c:5743
static D3DXVECTOR3 read_vec3(BYTE *vertices, const D3DVERTEXELEMENT9 *declaration, DWORD vertex_stride, DWORD index)
Definition: mesh.c:7290
static HRESULT WINAPI d3dx9_mesh_ConvertPointRepsToAdjacency(ID3DXMesh *iface, const DWORD *point_reps, DWORD *adjacency)
Definition: mesh.c:953
static BOOL weld_float1(void *to, void *from, FLOAT epsilon)
Definition: mesh.c:6440
static HRESULT WINAPI d3dx9_mesh_ConvertAdjacencyToPointReps(ID3DXMesh *iface, const DWORD *adjacency, DWORD *point_reps)
Definition: mesh.c:1103
HRESULT WINAPI D3DXCreateTextA(struct IDirect3DDevice9 *device, HDC hdc, const char *text, float deviation, float extrusion, struct ID3DXMesh **mesh, struct ID3DXBuffer **adjacency, GLYPHMETRICSFLOAT *glyphmetrics)
Definition: mesh.c:5177
static void empty_frame_queue(struct list *queue)
Definition: mesh.c:7632
HRESULT WINAPI D3DXFVFFromDeclarator(const D3DVERTEXELEMENT9 *declaration, DWORD *fvf)
Definition: mesh.c:2134
static BOOL weld_float3(void *to, void *from, FLOAT epsilon)
Definition: mesh.c:6473
pointtype
Definition: mesh.c:5308
@ POINTTYPE_CURVE_MIDDLE
Definition: mesh.c:5313
@ POINTTYPE_CORNER
Definition: mesh.c:5310
@ POINTTYPE_CURVE_END
Definition: mesh.c:5312
@ POINTTYPE_CURVE_START
Definition: mesh.c:5311
@ POINTTYPE_CURVE
Definition: mesh.c:5309
HRESULT WINAPI D3DXCreateMesh(DWORD numfaces, DWORD numvertices, DWORD options, const D3DVERTEXELEMENT9 *declaration, struct IDirect3DDevice9 *device, struct ID3DXMesh **mesh)
Definition: mesh.c:2433
static struct triangulation * add_triangulation(struct triangulation_array *array)
Definition: mesh.c:5441
static BOOL weld_short2(void *to, void *from, FLOAT epsilon)
Definition: mesh.c:6548
static BOOL weld_dec3n(void *to, void *from, FLOAT epsilon)
Definition: mesh.c:6707
HRESULT WINAPI D3DXComputeBoundingBox(const D3DXVECTOR3 *pfirstposition, DWORD numvertices, DWORD dwstride, D3DXVECTOR3 *pmin, D3DXVECTOR3 *pmax)
Definition: mesh.c:1964
static HRESULT parse_vertex_colors(ID3DXFileData *filedata, struct mesh_data *mesh)
Definition: mesh.c:2936
HRESULT WINAPI D3DXCreateTeapot(struct IDirect3DDevice9 *device, struct ID3DXMesh **mesh, struct ID3DXBuffer **adjacency)
Definition: mesh.c:5169
HRESULT WINAPI D3DXCleanMesh(D3DXCLEANTYPE clean_type, ID3DXMesh *mesh_in, const DWORD *adjacency_in, ID3DXMesh **mesh_out, DWORD *adjacency_out, ID3DXBuffer **errors_and_warnings)
Definition: mesh.c:4002
static BOOL weld_ubyte4(void *to, void *from, FLOAT epsilon)
Definition: mesh.c:6515
static HRESULT WINAPI d3dx9_mesh_OptimizeInplace(ID3DXMesh *iface, DWORD flags, const DWORD *adjacency_in, DWORD *adjacency_out, DWORD *face_remap_out, ID3DXBuffer **vertex_remap_out)
Definition: mesh.c:1642
static HRESULT WINAPI d3dx9_mesh_LockAttributeBuffer(ID3DXMesh *iface, DWORD flags, DWORD **data)
Definition: mesh.c:1429
HRESULT WINAPI D3DXTessellateNPatches(ID3DXMesh *mesh, const DWORD *adjacency_in, float num_segs, BOOL quadratic_normals, ID3DXMesh **mesh_out, ID3DXBuffer **adjacency_out)
Definition: mesh.c:7591
static D3DXVECTOR2 * get_ordered_vertex(struct glyphinfo *glyph, WORD index)
Definition: mesh.c:5738
HRESULT WINAPI D3DXIntersect(ID3DXBaseMesh *mesh, const D3DXVECTOR3 *ray_pos, const D3DXVECTOR3 *ray_dir, BOOL *hit, DWORD *face_index, float *u, float *v, float *distance, ID3DXBuffer **all_hits, DWORD *count_of_hits)
Definition: mesh.c:7582
HRESULT WINAPI D3DXLoadMeshHierarchyFromXW(const WCHAR *filename, DWORD options, struct IDirect3DDevice9 *device, struct ID3DXAllocateHierarchy *alloc_hier, struct ID3DXLoadUserData *load_user_data, D3DXFRAME **frame_hierarchy, struct ID3DXAnimationController **anim_controller)
Definition: mesh.c:3717
static HRESULT WINAPI d3dx9_mesh_GenerateAdjacency(ID3DXMesh *iface, float epsilon, DWORD *adjacency)
Definition: mesh.c:1224
static BOOL weld_ushort4n(void *to, void *from, FLOAT epsilon)
Definition: mesh.c:6619
HRESULT WINAPI D3DXOptimizeFaces(const void *indices, UINT num_faces, UINT num_vertices, BOOL indices_are_32bit, DWORD *face_remap)
Definition: mesh.c:7239
#define PROVIDE_MATERIALS
Definition: mesh.c:3163
HRESULT WINAPI D3DXComputeBoundingSphere(const D3DXVECTOR3 *pfirstposition, DWORD numvertices, DWORD dwstride, D3DXVECTOR3 *pcenter, float *pradius)
Definition: mesh.c:1992
static HRESULT WINAPI d3dx9_mesh_GetAttributeTable(ID3DXMesh *iface, D3DXATTRIBUTERANGE *attrib_table, DWORD *attrib_table_size)
Definition: mesh.c:842
HRESULT WINAPI D3DXLoadSkinMeshFromXof(struct ID3DXFileData *filedata, DWORD options, struct IDirect3DDevice9 *device, struct ID3DXBuffer **adjacency_out, struct ID3DXBuffer **materials_out, struct ID3DXBuffer **effects_out, DWORD *num_materials_out, struct ID3DXSkinInfo **skin_info_out, struct ID3DXMesh **mesh_out)
Definition: mesh.c:3445
static HRESULT propagate_face_vertices(const DWORD *adjacency, DWORD *point_reps, const DWORD *indices, DWORD *new_indices, DWORD face, DWORD numfaces)
Definition: mesh.c:1054
static BOOL weld_short2n(void *to, void *from, FLOAT epsilon)
Definition: mesh.c:6567
static int __cdecl attrib_entry_compare(const void *a, const void *b)
Definition: mesh.c:1593
BOOL WINAPI D3DXSphereBoundProbe(const D3DXVECTOR3 *center, float radius, const D3DXVECTOR3 *ray_position, const D3DXVECTOR3 *ray_direction)
Definition: mesh.c:2413
static BOOL queue_frame_node(struct list *queue, D3DXFRAME *frame)
Definition: mesh.c:7615
static BOOL weld_float16_2(void *to, void *from, FLOAT epsilon)
Definition: mesh.c:6733
static HRESULT load_frame(struct ID3DXFileData *filedata, DWORD options, struct IDirect3DDevice9 *device, struct ID3DXAllocateHierarchy *alloc_hier, D3DXFRAME **frame_out)
Definition: mesh.c:3836
static void convert_component(BYTE *dst, BYTE *src, D3DDECLTYPE type_dst, D3DDECLTYPE type_src)
Definition: mesh.c:469
static void append_decl_element(D3DVERTEXELEMENT9 *declaration, UINT *idx, UINT *offset, D3DDECLTYPE type, D3DDECLUSAGE usage, UINT usage_idx)
Definition: mesh.c:2019
static HRESULT WINAPI d3dx9_mesh_LockIndexBuffer(ID3DXMesh *iface, DWORD flags, void **data)
Definition: mesh.c:822
static HRESULT WINAPI d3dx9_mesh_GetDevice(struct ID3DXMesh *iface, struct IDirect3DDevice9 **device)
Definition: mesh.c:255
static HRESULT WINAPI d3dx9_mesh_Optimize(ID3DXMesh *iface, DWORD flags, const DWORD *adjacency_in, DWORD *adjacency_out, DWORD *face_remap, ID3DXBuffer **vertex_remap, ID3DXMesh **opt_mesh)
Definition: mesh.c:1467
static HRESULT parse_transform_matrix(ID3DXFileData *filedata, D3DXMATRIX *transform)
Definition: mesh.c:3807
#define PROVIDE_SKININFO
Definition: mesh.c:3164
static INT simple_round(FLOAT value)
Definition: mesh.c:337
static BOOL weld_float4(void *to, void *from, FLOAT epsilon)
Definition: mesh.c:6493
static D3DXVECTOR2 * get_indexed_point(struct point2d_index *pt_idx)
Definition: mesh.c:5733
static BOOL weld_float16_4(void *to, void *from, FLOAT epsilon)
Definition: mesh.c:6762
static BOOL compute_sincos_table(struct sincos_table *sincos_table, float angle_start, float angle_step, int n)
Definition: mesh.c:4762
static struct udec3 dword_to_udec3(DWORD d)
Definition: mesh.c:6650
static void fill_attribute_table(DWORD *attrib_buffer, DWORD numfaces, void *indices, BOOL is_32bit_indices, D3DXATTRIBUTERANGE *attrib_table)
Definition: mesh.c:1553
static HRESULT parse_mesh(ID3DXFileData *filedata, struct mesh_data *mesh_data, DWORD provide_flags)
Definition: mesh.c:3167
HRESULT WINAPI D3DXCreateSphere(struct IDirect3DDevice9 *device, float radius, UINT slices, UINT stacks, struct ID3DXMesh **mesh, struct ID3DXBuffer **adjacency)
Definition: mesh.c:4795
D3DXFRAME *WINAPI D3DXFrameFind(const D3DXFRAME *root, const char *name)
Definition: mesh.c:7642
static BOOL weld_component(void *to, void *from, D3DDECLTYPE type, FLOAT epsilon)
Definition: mesh.c:6798
HRESULT WINAPI D3DXLoadMeshFromXW(const WCHAR *filename, DWORD options, struct IDirect3DDevice9 *device, struct ID3DXBuffer **adjacency, struct ID3DXBuffer **materials, struct ID3DXBuffer **effect_instances, DWORD *num_materials, struct ID3DXMesh **mesh)
Definition: mesh.c:4080
static INT get_equivalent_declaration_index(D3DVERTEXELEMENT9 orig_declaration, D3DVERTEXELEMENT9 *declaration)
Definition: mesh.c:588
static HRESULT parse_skin_mesh_info(ID3DXFileData *filedata, struct mesh_data *mesh_data, DWORD index)
Definition: mesh.c:3110
static struct outline * add_outline(struct outline_array *array)
Definition: mesh.c:5424
static BOOL declaration_equals(const D3DVERTEXELEMENT9 *declaration1, const D3DVERTEXELEMENT9 *declaration2)
Definition: mesh.c:658
static ULONG WINAPI d3dx9_mesh_Release(ID3DXMesh *iface)
Definition: mesh.c:121
static BOOL reserve(struct dynamic_array *array, int count, int itemsize)
Definition: mesh.c:5392
static HRESULT load_mesh_container(struct ID3DXFileData *filedata, DWORD options, struct IDirect3DDevice9 *device, struct ID3DXAllocateHierarchy *alloc_hier, D3DXMESHCONTAINER **mesh_container)
Definition: mesh.c:3767
UINT WINAPI D3DXGetDeclVertexSize(const D3DVERTEXELEMENT9 *decl, DWORD stream_idx)
Definition: mesh.c:2323
static HRESULT compact_mesh(struct d3dx9_mesh *This, DWORD *indices, DWORD *new_num_vertices, ID3DXBuffer **vertex_remap)
Definition: mesh.c:1497
static HRESULT WINAPI d3dx9_mesh_LockVertexBuffer(ID3DXMesh *iface, DWORD flags, void **data)
Definition: mesh.c:804
static BOOL weld_ushort2n(void *to, void *from, FLOAT epsilon)
Definition: mesh.c:6600
static HRESULT filedata_get_name(ID3DXFileData *filedata, char **name)
Definition: mesh.c:3745
static DWORD * generate_identity_point_reps(DWORD num_vertices)
Definition: mesh.c:936
static const struct ID3DXMeshVtbl D3DXMesh_Vtbl
Definition: mesh.c:1862
HRESULT WINAPI D3DXValidMesh(ID3DXMesh *mesh, const DWORD *adjacency, ID3DXBuffer **errors_and_warnings)
Definition: mesh.c:6433
#define FILL_INDEX_BUFFER(indices_var)
HRESULT WINAPI D3DXLoadMeshFromXA(const char *filename, DWORD options, struct IDirect3DDevice9 *device, struct ID3DXBuffer **adjacency, struct ID3DXBuffer **materials, struct ID3DXBuffer **effect_instances, DWORD *num_materials, struct ID3DXMesh **mesh)
Definition: mesh.c:4052
static BOOL attempt_line_merge(struct outline *outline, int pt_index, const D3DXVECTOR2 *nextpt, BOOL to_curve, const struct cos_table *table)
Definition: mesh.c:5526
static ULONG WINAPI d3dx9_mesh_AddRef(ID3DXMesh *iface)
Definition: mesh.c:111
static HRESULT WINAPI d3dx9_mesh_UnlockAttributeBuffer(ID3DXMesh *iface)
Definition: mesh.c:1450
HRESULT WINAPI D3DXCreateTorus(struct IDirect3DDevice9 *device, float innerradius, float outerradius, UINT sides, UINT rings, struct ID3DXMesh **mesh, ID3DXBuffer **adjacency)
Definition: mesh.c:5201
static DWORD read_ib(void *index_buffer, BOOL indices_are_32bit, DWORD index)
Definition: mesh.c:6951
static HRESULT remap_faces_for_attrsort(struct d3dx9_mesh *This, const DWORD *indices, DWORD *attrib_buffer, DWORD **sorted_attrib_buffer, DWORD **face_remap)
Definition: mesh.c:1607
static const UINT d3dx_decltype_size[]
Definition: mesh.c:67
#define PROVIDE_ADJACENCY
Definition: mesh.c:3165
static struct dec3n dword_to_dec3n(DWORD d)
Definition: mesh.c:6695
HRESULT WINAPI D3DXComputeTangent(ID3DXMesh *mesh, DWORD stage_idx, DWORD tangent_idx, DWORD binorm_idx, DWORD wrap, const DWORD *adjacency)
Definition: mesh.c:7545
static D3DXVECTOR3 * vertex_element_vec3(BYTE *vertices, const D3DVERTEXELEMENT9 *declaration, DWORD vertex_stride, DWORD index)
Definition: mesh.c:7284
static BOOL weld_ubyte4n(void *to, void *from, FLOAT epsilon)
Definition: mesh.c:6538
HRESULT WINAPI D3DXConvertMeshSubsetToSingleStrip(struct ID3DXBaseMesh *mesh_in, DWORD attribute_id, DWORD ib_flags, struct IDirect3DIndexBuffer9 **index_buffer, DWORD *index_count)
Definition: mesh.c:7600
static DWORD WINAPI d3dx9_mesh_GetFVF(ID3DXMesh *iface)
Definition: mesh.c:209
static HRESULT parse_frame(struct ID3DXFileData *filedata, DWORD options, struct IDirect3DDevice9 *device, const D3DXMATRIX *parent_transform, struct list *container_list, DWORD provide_flags)
Definition: mesh.c:4143
HRESULT WINAPI D3DXCreateTextW(struct IDirect3DDevice9 *device, HDC hdc, const WCHAR *text, float deviation, float extrusion, struct ID3DXMesh **mesh_ptr, struct ID3DXBuffer **adjacency, GLYPHMETRICSFLOAT *glyphmetrics)
Definition: mesh.c:6094
static struct d3dx9_mesh * impl_from_ID3DXMesh(ID3DXMesh *iface)
Definition: mesh.c:88
static DWORD count_attributes(const DWORD *attrib_buffer, DWORD numfaces)
Definition: mesh.c:1539
HRESULT WINAPI D3DXComputeNormals(struct ID3DXBaseMesh *mesh, const DWORD *adjacency)
Definition: mesh.c:7563
HRESULT WINAPI D3DXLoadMeshFromXInMemory(const void *memory, DWORD memory_size, DWORD options, struct IDirect3DDevice9 *device, struct ID3DXBuffer **adjacency_out, struct ID3DXBuffer **materials_out, struct ID3DXBuffer **effects_out, DWORD *num_materials_out, struct ID3DXMesh **mesh_out)
Definition: mesh.c:4198
static D3DXVECTOR2 * unit_vec2(D3DXVECTOR2 *dir, const D3DXVECTOR2 *pt1, const D3DXVECTOR2 *pt2)
Definition: mesh.c:5514
HRESULT WINAPI D3DXWeldVertices(ID3DXMesh *mesh, DWORD flags, const D3DXWELDEPSILONS *epsilons, const DWORD *adjacency, DWORD *adjacency_out, DWORD *face_remap_out, ID3DXBuffer **vertex_remap_out)
Definition: mesh.c:7006
static BOOL weld_short4(void *to, void *from, FLOAT epsilon)
Definition: mesh.c:6572
static int __cdecl compare_vertex_keys(const void *a, const void *b)
Definition: mesh.c:1215
static HRESULT WINAPI d3dx9_mesh_CloneMeshFVF(struct ID3DXMesh *iface, DWORD options, DWORD fvf, struct IDirect3DDevice9 *device, struct ID3DXMesh **clone_mesh)
Definition: mesh.c:269
static HRESULT add_vertex_index(struct word_array *array, WORD vertex_index)
Definition: mesh.c:5453
HRESULT WINAPI D3DXCreateMeshFVF(DWORD numfaces, DWORD numvertices, DWORD options, DWORD fvf, struct IDirect3DDevice9 *device, struct ID3DXMesh **mesh)
Definition: mesh.c:2596
HRESULT WINAPI D3DXLoadMeshHierarchyFromXA(const char *filename, DWORD options, struct IDirect3DDevice9 *device, struct ID3DXAllocateHierarchy *alloc_hier, struct ID3DXLoadUserData *load_user_data, D3DXFRAME **frame_hierarchy, struct ID3DXAnimationController **anim_controller)
Definition: mesh.c:3689
static HRESULT parse_texture_coords(ID3DXFileData *filedata, struct mesh_data *mesh)
Definition: mesh.c:2881
static D3DXVECTOR2 * triangulation_get_next_point(struct triangulation *t, struct glyphinfo *glyph, BOOL on_top)
Definition: mesh.c:5830
static int __cdecl compare_vertex_indices(const void *a, const void *b)
Definition: mesh.c:5845
static DWORD WINAPI d3dx9_mesh_GetNumBytesPerVertex(ID3DXMesh *iface)
Definition: mesh.c:237
WORD face[3]
Definition: mesh.c:4747
static BOOL weld_udec3(void *to, void *from, FLOAT epsilon)
Definition: mesh.c:6662
HRESULT WINAPI D3DXFrameDestroy(D3DXFRAME *frame, ID3DXAllocateHierarchy *alloc_hier)
Definition: mesh.c:4010
static float get_line_to_point_y_distance(D3DXVECTOR2 *line_pt1, D3DXVECTOR2 *line_pt2, D3DXVECTOR2 *point)
Definition: mesh.c:5719
static HRESULT WINAPI d3dx9_mesh_UnlockIndexBuffer(ID3DXMesh *iface)
Definition: mesh.c:831
static void convert_float4(BYTE *dst, const D3DXVECTOR4 *src, D3DDECLTYPE type_dst)
Definition: mesh.c:344
static BOOL weld_short4n(void *to, void *from, FLOAT epsilon)
Definition: mesh.c:6595
static WORD vertex_index(UINT slices, int slice, int stack)
Definition: mesh.c:4790
BOOL WINAPI D3DXBoxBoundProbe(const D3DXVECTOR3 *pmin, const D3DXVECTOR3 *pmax, const D3DXVECTOR3 *prayposition, const D3DXVECTOR3 *praydirection)
Definition: mesh.c:1911
static HRESULT generate_effects(ID3DXBuffer *materials, DWORD num_materials, ID3DXBuffer **effects)
Definition: mesh.c:3347
static HRESULT WINAPI d3dx9_mesh_QueryInterface(ID3DXMesh *iface, REFIID riid, void **out)
Definition: mesh.c:93
static HRESULT parse_texture_filename(ID3DXFileData *filedata, char **filename_out)
Definition: mesh.c:2639
static DWORD WINAPI d3dx9_mesh_GetOptions(ID3DXMesh *iface)
Definition: mesh.c:246
static void destroy_materials(struct mesh_data *mesh)
Definition: mesh.c:2764
HRESULT WINAPI D3DXFileCreate(ID3DXFile **d3dxfile)
Definition: xfile.c:717
unsigned int idx
Definition: utils.c:41
#define GetProcessHeap()
Definition: compat.h:736
#define UnmapViewOfFile
Definition: compat.h:746
#define CP_ACP
Definition: compat.h:109
#define HeapAlloc
Definition: compat.h:733
#define HeapReAlloc
Definition: compat.h:734
#define HeapFree(x, y, z)
Definition: compat.h:735
#define MultiByteToWideChar
Definition: compat.h:110
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
#define lstrlenW
Definition: compat.h:750
static void cleanup(void)
Definition: main.c:1335
HRSRC WINAPI FindResourceA(HMODULE hModule, LPCSTR name, LPCSTR type)
Definition: res.c:155
const WCHAR * text
Definition: package.c:1799
#define assert(x)
Definition: debug.h:53
#define pt(x, y)
Definition: drawing.c:79
#define wrap(journal, var)
Definition: recovery.c:207
POINTL point
Definition: edittest.c:50
#define abs(i)
Definition: fconv.c:206
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
unsigned short WORD
Definition: ntddk_ex.h:93
FT_Vector * vec
Definition: ftbbox.c:448
pKey DeleteObject()
FxCollectionEntry * cur
GLuint start
Definition: gl.h:1545
GLint GLint GLsizei GLsizei GLsizei depth
Definition: gl.h:1546
const GLdouble * v
Definition: gl.h:2040
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLuint GLuint end
Definition: gl.h:1545
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLint GLint GLsizei GLsizei height
Definition: gl.h:1546
GLdouble GLdouble t
Definition: gl.h:2047
GLint GLint GLsizei width
Definition: gl.h:1546
GLuint GLuint GLsizei GLenum const GLvoid * indices
Definition: gl.h:1545
GLsizeiptr size
Definition: glext.h:5919
GLdouble n
Definition: glext.h:7729
GLuint GLenum GLenum transform
Definition: glext.h:9407
GLenum GLuint texture
Definition: glext.h:6295
GLuint res
Definition: glext.h:9613
GLenum GLenum GLenum GLenum GLenum scale
Definition: glext.h:9032
GLenum src
Definition: glext.h:6340
GLuint buffer
Definition: glext.h:5915
GLuint color
Definition: glext.h:6243
const GLubyte * c
Definition: glext.h:8905
GLuint index
Definition: glext.h:6031
GLdouble GLdouble right
Definition: glext.h:10859
GLenum GLuint GLint GLenum face
Definition: glext.h:7025
GLfloat f
Definition: glext.h:7540
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
GLsizei GLsizei GLfloat distance
Definition: glext.h:11755
GLint left
Definition: glext.h:7726
GLenum GLenum dst
Definition: glext.h:6340
GLbitfield flags
Definition: glext.h:7161
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
GLfloat angle
Definition: glext.h:10853
GLfloat v0
Definition: glext.h:6061
const GLbyte * weights
Definition: glext.h:6523
GLenum GLuint GLsizei bufsize
Definition: glext.h:7473
GLuint GLuint num
Definition: glext.h:9618
GLenum GLsizei len
Definition: glext.h:6722
GLboolean GLboolean GLboolean GLboolean a
Definition: glext.h:6204
GLfloat GLfloat v1
Definition: glext.h:6062
GLfloat GLfloat GLfloat v2
Definition: glext.h:6063
GLsizeiptr const GLvoid GLenum usage
Definition: glext.h:5919
GLdouble GLdouble z
Definition: glext.h:5874
GLintptr offset
Definition: glext.h:5920
const GLfloat * m
Definition: glext.h:10848
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble * u
Definition: glfuncs.h:240
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
_Must_inspect_result_ _In_ USAGE _In_ USHORT _In_ USAGE Usage
Definition: hidpi.h:384
#define FLOAT
Definition: i386-dis.c:525
#define SHRT_MAX
Definition: limits.h:37
#define UCHAR_MAX
Definition: limits.h:25
#define USHRT_MAX
Definition: limits.h:38
#define SHRT_MIN
Definition: limits.h:36
_Check_return_ float __cdecl acosf(_In_ float x)
Definition: math.h:219
_Check_return_ __CRT_INLINE float __CRTDECL fabsf(_In_ float x)
Definition: math.h:179
_Check_return_ float __cdecl cosf(_In_ float x)
Definition: math.h:224
_Check_return_ float __cdecl sinf(_In_ float x)
Definition: math.h:233
REFIID riid
Definition: atlbase.h:39
ULONG Release()
nsrefcnt Release()
#define S_OK
Definition: intsafe.h:52
#define SUCCEEDED(hr)
Definition: intsafe.h:50
#define FAILED(hr)
Definition: intsafe.h:51
#define C_ASSERT(e)
Definition: intsafe.h:73
const char * filename
Definition: ioapi.h:137
uint32_t entry
Definition: isohybrid.c:63
#define d
Definition: ke_i.h:81
#define a
Definition: ke_i.h:78
#define c
Definition: ke_i.h:80
#define b
Definition: ke_i.h:79
#define debugstr_guid
Definition: kernel32.h:35
#define debugstr_a
Definition: kernel32.h:31
#define debugstr_w
Definition: kernel32.h:32
if(dx< 0)
Definition: linetemp.h:194
const GUID * guid
struct S1 s1
struct S2 s2
#define isnan(x)
Definition: mingw_math.h:133
#define error(str)
Definition: mkdosfs.c:1605
#define matches(FN)
Definition: match.h:70
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
struct task_struct * current
Definition: linux.c:32
HDC hdc
Definition: main.c:9
static const WCHAR filenameW[]
Definition: amstream.c:41
static HDC
Definition: imagelist.c:92
static const WCHAR textW[]
Definition: itemdlg.c:1559
static CRYPT_DATA_BLOB b2[]
Definition: msg.c:582
static CRYPT_DATA_BLOB b1[]
Definition: msg.c:573
static ID3DXAllocateHierarchy alloc_hier
Definition: mesh.c:2010
pointtype
Definition: mesh.c:3496
static const ASMPROP_RES defaults[ASM_NAME_MAX_PARAMS]
Definition: asmname.c:82
static UINT UINT LPWORD glyphs
Definition: font.c:44
static UINT UINT last
Definition: font.c:45
static DWORD *static HFONT(WINAPI *pCreateFontIndirectExA)(const ENUMLOGFONTEXDVA *)
static char memory[1024 *256]
Definition: process.c:116
static IStream Stream
Definition: htmldoc.c:1115
static char * dest
Definition: rtl.c:135
static float(__cdecl *square_half_float)(float x
static HWND child
Definition: cursoricon.c:298
static ATOM item
Definition: dde.c:856
#define min(a, b)
Definition: monoChain.cc:55
int k
Definition: mpi.c:3369
Definition: mk_font.cpp:20
unsigned int UINT
Definition: ndis.h:50
#define DWORD
Definition: nt_native.h:44
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
#define OBJ_FONT
Definition: objidl.idl:1414
@ normal
Definition: optimize.h:166
short SHORT
Definition: pedump.c:59
long LONG
Definition: pedump.c:60
unsigned short USHORT
Definition: pedump.c:61
#define INT
Definition: polytest.cpp:20
static void cross(float v1[3], float v2[3], float result[3])
Definition: project.c:100
#define IsEqualGUID(rguid1, rguid2)
Definition: guiddef.h:147
#define REFIID
Definition: guiddef.h:118
#define next_frame(vp)
Definition: raisecond.c:84
static unsigned __int64 next
Definition: rand_nt.c:6
#define err(...)
static FILE * out
Definition: regtests2xml.c:44
#define D3DRM_XTEMPLATE_BYTES
Definition: rmxftmpl.h:283
unsigned char D3DRM_XTEMPLATES[]
Definition: rmxftmpl.h:6
static calc_node_t temp
Definition: rpn_ieee.c:38
#define LIST_FOR_EACH_ENTRY(elem, list, type, field)
Definition: list.h:198
#define LIST_FOR_EACH_ENTRY_SAFE(cursor, cursor2, list, type, field)
Definition: list.h:204
__WINE_SERVER_LIST_INLINE struct list * list_next(const struct list *list, const struct list *elem)
Definition: list.h:115
#define f2(x, y, z)
Definition: sha1.c:31
#define f1(x, y, z)
Definition: sha1.c:30
#define memset(x, y, z)
Definition: compat.h:39
void __cdecl qsort(_Inout_updates_bytes_(_NumOfElements *_SizeOfElements) void *_Base, _In_ size_t _NumOfElements, _In_ size_t _SizeOfElements, _In_ int(__cdecl *_PtFuncCompare)(const void *, const void *))
HRESULT hr
Definition: shlfolder.c:183
HRESULT WINAPI D3DXCreateSkinInfoFVF(DWORD num_vertices, DWORD fvf, DWORD num_bones, ID3DXSkinInfo **skin_info)
Definition: skin.c:591
#define TRACE(s)
Definition: solgame.cpp:4
CardRegion * from
Definition: spigame.cpp:19
FLOAT x
Definition: d3dx9math.h:64
FLOAT y
Definition: d3dx9math.h:64
FT_Pos x
Definition: ftimage.h:76
FT_Pos y
Definition: ftimage.h:77
LONG lfHeight
Definition: dimm.idl:59
LONG lfWidth
Definition: dimm.idl:60
D3DCOLORVALUE Emissive
Definition: d3d9types.h:1410
D3DCOLORVALUE Diffuse
Definition: d3d9types.h:1407
D3DCOLORVALUE Ambient
Definition: d3d9types.h:1408
D3DCOLORVALUE Specular
Definition: d3d9types.h:1409
LPD3DXEFFECTDEFAULT pDefaults
Definition: d3dx9mesh.h:211
struct _D3DXFRAME * pFrameFirstChild
Definition: d3dx9anim.h:111
char * Name
Definition: d3dx9anim.h:107
D3DXMATRIX TransformationMatrix
Definition: d3dx9anim.h:108
LPD3DXMESHCONTAINER pMeshContainer
Definition: d3dx9anim.h:109
struct _D3DXFRAME * pFrameSibling
Definition: d3dx9anim.h:110
D3DMATERIAL9 MatD3D
Definition: d3dx9mesh.h:195
char * pTextureFilename
Definition: d3dx9mesh.h:196
struct _D3DXMESHCONTAINER * pNextMeshContainer
Definition: d3dx9anim.h:102
FLOAT Texcoords[8]
Definition: d3dx9mesh.h:234
FLOAT gmfBlackBoxX
Definition: wingdi.h:2726
POINTFLOAT gmfptGlyphOrigin
Definition: wingdi.h:2728
FLOAT gmfBlackBoxY
Definition: wingdi.h:2727
short gmCellIncX
Definition: wingdi.h:2445
UINT gmBlackBoxY
Definition: wingdi.h:2443
UINT gmBlackBoxX
Definition: wingdi.h:2442
short gmCellIncY
Definition: wingdi.h:2446
POINT gmptGlyphOrigin
Definition: wingdi.h:2444
Definition: wingdi.h:2472
FLOAT x
Definition: wingdi.h:2722
FLOAT y
Definition: wingdi.h:2723
LONG y
Definition: windef.h:330
LONG x
Definition: windef.h:329
Definition: palette.c:468
struct list entry
Definition: metafile.c:154
float cos_90
Definition: mesh.c:5523
float cos_half
Definition: mesh.c:5521
float cos_45
Definition: mesh.c:5522
int attrib_buffer_lock_count
Definition: mesh.c:62
DWORD fvf
Definition: mesh.c:53
DWORD numfaces
Definition: mesh.c:50
D3DVERTEXELEMENT9 cached_declaration[MAX_FVF_DECL_SIZE]
Definition: mesh.c:55
UINT num_elem
Definition: mesh.c:58
D3DXATTRIBUTERANGE * attrib_table
Definition: mesh.c:64
LONG ref
Definition: mesh.c:48
DWORD numvertices
Definition: mesh.c:51
UINT vertex_declaration_size
Definition: mesh.c:57
IDirect3DDevice9 * device
Definition: mesh.c:54
IDirect3DVertexBuffer9 * vertex_buffer
Definition: mesh.c:59
DWORD options
Definition: mesh.c:52
DWORD * attrib_buffer
Definition: mesh.c:61
ID3DXMesh ID3DXMesh_iface
Definition: mesh.c:47
DWORD attrib_table_size
Definition: mesh.c:63
IDirect3DIndexBuffer9 * index_buffer
Definition: mesh.c:60
IDirect3DVertexDeclaration9 * vertex_declaration
Definition: mesh.c:56
Definition: mesh.c:6688
INT w
Definition: mesh.c:6692
INT y
Definition: mesh.c:6690
INT z
Definition: mesh.c:6691
INT x
Definition: mesh.c:6689
char * value
Definition: compiler.c:67
Definition: devices.h:37
void * items
Definition: mesh.c:5325
int count
Definition: mesh.c:5324
int capacity
Definition: mesh.c:5324
struct edge_face * entries
Definition: mesh.c:869
struct list * lists
Definition: mesh.c:868
struct list entry
Definition: mesh.c:861
DWORD v2
Definition: mesh.c:862
DWORD face
Definition: mesh.c:863
face * items
Definition: mesh.c:5345
int count
Definition: mesh.c:5344
D3DXFRAME * frame
Definition: mesh.c:7612
struct list entry
Definition: mesh.c:7611
float offset_x
Definition: mesh.c:5365
struct point2d_index_array ordered_vertices
Definition: mesh.c:5364
struct face_array faces
Definition: mesh.c:5363
struct outline_array outlines
Definition: mesh.c:5362
Definition: list.h:15
ID3DXBuffer * materials
Definition: mesh.c:4137
ID3DXMesh * mesh
Definition: mesh.c:4135
struct list entry
Definition: mesh.c:4134
ID3DXBuffer * adjacency
Definition: mesh.c:4136
ID3DXBuffer * effects
Definition: mesh.c:4138
D3DXMATRIX transform
Definition: mesh.c:4140
DWORD num_materials
Definition: mesh.c:4139
DWORD * vertex_colors
Definition: mesh.c:2629
DWORD * normal_indices
Definition: mesh.c:2625
D3DXVECTOR3 * vertices
Definition: mesh.c:2615
struct ID3DXSkinInfo * skin_info
Definition: mesh.c:2635
DWORD num_normals
Definition: mesh.c:2623
DWORD * material_indices
Definition: mesh.c:2633
DWORD fvf
Definition: mesh.c:2619
D3DXVECTOR2 * tex_coords
Definition: mesh.c:2627
DWORD num_poly_faces
Definition: mesh.c:2613
DWORD * num_tri_per_face
Definition: mesh.c:2616
D3DXMATERIAL * materials
Definition: mesh.c:2632
DWORD num_materials
Definition: mesh.c:2631
DWORD num_tri_faces
Definition: mesh.c:2614
DWORD nb_bones
Definition: mesh.c:2636
D3DXVECTOR3 * normals
Definition: mesh.c:2624
DWORD * indices
Definition: mesh.c:2617
DWORD num_vertices
Definition: mesh.c:2612
Definition: mesh.c:198
DWORD fvf
Definition: mesh.c:205
Definition: name.c:39
struct outline * items
Definition: mesh.c:5339
int capacity
Definition: mesh.c:5338
int count
Definition: mesh.c:5338
Definition: mesh.c:5330
struct point2d * items
Definition: mesh.c:5332
int count
Definition: mesh.c:5331
int capacity
Definition: mesh.c:5331
struct point2d_index * items
Definition: mesh.c:5357
struct outline * outline
Definition: mesh.c:5350
int vertex
Definition: mesh.c:5351
Definition: mesh.c:5317
D3DXVECTOR2 pos
Definition: mesh.c:5318
enum pointtype corner
Definition: mesh.c:5319
float * sin
Definition: mesh.c:4751
float * cos
Definition: mesh.c:4752
long y
Definition: polytest.cpp:48
long x
Definition: polytest.cpp:48
POINTFX apfx[1]
Definition: wingdi.h:2714
struct triangulation * items
Definition: mesh.c:5387
struct glyphinfo * glyph
Definition: mesh.c:5389
BOOL last_on_top
Definition: mesh.c:5380
struct word_array vertex_stack
Definition: mesh.c:5379
BOOL merging
Definition: mesh.c:5380
Definition: mesh.c:6643
UINT w
Definition: mesh.c:6647
UINT x
Definition: mesh.c:6644
UINT y
Definition: mesh.c:6645
UINT z
Definition: mesh.c:6646
DWORD first_shared_index
Definition: mesh.c:1212
float key
Definition: mesh.c:1210
DWORD vertex_index
Definition: mesh.c:1211
Definition: mesh.c:4558
D3DXVECTOR3 normal
Definition: mesh.c:4560
D3DXVECTOR3 position
Definition: mesh.c:4559
float x
Definition: hlsl.c:29
float y
Definition: hlsl.c:29
float z
Definition: hlsl.c:29
int capacity
Definition: mesh.c:5371
WORD * items
Definition: mesh.c:5372
int count
Definition: mesh.c:5371
#define max(a, b)
Definition: svc.c:63
static void buffer_size(GLcontext *ctx, GLuint *width, GLuint *height)
Definition: swimpl.c:888
#define LIST_INIT(head)
Definition: queue.h:197
#define LIST_ENTRY(type)
Definition: queue.h:175
float FLOAT
Definition: typedefs.h:69
ULONG_PTR SIZE_T
Definition: typedefs.h:80
int32_t INT
Definition: typedefs.h:58
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
Definition: dlist.c:348
Definition: pdh_main.c:94
int ret
#define ZeroMemory
Definition: winbase.h:1712
#define CopyMemory
Definition: winbase.h:1710
#define MoveMemory
Definition: winbase.h:1709
#define WINAPI
Definition: msvc.h:6
#define E_NOINTERFACE
Definition: winerror.h:2364
int WINAPI GetObjectW(_In_ HANDLE h, _In_ int c, _Out_writes_bytes_opt_(c) LPVOID pv)
HGDIOBJ WINAPI GetCurrentObject(_In_ HDC, _In_ UINT)
Definition: dc.c:428
HGDIOBJ WINAPI SelectObject(_In_ HDC, _In_ HGDIOBJ)
Definition: dc.c:1539
#define TT_POLYGON_TYPE
Definition: wingdi.h:1318
UINT WINAPI GetOutlineTextMetricsW(_In_ HDC hdc, _In_ UINT cjCopy, _Out_writes_bytes_opt_(cjCopy) LPOUTLINETEXTMETRICW potm)
HFONT WINAPI CreateFontIndirectW(_In_ const LOGFONTW *)
#define GGO_NATIVE
Definition: wingdi.h:850
#define TT_PRIM_LINE
Definition: wingdi.h:1319
DWORD WINAPI GetGlyphOutlineW(_In_ HDC hdc, _In_ UINT uChar, _In_ UINT fuFormat, _Out_ LPGLYPHMETRICS lpgm, _In_ DWORD cjBuffer, _Out_writes_bytes_opt_(cjBuffer) LPVOID pvBuffer, _In_ CONST MAT2 *lpmat2)
__wchar_t WCHAR
Definition: xmlstorage.h:180
unsigned char BYTE
Definition: xxhash.c:193