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..d48c55ad7d 100644 --- a/components/nifosg/controller.cpp +++ b/components/nifosg/controller.cpp @@ -277,19 +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); - osg::Matrix flipMat; - flipMat.preMultTranslate(osg::Vec3f(0,1,0)); - flipMat.preMultScale(osg::Vec3f(1,-1,1)); + // 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::scale(uScale, vScale, 1); - mat.setTrans(uTrans, vTrans, 0); - - mat = flipMat * mat * flipMat; + 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())