0027836: Visualization, TKOpenGl - gradient background is lost at some camera positions
authorkgv <kgv@opencascade.com>
Sat, 3 Sep 2016 18:37:55 +0000 (21:37 +0300)
committerbugmaster <bugmaster@opencascade.com>
Thu, 8 Sep 2016 08:43:01 +0000 (11:43 +0300)
OpenGl_View::ZLayerBoundingBox() now adds screen background plane for proper Z-fit.

Graphic3d_TransformPers::Compute() - projection matrix has been excluded
from the math to eliminate floating point computation error.

src/Graphic3d/Graphic3d_TransformPers.hxx
src/OpenGl/OpenGl_View.cxx
tests/bugs/vis/bug27836 [new file with mode: 0644]

index 6ce52b0..3ad72c1 100644 (file)
@@ -90,12 +90,25 @@ public:
                                const Standard_Integer theViewportWidth,
                                const Standard_Integer theViewportHeight) const;
 
+  //! Apply transformation persistence on specified matrices.
+  //! @param theCamera camera definition
+  //! @param theProjection projection matrix to modify
+  //! @param theWorldView  world-view matrix to modify
+  //! @param theViewportWidth  viewport width
+  //! @param theViewportHeight viewport height
   template<class T>
   void Apply (const Handle(Graphic3d_Camera)& theCamera,
               NCollection_Mat4<T>& theProjection,
               NCollection_Mat4<T>& theWorldView,
               const Standard_Integer theViewportWidth,
               const Standard_Integer theViewportHeight) const;
+
+  //! Return true if transformation persistence alters projection matrix.
+  bool AltersProjectionMatrix() const
+  {
+    return (Flags & Graphic3d_TMF_PanPers) != 0;
+  }
+
 };
 
 // =======================================================================
@@ -110,7 +123,8 @@ void Graphic3d_TransformPers::Apply (const Handle(Graphic3d_Camera)& theCamera,
                                      const Standard_Integer theViewportHeight) const
 {
   (void )theViewportWidth;
-  if (!Flags)
+  if (Flags == Graphic3d_TMF_None
+   || theViewportHeight == 0)
   {
     return;
   }
@@ -375,19 +389,30 @@ NCollection_Mat4<T> Graphic3d_TransformPers::Compute (const Handle(Graphic3d_Cam
     return NCollection_Mat4<T>();
   }
 
+  NCollection_Mat4<T> aProjection (theProjection);
+  NCollection_Mat4<T> aWorldView  (theWorldView);
   NCollection_Mat4<T> anUnviewMat;
+  if (AltersProjectionMatrix())
+  {
+    // destructive transformation persistence which directly modifies projection matrix
+    if (!(theProjection * theWorldView).Inverted (anUnviewMat))
+    {
+      return NCollection_Mat4<T>();
+    }
+
+    Apply (theCamera, aProjection, aWorldView, theViewportWidth, theViewportHeight);
+    return anUnviewMat * (aProjection * aWorldView);
+  }
 
-  if (!(theProjection * theWorldView).Inverted (anUnviewMat))
+  if (!theWorldView.Inverted (anUnviewMat))
   {
     return NCollection_Mat4<T>();
   }
 
-  NCollection_Mat4<T> aProjection (theProjection);
-  NCollection_Mat4<T> aWorldView (theWorldView);
-
+  // compute only world-view matrix difference to avoid floating point instability
+  // caused by projection matrix modifications outside of this algorithm (e.g. by Z-fit)
   Apply (theCamera, aProjection, aWorldView, theViewportWidth, theViewportHeight);
-
-  return anUnviewMat * (aProjection * aWorldView);
+  return anUnviewMat * aWorldView;
 }
 
 #endif // _Graphic3d_TransformPers_HeaderFile
index 92028a4..9873043 100644 (file)
@@ -550,16 +550,45 @@ Graphic3d_BndBox4f OpenGl_View::ZLayerBoundingBox (const Graphic3d_ZLayerId
                                                    const Standard_Integer          theWindowHeight,
                                                    const Standard_Boolean          theToIncludeAuxiliary) const
 {
+  Graphic3d_BndBox4f aBox;
   if (myZLayers.LayerIDs().IsBound (theLayerId))
   {
-    return myZLayers.Layer (theLayerId).BoundingBox (Identification(),
+    aBox = myZLayers.Layer (theLayerId).BoundingBox (Identification(),
                                                      theCamera,
                                                      theWindowWidth,
                                                      theWindowHeight,
                                                      theToIncludeAuxiliary);
   }
 
-  return Graphic3d_BndBox4f();
+  // add bounding box of gradient/texture background for proper Z-fit
+  if (theToIncludeAuxiliary
+   && theLayerId == Graphic3d_ZLayerId_BotOSD
+   && (myBgTextureArray->IsDefined()
+    || myBgGradientArray->IsDefined()))
+  {
+    // Background is drawn using 2D transformation persistence
+    // (e.g. it is actually placed in 3D coordinates within active camera position).
+    // We add here full-screen plane with 2D transformation persistence
+    // for simplicity (myBgTextureArray might define a little bit different options
+    // but it is updated within ::Render())
+    const Graphic3d_Mat4& aProjectionMat = theCamera->ProjectionMatrixF();
+    const Graphic3d_Mat4& aWorldViewMat  = theCamera->OrientationMatrixF();
+    Graphic3d_BndBox4f aBox2d (Graphic3d_Vec4 (0.0f, 0.0f, 0.0f, 0.0f),
+                               Graphic3d_Vec4 (float(theWindowWidth), float(theWindowHeight), 0.0f, 0.0f));
+
+    Graphic3d_TransformPers aTrsfPers;
+    aTrsfPers.Flags = Graphic3d_TMF_2d;
+    aTrsfPers.Point = Graphic3d_Vec3d(-1.0, -1.0, 0.0);
+    aTrsfPers.Apply (theCamera,
+                     aProjectionMat,
+                     aWorldViewMat,
+                     theWindowWidth,
+                     theWindowHeight,
+                     aBox2d);
+    aBox.Combine (aBox2d);
+  }
+
+  return aBox;
 }
 
 //=======================================================================
diff --git a/tests/bugs/vis/bug27836 b/tests/bugs/vis/bug27836
new file mode 100644 (file)
index 0000000..61a9e66
--- /dev/null
@@ -0,0 +1,24 @@
+puts "========"
+puts "Gradient background is lost at some camera positions"
+puts "========"
+
+# Test case setup the camera in such a position,
+# so that background plane will be clipped by Z-range if not handled by Z-fit.
+
+pload MODELING VISUALIZATION
+box b 0 0 -100 100 90 10
+
+vclear
+vinit View1
+vaxo
+vsetgradientbg 180 200 255 180 180 180 2
+vzbufftrihedron
+vdisplay -dispMode 1 b
+vsetlocation b 0 0 1000
+vfit
+
+vviewparams -scale 6.66 -eye 48 43 -210 -at 50 45 -95
+
+if { [vreadpixel 100 300 rgb name] != "GRAY74" } { puts "Error: gradient background is not displayed" }
+
+vdump $imagedir/${casename}.png