From 771801d826b9050498d2a4dee410b552f9770b55 Mon Sep 17 00:00:00 2001 From: Anders Jenbo Date: Wed, 4 Jun 2025 04:48:30 +0200 Subject: [PATCH] Implement InverseTransform() --- miniwin/src/d3drm/d3drmviewport.cpp | 49 ++++++++++++++++++++++- miniwin/src/internal/d3drmviewport_impl.h | 1 + 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/miniwin/src/d3drm/d3drmviewport.cpp b/miniwin/src/d3drm/d3drmviewport.cpp index 39108ba2..55184c17 100644 --- a/miniwin/src/d3drm/d3drmviewport.cpp +++ b/miniwin/src/d3drm/d3drmviewport.cpp @@ -446,10 +446,17 @@ void Direct3DRMViewportImpl::UpdateProjectionMatrix() {0, 0, m_back / depth, 1}, {0, 0, (-m_front * m_back) / depth, 0}, }; - memcpy(m_projectionMatrix, projection, sizeof(D3DRMMATRIX4D)); m_renderer->SetProjection(projection, m_front, m_back); + + D3DRMMATRIX4D inverseProjectionMatrix = { + {1.0f / f, 0, 0, 0}, + {0, 1.0f / (f * aspect), 0, 0}, + {0, 0, 0, depth / (-m_front * m_back)}, + {0, 0, 1, -(m_back / depth) * depth / (-m_front * m_back)}, + }; + memcpy(m_inverseProjectionMatrix, inverseProjectionMatrix, sizeof(D3DRMMATRIX4D)); } D3DVALUE Direct3DRMViewportImpl::GetField() @@ -506,7 +513,45 @@ HRESULT Direct3DRMViewportImpl::Transform(D3DRMVECTOR4D* screen, D3DVECTOR* worl HRESULT Direct3DRMViewportImpl::InverseTransform(D3DVECTOR* world, D3DRMVECTOR4D* screen) { - MINIWIN_NOT_IMPLEMENTED(); + // Convert to screen coordinates + float screenX = screen->x / screen->z; + float screenY = screen->y / screen->w; + + // Convert screen coordinates to NDC + float ndcX = screenX / m_width * 2.0f - 1.0f; + float ndcY = 1.0f - (screenY / m_height) * 2.0f; + + float clipVec[4] = {ndcX * screen->w, ndcY * screen->w, screen->z, screen->w}; + + float viewVec[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + viewVec[j] += m_inverseProjectionMatrix[i][j] * clipVec[i]; + } + } + + float invViewMatrix[4][4]; + D3DRMMatrixInvertOrthogonal(invViewMatrix, m_viewMatrix); + + float worldVec[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + worldVec[j] += invViewMatrix[i][j] * viewVec[i]; + } + } + + // Perspective divide + if (worldVec[3] != 0.0f) { + world->x = worldVec[0] / worldVec[3]; + world->y = worldVec[1] / worldVec[3]; + world->z = worldVec[2] / worldVec[3]; + } + else { + world->x = worldVec[0]; + world->y = worldVec[1]; + world->z = worldVec[2]; + } + return DD_OK; } diff --git a/miniwin/src/internal/d3drmviewport_impl.h b/miniwin/src/internal/d3drmviewport_impl.h index 900c40b5..162230d1 100644 --- a/miniwin/src/internal/d3drmviewport_impl.h +++ b/miniwin/src/internal/d3drmviewport_impl.h @@ -43,6 +43,7 @@ struct Direct3DRMViewportImpl : public Direct3DRMObjectBaseImpl