diff --git a/include/rt64_extended_gbi.h b/include/rt64_extended_gbi.h index ba18758..f1cf9b5 100644 --- a/include/rt64_extended_gbi.h +++ b/include/rt64_extended_gbi.h @@ -74,7 +74,8 @@ #define G_EX_SETDITHERNOISESTRENGTH_V1 0x00002B #define G_EX_SETRDRAMEXTENDED_V1 0x00002C #define G_EX_MATRIX_V1 0x00002D -#define G_EX_MAX 0x00002E +#define G_EX_SETINVVIEWMATRIXFLOAT_V1 0x00002E +#define G_EX_MAX 0x00002F #define G_EX_ORIGIN_NONE 0x800 #define G_EX_ORIGIN_LEFT 0x0 @@ -518,12 +519,18 @@ typedef union { PARAM(isExtended, 1, 0) \ ) -#define gEXMatrix(cmd, matrix, matrixp, param) \ +#define gEXMatrix(cmd, matrix, param, matrixp) \ G_EX_COMMAND2(cmd, \ PARAM(RT64_EXTENDED_OPCODE, 8, 24) | PARAM(G_EX_MATRIX_V1, 24, 0), \ - (unsigned)(param), \ (unsigned)(matrix), \ + (unsigned)(param), \ (unsigned)(matrixp) \ ) +#define gEXSetInvViewMatrixFloat(cmd, matrix) \ + G_EX_COMMAND1(cmd, \ + PARAM(RT64_EXTENDED_OPCODE, 8, 24) | PARAM(G_EX_SETINVVIEWMATRIXFLOAT_V1, 24, 0), \ + (unsigned)(matrix) \ + ) + #endif // RT64_EXTENDED_GBI diff --git a/src/gbi/rt64_gbi_extended.cpp b/src/gbi/rt64_gbi_extended.cpp index b41575c..3129b60 100644 --- a/src/gbi/rt64_gbi_extended.cpp +++ b/src/gbi/rt64_gbi_extended.cpp @@ -292,9 +292,13 @@ namespace RT64 { } void matrixV1(State *state, DisplayList **dl) { - uint32_t params = (*dl)->w0; + uint32_t matrix = (*dl)->w1; *dl = *dl + 1; - state->rsp->matrix((*dl)->w1, params, (*dl)->w0); + state->rsp->matrix(matrix, (*dl)->w0, (*dl)->w1); + } + + void setInvViewMatrixFloatV1(State *state, DisplayList **dl) { + state->rsp->setInvViewMatrixFloat((*dl)->w1); } void noOpHook(State *state, DisplayList **dl) { @@ -399,6 +403,7 @@ namespace RT64 { Map[G_EX_SETDITHERNOISESTRENGTH_V1] = &setDitherNoiseStrengthV1; Map[G_EX_SETRDRAMEXTENDED_V1] = &setRDRAMExtendedV1; Map[G_EX_MATRIX_V1] = &matrixV1; + Map[G_EX_SETINVVIEWMATRIXFLOAT_V1] = &setInvViewMatrixFloatV1; MapInitialized = true; } } diff --git a/src/hle/rt64_rsp.cpp b/src/hle/rt64_rsp.cpp index c7216a5..0cc664d 100644 --- a/src/hle/rt64_rsp.cpp +++ b/src/hle/rt64_rsp.cpp @@ -321,6 +321,20 @@ namespace RT64 { modelViewProjChanged = false; } + void RSP::setInvViewMatrixFloat(uint32_t address) { + const uint32_t rdramAddress = fromSegmentedMasked(address); + const float *floatMatrix = reinterpret_cast(state->fromRDRAM(rdramAddress)); + for (uint32_t j = 0; j < 4; j++) { + for (uint32_t i = 0; i < 4; i++) { + extended.invViewMatrix[j][i] = floatMatrix[j * 4 + i]; + } + } + + extended.invViewMatrixModel = hlslpp::inverse(extended.invViewMatrix); + projectionMatrixChanged = true; + modelViewProjChanged = true; + } + void RSP::computeModelViewProj() { const hlslpp::float4x4 &viewProjMatrix = viewProjMatrixStack[projectionMatrixStackSize - 1]; modelViewProjMatrix = hlslpp::mul(modelMatrixStack[modelMatrixStackSize - 1], viewProjMatrix); @@ -436,9 +450,9 @@ namespace RT64 { uint32_t physicalAddress = projectionMatrixPhysicalAddressStack[projectionMatrixStackSize - 1]; workload.physicalAddressTransformMap.emplace(physicalAddress, uint32_t(drawData.viewProjTransformGroups.size())); - drawData.viewTransforms.emplace_back(viewMatrixStack[projectionMatrixStackSize - 1]); + drawData.viewTransforms.emplace_back(hlslpp::mul(extended.invViewMatrix, viewMatrixStack[projectionMatrixStackSize - 1])); drawData.projTransforms.emplace_back(projMatrixStack[projectionMatrixStackSize - 1]); - drawData.viewProjTransforms.emplace_back(viewProjMatrixStack[projectionMatrixStackSize - 1]); + drawData.viewProjTransforms.emplace_back(hlslpp::mul(extended.invViewMatrix, viewProjMatrixStack[projectionMatrixStackSize - 1])); drawData.viewProjTransformGroups.emplace_back(extended.curViewProjMatrixIdGroupIndex); drawData.rspViewports.emplace_back(viewportStack[viewportStackSize - 1]); drawData.viewportOrigins.emplace_back(extended.viewportOrigin); @@ -473,7 +487,7 @@ namespace RT64 { if (modelViewProjChanged) { computeModelViewProj(); curTransformIndex = static_cast(worldTransforms.size()); - worldTransforms.emplace_back(modelMatrixStack[modelMatrixStackSize - 1]); + worldTransforms.emplace_back(hlslpp::mul(modelMatrixStack[modelMatrixStackSize - 1], extended.invViewMatrixModel)); } else if (modelViewProjInserted) { # ifdef LOG_SPECIAL_MATRIX_OPERATIONS @@ -488,7 +502,7 @@ namespace RT64 { } curTransformIndex = static_cast(worldTransforms.size()); - worldTransforms.emplace_back(hlslpp::mul(modelViewProjMatrix, invViewProjMatrixStack[projectionMatrixStackSize - 1])); + worldTransforms.emplace_back(hlslpp::mul(hlslpp::mul(modelViewProjMatrix, invViewProjMatrixStack[projectionMatrixStackSize - 1]), extended.invViewMatrixModel)); } if (addWorldTransform) { @@ -1212,6 +1226,8 @@ namespace RT64 { extended.viewProjMatrixIdStackChanged = false; extended.curViewProjMatrixIdGroupIndex = 0; extended.forceBranch = false; + extended.invViewMatrix = hlslpp::float4x4::identity(); + extended.invViewMatrixModel = hlslpp::float4x4::identity(); } void RSP::setGBI(GBI *gbi) { diff --git a/src/hle/rt64_rsp.h b/src/hle/rt64_rsp.h index aa0345a..7b0ad9f 100644 --- a/src/hle/rt64_rsp.h +++ b/src/hle/rt64_rsp.h @@ -217,6 +217,8 @@ namespace RT64 { bool viewProjMatrixIdStackChanged; int curViewProjMatrixIdGroupIndex; bool forceBranch; + hlslpp::float4x4 invViewMatrix; + hlslpp::float4x4 invViewMatrixModel; } extended; RSP(State *state); @@ -234,6 +236,7 @@ namespace RT64 { void popProjectionMatrix(); void insertMatrix(uint32_t address, uint32_t value); void forceMatrix(uint32_t address); + void setInvViewMatrixFloat(uint32_t address); void computeModelViewProj(); void specialComputeModelViewProj(); void setModelViewProjChanged(bool changed);