mirror of
https://github.com/isledecomp/isle-portable.git
synced 2025-09-22 11:31:57 -04:00
Make Lego Islan Fully playable (#230)
This commit is contained in:
parent
0ac7fee23c
commit
72eb992af4
@ -122,9 +122,9 @@ HRESULT Direct3DRMViewportImpl::CollectSceneData()
|
|||||||
std::vector<PositionColorVertex> verts;
|
std::vector<PositionColorVertex> verts;
|
||||||
|
|
||||||
// Compute camera matrix
|
// Compute camera matrix
|
||||||
D3DRMMATRIX4D cameraWorld, viewMatrix;
|
D3DRMMATRIX4D cameraWorld;
|
||||||
ComputeFrameWorldMatrix(m_camera, cameraWorld);
|
ComputeFrameWorldMatrix(m_camera, cameraWorld);
|
||||||
D3DRMMatrixInvertOrthogonal(viewMatrix, cameraWorld);
|
D3DRMMatrixInvertOrthogonal(m_viewMatrix, cameraWorld);
|
||||||
|
|
||||||
std::function<void(IDirect3DRMFrame*, D3DRMMATRIX4D)> recurseFrame;
|
std::function<void(IDirect3DRMFrame*, D3DRMMATRIX4D)> recurseFrame;
|
||||||
std::function<void(IDirect3DRMFrame*, D3DRMMATRIX4D)> recurseChildren;
|
std::function<void(IDirect3DRMFrame*, D3DRMMATRIX4D)> recurseChildren;
|
||||||
@ -270,12 +270,12 @@ HRESULT Direct3DRMViewportImpl::CollectSceneData()
|
|||||||
|
|
||||||
// View transform
|
// View transform
|
||||||
D3DVECTOR viewPos;
|
D3DVECTOR viewPos;
|
||||||
viewPos.x = worldPos.x * viewMatrix[0][0] + worldPos.y * viewMatrix[1][0] +
|
viewPos.x = worldPos.x * m_viewMatrix[0][0] + worldPos.y * m_viewMatrix[1][0] +
|
||||||
worldPos.z * viewMatrix[2][0] + viewMatrix[3][0];
|
worldPos.z * m_viewMatrix[2][0] + m_viewMatrix[3][0];
|
||||||
viewPos.y = worldPos.x * viewMatrix[0][1] + worldPos.y * viewMatrix[1][1] +
|
viewPos.y = worldPos.x * m_viewMatrix[0][1] + worldPos.y * m_viewMatrix[1][1] +
|
||||||
worldPos.z * viewMatrix[2][1] + viewMatrix[3][1];
|
worldPos.z * m_viewMatrix[2][1] + m_viewMatrix[3][1];
|
||||||
viewPos.z = worldPos.x * viewMatrix[0][2] + worldPos.y * viewMatrix[1][2] +
|
viewPos.z = worldPos.x * m_viewMatrix[0][2] + worldPos.y * m_viewMatrix[1][2] +
|
||||||
worldPos.z * viewMatrix[2][2] + viewMatrix[3][2];
|
worldPos.z * m_viewMatrix[2][2] + m_viewMatrix[3][2];
|
||||||
|
|
||||||
// View transform
|
// View transform
|
||||||
D3DVECTOR viewNorm;
|
D3DVECTOR viewNorm;
|
||||||
@ -440,14 +440,23 @@ void Direct3DRMViewportImpl::UpdateProjectionMatrix()
|
|||||||
float f = m_front / m_field;
|
float f = m_front / m_field;
|
||||||
float depth = m_back - m_front;
|
float depth = m_back - m_front;
|
||||||
|
|
||||||
D3DRMMATRIX4D perspective = {
|
D3DRMMATRIX4D projection = {
|
||||||
{f, 0, 0, 0},
|
{f, 0, 0, 0},
|
||||||
{0, f * aspect, 0, 0},
|
{0, f * aspect, 0, 0},
|
||||||
{0, 0, m_back / depth, 1},
|
{0, 0, m_back / depth, 1},
|
||||||
{0, 0, (-m_front * m_back) / depth, 0},
|
{0, 0, (-m_front * m_back) / depth, 0},
|
||||||
};
|
};
|
||||||
|
memcpy(m_projectionMatrix, projection, sizeof(D3DRMMATRIX4D));
|
||||||
|
|
||||||
m_renderer->SetProjection(perspective, m_front, m_back);
|
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()
|
D3DVALUE Direct3DRMViewportImpl::GetField()
|
||||||
@ -467,13 +476,82 @@ DWORD Direct3DRMViewportImpl::GetHeight()
|
|||||||
|
|
||||||
HRESULT Direct3DRMViewportImpl::Transform(D3DRMVECTOR4D* screen, D3DVECTOR* world)
|
HRESULT Direct3DRMViewportImpl::Transform(D3DRMVECTOR4D* screen, D3DVECTOR* world)
|
||||||
{
|
{
|
||||||
MINIWIN_NOT_IMPLEMENTED();
|
D3DRMVECTOR4D worldVec = {world->x, world->y, world->z, 1.0f};
|
||||||
|
|
||||||
|
D3DRMVECTOR4D viewVec;
|
||||||
|
viewVec.x = m_viewMatrix[0][0] * worldVec.x + m_viewMatrix[1][0] * worldVec.y + m_viewMatrix[2][0] * worldVec.z +
|
||||||
|
m_viewMatrix[3][0] * worldVec.w;
|
||||||
|
viewVec.y = m_viewMatrix[0][1] * worldVec.x + m_viewMatrix[1][1] * worldVec.y + m_viewMatrix[2][1] * worldVec.z +
|
||||||
|
m_viewMatrix[3][1] * worldVec.w;
|
||||||
|
viewVec.z = m_viewMatrix[0][2] * worldVec.x + m_viewMatrix[1][2] * worldVec.y + m_viewMatrix[2][2] * worldVec.z +
|
||||||
|
m_viewMatrix[3][2] * worldVec.w;
|
||||||
|
viewVec.w = m_viewMatrix[0][3] * worldVec.x + m_viewMatrix[1][3] * worldVec.y + m_viewMatrix[2][3] * worldVec.z +
|
||||||
|
m_viewMatrix[3][3] * worldVec.w;
|
||||||
|
|
||||||
|
screen->x = viewVec.x * m_projectionMatrix[0][0] + viewVec.y * m_projectionMatrix[1][0] +
|
||||||
|
viewVec.z * m_projectionMatrix[2][0] + viewVec.w * m_projectionMatrix[3][0];
|
||||||
|
screen->y = viewVec.x * m_projectionMatrix[0][1] + viewVec.y * m_projectionMatrix[1][1] +
|
||||||
|
viewVec.z * m_projectionMatrix[2][1] + viewVec.w * m_projectionMatrix[3][1];
|
||||||
|
screen->z = viewVec.x * m_projectionMatrix[0][2] + viewVec.y * m_projectionMatrix[1][2] +
|
||||||
|
viewVec.z * m_projectionMatrix[2][2] + viewVec.w * m_projectionMatrix[3][2];
|
||||||
|
screen->w = viewVec.x * m_projectionMatrix[0][3] + viewVec.y * m_projectionMatrix[1][3] +
|
||||||
|
viewVec.z * m_projectionMatrix[2][3] + viewVec.w * m_projectionMatrix[3][3];
|
||||||
|
|
||||||
|
float invW = 1.0f / screen->w;
|
||||||
|
float ndcX = screen->x * invW;
|
||||||
|
float ndcY = screen->y * invW;
|
||||||
|
|
||||||
|
screen->x = (ndcX * 0.5f + 0.5f) * m_width;
|
||||||
|
screen->y = (1.0f - (ndcY * 0.5f + 0.5f)) * m_height;
|
||||||
|
|
||||||
|
// Undo perspective divide
|
||||||
|
screen->x *= screen->z;
|
||||||
|
screen->y *= screen->w;
|
||||||
|
|
||||||
return DD_OK;
|
return DD_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT Direct3DRMViewportImpl::InverseTransform(D3DVECTOR* world, D3DRMVECTOR4D* screen)
|
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;
|
return DD_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,6 +41,9 @@ private:
|
|||||||
D3DCOLOR m_backgroundColor = 0xFF000000;
|
D3DCOLOR m_backgroundColor = 0xFF000000;
|
||||||
DWORD m_width;
|
DWORD m_width;
|
||||||
DWORD m_height;
|
DWORD m_height;
|
||||||
|
D3DRMMATRIX4D m_viewMatrix;
|
||||||
|
D3DRMMATRIX4D m_projectionMatrix;
|
||||||
|
D3DRMMATRIX4D m_inverseProjectionMatrix;
|
||||||
IDirect3DRMFrame* m_rootFrame = nullptr;
|
IDirect3DRMFrame* m_rootFrame = nullptr;
|
||||||
IDirect3DRMFrame* m_camera = nullptr;
|
IDirect3DRMFrame* m_camera = nullptr;
|
||||||
D3DVALUE m_front = 1.f;
|
D3DVALUE m_front = 1.f;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user