Dylan Smith : d3dx9: Implement D3DXLoadMeshHierarchy for only loading frames.
Alexandre Julliard
julliard at winehq.org
Tue May 24 12:53:52 CDT 2011
Module: wine
Branch: master
Commit: bf0979f557911ef8c60e80cef745e6888096cc8c
URL: http://source.winehq.org/git/wine.git/?a=commit;h=bf0979f557911ef8c60e80cef745e6888096cc8c
Author: Dylan Smith <dylan.ah.smith at gmail.com>
Date: Fri May 20 16:24:54 2011 -0400
d3dx9: Implement D3DXLoadMeshHierarchy for only loading frames.
---
dlls/d3dx9_36/Makefile.in | 2 +-
dlls/d3dx9_36/d3dx9_36.spec | 2 +-
dlls/d3dx9_36/mesh.c | 221 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 223 insertions(+), 2 deletions(-)
diff --git a/dlls/d3dx9_36/Makefile.in b/dlls/d3dx9_36/Makefile.in
index 238939e..cba0ea7 100644
--- a/dlls/d3dx9_36/Makefile.in
+++ b/dlls/d3dx9_36/Makefile.in
@@ -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 \
diff --git a/dlls/d3dx9_36/d3dx9_36.spec b/dlls/d3dx9_36/d3dx9_36.spec
index 80f34e2..9f42937 100644
--- a/dlls/d3dx9_36/d3dx9_36.spec
+++ b/dlls/d3dx9_36/d3dx9_36.spec
@@ -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)
diff --git a/dlls/d3dx9_36/mesh.c b/dlls/d3dx9_36/mesh.c
index c5954b3..37bbaf0 100644
--- a/dlls/d3dx9_36/mesh.c
+++ b/dlls/d3dx9_36/mesh.c
@@ -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;
More information about the wine-cvs
mailing list