xref: /reactos/dll/directx/wine/d3drm/meshbuilder.c (revision 1734f297)
1 /*
2  * Implementation of IDirect3DRMMeshBuilderX and IDirect3DRMMesh interfaces
3  *
4  * Copyright 2010, 2012 Christian Costa
5  * Copyright 2011 André Hentschel
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21 
22 #include "d3drm_private.h"
23 
24 WINE_DEFAULT_DEBUG_CHANNEL(d3drm);
25 
26 struct coords_2d
27 {
28     D3DVALUE u;
29     D3DVALUE v;
30 };
31 
32 struct mesh_material
33 {
34     D3DCOLOR color;
35     IDirect3DRMMaterial2 *material;
36     IDirect3DRMTexture3 *texture;
37 };
38 
39 char templates[] = {
40 "xof 0302txt 0064"
41 "template Header"
42 "{"
43 "<3D82AB43-62DA-11CF-AB39-0020AF71E433>"
44 "WORD major;"
45 "WORD minor;"
46 "DWORD flags;"
47 "}"
48 "template Vector"
49 "{"
50 "<3D82AB5E-62DA-11CF-AB39-0020AF71E433>"
51 "FLOAT x;"
52 "FLOAT y;"
53 "FLOAT z;"
54 "}"
55 "template Coords2d"
56 "{"
57 "<F6F23F44-7686-11CF-8F52-0040333594A3>"
58 "FLOAT u;"
59 "FLOAT v;"
60 "}"
61 "template Matrix4x4"
62 "{"
63 "<F6F23F45-7686-11CF-8F52-0040333594A3>"
64 "array FLOAT matrix[16];"
65 "}"
66 "template ColorRGBA"
67 "{"
68 "<35FF44E0-6C7C-11CF-8F52-0040333594A3>"
69 "FLOAT red;"
70 "FLOAT green;"
71 "FLOAT blue;"
72 "FLOAT alpha;"
73 "}"
74 "template ColorRGB"
75 "{"
76 "<D3E16E81-7835-11CF-8F52-0040333594A3>"
77 "FLOAT red;"
78 "FLOAT green;"
79 "FLOAT blue;"
80 "}"
81 "template IndexedColor"
82 "{"
83 "<1630B820-7842-11CF-8F52-0040333594A3>"
84 "DWORD index;"
85 "ColorRGBA indexColor;"
86 "}"
87 "template Boolean"
88 "{"
89 "<537DA6A0-CA37-11D0-941C-0080C80CFA7B>"
90 "DWORD truefalse;"
91 "}"
92 "template Boolean2d"
93 "{"
94 "<4885AE63-78E8-11CF-8F52-0040333594A3>"
95 "Boolean u;"
96 "Boolean v;"
97 "}"
98 "template MaterialWrap"
99 "{"
100 "<4885AE60-78E8-11CF-8F52-0040333594A3>"
101 "Boolean u;"
102 "Boolean v;"
103 "}"
104 "template TextureFilename"
105 "{"
106 "<A42790E1-7810-11CF-8F52-0040333594A3>"
107 "STRING filename;"
108 "}"
109 "template Material"
110 "{"
111 "<3D82AB4D-62DA-11CF-AB39-0020AF71E433>"
112 "ColorRGBA faceColor;"
113 "FLOAT power;"
114 "ColorRGB specularColor;"
115 "ColorRGB emissiveColor;"
116 "[...]"
117 "}"
118 "template MeshFace"
119 "{"
120 "<3D82AB5F-62DA-11CF-AB39-0020AF71E433>"
121 "DWORD nFaceVertexIndices;"
122 "array DWORD faceVertexIndices[nFaceVertexIndices];"
123 "}"
124 "template MeshFaceWraps"
125 "{"
126 "<ED1EC5C0-C0A8-11D0-941C-0080C80CFA7B>"
127 "DWORD nFaceWrapValues;"
128 "array Boolean2d faceWrapValues[nFaceWrapValues];"
129 "}"
130 "template MeshTextureCoords"
131 "{"
132 "<F6F23F40-7686-11CF-8F52-0040333594A3>"
133 "DWORD nTextureCoords;"
134 "array Coords2d textureCoords[nTextureCoords];"
135 "}"
136 "template MeshMaterialList"
137 "{"
138 "<F6F23F42-7686-11CF-8F52-0040333594A3>"
139 "DWORD nMaterials;"
140 "DWORD nFaceIndexes;"
141 "array DWORD faceIndexes[nFaceIndexes];"
142 "[Material]"
143 "}"
144 "template MeshNormals"
145 "{"
146 "<F6F23F43-7686-11CF-8F52-0040333594A3>"
147 "DWORD nNormals;"
148 "array Vector normals[nNormals];"
149 "DWORD nFaceNormals;"
150 "array MeshFace faceNormals[nFaceNormals];"
151 "}"
152 "template MeshVertexColors"
153 "{"
154 "<1630B821-7842-11CF-8F52-0040333594A3>"
155 "DWORD nVertexColors;"
156 "array IndexedColor vertexColors[nVertexColors];"
157 "}"
158 "template Mesh"
159 "{"
160 "<3D82AB44-62DA-11CF-AB39-0020AF71E433>"
161 "DWORD nVertices;"
162 "array Vector vertices[nVertices];"
163 "DWORD nFaces;"
164 "array MeshFace faces[nFaces];"
165 "[...]"
166 "}"
167 "template FrameTransformMatrix"
168 "{"
169 "<F6F23F41-7686-11CF-8F52-0040333594A3>"
170 "Matrix4x4 frameMatrix;"
171 "}"
172 "template Frame"
173 "{"
174 "<3D82AB46-62DA-11CF-AB39-0020AF71E433>"
175 "[...]"
176 "}"
177 "template FloatKeys"
178 "{"
179 "<10DD46A9-775B-11CF-8F52-0040333594A3>"
180 "DWORD nValues;"
181 "array FLOAT values[nValues];"
182 "}"
183 "template TimedFloatKeys"
184 "{"
185 "<F406B180-7B3B-11CF-8F52-0040333594A3>"
186 "DWORD time;"
187 "FloatKeys tfkeys;"
188 "}"
189 "template AnimationKey"
190 "{"
191 "<10DD46A8-775B-11CF-8F52-0040333594A3>"
192 "DWORD keyType;"
193 "DWORD nKeys;"
194 "array TimedFloatKeys keys[nKeys];"
195 "}"
196 "template AnimationOptions"
197 "{"
198 "<E2BF56C0-840F-11CF-8F52-0040333594A3>"
199 "DWORD openclosed;"
200 "DWORD positionquality;"
201 "}"
202 "template Animation"
203 "{"
204 "<3D82AB4F-62DA-11CF-AB39-0020AF71E433>"
205 "[...]"
206 "}"
207 "template AnimationSet"
208 "{"
209 "<3D82AB50-62DA-11CF-AB39-0020AF71E433>"
210 "[Animation]"
211 "}"
212 "template InlineData"
213 "{"
214 "<3A23EEA0-94B1-11D0-AB39-0020AF71E433>"
215 "[BINARY]"
216 "}"
217 "template Url"
218 "{"
219 "<3A23EEA1-94B1-11D0-AB39-0020AF71E433>"
220 "DWORD nUrls;"
221 "array STRING urls[nUrls];"
222 "}"
223 "template ProgressiveMesh"
224 "{"
225 "<8A63C360-997D-11D0-941C-0080C80CFA7B>"
226 "[Url,InlineData]"
227 "}"
228 "template Guid"
229 "{"
230 "<A42790E0-7810-11CF-8F52-0040333594A3>"
231 "DWORD data1;"
232 "WORD data2;"
233 "WORD data3;"
234 "array UCHAR data4[8];"
235 "}"
236 "template StringProperty"
237 "{"
238 "<7F0F21E0-BFE1-11D1-82C0-00A0C9697271>"
239 "STRING key;"
240 "STRING value;"
241 "}"
242 "template PropertyBag"
243 "{"
244 "<7F0F21E1-BFE1-11D1-82C0-00A0C9697271>"
245 "[StringProperty]"
246 "}"
247 "template ExternalVisual"
248 "{"
249 "<98116AA0-BDBA-11D1-82C0-00A0C9697271>"
250 "Guid guidExternalVisual;"
251 "[...]"
252 "}"
253 "template RightHanded"
254 "{"
255 "<7F5D5EA0-D53A-11D1-82C0-00A0C9697271>"
256 "DWORD bRightHanded;"
257 "}"
258 };
259 
260 BOOL d3drm_array_reserve(void **elements, SIZE_T *capacity, SIZE_T element_count, SIZE_T element_size)
261 {
262     SIZE_T new_capacity, max_capacity;
263     void *new_elements;
264 
265     if (element_count <= *capacity)
266         return TRUE;
267 
268     max_capacity = ~(SIZE_T)0 / element_size;
269     if (max_capacity < element_count)
270         return FALSE;
271 
272     new_capacity = max(*capacity, 4);
273     while (new_capacity < element_count && new_capacity <= max_capacity / 2)
274         new_capacity *= 2;
275 
276     if (new_capacity < element_count)
277         new_capacity = max_capacity;
278 
279     if (!(new_elements = heap_realloc(*elements, new_capacity * element_size)))
280         return FALSE;
281 
282     *elements = new_elements;
283     *capacity = new_capacity;
284     return TRUE;
285 }
286 
287 static inline struct d3drm_mesh *impl_from_IDirect3DRMMesh(IDirect3DRMMesh *iface)
288 {
289     return CONTAINING_RECORD(iface, struct d3drm_mesh, IDirect3DRMMesh_iface);
290 }
291 
292 static inline struct d3drm_mesh_builder *impl_from_IDirect3DRMMeshBuilder2(IDirect3DRMMeshBuilder2 *iface)
293 {
294     return CONTAINING_RECORD(iface, struct d3drm_mesh_builder, IDirect3DRMMeshBuilder2_iface);
295 }
296 
297 static inline struct d3drm_mesh_builder *impl_from_IDirect3DRMMeshBuilder3(IDirect3DRMMeshBuilder3 *iface)
298 {
299     return CONTAINING_RECORD(iface, struct d3drm_mesh_builder, IDirect3DRMMeshBuilder3_iface);
300 }
301 
302 static inline struct d3drm_wrap *impl_from_IDirect3DRMWrap(IDirect3DRMWrap *iface)
303 {
304     return CONTAINING_RECORD(iface, struct d3drm_wrap, IDirect3DRMWrap_iface);
305 }
306 
307 static void clean_mesh_builder_data(struct d3drm_mesh_builder *mesh_builder)
308 {
309     DWORD i;
310 
311     IDirect3DRMMeshBuilder3_SetName(&mesh_builder->IDirect3DRMMeshBuilder3_iface, NULL);
312     heap_free(mesh_builder->vertices);
313     mesh_builder->vertices = NULL;
314     mesh_builder->nb_vertices = 0;
315     mesh_builder->vertices_size = 0;
316     heap_free(mesh_builder->normals);
317     mesh_builder->normals = NULL;
318     mesh_builder->nb_normals = 0;
319     mesh_builder->normals_size = 0;
320     heap_free(mesh_builder->pFaceData);
321     mesh_builder->pFaceData = NULL;
322     mesh_builder->face_data_size = 0;
323     mesh_builder->nb_faces = 0;
324     heap_free(mesh_builder->pCoords2d);
325     mesh_builder->pCoords2d = NULL;
326     mesh_builder->nb_coords2d = 0;
327     for (i = 0; i < mesh_builder->nb_materials; i++)
328     {
329         if (mesh_builder->materials[i].material)
330             IDirect3DRMMaterial2_Release(mesh_builder->materials[i].material);
331         if (mesh_builder->materials[i].texture)
332             IDirect3DRMTexture3_Release(mesh_builder->materials[i].texture);
333     }
334     mesh_builder->nb_materials = 0;
335     heap_free(mesh_builder->materials);
336     mesh_builder->materials = NULL;
337     heap_free(mesh_builder->material_indices);
338     mesh_builder->material_indices = NULL;
339 }
340 
341 static HRESULT WINAPI d3drm_mesh_builder2_QueryInterface(IDirect3DRMMeshBuilder2 *iface, REFIID riid, void **out)
342 {
343     struct d3drm_mesh_builder *mesh_builder = impl_from_IDirect3DRMMeshBuilder2(iface);
344 
345     TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
346 
347     if (IsEqualGUID(riid, &IID_IDirect3DRMMeshBuilder2)
348             || IsEqualGUID(riid, &IID_IDirect3DRMMeshBuilder)
349             || IsEqualGUID(riid, &IID_IDirect3DRMVisual)
350             || IsEqualGUID(riid, &IID_IDirect3DRMObject)
351             || IsEqualGUID(riid, &IID_IUnknown))
352     {
353         *out = &mesh_builder->IDirect3DRMMeshBuilder2_iface;
354     }
355     else if (IsEqualGUID(riid, &IID_IDirect3DRMMeshBuilder3))
356     {
357         *out = &mesh_builder->IDirect3DRMMeshBuilder3_iface;
358     }
359     else
360     {
361         *out = NULL;
362         WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
363         return E_NOINTERFACE;
364     }
365 
366     IUnknown_AddRef((IUnknown *)*out);
367     return S_OK;
368 }
369 
370 static ULONG WINAPI d3drm_mesh_builder2_AddRef(IDirect3DRMMeshBuilder2 *iface)
371 {
372     struct d3drm_mesh_builder *mesh_builder = impl_from_IDirect3DRMMeshBuilder2(iface);
373     ULONG refcount = InterlockedIncrement(&mesh_builder->ref);
374 
375     TRACE("%p increasing refcount to %u.\n", mesh_builder, refcount);
376 
377     return refcount;
378 }
379 
380 static ULONG WINAPI d3drm_mesh_builder2_Release(IDirect3DRMMeshBuilder2 *iface)
381 {
382     struct d3drm_mesh_builder *mesh_builder = impl_from_IDirect3DRMMeshBuilder2(iface);
383     ULONG refcount = InterlockedDecrement(&mesh_builder->ref);
384 
385     TRACE("%p decreasing refcount to %u.\n", mesh_builder, refcount);
386 
387     if (!refcount)
388     {
389         d3drm_object_cleanup((IDirect3DRMObject *)iface, &mesh_builder->obj);
390         clean_mesh_builder_data(mesh_builder);
391         if (mesh_builder->material)
392             IDirect3DRMMaterial2_Release(mesh_builder->material);
393         if (mesh_builder->texture)
394             IDirect3DRMTexture3_Release(mesh_builder->texture);
395         IDirect3DRM_Release(mesh_builder->d3drm);
396         heap_free(mesh_builder);
397     }
398 
399     return refcount;
400 }
401 
402 static HRESULT WINAPI d3drm_mesh_builder2_Clone(IDirect3DRMMeshBuilder2 *iface,
403         IUnknown *outer, REFIID iid, void **out)
404 {
405     FIXME("iface %p, outer %p, iid %s, out %p stub!\n", iface, outer, debugstr_guid(iid), out);
406 
407     return E_NOTIMPL;
408 }
409 
410 static HRESULT WINAPI d3drm_mesh_builder2_AddDestroyCallback(IDirect3DRMMeshBuilder2 *iface,
411         D3DRMOBJECTCALLBACK cb, void *ctx)
412 {
413     struct d3drm_mesh_builder *mesh_builder = impl_from_IDirect3DRMMeshBuilder2(iface);
414 
415     TRACE("iface %p, cb %p, ctx %p.\n", iface, cb, ctx);
416 
417     return IDirect3DRMMeshBuilder3_AddDestroyCallback(&mesh_builder->IDirect3DRMMeshBuilder3_iface, cb, ctx);
418 }
419 
420 static HRESULT WINAPI d3drm_mesh_builder2_DeleteDestroyCallback(IDirect3DRMMeshBuilder2 *iface,
421         D3DRMOBJECTCALLBACK cb, void *ctx)
422 {
423     struct d3drm_mesh_builder *mesh_builder = impl_from_IDirect3DRMMeshBuilder2(iface);
424 
425     TRACE("iface %p, cb %p, ctx %p.\n", iface, cb, ctx);
426 
427     return IDirect3DRMMeshBuilder3_DeleteDestroyCallback(&mesh_builder->IDirect3DRMMeshBuilder3_iface, cb, ctx);
428 }
429 
430 static HRESULT WINAPI d3drm_mesh_builder3_SetAppData(IDirect3DRMMeshBuilder3 *iface, DWORD data)
431 {
432     struct d3drm_mesh_builder *mesh_builder = impl_from_IDirect3DRMMeshBuilder3(iface);
433 
434     TRACE("iface %p, data %#x.\n", iface, data);
435 
436     mesh_builder->obj.appdata = data;
437 
438     return D3DRM_OK;
439 }
440 
441 static HRESULT WINAPI d3drm_mesh_builder2_SetAppData(IDirect3DRMMeshBuilder2 *iface, DWORD data)
442 {
443     struct d3drm_mesh_builder *mesh_builder = impl_from_IDirect3DRMMeshBuilder2(iface);
444 
445     TRACE("iface %p, data %#x.\n", iface, data);
446 
447     return d3drm_mesh_builder3_SetAppData(&mesh_builder->IDirect3DRMMeshBuilder3_iface, data);
448 }
449 
450 static DWORD WINAPI d3drm_mesh_builder3_GetAppData(IDirect3DRMMeshBuilder3 *iface)
451 {
452     struct d3drm_mesh_builder *mesh_builder = impl_from_IDirect3DRMMeshBuilder3(iface);
453 
454     TRACE("iface %p.\n", iface);
455 
456     return mesh_builder->obj.appdata;
457 }
458 
459 static DWORD WINAPI d3drm_mesh_builder2_GetAppData(IDirect3DRMMeshBuilder2 *iface)
460 {
461     struct d3drm_mesh_builder *mesh_builder = impl_from_IDirect3DRMMeshBuilder2(iface);
462 
463     TRACE("iface %p.\n", iface);
464 
465     return d3drm_mesh_builder3_GetAppData(&mesh_builder->IDirect3DRMMeshBuilder3_iface);
466 }
467 
468 static HRESULT WINAPI d3drm_mesh_builder2_SetName(IDirect3DRMMeshBuilder2 *iface, const char *name)
469 {
470     struct d3drm_mesh_builder *mesh_builder = impl_from_IDirect3DRMMeshBuilder2(iface);
471 
472     TRACE("iface %p, name %s.\n", iface, debugstr_a(name));
473 
474     return IDirect3DRMMeshBuilder3_SetName(&mesh_builder->IDirect3DRMMeshBuilder3_iface, name);
475 }
476 
477 static HRESULT WINAPI d3drm_mesh_builder2_GetName(IDirect3DRMMeshBuilder2 *iface, DWORD *size, char *name)
478 {
479     struct d3drm_mesh_builder *mesh_builder = impl_from_IDirect3DRMMeshBuilder2(iface);
480 
481     TRACE("iface %p, size %p, name %p.\n", iface, size, name);
482 
483     return IDirect3DRMMeshBuilder3_GetName(&mesh_builder->IDirect3DRMMeshBuilder3_iface, size, name);
484 }
485 
486 static HRESULT WINAPI d3drm_mesh_builder2_GetClassName(IDirect3DRMMeshBuilder2 *iface, DWORD *size, char *name)
487 {
488     struct d3drm_mesh_builder *mesh_builder = impl_from_IDirect3DRMMeshBuilder2(iface);
489 
490     TRACE("iface %p, size %p, name %p.\n", iface, size, name);
491 
492     return IDirect3DRMMeshBuilder3_GetClassName(&mesh_builder->IDirect3DRMMeshBuilder3_iface, size, name);
493 }
494 
495 static HRESULT WINAPI d3drm_mesh_builder2_Load(IDirect3DRMMeshBuilder2 *iface, void *filename,
496         void *name, D3DRMLOADOPTIONS flags, D3DRMLOADTEXTURECALLBACK cb, void *ctx)
497 {
498     struct d3drm_mesh_builder *mesh_builder = impl_from_IDirect3DRMMeshBuilder2(iface);
499 
500     TRACE("iface %p, filename %p, name %p, flags %#x, cb %p, ctx %p.\n",
501             iface, filename, name, flags, cb, ctx);
502 
503     if (cb)
504         FIXME("Texture callback is not yet supported\n");
505 
506     return IDirect3DRMMeshBuilder3_Load(&mesh_builder->IDirect3DRMMeshBuilder3_iface,
507             filename, name, flags, NULL, ctx);
508 }
509 
510 static HRESULT WINAPI d3drm_mesh_builder2_Save(IDirect3DRMMeshBuilder2 *iface,
511         const char *filename, D3DRMXOFFORMAT format, D3DRMSAVEOPTIONS flags)
512 {
513     FIXME("iface %p, filename %s, format %#x, flags %#x stub!\n",
514             iface, debugstr_a(filename), format, flags);
515 
516     return E_NOTIMPL;
517 }
518 
519 static HRESULT WINAPI d3drm_mesh_builder2_Scale(IDirect3DRMMeshBuilder2 *iface,
520         D3DVALUE sx, D3DVALUE sy, D3DVALUE sz)
521 {
522     struct d3drm_mesh_builder *mesh_builder = impl_from_IDirect3DRMMeshBuilder2(iface);
523 
524     TRACE("iface %p, sx %.8e, sy %.8e, sz %.8e.\n", iface, sx, sy, sz);
525 
526     return IDirect3DRMMeshBuilder3_Scale(&mesh_builder->IDirect3DRMMeshBuilder3_iface, sx, sy, sz);
527 }
528 
529 static HRESULT WINAPI d3drm_mesh_builder2_Translate(IDirect3DRMMeshBuilder2 *iface,
530         D3DVALUE tx, D3DVALUE ty, D3DVALUE tz)
531 {
532     FIXME("iface %p, tx %.8e, ty %.8e, tz %.8e stub!\n", iface, tx, ty, tz);
533 
534     return E_NOTIMPL;
535 }
536 
537 static HRESULT WINAPI d3drm_mesh_builder2_SetColorSource(IDirect3DRMMeshBuilder2 *iface, D3DRMCOLORSOURCE source)
538 {
539     FIXME("iface %p, source %#x stub!\n", iface, source);
540 
541     return E_NOTIMPL;
542 }
543 
544 static HRESULT WINAPI d3drm_mesh_builder2_GetBox(IDirect3DRMMeshBuilder2 *iface, D3DRMBOX *box)
545 {
546     FIXME("iface %p, box %p stub!\n", iface, box);
547 
548     return E_NOTIMPL;
549 }
550 
551 static HRESULT WINAPI d3drm_mesh_builder2_GenerateNormals(IDirect3DRMMeshBuilder2 *iface)
552 {
553     FIXME("iface %p stub!\n", iface);
554 
555     return E_NOTIMPL;
556 }
557 
558 static D3DRMCOLORSOURCE WINAPI d3drm_mesh_builder2_GetColorSource(IDirect3DRMMeshBuilder2 *iface)
559 {
560     FIXME("iface %p stub!\n", iface);
561 
562     return E_NOTIMPL;
563 }
564 
565 static HRESULT WINAPI d3drm_mesh_builder2_AddMesh(IDirect3DRMMeshBuilder2 *iface, IDirect3DRMMesh *mesh)
566 {
567     FIXME("iface %p, mesh %p stub!\n", iface, mesh);
568 
569     return E_NOTIMPL;
570 }
571 
572 static HRESULT WINAPI d3drm_mesh_builder2_AddMeshBuilder(IDirect3DRMMeshBuilder2 *iface,
573         IDirect3DRMMeshBuilder *mesh_builder)
574 {
575     FIXME("iface %p, mesh_builder %p stub!\n", iface, mesh_builder);
576 
577     return E_NOTIMPL;
578 }
579 
580 static HRESULT WINAPI d3drm_mesh_builder2_AddFrame(IDirect3DRMMeshBuilder2 *iface, IDirect3DRMFrame *frame)
581 {
582     FIXME("iface %p, frame %p stub!\n", iface, frame);
583 
584     return E_NOTIMPL;
585 }
586 
587 static HRESULT WINAPI d3drm_mesh_builder2_AddFace(IDirect3DRMMeshBuilder2 *iface, IDirect3DRMFace *face)
588 {
589     FIXME("iface %p, face %p stub!\n", iface, face);
590 
591     return E_NOTIMPL;
592 }
593 
594 static HRESULT WINAPI d3drm_mesh_builder2_AddFaces(IDirect3DRMMeshBuilder2 *iface,
595         DWORD vertex_count, D3DVECTOR *vertices, DWORD normal_count, D3DVECTOR *normals,
596         DWORD *face_data, IDirect3DRMFaceArray **array)
597 {
598     FIXME("iface %p, vertex_count %u, vertices %p, normal_count %u, normals %p, face_data %p, array %p stub!\n",
599             iface, vertex_count, vertices, normal_count, normals, face_data, array);
600 
601     return E_NOTIMPL;
602 }
603 
604 static HRESULT WINAPI d3drm_mesh_builder2_ReserveSpace(IDirect3DRMMeshBuilder2 *iface,
605         DWORD vertex_count, DWORD normal_count, DWORD face_count)
606 {
607     FIXME("iface %p, vertex_count %u, normal_count %u, face_count %u stub!\n",
608             iface, vertex_count, normal_count, face_count);
609 
610     return E_NOTIMPL;
611 }
612 
613 static HRESULT WINAPI d3drm_mesh_builder2_SetColorRGB(IDirect3DRMMeshBuilder2 *iface,
614         D3DVALUE red, D3DVALUE green, D3DVALUE blue)
615 {
616     struct d3drm_mesh_builder *mesh_builder = impl_from_IDirect3DRMMeshBuilder2(iface);
617 
618     TRACE("iface %p, red %.8e, green %.8e, blue %.8e.\n", iface, red, green, blue);
619 
620     return IDirect3DRMMeshBuilder3_SetColorRGB(&mesh_builder->IDirect3DRMMeshBuilder3_iface, red, green, blue);
621 }
622 
623 static HRESULT WINAPI d3drm_mesh_builder2_SetColor(IDirect3DRMMeshBuilder2 *iface, D3DCOLOR color)
624 {
625     struct d3drm_mesh_builder *mesh_builder = impl_from_IDirect3DRMMeshBuilder2(iface);
626 
627     TRACE("iface %p, color 0x%08x.\n", iface, color);
628 
629     return IDirect3DRMMeshBuilder3_SetColor(&mesh_builder->IDirect3DRMMeshBuilder3_iface, color);
630 }
631 
632 static HRESULT WINAPI d3drm_mesh_builder2_SetTexture(IDirect3DRMMeshBuilder2 *iface,
633         IDirect3DRMTexture *texture)
634 {
635     struct d3drm_mesh_builder *mesh_builder = impl_from_IDirect3DRMMeshBuilder2(iface);
636     IDirect3DRMTexture3 *texture3 = NULL;
637     HRESULT hr = D3DRM_OK;
638 
639     TRACE("iface %p, texture %p.\n", iface, texture);
640 
641     if (texture)
642         hr = IDirect3DRMTexture_QueryInterface(texture, &IID_IDirect3DRMTexture3, (void **)&texture3);
643     if (SUCCEEDED(hr))
644         hr = IDirect3DRMMeshBuilder3_SetTexture(&mesh_builder->IDirect3DRMMeshBuilder3_iface, texture3);
645     if (texture3)
646         IDirect3DRMTexture3_Release(texture3);
647 
648     return hr;
649 }
650 
651 static HRESULT WINAPI d3drm_mesh_builder2_SetMaterial(IDirect3DRMMeshBuilder2 *iface,
652         IDirect3DRMMaterial *material)
653 {
654     struct d3drm_mesh_builder *mesh_builder = impl_from_IDirect3DRMMeshBuilder2(iface);
655 
656     TRACE("iface %p, material %p.\n", iface, material);
657 
658     return IDirect3DRMMeshBuilder3_SetMaterial(&mesh_builder->IDirect3DRMMeshBuilder3_iface,
659             (IDirect3DRMMaterial2 *)material);
660 }
661 
662 static HRESULT WINAPI d3drm_mesh_builder2_SetTextureTopology(IDirect3DRMMeshBuilder2 *iface,
663         BOOL wrap_u, BOOL wrap_v)
664 {
665     FIXME("iface %p, wrap_u %#x, wrap_v %#x stub!\n", iface, wrap_u, wrap_v);
666 
667     return E_NOTIMPL;
668 }
669 
670 static HRESULT WINAPI d3drm_mesh_builder2_SetQuality(IDirect3DRMMeshBuilder2 *iface,
671         D3DRMRENDERQUALITY quality)
672 {
673     FIXME("iface %p, quality %#x stub!\n", iface, quality);
674 
675     return E_NOTIMPL;
676 }
677 
678 static HRESULT WINAPI d3drm_mesh_builder2_SetPerspective(IDirect3DRMMeshBuilder2 *iface, BOOL enable)
679 {
680     FIXME("iface %p, enable %#x stub!\n", iface, enable);
681 
682     return E_NOTIMPL;
683 }
684 
685 static HRESULT WINAPI d3drm_mesh_builder2_SetVertex(IDirect3DRMMeshBuilder2 *iface,
686         DWORD index, D3DVALUE x, D3DVALUE y, D3DVALUE z)
687 {
688     FIXME("iface %p, index %u, x %.8e, y %.8e, z %.8e stub!\n", iface, index, x, y, z);
689 
690     return E_NOTIMPL;
691 }
692 
693 static HRESULT WINAPI d3drm_mesh_builder2_SetNormal(IDirect3DRMMeshBuilder2 *iface,
694         DWORD index, D3DVALUE x, D3DVALUE y, D3DVALUE z)
695 {
696     FIXME("iface %p, index %u, x %.8e, y %.8e, z %.8e stub!\n", iface, index, x, y, z);
697 
698     return E_NOTIMPL;
699 }
700 
701 static HRESULT WINAPI d3drm_mesh_builder2_SetTextureCoordinates(IDirect3DRMMeshBuilder2 *iface,
702         DWORD index, D3DVALUE u, D3DVALUE v)
703 {
704     struct d3drm_mesh_builder *mesh_builder = impl_from_IDirect3DRMMeshBuilder2(iface);
705 
706     TRACE("iface %p, index %u, u %.8e, v %.8e.\n", iface, index, u, v);
707 
708     return IDirect3DRMMeshBuilder3_SetTextureCoordinates(&mesh_builder->IDirect3DRMMeshBuilder3_iface,
709             index, u, v);
710 }
711 
712 static HRESULT WINAPI d3drm_mesh_builder2_SetVertexColor(IDirect3DRMMeshBuilder2 *iface,
713         DWORD index, D3DCOLOR color)
714 {
715     FIXME("iface %p, index %u, color 0x%08x stub!\n", iface, index, color);
716 
717     return E_NOTIMPL;
718 }
719 
720 static HRESULT WINAPI d3drm_mesh_builder2_SetVertexColorRGB(IDirect3DRMMeshBuilder2 *iface,
721         DWORD index, D3DVALUE red, D3DVALUE green, D3DVALUE blue)
722 {
723     FIXME("iface %p, index %u, red %.8e, green %.8e, blue %.8e stub!\n",
724             iface, index, red, green, blue);
725 
726     return E_NOTIMPL;
727 }
728 
729 static HRESULT WINAPI d3drm_mesh_builder2_GetFaces(IDirect3DRMMeshBuilder2 *iface,
730         IDirect3DRMFaceArray **array)
731 {
732     FIXME("iface %p, array %p stub!\n", iface, array);
733 
734     return E_NOTIMPL;
735 }
736 
737 static HRESULT WINAPI d3drm_mesh_builder2_GetVertices(IDirect3DRMMeshBuilder2 *iface,
738         DWORD *vertex_count, D3DVECTOR *vertices, DWORD *normal_count, D3DVECTOR *normals,
739         DWORD *face_data_size, DWORD *face_data)
740 {
741     struct d3drm_mesh_builder *mesh_builder = impl_from_IDirect3DRMMeshBuilder2(iface);
742 
743     TRACE("iface %p, vertex_count %p, vertices %p, normal_count %p, normals %p, face_data_size %p, face_data %p.\n",
744             iface, vertex_count, vertices, normal_count, normals, face_data_size, face_data);
745 
746     if (vertices && (!vertex_count || (*vertex_count < mesh_builder->nb_vertices)))
747         return D3DRMERR_BADVALUE;
748     if (vertex_count)
749         *vertex_count = mesh_builder->nb_vertices;
750     if (vertices && mesh_builder->nb_vertices)
751         memcpy(vertices, mesh_builder->vertices, mesh_builder->nb_vertices * sizeof(*vertices));
752 
753     if (normals && (!normal_count || (*normal_count < mesh_builder->nb_normals)))
754         return D3DRMERR_BADVALUE;
755     if (normal_count)
756         *normal_count = mesh_builder->nb_normals;
757     if (normals && mesh_builder->nb_normals)
758         memcpy(normals, mesh_builder->normals, mesh_builder->nb_normals * sizeof(*normals));
759 
760     if (face_data && (!face_data_size || (*face_data_size < mesh_builder->face_data_size)))
761         return D3DRMERR_BADVALUE;
762     if (face_data_size)
763         *face_data_size = mesh_builder->face_data_size;
764     if (face_data && mesh_builder->face_data_size)
765         memcpy(face_data, mesh_builder->pFaceData, mesh_builder->face_data_size * sizeof(*face_data));
766 
767     return D3DRM_OK;
768 }
769 
770 static HRESULT WINAPI d3drm_mesh_builder2_GetTextureCoordinates(IDirect3DRMMeshBuilder2 *iface,
771         DWORD index, D3DVALUE *u, D3DVALUE *v)
772 {
773     struct d3drm_mesh_builder *mesh_builder = impl_from_IDirect3DRMMeshBuilder2(iface);
774 
775     TRACE("iface %p, index %u, u %p, v %p.\n", iface, index, u, v);
776 
777     return IDirect3DRMMeshBuilder3_GetTextureCoordinates(&mesh_builder->IDirect3DRMMeshBuilder3_iface,
778             index, u, v);
779 }
780 
781 static int WINAPI d3drm_mesh_builder2_AddVertex(IDirect3DRMMeshBuilder2 *iface,
782         D3DVALUE x, D3DVALUE y, D3DVALUE z)
783 {
784     struct d3drm_mesh_builder *mesh_builder = impl_from_IDirect3DRMMeshBuilder2(iface);
785 
786     TRACE("iface %p, x %.8e, y %.8e, z %.8e.\n", iface, x, y, z);
787 
788     return IDirect3DRMMeshBuilder3_AddVertex(&mesh_builder->IDirect3DRMMeshBuilder3_iface, x, y, z);
789 }
790 
791 static int WINAPI d3drm_mesh_builder2_AddNormal(IDirect3DRMMeshBuilder2 *iface,
792         D3DVALUE x, D3DVALUE y, D3DVALUE z)
793 {
794     struct d3drm_mesh_builder *mesh_builder = impl_from_IDirect3DRMMeshBuilder2(iface);
795 
796     TRACE("iface %p, x %.8e, y %.8e, z %.8e.\n", iface, x, y, z);
797 
798     return IDirect3DRMMeshBuilder3_AddNormal(&mesh_builder->IDirect3DRMMeshBuilder3_iface, x, y, z);
799 }
800 
801 static HRESULT WINAPI d3drm_mesh_builder2_CreateFace(IDirect3DRMMeshBuilder2 *iface, IDirect3DRMFace **face)
802 {
803     struct d3drm_face *object;
804     HRESULT hr;
805 
806     TRACE("iface %p, face %p.\n", iface, face);
807 
808     if (FAILED(hr = d3drm_face_create(&object)))
809         return hr;
810 
811     *face = &object->IDirect3DRMFace_iface;
812 
813     return S_OK;
814 }
815 
816 static D3DRMRENDERQUALITY WINAPI d3drm_mesh_builder2_GetQuality(IDirect3DRMMeshBuilder2 *iface)
817 {
818     FIXME("iface %p stub!\n", iface);
819 
820     return 0;
821 }
822 
823 static BOOL WINAPI d3drm_mesh_builder2_GetPerspective(IDirect3DRMMeshBuilder2 *iface)
824 {
825     FIXME("iface %p stub!\n", iface);
826 
827     return FALSE;
828 }
829 
830 static int WINAPI d3drm_mesh_builder2_GetFaceCount(IDirect3DRMMeshBuilder2 *iface)
831 {
832     struct d3drm_mesh_builder *mesh_builder = impl_from_IDirect3DRMMeshBuilder2(iface);
833 
834     TRACE("iface %p.\n", iface);
835 
836     return mesh_builder->nb_faces;
837 }
838 
839 static int WINAPI d3drm_mesh_builder2_GetVertexCount(IDirect3DRMMeshBuilder2 *iface)
840 {
841     struct d3drm_mesh_builder *mesh_builder = impl_from_IDirect3DRMMeshBuilder2(iface);
842 
843     TRACE("iface %p.\n", iface);
844 
845     return mesh_builder->nb_vertices;
846 }
847 
848 static D3DCOLOR WINAPI d3drm_mesh_builder2_GetVertexColor(IDirect3DRMMeshBuilder2 *iface, DWORD index)
849 {
850     FIXME("iface %p, index %u stub!\n", iface, index);
851 
852     return 0;
853 }
854 
855 static HRESULT WINAPI d3drm_mesh_builder2_CreateMesh(IDirect3DRMMeshBuilder2 *iface, IDirect3DRMMesh **mesh)
856 {
857     struct d3drm_mesh_builder *mesh_builder = impl_from_IDirect3DRMMeshBuilder2(iface);
858 
859     TRACE("iface %p, mesh %p.\n", iface, mesh);
860 
861     return IDirect3DRMMeshBuilder3_CreateMesh(&mesh_builder->IDirect3DRMMeshBuilder3_iface, mesh);
862 }
863 
864 static HRESULT WINAPI d3drm_mesh_builder2_GenerateNormals2(IDirect3DRMMeshBuilder2 *iface,
865         D3DVALUE crease, DWORD flags)
866 {
867     FIXME("iface %p, crease %.8e, flags %#x stub!\n", iface, crease, flags);
868 
869     return E_NOTIMPL;
870 }
871 
872 static HRESULT WINAPI d3drm_mesh_builder2_GetFace(IDirect3DRMMeshBuilder2 *iface,
873         DWORD index, IDirect3DRMFace **face)
874 {
875     FIXME("iface %p, index %u, face %p stub!\n", iface, index, face);
876 
877     return E_NOTIMPL;
878 }
879 
880 static const struct IDirect3DRMMeshBuilder2Vtbl d3drm_mesh_builder2_vtbl =
881 {
882     d3drm_mesh_builder2_QueryInterface,
883     d3drm_mesh_builder2_AddRef,
884     d3drm_mesh_builder2_Release,
885     d3drm_mesh_builder2_Clone,
886     d3drm_mesh_builder2_AddDestroyCallback,
887     d3drm_mesh_builder2_DeleteDestroyCallback,
888     d3drm_mesh_builder2_SetAppData,
889     d3drm_mesh_builder2_GetAppData,
890     d3drm_mesh_builder2_SetName,
891     d3drm_mesh_builder2_GetName,
892     d3drm_mesh_builder2_GetClassName,
893     d3drm_mesh_builder2_Load,
894     d3drm_mesh_builder2_Save,
895     d3drm_mesh_builder2_Scale,
896     d3drm_mesh_builder2_Translate,
897     d3drm_mesh_builder2_SetColorSource,
898     d3drm_mesh_builder2_GetBox,
899     d3drm_mesh_builder2_GenerateNormals,
900     d3drm_mesh_builder2_GetColorSource,
901     d3drm_mesh_builder2_AddMesh,
902     d3drm_mesh_builder2_AddMeshBuilder,
903     d3drm_mesh_builder2_AddFrame,
904     d3drm_mesh_builder2_AddFace,
905     d3drm_mesh_builder2_AddFaces,
906     d3drm_mesh_builder2_ReserveSpace,
907     d3drm_mesh_builder2_SetColorRGB,
908     d3drm_mesh_builder2_SetColor,
909     d3drm_mesh_builder2_SetTexture,
910     d3drm_mesh_builder2_SetMaterial,
911     d3drm_mesh_builder2_SetTextureTopology,
912     d3drm_mesh_builder2_SetQuality,
913     d3drm_mesh_builder2_SetPerspective,
914     d3drm_mesh_builder2_SetVertex,
915     d3drm_mesh_builder2_SetNormal,
916     d3drm_mesh_builder2_SetTextureCoordinates,
917     d3drm_mesh_builder2_SetVertexColor,
918     d3drm_mesh_builder2_SetVertexColorRGB,
919     d3drm_mesh_builder2_GetFaces,
920     d3drm_mesh_builder2_GetVertices,
921     d3drm_mesh_builder2_GetTextureCoordinates,
922     d3drm_mesh_builder2_AddVertex,
923     d3drm_mesh_builder2_AddNormal,
924     d3drm_mesh_builder2_CreateFace,
925     d3drm_mesh_builder2_GetQuality,
926     d3drm_mesh_builder2_GetPerspective,
927     d3drm_mesh_builder2_GetFaceCount,
928     d3drm_mesh_builder2_GetVertexCount,
929     d3drm_mesh_builder2_GetVertexColor,
930     d3drm_mesh_builder2_CreateMesh,
931     d3drm_mesh_builder2_GenerateNormals2,
932     d3drm_mesh_builder2_GetFace,
933 };
934 
935 static HRESULT WINAPI d3drm_mesh_builder3_QueryInterface(IDirect3DRMMeshBuilder3 *iface, REFIID riid, void **out)
936 {
937     struct d3drm_mesh_builder *mesh_builder = impl_from_IDirect3DRMMeshBuilder3(iface);
938 
939     TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
940 
941     return d3drm_mesh_builder2_QueryInterface(&mesh_builder->IDirect3DRMMeshBuilder2_iface, riid, out);
942 }
943 
944 static ULONG WINAPI d3drm_mesh_builder3_AddRef(IDirect3DRMMeshBuilder3 *iface)
945 {
946     struct d3drm_mesh_builder *mesh_builder = impl_from_IDirect3DRMMeshBuilder3(iface);
947 
948     TRACE("iface %p.\n", iface);
949 
950     return d3drm_mesh_builder2_AddRef(&mesh_builder->IDirect3DRMMeshBuilder2_iface);
951 }
952 
953 static ULONG WINAPI d3drm_mesh_builder3_Release(IDirect3DRMMeshBuilder3 *iface)
954 {
955     struct d3drm_mesh_builder *mesh_builder = impl_from_IDirect3DRMMeshBuilder3(iface);
956 
957     TRACE("iface %p.\n", iface);
958 
959     return d3drm_mesh_builder2_Release(&mesh_builder->IDirect3DRMMeshBuilder2_iface);
960 }
961 
962 static HRESULT WINAPI d3drm_mesh_builder3_Clone(IDirect3DRMMeshBuilder3 *iface,
963         IUnknown *outer, REFIID iid, void **out)
964 {
965     FIXME("iface %p, outer %p, iid %s, out %p stub!\n", iface, outer, debugstr_guid(iid), out);
966 
967     return E_NOTIMPL;
968 }
969 
970 static HRESULT WINAPI d3drm_mesh_builder3_AddDestroyCallback(IDirect3DRMMeshBuilder3 *iface,
971         D3DRMOBJECTCALLBACK cb, void *ctx)
972 {
973     struct d3drm_mesh_builder *mesh_builder = impl_from_IDirect3DRMMeshBuilder3(iface);
974 
975     TRACE("iface %p, cb %p, ctx %p.\n", iface, cb, ctx);
976 
977     return d3drm_object_add_destroy_callback(&mesh_builder->obj, cb, ctx);
978 }
979 
980 static HRESULT WINAPI d3drm_mesh_builder3_DeleteDestroyCallback(IDirect3DRMMeshBuilder3 *iface,
981         D3DRMOBJECTCALLBACK cb, void *ctx)
982 {
983     struct d3drm_mesh_builder *mesh_builder = impl_from_IDirect3DRMMeshBuilder3(iface);
984 
985     TRACE("iface %p, cb %p, ctx %p.\n", iface, cb, ctx);
986 
987     return d3drm_object_delete_destroy_callback(&mesh_builder->obj, cb, ctx);
988 }
989 
990 static HRESULT WINAPI d3drm_mesh_builder3_SetName(IDirect3DRMMeshBuilder3 *iface, const char *name)
991 {
992     struct d3drm_mesh_builder *mesh_builder = impl_from_IDirect3DRMMeshBuilder3(iface);
993 
994     TRACE("iface %p, name %s.\n", iface, debugstr_a(name));
995 
996     return d3drm_object_set_name(&mesh_builder->obj, name);
997 }
998 
999 static HRESULT WINAPI d3drm_mesh_builder3_GetName(IDirect3DRMMeshBuilder3 *iface,
1000         DWORD *size, char *name)
1001 {
1002     struct d3drm_mesh_builder *mesh_builder = impl_from_IDirect3DRMMeshBuilder3(iface);
1003 
1004     TRACE("iface %p, size %p, name %p.\n", iface, size, name);
1005 
1006     return d3drm_object_get_name(&mesh_builder->obj, size, name);
1007 }
1008 
1009 static HRESULT WINAPI d3drm_mesh_builder3_GetClassName(IDirect3DRMMeshBuilder3 *iface,
1010         DWORD *size, char *name)
1011 {
1012     struct d3drm_mesh_builder *meshbuilder = impl_from_IDirect3DRMMeshBuilder3(iface);
1013 
1014     TRACE("iface %p, size %p, name %p.\n", iface, size, name);
1015 
1016     return d3drm_object_get_class_name(&meshbuilder->obj, size, name);
1017 }
1018 
1019 HRESULT load_mesh_data(IDirect3DRMMeshBuilder3 *iface, IDirectXFileData *pData,
1020         D3DRMLOADTEXTURECALLBACK load_texture_proc, void *arg)
1021 {
1022     struct d3drm_mesh_builder *mesh_builder = impl_from_IDirect3DRMMeshBuilder3(iface);
1023     IDirectXFileData *pData2 = NULL;
1024     const GUID* guid;
1025     DWORD size;
1026     BYTE *ptr;
1027     HRESULT hr;
1028     HRESULT ret = D3DRMERR_BADOBJECT;
1029     DWORD* faces_vertex_idx_data = NULL;
1030     DWORD* faces_vertex_idx_ptr;
1031     DWORD faces_vertex_idx_size;
1032     DWORD* faces_normal_idx_data = NULL;
1033     DWORD* faces_normal_idx_ptr = NULL;
1034     DWORD* faces_data_ptr;
1035     DWORD faces_data_size = 0;
1036     DWORD i;
1037 
1038     TRACE("(%p)->(%p)\n", mesh_builder, pData);
1039 
1040     hr = IDirectXFileData_GetName(pData, NULL, &size);
1041     if (hr != DXFILE_OK)
1042         return hr;
1043     if (size)
1044     {
1045         char *name;
1046 
1047         if (!(name = heap_alloc(size)))
1048             return E_OUTOFMEMORY;
1049 
1050         if (SUCCEEDED(hr = IDirectXFileData_GetName(pData, name, &size)))
1051             IDirect3DRMMeshBuilder3_SetName(iface, name);
1052         heap_free(name);
1053         if (hr != DXFILE_OK)
1054             return hr;
1055     }
1056 
1057     TRACE("Mesh name is %s\n", debugstr_a(mesh_builder->obj.name));
1058 
1059     mesh_builder->nb_normals = 0;
1060 
1061     hr = IDirectXFileData_GetData(pData, NULL, &size, (void**)&ptr);
1062     if (hr != DXFILE_OK)
1063         goto end;
1064 
1065     mesh_builder->nb_vertices = *(DWORD*)ptr;
1066     mesh_builder->nb_faces = *(DWORD*)(ptr + sizeof(DWORD) + mesh_builder->nb_vertices * sizeof(D3DVECTOR));
1067     faces_vertex_idx_size = size - sizeof(DWORD) - mesh_builder->nb_vertices * sizeof(D3DVECTOR) - sizeof(DWORD);
1068 
1069     TRACE("Mesh: nb_vertices = %lu, nb_faces = %d, faces_vertex_idx_size = %d\n", mesh_builder->nb_vertices,
1070             mesh_builder->nb_faces, faces_vertex_idx_size);
1071 
1072     if (!d3drm_array_reserve((void **)&mesh_builder->vertices, &mesh_builder->vertices_size, mesh_builder->nb_vertices,
1073            sizeof(*mesh_builder->vertices)))
1074     {
1075         hr = E_OUTOFMEMORY;
1076         goto end;
1077     }
1078     memcpy(mesh_builder->vertices, ptr + sizeof(DWORD), mesh_builder->nb_vertices * sizeof(D3DVECTOR));
1079 
1080     faces_vertex_idx_ptr = faces_vertex_idx_data = heap_alloc(faces_vertex_idx_size);
1081     memcpy(faces_vertex_idx_data, ptr + sizeof(DWORD) + mesh_builder->nb_vertices * sizeof(D3DVECTOR) + sizeof(DWORD),
1082             faces_vertex_idx_size);
1083 
1084     /* Each vertex index will have its normal index counterpart so just allocate twice the size */
1085     mesh_builder->pFaceData = heap_alloc(faces_vertex_idx_size * 2);
1086     faces_data_ptr = (DWORD*)mesh_builder->pFaceData;
1087 
1088     while (1)
1089     {
1090         IDirectXFileObject *object;
1091 
1092         hr =  IDirectXFileData_GetNextObject(pData, &object);
1093         if (hr == DXFILEERR_NOMOREOBJECTS)
1094         {
1095             TRACE("No more object\n");
1096             break;
1097         }
1098         if (hr != DXFILE_OK)
1099            goto end;
1100 
1101         hr = IDirectXFileObject_QueryInterface(object, &IID_IDirectXFileData, (void**)&pData2);
1102         IDirectXFileObject_Release(object);
1103         if (hr != DXFILE_OK)
1104             goto end;
1105 
1106         hr = IDirectXFileData_GetType(pData2, &guid);
1107         if (hr != DXFILE_OK)
1108             goto end;
1109 
1110         TRACE("Found object type whose GUID = %s\n", debugstr_guid(guid));
1111 
1112         if (IsEqualGUID(guid, &TID_D3DRMMeshNormals))
1113         {
1114             DWORD nb_faces_normals;
1115             DWORD faces_normal_idx_size;
1116 
1117             hr = IDirectXFileData_GetData(pData2, NULL, &size, (void**)&ptr);
1118             if (hr != DXFILE_OK)
1119                 goto end;
1120 
1121             mesh_builder->nb_normals = *(DWORD*)ptr;
1122             nb_faces_normals = *(DWORD*)(ptr + sizeof(DWORD) + mesh_builder->nb_normals * sizeof(D3DVECTOR));
1123 
1124             TRACE("MeshNormals: nb_normals = %lu, nb_faces_normals = %d\n", mesh_builder->nb_normals, nb_faces_normals);
1125             if (nb_faces_normals != mesh_builder->nb_faces)
1126                 WARN("nb_face_normals (%d) != nb_faces (%d)\n", nb_faces_normals, mesh_builder->nb_faces);
1127 
1128             if (!d3drm_array_reserve((void **)&mesh_builder->normals, &mesh_builder->normals_size,
1129                     mesh_builder->nb_normals, sizeof(*mesh_builder->normals)))
1130             {
1131                 hr = E_OUTOFMEMORY;
1132                 goto end;
1133             }
1134             memcpy(mesh_builder->normals, ptr + sizeof(DWORD), mesh_builder->nb_normals * sizeof(D3DVECTOR));
1135 
1136             faces_normal_idx_size = size - (2 * sizeof(DWORD) + mesh_builder->nb_normals * sizeof(D3DVECTOR));
1137             faces_normal_idx_ptr = faces_normal_idx_data = heap_alloc(faces_normal_idx_size);
1138             memcpy(faces_normal_idx_data, ptr + sizeof(DWORD) + mesh_builder->nb_normals * sizeof(D3DVECTOR)
1139                     + sizeof(DWORD), faces_normal_idx_size);
1140         }
1141         else if (IsEqualGUID(guid, &TID_D3DRMMeshTextureCoords))
1142         {
1143             hr = IDirectXFileData_GetData(pData2, NULL, &size, (void**)&ptr);
1144             if (hr != DXFILE_OK)
1145                 goto end;
1146 
1147             mesh_builder->nb_coords2d = *(DWORD*)ptr;
1148 
1149             TRACE("MeshTextureCoords: nb_coords2d = %d\n", mesh_builder->nb_coords2d);
1150 
1151             mesh_builder->pCoords2d = heap_calloc(mesh_builder->nb_coords2d, sizeof(*mesh_builder->pCoords2d));
1152             memcpy(mesh_builder->pCoords2d, ptr + sizeof(DWORD), mesh_builder->nb_coords2d * sizeof(*mesh_builder->pCoords2d));
1153         }
1154         else if (IsEqualGUID(guid, &TID_D3DRMMeshMaterialList))
1155         {
1156             DWORD nb_materials;
1157             DWORD nb_face_indices;
1158             DWORD data_size;
1159             IDirectXFileObject *child;
1160             DWORD i = 0;
1161             float* values;
1162             struct d3drm_texture *texture_object;
1163 
1164             TRACE("Process MeshMaterialList\n");
1165 
1166             hr = IDirectXFileData_GetData(pData2, NULL, &size, (void**)&ptr);
1167             if (hr != DXFILE_OK)
1168                 goto end;
1169 
1170             nb_materials = *(DWORD*)ptr;
1171             nb_face_indices = *(DWORD*)(ptr + sizeof(DWORD));
1172             data_size = 2 * sizeof(DWORD) + nb_face_indices * sizeof(DWORD);
1173 
1174             TRACE("nMaterials = %u, nFaceIndexes = %u\n", nb_materials, nb_face_indices);
1175 
1176             if (size != data_size)
1177                 WARN("Returned size %u does not match expected one %u\n", size, data_size);
1178 
1179             if (!(mesh_builder->material_indices = heap_calloc(nb_face_indices,
1180                     sizeof(*mesh_builder->material_indices))))
1181                 goto end;
1182             memcpy(mesh_builder->material_indices, ptr + 2 * sizeof(DWORD),
1183                     nb_face_indices * sizeof(*mesh_builder->material_indices));
1184 
1185             if (!(mesh_builder->materials = heap_calloc(nb_materials, sizeof(*mesh_builder->materials))))
1186             {
1187                 heap_free(mesh_builder->material_indices);
1188                 goto end;
1189             }
1190             mesh_builder->nb_materials = nb_materials;
1191 
1192             while (SUCCEEDED(hr = IDirectXFileData_GetNextObject(pData2, &child)) && (i < nb_materials))
1193             {
1194                 IDirectXFileData *data;
1195                 IDirectXFileDataReference *reference;
1196                 IDirectXFileObject *material_child;
1197                 struct d3drm_material *object;
1198 
1199                 hr = IDirectXFileObject_QueryInterface(child, &IID_IDirectXFileData, (void **)&data);
1200                 if (FAILED(hr))
1201                 {
1202                     hr = IDirectXFileObject_QueryInterface(child, &IID_IDirectXFileDataReference, (void **)&reference);
1203                     IDirectXFileObject_Release(child);
1204                     if (FAILED(hr))
1205                         goto end;
1206 
1207                     hr = IDirectXFileDataReference_Resolve(reference, &data);
1208                     IDirectXFileDataReference_Release(reference);
1209                     if (FAILED(hr))
1210                         goto end;
1211                 }
1212                 else
1213                 {
1214                     IDirectXFileObject_Release(child);
1215                 }
1216 
1217                 hr = d3drm_material_create(&object, mesh_builder->d3drm);
1218                 if (FAILED(hr))
1219                 {
1220                     IDirectXFileData_Release(data);
1221                     goto end;
1222                 }
1223                 mesh_builder->materials[i].material = &object->IDirect3DRMMaterial2_iface;
1224 
1225                 hr = IDirectXFileData_GetData(data, NULL, &size, (void**)&ptr);
1226                 if (hr != DXFILE_OK)
1227                 {
1228                     IDirectXFileData_Release(data);
1229                     goto end;
1230                 }
1231 
1232                 if (size != 44)
1233                     WARN("Material size %u does not match expected one %u\n", size, 44);
1234 
1235                 values = (float*)ptr;
1236 
1237                 d3drm_set_color(&mesh_builder->materials[i].color, values[0], values[1], values[2], values[3]);
1238 
1239                 IDirect3DRMMaterial2_SetAmbient(mesh_builder->materials[i].material, values[0], values [1], values[2]); /* Alpha ignored */
1240                 IDirect3DRMMaterial2_SetPower(mesh_builder->materials[i].material, values[4]);
1241                 IDirect3DRMMaterial2_SetSpecular(mesh_builder->materials[i].material, values[5], values[6], values[7]);
1242                 IDirect3DRMMaterial2_SetEmissive(mesh_builder->materials[i].material, values[8], values[9], values[10]);
1243 
1244                 mesh_builder->materials[i].texture = NULL;
1245 
1246                 hr = IDirectXFileData_GetNextObject(data, &material_child);
1247                 if (hr == S_OK)
1248                 {
1249                     IDirectXFileData *data;
1250                     char **filename;
1251 
1252                     if (FAILED(hr = IDirectXFileObject_QueryInterface(material_child,
1253                             &IID_IDirectXFileData, (void **)&data)))
1254                     {
1255                         IDirectXFileDataReference *reference;
1256 
1257                         if (SUCCEEDED(IDirectXFileObject_QueryInterface(material_child,
1258                                 &IID_IDirectXFileDataReference, (void **)&reference)))
1259                         {
1260                             hr = IDirectXFileDataReference_Resolve(reference, &data);
1261                             IDirectXFileDataReference_Release(reference);
1262                         }
1263                     }
1264                     IDirectXFileObject_Release(material_child);
1265                     if (FAILED(hr))
1266                         goto end;
1267 
1268                     hr = IDirectXFileData_GetType(data, &guid);
1269                     if (hr != DXFILE_OK)
1270                         goto end;
1271                     if (!IsEqualGUID(guid, &TID_D3DRMTextureFilename))
1272                     {
1273                          WARN("Not a texture filename\n");
1274                          goto end;
1275                     }
1276 
1277                     size = 4;
1278                     hr = IDirectXFileData_GetData(data, NULL, &size, (void**)&filename);
1279                     if (SUCCEEDED(hr))
1280                     {
1281                         if (load_texture_proc)
1282                         {
1283                             IDirect3DRMTexture *texture;
1284 
1285                             hr = load_texture_proc(*filename, arg, &texture);
1286                             if (SUCCEEDED(hr))
1287                             {
1288                                 hr = IDirect3DTexture_QueryInterface(texture, &IID_IDirect3DRMTexture3,
1289                                         (void **)&mesh_builder->materials[i].texture);
1290                                 IDirect3DTexture_Release(texture);
1291                             }
1292                         }
1293                         else
1294                         {
1295                             HANDLE file;
1296 
1297                             /* If the texture file is not found, no texture is associated with the material */
1298                             file = CreateFileA(*filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
1299                             if (file != INVALID_HANDLE_VALUE)
1300                             {
1301                                 CloseHandle(file);
1302                                 if (FAILED(hr = d3drm_texture_create(&texture_object, NULL)))
1303                                 {
1304                                     IDirectXFileData_Release(data);
1305                                     goto end;
1306                                 }
1307                                 mesh_builder->materials[i].texture = &texture_object->IDirect3DRMTexture3_iface;
1308                             }
1309                         }
1310                     }
1311                     IDirectXFileData_Release(data);
1312                 }
1313                 else if (hr != DXFILEERR_NOMOREOBJECTS)
1314                 {
1315                     goto end;
1316                 }
1317                 hr = S_OK;
1318 
1319                 IDirectXFileData_Release(data);
1320                 i++;
1321             }
1322             if (hr == S_OK)
1323             {
1324                 IDirectXFileObject_Release(child);
1325                 WARN("Found more sub-objects than expected\n");
1326             }
1327             else if (hr != DXFILEERR_NOMOREOBJECTS)
1328             {
1329                 goto end;
1330             }
1331             hr = S_OK;
1332         }
1333         else
1334         {
1335             FIXME("Unknown GUID %s, ignoring...\n", debugstr_guid(guid));
1336         }
1337 
1338         IDirectXFileData_Release(pData2);
1339         pData2 = NULL;
1340     }
1341 
1342     if (!mesh_builder->nb_normals)
1343     {
1344         /* Allocate normals, one per vertex */
1345         if (!d3drm_array_reserve((void **)&mesh_builder->normals, &mesh_builder->normals_size,
1346                 mesh_builder->nb_vertices, sizeof(*mesh_builder->normals)))
1347             goto end;
1348         memset(mesh_builder->normals, 0, mesh_builder->nb_vertices * sizeof(*mesh_builder->normals));
1349     }
1350 
1351     for (i = 0; i < mesh_builder->nb_faces; i++)
1352     {
1353         DWORD j;
1354         DWORD nb_face_indexes;
1355         D3DVECTOR face_normal;
1356 
1357         if (faces_vertex_idx_size < sizeof(DWORD))
1358             WARN("Not enough data to read number of indices of face %d\n", i);
1359 
1360         nb_face_indexes  = *(faces_data_ptr + faces_data_size++) = *(faces_vertex_idx_ptr++);
1361         faces_vertex_idx_size--;
1362         if (faces_normal_idx_data && (*(faces_normal_idx_ptr++) != nb_face_indexes))
1363             WARN("Faces indices number mismatch\n");
1364 
1365         if (faces_vertex_idx_size < (nb_face_indexes * sizeof(DWORD)))
1366             WARN("Not enough data to read all indices of face %d\n", i);
1367 
1368         if (!mesh_builder->nb_normals)
1369         {
1370             /* Compute face normal */
1371             if (nb_face_indexes > 2
1372                     && faces_vertex_idx_ptr[0] < mesh_builder->nb_vertices
1373                     && faces_vertex_idx_ptr[1] < mesh_builder->nb_vertices
1374                     && faces_vertex_idx_ptr[2] < mesh_builder->nb_vertices)
1375             {
1376                 D3DVECTOR a, b;
1377 
1378                 D3DRMVectorSubtract(&a, &mesh_builder->vertices[faces_vertex_idx_ptr[2]], &mesh_builder->vertices[faces_vertex_idx_ptr[1]]);
1379                 D3DRMVectorSubtract(&b, &mesh_builder->vertices[faces_vertex_idx_ptr[0]], &mesh_builder->vertices[faces_vertex_idx_ptr[1]]);
1380                 D3DRMVectorCrossProduct(&face_normal, &a, &b);
1381                 D3DRMVectorNormalize(&face_normal);
1382             }
1383             else
1384             {
1385                 face_normal.u1.x = 0.0f;
1386                 face_normal.u2.y = 0.0f;
1387                 face_normal.u3.z = 0.0f;
1388             }
1389         }
1390 
1391         for (j = 0; j < nb_face_indexes; j++)
1392         {
1393             /* Copy vertex index */
1394             *(faces_data_ptr + faces_data_size++) = *faces_vertex_idx_ptr;
1395             /* Copy normal index */
1396             if (mesh_builder->nb_normals)
1397             {
1398                 /* Read from x file */
1399                 *(faces_data_ptr + faces_data_size++) = *(faces_normal_idx_ptr++);
1400             }
1401             else
1402             {
1403                 DWORD vertex_idx = *faces_vertex_idx_ptr;
1404                 if (vertex_idx >= mesh_builder->nb_vertices)
1405                 {
1406                     WARN("Found vertex index %u but only %lu vertices available => use index 0\n", vertex_idx,
1407                             mesh_builder->nb_vertices);
1408                     vertex_idx = 0;
1409                 }
1410                 *(faces_data_ptr + faces_data_size++) = vertex_idx;
1411                 /* Add face normal to vertex normal */
1412                 D3DRMVectorAdd(&mesh_builder->normals[vertex_idx], &mesh_builder->normals[vertex_idx], &face_normal);
1413             }
1414             faces_vertex_idx_ptr++;
1415         }
1416         faces_vertex_idx_size -= nb_face_indexes;
1417     }
1418 
1419     /* Last DWORD must be 0 */
1420     *(faces_data_ptr + faces_data_size++) = 0;
1421 
1422     /* Set size (in number of DWORD) of all faces data */
1423     mesh_builder->face_data_size = faces_data_size;
1424 
1425     if (!mesh_builder->nb_normals)
1426     {
1427         /* Normalize all normals */
1428         for (i = 0; i < mesh_builder->nb_vertices; i++)
1429         {
1430             D3DRMVectorNormalize(&mesh_builder->normals[i]);
1431         }
1432         mesh_builder->nb_normals = mesh_builder->nb_vertices;
1433     }
1434 
1435     /* If there is no texture coordinates, generate default texture coordinates (0.0f, 0.0f) for each vertex */
1436     if (!mesh_builder->pCoords2d)
1437     {
1438         mesh_builder->nb_coords2d = mesh_builder->nb_vertices;
1439         mesh_builder->pCoords2d = heap_calloc(mesh_builder->nb_coords2d, sizeof(*mesh_builder->pCoords2d));
1440         for (i = 0; i < mesh_builder->nb_coords2d; ++i)
1441         {
1442             mesh_builder->pCoords2d[i].u = 0.0f;
1443             mesh_builder->pCoords2d[i].v = 0.0f;
1444         }
1445     }
1446 
1447     TRACE("Mesh data loaded successfully\n");
1448 
1449     ret = D3DRM_OK;
1450 
1451 end:
1452 
1453     heap_free(faces_normal_idx_data);
1454     heap_free(faces_vertex_idx_data);
1455 
1456     return ret;
1457 }
1458 
1459 static HRESULT WINAPI d3drm_mesh_builder3_Load(IDirect3DRMMeshBuilder3 *iface, void *filename,
1460         void *name, D3DRMLOADOPTIONS loadflags, D3DRMLOADTEXTURE3CALLBACK cb, void *arg)
1461 {
1462     struct d3drm_mesh_builder *mesh_builder = impl_from_IDirect3DRMMeshBuilder3(iface);
1463     DXFILELOADOPTIONS load_options;
1464     IDirectXFile *dxfile = NULL;
1465     IDirectXFileEnumObject *enum_object = NULL;
1466     IDirectXFileData *data = NULL;
1467     const GUID* guid;
1468     DWORD size;
1469     struct d3drm_file_header *header;
1470     HRESULT hr;
1471     HRESULT ret = D3DRMERR_BADOBJECT;
1472 
1473     TRACE("iface %p, filename %p, name %p, loadflags %#x, cb %p, arg %p.\n",
1474             iface, filename, name, loadflags, cb, arg);
1475 
1476     clean_mesh_builder_data(mesh_builder);
1477 
1478     if (loadflags == D3DRMLOAD_FROMMEMORY)
1479     {
1480         load_options = DXFILELOAD_FROMMEMORY;
1481     }
1482     else if (loadflags == D3DRMLOAD_FROMFILE)
1483     {
1484         load_options = DXFILELOAD_FROMFILE;
1485         TRACE("Loading from file %s\n", debugstr_a(filename));
1486     }
1487     else
1488     {
1489         FIXME("Load options %d not supported yet\n", loadflags);
1490         return E_NOTIMPL;
1491     }
1492 
1493     hr = DirectXFileCreate(&dxfile);
1494     if (hr != DXFILE_OK)
1495         goto end;
1496 
1497     hr = IDirectXFile_RegisterTemplates(dxfile, templates, strlen(templates));
1498     if (hr != DXFILE_OK)
1499         goto end;
1500 
1501     hr = IDirectXFile_CreateEnumObject(dxfile, filename, load_options, &enum_object);
1502     if (hr != DXFILE_OK)
1503         goto end;
1504 
1505     hr = IDirectXFileEnumObject_GetNextDataObject(enum_object, &data);
1506     if (hr != DXFILE_OK)
1507         goto end;
1508 
1509     hr = IDirectXFileData_GetType(data, &guid);
1510     if (hr != DXFILE_OK)
1511         goto end;
1512 
1513     TRACE("Found object type whose GUID = %s\n", debugstr_guid(guid));
1514 
1515     if (!IsEqualGUID(guid, &TID_DXFILEHeader))
1516     {
1517         ret = D3DRMERR_BADFILE;
1518         goto end;
1519     }
1520 
1521     hr = IDirectXFileData_GetData(data, NULL, &size, (void**)&header);
1522     if ((hr != DXFILE_OK) || (size != sizeof(*header)))
1523         goto end;
1524 
1525     TRACE("Version is %u.%u, flags %#x.\n", header->major, header->minor, header->flags);
1526 
1527     /* Version must be 1.0.x */
1528     if ((header->major != 1) || (header->minor != 0))
1529     {
1530         ret = D3DRMERR_BADFILE;
1531         goto end;
1532     }
1533 
1534     IDirectXFileData_Release(data);
1535     data = NULL;
1536 
1537     hr = IDirectXFileEnumObject_GetNextDataObject(enum_object, &data);
1538     if (hr != DXFILE_OK)
1539     {
1540         ret = D3DRMERR_NOTFOUND;
1541         goto end;
1542     }
1543 
1544     hr = IDirectXFileData_GetType(data, &guid);
1545     if (hr != DXFILE_OK)
1546         goto end;
1547 
1548     TRACE("Found object type whose GUID = %s\n", debugstr_guid(guid));
1549 
1550     if (!IsEqualGUID(guid, &TID_D3DRMMesh))
1551     {
1552         ret = D3DRMERR_NOTFOUND;
1553         goto end;
1554     }
1555 
1556     /* We don't care about the texture interface version since we rely on QueryInterface */
1557     hr = load_mesh_data(iface, data, (D3DRMLOADTEXTURECALLBACK)cb, arg);
1558     if (hr == S_OK)
1559         ret = D3DRM_OK;
1560 
1561 end:
1562 
1563     if (data)
1564         IDirectXFileData_Release(data);
1565     if (enum_object)
1566         IDirectXFileEnumObject_Release(enum_object);
1567     if (dxfile)
1568         IDirectXFile_Release(dxfile);
1569 
1570     if (ret != D3DRM_OK)
1571         clean_mesh_builder_data(mesh_builder);
1572 
1573     return ret;
1574 }
1575 
1576 static HRESULT WINAPI d3drm_mesh_builder3_Save(IDirect3DRMMeshBuilder3 *iface,
1577         const char *filename, D3DRMXOFFORMAT format, D3DRMSAVEOPTIONS flags)
1578 {
1579     FIXME("iface %p, filename %s, format %#x, flags %#x stub!\n",
1580             iface, debugstr_a(filename), format, flags);
1581 
1582     return E_NOTIMPL;
1583 }
1584 
1585 static HRESULT WINAPI d3drm_mesh_builder3_Scale(IDirect3DRMMeshBuilder3 *iface,
1586         D3DVALUE sx, D3DVALUE sy, D3DVALUE sz)
1587 {
1588     struct d3drm_mesh_builder *mesh_builder = impl_from_IDirect3DRMMeshBuilder3(iface);
1589     DWORD i;
1590 
1591     TRACE("iface %p, sx %.8e, sy %.8e, sz %.8e.\n", iface, sx, sy, sz);
1592 
1593     for (i = 0; i < mesh_builder->nb_vertices; ++i)
1594     {
1595         mesh_builder->vertices[i].u1.x *= sx;
1596         mesh_builder->vertices[i].u2.y *= sy;
1597         mesh_builder->vertices[i].u3.z *= sz;
1598     }
1599 
1600     /* Normals are not affected by Scale */
1601 
1602     return D3DRM_OK;
1603 }
1604 
1605 static HRESULT WINAPI d3drm_mesh_builder3_Translate(IDirect3DRMMeshBuilder3 *iface,
1606         D3DVALUE tx, D3DVALUE ty, D3DVALUE tz)
1607 {
1608     FIXME("iface %p, tx %.8e, ty %.8e, tz %.8e stub!\n", iface, tx, ty, tz);
1609 
1610     return E_NOTIMPL;
1611 }
1612 
1613 static HRESULT WINAPI d3drm_mesh_builder3_SetColorSource(IDirect3DRMMeshBuilder3 *iface,
1614         D3DRMCOLORSOURCE source)
1615 {
1616     FIXME("iface %p, source %#x stub!\n", iface, source);
1617 
1618     return E_NOTIMPL;
1619 }
1620 
1621 static HRESULT WINAPI d3drm_mesh_builder3_GetBox(IDirect3DRMMeshBuilder3 *iface, D3DRMBOX *box)
1622 {
1623     FIXME("iface %p, box %p stub!\n", iface, box);
1624 
1625     return E_NOTIMPL;
1626 }
1627 
1628 static HRESULT WINAPI d3drm_mesh_builder3_GenerateNormals(IDirect3DRMMeshBuilder3 *iface,
1629         D3DVALUE crease, DWORD flags)
1630 {
1631     FIXME("iface %p, crease %.8e, flags %#x stub!\n", iface, crease, flags);
1632 
1633     return E_NOTIMPL;
1634 }
1635 
1636 static D3DRMCOLORSOURCE WINAPI d3drm_mesh_builder3_GetColorSource(IDirect3DRMMeshBuilder3 *iface)
1637 {
1638     FIXME("iface %p stub!\n", iface);
1639 
1640     return E_NOTIMPL;
1641 }
1642 
1643 static HRESULT WINAPI d3drm_mesh_builder3_AddMesh(IDirect3DRMMeshBuilder3 *iface, IDirect3DRMMesh *mesh)
1644 {
1645     FIXME("iface %p, mesh %p stub!\n", iface, mesh);
1646 
1647     return E_NOTIMPL;
1648 }
1649 
1650 static HRESULT WINAPI d3drm_mesh_builder3_AddMeshBuilder(IDirect3DRMMeshBuilder3 *iface,
1651         IDirect3DRMMeshBuilder3 *mesh_builder, DWORD flags)
1652 {
1653     FIXME("iface %p, mesh_builder %p, flags %#x stub!\n", iface, mesh_builder, flags);
1654 
1655     return E_NOTIMPL;
1656 }
1657 
1658 static HRESULT WINAPI d3drm_mesh_builder3_AddFrame(IDirect3DRMMeshBuilder3 *iface, IDirect3DRMFrame3 *frame)
1659 {
1660     FIXME("iface %p, frame %p stub!\n", iface, frame);
1661 
1662     return E_NOTIMPL;
1663 }
1664 
1665 static HRESULT WINAPI d3drm_mesh_builder3_AddFace(IDirect3DRMMeshBuilder3 *iface, IDirect3DRMFace2 *face)
1666 {
1667     FIXME("iface %p, face %p stub!\n", iface, face);
1668 
1669     return E_NOTIMPL;
1670 }
1671 
1672 static HRESULT WINAPI d3drm_mesh_builder3_AddFaces(IDirect3DRMMeshBuilder3 *iface,
1673         DWORD vertex_count, D3DVECTOR *vertices, DWORD normal_count, D3DVECTOR *normals,
1674         DWORD *face_data, IDirect3DRMFaceArray **array)
1675 {
1676     FIXME("iface %p, vertex_count %u, vertices %p, normal_count %u, normals %p, face_data %p array %p stub!\n",
1677             iface, vertex_count, vertices, normal_count, normals, face_data, array);
1678 
1679     return E_NOTIMPL;
1680 }
1681 
1682 static HRESULT WINAPI d3drm_mesh_builder3_ReserveSpace(IDirect3DRMMeshBuilder3 *iface,
1683         DWORD vertex_count, DWORD normal_count, DWORD face_count)
1684 {
1685     FIXME("iface %p, vertex_count %u, normal_count %u, face_count %u stub!\n",
1686             iface, vertex_count, normal_count, face_count);
1687 
1688     return E_NOTIMPL;
1689 }
1690 
1691 static HRESULT WINAPI d3drm_mesh_builder3_SetColorRGB(IDirect3DRMMeshBuilder3 *iface,
1692         D3DVALUE red, D3DVALUE green, D3DVALUE blue)
1693 {
1694     struct d3drm_mesh_builder *mesh_builder = impl_from_IDirect3DRMMeshBuilder3(iface);
1695 
1696     TRACE("iface %p, red %.8e, green %.8e, blue %.8e.\n", iface, red, green, blue);
1697 
1698     d3drm_set_color(&mesh_builder->color, red, green, blue, 1.0f);
1699 
1700     return D3DRM_OK;
1701 }
1702 
1703 static HRESULT WINAPI d3drm_mesh_builder3_SetColor(IDirect3DRMMeshBuilder3 *iface, D3DCOLOR color)
1704 {
1705     struct d3drm_mesh_builder *mesh_builder = impl_from_IDirect3DRMMeshBuilder3(iface);
1706 
1707     TRACE("iface %p, color 0x%08x.\n", iface, color);
1708 
1709     mesh_builder->color = color;
1710 
1711     return D3DRM_OK;
1712 }
1713 
1714 static HRESULT WINAPI d3drm_mesh_builder3_SetTexture(IDirect3DRMMeshBuilder3 *iface,
1715         IDirect3DRMTexture3 *texture)
1716 {
1717     struct d3drm_mesh_builder *mesh_builder = impl_from_IDirect3DRMMeshBuilder3(iface);
1718 
1719     TRACE("iface %p, texture %p.\n", iface, texture);
1720 
1721     if (texture)
1722         IDirect3DRMTexture3_AddRef(texture);
1723     if (mesh_builder->texture)
1724         IDirect3DRMTexture3_Release(mesh_builder->texture);
1725     mesh_builder->texture = texture;
1726 
1727     return D3DRM_OK;
1728 }
1729 
1730 static HRESULT WINAPI d3drm_mesh_builder3_SetMaterial(IDirect3DRMMeshBuilder3 *iface,
1731         IDirect3DRMMaterial2 *material)
1732 {
1733     struct d3drm_mesh_builder *mesh_builder = impl_from_IDirect3DRMMeshBuilder3(iface);
1734 
1735     TRACE("iface %p, material %p.\n", iface, material);
1736 
1737     if (material)
1738         IDirect3DRMTexture2_AddRef(material);
1739     if (mesh_builder->material)
1740         IDirect3DRMTexture2_Release(mesh_builder->material);
1741     mesh_builder->material = material;
1742 
1743     return D3DRM_OK;
1744 }
1745 
1746 static HRESULT WINAPI d3drm_mesh_builder3_SetTextureTopology(IDirect3DRMMeshBuilder3 *iface,
1747         BOOL wrap_u, BOOL wrap_v)
1748 {
1749     FIXME("iface %p, wrap_u %#x, wrap_v %#x stub!\n", iface, wrap_u, wrap_v);
1750 
1751     return E_NOTIMPL;
1752 }
1753 
1754 static HRESULT WINAPI d3drm_mesh_builder3_SetQuality(IDirect3DRMMeshBuilder3 *iface,
1755         D3DRMRENDERQUALITY quality)
1756 {
1757     FIXME("iface %p, quality %#x stub!\n", iface, quality);
1758 
1759     return E_NOTIMPL;
1760 }
1761 
1762 static HRESULT WINAPI d3drm_mesh_builder3_SetPerspective(IDirect3DRMMeshBuilder3 *iface,
1763         BOOL enable)
1764 {
1765     FIXME("iface %p, enable %#x stub!\n", iface, enable);
1766 
1767     return E_NOTIMPL;
1768 }
1769 
1770 static HRESULT WINAPI d3drm_mesh_builder3_SetVertex(IDirect3DRMMeshBuilder3 *iface,
1771         DWORD index, D3DVALUE x, D3DVALUE y, D3DVALUE z)
1772 {
1773     FIXME("iface %p, index %u, x %.8e, y %.8e, z %.8e stub!\n", iface, index, x, y, z);
1774 
1775     return E_NOTIMPL;
1776 }
1777 
1778 static HRESULT WINAPI d3drm_mesh_builder3_SetNormal(IDirect3DRMMeshBuilder3 *iface,
1779         DWORD index, D3DVALUE x, D3DVALUE y, D3DVALUE z)
1780 {
1781     FIXME("iface %p, index %u, x %.8e, y %.8e, z %.8e stub!\n", iface, index, x, y, z);
1782 
1783     return E_NOTIMPL;
1784 }
1785 
1786 static HRESULT WINAPI d3drm_mesh_builder3_SetTextureCoordinates(IDirect3DRMMeshBuilder3 *iface,
1787         DWORD index, D3DVALUE u, D3DVALUE v)
1788 {
1789     struct d3drm_mesh_builder *mesh_builder = impl_from_IDirect3DRMMeshBuilder3(iface);
1790 
1791     TRACE("iface %p, index %u, u %.8e, v %.8e.\n", iface, index, u, v);
1792 
1793     if (index >= mesh_builder->nb_coords2d)
1794         return D3DRMERR_BADVALUE;
1795 
1796     mesh_builder->pCoords2d[index].u = u;
1797     mesh_builder->pCoords2d[index].v = v;
1798 
1799     return D3DRM_OK;
1800 }
1801 
1802 static HRESULT WINAPI d3drm_mesh_builder3_SetVertexColor(IDirect3DRMMeshBuilder3 *iface,
1803         DWORD index, D3DCOLOR color)
1804 {
1805     FIXME("iface %p, index %u, color 0x%08x stub!\n", iface, index, color);
1806 
1807     return E_NOTIMPL;
1808 }
1809 
1810 static HRESULT WINAPI d3drm_mesh_builder3_SetVertexColorRGB(IDirect3DRMMeshBuilder3 *iface,
1811         DWORD index, D3DVALUE red, D3DVALUE green, D3DVALUE blue)
1812 {
1813     FIXME("iface %p, index %u, red %.8e, green %.8e, blue %.8e stub!\n",
1814             iface, index, red, green, blue);
1815 
1816     return E_NOTIMPL;
1817 }
1818 
1819 static HRESULT WINAPI d3drm_mesh_builder3_GetFaces(IDirect3DRMMeshBuilder3 *iface,
1820         IDirect3DRMFaceArray **array)
1821 {
1822     FIXME("iface %p, array %p stub!\n", iface, array);
1823 
1824     return E_NOTIMPL;
1825 }
1826 
1827 static HRESULT WINAPI d3drm_mesh_builder3_GetGeometry(IDirect3DRMMeshBuilder3 *iface,
1828         DWORD *vertex_count, D3DVECTOR *vertices, DWORD *normal_count, D3DVECTOR *normals,
1829         DWORD *face_data_size, DWORD *face_data)
1830 {
1831     FIXME("iface %p, vertex_count %p, vertices %p, normal_count %p, normals %p, "
1832             "face_data_size %p, face_data %p stub!\n",
1833             iface, vertex_count, vertices, normal_count, normals, face_data_size, face_data);
1834 
1835     return E_NOTIMPL;
1836 }
1837 
1838 static HRESULT WINAPI d3drm_mesh_builder3_GetTextureCoordinates(IDirect3DRMMeshBuilder3 *iface,
1839         DWORD index, D3DVALUE *u, D3DVALUE *v)
1840 {
1841     struct d3drm_mesh_builder *mesh_builder = impl_from_IDirect3DRMMeshBuilder3(iface);
1842 
1843     TRACE("iface %p, index %u, u %p, v %p.\n", iface, index, u, v);
1844 
1845     if (index >= mesh_builder->nb_coords2d)
1846         return D3DRMERR_BADVALUE;
1847 
1848     *u = mesh_builder->pCoords2d[index].u;
1849     *v = mesh_builder->pCoords2d[index].v;
1850 
1851     return D3DRM_OK;
1852 }
1853 
1854 static int WINAPI d3drm_mesh_builder3_AddVertex(IDirect3DRMMeshBuilder3 *iface,
1855         D3DVALUE x, D3DVALUE y, D3DVALUE z)
1856 {
1857     struct d3drm_mesh_builder *mesh_builder = impl_from_IDirect3DRMMeshBuilder3(iface);
1858 
1859     TRACE("iface %p, x %.8e, y %.8e, z %.8e.\n", iface, x, y, z);
1860 
1861     if (!d3drm_array_reserve((void **)&mesh_builder->vertices, &mesh_builder->vertices_size,
1862             mesh_builder->nb_vertices + 1, sizeof(*mesh_builder->vertices)))
1863         return 0;
1864 
1865     mesh_builder->vertices[mesh_builder->nb_vertices].u1.x = x;
1866     mesh_builder->vertices[mesh_builder->nb_vertices].u2.y = y;
1867     mesh_builder->vertices[mesh_builder->nb_vertices].u3.z = z;
1868 
1869     return mesh_builder->nb_vertices++;
1870 }
1871 
1872 static int WINAPI d3drm_mesh_builder3_AddNormal(IDirect3DRMMeshBuilder3 *iface,
1873         D3DVALUE x, D3DVALUE y, D3DVALUE z)
1874 {
1875     struct d3drm_mesh_builder *mesh_builder = impl_from_IDirect3DRMMeshBuilder3(iface);
1876 
1877     TRACE("iface %p, x %.8e, y %.8e, z %.8e.\n", iface, x, y, z);
1878 
1879     if (!d3drm_array_reserve((void **)&mesh_builder->normals, &mesh_builder->normals_size,
1880             mesh_builder->nb_normals + 1, sizeof(*mesh_builder->normals)))
1881         return 0;
1882 
1883     mesh_builder->normals[mesh_builder->nb_normals].u1.x = x;
1884     mesh_builder->normals[mesh_builder->nb_normals].u2.y = y;
1885     mesh_builder->normals[mesh_builder->nb_normals].u3.z = z;
1886 
1887     return mesh_builder->nb_normals++;
1888 }
1889 
1890 static HRESULT WINAPI d3drm_mesh_builder3_CreateFace(IDirect3DRMMeshBuilder3 *iface, IDirect3DRMFace2 **face)
1891 {
1892     struct d3drm_face *object;
1893     HRESULT hr;
1894 
1895     TRACE("iface %p, face %p.\n", iface, face);
1896 
1897     if (FAILED(hr = d3drm_face_create(&object)))
1898         return hr;
1899 
1900     *face = &object->IDirect3DRMFace2_iface;
1901 
1902     return S_OK;
1903 }
1904 
1905 static D3DRMRENDERQUALITY WINAPI d3drm_mesh_builder3_GetQuality(IDirect3DRMMeshBuilder3 *iface)
1906 {
1907     FIXME("iface %p stub!\n", iface);
1908 
1909     return 0;
1910 }
1911 
1912 static BOOL WINAPI d3drm_mesh_builder3_GetPerspective(IDirect3DRMMeshBuilder3 *iface)
1913 {
1914     FIXME("iface %p stub!\n", iface);
1915 
1916     return FALSE;
1917 }
1918 
1919 static int WINAPI d3drm_mesh_builder3_GetFaceCount(IDirect3DRMMeshBuilder3 *iface)
1920 {
1921     struct d3drm_mesh_builder *mesh_builder = impl_from_IDirect3DRMMeshBuilder3(iface);
1922 
1923     TRACE("iface %p.\n", iface);
1924 
1925     return mesh_builder->nb_faces;
1926 }
1927 
1928 static int WINAPI d3drm_mesh_builder3_GetVertexCount(IDirect3DRMMeshBuilder3 *iface)
1929 {
1930     struct d3drm_mesh_builder *mesh_builder = impl_from_IDirect3DRMMeshBuilder3(iface);
1931 
1932     TRACE("iface %p.\n", iface);
1933 
1934     return mesh_builder->nb_vertices;
1935 }
1936 
1937 static D3DCOLOR WINAPI d3drm_mesh_builder3_GetVertexColor(IDirect3DRMMeshBuilder3 *iface,
1938         DWORD index)
1939 {
1940     FIXME("iface %p, index %u stub!\n", iface, index);
1941 
1942     return 0;
1943 }
1944 
1945 static HRESULT WINAPI d3drm_mesh_builder3_CreateMesh(IDirect3DRMMeshBuilder3 *iface, IDirect3DRMMesh **mesh)
1946 {
1947     struct d3drm_mesh_builder *mesh_builder = impl_from_IDirect3DRMMeshBuilder3(iface);
1948     HRESULT hr;
1949     D3DRMGROUPINDEX group;
1950 
1951     TRACE("iface %p, mesh %p.\n", iface, mesh);
1952 
1953     if (!mesh)
1954         return E_POINTER;
1955 
1956     hr = IDirect3DRM_CreateMesh(mesh_builder->d3drm, mesh);
1957     if (FAILED(hr))
1958         return hr;
1959 
1960     /* If there is mesh data, create a group and put data inside */
1961     if (mesh_builder->nb_vertices)
1962     {
1963         DWORD i, j;
1964         int k;
1965         D3DRMVERTEX* vertices;
1966 
1967         if (!(vertices = heap_calloc(mesh_builder->nb_vertices, sizeof(*vertices))))
1968         {
1969             IDirect3DRMMesh_Release(*mesh);
1970             return E_OUTOFMEMORY;
1971         }
1972         for (i = 0; i < mesh_builder->nb_vertices; i++)
1973             vertices[i].position = mesh_builder->vertices[i];
1974         hr = IDirect3DRMMesh_SetVertices(*mesh, 0, 0, mesh_builder->nb_vertices, vertices);
1975         heap_free(vertices);
1976 
1977         /* Groups are in reverse order compared to materials list in X file */
1978         for (k = mesh_builder->nb_materials - 1; k >= 0; k--)
1979         {
1980             unsigned* face_data;
1981             unsigned* out_ptr;
1982             DWORD* in_ptr = mesh_builder->pFaceData;
1983             ULONG vertex_per_face = 0;
1984             BOOL* used_vertices;
1985             unsigned nb_vertices = 0;
1986             unsigned nb_faces = 0;
1987 
1988             if (!(used_vertices = heap_calloc(mesh_builder->face_data_size, sizeof(*used_vertices))))
1989             {
1990                 IDirect3DRMMesh_Release(*mesh);
1991                 return E_OUTOFMEMORY;
1992             }
1993 
1994             if (!(face_data = heap_calloc(mesh_builder->face_data_size, sizeof(*face_data))))
1995             {
1996                 heap_free(used_vertices);
1997                 IDirect3DRMMesh_Release(*mesh);
1998                 return E_OUTOFMEMORY;
1999             }
2000             out_ptr = face_data;
2001 
2002             /* If all faces have the same number of vertex, set vertex_per_face */
2003             for (i = 0; i < mesh_builder->nb_faces; i++)
2004             {
2005                 /* Process only faces belonging to the group */
2006                 if (mesh_builder->material_indices[i] == k)
2007                 {
2008                     if (vertex_per_face && (vertex_per_face != *in_ptr))
2009                         break;
2010                     vertex_per_face = *in_ptr;
2011                 }
2012                 in_ptr += 1 + *in_ptr * 2;
2013             }
2014             if (i != mesh_builder->nb_faces)
2015                 vertex_per_face = 0;
2016 
2017             /* Put only vertex indices */
2018             in_ptr = mesh_builder->pFaceData;
2019             for (i = 0; i < mesh_builder->nb_faces; i++)
2020             {
2021                 DWORD nb_indices = *in_ptr++;
2022 
2023                 /* Skip faces not belonging to the group */
2024                 if (mesh_builder->material_indices[i] != k)
2025                 {
2026                     in_ptr += 2 * nb_indices;
2027                     continue;
2028                 }
2029 
2030                 /* Don't put nb indices when vertex_per_face is set */
2031                 if (vertex_per_face)
2032                     *out_ptr++ = nb_indices;
2033 
2034                 for (j = 0; j < nb_indices; j++)
2035                 {
2036                     *out_ptr = *in_ptr++;
2037                     used_vertices[*out_ptr++] = TRUE;
2038                     /* Skip normal index */
2039                     in_ptr++;
2040                 }
2041 
2042                 nb_faces++;
2043             }
2044 
2045             for (i = 0; i < mesh_builder->nb_vertices; i++)
2046                 if (used_vertices[i])
2047                     nb_vertices++;
2048 
2049             hr = IDirect3DRMMesh_AddGroup(*mesh, nb_vertices, nb_faces, vertex_per_face, face_data, &group);
2050             heap_free(used_vertices);
2051             heap_free(face_data);
2052             if (SUCCEEDED(hr))
2053                 hr = IDirect3DRMMesh_SetGroupColor(*mesh, group, mesh_builder->materials[k].color);
2054             if (SUCCEEDED(hr))
2055                 hr = IDirect3DRMMesh_SetGroupMaterial(*mesh, group,
2056                         (IDirect3DRMMaterial *)mesh_builder->materials[k].material);
2057             if (SUCCEEDED(hr) && mesh_builder->materials[k].texture)
2058             {
2059                 IDirect3DRMTexture *texture;
2060 
2061                 IDirect3DRMTexture3_QueryInterface(mesh_builder->materials[k].texture,
2062                         &IID_IDirect3DRMTexture, (void **)&texture);
2063                 hr = IDirect3DRMMesh_SetGroupTexture(*mesh, group, texture);
2064                 IDirect3DRMTexture_Release(texture);
2065             }
2066             if (FAILED(hr))
2067             {
2068                 IDirect3DRMMesh_Release(*mesh);
2069                 return hr;
2070             }
2071         }
2072     }
2073 
2074     return D3DRM_OK;
2075 }
2076 
2077 static HRESULT WINAPI d3drm_mesh_builder3_GetFace(IDirect3DRMMeshBuilder3 *iface,
2078         DWORD index, IDirect3DRMFace2 **face)
2079 {
2080     FIXME("iface %p, index %u, face %p stub!\n", iface, index, face);
2081 
2082     return E_NOTIMPL;
2083 }
2084 
2085 static HRESULT WINAPI d3drm_mesh_builder3_GetVertex(IDirect3DRMMeshBuilder3 *iface,
2086         DWORD index, D3DVECTOR *vector)
2087 {
2088     FIXME("iface %p, index %u, vector %p stub!\n", iface, index, vector);
2089 
2090     return E_NOTIMPL;
2091 }
2092 
2093 static HRESULT WINAPI d3drm_mesh_builder3_GetNormal(IDirect3DRMMeshBuilder3 *iface,
2094         DWORD index, D3DVECTOR *vector)
2095 {
2096     FIXME("iface %p, index %u, vector %p stub!\n", iface, index, vector);
2097 
2098     return E_NOTIMPL;
2099 }
2100 
2101 static HRESULT WINAPI d3drm_mesh_builder3_DeleteVertices(IDirect3DRMMeshBuilder3 *iface,
2102         DWORD start_idx, DWORD count)
2103 {
2104     FIXME("iface %p, start_idx %u, count %u stub!\n", iface, start_idx, count);
2105 
2106     return E_NOTIMPL;
2107 }
2108 
2109 static HRESULT WINAPI d3drm_mesh_builder3_DeleteNormals(IDirect3DRMMeshBuilder3 *iface,
2110         DWORD start_idx, DWORD count)
2111 {
2112     FIXME("iface %p, start_idx %u, count %u stub!\n", iface, start_idx, count);
2113 
2114     return E_NOTIMPL;
2115 }
2116 
2117 static HRESULT WINAPI d3drm_mesh_builder3_DeleteFace(IDirect3DRMMeshBuilder3 *iface, IDirect3DRMFace2 *face)
2118 {
2119     FIXME("iface %p, face %p stub!\n", iface, face);
2120 
2121     return E_NOTIMPL;
2122 }
2123 
2124 static HRESULT WINAPI d3drm_mesh_builder3_Empty(IDirect3DRMMeshBuilder3 *iface, DWORD flags)
2125 {
2126     FIXME("iface %p, flags %#x stub!\n", iface, flags);
2127 
2128     return E_NOTIMPL;
2129 }
2130 
2131 static HRESULT WINAPI d3drm_mesh_builder3_Optimize(IDirect3DRMMeshBuilder3 *iface, DWORD flags)
2132 {
2133     FIXME("iface %p, flags %#x stub!\n", iface, flags);
2134 
2135     return E_NOTIMPL;
2136 }
2137 
2138 static HRESULT WINAPI d3drm_mesh_builder3_AddFacesIndexed(IDirect3DRMMeshBuilder3 *iface,
2139         DWORD flags, DWORD *indices, DWORD *start_idx, DWORD *count)
2140 {
2141     FIXME("iface %p, flags %#x, indices %p, start_idx %p, count %p stub!\n",
2142             iface, flags, indices, start_idx, count);
2143 
2144     return E_NOTIMPL;
2145 }
2146 
2147 static HRESULT WINAPI d3drm_mesh_builder3_CreateSubMesh(IDirect3DRMMeshBuilder3 *iface, IUnknown **mesh)
2148 {
2149     FIXME("iface %p, mesh %p stub!\n", iface, mesh);
2150 
2151     return E_NOTIMPL;
2152 }
2153 
2154 static HRESULT WINAPI d3drm_mesh_builder3_GetParentMesh(IDirect3DRMMeshBuilder3 *iface,
2155         DWORD flags, IUnknown **parent)
2156 {
2157     FIXME("iface %p, flags %#x, parent %p stub!\n", iface, flags, parent);
2158 
2159     return E_NOTIMPL;
2160 }
2161 
2162 static HRESULT WINAPI d3drm_mesh_builder3_GetSubMeshes(IDirect3DRMMeshBuilder3 *iface,
2163         DWORD *count, IUnknown **meshes)
2164 {
2165     FIXME("iface %p, count %p, meshes %p stub!\n", iface, count, meshes);
2166 
2167     return E_NOTIMPL;
2168 }
2169 
2170 static HRESULT WINAPI d3drm_mesh_builder3_DeleteSubMesh(IDirect3DRMMeshBuilder3 *iface, IUnknown *mesh)
2171 {
2172     FIXME("iface %p, mesh %p stub!\n", iface, mesh);
2173 
2174     return E_NOTIMPL;
2175 }
2176 
2177 static HRESULT WINAPI d3drm_mesh_builder3_Enable(IDirect3DRMMeshBuilder3 *iface, DWORD index)
2178 {
2179     FIXME("iface %p, index %u stub!\n", iface, index);
2180 
2181     return E_NOTIMPL;
2182 }
2183 
2184 static HRESULT WINAPI d3drm_mesh_builder3_GetEnable(IDirect3DRMMeshBuilder3 *iface, DWORD *indices)
2185 {
2186     FIXME("iface %p, indices %p stub!\n", iface, indices);
2187 
2188     return E_NOTIMPL;
2189 }
2190 
2191 static HRESULT WINAPI d3drm_mesh_builder3_AddTriangles(IDirect3DRMMeshBuilder3 *iface,
2192         DWORD flags, DWORD format, DWORD vertex_count, void *data)
2193 {
2194     FIXME("iface %p, flags %#x, format %#x, vertex_count %u, data %p stub!\n",
2195             iface, flags, format, vertex_count, data);
2196 
2197     return E_NOTIMPL;
2198 }
2199 
2200 static HRESULT WINAPI d3drm_mesh_builder3_SetVertices(IDirect3DRMMeshBuilder3 *iface,
2201         DWORD start_idx, DWORD count, D3DVECTOR *vector)
2202 {
2203     FIXME("iface %p, start_idx %u, count %u, vector %p stub!\n", iface, start_idx, count, vector);
2204 
2205     return E_NOTIMPL;
2206 }
2207 
2208 static HRESULT WINAPI d3drm_mesh_builder3_GetVertices(IDirect3DRMMeshBuilder3 *iface,
2209         DWORD start_idx, DWORD *vertex_count, D3DVECTOR *vertices)
2210 {
2211     struct d3drm_mesh_builder *mesh_builder = impl_from_IDirect3DRMMeshBuilder3(iface);
2212     DWORD count = mesh_builder->nb_vertices - start_idx;
2213 
2214     TRACE("iface %p, start_idx %u, vertex_count %p, vertices %p.\n",
2215             iface, start_idx, vertex_count, vertices);
2216 
2217     if (vertex_count)
2218         *vertex_count = count;
2219     if (vertices && mesh_builder->nb_vertices)
2220         memcpy(vertices, mesh_builder->vertices + start_idx, count * sizeof(*vertices));
2221 
2222     return D3DRM_OK;
2223 }
2224 
2225 static HRESULT WINAPI d3drm_mesh_builder3_SetNormals(IDirect3DRMMeshBuilder3 *iface,
2226         DWORD start_idx, DWORD count, D3DVECTOR *vector)
2227 {
2228     FIXME("iface %p, start_idx %u, count %u, vector %p stub!\n",
2229             iface, start_idx, count, vector);
2230 
2231     return E_NOTIMPL;
2232 }
2233 
2234 static HRESULT WINAPI d3drm_mesh_builder3_GetNormals(IDirect3DRMMeshBuilder3 *iface,
2235         DWORD start_idx, DWORD *normal_count, D3DVECTOR *normals)
2236 {
2237     struct d3drm_mesh_builder *mesh_builder = impl_from_IDirect3DRMMeshBuilder3(iface);
2238     DWORD count = mesh_builder->nb_normals - start_idx;
2239 
2240     TRACE("iface %p, start_idx %u, normal_count %p, normals %p.\n",
2241             iface, start_idx, normal_count, normals);
2242 
2243     if (normal_count)
2244         *normal_count = count;
2245     if (normals && mesh_builder->nb_normals)
2246         memcpy(normals, &mesh_builder->normals[start_idx], count * sizeof(*normals));
2247 
2248     return D3DRM_OK;
2249 }
2250 
2251 static int WINAPI d3drm_mesh_builder3_GetNormalCount(IDirect3DRMMeshBuilder3 *iface)
2252 {
2253     struct d3drm_mesh_builder *mesh_builder = impl_from_IDirect3DRMMeshBuilder3(iface);
2254 
2255     TRACE("iface %p.\n", iface);
2256 
2257     return mesh_builder->nb_normals;
2258 }
2259 
2260 static const struct IDirect3DRMMeshBuilder3Vtbl d3drm_mesh_builder3_vtbl =
2261 {
2262     d3drm_mesh_builder3_QueryInterface,
2263     d3drm_mesh_builder3_AddRef,
2264     d3drm_mesh_builder3_Release,
2265     d3drm_mesh_builder3_Clone,
2266     d3drm_mesh_builder3_AddDestroyCallback,
2267     d3drm_mesh_builder3_DeleteDestroyCallback,
2268     d3drm_mesh_builder3_SetAppData,
2269     d3drm_mesh_builder3_GetAppData,
2270     d3drm_mesh_builder3_SetName,
2271     d3drm_mesh_builder3_GetName,
2272     d3drm_mesh_builder3_GetClassName,
2273     d3drm_mesh_builder3_Load,
2274     d3drm_mesh_builder3_Save,
2275     d3drm_mesh_builder3_Scale,
2276     d3drm_mesh_builder3_Translate,
2277     d3drm_mesh_builder3_SetColorSource,
2278     d3drm_mesh_builder3_GetBox,
2279     d3drm_mesh_builder3_GenerateNormals,
2280     d3drm_mesh_builder3_GetColorSource,
2281     d3drm_mesh_builder3_AddMesh,
2282     d3drm_mesh_builder3_AddMeshBuilder,
2283     d3drm_mesh_builder3_AddFrame,
2284     d3drm_mesh_builder3_AddFace,
2285     d3drm_mesh_builder3_AddFaces,
2286     d3drm_mesh_builder3_ReserveSpace,
2287     d3drm_mesh_builder3_SetColorRGB,
2288     d3drm_mesh_builder3_SetColor,
2289     d3drm_mesh_builder3_SetTexture,
2290     d3drm_mesh_builder3_SetMaterial,
2291     d3drm_mesh_builder3_SetTextureTopology,
2292     d3drm_mesh_builder3_SetQuality,
2293     d3drm_mesh_builder3_SetPerspective,
2294     d3drm_mesh_builder3_SetVertex,
2295     d3drm_mesh_builder3_SetNormal,
2296     d3drm_mesh_builder3_SetTextureCoordinates,
2297     d3drm_mesh_builder3_SetVertexColor,
2298     d3drm_mesh_builder3_SetVertexColorRGB,
2299     d3drm_mesh_builder3_GetFaces,
2300     d3drm_mesh_builder3_GetGeometry,
2301     d3drm_mesh_builder3_GetTextureCoordinates,
2302     d3drm_mesh_builder3_AddVertex,
2303     d3drm_mesh_builder3_AddNormal,
2304     d3drm_mesh_builder3_CreateFace,
2305     d3drm_mesh_builder3_GetQuality,
2306     d3drm_mesh_builder3_GetPerspective,
2307     d3drm_mesh_builder3_GetFaceCount,
2308     d3drm_mesh_builder3_GetVertexCount,
2309     d3drm_mesh_builder3_GetVertexColor,
2310     d3drm_mesh_builder3_CreateMesh,
2311     d3drm_mesh_builder3_GetFace,
2312     d3drm_mesh_builder3_GetVertex,
2313     d3drm_mesh_builder3_GetNormal,
2314     d3drm_mesh_builder3_DeleteVertices,
2315     d3drm_mesh_builder3_DeleteNormals,
2316     d3drm_mesh_builder3_DeleteFace,
2317     d3drm_mesh_builder3_Empty,
2318     d3drm_mesh_builder3_Optimize,
2319     d3drm_mesh_builder3_AddFacesIndexed,
2320     d3drm_mesh_builder3_CreateSubMesh,
2321     d3drm_mesh_builder3_GetParentMesh,
2322     d3drm_mesh_builder3_GetSubMeshes,
2323     d3drm_mesh_builder3_DeleteSubMesh,
2324     d3drm_mesh_builder3_Enable,
2325     d3drm_mesh_builder3_GetEnable,
2326     d3drm_mesh_builder3_AddTriangles,
2327     d3drm_mesh_builder3_SetVertices,
2328     d3drm_mesh_builder3_GetVertices,
2329     d3drm_mesh_builder3_SetNormals,
2330     d3drm_mesh_builder3_GetNormals,
2331     d3drm_mesh_builder3_GetNormalCount,
2332 };
2333 
2334 HRESULT d3drm_mesh_builder_create(struct d3drm_mesh_builder **mesh_builder, IDirect3DRM *d3drm)
2335 {
2336     static const char classname[] = "Builder";
2337     struct d3drm_mesh_builder *object;
2338 
2339     TRACE("mesh_builder %p.\n", mesh_builder);
2340 
2341     if (!(object = heap_alloc_zero(sizeof(*object))))
2342         return E_OUTOFMEMORY;
2343 
2344     object->IDirect3DRMMeshBuilder2_iface.lpVtbl = &d3drm_mesh_builder2_vtbl;
2345     object->IDirect3DRMMeshBuilder3_iface.lpVtbl = &d3drm_mesh_builder3_vtbl;
2346     object->ref = 1;
2347     object->d3drm = d3drm;
2348     IDirect3DRM_AddRef(object->d3drm);
2349 
2350     d3drm_object_init(&object->obj, classname);
2351 
2352     *mesh_builder = object;
2353 
2354     return S_OK;
2355 }
2356 
2357 static HRESULT WINAPI d3drm_mesh_QueryInterface(IDirect3DRMMesh *iface, REFIID riid, void **out)
2358 {
2359     TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
2360 
2361     if (IsEqualGUID(riid, &IID_IDirect3DRMMesh)
2362             || IsEqualGUID(riid, &IID_IDirect3DRMVisual)
2363             || IsEqualGUID(riid, &IID_IDirect3DRMObject)
2364             || IsEqualGUID(riid, &IID_IUnknown))
2365     {
2366         IDirect3DRMMesh_AddRef(iface);
2367         *out = iface;
2368         return S_OK;
2369     }
2370 
2371     WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
2372 
2373     *out = NULL;
2374     return E_NOINTERFACE;
2375 }
2376 
2377 static ULONG WINAPI d3drm_mesh_AddRef(IDirect3DRMMesh *iface)
2378 {
2379     struct d3drm_mesh *mesh = impl_from_IDirect3DRMMesh(iface);
2380     ULONG refcount = InterlockedIncrement(&mesh->ref);
2381 
2382     TRACE("%p increasing refcount to %u.\n", iface, refcount);
2383 
2384     return refcount;
2385 }
2386 
2387 static ULONG WINAPI d3drm_mesh_Release(IDirect3DRMMesh *iface)
2388 {
2389     struct d3drm_mesh *mesh = impl_from_IDirect3DRMMesh(iface);
2390     ULONG refcount = InterlockedDecrement(&mesh->ref);
2391 
2392     TRACE("%p decreasing refcount to %u.\n", iface, refcount);
2393 
2394     if (!refcount)
2395     {
2396         DWORD i;
2397 
2398         d3drm_object_cleanup((IDirect3DRMObject *)iface, &mesh->obj);
2399         IDirect3DRM_Release(mesh->d3drm);
2400         for (i = 0; i < mesh->nb_groups; ++i)
2401         {
2402             heap_free(mesh->groups[i].vertices);
2403             heap_free(mesh->groups[i].face_data);
2404             if (mesh->groups[i].material)
2405                 IDirect3DRMMaterial2_Release(mesh->groups[i].material);
2406             if (mesh->groups[i].texture)
2407                 IDirect3DRMTexture3_Release(mesh->groups[i].texture);
2408         }
2409         heap_free(mesh->groups);
2410         heap_free(mesh);
2411     }
2412 
2413     return refcount;
2414 }
2415 
2416 static HRESULT WINAPI d3drm_mesh_Clone(IDirect3DRMMesh *iface,
2417         IUnknown *outer, REFIID iid, void **out)
2418 {
2419     FIXME("iface %p, outer %p, iid %s, out %p stub!\n", iface, outer, debugstr_guid(iid), out);
2420 
2421     return E_NOTIMPL;
2422 }
2423 
2424 static HRESULT WINAPI d3drm_mesh_AddDestroyCallback(IDirect3DRMMesh *iface,
2425         D3DRMOBJECTCALLBACK cb, void *ctx)
2426 {
2427     struct d3drm_mesh *mesh = impl_from_IDirect3DRMMesh(iface);
2428 
2429     TRACE("iface %p, cb %p, ctx %p.\n", iface, cb, ctx);
2430 
2431     return d3drm_object_add_destroy_callback(&mesh->obj, cb, ctx);
2432 }
2433 
2434 static HRESULT WINAPI d3drm_mesh_DeleteDestroyCallback(IDirect3DRMMesh *iface,
2435         D3DRMOBJECTCALLBACK cb, void *ctx)
2436 {
2437     struct d3drm_mesh *mesh = impl_from_IDirect3DRMMesh(iface);
2438 
2439     TRACE("iface %p, cb %p, ctx %p.\n", iface, cb, ctx);
2440 
2441     return d3drm_object_delete_destroy_callback(&mesh->obj, cb, ctx);
2442 }
2443 
2444 static HRESULT WINAPI d3drm_mesh_SetAppData(IDirect3DRMMesh *iface, DWORD data)
2445 {
2446     struct d3drm_mesh *mesh = impl_from_IDirect3DRMMesh(iface);
2447 
2448     TRACE("iface %p, data %#x.\n", iface, data);
2449 
2450     mesh->obj.appdata = data;
2451 
2452     return D3DRM_OK;
2453 }
2454 
2455 static DWORD WINAPI d3drm_mesh_GetAppData(IDirect3DRMMesh *iface)
2456 {
2457     struct d3drm_mesh *mesh = impl_from_IDirect3DRMMesh(iface);
2458 
2459     TRACE("iface %p.\n", iface);
2460 
2461     return mesh->obj.appdata;
2462 }
2463 
2464 static HRESULT WINAPI d3drm_mesh_SetName(IDirect3DRMMesh *iface, const char *name)
2465 {
2466     struct d3drm_mesh *mesh = impl_from_IDirect3DRMMesh(iface);
2467 
2468     TRACE("iface %p, name %s.\n", iface, debugstr_a(name));
2469 
2470     return d3drm_object_set_name(&mesh->obj, name);
2471 }
2472 
2473 static HRESULT WINAPI d3drm_mesh_GetName(IDirect3DRMMesh *iface, DWORD *size, char *name)
2474 {
2475     struct d3drm_mesh *mesh = impl_from_IDirect3DRMMesh(iface);
2476 
2477     TRACE("iface %p, size %p, name %p.\n", iface, size, name);
2478 
2479     return d3drm_object_get_name(&mesh->obj, size, name);
2480 }
2481 
2482 static HRESULT WINAPI d3drm_mesh_GetClassName(IDirect3DRMMesh *iface, DWORD *size, char *name)
2483 {
2484     struct d3drm_mesh *mesh = impl_from_IDirect3DRMMesh(iface);
2485 
2486     TRACE("iface %p, size %p, name %p.\n", iface, size, name);
2487 
2488     return d3drm_object_get_class_name(&mesh->obj, size, name);
2489 }
2490 
2491 static HRESULT WINAPI d3drm_mesh_Scale(IDirect3DRMMesh *iface,
2492         D3DVALUE sx, D3DVALUE sy, D3DVALUE sz)
2493 {
2494     FIXME("iface %p, sx %.8e, sy %.8e, sz %.8e stub!\n", iface, sx, sy, sz);
2495 
2496     return E_NOTIMPL;
2497 }
2498 
2499 static HRESULT WINAPI d3drm_mesh_Translate(IDirect3DRMMesh *iface,
2500         D3DVALUE tx, D3DVALUE ty, D3DVALUE tz)
2501 {
2502     FIXME("iface %p, tx %.8e, ty %.8e, tz %.8e stub!\n", iface, tx, ty, tz);
2503 
2504     return E_NOTIMPL;
2505 }
2506 
2507 static HRESULT WINAPI d3drm_mesh_GetBox(IDirect3DRMMesh *iface, D3DRMBOX *box)
2508 {
2509     FIXME("iface %p, box %p stub!\n", iface, box);
2510 
2511     return E_NOTIMPL;
2512 }
2513 
2514 static HRESULT WINAPI d3drm_mesh_AddGroup(IDirect3DRMMesh *iface, unsigned vertex_count,
2515         unsigned face_count, unsigned vertex_per_face, unsigned *face_data, D3DRMGROUPINDEX *id)
2516 {
2517     struct d3drm_mesh *mesh = impl_from_IDirect3DRMMesh(iface);
2518     struct mesh_group *group;
2519 
2520     TRACE("iface %p, vertex_count %u, face_count %u, vertex_per_face %u, face_data %p, id %p.\n",
2521             iface, vertex_count, face_count, vertex_per_face, face_data, id);
2522 
2523     if (!face_data || !id)
2524         return E_POINTER;
2525 
2526     if (!d3drm_array_reserve((void **)&mesh->groups, &mesh->groups_size, mesh->nb_groups + 1, sizeof(*mesh->groups)))
2527         return E_OUTOFMEMORY;
2528 
2529     group = mesh->groups + mesh->nb_groups;
2530 
2531     if (!(group->vertices = heap_calloc(vertex_count, sizeof(*group->vertices))))
2532         return E_OUTOFMEMORY;
2533     group->nb_vertices = vertex_count;
2534     group->nb_faces = face_count;
2535     group->vertex_per_face = vertex_per_face;
2536 
2537     if (vertex_per_face)
2538     {
2539         group->face_data_size = face_count * vertex_per_face;
2540     }
2541     else
2542     {
2543         unsigned i;
2544         unsigned nb_indices;
2545         unsigned* face_data_ptr = face_data;
2546         group->face_data_size = 0;
2547 
2548         for (i = 0; i < face_count; i++)
2549         {
2550             nb_indices = *face_data_ptr;
2551             group->face_data_size += nb_indices + 1;
2552             face_data_ptr += nb_indices;
2553         }
2554     }
2555 
2556     if (!(group->face_data = heap_calloc(group->face_data_size, sizeof(*group->face_data))))
2557     {
2558         heap_free(group->vertices);
2559         return E_OUTOFMEMORY;
2560     }
2561     memcpy(group->face_data, face_data, group->face_data_size * sizeof(*face_data));
2562 
2563     group->material = NULL;
2564     group->texture = NULL;
2565 
2566     *id = mesh->nb_groups++;
2567 
2568     return D3DRM_OK;
2569 }
2570 
2571 static HRESULT WINAPI d3drm_mesh_SetVertices(IDirect3DRMMesh *iface, D3DRMGROUPINDEX group_id,
2572         unsigned int start_idx, unsigned int count, D3DRMVERTEX *values)
2573 {
2574     struct d3drm_mesh *mesh = impl_from_IDirect3DRMMesh(iface);
2575 
2576     TRACE("iface %p, group_id %#x, start_idx %u, count %u, values %p.\n",
2577             iface, group_id, start_idx, count, values);
2578 
2579     if (group_id >= mesh->nb_groups)
2580         return D3DRMERR_BADVALUE;
2581 
2582     if ((start_idx + count - 1) >= mesh->groups[group_id].nb_vertices)
2583         return D3DRMERR_BADVALUE;
2584 
2585     if (!values)
2586         return E_POINTER;
2587 
2588     memcpy(mesh->groups[group_id].vertices + start_idx, values, count * sizeof(*values));
2589 
2590     return D3DRM_OK;
2591 }
2592 
2593 static HRESULT WINAPI d3drm_mesh_SetGroupColor(IDirect3DRMMesh *iface, D3DRMGROUPINDEX id, D3DCOLOR color)
2594 {
2595     struct d3drm_mesh *mesh = impl_from_IDirect3DRMMesh(iface);
2596 
2597     TRACE("iface %p, id %#x, color 0x%08x.\n", iface, id, color);
2598 
2599     if (id >= mesh->nb_groups)
2600         return D3DRMERR_BADVALUE;
2601 
2602     mesh->groups[id].color = color;
2603 
2604     return D3DRM_OK;
2605 }
2606 
2607 static HRESULT WINAPI d3drm_mesh_SetGroupColorRGB(IDirect3DRMMesh *iface,
2608         D3DRMGROUPINDEX id, D3DVALUE red, D3DVALUE green, D3DVALUE blue)
2609 {
2610     struct d3drm_mesh *mesh = impl_from_IDirect3DRMMesh(iface);
2611 
2612     TRACE("iface %p, id %#x, red %.8e, green %.8e, blue %.8e.\n", iface, id, red, green, blue);
2613 
2614     if (id >= mesh->nb_groups)
2615         return D3DRMERR_BADVALUE;
2616 
2617     d3drm_set_color(&mesh->groups[id].color, red, green, blue, 1.0f);
2618 
2619     return D3DRM_OK;
2620 }
2621 
2622 static HRESULT WINAPI d3drm_mesh_SetGroupMapping(IDirect3DRMMesh *iface, D3DRMGROUPINDEX id, D3DRMMAPPING value)
2623 {
2624     FIXME("iface %p, id %#x, value %#x stub!\n", iface, id, value);
2625 
2626     return E_NOTIMPL;
2627 }
2628 
2629 static HRESULT WINAPI d3drm_mesh_SetGroupQuality(IDirect3DRMMesh *iface, D3DRMGROUPINDEX id, D3DRMRENDERQUALITY value)
2630 {
2631     FIXME("iface %p, id %#x, value %#x stub!\n", iface, id, value);
2632 
2633     return E_NOTIMPL;
2634 }
2635 
2636 static HRESULT WINAPI d3drm_mesh_SetGroupMaterial(IDirect3DRMMesh *iface,
2637         D3DRMGROUPINDEX id, IDirect3DRMMaterial *material)
2638 {
2639     struct d3drm_mesh *mesh = impl_from_IDirect3DRMMesh(iface);
2640 
2641     TRACE("iface %p, id %#x, material %p.\n", iface, id, material);
2642 
2643     if (id >= mesh->nb_groups)
2644         return D3DRMERR_BADVALUE;
2645 
2646     if (mesh->groups[id].material)
2647         IDirect3DRMMaterial2_Release(mesh->groups[id].material);
2648 
2649     mesh->groups[id].material = (IDirect3DRMMaterial2 *)material;
2650 
2651     if (material)
2652         IDirect3DRMMaterial2_AddRef(mesh->groups[id].material);
2653 
2654     return D3DRM_OK;
2655 }
2656 
2657 static HRESULT WINAPI d3drm_mesh_SetGroupTexture(IDirect3DRMMesh *iface,
2658         D3DRMGROUPINDEX id, IDirect3DRMTexture *texture)
2659 {
2660     struct d3drm_mesh *mesh = impl_from_IDirect3DRMMesh(iface);
2661 
2662     TRACE("iface %p, id %#x, texture %p.\n", iface, id, texture);
2663 
2664     if (id >= mesh->nb_groups)
2665         return D3DRMERR_BADVALUE;
2666 
2667     if (mesh->groups[id].texture)
2668         IDirect3DRMTexture3_Release(mesh->groups[id].texture);
2669 
2670     if (!texture)
2671     {
2672         mesh->groups[id].texture = NULL;
2673         return D3DRM_OK;
2674     }
2675 
2676     return IDirect3DRMTexture3_QueryInterface(texture, &IID_IDirect3DRMTexture, (void **)&mesh->groups[id].texture);
2677 }
2678 
2679 static DWORD WINAPI d3drm_mesh_GetGroupCount(IDirect3DRMMesh *iface)
2680 {
2681     struct d3drm_mesh *mesh = impl_from_IDirect3DRMMesh(iface);
2682 
2683     TRACE("iface %p.\n", iface);
2684 
2685     return mesh->nb_groups;
2686 }
2687 
2688 static HRESULT WINAPI d3drm_mesh_GetGroup(IDirect3DRMMesh *iface, D3DRMGROUPINDEX id, unsigned *vertex_count,
2689         unsigned *face_count, unsigned *vertex_per_face, DWORD *face_data_size, unsigned *face_data)
2690 {
2691     struct d3drm_mesh *mesh = impl_from_IDirect3DRMMesh(iface);
2692 
2693     TRACE("iface %p, id %#x, vertex_count %p, face_count %p, vertex_per_face %p, face_data_size %p, face_data %p.\n",
2694             iface, id, vertex_count, face_count, vertex_per_face, face_data_size,face_data);
2695 
2696     if (id >= mesh->nb_groups)
2697         return D3DRMERR_BADVALUE;
2698 
2699     if (vertex_count)
2700         *vertex_count = mesh->groups[id].nb_vertices;
2701     if (face_count)
2702         *face_count = mesh->groups[id].nb_faces;
2703     if (vertex_per_face)
2704         *vertex_per_face = mesh->groups[id].vertex_per_face;
2705     if (face_data_size)
2706         *face_data_size = mesh->groups[id].face_data_size;
2707     if (face_data)
2708         memcpy(face_data, mesh->groups[id].face_data, mesh->groups[id].face_data_size * sizeof(*face_data));
2709 
2710     return D3DRM_OK;
2711 }
2712 
2713 static HRESULT WINAPI d3drm_mesh_GetVertices(IDirect3DRMMesh *iface,
2714         D3DRMGROUPINDEX group_id, DWORD start_idx, DWORD count, D3DRMVERTEX *vertices)
2715 {
2716     struct d3drm_mesh *mesh = impl_from_IDirect3DRMMesh(iface);
2717 
2718     TRACE("iface %p, group_id %#x, start_idx %u, count %u, vertices %p.\n",
2719             iface, group_id, start_idx, count, vertices);
2720 
2721     if (group_id >= mesh->nb_groups)
2722         return D3DRMERR_BADVALUE;
2723 
2724     if ((start_idx + count - 1) >= mesh->groups[group_id].nb_vertices)
2725         return D3DRMERR_BADVALUE;
2726 
2727     if (!vertices)
2728         return E_POINTER;
2729 
2730     memcpy(vertices, mesh->groups[group_id].vertices + start_idx, count * sizeof(*vertices));
2731 
2732     return D3DRM_OK;
2733 }
2734 
2735 static D3DCOLOR WINAPI d3drm_mesh_GetGroupColor(IDirect3DRMMesh *iface, D3DRMGROUPINDEX id)
2736 {
2737     struct d3drm_mesh *mesh = impl_from_IDirect3DRMMesh(iface);
2738 
2739     TRACE("iface %p, id %#x.\n", iface, id);
2740 
2741     return mesh->groups[id].color;
2742 }
2743 
2744 static D3DRMMAPPING WINAPI d3drm_mesh_GetGroupMapping(IDirect3DRMMesh *iface, D3DRMGROUPINDEX id)
2745 {
2746     FIXME("iface %p, id %#x stub!\n", iface, id);
2747 
2748     return 0;
2749 }
2750 static D3DRMRENDERQUALITY WINAPI d3drm_mesh_GetGroupQuality(IDirect3DRMMesh *iface, D3DRMGROUPINDEX id)
2751 {
2752     FIXME("iface %p, id %#x stub!\n", iface, id);
2753 
2754     return 0;
2755 }
2756 
2757 static HRESULT WINAPI d3drm_mesh_GetGroupMaterial(IDirect3DRMMesh *iface,
2758         D3DRMGROUPINDEX id, IDirect3DRMMaterial **material)
2759 {
2760     struct d3drm_mesh *mesh = impl_from_IDirect3DRMMesh(iface);
2761 
2762     TRACE("iface %p, id %#x, material %p.\n", iface, id, material);
2763 
2764     if (id >= mesh->nb_groups)
2765         return D3DRMERR_BADVALUE;
2766 
2767     if (!material)
2768         return E_POINTER;
2769 
2770     if (mesh->groups[id].material)
2771         IDirect3DRMTexture_QueryInterface(mesh->groups[id].material, &IID_IDirect3DRMMaterial, (void **)material);
2772     else
2773         *material = NULL;
2774 
2775     return D3DRM_OK;
2776 }
2777 
2778 static HRESULT WINAPI d3drm_mesh_GetGroupTexture(IDirect3DRMMesh *iface,
2779         D3DRMGROUPINDEX id, IDirect3DRMTexture **texture)
2780 {
2781     struct d3drm_mesh *mesh = impl_from_IDirect3DRMMesh(iface);
2782 
2783     TRACE("iface %p, id %#x, texture %p.\n", iface, id, texture);
2784 
2785     if (id >= mesh->nb_groups)
2786         return D3DRMERR_BADVALUE;
2787 
2788     if (!texture)
2789         return E_POINTER;
2790 
2791     if (mesh->groups[id].texture)
2792         IDirect3DRMTexture_QueryInterface(mesh->groups[id].texture, &IID_IDirect3DRMTexture, (void **)texture);
2793     else
2794         *texture = NULL;
2795 
2796     return D3DRM_OK;
2797 }
2798 
2799 static const struct IDirect3DRMMeshVtbl d3drm_mesh_vtbl =
2800 {
2801     d3drm_mesh_QueryInterface,
2802     d3drm_mesh_AddRef,
2803     d3drm_mesh_Release,
2804     d3drm_mesh_Clone,
2805     d3drm_mesh_AddDestroyCallback,
2806     d3drm_mesh_DeleteDestroyCallback,
2807     d3drm_mesh_SetAppData,
2808     d3drm_mesh_GetAppData,
2809     d3drm_mesh_SetName,
2810     d3drm_mesh_GetName,
2811     d3drm_mesh_GetClassName,
2812     d3drm_mesh_Scale,
2813     d3drm_mesh_Translate,
2814     d3drm_mesh_GetBox,
2815     d3drm_mesh_AddGroup,
2816     d3drm_mesh_SetVertices,
2817     d3drm_mesh_SetGroupColor,
2818     d3drm_mesh_SetGroupColorRGB,
2819     d3drm_mesh_SetGroupMapping,
2820     d3drm_mesh_SetGroupQuality,
2821     d3drm_mesh_SetGroupMaterial,
2822     d3drm_mesh_SetGroupTexture,
2823     d3drm_mesh_GetGroupCount,
2824     d3drm_mesh_GetGroup,
2825     d3drm_mesh_GetVertices,
2826     d3drm_mesh_GetGroupColor,
2827     d3drm_mesh_GetGroupMapping,
2828     d3drm_mesh_GetGroupQuality,
2829     d3drm_mesh_GetGroupMaterial,
2830     d3drm_mesh_GetGroupTexture,
2831 };
2832 
2833 HRESULT d3drm_mesh_create(struct d3drm_mesh **mesh, IDirect3DRM *d3drm)
2834 {
2835     static const char classname[] = "Mesh";
2836     struct d3drm_mesh *object;
2837 
2838     TRACE("mesh %p, d3drm %p.\n", mesh, d3drm);
2839 
2840     if (!(object = heap_alloc_zero(sizeof(*object))))
2841         return E_OUTOFMEMORY;
2842 
2843     object->IDirect3DRMMesh_iface.lpVtbl = &d3drm_mesh_vtbl;
2844     object->ref = 1;
2845     object->d3drm = d3drm;
2846     IDirect3DRM_AddRef(object->d3drm);
2847 
2848     d3drm_object_init(&object->obj, classname);
2849 
2850     *mesh = object;
2851 
2852     return S_OK;
2853 }
2854 
2855 static HRESULT WINAPI d3drm_wrap_QueryInterface(IDirect3DRMWrap *iface, REFIID riid, void **out)
2856 {
2857     TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
2858 
2859     if (IsEqualGUID(riid, &IID_IDirect3DRMWrap)
2860             || IsEqualGUID(riid, &IID_IDirect3DRMObject)
2861             || IsEqualGUID(riid, &IID_IUnknown))
2862     {
2863         IDirect3DRMWrap_AddRef(iface);
2864         *out = iface;
2865         return S_OK;
2866     }
2867 
2868     WARN("%s not implemented.\n", debugstr_guid(riid));
2869 
2870     *out = NULL;
2871     return CLASS_E_CLASSNOTAVAILABLE;
2872 }
2873 
2874 static ULONG WINAPI d3drm_wrap_AddRef(IDirect3DRMWrap *iface)
2875 {
2876     struct d3drm_wrap *wrap = impl_from_IDirect3DRMWrap(iface);
2877     ULONG refcount = InterlockedIncrement(&wrap->ref);
2878 
2879     TRACE("%p increasing refcount to %u.\n", iface, refcount);
2880 
2881     return refcount;
2882 }
2883 
2884 static ULONG WINAPI d3drm_wrap_Release(IDirect3DRMWrap *iface)
2885 {
2886     struct d3drm_wrap *wrap = impl_from_IDirect3DRMWrap(iface);
2887     ULONG refcount = InterlockedDecrement(&wrap->ref);
2888 
2889     TRACE("%p decreasing refcount to %u.\n", iface, refcount);
2890 
2891     if (!refcount)
2892     {
2893         d3drm_object_cleanup((IDirect3DRMObject *)iface, &wrap->obj);
2894         heap_free(wrap);
2895     }
2896 
2897     return refcount;
2898 }
2899 
2900 static HRESULT WINAPI d3drm_wrap_Clone(IDirect3DRMWrap *iface,
2901         IUnknown *outer, REFIID iid, void **out)
2902 {
2903     FIXME("iface %p, outer %p, iid %s, out %p stub!\n", iface, outer, debugstr_guid(iid), out);
2904 
2905     return E_NOTIMPL;
2906 }
2907 
2908 static HRESULT WINAPI d3drm_wrap_AddDestroyCallback(IDirect3DRMWrap *iface,
2909         D3DRMOBJECTCALLBACK cb, void *ctx)
2910 {
2911     struct d3drm_wrap *wrap = impl_from_IDirect3DRMWrap(iface);
2912 
2913     TRACE("iface %p, cb %p, ctx %p.\n", iface, cb, ctx);
2914 
2915     return d3drm_object_add_destroy_callback(&wrap->obj, cb, ctx);
2916 }
2917 
2918 static HRESULT WINAPI d3drm_wrap_DeleteDestroyCallback(IDirect3DRMWrap *iface,
2919         D3DRMOBJECTCALLBACK cb, void *ctx)
2920 {
2921     struct d3drm_wrap *wrap = impl_from_IDirect3DRMWrap(iface);
2922 
2923     TRACE("iface %p, cb %p, ctx %p.\n", iface, cb, ctx);
2924 
2925     return d3drm_object_delete_destroy_callback(&wrap->obj, cb, ctx);
2926 }
2927 
2928 static HRESULT WINAPI d3drm_wrap_SetAppData(IDirect3DRMWrap *iface, DWORD data)
2929 {
2930     struct d3drm_wrap *wrap = impl_from_IDirect3DRMWrap(iface);
2931 
2932     TRACE("iface %p, data %#x.\n", iface, data);
2933 
2934     wrap->obj.appdata = data;
2935 
2936     return D3DRM_OK;
2937 }
2938 
2939 static DWORD WINAPI d3drm_wrap_GetAppData(IDirect3DRMWrap *iface)
2940 {
2941     struct d3drm_wrap *wrap = impl_from_IDirect3DRMWrap(iface);
2942 
2943     TRACE("iface %p.\n", iface);
2944 
2945     return wrap->obj.appdata;
2946 }
2947 
2948 static HRESULT WINAPI d3drm_wrap_SetName(IDirect3DRMWrap *iface, const char *name)
2949 {
2950     struct d3drm_wrap *wrap = impl_from_IDirect3DRMWrap(iface);
2951 
2952     TRACE("iface %p, name %s.\n", iface, debugstr_a(name));
2953 
2954     return d3drm_object_set_name(&wrap->obj, name);
2955 }
2956 
2957 static HRESULT WINAPI d3drm_wrap_GetName(IDirect3DRMWrap *iface, DWORD *size, char *name)
2958 {
2959     struct d3drm_wrap *wrap = impl_from_IDirect3DRMWrap(iface);
2960 
2961     TRACE("iface %p, size %p, name %p.\n", iface, size, name);
2962 
2963     return d3drm_object_get_name(&wrap->obj, size, name);
2964 }
2965 
2966 static HRESULT WINAPI d3drm_wrap_GetClassName(IDirect3DRMWrap *iface, DWORD *size, char *name)
2967 {
2968     struct d3drm_wrap *wrap = impl_from_IDirect3DRMWrap(iface);
2969 
2970     TRACE("iface %p, size %p, name %p.\n", iface, size, name);
2971 
2972     return d3drm_object_get_class_name(&wrap->obj, size, name);
2973 }
2974 
2975 static HRESULT WINAPI d3drm_wrap_Init(IDirect3DRMWrap *iface, D3DRMWRAPTYPE type, IDirect3DRMFrame *reference,
2976        D3DVALUE ox, D3DVALUE oy, D3DVALUE oz, D3DVALUE dx, D3DVALUE dy, D3DVALUE dz, D3DVALUE ux,
2977        D3DVALUE uy, D3DVALUE uz, D3DVALUE ou, D3DVALUE ov, D3DVALUE su, D3DVALUE sv)
2978 {
2979     FIXME("iface %p, type %d, reference frame %p, ox %.8e, oy %.8e, oz %.8e, dx %.8e, dy %.8e, dz %.8e, ux %.8e, "
2980             "uy %.8e, uz %.8e, ou %.8e, ov %.8e, su %.8e, sv %.8e.\n", iface, type, reference, ox, oy, oz, dx, dy, dz,
2981             ux, uy, uz, ou, ov, su, sv);
2982 
2983     return E_NOTIMPL;
2984 }
2985 
2986 static HRESULT WINAPI d3drm_wrap_Apply(IDirect3DRMWrap *iface, IDirect3DRMObject *object)
2987 {
2988     FIXME("iface %p, object %p.\n", iface, object);
2989 
2990     return E_NOTIMPL;
2991 }
2992 
2993 static HRESULT WINAPI d3drm_wrap_ApplyRelative(IDirect3DRMWrap *iface, IDirect3DRMFrame *frame,
2994        IDirect3DRMObject *object)
2995 {
2996     FIXME("iface %p, frame %p, object %p.\n", iface, frame, object);
2997 
2998     return E_NOTIMPL;
2999 }
3000 
3001 static const struct IDirect3DRMWrapVtbl d3drm_wrap_vtbl =
3002 {
3003     d3drm_wrap_QueryInterface,
3004     d3drm_wrap_AddRef,
3005     d3drm_wrap_Release,
3006     d3drm_wrap_Clone,
3007     d3drm_wrap_AddDestroyCallback,
3008     d3drm_wrap_DeleteDestroyCallback,
3009     d3drm_wrap_SetAppData,
3010     d3drm_wrap_GetAppData,
3011     d3drm_wrap_SetName,
3012     d3drm_wrap_GetName,
3013     d3drm_wrap_GetClassName,
3014     d3drm_wrap_Init,
3015     d3drm_wrap_Apply,
3016     d3drm_wrap_ApplyRelative,
3017 };
3018 
3019 HRESULT d3drm_wrap_create(struct d3drm_wrap **wrap, IDirect3DRM *d3drm)
3020 {
3021     static const char classname[] = "";
3022     struct d3drm_wrap *object;
3023 
3024     TRACE("wrap %p, d3drm %p.\n", wrap, d3drm);
3025 
3026     if (!(object = heap_alloc_zero(sizeof(*object))))
3027         return E_OUTOFMEMORY;
3028 
3029     object->IDirect3DRMWrap_iface.lpVtbl = &d3drm_wrap_vtbl;
3030     object->ref = 1;
3031 
3032     d3drm_object_init(&object->obj, classname);
3033 
3034     *wrap = object;
3035 
3036     return S_OK;
3037 }
3038