From 71d8ccc753ed584f150b3999ff0e3c3d0865bdd1 Mon Sep 17 00:00:00 2001 From: kgv Date: Sat, 3 Sep 2016 21:37:55 +0300 Subject: [PATCH] 0027836: Visualization, TKOpenGl - gradient background is lost at some camera positions 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 | 39 +++++++++++++++++++---- src/OpenGl/OpenGl_View.cxx | 33 +++++++++++++++++-- tests/bugs/vis/bug27836 | 24 ++++++++++++++ 3 files changed, 87 insertions(+), 9 deletions(-) create mode 100644 tests/bugs/vis/bug27836 diff --git a/src/Graphic3d/Graphic3d_TransformPers.hxx b/src/Graphic3d/Graphic3d_TransformPers.hxx index 6ce52b0e13..3ad72c1ee2 100644 --- a/src/Graphic3d/Graphic3d_TransformPers.hxx +++ b/src/Graphic3d/Graphic3d_TransformPers.hxx @@ -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 void Apply (const Handle(Graphic3d_Camera)& theCamera, NCollection_Mat4& theProjection, NCollection_Mat4& 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 Graphic3d_TransformPers::Compute (const Handle(Graphic3d_Cam return NCollection_Mat4(); } + NCollection_Mat4 aProjection (theProjection); + NCollection_Mat4 aWorldView (theWorldView); NCollection_Mat4 anUnviewMat; + if (AltersProjectionMatrix()) + { + // destructive transformation persistence which directly modifies projection matrix + if (!(theProjection * theWorldView).Inverted (anUnviewMat)) + { + return NCollection_Mat4(); + } + + Apply (theCamera, aProjection, aWorldView, theViewportWidth, theViewportHeight); + return anUnviewMat * (aProjection * aWorldView); + } - if (!(theProjection * theWorldView).Inverted (anUnviewMat)) + if (!theWorldView.Inverted (anUnviewMat)) { return NCollection_Mat4(); } - NCollection_Mat4 aProjection (theProjection); - NCollection_Mat4 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 diff --git a/src/OpenGl/OpenGl_View.cxx b/src/OpenGl/OpenGl_View.cxx index 92028a4a43..9873043808 100644 --- a/src/OpenGl/OpenGl_View.cxx +++ b/src/OpenGl/OpenGl_View.cxx @@ -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 index 0000000000..61a9e662a2 --- /dev/null +++ b/tests/bugs/vis/bug27836 @@ -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 -- 2.20.1