mirror of
https://github.com/isledecomp/isle-portable.git
synced 2026-02-03 12:31:15 +00:00
Merge branch 'master' into add-IDirect3DRMMiniwinDevice-interface
This commit is contained in:
commit
9af819ab5b
@ -18,6 +18,7 @@ add_library(miniwin STATIC EXCLUDE_FROM_ALL
|
|||||||
src/d3drm/d3drmmesh.cpp
|
src/d3drm/d3drmmesh.cpp
|
||||||
src/d3drm/d3drmtexture.cpp
|
src/d3drm/d3drmtexture.cpp
|
||||||
src/d3drm/d3drmviewport.cpp
|
src/d3drm/d3drmviewport.cpp
|
||||||
|
src/internal/meshutils.cpp
|
||||||
|
|
||||||
# D3DRM backends
|
# D3DRM backends
|
||||||
src/d3drm/backends/software/renderer.cpp
|
src/d3drm/backends/software/renderer.cpp
|
||||||
|
|||||||
@ -192,8 +192,8 @@ struct IDirect3DRMMesh : public IDirect3DRMVisual {
|
|||||||
DWORD* vertexCount,
|
DWORD* vertexCount,
|
||||||
DWORD* faceCount,
|
DWORD* faceCount,
|
||||||
DWORD* vertexPerFace,
|
DWORD* vertexPerFace,
|
||||||
DWORD* dataSize,
|
DWORD* indexCount,
|
||||||
DWORD* data
|
DWORD* indices
|
||||||
) = 0;
|
) = 0;
|
||||||
virtual DWORD GetGroupCount() = 0;
|
virtual DWORD GetGroupCount() = 0;
|
||||||
virtual HRESULT SetGroupColor(DWORD groupIndex, D3DCOLOR color) = 0;
|
virtual HRESULT SetGroupColor(DWORD groupIndex, D3DCOLOR color) = 0;
|
||||||
|
|||||||
@ -2,8 +2,10 @@
|
|||||||
#include "ddraw_impl.h"
|
#include "ddraw_impl.h"
|
||||||
#include "ddsurface_impl.h"
|
#include "ddsurface_impl.h"
|
||||||
#include "mathutils.h"
|
#include "mathutils.h"
|
||||||
|
#include "meshutils.h"
|
||||||
|
|
||||||
#include <GL/glew.h>
|
#include <GL/glew.h>
|
||||||
|
#include <algorithm>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@ -305,7 +307,9 @@ HRESULT OpenGL15Renderer::BeginFrame(const D3DRMMATRIX4D& viewMatrix)
|
|||||||
|
|
||||||
void OpenGL15Renderer::SubmitDraw(
|
void OpenGL15Renderer::SubmitDraw(
|
||||||
const D3DRMVERTEX* vertices,
|
const D3DRMVERTEX* vertices,
|
||||||
const size_t count,
|
const size_t vertexCount,
|
||||||
|
const DWORD* indices,
|
||||||
|
const size_t indexCount,
|
||||||
const D3DRMMATRIX4D& worldMatrix,
|
const D3DRMMATRIX4D& worldMatrix,
|
||||||
const Matrix3x3& normalMatrix,
|
const Matrix3x3& normalMatrix,
|
||||||
const Appearance& appearance
|
const Appearance& appearance
|
||||||
@ -319,27 +323,46 @@ void OpenGL15Renderer::SubmitDraw(
|
|||||||
glLoadMatrixf(&mvMatrix[0][0]);
|
glLoadMatrixf(&mvMatrix[0][0]);
|
||||||
glEnable(GL_NORMALIZE);
|
glEnable(GL_NORMALIZE);
|
||||||
|
|
||||||
glColor4ub(appearance.color.r, appearance.color.g, appearance.color.b, appearance.color.a);
|
std::vector<D3DRMVERTEX> newVertices;
|
||||||
|
std::vector<DWORD> newIndices;
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (appearance.flat) {
|
if (appearance.flat) {
|
||||||
glShadeModel(GL_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 {
|
else {
|
||||||
glShadeModel(GL_SMOOTH);
|
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;
|
float shininess = appearance.shininess;
|
||||||
glMaterialf(GL_FRONT, GL_SHININESS, shininess);
|
glMaterialf(GL_FRONT, GL_SHININESS, shininess);
|
||||||
if (shininess != 0.0f) {
|
if (shininess != 0.0f) {
|
||||||
@ -351,14 +374,29 @@ void OpenGL15Renderer::SubmitDraw(
|
|||||||
glMaterialfv(GL_FRONT, GL_SPECULAR, noSpec);
|
glMaterialfv(GL_FRONT, GL_SPECULAR, noSpec);
|
||||||
}
|
}
|
||||||
|
|
||||||
glBegin(GL_TRIANGLES);
|
std::vector<D3DVECTOR> positions;
|
||||||
for (size_t i = 0; i < count; i++) {
|
positions.resize(newVertices.size());
|
||||||
const D3DRMVERTEX& v = vertices[i];
|
std::transform(newVertices.begin(), newVertices.end(), positions.begin(), [](const D3DRMVERTEX& v) {
|
||||||
glNormal3f(v.normal.x, v.normal.y, v.normal.z);
|
return v.position;
|
||||||
glTexCoord2f(v.texCoord.u, v.texCoord.v);
|
});
|
||||||
glVertex3f(v.position.x, v.position.y, v.position.z);
|
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();
|
glPopMatrix();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,6 +3,7 @@
|
|||||||
#include "d3drmrenderer_sdl3gpu.h"
|
#include "d3drmrenderer_sdl3gpu.h"
|
||||||
#include "ddraw_impl.h"
|
#include "ddraw_impl.h"
|
||||||
#include "mathutils.h"
|
#include "mathutils.h"
|
||||||
|
#include "meshutils.h"
|
||||||
#include "miniwin.h"
|
#include "miniwin.h"
|
||||||
|
|
||||||
#include <SDL3/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
@ -600,7 +601,9 @@ SDL_GPUTransferBuffer* Direct3DRMSDL3GPURenderer::GetUploadBuffer(size_t size)
|
|||||||
|
|
||||||
void Direct3DRMSDL3GPURenderer::SubmitDraw(
|
void Direct3DRMSDL3GPURenderer::SubmitDraw(
|
||||||
const D3DRMVERTEX* vertices,
|
const D3DRMVERTEX* vertices,
|
||||||
const size_t count,
|
const size_t vertexCount,
|
||||||
|
const DWORD* indices,
|
||||||
|
const size_t indexCount,
|
||||||
const D3DRMMATRIX4D& worldMatrix,
|
const D3DRMMATRIX4D& worldMatrix,
|
||||||
const Matrix3x3& normalMatrix,
|
const Matrix3x3& normalMatrix,
|
||||||
const Appearance& appearance
|
const Appearance& appearance
|
||||||
@ -613,21 +616,46 @@ void Direct3DRMSDL3GPURenderer::SubmitDraw(
|
|||||||
m_fragmentShadingData.color = appearance.color;
|
m_fragmentShadingData.color = appearance.color;
|
||||||
m_fragmentShadingData.shininess = appearance.shininess;
|
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) {
|
if (m_vertexBuffer) {
|
||||||
SDL_ReleaseGPUBuffer(m_device, m_vertexBuffer);
|
SDL_ReleaseGPUBuffer(m_device, m_vertexBuffer);
|
||||||
}
|
}
|
||||||
SDL_GPUBufferCreateInfo bufferCreateInfo = {};
|
SDL_GPUBufferCreateInfo bufferCreateInfo = {};
|
||||||
bufferCreateInfo.usage = SDL_GPU_BUFFERUSAGE_VERTEX;
|
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);
|
m_vertexBuffer = SDL_CreateGPUBuffer(m_device, &bufferCreateInfo);
|
||||||
if (!m_vertexBuffer) {
|
if (!m_vertexBuffer) {
|
||||||
SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_CreateGPUBuffer failed (%s)", SDL_GetError());
|
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);
|
SDL_GPUTransferBuffer* uploadBuffer = GetUploadBuffer(sizeof(D3DRMVERTEX) * m_vertexCount);
|
||||||
if (!uploadBuffer) {
|
if (!uploadBuffer) {
|
||||||
@ -639,7 +667,7 @@ void Direct3DRMSDL3GPURenderer::SubmitDraw(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(transferData, vertices, m_vertexCount * sizeof(D3DRMVERTEX));
|
memcpy(transferData, flatVertices.data(), m_vertexCount * sizeof(D3DRMVERTEX));
|
||||||
SDL_UnmapGPUTransferBuffer(m_device, uploadBuffer);
|
SDL_UnmapGPUTransferBuffer(m_device, uploadBuffer);
|
||||||
|
|
||||||
// Upload the transfer data to the vertex buffer
|
// Upload the transfer data to the vertex buffer
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
#include "d3drmrenderer_software.h"
|
#include "d3drmrenderer_software.h"
|
||||||
#include "ddsurface_impl.h"
|
#include "ddsurface_impl.h"
|
||||||
#include "mathutils.h"
|
#include "mathutils.h"
|
||||||
|
#include "meshutils.h"
|
||||||
#include "miniwin.h"
|
#include "miniwin.h"
|
||||||
|
|
||||||
#include <SDL3/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
@ -145,15 +146,15 @@ void Direct3DRMSoftwareRenderer::BlendPixel(Uint8* pixelAddr, Uint8 r, Uint8 g,
|
|||||||
memcpy(pixelAddr, &blended, m_bytesPerPixel);
|
memcpy(pixelAddr, &blended, m_bytesPerPixel);
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_Color Direct3DRMSoftwareRenderer::ApplyLighting(const D3DRMVERTEX& vertex, const Appearance& appearance)
|
SDL_Color Direct3DRMSoftwareRenderer::ApplyLighting(
|
||||||
|
const D3DVECTOR& position,
|
||||||
|
const D3DVECTOR& normal,
|
||||||
|
const Appearance& appearance
|
||||||
|
)
|
||||||
{
|
{
|
||||||
FColor specular = {0, 0, 0, 0};
|
FColor specular = {0, 0, 0, 0};
|
||||||
FColor diffuse = {0, 0, 0, 0};
|
FColor diffuse = {0, 0, 0, 0};
|
||||||
|
|
||||||
// Position and normal
|
|
||||||
D3DVECTOR position = vertex.position;
|
|
||||||
D3DVECTOR normal = Normalize(vertex.normal);
|
|
||||||
|
|
||||||
for (const auto& light : m_lights) {
|
for (const auto& light : m_lights) {
|
||||||
FColor lightColor = light.color;
|
FColor lightColor = light.color;
|
||||||
|
|
||||||
@ -200,6 +201,16 @@ SDL_Color Direct3DRMSoftwareRenderer::ApplyLighting(const D3DRMVERTEX& vertex, c
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline float EdgeFloat(float x0, float y0, float x1, float y1, float x, float y)
|
||||||
|
{
|
||||||
|
return (x - x0) * (y1 - y0) - (y - y0) * (x1 - x0);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline float EdgeDouble(double x0, double y0, double x1, double y1, double x, double y)
|
||||||
|
{
|
||||||
|
return (x - x0) * (y1 - y0) - (y - y0) * (x1 - x0);
|
||||||
|
}
|
||||||
|
|
||||||
void Direct3DRMSoftwareRenderer::DrawTriangleProjected(
|
void Direct3DRMSoftwareRenderer::DrawTriangleProjected(
|
||||||
const D3DRMVERTEX& v0,
|
const D3DRMVERTEX& v0,
|
||||||
const D3DRMVERTEX& v1,
|
const D3DRMVERTEX& v1,
|
||||||
@ -234,19 +245,20 @@ void Direct3DRMSoftwareRenderer::DrawTriangleProjected(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto edge = [](double x0, double y0, double x1, double y1, double x, double y) {
|
// Cull backfaces
|
||||||
return (x - x0) * (y1 - y0) - (y - y0) * (x1 - x0);
|
float area = EdgeFloat(p0.x, p0.y, p1.x, p1.y, p2.x, p2.y);
|
||||||
};
|
|
||||||
float area = edge(p0.x, p0.y, p1.x, p1.y, p2.x, p2.y);
|
|
||||||
if (area >= 0) {
|
if (area >= 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
float invArea = 1.0f / area;
|
float invArea = 1.0f / area;
|
||||||
|
|
||||||
// Per-vertex lighting using vertex normals
|
Uint8 r, g, b;
|
||||||
SDL_Color c0 = ApplyLighting(v0, appearance);
|
SDL_Color c0 = ApplyLighting(v0.position, v0.normal, appearance);
|
||||||
SDL_Color c1 = ApplyLighting(v1, appearance);
|
SDL_Color c1, c2;
|
||||||
SDL_Color c2 = ApplyLighting(v2, appearance);
|
if (!appearance.flat) {
|
||||||
|
c1 = ApplyLighting(v1.position, v1.normal, appearance);
|
||||||
|
c2 = ApplyLighting(v2.position, v2.normal, appearance);
|
||||||
|
}
|
||||||
|
|
||||||
Uint32 textureId = appearance.textureId;
|
Uint32 textureId = appearance.textureId;
|
||||||
int texturePitch;
|
int texturePitch;
|
||||||
@ -270,12 +282,12 @@ void Direct3DRMSoftwareRenderer::DrawTriangleProjected(
|
|||||||
for (int x = minX; x <= maxX; ++x) {
|
for (int x = minX; x <= maxX; ++x) {
|
||||||
float px = x + 0.5f;
|
float px = x + 0.5f;
|
||||||
float py = y + 0.5f;
|
float py = y + 0.5f;
|
||||||
float w0 = edge(p1.x, p1.y, p2.x, p2.y, px, py) * invArea;
|
float w0 = EdgeDouble(p1.x, p1.y, p2.x, p2.y, px, py) * invArea;
|
||||||
if (w0 < 0.0f || w0 > 1.0f) {
|
if (w0 < 0.0f || w0 > 1.0f) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
float w1 = edge(p2.x, p2.y, p0.x, p0.y, px, py) * invArea;
|
float w1 = EdgeDouble(p2.x, p2.y, p0.x, p0.y, px, py) * invArea;
|
||||||
if (w1 < 0.0f || w1 > 1.0f - w0) {
|
if (w1 < 0.0f || w1 > 1.0f - w0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -289,10 +301,16 @@ void Direct3DRMSoftwareRenderer::DrawTriangleProjected(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Interpolate color
|
if (appearance.flat) {
|
||||||
Uint8 r = static_cast<Uint8>(w0 * c0.r + w1 * c1.r + w2 * c2.r);
|
r = c0.r;
|
||||||
Uint8 g = static_cast<Uint8>(w0 * c0.g + w1 * c1.g + w2 * c2.g);
|
g = c0.g;
|
||||||
Uint8 b = static_cast<Uint8>(w0 * c0.b + w1 * c1.b + w2 * c2.b);
|
b = c0.b;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
r = static_cast<Uint8>(w0 * c0.r + w1 * c1.r + w2 * c2.r);
|
||||||
|
g = static_cast<Uint8>(w0 * c0.g + w1 * c1.g + w2 * c2.g);
|
||||||
|
b = static_cast<Uint8>(w0 * c0.b + w1 * c1.b + w2 * c2.b);
|
||||||
|
}
|
||||||
Uint8* pixelAddr = pixels + y * pitch + x * m_bytesPerPixel;
|
Uint8* pixelAddr = pixels + y * pitch + x * m_bytesPerPixel;
|
||||||
|
|
||||||
if (appearance.color.a == 255) {
|
if (appearance.color.a == 255) {
|
||||||
@ -321,8 +339,22 @@ void Direct3DRMSoftwareRenderer::DrawTriangleProjected(
|
|||||||
|
|
||||||
Uint8* texelAddr = texels + texY * texturePitch + texX * m_bytesPerPixel;
|
Uint8* texelAddr = texels + texY * texturePitch + texX * m_bytesPerPixel;
|
||||||
|
|
||||||
Uint32 texelColor = 0;
|
Uint32 texelColor;
|
||||||
memcpy(&texelColor, texelAddr, m_bytesPerPixel);
|
switch (m_bytesPerPixel) {
|
||||||
|
case 1:
|
||||||
|
texelColor = *texelAddr;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
texelColor = *(Uint16*) texelAddr;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
// Manually build the 24-bit color (assuming byte order)
|
||||||
|
texelColor = texelAddr[0] | (texelAddr[1] << 8) | (texelAddr[2] << 16);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
texelColor = *(Uint32*) texelAddr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
Uint8 tr, tg, tb, ta;
|
Uint8 tr, tg, tb, ta;
|
||||||
SDL_GetRGBA(texelColor, m_format, m_palette, &tr, &tg, &tb, &ta);
|
SDL_GetRGBA(texelColor, m_format, m_palette, &tr, &tg, &tb, &ta);
|
||||||
@ -452,7 +484,9 @@ HRESULT Direct3DRMSoftwareRenderer::BeginFrame(const D3DRMMATRIX4D& viewMatrix)
|
|||||||
|
|
||||||
void Direct3DRMSoftwareRenderer::SubmitDraw(
|
void Direct3DRMSoftwareRenderer::SubmitDraw(
|
||||||
const D3DRMVERTEX* vertices,
|
const D3DRMVERTEX* vertices,
|
||||||
const size_t count,
|
const size_t vertexCount,
|
||||||
|
const DWORD* indices,
|
||||||
|
const size_t indexCount,
|
||||||
const D3DRMMATRIX4D& worldMatrix,
|
const D3DRMMATRIX4D& worldMatrix,
|
||||||
const Matrix3x3& normalMatrix,
|
const Matrix3x3& normalMatrix,
|
||||||
const Appearance& appearance
|
const Appearance& appearance
|
||||||
@ -461,15 +495,42 @@ void Direct3DRMSoftwareRenderer::SubmitDraw(
|
|||||||
D3DRMMATRIX4D mvMatrix;
|
D3DRMMATRIX4D mvMatrix;
|
||||||
MultiplyMatrix(mvMatrix, worldMatrix, m_viewMatrix);
|
MultiplyMatrix(mvMatrix, worldMatrix, m_viewMatrix);
|
||||||
|
|
||||||
for (size_t i = 0; i + 2 < count; i += 3) {
|
std::vector<D3DRMVERTEX> newVertices;
|
||||||
D3DRMVERTEX vrts[3];
|
std::vector<DWORD> newIndices;
|
||||||
for (size_t j = 0; j < 3; ++j) {
|
if (appearance.flat) {
|
||||||
const D3DRMVERTEX& src = vertices[i + j];
|
// FIXME move this to a one time mesh upload stage
|
||||||
vrts[j].position = TransformPoint(src.position, mvMatrix);
|
FlattenSurfaces(
|
||||||
vrts[j].normal = Normalize(TransformNormal(src.normal, normalMatrix));
|
vertices,
|
||||||
vrts[j].texCoord = src.texCoord;
|
vertexCount,
|
||||||
|
indices,
|
||||||
|
indexCount,
|
||||||
|
appearance.textureId != NO_TEXTURE_ID,
|
||||||
|
newVertices,
|
||||||
|
newIndices
|
||||||
|
);
|
||||||
}
|
}
|
||||||
DrawTriangleClipped(vrts, appearance);
|
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;
|
group.vertexPerFace = vertexPerFace;
|
||||||
|
|
||||||
DWORD* src = faceBuffer;
|
DWORD* src = faceBuffer;
|
||||||
group.faces.assign(src, src + faceCount * vertexPerFace);
|
group.indices.assign(src, src + faceCount * vertexPerFace);
|
||||||
|
|
||||||
m_groups.push_back(std::move(group));
|
m_groups.push_back(std::move(group));
|
||||||
|
|
||||||
@ -72,8 +72,8 @@ HRESULT Direct3DRMMeshImpl::GetGroup(
|
|||||||
DWORD* vertexCount,
|
DWORD* vertexCount,
|
||||||
DWORD* faceCount,
|
DWORD* faceCount,
|
||||||
DWORD* vertexPerFace,
|
DWORD* vertexPerFace,
|
||||||
DWORD* dataSize,
|
DWORD* indexCount,
|
||||||
DWORD* data
|
DWORD* indices
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if (groupIndex >= m_groups.size()) {
|
if (groupIndex >= m_groups.size()) {
|
||||||
@ -86,16 +86,16 @@ HRESULT Direct3DRMMeshImpl::GetGroup(
|
|||||||
*vertexCount = static_cast<DWORD>(group.vertices.size());
|
*vertexCount = static_cast<DWORD>(group.vertices.size());
|
||||||
}
|
}
|
||||||
if (faceCount) {
|
if (faceCount) {
|
||||||
*faceCount = static_cast<DWORD>(group.faces.size() / group.vertexPerFace);
|
*faceCount = static_cast<DWORD>(group.indices.size() / group.vertexPerFace);
|
||||||
}
|
}
|
||||||
if (vertexPerFace) {
|
if (vertexPerFace) {
|
||||||
*vertexPerFace = static_cast<DWORD>(group.vertexPerFace);
|
*vertexPerFace = static_cast<DWORD>(group.vertexPerFace);
|
||||||
}
|
}
|
||||||
if (dataSize) {
|
if (indexCount) {
|
||||||
*dataSize = static_cast<DWORD>(group.faces.size());
|
*indexCount = static_cast<DWORD>(group.indices.size());
|
||||||
}
|
}
|
||||||
if (data) {
|
if (indices) {
|
||||||
std::copy(group.faces.begin(), group.faces.end(), reinterpret_cast<unsigned int*>(data));
|
std::copy(group.indices.begin(), group.indices.end(), reinterpret_cast<unsigned int*>(indices));
|
||||||
}
|
}
|
||||||
|
|
||||||
return DD_OK;
|
return DD_OK;
|
||||||
|
|||||||
@ -95,21 +95,6 @@ static void ComputeFrameWorldMatrix(IDirect3DRMFrame* frame, D3DRMMATRIX4D out)
|
|||||||
memcpy(out, acc, sizeof(acc));
|
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(
|
void Direct3DRMViewportImpl::CollectLightsFromFrame(
|
||||||
IDirect3DRMFrame* frame,
|
IDirect3DRMFrame* frame,
|
||||||
D3DRMMATRIX4D parentToWorld,
|
D3DRMMATRIX4D parentToWorld,
|
||||||
@ -215,9 +200,8 @@ bool IsBoxInFrustum(const D3DVECTOR corners[8], const Plane planes[6])
|
|||||||
void Direct3DRMViewportImpl::CollectMeshesFromFrame(
|
void Direct3DRMViewportImpl::CollectMeshesFromFrame(
|
||||||
IDirect3DRMFrame* frame,
|
IDirect3DRMFrame* frame,
|
||||||
D3DRMMATRIX4D parentMatrix,
|
D3DRMMATRIX4D parentMatrix,
|
||||||
std::vector<D3DRMVERTEX>& verts,
|
|
||||||
std::vector<D3DRMVERTEX>& d3dVerts,
|
std::vector<D3DRMVERTEX>& d3dVerts,
|
||||||
std::vector<DWORD>& faces
|
std::vector<DWORD>& indices
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
Direct3DRMFrameImpl* frameImpl = static_cast<Direct3DRMFrameImpl*>(frame);
|
Direct3DRMFrameImpl* frameImpl = static_cast<Direct3DRMFrameImpl*>(frame);
|
||||||
@ -242,7 +226,7 @@ void Direct3DRMViewportImpl::CollectMeshesFromFrame(
|
|||||||
IDirect3DRMFrame* childFrame = nullptr;
|
IDirect3DRMFrame* childFrame = nullptr;
|
||||||
visual->QueryInterface(IID_IDirect3DRMFrame, (void**) &childFrame);
|
visual->QueryInterface(IID_IDirect3DRMFrame, (void**) &childFrame);
|
||||||
if (childFrame) {
|
if (childFrame) {
|
||||||
CollectMeshesFromFrame(childFrame, worldMatrix, verts, d3dVerts, faces);
|
CollectMeshesFromFrame(childFrame, worldMatrix, d3dVerts, indices);
|
||||||
childFrame->Release();
|
childFrame->Release();
|
||||||
visual->Release();
|
visual->Release();
|
||||||
continue;
|
continue;
|
||||||
@ -278,19 +262,16 @@ void Direct3DRMViewportImpl::CollectMeshesFromFrame(
|
|||||||
|
|
||||||
DWORD groupCount = mesh->GetGroupCount();
|
DWORD groupCount = mesh->GetGroupCount();
|
||||||
for (DWORD gi = 0; gi < groupCount; ++gi) {
|
for (DWORD gi = 0; gi < groupCount; ++gi) {
|
||||||
DWORD vtxCount, faceCount, vpf, dataSize;
|
DWORD vtxCount, indexCount;
|
||||||
mesh->GetGroup(gi, &vtxCount, &faceCount, &vpf, &dataSize, nullptr);
|
mesh->GetGroup(gi, &vtxCount, nullptr, nullptr, &indexCount, nullptr);
|
||||||
|
|
||||||
verts.reserve(dataSize);
|
|
||||||
verts.clear();
|
|
||||||
d3dVerts.resize(vtxCount);
|
d3dVerts.resize(vtxCount);
|
||||||
faces.resize(dataSize);
|
indices.resize(indexCount);
|
||||||
mesh->GetVertices(gi, 0, vtxCount, d3dVerts.data());
|
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);
|
D3DCOLOR color = mesh->GetGroupColor(gi);
|
||||||
D3DRMRENDERQUALITY quality = mesh->GetGroupQuality(gi);
|
D3DRMRENDERQUALITY quality = mesh->GetGroupQuality(gi);
|
||||||
bool flat = quality == D3DRMRENDER_FLAT || quality == D3DRMRENDER_UNLITFLAT;
|
|
||||||
|
|
||||||
IDirect3DRMTexture* texture = nullptr;
|
IDirect3DRMTexture* texture = nullptr;
|
||||||
mesh->GetGroupTexture(gi, &texture);
|
mesh->GetGroupTexture(gi, &texture);
|
||||||
@ -308,28 +289,11 @@ void Direct3DRMViewportImpl::CollectMeshesFromFrame(
|
|||||||
material->Release();
|
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(
|
m_renderer->SubmitDraw(
|
||||||
verts.data(),
|
d3dVerts.data(),
|
||||||
verts.size(),
|
d3dVerts.size(),
|
||||||
|
indices.data(),
|
||||||
|
indices.size(),
|
||||||
worldMatrix,
|
worldMatrix,
|
||||||
worldMatrixInvert,
|
worldMatrixInvert,
|
||||||
{{static_cast<Uint8>((color >> 16) & 0xFF),
|
{{static_cast<Uint8>((color >> 16) & 0xFF),
|
||||||
@ -338,7 +302,7 @@ void Direct3DRMViewportImpl::CollectMeshesFromFrame(
|
|||||||
static_cast<Uint8>((color >> 24) & 0xFF)},
|
static_cast<Uint8>((color >> 24) & 0xFF)},
|
||||||
shininess,
|
shininess,
|
||||||
textureId,
|
textureId,
|
||||||
flat}
|
quality == D3DRMRENDER_FLAT || quality == D3DRMRENDER_UNLITFLAT}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
mesh->Release();
|
mesh->Release();
|
||||||
@ -367,11 +331,10 @@ HRESULT Direct3DRMViewportImpl::RenderScene()
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<D3DRMVERTEX> verts;
|
|
||||||
std::vector<D3DRMVERTEX> d3dVerts;
|
std::vector<D3DRMVERTEX> d3dVerts;
|
||||||
std::vector<DWORD> faces;
|
std::vector<DWORD> indices;
|
||||||
ExtractFrustumPlanes(viewProj);
|
ExtractFrustumPlanes(viewProj);
|
||||||
CollectMeshesFromFrame(m_rootFrame, identity, verts, d3dVerts, faces);
|
CollectMeshesFromFrame(m_rootFrame, identity, d3dVerts, indices);
|
||||||
return m_renderer->FinalizeFrame();
|
return m_renderer->FinalizeFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -726,23 +689,19 @@ bool RayIntersectsMeshTriangles(
|
|||||||
{
|
{
|
||||||
DWORD groupCount = mesh->GetGroupCount();
|
DWORD groupCount = mesh->GetGroupCount();
|
||||||
for (DWORD g = 0; g < groupCount; ++g) {
|
for (DWORD g = 0; g < groupCount; ++g) {
|
||||||
DWORD vtxCount = 0, faceCount = 0, vpf = 0, dataSize = 0;
|
DWORD vtxCount, faceCount, indexCount;
|
||||||
mesh->GetGroup(g, &vtxCount, &faceCount, &vpf, &dataSize, nullptr);
|
mesh->GetGroup(g, &vtxCount, &faceCount, nullptr, &indexCount, nullptr);
|
||||||
|
|
||||||
std::vector<D3DRMVERTEX> vertices(vtxCount);
|
std::vector<D3DRMVERTEX> vertices(vtxCount);
|
||||||
mesh->GetVertices(g, 0, vtxCount, vertices.data());
|
mesh->GetVertices(g, 0, vtxCount, vertices.data());
|
||||||
std::vector<DWORD> faces(faceCount * vpf);
|
std::vector<DWORD> indices(indexCount);
|
||||||
mesh->GetGroup(g, nullptr, nullptr, nullptr, nullptr, faces.data());
|
mesh->GetGroup(g, nullptr, nullptr, nullptr, nullptr, indices.data());
|
||||||
|
|
||||||
// Iterate over each face and do ray-triangle tests
|
// Iterate over each face and do ray-triangle tests
|
||||||
for (DWORD fi = 0; fi < faceCount; ++fi) {
|
for (DWORD fi = 0; fi < faceCount; fi += 3) {
|
||||||
DWORD i0 = faces[fi * vpf + 0];
|
DWORD i0 = indices[fi + 0];
|
||||||
DWORD i1 = faces[fi * vpf + 1];
|
DWORD i1 = indices[fi + 1];
|
||||||
DWORD i2 = faces[fi * vpf + 2];
|
DWORD i2 = indices[fi + 2];
|
||||||
|
|
||||||
if (i0 >= vtxCount || i1 >= vtxCount || i2 >= vtxCount) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Transform vertices to world space
|
// Transform vertices to world space
|
||||||
D3DVECTOR tri[3];
|
D3DVECTOR tri[3];
|
||||||
|
|||||||
@ -12,13 +12,13 @@ struct MeshGroup {
|
|||||||
D3DRMRENDERQUALITY quality = D3DRMRENDER_GOURAUD;
|
D3DRMRENDERQUALITY quality = D3DRMRENDER_GOURAUD;
|
||||||
int vertexPerFace = 0;
|
int vertexPerFace = 0;
|
||||||
std::vector<D3DRMVERTEX> vertices;
|
std::vector<D3DRMVERTEX> vertices;
|
||||||
std::vector<unsigned int> faces;
|
std::vector<unsigned int> indices;
|
||||||
|
|
||||||
MeshGroup() = default;
|
MeshGroup() = default;
|
||||||
|
|
||||||
MeshGroup(const MeshGroup& other)
|
MeshGroup(const MeshGroup& other)
|
||||||
: color(other.color), texture(other.texture), material(other.material), quality(other.quality),
|
: 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) {
|
if (texture) {
|
||||||
texture->AddRef();
|
texture->AddRef();
|
||||||
@ -31,7 +31,7 @@ struct MeshGroup {
|
|||||||
// Move constructor
|
// Move constructor
|
||||||
MeshGroup(MeshGroup&& other) noexcept
|
MeshGroup(MeshGroup&& other) noexcept
|
||||||
: color(other.color), texture(other.texture), material(other.material), quality(other.quality),
|
: 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.texture = nullptr;
|
||||||
other.material = nullptr;
|
other.material = nullptr;
|
||||||
@ -46,7 +46,7 @@ struct MeshGroup {
|
|||||||
quality = other.quality;
|
quality = other.quality;
|
||||||
vertexPerFace = other.vertexPerFace;
|
vertexPerFace = other.vertexPerFace;
|
||||||
vertices = std::move(other.vertices);
|
vertices = std::move(other.vertices);
|
||||||
faces = std::move(other.faces);
|
indices = std::move(other.indices);
|
||||||
other.texture = nullptr;
|
other.texture = nullptr;
|
||||||
other.material = nullptr;
|
other.material = nullptr;
|
||||||
return *this;
|
return *this;
|
||||||
@ -73,8 +73,8 @@ struct Direct3DRMMeshImpl : public Direct3DRMObjectBaseImpl<IDirect3DRMMesh> {
|
|||||||
DWORD* vertexCount,
|
DWORD* vertexCount,
|
||||||
DWORD* faceCount,
|
DWORD* faceCount,
|
||||||
DWORD* vertexPerFace,
|
DWORD* vertexPerFace,
|
||||||
DWORD* dataSize,
|
DWORD* indexCount,
|
||||||
DWORD* data
|
DWORD* indices
|
||||||
) override;
|
) override;
|
||||||
DWORD GetGroupCount() override;
|
DWORD GetGroupCount() override;
|
||||||
HRESULT SetGroupColor(DWORD groupIndex, D3DCOLOR color) override;
|
HRESULT SetGroupColor(DWORD groupIndex, D3DCOLOR color) override;
|
||||||
|
|||||||
@ -14,7 +14,7 @@ struct Appearance {
|
|||||||
SDL_Color color;
|
SDL_Color color;
|
||||||
float shininess;
|
float shininess;
|
||||||
Uint32 textureId;
|
Uint32 textureId;
|
||||||
bool flat;
|
Uint32 flat;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FColor {
|
struct FColor {
|
||||||
@ -42,7 +42,9 @@ class Direct3DRMRenderer : public IDirect3DDevice2 {
|
|||||||
virtual HRESULT BeginFrame(const D3DRMMATRIX4D& viewMatrix) = 0;
|
virtual HRESULT BeginFrame(const D3DRMMATRIX4D& viewMatrix) = 0;
|
||||||
virtual void SubmitDraw(
|
virtual void SubmitDraw(
|
||||||
const D3DRMVERTEX* vertices,
|
const D3DRMVERTEX* vertices,
|
||||||
const size_t count,
|
const size_t vertexCount,
|
||||||
|
const DWORD* indices,
|
||||||
|
const size_t indexCount,
|
||||||
const D3DRMMATRIX4D& worldMatrix,
|
const D3DRMMATRIX4D& worldMatrix,
|
||||||
const Matrix3x3& normalMatrix,
|
const Matrix3x3& normalMatrix,
|
||||||
const Appearance& appearance
|
const Appearance& appearance
|
||||||
|
|||||||
@ -31,7 +31,9 @@ class OpenGL15Renderer : public Direct3DRMRenderer {
|
|||||||
HRESULT BeginFrame(const D3DRMMATRIX4D& viewMatrix) override;
|
HRESULT BeginFrame(const D3DRMMATRIX4D& viewMatrix) override;
|
||||||
void SubmitDraw(
|
void SubmitDraw(
|
||||||
const D3DRMVERTEX* vertices,
|
const D3DRMVERTEX* vertices,
|
||||||
const size_t count,
|
const size_t vertexCount,
|
||||||
|
const DWORD* indices,
|
||||||
|
const size_t indexCount,
|
||||||
const D3DRMMATRIX4D& worldMatrix,
|
const D3DRMMATRIX4D& worldMatrix,
|
||||||
const Matrix3x3& normalMatrix,
|
const Matrix3x3& normalMatrix,
|
||||||
const Appearance& appearance
|
const Appearance& appearance
|
||||||
|
|||||||
@ -48,7 +48,9 @@ class Direct3DRMSDL3GPURenderer : public Direct3DRMRenderer {
|
|||||||
HRESULT BeginFrame(const D3DRMMATRIX4D& viewMatrix) override;
|
HRESULT BeginFrame(const D3DRMMATRIX4D& viewMatrix) override;
|
||||||
void SubmitDraw(
|
void SubmitDraw(
|
||||||
const D3DRMVERTEX* vertices,
|
const D3DRMVERTEX* vertices,
|
||||||
const size_t count,
|
const size_t vertexCount,
|
||||||
|
const DWORD* indices,
|
||||||
|
const size_t indexCount,
|
||||||
const D3DRMMATRIX4D& worldMatrix,
|
const D3DRMMATRIX4D& worldMatrix,
|
||||||
const Matrix3x3& normalMatrix,
|
const Matrix3x3& normalMatrix,
|
||||||
const Appearance& appearance
|
const Appearance& appearance
|
||||||
|
|||||||
@ -29,7 +29,9 @@ class Direct3DRMSoftwareRenderer : public Direct3DRMRenderer {
|
|||||||
HRESULT BeginFrame(const D3DRMMATRIX4D& viewMatrix) override;
|
HRESULT BeginFrame(const D3DRMMATRIX4D& viewMatrix) override;
|
||||||
void SubmitDraw(
|
void SubmitDraw(
|
||||||
const D3DRMVERTEX* vertices,
|
const D3DRMVERTEX* vertices,
|
||||||
const size_t count,
|
const size_t vertexCount,
|
||||||
|
const DWORD* indices,
|
||||||
|
const size_t indexCount,
|
||||||
const D3DRMMATRIX4D& worldMatrix,
|
const D3DRMMATRIX4D& worldMatrix,
|
||||||
const Matrix3x3& normalMatrix,
|
const Matrix3x3& normalMatrix,
|
||||||
const Appearance& appearance
|
const Appearance& appearance
|
||||||
@ -48,7 +50,7 @@ class Direct3DRMSoftwareRenderer : public Direct3DRMRenderer {
|
|||||||
void DrawTriangleClipped(const D3DRMVERTEX (&v)[3], const Appearance& appearance);
|
void DrawTriangleClipped(const D3DRMVERTEX (&v)[3], const Appearance& appearance);
|
||||||
void ProjectVertex(const D3DRMVERTEX& v, D3DRMVECTOR4D& p) const;
|
void ProjectVertex(const D3DRMVERTEX& v, D3DRMVECTOR4D& p) const;
|
||||||
void BlendPixel(Uint8* pixelAddr, Uint8 r, Uint8 g, Uint8 b, Uint8 a);
|
void BlendPixel(Uint8* pixelAddr, Uint8 r, Uint8 g, Uint8 b, Uint8 a);
|
||||||
SDL_Color ApplyLighting(const D3DRMVERTEX& vertex, const Appearance& appearance);
|
SDL_Color ApplyLighting(const D3DVECTOR& position, const D3DVECTOR& normal, const Appearance& appearance);
|
||||||
void AddTextureDestroyCallback(Uint32 id, IDirect3DRMTexture* texture);
|
void AddTextureDestroyCallback(Uint32 id, IDirect3DRMTexture* texture);
|
||||||
|
|
||||||
DWORD m_width;
|
DWORD m_width;
|
||||||
|
|||||||
@ -40,7 +40,6 @@ struct Direct3DRMViewportImpl : public Direct3DRMObjectBaseImpl<IDirect3DRMViewp
|
|||||||
void CollectMeshesFromFrame(
|
void CollectMeshesFromFrame(
|
||||||
IDirect3DRMFrame* frame,
|
IDirect3DRMFrame* frame,
|
||||||
D3DRMMATRIX4D parentMatrix,
|
D3DRMMATRIX4D parentMatrix,
|
||||||
std::vector<D3DRMVERTEX>& verts,
|
|
||||||
std::vector<D3DRMVERTEX>& d3dVerts,
|
std::vector<D3DRMVERTEX>& d3dVerts,
|
||||||
std::vector<DWORD>& faces
|
std::vector<DWORD>& faces
|
||||||
);
|
);
|
||||||
|
|||||||
@ -25,6 +25,11 @@ inline D3DVECTOR Normalize(const D3DVECTOR& v)
|
|||||||
return {0, 0, 0};
|
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)
|
inline D3DVECTOR TransformPoint(const D3DVECTOR& p, const D3DRMMATRIX4D& m)
|
||||||
{
|
{
|
||||||
return {
|
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