1 /* 2 * Skin Info operations specific to D3DX9. 3 * 4 * Copyright (C) 2011 Dylan Smith 5 * Copyright (C) 2013 Christian Costa 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 "config.h" 23 #include "wine/port.h" 24 25 #include "d3dx9_private.h" 26 27 WINE_DEFAULT_DEBUG_CHANNEL(d3dx); 28 29 struct bone 30 { 31 char *name; 32 D3DXMATRIX transform; 33 DWORD num_influences; 34 DWORD *vertices; 35 FLOAT *weights; 36 }; 37 38 struct d3dx9_skin_info 39 { 40 ID3DXSkinInfo ID3DXSkinInfo_iface; 41 LONG ref; 42 43 DWORD fvf; 44 D3DVERTEXELEMENT9 vertex_declaration[MAX_FVF_DECL_SIZE]; 45 DWORD num_vertices; 46 DWORD num_bones; 47 struct bone *bones; 48 }; 49 50 static inline struct d3dx9_skin_info *impl_from_ID3DXSkinInfo(ID3DXSkinInfo *iface) 51 { 52 return CONTAINING_RECORD(iface, struct d3dx9_skin_info, ID3DXSkinInfo_iface); 53 } 54 55 static HRESULT WINAPI d3dx9_skin_info_QueryInterface(ID3DXSkinInfo *iface, REFIID riid, void **out) 56 { 57 TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out); 58 59 if (IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_ID3DXSkinInfo)) 60 { 61 IUnknown_AddRef(iface); 62 *out = iface; 63 return D3D_OK; 64 } 65 66 WARN("%s not implemented, returning E_NOINTERFACE\n", debugstr_guid(riid)); 67 68 return E_NOINTERFACE; 69 } 70 71 static ULONG WINAPI d3dx9_skin_info_AddRef(ID3DXSkinInfo *iface) 72 { 73 struct d3dx9_skin_info *skin = impl_from_ID3DXSkinInfo(iface); 74 ULONG refcount = InterlockedIncrement(&skin->ref); 75 76 TRACE("%p increasing refcount to %u.\n", skin, refcount); 77 78 return refcount; 79 } 80 81 static ULONG WINAPI d3dx9_skin_info_Release(ID3DXSkinInfo *iface) 82 { 83 struct d3dx9_skin_info *skin = impl_from_ID3DXSkinInfo(iface); 84 ULONG refcount = InterlockedDecrement(&skin->ref); 85 86 TRACE("%p decreasing refcount to %u.\n", skin, refcount); 87 88 if (!refcount) 89 { 90 DWORD i; 91 92 for (i = 0; i < skin->num_bones; ++i) 93 { 94 HeapFree(GetProcessHeap(), 0, skin->bones[i].name); 95 HeapFree(GetProcessHeap(), 0, skin->bones[i].vertices); 96 HeapFree(GetProcessHeap(), 0, skin->bones[i].weights); 97 } 98 if (skin->bones) HeapFree(GetProcessHeap(), 0, skin->bones); 99 HeapFree(GetProcessHeap(), 0, skin); 100 } 101 102 return refcount; 103 } 104 105 static HRESULT WINAPI d3dx9_skin_info_SetBoneInfluence(ID3DXSkinInfo *iface, 106 DWORD bone_num, DWORD num_influences, const DWORD *vertices, const float *weights) 107 { 108 struct d3dx9_skin_info *skin = impl_from_ID3DXSkinInfo(iface); 109 struct bone *bone; 110 DWORD *new_vertices = NULL; 111 FLOAT *new_weights = NULL; 112 113 TRACE("iface %p, bone_num %u, num_influences %u, vertices %p, weights %p.\n", 114 iface, bone_num, num_influences, vertices, weights); 115 116 if (bone_num >= skin->num_bones || !vertices || !weights) 117 return D3DERR_INVALIDCALL; 118 119 if (num_influences) { 120 new_vertices = HeapAlloc(GetProcessHeap(), 0, num_influences * sizeof(*vertices)); 121 if (!new_vertices) 122 return E_OUTOFMEMORY; 123 new_weights = HeapAlloc(GetProcessHeap(), 0, num_influences * sizeof(*weights)); 124 if (!new_weights) { 125 HeapFree(GetProcessHeap(), 0, new_vertices); 126 return E_OUTOFMEMORY; 127 } 128 memcpy(new_vertices, vertices, num_influences * sizeof(*vertices)); 129 memcpy(new_weights, weights, num_influences * sizeof(*weights)); 130 } 131 bone = &skin->bones[bone_num]; 132 bone->num_influences = num_influences; 133 HeapFree(GetProcessHeap(), 0, bone->vertices); 134 HeapFree(GetProcessHeap(), 0, bone->weights); 135 bone->vertices = new_vertices; 136 bone->weights = new_weights; 137 138 return D3D_OK; 139 } 140 141 static HRESULT WINAPI d3dx9_skin_info_SetBoneVertexInfluence(ID3DXSkinInfo *iface, 142 DWORD bone_num, DWORD influence_num, float weight) 143 { 144 FIXME("iface %p, bone_num %u, influence_num %u, weight %.8e stub!\n", 145 iface, bone_num, influence_num, weight); 146 147 return E_NOTIMPL; 148 } 149 150 static DWORD WINAPI d3dx9_skin_info_GetNumBoneInfluences(ID3DXSkinInfo *iface, DWORD bone_num) 151 { 152 struct d3dx9_skin_info *skin = impl_from_ID3DXSkinInfo(iface); 153 154 TRACE("iface %p, bone_num %u.\n", iface, bone_num); 155 156 if (bone_num >= skin->num_bones) 157 return 0; 158 159 return skin->bones[bone_num].num_influences; 160 } 161 162 static HRESULT WINAPI d3dx9_skin_info_GetBoneInfluence(ID3DXSkinInfo *iface, 163 DWORD bone_num, DWORD *vertices, float *weights) 164 { 165 struct d3dx9_skin_info *skin = impl_from_ID3DXSkinInfo(iface); 166 struct bone *bone; 167 168 TRACE("iface %p, bone_num %u, vertices %p, weights %p.\n", 169 iface, bone_num, vertices, weights); 170 171 if (bone_num >= skin->num_bones || !vertices) 172 return D3DERR_INVALIDCALL; 173 174 bone = &skin->bones[bone_num]; 175 if (!bone->num_influences) 176 return D3D_OK; 177 178 memcpy(vertices, bone->vertices, bone->num_influences * sizeof(*vertices)); 179 if (weights) 180 memcpy(weights, bone->weights, bone->num_influences * sizeof(*weights)); 181 182 return D3D_OK; 183 } 184 185 static HRESULT WINAPI d3dx9_skin_info_GetBoneVertexInfluence(ID3DXSkinInfo *iface, 186 DWORD bone_num, DWORD influence_num, float *weight, DWORD *vertex_num) 187 { 188 FIXME("iface %p, bone_num %u, influence_num %u, weight %p, vertex_num %p stub!\n", 189 iface, bone_num, influence_num, weight, vertex_num); 190 191 return E_NOTIMPL; 192 } 193 194 static HRESULT WINAPI d3dx9_skin_info_GetMaxVertexInfluences(ID3DXSkinInfo *iface, DWORD *max_vertex_influences) 195 { 196 FIXME("iface %p, max_vertex_influences %p stub!\n", iface, max_vertex_influences); 197 198 return E_NOTIMPL; 199 } 200 201 static DWORD WINAPI d3dx9_skin_info_GetNumBones(ID3DXSkinInfo *iface) 202 { 203 struct d3dx9_skin_info *skin = impl_from_ID3DXSkinInfo(iface); 204 205 TRACE("iface %p.\n", iface); 206 207 return skin->num_bones; 208 } 209 210 static HRESULT WINAPI d3dx9_skin_info_FindBoneVertexInfluenceIndex(ID3DXSkinInfo *iface, 211 DWORD bone_num, DWORD vertex_num, DWORD *influence_index) 212 { 213 FIXME("iface %p, bone_num %u, vertex_num %u, influence_index %p stub!\n", 214 iface, bone_num, vertex_num, influence_index); 215 216 return E_NOTIMPL; 217 } 218 219 static HRESULT WINAPI d3dx9_skin_info_GetMaxFaceInfluences(struct ID3DXSkinInfo *iface, 220 struct IDirect3DIndexBuffer9 *index_buffer, DWORD num_faces, DWORD *max_face_influences) 221 { 222 FIXME("iface %p, index_buffer %p, num_faces %u, max_face_influences %p stub!\n", 223 iface, index_buffer, num_faces, max_face_influences); 224 225 return E_NOTIMPL; 226 } 227 228 static HRESULT WINAPI d3dx9_skin_info_SetMinBoneInfluence(ID3DXSkinInfo *iface, float min_influence) 229 { 230 FIXME("iface %p, min_influence %.8e stub!\n", iface, min_influence); 231 232 return E_NOTIMPL; 233 } 234 235 static float WINAPI d3dx9_skin_info_GetMinBoneInfluence(ID3DXSkinInfo *iface) 236 { 237 FIXME("iface %p stub!\n", iface); 238 239 return 0.0f; 240 } 241 242 static HRESULT WINAPI d3dx9_skin_info_SetBoneName(ID3DXSkinInfo *iface, DWORD bone_idx, const char *name) 243 { 244 struct d3dx9_skin_info *skin = impl_from_ID3DXSkinInfo(iface); 245 char *new_name; 246 size_t size; 247 248 TRACE("iface %p, bone_idx %u, name %s.\n", iface, bone_idx, debugstr_a(name)); 249 250 if (bone_idx >= skin->num_bones || !name) 251 return D3DERR_INVALIDCALL; 252 253 size = strlen(name) + 1; 254 new_name = HeapAlloc(GetProcessHeap(), 0, size); 255 if (!new_name) 256 return E_OUTOFMEMORY; 257 memcpy(new_name, name, size); 258 HeapFree(GetProcessHeap(), 0, skin->bones[bone_idx].name); 259 skin->bones[bone_idx].name = new_name; 260 261 return D3D_OK; 262 } 263 264 static const char * WINAPI d3dx9_skin_info_GetBoneName(ID3DXSkinInfo *iface, DWORD bone_idx) 265 { 266 struct d3dx9_skin_info *skin = impl_from_ID3DXSkinInfo(iface); 267 268 TRACE("iface %p, bone_idx %u.\n", iface, bone_idx); 269 270 if (bone_idx >= skin->num_bones) 271 return NULL; 272 273 return skin->bones[bone_idx].name; 274 } 275 276 static HRESULT WINAPI d3dx9_skin_info_SetBoneOffsetMatrix(ID3DXSkinInfo *iface, 277 DWORD bone_num, const D3DXMATRIX *bone_transform) 278 { 279 struct d3dx9_skin_info *skin = impl_from_ID3DXSkinInfo(iface); 280 281 TRACE("iface %p, bone_num %u, bone_transform %p.\n", iface, bone_num, bone_transform); 282 283 if (bone_num >= skin->num_bones || !bone_transform) 284 return D3DERR_INVALIDCALL; 285 286 skin->bones[bone_num].transform = *bone_transform; 287 return D3D_OK; 288 } 289 290 static D3DXMATRIX * WINAPI d3dx9_skin_info_GetBoneOffsetMatrix(ID3DXSkinInfo *iface, DWORD bone_num) 291 { 292 struct d3dx9_skin_info *skin = impl_from_ID3DXSkinInfo(iface); 293 294 TRACE("iface %p, bone_num %u.\n", iface, bone_num); 295 296 if (bone_num >= skin->num_bones) 297 return NULL; 298 299 return &skin->bones[bone_num].transform; 300 } 301 302 static HRESULT WINAPI d3dx9_skin_info_Clone(ID3DXSkinInfo *iface, ID3DXSkinInfo **skin_info) 303 { 304 FIXME("iface %p, skin_info %p stub!\n", iface, skin_info); 305 306 return E_NOTIMPL; 307 } 308 309 static HRESULT WINAPI d3dx9_skin_info_Remap(ID3DXSkinInfo *iface, DWORD num_vertices, DWORD *vertex_remap) 310 { 311 FIXME("iface %p, num_vertices %u, vertex_remap %p stub!\n", iface, num_vertices, vertex_remap); 312 313 return E_NOTIMPL; 314 } 315 316 static HRESULT WINAPI d3dx9_skin_info_SetFVF(ID3DXSkinInfo *iface, DWORD fvf) 317 { 318 HRESULT hr; 319 D3DVERTEXELEMENT9 declaration[MAX_FVF_DECL_SIZE]; 320 321 TRACE("iface %p, fvf %#x.\n", iface, fvf); 322 323 hr = D3DXDeclaratorFromFVF(fvf, declaration); 324 if (FAILED(hr)) return hr; 325 326 return iface->lpVtbl->SetDeclaration(iface, declaration); 327 } 328 329 static HRESULT WINAPI d3dx9_skin_info_SetDeclaration(ID3DXSkinInfo *iface, const D3DVERTEXELEMENT9 *declaration) 330 { 331 struct d3dx9_skin_info *skin = impl_from_ID3DXSkinInfo(iface); 332 HRESULT hr; 333 int count; 334 335 TRACE("iface %p, declaration %p.\n", iface, declaration); 336 337 if (!declaration) 338 return D3DERR_INVALIDCALL; 339 for (count = 0; declaration[count].Stream != 0xff; count++) { 340 if (declaration[count].Stream != 0) { 341 WARN("Invalid vertex element %u; contains non-zero stream %u\n", 342 count, declaration[count].Stream); 343 return D3DERR_INVALIDCALL; 344 } 345 } 346 count++; 347 348 memcpy(skin->vertex_declaration, declaration, count * sizeof(*declaration)); 349 350 if (FAILED(hr = D3DXFVFFromDeclarator(skin->vertex_declaration, &skin->fvf))) 351 skin->fvf = 0; 352 353 return D3D_OK; 354 } 355 356 static DWORD WINAPI d3dx9_skin_info_GetFVF(ID3DXSkinInfo *iface) 357 { 358 struct d3dx9_skin_info *skin = impl_from_ID3DXSkinInfo(iface); 359 360 TRACE("iface %p.\n", iface); 361 362 return skin->fvf; 363 } 364 365 static HRESULT WINAPI d3dx9_skin_info_GetDeclaration(ID3DXSkinInfo *iface, 366 D3DVERTEXELEMENT9 declaration[MAX_FVF_DECL_SIZE]) 367 { 368 struct d3dx9_skin_info *skin = impl_from_ID3DXSkinInfo(iface); 369 UINT count = 0; 370 371 TRACE("iface %p, declaration %p.\n", iface, declaration); 372 373 while (skin->vertex_declaration[count++].Stream != 0xff); 374 memcpy(declaration, skin->vertex_declaration, count * sizeof(declaration[0])); 375 return D3D_OK; 376 } 377 378 static HRESULT WINAPI d3dx9_skin_info_UpdateSkinnedMesh(ID3DXSkinInfo *iface, const D3DXMATRIX *bone_transforms, 379 const D3DXMATRIX *bone_inv_transpose_transforms, const void *src_vertices, void *dst_vertices) 380 { 381 struct d3dx9_skin_info *skin = impl_from_ID3DXSkinInfo(iface); 382 DWORD size = D3DXGetFVFVertexSize(skin->fvf); 383 DWORD i, j; 384 385 TRACE("iface %p, bone_transforms %p, bone_inv_transpose_transforms %p, src_vertices %p, dst_vertices %p\n", 386 skin, bone_transforms, bone_inv_transpose_transforms, src_vertices, dst_vertices); 387 388 if (bone_inv_transpose_transforms) 389 FIXME("Skinning vertices with two position elements not supported\n"); 390 391 if ((skin->fvf & D3DFVF_POSITION_MASK) != D3DFVF_XYZ) { 392 FIXME("Vertex type %#x not supported\n", skin->fvf & D3DFVF_POSITION_MASK); 393 return E_FAIL; 394 } 395 396 /* Reset all positions */ 397 for (i = 0; i < skin->num_vertices; i++) { 398 D3DXVECTOR3 *position = (D3DXVECTOR3*)((BYTE*)dst_vertices + size * i); 399 position->x = 0.0f; 400 position->y = 0.0f; 401 position->z = 0.0f; 402 } 403 404 /* Update positions that are influenced by bones */ 405 for (i = 0; i < skin->num_bones; i++) { 406 D3DXMATRIX bone_inverse, matrix; 407 408 D3DXMatrixInverse(&bone_inverse, NULL, &skin->bones[i].transform); 409 D3DXMatrixMultiply(&matrix, &bone_transforms[i], &bone_inverse); 410 D3DXMatrixMultiply(&matrix, &matrix, &skin->bones[i].transform); 411 412 for (j = 0; j < skin->bones[i].num_influences; j++) { 413 D3DXVECTOR3 position; 414 D3DXVECTOR3 *position_src = (D3DXVECTOR3*)((BYTE*)src_vertices + size * skin->bones[i].vertices[j]); 415 D3DXVECTOR3 *position_dest = (D3DXVECTOR3*)((BYTE*)dst_vertices + size * skin->bones[i].vertices[j]); 416 FLOAT weight = skin->bones[i].weights[j]; 417 418 D3DXVec3TransformCoord(&position, position_src, &matrix); 419 position_dest->x += weight * position.x; 420 position_dest->y += weight * position.y; 421 position_dest->z += weight * position.z; 422 } 423 } 424 425 if (skin->fvf & D3DFVF_NORMAL) { 426 /* Reset all normals */ 427 for (i = 0; i < skin->num_vertices; i++) { 428 D3DXVECTOR3 *normal = (D3DXVECTOR3*)((BYTE*)dst_vertices + size * i + sizeof(D3DXVECTOR3)); 429 normal->x = 0.0f; 430 normal->y = 0.0f; 431 normal->z = 0.0f; 432 } 433 434 /* Update normals that are influenced by bones */ 435 for (i = 0; i < skin->num_bones; i++) { 436 D3DXMATRIX bone_inverse, matrix; 437 438 D3DXMatrixInverse(&bone_inverse, NULL, &skin->bones[i].transform); 439 D3DXMatrixMultiply(&matrix, &skin->bones[i].transform, &bone_transforms[i]); 440 441 for (j = 0; j < skin->bones[i].num_influences; j++) { 442 D3DXVECTOR3 normal; 443 D3DXVECTOR3 *normal_src = (D3DXVECTOR3*)((BYTE*)src_vertices + size * skin->bones[i].vertices[j] + sizeof(D3DXVECTOR3)); 444 D3DXVECTOR3 *normal_dest = (D3DXVECTOR3*)((BYTE*)dst_vertices + size * skin->bones[i].vertices[j] + sizeof(D3DXVECTOR3)); 445 FLOAT weight = skin->bones[i].weights[j]; 446 447 D3DXVec3TransformNormal(&normal, normal_src, &bone_inverse); 448 D3DXVec3TransformNormal(&normal, &normal, &matrix); 449 normal_dest->x += weight * normal.x; 450 normal_dest->y += weight * normal.y; 451 normal_dest->z += weight * normal.z; 452 } 453 } 454 455 /* Normalize all normals that are influenced by bones*/ 456 for (i = 0; i < skin->num_vertices; i++) { 457 D3DXVECTOR3 *normal_dest = (D3DXVECTOR3*)((BYTE*)dst_vertices + (i * size) + sizeof(D3DXVECTOR3)); 458 if ((normal_dest->x != 0.0f) && (normal_dest->y != 0.0f) && (normal_dest->z != 0.0f)) 459 D3DXVec3Normalize(normal_dest, normal_dest); 460 } 461 } 462 463 return D3D_OK; 464 } 465 466 static HRESULT WINAPI d3dx9_skin_info_ConvertToBlendedMesh(ID3DXSkinInfo *iface, ID3DXMesh *mesh_in, 467 DWORD options, const DWORD *adjacency_in, DWORD *adjacency_out, DWORD *face_remap, 468 ID3DXBuffer **vertex_remap, DWORD *max_face_infl, DWORD *num_bone_combinations, 469 ID3DXBuffer **bone_combination_table, ID3DXMesh **mesh_out) 470 { 471 FIXME("iface %p, mesh_in %p, options %#x, adjacency_in %p, adjacency_out %p, face_remap %p, vertex_remap %p, " 472 "max_face_infl %p, num_bone_combinations %p, bone_combination_table %p, mesh_out %p stub!\n", 473 iface, mesh_in, options, adjacency_in, adjacency_out, face_remap, vertex_remap, 474 max_face_infl, num_bone_combinations, bone_combination_table, mesh_out); 475 476 return E_NOTIMPL; 477 } 478 479 static HRESULT WINAPI d3dx9_skin_info_ConvertToIndexedBlendedMesh(ID3DXSkinInfo *iface, ID3DXMesh *mesh_in, 480 DWORD options, DWORD palette_size, const DWORD *adjacency_in, DWORD *adjacency_out, DWORD *face_remap, 481 ID3DXBuffer **vertex_remap, DWORD *max_face_infl, DWORD *num_bone_combinations, 482 ID3DXBuffer **bone_combination_table, ID3DXMesh **mesh_out) 483 { 484 FIXME("iface %p, mesh_in %p, options %#x, palette_size %u, adjacency_in %p, adjacency_out %p, face_remap %p, vertex_remap %p, " 485 "max_face_infl %p, num_bone_combinations %p, bone_combination_table %p, mesh_out %p stub!\n", 486 iface, mesh_in, options, palette_size, adjacency_in, adjacency_out, face_remap, vertex_remap, 487 max_face_infl, num_bone_combinations, bone_combination_table, mesh_out); 488 489 return E_NOTIMPL; 490 } 491 492 static const struct ID3DXSkinInfoVtbl d3dx9_skin_info_vtbl = 493 { 494 d3dx9_skin_info_QueryInterface, 495 d3dx9_skin_info_AddRef, 496 d3dx9_skin_info_Release, 497 d3dx9_skin_info_SetBoneInfluence, 498 d3dx9_skin_info_SetBoneVertexInfluence, 499 d3dx9_skin_info_GetNumBoneInfluences, 500 d3dx9_skin_info_GetBoneInfluence, 501 d3dx9_skin_info_GetBoneVertexInfluence, 502 d3dx9_skin_info_GetMaxVertexInfluences, 503 d3dx9_skin_info_GetNumBones, 504 d3dx9_skin_info_FindBoneVertexInfluenceIndex, 505 d3dx9_skin_info_GetMaxFaceInfluences, 506 d3dx9_skin_info_SetMinBoneInfluence, 507 d3dx9_skin_info_GetMinBoneInfluence, 508 d3dx9_skin_info_SetBoneName, 509 d3dx9_skin_info_GetBoneName, 510 d3dx9_skin_info_SetBoneOffsetMatrix, 511 d3dx9_skin_info_GetBoneOffsetMatrix, 512 d3dx9_skin_info_Clone, 513 d3dx9_skin_info_Remap, 514 d3dx9_skin_info_SetFVF, 515 d3dx9_skin_info_SetDeclaration, 516 d3dx9_skin_info_GetFVF, 517 d3dx9_skin_info_GetDeclaration, 518 d3dx9_skin_info_UpdateSkinnedMesh, 519 d3dx9_skin_info_ConvertToBlendedMesh, 520 d3dx9_skin_info_ConvertToIndexedBlendedMesh, 521 }; 522 523 HRESULT WINAPI D3DXCreateSkinInfo(DWORD num_vertices, const D3DVERTEXELEMENT9 *declaration, 524 DWORD num_bones, ID3DXSkinInfo **skin_info) 525 { 526 HRESULT hr; 527 static const D3DVERTEXELEMENT9 empty_declaration = D3DDECL_END(); 528 struct d3dx9_skin_info *object = NULL; 529 530 TRACE("num_vertices %u, declaration %p, num_bones %u, skin_info %p.\n", 531 num_vertices, declaration, num_bones, skin_info); 532 533 if (!skin_info || !declaration) 534 return D3DERR_INVALIDCALL; 535 536 object = HeapAlloc(GetProcessHeap(), 0, sizeof(*object)); 537 if (!object) 538 return E_OUTOFMEMORY; 539 540 object->ID3DXSkinInfo_iface.lpVtbl = &d3dx9_skin_info_vtbl; 541 object->ref = 1; 542 object->num_vertices = num_vertices; 543 object->num_bones = num_bones; 544 object->vertex_declaration[0] = empty_declaration; 545 object->fvf = 0; 546 547 object->bones = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, num_bones * sizeof(*object->bones)); 548 if (!object->bones) { 549 hr = E_OUTOFMEMORY; 550 goto error; 551 } 552 553 if (FAILED(hr = d3dx9_skin_info_SetDeclaration(&object->ID3DXSkinInfo_iface, declaration))) 554 goto error; 555 556 *skin_info = &object->ID3DXSkinInfo_iface; 557 558 return D3D_OK; 559 error: 560 HeapFree(GetProcessHeap(), 0, object->bones); 561 HeapFree(GetProcessHeap(), 0, object); 562 return hr; 563 } 564 565 HRESULT WINAPI D3DXCreateSkinInfoFVF(DWORD num_vertices, DWORD fvf, DWORD num_bones, ID3DXSkinInfo **skin_info) 566 { 567 HRESULT hr; 568 D3DVERTEXELEMENT9 declaration[MAX_FVF_DECL_SIZE]; 569 570 TRACE("(%u, %x, %u, %p)\n", num_vertices, fvf, num_bones, skin_info); 571 572 hr = D3DXDeclaratorFromFVF(fvf, declaration); 573 if (FAILED(hr)) 574 return hr; 575 576 return D3DXCreateSkinInfo(num_vertices, declaration, num_bones, skin_info); 577 } 578 579 HRESULT create_dummy_skin(ID3DXSkinInfo **iface) 580 { 581 static const D3DVERTEXELEMENT9 empty_declaration = D3DDECL_END(); 582 struct d3dx9_skin_info *object = NULL; 583 584 object = HeapAlloc(GetProcessHeap(), 0, sizeof(*object)); 585 if (!object) return E_OUTOFMEMORY; 586 587 object->ID3DXSkinInfo_iface.lpVtbl = &d3dx9_skin_info_vtbl; 588 object->ref = 1; 589 object->num_vertices = 0; 590 object->num_bones = 0; 591 object->vertex_declaration[0] = empty_declaration; 592 object->fvf = 0; 593 object->bones = NULL; 594 595 *iface = &object->ID3DXSkinInfo_iface; 596 return D3D_OK; 597 } 598