diff --git a/miniwin/miniwin/include/miniwin_d3drm.h b/miniwin/miniwin/include/miniwin_d3drm.h index 8cfb2f3b..e8b33522 100644 --- a/miniwin/miniwin/include/miniwin_d3drm.h +++ b/miniwin/miniwin/include/miniwin_d3drm.h @@ -174,29 +174,29 @@ struct IDirect3DRMMesh : public IDirect3DRMVisual { int vertexCount, int faceCount, int vertexPerFace, - void* faceBuffer, + DWORD* faceBuffer, D3DRMGROUPINDEX* groupIndex ) = 0; virtual HRESULT GetGroup( - int groupIndex, + DWORD groupIndex, DWORD* vertexCount, DWORD* faceCount, DWORD* vertexPerFace, DWORD* dataSize, DWORD* data ) = 0; - virtual HRESULT SetGroupColor(int groupIndex, D3DCOLOR color) = 0; - virtual HRESULT SetGroupColorRGB(int groupIndex, float r, float g, float b) = 0; - virtual HRESULT SetGroupTexture(int groupIndex, IDirect3DRMTexture* texture) = 0; - virtual HRESULT SetGroupMaterial(int groupIndex, IDirect3DRMMaterial* material) = 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; + virtual HRESULT SetGroupMaterial(DWORD groupIndex, IDirect3DRMMaterial* material) = 0; virtual HRESULT SetGroupMapping(D3DRMGROUPINDEX groupIndex, D3DRMMAPPING mapping) = 0; - virtual HRESULT SetGroupQuality(int groupIndex, D3DRMRENDERQUALITY quality) = 0; - virtual HRESULT SetVertices(int groupIndex, int offset, int count, D3DRMVERTEX* vertices) = 0; - virtual HRESULT GetGroupTexture(int groupIndex, LPDIRECT3DRMTEXTURE* texture) = 0; - virtual D3DRMMAPPING GetGroupMapping(int groupIndex) = 0; - virtual D3DRMRENDERQUALITY GetGroupQuality(int groupIndex) = 0; + virtual HRESULT SetGroupQuality(DWORD groupIndex, D3DRMRENDERQUALITY quality) = 0; + virtual HRESULT SetVertices(DWORD groupIndex, int offset, int count, D3DRMVERTEX* vertices) = 0; + virtual HRESULT GetGroupTexture(DWORD groupIndex, LPDIRECT3DRMTEXTURE* texture) = 0; + virtual D3DRMMAPPING GetGroupMapping(DWORD groupIndex) = 0; + virtual D3DRMRENDERQUALITY GetGroupQuality(DWORD groupIndex) = 0; virtual D3DCOLOR GetGroupColor(D3DRMGROUPINDEX index) = 0; - virtual HRESULT GetVertices(int groupIndex, int startIndex, int count, D3DRMVERTEX* vertices) = 0; + virtual HRESULT GetVertices(DWORD groupIndex, int startIndex, int count, D3DRMVERTEX* vertices) = 0; }; struct IDirect3DRMLight : public IDirect3DRMObject { diff --git a/miniwin/miniwin/src/include/miniwin_d3drmmesh_p.h b/miniwin/miniwin/src/include/miniwin_d3drmmesh_p.h index 0e1f76cb..a56a8792 100644 --- a/miniwin/miniwin/src/include/miniwin_d3drmmesh_p.h +++ b/miniwin/miniwin/src/include/miniwin_d3drmmesh_p.h @@ -2,33 +2,93 @@ #include "miniwin_d3drmobject_p.h" +#include +#include + +struct MeshGroup { + D3DCOLOR color = 0xFFFFFFFF; + IDirect3DRMTexture* texture = nullptr; + IDirect3DRMMaterial* material = nullptr; + D3DRMRENDERQUALITY quality = D3DRMRENDER_GOURAUD; + int vertexPerFace = 0; + std::vector vertices; + std::vector faces; + + MeshGroup() = default; + + MeshGroup(const MeshGroup& other) + : color(other.color), texture(other.texture), material(other.material), quality(other.quality), + vertexPerFace(other.vertexPerFace), vertices(std::move(other.vertices)), faces(std::move(other.faces)) + { + if (texture) { + texture->AddRef(); + } + if (material) { + material->AddRef(); + } + } + + // Move constructor + MeshGroup(MeshGroup&& other) noexcept + : color(other.color), texture(other.texture), material(other.material), quality(other.quality), + vertexPerFace(other.vertexPerFace), vertices(other.vertices), faces(other.faces) + { + other.texture = nullptr; + other.material = nullptr; + } + + // Move assignment + MeshGroup& operator=(MeshGroup&& other) noexcept + { + color = other.color; + texture = other.texture; + material = other.material; + quality = other.quality; + vertexPerFace = other.vertexPerFace; + vertices = std::move(other.vertices); + faces = std::move(other.faces); + other.texture = nullptr; + other.material = nullptr; + return *this; + } + + ~MeshGroup() + { + if (texture) { + texture->Release(); + } + if (material) { + material->Release(); + } + } +}; + struct Direct3DRMMeshImpl : public Direct3DRMObjectBase { HRESULT Clone(int flags, GUID iid, void** object) override; - HRESULT GetBox(D3DRMBOX* box) override; - HRESULT AddGroup(int vertexCount, int faceCount, int vertexPerFace, void* faceBuffer, D3DRMGROUPINDEX* groupIndex) + HRESULT AddGroup(int vertexCount, int faceCount, int vertexPerFace, DWORD* faceBuffer, D3DRMGROUPINDEX* groupIndex) override; HRESULT GetGroup( - int groupIndex, + DWORD groupIndex, DWORD* vertexCount, DWORD* faceCount, DWORD* vertexPerFace, DWORD* dataSize, DWORD* data ) override; - HRESULT SetGroupColor(int groupIndex, D3DCOLOR color) override; - HRESULT SetGroupColorRGB(int groupIndex, float r, float g, float b) override; - HRESULT SetGroupMaterial(int groupIndex, IDirect3DRMMaterial* material) override; + HRESULT SetGroupColor(DWORD groupIndex, D3DCOLOR color) override; + HRESULT SetGroupColorRGB(DWORD groupIndex, float r, float g, float b) override; + D3DCOLOR GetGroupColor(D3DRMGROUPINDEX index) override; + HRESULT SetGroupMaterial(DWORD groupIndex, IDirect3DRMMaterial* material) override; + HRESULT SetGroupTexture(DWORD groupIndex, IDirect3DRMTexture* texture) override; + HRESULT GetGroupTexture(DWORD groupIndex, LPDIRECT3DRMTEXTURE* texture) override; HRESULT SetGroupMapping(D3DRMGROUPINDEX groupIndex, D3DRMMAPPING mapping) override; - HRESULT SetGroupQuality(int groupIndex, D3DRMRENDERQUALITY quality) override; - HRESULT SetVertices(int groupIndex, int offset, int count, D3DRMVERTEX* vertices) override; - HRESULT SetGroupTexture(int groupIndex, IDirect3DRMTexture* texture) override; - ; - HRESULT GetGroupTexture(int groupIndex, LPDIRECT3DRMTEXTURE* texture) override; - D3DRMMAPPING GetGroupMapping(int groupIndex) override; - D3DRMRENDERQUALITY GetGroupQuality(int groupIndex) override; - HRESULT GetGroupColor(D3DRMGROUPINDEX index) override; - HRESULT GetVertices(int groupIndex, int startIndex, int count, D3DRMVERTEX* vertices) override; + D3DRMMAPPING GetGroupMapping(DWORD groupIndex) override; + HRESULT SetGroupQuality(DWORD groupIndex, D3DRMRENDERQUALITY quality) override; + D3DRMRENDERQUALITY GetGroupQuality(DWORD groupIndex) override; + HRESULT SetVertices(DWORD groupIndex, int offset, int count, D3DRMVERTEX* vertices) override; + HRESULT GetVertices(DWORD groupIndex, int startIndex, int count, D3DRMVERTEX* vertices) override; + HRESULT GetBox(D3DRMBOX* box) override; private: - IDirect3DRMTexture* m_groupTexture = nullptr; + std::vector m_groups; }; diff --git a/miniwin/miniwin/src/miniwin_d3drmmesh.cpp b/miniwin/miniwin/src/miniwin_d3drmmesh.cpp index 244ec0b2..ceae38d2 100644 --- a/miniwin/miniwin/src/miniwin_d3drmmesh.cpp +++ b/miniwin/miniwin/src/miniwin_d3drmmesh.cpp @@ -1,19 +1,27 @@ #include "miniwin_d3drmmesh_p.h" #include "miniwin_p.h" +#include + HRESULT Direct3DRMMeshImpl::Clone(int flags, GUID iid, void** object) { - if (SDL_memcmp(&iid, &IID_IDirect3DRMMesh, sizeof(GUID)) == 0) { - *object = static_cast(new Direct3DRMMeshImpl); - return DD_OK; + if (!object || SDL_memcmp(&iid, &IID_IDirect3DRMMesh, sizeof(GUID)) != 0) { + return DDERR_INVALIDPARAMS; } - return DDERR_GENERIC; -} + auto* clone = new Direct3DRMMeshImpl(*this); -HRESULT Direct3DRMMeshImpl::GetBox(D3DRMBOX* box) -{ - MINIWIN_NOT_IMPLEMENTED(); + for (auto& group : clone->m_groups) { + // Reusing the same texture and material on the new mesh instead of cloning them might not be correct + if (group.texture) { + group.texture->AddRef(); + } + if (group.material) { + group.material->AddRef(); + } + } + + *object = static_cast(clone); return DD_OK; } @@ -21,16 +29,31 @@ HRESULT Direct3DRMMeshImpl::AddGroup( int vertexCount, int faceCount, int vertexPerFace, - void* faceBuffer, + DWORD* faceBuffer, D3DRMGROUPINDEX* groupIndex ) { - MINIWIN_NOT_IMPLEMENTED(); + if (faceCount < 0 || vertexPerFace < 0 || !faceBuffer) { + return DDERR_INVALIDPARAMS; + } + + int newIndex = m_groups.size(); + if (groupIndex) { + *groupIndex = newIndex; + } + + MeshGroup group; + group.vertexPerFace = vertexPerFace; + + DWORD* src = faceBuffer; + group.faces.assign(src, src + faceCount * vertexPerFace); + + m_groups.push_back(std::move(group)); return DD_OK; } HRESULT Direct3DRMMeshImpl::GetGroup( - int groupIndex, + DWORD groupIndex, DWORD* vertexCount, DWORD* faceCount, DWORD* vertexPerFace, @@ -38,85 +61,179 @@ HRESULT Direct3DRMMeshImpl::GetGroup( DWORD* data ) { - MINIWIN_NOT_IMPLEMENTED(); + if (groupIndex >= m_groups.size()) { + return DDERR_INVALIDPARAMS; + } + + const auto& group = m_groups[groupIndex]; + + if (vertexCount) { + *vertexCount = static_cast(group.vertices.size()); + } + if (faceCount) { + *faceCount = static_cast(group.faces.size() / group.vertexPerFace); + } + if (vertexPerFace) { + *vertexPerFace = static_cast(group.vertexPerFace); + } + if (dataSize) { + *dataSize = static_cast(group.faces.size()); + } + if (data) { + std::copy(group.faces.begin(), group.faces.end(), reinterpret_cast(data)); + } + return DD_OK; } -HRESULT Direct3DRMMeshImpl::SetGroupColor(int groupIndex, D3DCOLOR color) +HRESULT Direct3DRMMeshImpl::SetGroupColor(DWORD groupIndex, D3DCOLOR color) { - MINIWIN_NOT_IMPLEMENTED(); + if (groupIndex >= m_groups.size()) { + return DDERR_INVALIDPARAMS; + } + + m_groups[groupIndex].color = color; return DD_OK; } -HRESULT Direct3DRMMeshImpl::SetGroupColorRGB(int groupIndex, float r, float g, float b) +HRESULT Direct3DRMMeshImpl::SetGroupColorRGB(DWORD groupIndex, float r, float g, float b) { - MINIWIN_NOT_IMPLEMENTED(); + if (groupIndex >= m_groups.size()) { + return DDERR_INVALIDPARAMS; + } + + D3DCOLOR color = (0xFF << 24) | (static_cast(r * 255.0f) << 16) | (static_cast(g * 255.0f) << 8) | + (static_cast(b * 255.0f)); + + m_groups[groupIndex].color = color; return DD_OK; } -HRESULT Direct3DRMMeshImpl::SetGroupMaterial(int groupIndex, IDirect3DRMMaterial* material) +D3DCOLOR Direct3DRMMeshImpl::GetGroupColor(D3DRMGROUPINDEX index) { - MINIWIN_NOT_IMPLEMENTED(); + if (index < 0 || index >= static_cast(m_groups.size())) { + return 0xFFFFFFFF; + } + return m_groups[index].color; +} + +HRESULT Direct3DRMMeshImpl::SetGroupMaterial(DWORD groupIndex, IDirect3DRMMaterial* material) +{ + if (groupIndex >= m_groups.size()) { + return DDERR_INVALIDPARAMS; + } + + material->AddRef(); + m_groups[groupIndex].material = material; + return DD_OK; +} + +HRESULT Direct3DRMMeshImpl::SetGroupTexture(DWORD groupIndex, IDirect3DRMTexture* texture) +{ + if (groupIndex >= m_groups.size()) { + return DDERR_INVALIDPARAMS; + } + + texture->AddRef(); + m_groups[groupIndex].texture = texture; + return DD_OK; +} + +HRESULT Direct3DRMMeshImpl::GetGroupTexture(DWORD groupIndex, LPDIRECT3DRMTEXTURE* texture) +{ + if (groupIndex >= m_groups.size()) { + return DDERR_GENERIC; + } + + auto& group = m_groups[groupIndex]; + if (!group.texture) { + return DDERR_GENERIC; + } + + group.texture->AddRef(); + *texture = group.texture; return DD_OK; } HRESULT Direct3DRMMeshImpl::SetGroupMapping(D3DRMGROUPINDEX groupIndex, D3DRMMAPPING mapping) { - MINIWIN_NOT_IMPLEMENTED(); return DD_OK; } -HRESULT Direct3DRMMeshImpl::SetGroupQuality(int groupIndex, D3DRMRENDERQUALITY quality) +D3DRMMAPPING Direct3DRMMeshImpl::GetGroupMapping(DWORD groupIndex) { - MINIWIN_NOT_IMPLEMENTED(); - return DD_OK; -} - -HRESULT Direct3DRMMeshImpl::SetVertices(int groupIndex, int offset, int count, D3DRMVERTEX* vertices) -{ - MINIWIN_NOT_IMPLEMENTED(); - return DD_OK; -} - -HRESULT Direct3DRMMeshImpl::SetGroupTexture(int groupIndex, IDirect3DRMTexture* texture) -{ - MINIWIN_NOT_IMPLEMENTED(); - m_groupTexture = texture; - return DD_OK; -} - -HRESULT Direct3DRMMeshImpl::GetGroupTexture(int groupIndex, LPDIRECT3DRMTEXTURE* texture) -{ - MINIWIN_NOT_IMPLEMENTED(); - if (!m_groupTexture) { - return DDERR_GENERIC; - } - - m_groupTexture->AddRef(); - *texture = m_groupTexture; - return DD_OK; -} - -D3DRMMAPPING Direct3DRMMeshImpl::GetGroupMapping(int groupIndex) -{ - MINIWIN_NOT_IMPLEMENTED(); return D3DRMMAP_PERSPCORRECT; } -D3DRMRENDERQUALITY Direct3DRMMeshImpl::GetGroupQuality(int groupIndex) +HRESULT Direct3DRMMeshImpl::SetGroupQuality(DWORD groupIndex, D3DRMRENDERQUALITY quality) { - MINIWIN_NOT_IMPLEMENTED(); - return D3DRMRENDER_GOURAUD; -} + if (groupIndex >= m_groups.size()) { + return DDERR_INVALIDPARAMS; + } -HRESULT Direct3DRMMeshImpl::GetGroupColor(D3DRMGROUPINDEX index) -{ - MINIWIN_NOT_IMPLEMENTED(); + m_groups[groupIndex].quality = quality; return DD_OK; } -HRESULT Direct3DRMMeshImpl::GetVertices(int groupIndex, int startIndex, int count, D3DRMVERTEX* vertices) +D3DRMRENDERQUALITY Direct3DRMMeshImpl::GetGroupQuality(DWORD groupIndex) { - MINIWIN_NOT_IMPLEMENTED(); + if (groupIndex >= m_groups.size()) { + return D3DRMRENDER_GOURAUD; + } + + return m_groups[groupIndex].quality; +} + +HRESULT Direct3DRMMeshImpl::SetVertices(DWORD groupIndex, int offset, int count, D3DRMVERTEX* vertices) +{ + if (count <= 0 || offset < 0 || groupIndex < 0 || groupIndex >= static_cast(m_groups.size())) { + return DDERR_INVALIDPARAMS; + } + + auto& vertList = m_groups[groupIndex].vertices; + + if (offset + count > static_cast(vertList.size())) { + vertList.resize(offset + count); + } + + std::copy(vertices, vertices + count, vertList.begin() + offset); + return DD_OK; +} + +HRESULT Direct3DRMMeshImpl::GetVertices(DWORD groupIndex, int startIndex, int count, D3DRMVERTEX* vertices) +{ + if (count <= 0 || startIndex < 0 || groupIndex < 0 || groupIndex >= static_cast(m_groups.size())) { + return DDERR_INVALIDPARAMS; + } + + const auto& vertList = m_groups[groupIndex].vertices; + + if (startIndex + count > static_cast(vertList.size())) { + return DDERR_INVALIDPARAMS; + } + + std::copy(vertList.begin() + startIndex, vertList.begin() + startIndex + count, vertices); + return DD_OK; +} + +/** + * @todo Maybe a good idea to cache this + */ +HRESULT Direct3DRMMeshImpl::GetBox(D3DRMBOX* box) +{ + box->min.x = box->min.y = box->min.z = std::numeric_limits::max(); + box->max.x = box->max.y = box->max.z = std::numeric_limits::min(); + + for (const auto& group : m_groups) { + for (const D3DRMVERTEX& v : group.vertices) { + box->min.x = std::min(box->min.x, v.position.x); + box->min.y = std::min(box->min.y, v.position.y); + box->min.z = std::min(box->min.z, v.position.z); + box->max.x = std::max(box->max.x, v.position.x); + box->max.y = std::max(box->max.y, v.position.y); + box->max.z = std::max(box->max.z, v.position.z); + } + } + return DD_OK; }