mirror of
https://github.com/isledecomp/isle-portable.git
synced 2026-01-11 18:41:14 +00:00
Use indexed faces (#257)
This commit is contained in:
parent
897700c19a
commit
cd4a24ec9e
@ -15,6 +15,7 @@ add_library(miniwin STATIC EXCLUDE_FROM_ALL
|
||||
src/d3drm/d3drmmesh.cpp
|
||||
src/d3drm/d3drmtexture.cpp
|
||||
src/d3drm/d3drmviewport.cpp
|
||||
src/internal/meshutils.cpp
|
||||
|
||||
# D3DRM backends
|
||||
src/d3drm/backends/software/renderer.cpp
|
||||
|
||||
@ -191,8 +191,8 @@ struct IDirect3DRMMesh : public IDirect3DRMVisual {
|
||||
DWORD* vertexCount,
|
||||
DWORD* faceCount,
|
||||
DWORD* vertexPerFace,
|
||||
DWORD* dataSize,
|
||||
DWORD* data
|
||||
DWORD* indexCount,
|
||||
DWORD* indices
|
||||
) = 0;
|
||||
virtual DWORD GetGroupCount() = 0;
|
||||
virtual HRESULT SetGroupColor(DWORD groupIndex, D3DCOLOR color) = 0;
|
||||
|
||||
@ -2,8 +2,10 @@
|
||||
#include "ddraw_impl.h"
|
||||
#include "ddsurface_impl.h"
|
||||
#include "mathutils.h"
|
||||
#include "meshutils.h"
|
||||
|
||||
#include <GL/glew.h>
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
|
||||
@ -305,7 +307,9 @@ HRESULT OpenGL15Renderer::BeginFrame(const D3DRMMATRIX4D& viewMatrix)
|
||||
|
||||
void OpenGL15Renderer::SubmitDraw(
|
||||
const D3DRMVERTEX* vertices,
|
||||
const size_t count,
|
||||
const size_t vertexCount,
|
||||
const DWORD* indices,
|
||||
const size_t indexCount,
|
||||
const D3DRMMATRIX4D& worldMatrix,
|
||||
const Matrix3x3& normalMatrix,
|
||||
const Appearance& appearance
|
||||
@ -319,27 +323,46 @@ void OpenGL15Renderer::SubmitDraw(
|
||||
glLoadMatrixf(&mvMatrix[0][0]);
|
||||
glEnable(GL_NORMALIZE);
|
||||
|
||||
glColor4ub(appearance.color.r, appearance.color.g, appearance.color.b, appearance.color.a);
|
||||
|
||||
// Bind texture if present
|
||||
if (appearance.textureId != NO_TEXTURE_ID) {
|
||||
auto& tex = m_textures[appearance.textureId];
|
||||
if (tex.glTextureId) {
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glBindTexture(GL_TEXTURE_2D, tex.glTextureId);
|
||||
}
|
||||
}
|
||||
else {
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
std::vector<D3DRMVERTEX> newVertices;
|
||||
std::vector<DWORD> newIndices;
|
||||
if (appearance.flat) {
|
||||
glShadeModel(GL_FLAT);
|
||||
// FIXME move this to a one time mesh upload stage
|
||||
FlattenSurfaces(
|
||||
vertices,
|
||||
vertexCount,
|
||||
indices,
|
||||
indexCount,
|
||||
appearance.textureId != NO_TEXTURE_ID,
|
||||
newVertices,
|
||||
newIndices
|
||||
);
|
||||
}
|
||||
else {
|
||||
glShadeModel(GL_SMOOTH);
|
||||
newVertices.assign(vertices, vertices + vertexCount);
|
||||
newIndices.assign(indices, indices + indexCount);
|
||||
}
|
||||
|
||||
// Bind texture if present
|
||||
std::vector<TexCoord> texcoords;
|
||||
if (appearance.textureId != NO_TEXTURE_ID) {
|
||||
auto& tex = m_textures[appearance.textureId];
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glBindTexture(GL_TEXTURE_2D, tex.glTextureId);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
texcoords.resize(newVertices.size());
|
||||
std::transform(newVertices.begin(), newVertices.end(), texcoords.begin(), [](const D3DRMVERTEX& v) {
|
||||
return v.texCoord;
|
||||
});
|
||||
}
|
||||
else {
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
}
|
||||
|
||||
glColor4ub(appearance.color.r, appearance.color.g, appearance.color.b, appearance.color.a);
|
||||
|
||||
float shininess = appearance.shininess;
|
||||
glMaterialf(GL_FRONT, GL_SHININESS, shininess);
|
||||
if (shininess != 0.0f) {
|
||||
@ -351,14 +374,29 @@ void OpenGL15Renderer::SubmitDraw(
|
||||
glMaterialfv(GL_FRONT, GL_SPECULAR, noSpec);
|
||||
}
|
||||
|
||||
glBegin(GL_TRIANGLES);
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
const D3DRMVERTEX& v = vertices[i];
|
||||
glNormal3f(v.normal.x, v.normal.y, v.normal.z);
|
||||
glTexCoord2f(v.texCoord.u, v.texCoord.v);
|
||||
glVertex3f(v.position.x, v.position.y, v.position.z);
|
||||
std::vector<D3DVECTOR> positions;
|
||||
positions.resize(newVertices.size());
|
||||
std::transform(newVertices.begin(), newVertices.end(), positions.begin(), [](const D3DRMVERTEX& v) {
|
||||
return v.position;
|
||||
});
|
||||
std::vector<D3DVECTOR> normals;
|
||||
normals.resize(newVertices.size());
|
||||
std::transform(newVertices.begin(), newVertices.end(), normals.begin(), [](const D3DRMVERTEX& v) {
|
||||
return v.normal;
|
||||
});
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glVertexPointer(3, GL_FLOAT, 0, positions.data());
|
||||
|
||||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
glNormalPointer(GL_FLOAT, 0, normals.data());
|
||||
|
||||
if (appearance.textureId != NO_TEXTURE_ID) {
|
||||
glTexCoordPointer(2, GL_FLOAT, 0, texcoords.data());
|
||||
}
|
||||
glEnd();
|
||||
|
||||
// Draw triangles
|
||||
glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(newIndices.size()), GL_UNSIGNED_INT, newIndices.data());
|
||||
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
#include "d3drmrenderer_sdl3gpu.h"
|
||||
#include "ddraw_impl.h"
|
||||
#include "mathutils.h"
|
||||
#include "meshutils.h"
|
||||
#include "miniwin.h"
|
||||
|
||||
#include <SDL3/SDL.h>
|
||||
@ -600,7 +601,9 @@ SDL_GPUTransferBuffer* Direct3DRMSDL3GPURenderer::GetUploadBuffer(size_t size)
|
||||
|
||||
void Direct3DRMSDL3GPURenderer::SubmitDraw(
|
||||
const D3DRMVERTEX* vertices,
|
||||
const size_t count,
|
||||
const size_t vertexCount,
|
||||
const DWORD* indices,
|
||||
const size_t indexCount,
|
||||
const D3DRMMATRIX4D& worldMatrix,
|
||||
const Matrix3x3& normalMatrix,
|
||||
const Appearance& appearance
|
||||
@ -613,21 +616,46 @@ void Direct3DRMSDL3GPURenderer::SubmitDraw(
|
||||
m_fragmentShadingData.color = appearance.color;
|
||||
m_fragmentShadingData.shininess = appearance.shininess;
|
||||
|
||||
if (count > m_vertexBufferCount) {
|
||||
std::vector<D3DRMVERTEX> flatVertices;
|
||||
if (appearance.flat) {
|
||||
std::vector<D3DRMVERTEX> newVertices;
|
||||
std::vector<DWORD> newIndices;
|
||||
// FIXME move this to a one time mesh upload stage
|
||||
FlattenSurfaces(
|
||||
vertices,
|
||||
vertexCount,
|
||||
indices,
|
||||
indexCount,
|
||||
appearance.textureId != NO_TEXTURE_ID,
|
||||
newVertices,
|
||||
newIndices
|
||||
);
|
||||
for (DWORD& index : newIndices) {
|
||||
flatVertices.push_back(newVertices[index]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// TODO handle indexed verticies on GPU
|
||||
for (int i = 0; i < indexCount; ++i) {
|
||||
flatVertices.push_back(vertices[indices[i]]);
|
||||
}
|
||||
}
|
||||
|
||||
if (flatVertices.size() > m_vertexBufferCount) {
|
||||
if (m_vertexBuffer) {
|
||||
SDL_ReleaseGPUBuffer(m_device, m_vertexBuffer);
|
||||
}
|
||||
SDL_GPUBufferCreateInfo bufferCreateInfo = {};
|
||||
bufferCreateInfo.usage = SDL_GPU_BUFFERUSAGE_VERTEX;
|
||||
bufferCreateInfo.size = static_cast<Uint32>(sizeof(D3DRMVERTEX) * count);
|
||||
bufferCreateInfo.size = static_cast<Uint32>(sizeof(D3DRMVERTEX) * flatVertices.size());
|
||||
m_vertexBuffer = SDL_CreateGPUBuffer(m_device, &bufferCreateInfo);
|
||||
if (!m_vertexBuffer) {
|
||||
SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_CreateGPUBuffer failed (%s)", SDL_GetError());
|
||||
}
|
||||
m_vertexBufferCount = count;
|
||||
m_vertexBufferCount = flatVertices.size();
|
||||
}
|
||||
|
||||
m_vertexCount = count;
|
||||
m_vertexCount = flatVertices.size();
|
||||
|
||||
SDL_GPUTransferBuffer* uploadBuffer = GetUploadBuffer(sizeof(D3DRMVERTEX) * m_vertexCount);
|
||||
if (!uploadBuffer) {
|
||||
@ -639,7 +667,7 @@ void Direct3DRMSDL3GPURenderer::SubmitDraw(
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(transferData, vertices, m_vertexCount * sizeof(D3DRMVERTEX));
|
||||
memcpy(transferData, flatVertices.data(), m_vertexCount * sizeof(D3DRMVERTEX));
|
||||
SDL_UnmapGPUTransferBuffer(m_device, uploadBuffer);
|
||||
|
||||
// Upload the transfer data to the vertex buffer
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
#include "d3drmrenderer_software.h"
|
||||
#include "ddsurface_impl.h"
|
||||
#include "mathutils.h"
|
||||
#include "meshutils.h"
|
||||
#include "miniwin.h"
|
||||
|
||||
#include <SDL3/SDL.h>
|
||||
@ -452,7 +453,9 @@ HRESULT Direct3DRMSoftwareRenderer::BeginFrame(const D3DRMMATRIX4D& viewMatrix)
|
||||
|
||||
void Direct3DRMSoftwareRenderer::SubmitDraw(
|
||||
const D3DRMVERTEX* vertices,
|
||||
const size_t count,
|
||||
const size_t vertexCount,
|
||||
const DWORD* indices,
|
||||
const size_t indexCount,
|
||||
const D3DRMMATRIX4D& worldMatrix,
|
||||
const Matrix3x3& normalMatrix,
|
||||
const Appearance& appearance
|
||||
@ -461,15 +464,42 @@ void Direct3DRMSoftwareRenderer::SubmitDraw(
|
||||
D3DRMMATRIX4D mvMatrix;
|
||||
MultiplyMatrix(mvMatrix, worldMatrix, m_viewMatrix);
|
||||
|
||||
for (size_t i = 0; i + 2 < count; i += 3) {
|
||||
D3DRMVERTEX vrts[3];
|
||||
for (size_t j = 0; j < 3; ++j) {
|
||||
const D3DRMVERTEX& src = vertices[i + j];
|
||||
vrts[j].position = TransformPoint(src.position, mvMatrix);
|
||||
vrts[j].normal = Normalize(TransformNormal(src.normal, normalMatrix));
|
||||
vrts[j].texCoord = src.texCoord;
|
||||
}
|
||||
DrawTriangleClipped(vrts, appearance);
|
||||
std::vector<D3DRMVERTEX> newVertices;
|
||||
std::vector<DWORD> newIndices;
|
||||
if (appearance.flat) {
|
||||
// FIXME move this to a one time mesh upload stage
|
||||
FlattenSurfaces(
|
||||
vertices,
|
||||
vertexCount,
|
||||
indices,
|
||||
indexCount,
|
||||
appearance.textureId != NO_TEXTURE_ID,
|
||||
newVertices,
|
||||
newIndices
|
||||
);
|
||||
}
|
||||
else {
|
||||
newVertices.assign(vertices, vertices + vertexCount);
|
||||
newIndices.assign(indices, indices + indexCount);
|
||||
}
|
||||
|
||||
// Pre-transform all vertex positions and normals
|
||||
std::vector<D3DRMVERTEX> transformedVerts(newVertices.size());
|
||||
for (size_t i = 0; i < newVertices.size(); ++i) {
|
||||
const D3DRMVERTEX& src = newVertices[i];
|
||||
D3DRMVERTEX& dst = transformedVerts[i];
|
||||
dst.position = TransformPoint(src.position, mvMatrix);
|
||||
// TODO defer normal transformation til lighting to allow culling first
|
||||
dst.normal = Normalize(TransformNormal(src.normal, normalMatrix));
|
||||
dst.texCoord = src.texCoord;
|
||||
}
|
||||
|
||||
// Assemble triangles using index buffer
|
||||
for (size_t i = 0; i + 2 < newIndices.size(); i += 3) {
|
||||
DrawTriangleClipped(
|
||||
{transformedVerts[newIndices[i]], transformedVerts[newIndices[i + 1]], transformedVerts[newIndices[i + 2]]},
|
||||
appearance
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -60,7 +60,7 @@ HRESULT Direct3DRMMeshImpl::AddGroup(
|
||||
group.vertexPerFace = vertexPerFace;
|
||||
|
||||
DWORD* src = faceBuffer;
|
||||
group.faces.assign(src, src + faceCount * vertexPerFace);
|
||||
group.indices.assign(src, src + faceCount * vertexPerFace);
|
||||
|
||||
m_groups.push_back(std::move(group));
|
||||
|
||||
@ -72,8 +72,8 @@ HRESULT Direct3DRMMeshImpl::GetGroup(
|
||||
DWORD* vertexCount,
|
||||
DWORD* faceCount,
|
||||
DWORD* vertexPerFace,
|
||||
DWORD* dataSize,
|
||||
DWORD* data
|
||||
DWORD* indexCount,
|
||||
DWORD* indices
|
||||
)
|
||||
{
|
||||
if (groupIndex >= m_groups.size()) {
|
||||
@ -86,16 +86,16 @@ HRESULT Direct3DRMMeshImpl::GetGroup(
|
||||
*vertexCount = static_cast<DWORD>(group.vertices.size());
|
||||
}
|
||||
if (faceCount) {
|
||||
*faceCount = static_cast<DWORD>(group.faces.size() / group.vertexPerFace);
|
||||
*faceCount = static_cast<DWORD>(group.indices.size() / group.vertexPerFace);
|
||||
}
|
||||
if (vertexPerFace) {
|
||||
*vertexPerFace = static_cast<DWORD>(group.vertexPerFace);
|
||||
}
|
||||
if (dataSize) {
|
||||
*dataSize = static_cast<DWORD>(group.faces.size());
|
||||
if (indexCount) {
|
||||
*indexCount = static_cast<DWORD>(group.indices.size());
|
||||
}
|
||||
if (data) {
|
||||
std::copy(group.faces.begin(), group.faces.end(), reinterpret_cast<unsigned int*>(data));
|
||||
if (indices) {
|
||||
std::copy(group.indices.begin(), group.indices.end(), reinterpret_cast<unsigned int*>(indices));
|
||||
}
|
||||
|
||||
return DD_OK;
|
||||
|
||||
@ -95,21 +95,6 @@ static void ComputeFrameWorldMatrix(IDirect3DRMFrame* frame, D3DRMMATRIX4D out)
|
||||
memcpy(out, acc, sizeof(acc));
|
||||
}
|
||||
|
||||
inline D3DVECTOR CrossProduct(const D3DVECTOR& a, const D3DVECTOR& b)
|
||||
{
|
||||
return {a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x};
|
||||
}
|
||||
|
||||
D3DVECTOR ComputeTriangleNormal(const D3DVECTOR& v0, const D3DVECTOR& v1, const D3DVECTOR& v2)
|
||||
{
|
||||
D3DVECTOR u = {v1.x - v0.x, v1.y - v0.y, v1.z - v0.z};
|
||||
D3DVECTOR v = {v2.x - v0.x, v2.y - v0.y, v2.z - v0.z};
|
||||
D3DVECTOR normal = CrossProduct(u, v);
|
||||
normal = Normalize(normal);
|
||||
|
||||
return normal;
|
||||
}
|
||||
|
||||
void Direct3DRMViewportImpl::CollectLightsFromFrame(
|
||||
IDirect3DRMFrame* frame,
|
||||
D3DRMMATRIX4D parentToWorld,
|
||||
@ -215,9 +200,8 @@ bool IsBoxInFrustum(const D3DVECTOR corners[8], const Plane planes[6])
|
||||
void Direct3DRMViewportImpl::CollectMeshesFromFrame(
|
||||
IDirect3DRMFrame* frame,
|
||||
D3DRMMATRIX4D parentMatrix,
|
||||
std::vector<D3DRMVERTEX>& verts,
|
||||
std::vector<D3DRMVERTEX>& d3dVerts,
|
||||
std::vector<DWORD>& faces
|
||||
std::vector<DWORD>& indices
|
||||
)
|
||||
{
|
||||
Direct3DRMFrameImpl* frameImpl = static_cast<Direct3DRMFrameImpl*>(frame);
|
||||
@ -240,7 +224,7 @@ void Direct3DRMViewportImpl::CollectMeshesFromFrame(
|
||||
IDirect3DRMFrame* childFrame = nullptr;
|
||||
visual->QueryInterface(IID_IDirect3DRMFrame, (void**) &childFrame);
|
||||
if (childFrame) {
|
||||
CollectMeshesFromFrame(childFrame, worldMatrix, verts, d3dVerts, faces);
|
||||
CollectMeshesFromFrame(childFrame, worldMatrix, d3dVerts, indices);
|
||||
childFrame->Release();
|
||||
visual->Release();
|
||||
continue;
|
||||
@ -276,19 +260,16 @@ void Direct3DRMViewportImpl::CollectMeshesFromFrame(
|
||||
|
||||
DWORD groupCount = mesh->GetGroupCount();
|
||||
for (DWORD gi = 0; gi < groupCount; ++gi) {
|
||||
DWORD vtxCount, faceCount, vpf, dataSize;
|
||||
mesh->GetGroup(gi, &vtxCount, &faceCount, &vpf, &dataSize, nullptr);
|
||||
DWORD vtxCount, indexCount;
|
||||
mesh->GetGroup(gi, &vtxCount, nullptr, nullptr, &indexCount, nullptr);
|
||||
|
||||
verts.reserve(dataSize);
|
||||
verts.clear();
|
||||
d3dVerts.resize(vtxCount);
|
||||
faces.resize(dataSize);
|
||||
indices.resize(indexCount);
|
||||
mesh->GetVertices(gi, 0, vtxCount, d3dVerts.data());
|
||||
mesh->GetGroup(gi, nullptr, nullptr, nullptr, nullptr, faces.data());
|
||||
mesh->GetGroup(gi, nullptr, nullptr, nullptr, nullptr, indices.data());
|
||||
|
||||
D3DCOLOR color = mesh->GetGroupColor(gi);
|
||||
D3DRMRENDERQUALITY quality = mesh->GetGroupQuality(gi);
|
||||
bool flat = quality == D3DRMRENDER_FLAT || quality == D3DRMRENDER_UNLITFLAT;
|
||||
|
||||
IDirect3DRMTexture* texture = nullptr;
|
||||
mesh->GetGroupTexture(gi, &texture);
|
||||
@ -306,28 +287,11 @@ void Direct3DRMViewportImpl::CollectMeshesFromFrame(
|
||||
material->Release();
|
||||
}
|
||||
|
||||
for (DWORD fi = 0; fi < faceCount; ++fi) {
|
||||
D3DVECTOR norm;
|
||||
if (flat) {
|
||||
D3DRMVERTEX& v0 = d3dVerts[faces[fi * vpf + 0]];
|
||||
D3DRMVERTEX& v1 = d3dVerts[faces[fi * vpf + 1]];
|
||||
D3DRMVERTEX& v2 = d3dVerts[faces[fi * vpf + 2]];
|
||||
norm = ComputeTriangleNormal(v0.position, v1.position, v2.position);
|
||||
}
|
||||
|
||||
for (DWORD idx = 0; idx < vpf; ++idx) {
|
||||
D3DRMVERTEX& dv = d3dVerts[faces[fi * vpf + idx]];
|
||||
D3DVECTOR pos = dv.position;
|
||||
if (quality == D3DRMRENDER_GOURAUD || quality == D3DRMRENDER_PHONG) {
|
||||
norm = dv.normal;
|
||||
}
|
||||
|
||||
verts.push_back({pos, norm, {dv.tu, dv.tv}});
|
||||
}
|
||||
}
|
||||
m_renderer->SubmitDraw(
|
||||
verts.data(),
|
||||
verts.size(),
|
||||
d3dVerts.data(),
|
||||
d3dVerts.size(),
|
||||
indices.data(),
|
||||
indices.size(),
|
||||
worldMatrix,
|
||||
worldMatrixInvert,
|
||||
{{static_cast<Uint8>((color >> 16) & 0xFF),
|
||||
@ -336,7 +300,7 @@ void Direct3DRMViewportImpl::CollectMeshesFromFrame(
|
||||
static_cast<Uint8>((color >> 24) & 0xFF)},
|
||||
shininess,
|
||||
textureId,
|
||||
flat}
|
||||
quality == D3DRMRENDER_FLAT || quality == D3DRMRENDER_UNLITFLAT}
|
||||
);
|
||||
}
|
||||
mesh->Release();
|
||||
@ -365,11 +329,10 @@ HRESULT Direct3DRMViewportImpl::RenderScene()
|
||||
return status;
|
||||
}
|
||||
|
||||
std::vector<D3DRMVERTEX> verts;
|
||||
std::vector<D3DRMVERTEX> d3dVerts;
|
||||
std::vector<DWORD> faces;
|
||||
std::vector<DWORD> indices;
|
||||
ExtractFrustumPlanes(viewProj);
|
||||
CollectMeshesFromFrame(m_rootFrame, identity, verts, d3dVerts, faces);
|
||||
CollectMeshesFromFrame(m_rootFrame, identity, d3dVerts, indices);
|
||||
return m_renderer->FinalizeFrame();
|
||||
}
|
||||
|
||||
@ -724,23 +687,19 @@ bool RayIntersectsMeshTriangles(
|
||||
{
|
||||
DWORD groupCount = mesh->GetGroupCount();
|
||||
for (DWORD g = 0; g < groupCount; ++g) {
|
||||
DWORD vtxCount = 0, faceCount = 0, vpf = 0, dataSize = 0;
|
||||
mesh->GetGroup(g, &vtxCount, &faceCount, &vpf, &dataSize, nullptr);
|
||||
DWORD vtxCount, faceCount, indexCount;
|
||||
mesh->GetGroup(g, &vtxCount, &faceCount, nullptr, &indexCount, nullptr);
|
||||
|
||||
std::vector<D3DRMVERTEX> vertices(vtxCount);
|
||||
mesh->GetVertices(g, 0, vtxCount, vertices.data());
|
||||
std::vector<DWORD> faces(faceCount * vpf);
|
||||
mesh->GetGroup(g, nullptr, nullptr, nullptr, nullptr, faces.data());
|
||||
std::vector<DWORD> indices(indexCount);
|
||||
mesh->GetGroup(g, nullptr, nullptr, nullptr, nullptr, indices.data());
|
||||
|
||||
// Iterate over each face and do ray-triangle tests
|
||||
for (DWORD fi = 0; fi < faceCount; ++fi) {
|
||||
DWORD i0 = faces[fi * vpf + 0];
|
||||
DWORD i1 = faces[fi * vpf + 1];
|
||||
DWORD i2 = faces[fi * vpf + 2];
|
||||
|
||||
if (i0 >= vtxCount || i1 >= vtxCount || i2 >= vtxCount) {
|
||||
continue;
|
||||
}
|
||||
for (DWORD fi = 0; fi < faceCount; fi += 3) {
|
||||
DWORD i0 = indices[fi + 0];
|
||||
DWORD i1 = indices[fi + 1];
|
||||
DWORD i2 = indices[fi + 2];
|
||||
|
||||
// Transform vertices to world space
|
||||
D3DVECTOR tri[3];
|
||||
|
||||
@ -12,13 +12,13 @@ struct MeshGroup {
|
||||
D3DRMRENDERQUALITY quality = D3DRMRENDER_GOURAUD;
|
||||
int vertexPerFace = 0;
|
||||
std::vector<D3DRMVERTEX> vertices;
|
||||
std::vector<unsigned int> faces;
|
||||
std::vector<unsigned int> indices;
|
||||
|
||||
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))
|
||||
vertexPerFace(other.vertexPerFace), vertices(std::move(other.vertices)), indices(std::move(other.indices))
|
||||
{
|
||||
if (texture) {
|
||||
texture->AddRef();
|
||||
@ -31,7 +31,7 @@ struct MeshGroup {
|
||||
// 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)
|
||||
vertexPerFace(other.vertexPerFace), vertices(other.vertices), indices(other.indices)
|
||||
{
|
||||
other.texture = nullptr;
|
||||
other.material = nullptr;
|
||||
@ -46,7 +46,7 @@ struct MeshGroup {
|
||||
quality = other.quality;
|
||||
vertexPerFace = other.vertexPerFace;
|
||||
vertices = std::move(other.vertices);
|
||||
faces = std::move(other.faces);
|
||||
indices = std::move(other.indices);
|
||||
other.texture = nullptr;
|
||||
other.material = nullptr;
|
||||
return *this;
|
||||
@ -73,8 +73,8 @@ struct Direct3DRMMeshImpl : public Direct3DRMObjectBaseImpl<IDirect3DRMMesh> {
|
||||
DWORD* vertexCount,
|
||||
DWORD* faceCount,
|
||||
DWORD* vertexPerFace,
|
||||
DWORD* dataSize,
|
||||
DWORD* data
|
||||
DWORD* indexCount,
|
||||
DWORD* indices
|
||||
) override;
|
||||
DWORD GetGroupCount() override;
|
||||
HRESULT SetGroupColor(DWORD groupIndex, D3DCOLOR color) override;
|
||||
|
||||
@ -13,7 +13,7 @@ struct Appearance {
|
||||
SDL_Color color;
|
||||
float shininess;
|
||||
Uint32 textureId;
|
||||
bool flat;
|
||||
Uint32 flat;
|
||||
};
|
||||
|
||||
struct FColor {
|
||||
@ -41,7 +41,9 @@ class Direct3DRMRenderer : public IDirect3DDevice2 {
|
||||
virtual HRESULT BeginFrame(const D3DRMMATRIX4D& viewMatrix) = 0;
|
||||
virtual void SubmitDraw(
|
||||
const D3DRMVERTEX* vertices,
|
||||
const size_t count,
|
||||
const size_t vertexCount,
|
||||
const DWORD* indices,
|
||||
const size_t indexCount,
|
||||
const D3DRMMATRIX4D& worldMatrix,
|
||||
const Matrix3x3& normalMatrix,
|
||||
const Appearance& appearance
|
||||
|
||||
@ -31,7 +31,9 @@ class OpenGL15Renderer : public Direct3DRMRenderer {
|
||||
HRESULT BeginFrame(const D3DRMMATRIX4D& viewMatrix) override;
|
||||
void SubmitDraw(
|
||||
const D3DRMVERTEX* vertices,
|
||||
const size_t count,
|
||||
const size_t vertexCount,
|
||||
const DWORD* indices,
|
||||
const size_t indexCount,
|
||||
const D3DRMMATRIX4D& worldMatrix,
|
||||
const Matrix3x3& normalMatrix,
|
||||
const Appearance& appearance
|
||||
|
||||
@ -48,7 +48,9 @@ class Direct3DRMSDL3GPURenderer : public Direct3DRMRenderer {
|
||||
HRESULT BeginFrame(const D3DRMMATRIX4D& viewMatrix) override;
|
||||
void SubmitDraw(
|
||||
const D3DRMVERTEX* vertices,
|
||||
const size_t count,
|
||||
const size_t vertexCount,
|
||||
const DWORD* indices,
|
||||
const size_t indexCount,
|
||||
const D3DRMMATRIX4D& worldMatrix,
|
||||
const Matrix3x3& normalMatrix,
|
||||
const Appearance& appearance
|
||||
|
||||
@ -29,7 +29,9 @@ class Direct3DRMSoftwareRenderer : public Direct3DRMRenderer {
|
||||
HRESULT BeginFrame(const D3DRMMATRIX4D& viewMatrix) override;
|
||||
void SubmitDraw(
|
||||
const D3DRMVERTEX* vertices,
|
||||
const size_t count,
|
||||
const size_t vertexCount,
|
||||
const DWORD* indices,
|
||||
const size_t indexCount,
|
||||
const D3DRMMATRIX4D& worldMatrix,
|
||||
const Matrix3x3& normalMatrix,
|
||||
const Appearance& appearance
|
||||
|
||||
@ -40,7 +40,6 @@ struct Direct3DRMViewportImpl : public Direct3DRMObjectBaseImpl<IDirect3DRMViewp
|
||||
void CollectMeshesFromFrame(
|
||||
IDirect3DRMFrame* frame,
|
||||
D3DRMMATRIX4D parentMatrix,
|
||||
std::vector<D3DRMVERTEX>& verts,
|
||||
std::vector<D3DRMVERTEX>& d3dVerts,
|
||||
std::vector<DWORD>& faces
|
||||
);
|
||||
|
||||
@ -25,6 +25,11 @@ inline D3DVECTOR Normalize(const D3DVECTOR& v)
|
||||
return {0, 0, 0};
|
||||
}
|
||||
|
||||
inline D3DVECTOR CrossProduct(const D3DVECTOR& a, const D3DVECTOR& b)
|
||||
{
|
||||
return {a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x};
|
||||
}
|
||||
|
||||
inline D3DVECTOR TransformPoint(const D3DVECTOR& p, const D3DRMMATRIX4D& m)
|
||||
{
|
||||
return {
|
||||
|
||||
77
miniwin/src/internal/meshutils.cpp
Normal file
77
miniwin/src/internal/meshutils.cpp
Normal file
@ -0,0 +1,77 @@
|
||||
#include "meshutils.h"
|
||||
|
||||
#include "mathutils.h"
|
||||
|
||||
#include <tuple>
|
||||
#include <unordered_map>
|
||||
|
||||
bool operator==(const D3DRMVERTEX& a, const D3DRMVERTEX& b)
|
||||
{
|
||||
return memcmp(&a, &b, sizeof(D3DRMVERTEX)) == 0;
|
||||
}
|
||||
|
||||
namespace std
|
||||
{
|
||||
template <>
|
||||
struct hash<D3DRMVERTEX> {
|
||||
size_t operator()(const D3DRMVERTEX& v) const
|
||||
{
|
||||
const float* f = reinterpret_cast<const float*>(&v);
|
||||
size_t h = 0;
|
||||
for (int i = 0; i < sizeof(D3DRMVERTEX) / sizeof(float); ++i) {
|
||||
h ^= std::hash<float>()(f[i]) + 0x9e3779b9 + (h << 6) + (h >> 2);
|
||||
}
|
||||
return h;
|
||||
}
|
||||
};
|
||||
} // namespace std
|
||||
|
||||
D3DVECTOR ComputeTriangleNormal(const D3DVECTOR& v0, const D3DVECTOR& v1, const D3DVECTOR& v2)
|
||||
{
|
||||
D3DVECTOR u = {v1.x - v0.x, v1.y - v0.y, v1.z - v0.z};
|
||||
D3DVECTOR v = {v2.x - v0.x, v2.y - v0.y, v2.z - v0.z};
|
||||
D3DVECTOR normal = CrossProduct(u, v);
|
||||
normal = Normalize(normal);
|
||||
|
||||
return normal;
|
||||
}
|
||||
|
||||
void FlattenSurfaces(
|
||||
const D3DRMVERTEX* vertices,
|
||||
const size_t vertexCount,
|
||||
const DWORD* indices,
|
||||
const size_t indexCount,
|
||||
bool hasTexture,
|
||||
std::vector<D3DRMVERTEX>& dedupedVertices,
|
||||
std::vector<DWORD>& newIndices
|
||||
)
|
||||
{
|
||||
std::unordered_map<D3DRMVERTEX, DWORD> uniqueVertexMap;
|
||||
|
||||
dedupedVertices.reserve(vertexCount);
|
||||
newIndices.reserve(indexCount);
|
||||
|
||||
for (size_t i = 0; i < indexCount; i += 3) {
|
||||
D3DRMVERTEX v0 = vertices[indices[i + 0]];
|
||||
D3DRMVERTEX v1 = vertices[indices[i + 1]];
|
||||
D3DRMVERTEX v2 = vertices[indices[i + 2]];
|
||||
v0.normal = v1.normal = v2.normal = ComputeTriangleNormal(v0.position, v1.position, v2.position);
|
||||
if (!hasTexture) {
|
||||
v0.texCoord = v1.texCoord = v2.texCoord = {0.0f, 0.0f};
|
||||
}
|
||||
|
||||
// Deduplicate vertecies
|
||||
for (const D3DRMVERTEX& v : {v0, v1, v2}) {
|
||||
auto it = uniqueVertexMap.find(v);
|
||||
if (it != uniqueVertexMap.end()) {
|
||||
newIndices.push_back(it->second);
|
||||
}
|
||||
else {
|
||||
DWORD newIndex = static_cast<DWORD>(dedupedVertices.size());
|
||||
uniqueVertexMap[v] = newIndex;
|
||||
dedupedVertices.push_back(v);
|
||||
newIndices.push_back(newIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
15
miniwin/src/internal/meshutils.h
Normal file
15
miniwin/src/internal/meshutils.h
Normal file
@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include "miniwin/d3drm.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
void FlattenSurfaces(
|
||||
const D3DRMVERTEX* vertices,
|
||||
const size_t vertexCount,
|
||||
const DWORD* indices,
|
||||
const size_t indexCount,
|
||||
bool hasTexture,
|
||||
std::vector<D3DRMVERTEX>& dedupedVertices,
|
||||
std::vector<DWORD>& newIndices
|
||||
);
|
||||
Loading…
Reference in New Issue
Block a user