From 24f4bf9c28eec36ddb9c4adbd6af46d887674ded Mon Sep 17 00:00:00 2001 From: Dobrohotov Alexei <alexdobrohotov@yandex.ru> Date: Fri, 30 Apr 2021 12:36:16 +0300 Subject: [PATCH 1/2] Fix NiUVController UV offset calculations (bug #5995) --- CHANGELOG.md | 1 + components/nifosg/controller.cpp | 17 ++++++++++------- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dec5e1e7f0..87009f58d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -118,6 +118,7 @@ Bug #5923: Clicking on empty spaces between journal entries might show random topics Bug #5934: AddItem command doesn't accept negative values Bug #5975: NIF controllers from sheath meshes are used + Bug #5995: NiUVController doesn't calculate the UV offset properly Feature #390: 3rd person look "over the shoulder" Feature #832: OpenMW-CS: Handle deleted references Feature #1536: Show more information about level on menu diff --git a/components/nifosg/controller.cpp b/components/nifosg/controller.cpp index 31fd92b43e..7f4bdcef21 100644 --- a/components/nifosg/controller.cpp +++ b/components/nifosg/controller.cpp @@ -282,14 +282,17 @@ void UVController::apply(osg::StateSet* stateset, osg::NodeVisitor* nv) float uScale = mUScale.interpKey(value); float vScale = mVScale.interpKey(value); - osg::Matrix flipMat; - flipMat.preMultTranslate(osg::Vec3f(0,1,0)); - flipMat.preMultScale(osg::Vec3f(1,-1,1)); - + // First scale the UV relative to (0,0), + // then offset the UV to change the scaling origin to its center. osg::Matrixf mat = osg::Matrixf::scale(uScale, vScale, 1); - mat.setTrans(uTrans, vTrans, 0); - - mat = flipMat * mat * flipMat; + float uOffset = 0.5f * (1.f - uScale); + float vOffset = 0.5f * (1.f - vScale); + // Apply the original offsets: + // U offset is supposed to be subtracted regardless of the graphics library, + // while V offset is made negative to account for OpenGL's Y axis convention. + uOffset -= uTrans; + vOffset -= vTrans; + mat.setTrans(uOffset, vOffset, 0); // setting once is enough because all other texture units share the same TexMat (see setDefaults). if (!mTextureUnits.empty()) From 971ba81ed279f97b2116540d3217a041d6cdb66a Mon Sep 17 00:00:00 2001 From: Dobrohotov Alexei <alexdobrohotov@yandex.ru> Date: Fri, 30 Apr 2021 18:23:04 +0300 Subject: [PATCH 2/2] Use higher level transformations in UVController --- components/nifosg/controller.cpp | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/components/nifosg/controller.cpp b/components/nifosg/controller.cpp index 7f4bdcef21..d48c55ad7d 100644 --- a/components/nifosg/controller.cpp +++ b/components/nifosg/controller.cpp @@ -277,22 +277,18 @@ void UVController::apply(osg::StateSet* stateset, osg::NodeVisitor* nv) if (hasInput()) { float value = getInputValue(nv); - float uTrans = mUTrans.interpKey(value); - float vTrans = mVTrans.interpKey(value); - float uScale = mUScale.interpKey(value); - float vScale = mVScale.interpKey(value); - // First scale the UV relative to (0,0), - // then offset the UV to change the scaling origin to its center. - osg::Matrixf mat = osg::Matrixf::scale(uScale, vScale, 1); - float uOffset = 0.5f * (1.f - uScale); - float vOffset = 0.5f * (1.f - vScale); - // Apply the original offsets: - // U offset is supposed to be subtracted regardless of the graphics library, - // while V offset is made negative to account for OpenGL's Y axis convention. - uOffset -= uTrans; - vOffset -= vTrans; - mat.setTrans(uOffset, vOffset, 0); + // First scale the UV relative to its center, then apply the offset. + // U offset is flipped regardless of the graphics library, + // while V offset is flipped to account for OpenGL Y axis convention. + osg::Vec3f uvOrigin(0.5f, 0.5f, 0.f); + osg::Vec3f uvScale(mUScale.interpKey(value), mVScale.interpKey(value), 1.f); + osg::Vec3f uvTrans(-mUTrans.interpKey(value), -mVTrans.interpKey(value), 0.f); + + osg::Matrixf mat = osg::Matrixf::translate(uvOrigin); + mat.preMultScale(uvScale); + mat.preMultTranslate(-uvOrigin); + mat.setTrans(mat.getTrans() + uvTrans); // setting once is enough because all other texture units share the same TexMat (see setDefaults). if (!mTextureUnits.empty())