mirror of
https://github.com/isledecomp/isle-portable.git
synced 2026-01-11 18:41:14 +00:00
317 lines
7.2 KiB
C++
317 lines
7.2 KiB
C++
#include "d3drmmesh_impl.h"
|
|
#include "miniwin.h"
|
|
|
|
#include <limits>
|
|
|
|
HRESULT Direct3DRMMeshImpl::QueryInterface(const GUID& riid, void** ppvObject)
|
|
{
|
|
if (SDL_memcmp(&riid, &IID_IDirect3DRMMesh, sizeof(GUID)) == 0) {
|
|
this->IUnknown::AddRef();
|
|
*ppvObject = static_cast<IDirect3DRMMesh*>(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) {
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
auto* clone = new Direct3DRMMeshImpl(*this);
|
|
|
|
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<IDirect3DRMMesh*>(clone);
|
|
return DD_OK;
|
|
}
|
|
|
|
HRESULT Direct3DRMMeshImpl::AddGroup(
|
|
int vertexCount,
|
|
int faceCount,
|
|
int vertexPerFace,
|
|
DWORD* faceBuffer,
|
|
D3DRMGROUPINDEX* groupIndex
|
|
)
|
|
{
|
|
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.indices.assign(src, src + faceCount * vertexPerFace);
|
|
|
|
m_groups.push_back(std::move(group));
|
|
|
|
return DD_OK;
|
|
}
|
|
|
|
HRESULT Direct3DRMMeshImpl::GetGroup(
|
|
DWORD groupIndex,
|
|
DWORD* vertexCount,
|
|
DWORD* faceCount,
|
|
DWORD* vertexPerFace,
|
|
DWORD* indexCount,
|
|
DWORD* indices
|
|
)
|
|
{
|
|
if (groupIndex >= m_groups.size()) {
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
const auto& group = m_groups[groupIndex];
|
|
|
|
if (vertexCount) {
|
|
*vertexCount = static_cast<DWORD>(group.vertices.size());
|
|
}
|
|
if (faceCount) {
|
|
*faceCount = static_cast<DWORD>(group.indices.size() / group.vertexPerFace);
|
|
}
|
|
if (vertexPerFace) {
|
|
*vertexPerFace = static_cast<DWORD>(group.vertexPerFace);
|
|
}
|
|
if (indexCount) {
|
|
*indexCount = static_cast<DWORD>(group.indices.size());
|
|
}
|
|
if (indices) {
|
|
std::copy(group.indices.begin(), group.indices.end(), reinterpret_cast<unsigned int*>(indices));
|
|
}
|
|
|
|
return DD_OK;
|
|
}
|
|
|
|
const MeshGroup& Direct3DRMMeshImpl::GetGroup(DWORD groupIndex)
|
|
{
|
|
return m_groups[groupIndex];
|
|
}
|
|
|
|
DWORD Direct3DRMMeshImpl::GetGroupCount()
|
|
{
|
|
return m_groups.size();
|
|
}
|
|
|
|
HRESULT Direct3DRMMeshImpl::SetGroupColor(DWORD groupIndex, D3DCOLOR color)
|
|
{
|
|
if (groupIndex >= m_groups.size()) {
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
m_groups[groupIndex].color = {
|
|
static_cast<Uint8>((color >> 16) & 0xFF),
|
|
static_cast<Uint8>((color >> 8) & 0xFF),
|
|
static_cast<Uint8>((color >> 0) & 0xFF),
|
|
static_cast<Uint8>((color >> 24) & 0xFF)
|
|
};
|
|
return DD_OK;
|
|
}
|
|
|
|
HRESULT Direct3DRMMeshImpl::SetGroupColorRGB(DWORD groupIndex, float r, float g, float b)
|
|
{
|
|
if (groupIndex >= m_groups.size()) {
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
m_groups[groupIndex]
|
|
.color = {static_cast<Uint8>(r * 255.0f), static_cast<Uint8>(g * 255.0f), static_cast<Uint8>(b * 255.0f), 255};
|
|
|
|
return DD_OK;
|
|
}
|
|
|
|
D3DCOLOR Direct3DRMMeshImpl::GetGroupColor(D3DRMGROUPINDEX index)
|
|
{
|
|
if (index < 0 || index >= static_cast<int>(m_groups.size())) {
|
|
return 0xFFFFFFFF;
|
|
}
|
|
|
|
const SDL_Color& color = m_groups[index].color;
|
|
return (color.a << 24) | (color.r << 16) | (color.g << 8) | color.b;
|
|
}
|
|
|
|
HRESULT Direct3DRMMeshImpl::SetGroupMaterial(DWORD groupIndex, IDirect3DRMMaterial* material)
|
|
{
|
|
if (groupIndex >= m_groups.size()) {
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
auto& group = m_groups[groupIndex];
|
|
if (group.material) {
|
|
group.material->Release();
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
auto& group = m_groups[groupIndex];
|
|
if (group.texture) {
|
|
group.texture->Release();
|
|
}
|
|
|
|
texture->AddRef();
|
|
group.texture = texture;
|
|
group.version++;
|
|
return DD_OK;
|
|
}
|
|
|
|
HRESULT Direct3DRMMeshImpl::GetGroupMaterial(DWORD groupIndex, LPDIRECT3DRMMATERIAL* material)
|
|
{
|
|
if (groupIndex >= m_groups.size()) {
|
|
return DDERR_GENERIC;
|
|
}
|
|
|
|
auto& group = m_groups[groupIndex];
|
|
if (!group.material) {
|
|
return DDERR_GENERIC;
|
|
}
|
|
|
|
group.material->AddRef();
|
|
*material = group.material;
|
|
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)
|
|
{
|
|
return DD_OK;
|
|
}
|
|
|
|
D3DRMMAPPING Direct3DRMMeshImpl::GetGroupMapping(DWORD groupIndex)
|
|
{
|
|
return D3DRMMAP_PERSPCORRECT;
|
|
}
|
|
|
|
HRESULT Direct3DRMMeshImpl::SetGroupQuality(DWORD groupIndex, D3DRMRENDERQUALITY quality)
|
|
{
|
|
if (groupIndex >= m_groups.size()) {
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
switch (quality) {
|
|
case D3DRMRENDER_WIREFRAME:
|
|
case D3DRMRENDER_UNLITFLAT:
|
|
MINIWIN_NOT_IMPLEMENTED();
|
|
break;
|
|
}
|
|
|
|
auto& group = m_groups[groupIndex];
|
|
group.quality = quality;
|
|
group.version++;
|
|
|
|
return DD_OK;
|
|
}
|
|
|
|
D3DRMRENDERQUALITY Direct3DRMMeshImpl::GetGroupQuality(DWORD groupIndex)
|
|
{
|
|
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<int>(m_groups.size())) {
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
auto& group = m_groups[groupIndex];
|
|
auto& vertList = group.vertices;
|
|
|
|
if (offset + count > static_cast<int>(vertList.size())) {
|
|
vertList.resize(offset + count);
|
|
}
|
|
|
|
std::copy(vertices, vertices + count, vertList.begin() + offset);
|
|
|
|
UpdateBox();
|
|
|
|
group.version++;
|
|
|
|
return DD_OK;
|
|
}
|
|
|
|
HRESULT Direct3DRMMeshImpl::GetVertices(DWORD groupIndex, int startIndex, int count, D3DRMVERTEX* vertices)
|
|
{
|
|
if (count <= 0 || startIndex < 0 || groupIndex < 0 || groupIndex >= static_cast<int>(m_groups.size())) {
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
const auto& vertList = m_groups[groupIndex].vertices;
|
|
|
|
if (startIndex + count > static_cast<int>(vertList.size())) {
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
std::copy(vertList.begin() + startIndex, vertList.begin() + startIndex + count, vertices);
|
|
return DD_OK;
|
|
}
|
|
|
|
void Direct3DRMMeshImpl::UpdateBox()
|
|
{
|
|
const float INF = std::numeric_limits<float>::max();
|
|
m_box.min = {INF, INF, INF};
|
|
m_box.max = {-INF, -INF, -INF};
|
|
|
|
for (size_t i = 0; i < m_groups.size(); ++i) {
|
|
for (const D3DRMVERTEX& v : m_groups[i].vertices) {
|
|
m_box.min.x = std::min(m_box.min.x, v.position.x);
|
|
m_box.min.y = std::min(m_box.min.y, v.position.y);
|
|
m_box.min.z = std::min(m_box.min.z, v.position.z);
|
|
m_box.max.x = std::max(m_box.max.x, v.position.x);
|
|
m_box.max.y = std::max(m_box.max.y, v.position.y);
|
|
m_box.max.z = std::max(m_box.max.z, v.position.z);
|
|
}
|
|
}
|
|
}
|
|
|
|
HRESULT Direct3DRMMeshImpl::GetBox(D3DRMBOX* box)
|
|
{
|
|
*box = m_box;
|
|
|
|
return DD_OK;
|
|
}
|