From 8782fdb62e6fa1287fe37550d7cc2985a067cc1d Mon Sep 17 00:00:00 2001 From: Anders Jenbo Date: Sun, 25 May 2025 02:24:32 +0200 Subject: [PATCH] Implement 3D geometry rendering (#162) --- miniwin/miniwin/include/miniwin_d3drm.h | 2 + .../src/include/miniwin_d3drmframe_p.h | 1 + .../miniwin/src/include/miniwin_d3drmmesh_p.h | 2 + .../src/include/miniwin_d3drmviewport_p.h | 2 +- miniwin/miniwin/src/miniwin_d3drmframe.cpp | 14 +++ miniwin/miniwin/src/miniwin_d3drmmesh.cpp | 19 ++++ miniwin/miniwin/src/miniwin_d3drmviewport.cpp | 93 ++++++++++++++++--- 7 files changed, 120 insertions(+), 13 deletions(-) diff --git a/miniwin/miniwin/include/miniwin_d3drm.h b/miniwin/miniwin/include/miniwin_d3drm.h index 8fe98156..3f80b9cb 100644 --- a/miniwin/miniwin/include/miniwin_d3drm.h +++ b/miniwin/miniwin/include/miniwin_d3drm.h @@ -101,6 +101,7 @@ typedef D3DRMPROJECTIONTYPE* LPD3DRMPROJECTIONTYPE; // --- GUIDs --- DEFINE_GUID(IID_IDirect3DRM2, 0x4516ecc8, 0x8f20, 0x11d0, 0x9b, 0x6d, 0x00, 0x00, 0xc0, 0x78, 0x1b, 0xc3); DEFINE_GUID(IID_IDirect3DRMWinDevice, 0xc5016cc0, 0xd273, 0x11ce, 0xac, 0x48, 0x00, 0x00, 0xc0, 0x38, 0x25, 0xa1); +DEFINE_GUID(IID_IDirect3DRMFrame, 0xeb16cb03, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); DEFINE_GUID(IID_IDirect3DRMMesh, 0xa3a80d01, 0x6e12, 0x11cf, 0xac, 0x4a, 0x00, 0x00, 0xc0, 0x38, 0x25, 0xa1); DEFINE_GUID(IID_IDirect3DRMMeshBuilder, 0xa3a80d02, 0x6e12, 0x11cf, 0xac, 0x4a, 0x00, 0x00, 0xc0, 0x38, 0x25, 0xa1); DEFINE_GUID(IID_IDirect3DRMTexture2, 0x120f30c0, 0x1629, 0x11d0, 0x94, 0x1c, 0x00, 0x80, 0xc8, 0x0c, 0xfa, 0x7b); @@ -185,6 +186,7 @@ struct IDirect3DRMMesh : public IDirect3DRMVisual { DWORD* dataSize, DWORD* data ) = 0; + virtual DWORD GetGroupCount() = 0; virtual HRESULT SetGroupColor(DWORD groupIndex, D3DCOLOR color) = 0; virtual HRESULT SetGroupColorRGB(DWORD groupIndex, float r, float g, float b) = 0; virtual HRESULT SetGroupTexture(DWORD groupIndex, IDirect3DRMTexture* texture) = 0; diff --git a/miniwin/miniwin/src/include/miniwin_d3drmframe_p.h b/miniwin/miniwin/src/include/miniwin_d3drmframe_p.h index 1860a2c6..29ecd434 100644 --- a/miniwin/miniwin/src/include/miniwin_d3drmframe_p.h +++ b/miniwin/miniwin/src/include/miniwin_d3drmframe_p.h @@ -6,6 +6,7 @@ struct Direct3DRMFrameImpl : public Direct3DRMObjectBase { Direct3DRMFrameImpl(); ~Direct3DRMFrameImpl() override; + HRESULT QueryInterface(const GUID& riid, void** ppvObject) override; HRESULT AddChild(IDirect3DRMFrame* child) override; HRESULT DeleteChild(IDirect3DRMFrame* child) override; HRESULT SetSceneBackgroundRGB(float r, float g, float b) override; diff --git a/miniwin/miniwin/src/include/miniwin_d3drmmesh_p.h b/miniwin/miniwin/src/include/miniwin_d3drmmesh_p.h index a56a8792..f0063904 100644 --- a/miniwin/miniwin/src/include/miniwin_d3drmmesh_p.h +++ b/miniwin/miniwin/src/include/miniwin_d3drmmesh_p.h @@ -64,6 +64,7 @@ struct MeshGroup { }; struct Direct3DRMMeshImpl : public Direct3DRMObjectBase { + HRESULT QueryInterface(const GUID& riid, void** ppvObject) override; HRESULT Clone(int flags, GUID iid, void** object) override; HRESULT AddGroup(int vertexCount, int faceCount, int vertexPerFace, DWORD* faceBuffer, D3DRMGROUPINDEX* groupIndex) override; @@ -75,6 +76,7 @@ struct Direct3DRMMeshImpl : public Direct3DRMObjectBase { DWORD* dataSize, DWORD* data ) override; + DWORD GetGroupCount() override; HRESULT SetGroupColor(DWORD groupIndex, D3DCOLOR color) override; HRESULT SetGroupColorRGB(DWORD groupIndex, float r, float g, float b) override; D3DCOLOR GetGroupColor(D3DRMGROUPINDEX index) override; diff --git a/miniwin/miniwin/src/include/miniwin_d3drmviewport_p.h b/miniwin/miniwin/src/include/miniwin_d3drmviewport_p.h index ca811eb0..59870494 100644 --- a/miniwin/miniwin/src/include/miniwin_d3drmviewport_p.h +++ b/miniwin/miniwin/src/include/miniwin_d3drmviewport_p.h @@ -38,7 +38,7 @@ struct Direct3DRMViewportImpl : public Direct3DRMObjectBase HRESULT InverseTransform(D3DVECTOR* world, D3DRMVECTOR4D* screen) override; HRESULT Pick(float x, float y, LPDIRECT3DRMPICKEDARRAY* pickedArray) override; void CloseDevice(); - void CollectSceneData(IDirect3DRMFrame* group); + HRESULT CollectSceneData(IDirect3DRMFrame* group); void PushVertices(const PositionColorVertex* vertices, size_t count); private: diff --git a/miniwin/miniwin/src/miniwin_d3drmframe.cpp b/miniwin/miniwin/src/miniwin_d3drmframe.cpp index 948ed96d..abb0c64f 100644 --- a/miniwin/miniwin/src/miniwin_d3drmframe.cpp +++ b/miniwin/miniwin/src/miniwin_d3drmframe.cpp @@ -21,6 +21,20 @@ Direct3DRMFrameImpl::~Direct3DRMFrameImpl() } } +HRESULT Direct3DRMFrameImpl::QueryInterface(const GUID& riid, void** ppvObject) +{ + if (SDL_memcmp(&riid, &IID_IDirect3DRMFrame, sizeof(GUID)) == 0) { + this->IUnknown::AddRef(); + *ppvObject = static_cast(this); + return S_OK; + } + if (SDL_memcmp(&riid, &IID_IDirect3DRMMesh, sizeof(GUID)) == 0) { + return E_NOINTERFACE; + } + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Direct3DRMFrameImpl does not implement guid"); + return E_NOINTERFACE; +} + HRESULT Direct3DRMFrameImpl::AddChild(IDirect3DRMFrame* child) { return m_children->AddElement(child); diff --git a/miniwin/miniwin/src/miniwin_d3drmmesh.cpp b/miniwin/miniwin/src/miniwin_d3drmmesh.cpp index ceae38d2..1a8fc7a7 100644 --- a/miniwin/miniwin/src/miniwin_d3drmmesh.cpp +++ b/miniwin/miniwin/src/miniwin_d3drmmesh.cpp @@ -3,6 +3,20 @@ #include +HRESULT Direct3DRMMeshImpl::QueryInterface(const GUID& riid, void** ppvObject) +{ + if (SDL_memcmp(&riid, &IID_IDirect3DRMMesh, sizeof(GUID)) == 0) { + this->IUnknown::AddRef(); + *ppvObject = static_cast(this); + return S_OK; + } + if (SDL_memcmp(&riid, &IID_IDirect3DRMFrame, sizeof(GUID)) == 0) { + return E_NOINTERFACE; + } + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Direct3DRMMeshImpl does not implement guid"); + return E_NOINTERFACE; +} + HRESULT Direct3DRMMeshImpl::Clone(int flags, GUID iid, void** object) { if (!object || SDL_memcmp(&iid, &IID_IDirect3DRMMesh, sizeof(GUID)) != 0) { @@ -86,6 +100,11 @@ HRESULT Direct3DRMMeshImpl::GetGroup( return DD_OK; } +DWORD Direct3DRMMeshImpl::GetGroupCount() +{ + return m_groups.size(); +} + HRESULT Direct3DRMMeshImpl::SetGroupColor(DWORD groupIndex, D3DCOLOR color) { if (groupIndex >= m_groups.size()) { diff --git a/miniwin/miniwin/src/miniwin_d3drmviewport.cpp b/miniwin/miniwin/src/miniwin_d3drmviewport.cpp index 0f000acf..fea07333 100644 --- a/miniwin/miniwin/src/miniwin_d3drmviewport.cpp +++ b/miniwin/miniwin/src/miniwin_d3drmviewport.cpp @@ -4,6 +4,7 @@ #include "miniwin_p.h" #include +#include Direct3DRMViewportImpl::Direct3DRMViewportImpl( DWORD width, @@ -29,14 +30,73 @@ Direct3DRMViewportImpl::~Direct3DRMViewportImpl() FreeDeviceResources(); } -void Direct3DRMViewportImpl::CollectSceneData(IDirect3DRMFrame* group) +HRESULT Direct3DRMViewportImpl::CollectSceneData(IDirect3DRMFrame* group) { - m_backgroundColor = static_cast(group)->m_backgroundColor; + MINIWIN_NOT_IMPLEMENTED(); // Lights, textures, materials - std::vector vertices = - {{-1, -1, 0, 0, 255, 0, 255}, {1, -1, 0, 0, 0, 255, 255}, {0, 1, 0, 255, 0, 0, 128}}; + std::vector verts; + std::function recurseFrame; - PushVertices(vertices.data(), vertices.size()); + recurseFrame = [&](IDirect3DRMFrame* frame) { + IDirect3DRMVisualArray* va = nullptr; + if (SUCCEEDED(frame->GetVisuals(&va)) && va) { + DWORD n = va->GetSize(); + for (DWORD i = 0; i < n; ++i) { + IDirect3DRMVisual* vis = nullptr; + va->GetElement(i, &vis); + if (!vis) { + continue; + } + + // Pull geometry from meshes + IDirect3DRMMesh* mesh = nullptr; + if (SUCCEEDED(vis->QueryInterface(IID_IDirect3DRMMesh, (void**) &mesh)) && mesh) { + DWORD groupCount = mesh->GetGroupCount(); + for (DWORD gi = 0; gi < groupCount; ++gi) { + DWORD vtxCount, faceCount, vpf, dataSize; + mesh->GetGroup(gi, &vtxCount, &faceCount, &vpf, &dataSize, nullptr); + std::vector d3dVerts(vtxCount); + std::vector faces(faceCount * vpf); + mesh->GetVertices(gi, 0, vtxCount, d3dVerts.data()); + mesh->GetGroup(gi, &vtxCount, &faceCount, &vpf, nullptr, faces.data()); + D3DCOLOR color = mesh->GetGroupColor(gi); + + for (DWORD fi = 0; fi < faceCount; ++fi) { + for (int idx = 0; idx < vpf; ++idx) { + auto& dv = d3dVerts[faces[fi * vpf + idx]]; + PositionColorVertex vtx; + vtx.x = dv.position.x; + vtx.y = dv.position.y; + vtx.z = dv.position.z; + vtx.a = (color >> 24) & 0xFF; + vtx.r = (color >> 16) & 0xFF; + vtx.g = (color >> 8) & 0xFF; + vtx.b = (color >> 0) & 0xFF; + verts.push_back(vtx); + } + } + } + mesh->Release(); + } + + // Recurse over sub-frames + IDirect3DRMFrame* childFrame = nullptr; + if (SUCCEEDED(vis->QueryInterface(IID_IDirect3DRMFrame, (void**) &childFrame)) && childFrame) { + recurseFrame(childFrame); + childFrame->Release(); + } + + vis->Release(); + } + va->Release(); + } + }; + + recurseFrame(group); + + PushVertices(verts.data(), verts.size()); + + return D3DRM_OK; } void Direct3DRMViewportImpl::PushVertices(const PositionColorVertex* vertices, size_t count) @@ -53,8 +113,10 @@ void Direct3DRMViewportImpl::PushVertices(const PositionColorVertex* vertices, s } m_vertexCount = count; + if (!count) { + return; + } - MINIWIN_NOT_IMPLEMENTED(); SDL_GPUTransferBufferCreateInfo transferCreateInfo = {}; transferCreateInfo.usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD; transferCreateInfo.size = static_cast(sizeof(PositionColorVertex) * m_vertexCount); @@ -92,7 +154,10 @@ HRESULT Direct3DRMViewportImpl::Render(IDirect3DRMFrame* group) return DDERR_GENERIC; } - CollectSceneData(group); + HRESULT success = CollectSceneData(group); + if (success != DD_OK) { + return success; + } SDL_GPUCommandBuffer* cmdbuf = SDL_AcquireGPUCommandBuffer(m_device); if (cmdbuf == NULL) { @@ -107,11 +172,15 @@ HRESULT Direct3DRMViewportImpl::Render(IDirect3DRMFrame* group) colorTargetInfo.load_op = SDL_GPU_LOADOP_CLEAR; SDL_GPURenderPass* renderPass = SDL_BeginGPURenderPass(cmdbuf, &colorTargetInfo, 1, NULL); SDL_BindGPUGraphicsPipeline(renderPass, m_pipeline); - SDL_GPUBufferBinding vertexBufferBinding = {}; - vertexBufferBinding.buffer = m_vertexBuffer; - vertexBufferBinding.offset = 0; - SDL_BindGPUVertexBuffers(renderPass, 0, &vertexBufferBinding, 1); - SDL_DrawGPUPrimitives(renderPass, m_vertexCount, 1, 0, 0); + + if (m_vertexCount) { + SDL_GPUBufferBinding vertexBufferBinding = {}; + vertexBufferBinding.buffer = m_vertexBuffer; + vertexBufferBinding.offset = 0; + SDL_BindGPUVertexBuffers(renderPass, 0, &vertexBufferBinding, 1); + SDL_DrawGPUPrimitives(renderPass, m_vertexCount, 1, 0, 0); + } + SDL_EndGPURenderPass(renderPass); // Download rendered image