diff --git a/src/AIS/AIS_GlobalStatus.hxx b/src/AIS/AIS_GlobalStatus.hxx
index faec81e7a4..9c5f8e5cfe 100644
--- a/src/AIS/AIS_GlobalStatus.hxx
+++ b/src/AIS/AIS_GlobalStatus.hxx
@@ -90,6 +90,11 @@ public:
   
   Standard_EXPORT Standard_Boolean IsSModeIn (const Standard_Integer aMode) const;
 
+  //! Returns layer index.
+  Standard_Integer GetLayerIndex() const
+  {
+    return myLayerIndex;
+  }
 
 
 
diff --git a/src/AIS/AIS_InteractiveContext.cxx b/src/AIS/AIS_InteractiveContext.cxx
index 1f52174ec3..721b3a2e10 100644
--- a/src/AIS/AIS_InteractiveContext.cxx
+++ b/src/AIS/AIS_InteractiveContext.cxx
@@ -2989,3 +2989,29 @@ void AIS_InteractiveContext::FitSelected (const Handle(V3d_View)& theView,
 
   theView->FitAll (aBndSelected, theMargin, theToUpdate);
 }
+
+//=======================================================================
+//function : SetTransformPersistence
+//purpose  :
+//=======================================================================
+void AIS_InteractiveContext::SetTransformPersistence (const Handle(AIS_InteractiveObject)& theObject,
+                                                      const Graphic3d_TransModeFlags&      theFlag,
+                                                      const gp_Pnt&                        thePoint)
+{
+  theObject->SetTransformPersistence (theFlag, thePoint);
+
+  if (!myObjects.IsBound (theObject))
+  {
+    return;
+  }
+
+  mgrSelector->UpdateSelection (theObject);
+
+  const Standard_Integer    aLayerId   = myObjects.Find (theObject)->GetLayerIndex();
+  const Handle(V3d_Viewer)& aCurViewer = CurrentViewer();
+  for (aCurViewer->InitActiveViews(); aCurViewer->MoreActiveViews(); aCurViewer->NextActiveViews())
+  {
+    aCurViewer->ActiveView()->View()->InvalidateBVHData (aLayerId);
+    aCurViewer->ActiveView()->View()->InvalidateZLayerBoundingBox (aLayerId);
+  }
+}
diff --git a/src/AIS/AIS_InteractiveContext.hxx b/src/AIS/AIS_InteractiveContext.hxx
index 96a9db1088..288b401ffb 100644
--- a/src/AIS/AIS_InteractiveContext.hxx
+++ b/src/AIS/AIS_InteractiveContext.hxx
@@ -601,6 +601,10 @@ public:
   //! for the view of the Interactive Object anObj.
   Standard_EXPORT void Status (const Handle(AIS_InteractiveObject)& anObj, TCollection_ExtendedString& astatus) const;
   
+  //! Sets transform persistence.
+  Standard_EXPORT void SetTransformPersistence (const Handle(AIS_InteractiveObject)& theObj,
+                                                const Graphic3d_TransModeFlags&      theFlag,
+                                                const gp_Pnt&                        thePoint = gp_Pnt (0.0, 0.0, 0.0));
 
   //! Updates the current viewer, the viewer in Neutral Point.
   //! Objects selected when there is no open local context
diff --git a/src/Graphic3d/Graphic3d_TransformPers.hxx b/src/Graphic3d/Graphic3d_TransformPers.hxx
index a687fad656..f64417d58b 100644
--- a/src/Graphic3d/Graphic3d_TransformPers.hxx
+++ b/src/Graphic3d/Graphic3d_TransformPers.hxx
@@ -158,25 +158,34 @@ void Graphic3d_TransformPers::Apply (NCollection_Mat4<T>& theProjection,
     }
 
     // Prevent zooming.
-    if (Flags & Graphic3d_TMF_ZoomPers)
+    if ((Flags == Graphic3d_TMF_TriedronPers)
+     || (Flags & Graphic3d_TMF_ZoomPers))
     {
-      const T aDet00 = (2.0f / theViewportWidth) / theProjection.GetValue(0, 0);
-      const T aDet11 = (2.0f / theViewportHeight) / theProjection.GetValue(1, 1);
-      const T aDet2 = Max (aDet00, aDet11);
+      const T aSize = static_cast<T> (1.0);
+      const Standard_Integer aViewport[4] = { 0, 0, theViewportHeight, theViewportHeight };
+      NCollection_Mat4<T> aWorldView;
+      aWorldView.InitIdentity();
 
-      theProjection.ChangeValue(0, 0) *= aDet00;
-      theProjection.ChangeValue(1, 1) *= aDet11;
-      theProjection.ChangeValue(2, 2) *= aDet2;
-    }
+      NCollection_Vec3<T> aWinCoordsRefPoint;
+      Graphic3d_TransformUtils::Project (static_cast<T> (Point.x()),
+                                         static_cast<T> (Point.y()),
+                                         static_cast<T> (Point.z()),
+                                         theWorldView, theProjection, aViewport,
+                                         aWinCoordsRefPoint.x(), aWinCoordsRefPoint.y(), aWinCoordsRefPoint.z());
 
-    if (Flags == Graphic3d_TMF_TriedronPers)
-    {
-      // Compute fixed-zoom multiplier. Actually function works ugly with TelPerspective!
-      const T aDet2 = static_cast<T> (0.002) / Max (theProjection.GetValue (1, 1), theProjection.GetValue (0, 0));
+      NCollection_Vec3<T> anUnProj1;
+      Graphic3d_TransformUtils::UnProject (aWinCoordsRefPoint.x(), aWinCoordsRefPoint.y(), aWinCoordsRefPoint.z(),
+                                           aWorldView, theProjection, aViewport,
+                                           anUnProj1.x(), anUnProj1.y(), anUnProj1.z());
 
-      theProjection.ChangeValue (0, 0) *= aDet2;
-      theProjection.ChangeValue (1, 1) *= aDet2;
-      theProjection.ChangeValue (2, 2) *= aDet2;
+      NCollection_Vec3<T> anUnProj2;
+      Graphic3d_TransformUtils::UnProject (aWinCoordsRefPoint.x(), aWinCoordsRefPoint.y() + aSize, aWinCoordsRefPoint.z(),
+                                           aWorldView, theProjection, aViewport,
+                                           anUnProj2.x(), anUnProj2.y(), anUnProj2.z());
+
+      const T aScale = (anUnProj2.y() - anUnProj1.y()) / aSize;
+
+      Graphic3d_TransformUtils::Scale (theWorldView, aScale, aScale, aScale);
     }
 
     // Prevent translation by nullifying translation component.
@@ -190,23 +199,6 @@ void Graphic3d_TransformPers::Apply (NCollection_Mat4<T>& theProjection,
       theProjection.SetValue (2, 3, static_cast<T> (0.0));
     }
 
-    // Prevent scaling-on-axis.
-    if (Flags & Graphic3d_TMF_ZoomPers)
-    {
-      NCollection_Vec3<T> aVecX = theWorldView.GetColumn (0).xyz();
-      NCollection_Vec3<T> aVecY = theWorldView.GetColumn (1).xyz();
-      NCollection_Vec3<T> aVecZ = theWorldView.GetColumn (2).xyz();
-      T aScaleX = aVecX.Modulus();
-      T aScaleY = aVecY.Modulus();
-      T aScaleZ = aVecZ.Modulus();
-      for (Standard_Integer anI = 0; anI < 3; ++anI)
-      {
-        theWorldView.ChangeValue (0, anI) /= aScaleX;
-        theWorldView.ChangeValue (1, anI) /= aScaleY;
-        theWorldView.ChangeValue (2, anI) /= aScaleZ;
-      }
-    }
-
     // Prevent rotation by nullifying rotation component.
     if (Flags & Graphic3d_TMF_RotatePers)
     {
diff --git a/src/Graphic3d/Graphic3d_TransformUtils.hxx b/src/Graphic3d/Graphic3d_TransformUtils.hxx
index f2f4c7c391..a2ba5cd526 100644
--- a/src/Graphic3d/Graphic3d_TransformUtils.hxx
+++ b/src/Graphic3d/Graphic3d_TransformUtils.hxx
@@ -41,6 +41,11 @@ namespace Graphic3d_TransformUtils
     typedef Graphic3d_Vec4 Vec4;
   };
 
+  //! Converts gp_Trsf to Graphic3d_Mat4.
+  template<class T>
+  static void Convert (const gp_Trsf&                theTransformation,
+                       typename MatrixType<T>::Mat4& theOut);
+
   //! Constructs a 3D orthographic projection matrix.
   template<class T>
   static void Ortho (typename MatrixType<T>::Mat4& theOut,
@@ -112,6 +117,37 @@ namespace Graphic3d_TransformUtils
                          T                             theX,
                          T                             theY,
                          T                             theZ);
+
+  //! Returns scaling factor from 3x3 affine matrix.
+  template<class T>
+  static Standard_Real ScaleFactor (const typename MatrixType<T>::Mat4& theMatrix);
+}
+
+// =======================================================================
+// function : Convert
+// purpose  :
+// =======================================================================
+template<class T>
+void Graphic3d_TransformUtils::Convert (const gp_Trsf&                theTransformation,
+                                        typename MatrixType<T>::Mat4& theOut)
+{
+  theOut.InitIdentity();
+
+  // Copy a 3x3 submatrix.
+  theOut.ChangeValue (0, 0) = theTransformation.Value (1, 1);
+  theOut.ChangeValue (0, 1) = theTransformation.Value (1, 2);
+  theOut.ChangeValue (0, 2) = theTransformation.Value (1, 3);
+  theOut.ChangeValue (1, 0) = theTransformation.Value (2, 1);
+  theOut.ChangeValue (1, 1) = theTransformation.Value (2, 2);
+  theOut.ChangeValue (1, 2) = theTransformation.Value (2, 3);
+  theOut.ChangeValue (2, 0) = theTransformation.Value (3, 1);
+  theOut.ChangeValue (2, 1) = theTransformation.Value (3, 2);
+  theOut.ChangeValue (2, 2) = theTransformation.Value (3, 3);
+
+  // Add a translate component.
+  theOut.ChangeValue (0, 3) = theTransformation.TranslationPart().X();
+  theOut.ChangeValue (1, 3) = theTransformation.TranslationPart().Y();
+  theOut.ChangeValue (2, 3) = theTransformation.TranslationPart().Z();
 }
 
 // =======================================================================
@@ -449,4 +485,22 @@ static Standard_Boolean Graphic3d_TransformUtils::UnProject (const T
   return Standard_True;
 }
 
+// =======================================================================
+// function : ScaleFactor
+// purpose  :
+// =======================================================================
+template<class T>
+static Standard_Real Graphic3d_TransformUtils::ScaleFactor (const typename MatrixType<T>::Mat4& theMatrix)
+{
+  // The determinant of the matrix should give the scale factor (cubed).
+  const T aDeterminant = (theMatrix.GetValue (0, 0) * theMatrix.GetValue (1, 1) * theMatrix.GetValue (2, 2) +
+                          theMatrix.GetValue (0, 1) * theMatrix.GetValue (1, 2) * theMatrix.GetValue (2, 0) +
+                          theMatrix.GetValue (0, 2) * theMatrix.GetValue (1, 0) * theMatrix.GetValue (2, 1))
+                       - (theMatrix.GetValue (0, 2) * theMatrix.GetValue (1, 1) * theMatrix.GetValue (2, 0) +
+                          theMatrix.GetValue (0, 0) * theMatrix.GetValue (1, 2) * theMatrix.GetValue (2, 1) +
+                          theMatrix.GetValue (0, 1) * theMatrix.GetValue (1, 0) * theMatrix.GetValue (2, 2));
+
+  return Pow (static_cast<Standard_Real> (aDeterminant), 1.0 / 3.0);
+}
+
 #endif // _Graphic3d_TransformUtils_HeaderFile
diff --git a/src/OpenGl/OpenGl_Layer.cxx b/src/OpenGl/OpenGl_Layer.cxx
index a1ec6162e4..b3aa452832 100644
--- a/src/OpenGl/OpenGl_Layer.cxx
+++ b/src/OpenGl/OpenGl_Layer.cxx
@@ -168,11 +168,6 @@ const Graphic3d_BndBox4f& OpenGl_Layer::BoundingBox (const Standard_Integer
         {
           if (!theToIgnoreInfiniteFlag && (aStructure->TransformPersistence.Flags & Graphic3d_TMF_ZoomPers))
           {
-            if (!theCamera->IsOrthographic())
-            {
-              continue;
-            }
-
             BVH_Vec4f aTPPoint (static_cast<float> (aStructure->TransformPersistence.Point.x()),
                                 static_cast<float> (aStructure->TransformPersistence.Point.y()),
                                 static_cast<float> (aStructure->TransformPersistence.Point.z()),
diff --git a/src/OpenGl/OpenGl_Structure.cxx b/src/OpenGl/OpenGl_Structure.cxx
index 9d93bff8ea..05d0dd6b16 100644
--- a/src/OpenGl/OpenGl_Structure.cxx
+++ b/src/OpenGl/OpenGl_Structure.cxx
@@ -474,6 +474,20 @@ void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &theWorkspace) con
   aCtx->ModelWorldState.Push();
   aCtx->ModelWorldState.SetCurrent (Transformation);
 
+  const Standard_Boolean anOldGlNormalize = aCtx->IsGlNormalizeEnabled();
+
+#if !defined(GL_ES_VERSION_2_0)
+  // detect scale transform
+  if (aCtx->core11 != NULL)
+  {
+    const Standard_ShortReal aScaleX = Transformation.GetRow (0).xyz().SquareModulus();
+    if (Abs (aScaleX - 1.f) > Precision::Confusion())
+    {
+      aCtx->SetGlNormalizeEnabled (Standard_True);
+    }
+  }
+#endif
+
   if (TransformPersistence.Flags)
   {
     OpenGl_Mat4 aProjection = aCtx->ProjectionState.Current();
@@ -485,14 +499,18 @@ void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &theWorkspace) con
     aCtx->ProjectionState.SetCurrent (aProjection);
     aCtx->WorldViewState.SetCurrent (aWorldView);
     aCtx->ApplyProjectionMatrix();
-  }
 
-  // detect scale transform
-  const Standard_Boolean   anOldGlNormalize = aCtx->IsGlNormalizeEnabled();
-  const Standard_ShortReal aScaleX          = aCtx->ModelWorldState.Current().GetRow (0).xyz().SquareModulus();
-  if (Abs (aScaleX - 1.f) > Precision::Confusion())
-  {
-    aCtx->SetGlNormalizeEnabled (Standard_True);
+  #if !defined(GL_ES_VERSION_2_0)
+    if (!aCtx->IsGlNormalizeEnabled()
+      && aCtx->core11 != NULL)
+    {
+      const Standard_Real aScale = Graphic3d_TransformUtils::ScaleFactor<Standard_ShortReal> (aWorldView);
+      if (Abs (aScale - 1.0f) > Precision::Confusion())
+      {
+        aCtx->SetGlNormalizeEnabled (Standard_True);
+      }
+    }
+  #endif
   }
 
   // Take into account transform persistence
diff --git a/src/OpenGl/OpenGl_View.cxx b/src/OpenGl/OpenGl_View.cxx
index c054675599..17280c126f 100644
--- a/src/OpenGl/OpenGl_View.cxx
+++ b/src/OpenGl/OpenGl_View.cxx
@@ -595,7 +595,7 @@ Standard_Real OpenGl_View::considerZoomPersistenceObjects (const Graphic3d_ZLaye
                                                            const Standard_Integer          theWindowHeight,
                                                            const Standard_Boolean          theToIgnoreInfiniteFlag) const
 {
-  if (myZLayers.LayerIDs().IsBound (theLayerId) && theCamera->IsOrthographic())
+  if (myZLayers.LayerIDs().IsBound (theLayerId))
   {
     return myZLayers.Layer (theLayerId).considerZoomPersistenceObjects (Identification(),
                                                                         theCamera,
diff --git a/src/PrsMgr/PrsMgr_PresentableObject.cxx b/src/PrsMgr/PrsMgr_PresentableObject.cxx
index b98d3cefca..93394da5bf 100644
--- a/src/PrsMgr/PrsMgr_PresentableObject.cxx
+++ b/src/PrsMgr/PrsMgr_PresentableObject.cxx
@@ -325,16 +325,6 @@ void PrsMgr_PresentableObject::SetTransformPersistence (const Graphic3d_TransMod
   }
 }
 
-//=======================================================================
-//function : SetTransformPersistence
-//purpose  : 
-//=======================================================================
-void  PrsMgr_PresentableObject::SetTransformPersistence( 
-				       const Graphic3d_TransModeFlags& TheFlag )
-{
-  SetTransformPersistence( TheFlag, gp_Pnt(0,0,0) );
-}
-
 //=======================================================================
 //function : GetTransformPersistence
 //purpose  : 
diff --git a/src/PrsMgr/PrsMgr_PresentableObject.hxx b/src/PrsMgr/PrsMgr_PresentableObject.hxx
index 3b25a15e7d..ed1625041f 100644
--- a/src/PrsMgr/PrsMgr_PresentableObject.hxx
+++ b/src/PrsMgr/PrsMgr_PresentableObject.hxx
@@ -98,11 +98,8 @@ public:
   //! -   X < 0.0, Y > 0.0 - left  upper corner of view window;
   //! -   X < 0.0, Y < 0.0 - left  lower corner of view window.
   //! And Z coordinate defines the gap from border of view window (except center position).
-  Standard_EXPORT virtual void SetTransformPersistence (const Graphic3d_TransModeFlags& aFlag, const gp_Pnt& APoint);
-  
-  //! Calls previous method  with  point  (0,0,0)
-  Standard_EXPORT void SetTransformPersistence (const Graphic3d_TransModeFlags& aFlag);
-  
+  Standard_EXPORT virtual void SetTransformPersistence (const Graphic3d_TransModeFlags& aFlag, const gp_Pnt& APoint = gp_Pnt (0.0, 0.0, 0.0));
+
   //! Gets  Transform  Persistence Mode  for  this  object
   Standard_EXPORT Graphic3d_TransModeFlags GetTransformPersistenceMode() const;
   
diff --git a/src/QABugs/QABugs_11.cxx b/src/QABugs/QABugs_11.cxx
index 7137145743..84784786f6 100644
--- a/src/QABugs/QABugs_11.cxx
+++ b/src/QABugs/QABugs_11.cxx
@@ -4557,7 +4557,7 @@ static Standard_Integer OCC12584 (Draw_Interpretor& di, Standard_Integer argc, c
   }
   if (aCS->GetTransformPersistenceMode() != Graphic3d_TMF_2d)
   {
-    aCS->SetTransformPersistence (Graphic3d_TMF_2d, gp_Pnt (-1,-1,0));
+    aContext->SetTransformPersistence (aCS, Graphic3d_TMF_2d, gp_Pnt (-1,-1,0));
   }
   Standard_Integer aWinWidth, aWinHeight;
   V->Window()->Size (aWinWidth, aWinHeight);
diff --git a/src/SelectMgr/SelectMgr_SelectionManager.cxx b/src/SelectMgr/SelectMgr_SelectionManager.cxx
index 8072850b7d..35f54516a3 100644
--- a/src/SelectMgr/SelectMgr_SelectionManager.cxx
+++ b/src/SelectMgr/SelectMgr_SelectionManager.cxx
@@ -974,3 +974,35 @@ void SelectMgr_SelectionManager::SetSelectionSensitivity (const Handle(SelectMgr
     }
   }
 }
+
+//=======================================================================
+//function : UpdateSelection
+//purpose  :
+//=======================================================================
+void SelectMgr_SelectionManager::UpdateSelection (const Handle(SelectMgr_SelectableObject)& theObject)
+{
+  if (myGlobal.Contains (theObject))
+  {
+    for (TColStd_MapIteratorOfMapOfTransient aSelectorsIter (mySelectors); aSelectorsIter.More(); aSelectorsIter.Next())
+    {
+      Handle(SelectMgr_ViewerSelector) aSelector = Handle(SelectMgr_ViewerSelector)::DownCast (aSelectorsIter.Key());
+      if (aSelector->Contains (theObject))
+      {
+        aSelector->MoveSelectableObject (theObject);
+      }
+    }
+  }
+
+  if (myLocal.IsBound (theObject))
+  {
+    const SelectMgr_SequenceOfSelector& aSelectors = myLocal (theObject);
+    for (SelectMgr_SequenceOfSelector::Iterator aSelectorsIter (aSelectors); aSelectorsIter.More(); aSelectorsIter.Next())
+    {
+      Handle(SelectMgr_ViewerSelector)& aSelector = aSelectorsIter.ChangeValue();
+      if (aSelector->Contains (theObject))
+      {
+        aSelector->MoveSelectableObject (theObject);
+      }
+    }
+  }
+}
diff --git a/src/SelectMgr/SelectMgr_SelectionManager.hxx b/src/SelectMgr/SelectMgr_SelectionManager.hxx
index afdef8f862..2ec9cc4393 100644
--- a/src/SelectMgr/SelectMgr_SelectionManager.hxx
+++ b/src/SelectMgr/SelectMgr_SelectionManager.hxx
@@ -125,6 +125,9 @@ public:
                                                 const Standard_Integer theMode,
                                                 const Standard_Integer theNewSens);
 
+  //! Re-adds selectable object in BVHs in all viewer selectors.
+  Standard_EXPORT void UpdateSelection (const Handle(SelectMgr_SelectableObject)& theObj);
+
   DEFINE_STANDARD_RTTIEXT(SelectMgr_SelectionManager,MMgt_TShared)
 
 protected:
diff --git a/src/SelectMgr/SelectMgr_ViewerSelector.cxx b/src/SelectMgr/SelectMgr_ViewerSelector.cxx
index ddf9ba5a2d..9bb2816402 100644
--- a/src/SelectMgr/SelectMgr_ViewerSelector.cxx
+++ b/src/SelectMgr/SelectMgr_ViewerSelector.cxx
@@ -322,6 +322,7 @@ void SelectMgr_ViewerSelector::traverseObject (const Handle(SelectMgr_Selectable
     {
       const Graphic3d_Mat4d& aProjection = mySelectingVolumeMgr.ProjectionMatrix();
       const Graphic3d_Mat4d& aWorldView  = mySelectingVolumeMgr.WorldViewMatrix();
+
       Standard_Integer aViewportWidth;
       Standard_Integer aViewportHeight;
       mySelectingVolumeMgr.WindowSize (aViewportWidth, aViewportHeight);
@@ -810,6 +811,27 @@ void SelectMgr_ViewerSelector::AddSelectionToObject (const Handle(SelectMgr_Sele
   }
 }
 
+//=======================================================================
+// function : MoveSelectableObject
+// purpose  :
+//=======================================================================
+void SelectMgr_ViewerSelector::MoveSelectableObject (const Handle(SelectMgr_SelectableObject)& theObject)
+{
+  if (!mySelectableObjects.Remove (theObject))
+  {
+    mySelectableObjectsTrsfPers.Remove (theObject);
+  }
+
+  if (!theObject->TransformPersistence().Flags)
+  {
+    mySelectableObjects.Append (theObject);
+  }
+  else
+  {
+    mySelectableObjectsTrsfPers.Append (theObject);
+  }
+}
+
 //=======================================================================
 // function : RemoveSelectableObject
 // purpose  : Removes selectable object from map of selectable ones
diff --git a/src/SelectMgr/SelectMgr_ViewerSelector.hxx b/src/SelectMgr/SelectMgr_ViewerSelector.hxx
index c7ff4f4fd0..f8892972ef 100644
--- a/src/SelectMgr/SelectMgr_ViewerSelector.hxx
+++ b/src/SelectMgr/SelectMgr_ViewerSelector.hxx
@@ -217,6 +217,10 @@ public:
   Standard_EXPORT void AddSelectionToObject (const Handle(SelectMgr_SelectableObject)& theObject,
                                              const Handle(SelectMgr_Selection)& theSelection);
 
+  //! Moves existing object from set of not transform persistence objects
+  //! to set of transform persistence objects (or vice versa).
+  Standard_EXPORT void MoveSelectableObject (const Handle(SelectMgr_SelectableObject)& theObject);
+
   //! Removes selectable object from map of selectable ones
   Standard_EXPORT void RemoveSelectableObject (const Handle(SelectMgr_SelectableObject)& theObject);
 
diff --git a/src/ViewerTest/ViewerTest.cxx b/src/ViewerTest/ViewerTest.cxx
index a216866317..92b741ac2d 100644
--- a/src/ViewerTest/ViewerTest.cxx
+++ b/src/ViewerTest/ViewerTest.cxx
@@ -3656,7 +3656,7 @@ static int VDisplay2 (Draw_Interpretor& theDI,
         }
         if (toSetTrsfPers)
         {
-          aShape->SetTransformPersistence (aTrsfPersFlags, aTPPosition);
+          aCtx->SetTransformPersistence (aShape, aTrsfPersFlags, aTPPosition);
         }
         if (anObjDispMode != -2)
         {
@@ -3710,7 +3710,7 @@ static int VDisplay2 (Draw_Interpretor& theDI,
     }
     if (toSetTrsfPers)
     {
-      aShape->SetTransformPersistence (aTrsfPersFlags, aTPPosition);
+      aCtx->SetTransformPersistence (aShape, aTrsfPersFlags, aTPPosition);
     }
     if (anObjDispMode != -2)
     {
@@ -4454,6 +4454,7 @@ static Standard_Integer VState (Draw_Interpretor& theDI,
       {
         const Graphic3d_Mat4d& aProjection = aMgr.ProjectionMatrix();
         const Graphic3d_Mat4d& aWorldView  = aMgr.WorldViewMatrix();
+
         Standard_Integer aViewportWidth = 0;
         Standard_Integer aViewportHeight = 0;
         aMgr.WindowSize (aViewportWidth, aViewportHeight);
diff --git a/src/ViewerTest/ViewerTest_ObjectCommands.cxx b/src/ViewerTest/ViewerTest_ObjectCommands.cxx
index b88713308c..3ff30301d1 100644
--- a/src/ViewerTest/ViewerTest_ObjectCommands.cxx
+++ b/src/ViewerTest/ViewerTest_ObjectCommands.cxx
@@ -2846,7 +2846,7 @@ static int VDrawText (Draw_Interpretor& theDI,
 
   if (aTrsfPersFlags != Graphic3d_TMF_None)
   {
-    aTextPrs->SetTransformPersistence (aTrsfPersFlags, aTPPosition);
+    aContext->SetTransformPersistence (aTextPrs, aTrsfPersFlags, aTPPosition);
     aTextPrs->SetZLayer(Graphic3d_ZLayerId_TopOSD);
     if (aTextPrs->Position().Z() != 0)
     {
@@ -2855,7 +2855,7 @@ static int VDrawText (Draw_Interpretor& theDI,
   }
   else if (aTrsfPersFlags != aTextPrs->TransformPersistence().Flags)
   {
-    aTextPrs->SetTransformPersistence (aTrsfPersFlags);
+    aContext->SetTransformPersistence (aTextPrs, aTrsfPersFlags);
   }
   ViewerTest::Display (aName, aTextPrs, Standard_False);
   return 0;
diff --git a/src/ViewerTest/ViewerTest_ViewerCommands.cxx b/src/ViewerTest/ViewerTest_ViewerCommands.cxx
index 96db8d80eb..6d423e0932 100644
--- a/src/ViewerTest/ViewerTest_ViewerCommands.cxx
+++ b/src/ViewerTest/ViewerTest_ViewerCommands.cxx
@@ -3570,7 +3570,7 @@ static int VColorScale (Draw_Interpretor& theDI,
   }
   if (aCS->GetTransformPersistenceMode() != Graphic3d_TMF_2d)
   {
-    aCS->SetTransformPersistence (Graphic3d_TMF_2d, gp_Pnt (-1,-1,0));
+    aContext->SetTransformPersistence (aCS, Graphic3d_TMF_2d, gp_Pnt (-1.0, -1.0, 0.0));
   }
 
   Standard_Real                   aMinRange    = aCS->GetMin();
@@ -4879,7 +4879,7 @@ static int VLayerLine(Draw_Interpretor& di, Standard_Integer argc, const char**
                             aLineType, aWidth,
                             aTransparency);
 
-  aLine->SetTransformPersistence (Graphic3d_TMF_2d,gp_Pnt(-1,-1,0));
+  aContext->SetTransformPersistence (aLine, Graphic3d_TMF_2d, gp_Pnt (-1.0, -1.0, 0.0));
   aLine->SetZLayer (Graphic3d_ZLayerId_TopOSD);
   aLine->SetToUpdate();
   aContext->Display (aLine, Standard_True);
diff --git a/tests/bugs/vis/bug26344 b/tests/bugs/vis/bug26344
index 8b7ddd40d8..f7cc40e450 100644
--- a/tests/bugs/vis/bug26344
+++ b/tests/bugs/vis/bug26344
@@ -24,22 +24,21 @@ vdisplay b1 -trsfPers zoom -trsfPersPos 200 200 200
 vdisplay b2 -trsfPers zoom -trsfPersPos 200 200 200
 vsetlocation b2 -25 -25 -25
 
-vmoveto 384 78
-if { ![checkcolor 384 78 0 1 1] } {
+vmoveto 387 77
+if { ![checkcolor 387 77 0 1 1] } {
   puts "Error picking zoom persistence object"
 }
 
-vmoveto 356 96
-if { ![checkcolor 356 96 0 1 1] } {
+vmoveto 352 96
+if { ![checkcolor 352 96 0 1 1] } {
   puts "Error picking zoom persistent object with location"
 }
 
 vselect 330 120 400 50
 
-if { ![checkcolor 384 78 0.8 0.8 0.8] || ![checkcolor 356 96 0.8 0.8 0.8] } {
+if { ![checkcolor 387 77 0.8 0.8 0.8] || ![checkcolor 352 96 0.8 0.8 0.8] } {
   puts "Error selecting zoom persistence object(s)"
 }
-
 # 2) Rotate persistence
 
 vdisplay b3 -trsfPers rotate -trsfPersPos -200 -200 -200
@@ -67,12 +66,12 @@ if { ![checkcolor 233 188 0.8 0.8 0.8] } {
 # 4) Trihedron persistence
 
 vdisplay b5 -trsfPers trihedron -trsfPersPos -1 -1 300
-vmoveto 90 300
-if { ![checkcolor 90 300 0 1 1] } {
+vmoveto 132 300
+if { ![checkcolor 132 300 0 1 1] } {
   puts "Error picking trihedron persistence object"
 }
-vselect 50 380 140 280
-if { ![checkcolor 90 300 0.8 0.8 0.8] } {
+vselect 50 223 235 395
+if { ![checkcolor 132 300 0.8 0.8 0.8] } {
   puts "Error selecting trihedron persistence object"
 }
 
diff --git a/tests/bugs/vis/bug26641 b/tests/bugs/vis/bug26641
new file mode 100644
index 0000000000..0052afa766
--- /dev/null
+++ b/tests/bugs/vis/bug26641
@@ -0,0 +1,35 @@
+puts "============"
+puts "CR26641"
+puts "============"
+puts ""
+
+##############################################################################################################
+# 0026641: Visualization, TKOpenGl - handle correctly transformation persistence within perspective projection
+##############################################################################################################
+
+vinit
+vclear
+
+box b0 30 0 0 10 10 10
+box b1 -30 -30 30 10 30 20
+vdisplay b0
+vdisplay b1
+vfit
+
+vdump ${imagedir}/${casename}_none_pers_ortho.png
+
+vdisplay b1 -trsfPers zoom -trsfPersPos -30 -30 30
+vfit
+
+vdump ${imagedir}/${casename}_zoom_pers_ortho.png
+
+vcamera -persp
+vfit
+
+vdump ${imagedir}/${casename}_zoom_pers_persp.png
+
+vselect 30 70
+
+if {[vnbselected] != 1} {
+  puts "ERROR: Transform persistence object is not selected!"
+}