d3dx9: Implement D3DXLoadMeshHierarchy for only loading frames.
This commit is contained in:
parent
40dfd72bdb
commit
bf0979f557
|
@ -1,6 +1,6 @@
|
|||
MODULE = d3dx9_36.dll
|
||||
IMPORTLIB = d3dx9
|
||||
IMPORTS = d3d9 d3dcompiler ole32 gdi32 user32
|
||||
IMPORTS = d3d9 d3dcompiler dxguid d3dxof ole32 gdi32 user32
|
||||
|
||||
C_SRCS = \
|
||||
core.c \
|
||||
|
|
|
@ -174,7 +174,7 @@
|
|||
@ stub D3DXLoadMeshFromXW(ptr long ptr ptr ptr ptr ptr ptr)
|
||||
@ stub D3DXLoadMeshFromXof(ptr long ptr ptr ptr ptr ptr ptr)
|
||||
@ stub D3DXLoadMeshHierarchyFromXA(ptr long ptr ptr ptr ptr ptr)
|
||||
@ stub D3DXLoadMeshHierarchyFromXInMemory(ptr long long ptr ptr ptr ptr ptr)
|
||||
@ stdcall D3DXLoadMeshHierarchyFromXInMemory(ptr long long ptr ptr ptr ptr ptr)
|
||||
@ stub D3DXLoadMeshHierarchyFromXW(ptr long ptr ptr ptr ptr ptr)
|
||||
@ stub D3DXLoadPatchMeshFromXof(ptr long ptr ptr ptr long ptr)
|
||||
@ stub D3DXLoadPRTBufferFromFileA(ptr ptr)
|
||||
|
|
|
@ -30,6 +30,10 @@
|
|||
#include "windef.h"
|
||||
#include "wingdi.h"
|
||||
#include "d3dx9.h"
|
||||
#undef MAKE_DDHRESULT
|
||||
#include "dxfile.h"
|
||||
#include "rmxfguid.h"
|
||||
#include "rmxftmpl.h"
|
||||
#include "wine/debug.h"
|
||||
#include "wine/unicode.h"
|
||||
#include "d3dx9_36_private.h"
|
||||
|
@ -1809,6 +1813,223 @@ HRESULT WINAPI D3DXCreateMeshFVF(DWORD numfaces, DWORD numvertices, DWORD option
|
|||
}
|
||||
|
||||
|
||||
static HRESULT get_next_child(IDirectXFileData *filedata, IDirectXFileData **child, const GUID **type)
|
||||
{
|
||||
HRESULT hr;
|
||||
IDirectXFileDataReference *child_ref = NULL;
|
||||
IDirectXFileObject *child_obj = NULL;
|
||||
IDirectXFileData *child_data = NULL;
|
||||
|
||||
hr = IDirectXFileData_GetNextObject(filedata, &child_obj);
|
||||
if (FAILED(hr)) return hr;
|
||||
|
||||
hr = IDirectXFileObject_QueryInterface(child_obj, &IID_IDirectXFileDataReference, (void**)&child_ref);
|
||||
if (SUCCEEDED(hr)) {
|
||||
hr = IDirectXFileDataReference_Resolve(child_ref, &child_data);
|
||||
IDirectXFileDataReference_Release(child_ref);
|
||||
} else {
|
||||
hr = IDirectXFileObject_QueryInterface(child_obj, &IID_IDirectXFileData, (void**)&child_data);
|
||||
}
|
||||
IDirectXFileObject_Release(child_obj);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
hr = IDirectXFileData_GetType(child_data, type);
|
||||
if (FAILED(hr)) {
|
||||
IDirectXFileData_Release(child_data);
|
||||
} else {
|
||||
*child = child_data;
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT filedata_get_name(IDirectXFileData *filedata, char **name)
|
||||
{
|
||||
HRESULT hr;
|
||||
DWORD name_len;
|
||||
|
||||
hr = IDirectXFileData_GetName(filedata, NULL, &name_len);
|
||||
if (FAILED(hr)) return hr;
|
||||
|
||||
if (!name_len)
|
||||
name_len++;
|
||||
*name = HeapAlloc(GetProcessHeap(), 0, name_len);
|
||||
if (!*name) return E_OUTOFMEMORY;
|
||||
|
||||
hr = IDirectXFileObject_GetName(filedata, *name, &name_len);
|
||||
if (FAILED(hr))
|
||||
HeapFree(GetProcessHeap(), 0, name);
|
||||
if (!name_len)
|
||||
(*name)[0] = 0;
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT parse_transform_matrix(IDirectXFileData *filedata, D3DXMATRIX *transform)
|
||||
{
|
||||
HRESULT hr;
|
||||
DWORD data_size;
|
||||
BYTE *data;
|
||||
|
||||
/* template Matrix4x4 {
|
||||
* array FLOAT matrix[16];
|
||||
* }
|
||||
* template FrameTransformMatrix {
|
||||
* Matrix4x4 frameMatrix;
|
||||
* }
|
||||
*/
|
||||
|
||||
hr = IDirectXFileData_GetData(filedata, NULL, &data_size, (void**)&data);
|
||||
if (FAILED(hr)) return hr;
|
||||
|
||||
if (data_size != sizeof(D3DXMATRIX)) {
|
||||
WARN("incorrect data size (%u bytes)\n", data_size);
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
memcpy(transform, data, sizeof(D3DXMATRIX));
|
||||
|
||||
return D3D_OK;
|
||||
}
|
||||
|
||||
static HRESULT load_frame(IDirectXFileData *filedata,
|
||||
DWORD options,
|
||||
LPDIRECT3DDEVICE9 device,
|
||||
LPD3DXALLOCATEHIERARCHY alloc_hier,
|
||||
D3DXFRAME **frame_out)
|
||||
{
|
||||
HRESULT hr;
|
||||
const GUID *type;
|
||||
IDirectXFileData *child;
|
||||
char *name = NULL;
|
||||
D3DXFRAME *frame = NULL;
|
||||
D3DXFRAME **next_child;
|
||||
|
||||
hr = filedata_get_name(filedata, &name);
|
||||
if (FAILED(hr)) return hr;
|
||||
|
||||
hr = alloc_hier->lpVtbl->CreateFrame(alloc_hier, name, frame_out);
|
||||
HeapFree(GetProcessHeap(), 0, name);
|
||||
if (FAILED(hr)) return E_FAIL;
|
||||
|
||||
frame = *frame_out;
|
||||
D3DXMatrixIdentity(&frame->TransformationMatrix);
|
||||
next_child = &frame->pFrameFirstChild;
|
||||
|
||||
while (SUCCEEDED(hr = get_next_child(filedata, &child, &type)))
|
||||
{
|
||||
if (IsEqualGUID(type, &TID_D3DRMMesh)) {
|
||||
FIXME("Mesh loading not implemented\n");
|
||||
hr = E_NOTIMPL;
|
||||
} else if (IsEqualGUID(type, &TID_D3DRMFrameTransformMatrix)) {
|
||||
hr = parse_transform_matrix(child, &frame->TransformationMatrix);
|
||||
} else if (IsEqualGUID(type, &TID_D3DRMFrame)) {
|
||||
hr = load_frame(child, options, device, alloc_hier, next_child);
|
||||
if (SUCCEEDED(hr))
|
||||
next_child = &(*next_child)->pFrameSibling;
|
||||
}
|
||||
if (FAILED(hr)) break;
|
||||
}
|
||||
if (hr == DXFILEERR_NOMOREOBJECTS)
|
||||
hr = D3D_OK;
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT WINAPI D3DXLoadMeshHierarchyFromXInMemory(LPCVOID memory,
|
||||
DWORD memory_size,
|
||||
DWORD options,
|
||||
LPDIRECT3DDEVICE9 device,
|
||||
LPD3DXALLOCATEHIERARCHY alloc_hier,
|
||||
LPD3DXLOADUSERDATA load_user_data,
|
||||
LPD3DXFRAME *frame_hierarchy,
|
||||
LPD3DXANIMATIONCONTROLLER *anim_controller)
|
||||
{
|
||||
HRESULT hr;
|
||||
IDirectXFile *dxfile = NULL;
|
||||
IDirectXFileEnumObject *enumobj = NULL;
|
||||
IDirectXFileData *filedata = NULL;
|
||||
DXFILELOADMEMORY source;
|
||||
D3DXFRAME *first_frame = NULL;
|
||||
D3DXFRAME **next_frame = &first_frame;
|
||||
|
||||
TRACE("(%p, %u, %x, %p, %p, %p, %p, %p)\n", memory, memory_size, options,
|
||||
device, alloc_hier, load_user_data, frame_hierarchy, anim_controller);
|
||||
|
||||
if (!memory || !memory_size || !device || !frame_hierarchy || !alloc_hier)
|
||||
return D3DERR_INVALIDCALL;
|
||||
if (load_user_data || anim_controller) {
|
||||
if (load_user_data)
|
||||
FIXME("Loading user data not implemented\n");
|
||||
if (anim_controller)
|
||||
FIXME("Animation controller creation not implemented\n");
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
hr = DirectXFileCreate(&dxfile);
|
||||
if (FAILED(hr)) goto cleanup;
|
||||
|
||||
hr = IDirectXFile_RegisterTemplates(dxfile, D3DRM_XTEMPLATES, D3DRM_XTEMPLATE_BYTES);
|
||||
if (FAILED(hr)) goto cleanup;
|
||||
|
||||
source.lpMemory = (void*)memory;
|
||||
source.dSize = memory_size;
|
||||
hr = IDirectXFile_CreateEnumObject(dxfile, &source, DXFILELOAD_FROMMEMORY, &enumobj);
|
||||
if (FAILED(hr)) goto cleanup;
|
||||
|
||||
while (SUCCEEDED(hr = IDirectXFileEnumObject_GetNextDataObject(enumobj, &filedata)))
|
||||
{
|
||||
const GUID *guid = NULL;
|
||||
|
||||
hr = IDirectXFileData_GetType(filedata, &guid);
|
||||
if (SUCCEEDED(hr)) {
|
||||
if (IsEqualGUID(guid, &TID_D3DRMMesh)) {
|
||||
FIXME("Mesh loading not implemented\n");
|
||||
hr = E_NOTIMPL;
|
||||
goto cleanup;
|
||||
} else if (IsEqualGUID(guid, &TID_D3DRMFrame)) {
|
||||
hr = load_frame(filedata, options, device, alloc_hier, next_frame);
|
||||
if (FAILED(hr)) goto cleanup;
|
||||
}
|
||||
while (*next_frame)
|
||||
next_frame = &(*next_frame)->pFrameSibling;
|
||||
}
|
||||
|
||||
IDirectXFileData_Release(filedata);
|
||||
filedata = NULL;
|
||||
if (FAILED(hr))
|
||||
goto cleanup;
|
||||
}
|
||||
if (hr != DXFILEERR_NOMOREOBJECTS)
|
||||
goto cleanup;
|
||||
|
||||
if (!first_frame) {
|
||||
hr = E_FAIL;
|
||||
} else if (first_frame->pFrameSibling) {
|
||||
D3DXFRAME *root_frame = NULL;
|
||||
hr = alloc_hier->lpVtbl->CreateFrame(alloc_hier, NULL, &root_frame);
|
||||
if (FAILED(hr)) {
|
||||
hr = E_FAIL;
|
||||
goto cleanup;
|
||||
}
|
||||
D3DXMatrixIdentity(&root_frame->TransformationMatrix);
|
||||
root_frame->pFrameFirstChild = first_frame;
|
||||
*frame_hierarchy = root_frame;
|
||||
hr = D3D_OK;
|
||||
} else {
|
||||
*frame_hierarchy = first_frame;
|
||||
hr = D3D_OK;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
if (FAILED(hr) && first_frame) D3DXFrameDestroy(first_frame, alloc_hier);
|
||||
if (filedata) IDirectXFileData_Release(filedata);
|
||||
if (enumobj) IDirectXFileEnumObject_Release(enumobj);
|
||||
if (dxfile) IDirectXFile_Release(dxfile);
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT WINAPI D3DXFrameDestroy(LPD3DXFRAME frame, LPD3DXALLOCATEHIERARCHY alloc_hier)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
|
Loading…
Reference in New Issue