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())