diff --git a/radiantcore/brush/TextureMatrix.cpp b/radiantcore/brush/TextureMatrix.cpp index 533ecd7051..8c36224223 100644 --- a/radiantcore/brush/TextureMatrix.cpp +++ b/radiantcore/brush/TextureMatrix.cpp @@ -207,3 +207,13 @@ Matrix4 TextureMatrix::getTransform() const { return transform; } + +bool TextureMatrix::isSane() const +{ + return !std::isnan(coords[0][0]) && !std::isinf(coords[0][0]) && + !std::isnan(coords[0][1]) && !std::isinf(coords[0][1]) && + !std::isnan(coords[0][2]) && !std::isinf(coords[0][2]) && + !std::isnan(coords[1][0]) && !std::isinf(coords[1][0]) && + !std::isnan(coords[1][1]) && !std::isinf(coords[1][1]) && + !std::isnan(coords[1][2]) && !std::isinf(coords[1][2]); +} diff --git a/radiantcore/brush/TextureMatrix.h b/radiantcore/brush/TextureMatrix.h index 05ccee4094..be960d722b 100644 --- a/radiantcore/brush/TextureMatrix.h +++ b/radiantcore/brush/TextureMatrix.h @@ -57,6 +57,9 @@ struct TextureMatrix * components, they are just copied into the right places. */ Matrix4 getTransform() const; + + // Checks if any of the matrix components are NaN or INF (in which case the matrix is not sane) + bool isSane() const; }; inline std::ostream& operator<<(std::ostream& st, const TextureMatrix& texdef) diff --git a/radiantcore/brush/TextureProjection.cpp b/radiantcore/brush/TextureProjection.cpp index 2acb2a57ae..6f65d58f76 100644 --- a/radiantcore/brush/TextureProjection.cpp +++ b/radiantcore/brush/TextureProjection.cpp @@ -177,7 +177,8 @@ void TextureProjection::fitTexture(std::size_t width, std::size_t height, const return; } - Matrix4 st2tex = getTransform(); + // Sanity-check the matrix, if it contains any NaNs or INFs we fall back to the default projection (#5371) + Matrix4 st2tex = matrix.isSane() ? getTransform() : GetDefaultProjection().getTransform(); // the current texture transform Matrix4 local2tex = st2tex;