diff --git a/src/AIS/AIS_Manipulator.cxx b/src/AIS/AIS_Manipulator.cxx index bf93dbfc10..76b82782b8 100644 --- a/src/AIS/AIS_Manipulator.cxx +++ b/src/AIS/AIS_Manipulator.cxx @@ -843,10 +843,18 @@ void AIS_Manipulator::updateTransformation() if (myIsZoomPersistentMode) { if (TransformPersistence().IsNull() - || TransformPersistence()->Mode() != Graphic3d_TMF_ZoomPers + || TransformPersistence()->Mode() != Graphic3d_TMF_AxialZoomPers || !TransformPersistence()->AnchorPoint().IsEqual (myPosition.Location(), 0.0)) { - setTransformPersistence (new Graphic3d_TransformPers (Graphic3d_TMF_ZoomPers, myPosition.Location())); + setTransformPersistence (new Graphic3d_TransformPers (Graphic3d_TMF_AxialZoomPers, myPosition.Location())); + } + } + else + { + if (TransformPersistence().IsNull() + || TransformPersistence()->Mode() != Graphic3d_TMF_AxialScalePers) + { + setTransformPersistence (new Graphic3d_TransformPers (Graphic3d_TMF_AxialScalePers, myPosition.Location())); } } } @@ -931,7 +939,7 @@ void AIS_Manipulator::SetZoomPersistence (const Standard_Boolean theToEnable) if (!theToEnable) { - setTransformPersistence (Handle(Graphic3d_TransformPers)()); + setTransformPersistence (new (Graphic3d_TransformPers)(Graphic3d_TMF_AxialScalePers)); } updateTransformation(); diff --git a/src/Graphic3d/Graphic3d_Camera.cxx b/src/Graphic3d/Graphic3d_Camera.cxx index ee7204fe8e..e1fc21edfc 100644 --- a/src/Graphic3d/Graphic3d_Camera.cxx +++ b/src/Graphic3d/Graphic3d_Camera.cxx @@ -309,6 +309,10 @@ void Graphic3d_Camera::SetUp (const gp_Dir& theUp) // ======================================================================= void Graphic3d_Camera::SetAxialScale (const gp_XYZ& theAxialScale) { + Standard_OutOfRange_Raise_if (theAxialScale.X() <= 0.0 + || theAxialScale.Y() <= 0.0 + || theAxialScale.Z() <= 0.0, + "Graphic3d_Camera::SetAxialScale, bad coefficient"); if (AxialScale().IsEqual (theAxialScale, 0.0)) { return; diff --git a/src/Graphic3d/Graphic3d_TransModeFlags.hxx b/src/Graphic3d/Graphic3d_TransModeFlags.hxx index 0c9f329362..d06a8329a1 100644 --- a/src/Graphic3d/Graphic3d_TransModeFlags.hxx +++ b/src/Graphic3d/Graphic3d_TransModeFlags.hxx @@ -19,15 +19,18 @@ //! Transform Persistence Mode defining whether to lock in object position, rotation and / or zooming relative to camera position. enum Graphic3d_TransModeFlags { - Graphic3d_TMF_None = 0x0000, //!< no persistence attributes (normal 3D object) - Graphic3d_TMF_ZoomPers = 0x0002, //!< object does not resize - Graphic3d_TMF_RotatePers = 0x0008, //!< object does not rotate; - Graphic3d_TMF_TriedronPers = 0x0020, //!< object behaves like trihedron - it is fixed at the corner of view and does not resizing (but rotating) - Graphic3d_TMF_2d = 0x0040, //!< object is defined in 2D screen coordinates (pixels) and does not resize, pan and rotate - Graphic3d_TMF_CameraPers = 0x0080, //!< object is in front of the camera - Graphic3d_TMF_OrthoPers = 0x0100, //!< object is forced to be rendered with orthographic projection. + Graphic3d_TMF_None = 0x0000, //!< no persistence attributes (normal 3D object) + Graphic3d_TMF_ZoomPers = 0x0002, //!< object does not resize + Graphic3d_TMF_RotatePers = 0x0008, //!< object does not rotate; + Graphic3d_TMF_TriedronPers = 0x0020, //!< object behaves like trihedron - it is fixed at the corner of view and does not resizing (but rotating) + Graphic3d_TMF_2d = 0x0040, //!< object is defined in 2D screen coordinates (pixels) and does not resize, pan and rotate + Graphic3d_TMF_CameraPers = 0x0080, //!< object is in front of the camera + Graphic3d_TMF_OrthoPers = 0x0100, //!< object is forced to be rendered with orthographic projection. + Graphic3d_TMF_AxialScalePers = 0x0200, //!< object does not resize with axial scale Graphic3d_TMF_ZoomRotatePers = Graphic3d_TMF_ZoomPers - | Graphic3d_TMF_RotatePers //!< object doesn't resize and rotate + | Graphic3d_TMF_RotatePers, //!< object doesn't resize and rotate + Graphic3d_TMF_AxialZoomPers = Graphic3d_TMF_ZoomPers + | Graphic3d_TMF_AxialScalePers //!< object does not visually resize with either object or axial scale }; //! Bitwise OR operator for transform persistence mode flags. Be aware that some flags combinations are not valid. diff --git a/src/Graphic3d/Graphic3d_TransformPers.hxx b/src/Graphic3d/Graphic3d_TransformPers.hxx index d0f70ba64c..36dc3636a1 100644 --- a/src/Graphic3d/Graphic3d_TransformPers.hxx +++ b/src/Graphic3d/Graphic3d_TransformPers.hxx @@ -40,6 +40,9 @@ DEFINE_STANDARD_HANDLE(Graphic3d_TransformPers, Standard_Transient) //! Beware that Graphic3d_RenderingParams::ResolutionRatio() will be ignored! //! For other Persistence flags, normal (world) length units will apply. //! +//! Graphic3d_TMF_AxialPers and Graphic3d_TMF_AxialZoomPers defines persistence in the axial scale, +//! i.e., keeps the object visual coherence when the camera's axial scale is changed. +//! Meant to be used by objects such as Manipulators and trihedrons. //! WARNING: Graphic3d_TMF_None is not permitted for defining instance of this class - NULL handle should be used for this purpose! class Graphic3d_TransformPers : public Standard_Transient { @@ -64,13 +67,19 @@ public: return (theMode & Graphic3d_TMF_OrthoPers) != 0; } + //! Return true if specified mode is axial transformation persistence. + static Standard_Boolean IsAxial (Graphic3d_TransModeFlags theMode) + { + return (theMode & Graphic3d_TMF_AxialScalePers) != 0; + } + public: //! Set transformation persistence. Graphic3d_TransformPers (const Graphic3d_TransModeFlags theMode) : myMode (theMode) { - if (IsZoomOrRotate (theMode)) + if (IsZoomOrRotate (theMode) || IsAxial (theMode)) { SetPersistence (theMode, gp_Pnt(0.0, 0.0, 0.0)); } @@ -119,6 +128,9 @@ public: //! Return true for Graphic3d_TMF_OrthoPers mode. Standard_Boolean IsOrthoPers () const { return IsOrthoPers (myMode); } + //! Return true for Graphic3d_TMF_AxialScalePers modes. + Standard_Boolean IsAxial() const { return IsAxial (myMode); } + //! Transformation persistence mode flags. Graphic3d_TransModeFlags Mode() const { return myMode; } @@ -130,7 +142,7 @@ public: void SetPersistence (const Graphic3d_TransModeFlags theMode, const gp_Pnt& thePnt) { - if (!IsZoomOrRotate (theMode)) + if (!IsZoomOrRotate (theMode) && !IsAxial (theMode)) { throw Standard_ProgramError("Graphic3d_TransformPers::SetPersistence(), wrong persistence mode."); } @@ -163,7 +175,7 @@ public: //! Return the anchor point for zoom/rotate transformation persistence. gp_Pnt AnchorPoint() const { - if (!IsZoomOrRotate()) + if (!IsZoomOrRotate() && !IsAxial()) { throw Standard_ProgramError("Graphic3d_TransformPers::AnchorPoint(), wrong persistence mode."); } @@ -174,7 +186,7 @@ public: //! Set the anchor point for zoom/rotate transformation persistence. void SetAnchorPoint (const gp_Pnt& thePnt) { - if (!IsZoomOrRotate()) + if (!IsZoomOrRotate() && !IsAxial()) { throw Standard_ProgramError("Graphic3d_TransformPers::SetAnchorPoint(), wrong persistence mode."); } @@ -448,6 +460,10 @@ void Graphic3d_TransformPers::Apply (const Handle(Graphic3d_Camera)& theCamera, } } + Graphic3d_TransformUtils::Scale (aWorldView, + 1.0 / theCamera->AxialScale().X(), + 1.0 / theCamera->AxialScale().Y(), + 1.0 / theCamera->AxialScale().Z()); Graphic3d_TransformUtils::Translate (aWorldView, aCenter.X(), aCenter.Y(), aCenter.Z()); Graphic3d_TransformUtils::Scale (aWorldView, aScale, aScale, aScale); } @@ -517,6 +533,14 @@ void Graphic3d_TransformPers::Apply (const Handle(Graphic3d_Camera)& theCamera, aWorldView.SetValue (2, 2, aRotMat.GetColumn (2).z()); } + if (IsAxial()) + { + Graphic3d_TransformUtils::Scale (aWorldView, + 1.0 / theCamera->AxialScale().X(), + 1.0 / theCamera->AxialScale().Y(), + 1.0 / theCamera->AxialScale().Z()); + } + if ((myMode & Graphic3d_TMF_ZoomPers) != 0) { // lock zooming diff --git a/src/ViewerTest/ViewerTest.cxx b/src/ViewerTest/ViewerTest.cxx index 43aced25af..dced0cf3f9 100644 --- a/src/ViewerTest/ViewerTest.cxx +++ b/src/ViewerTest/ViewerTest.cxx @@ -4798,6 +4798,14 @@ inline Standard_Boolean parseTrsfPersFlag (const TCollection_AsciiString& theFla { theFlags = Graphic3d_TMF_TriedronPers; } + else if (theFlagString == "axial") + { + theFlags = Graphic3d_TMF_AxialScalePers; + } + else if (theFlagString == "zoomaxial") + { + theFlags = Graphic3d_TMF_AxialZoomPers; + } else if (theFlagString == "none") { theFlags = Graphic3d_TMF_None; @@ -6648,7 +6656,7 @@ If last 3 optional parameters are not set prints numbers of U-, V- isolines and addCmd ("vdisplay", VDisplay2, /* [vdisplay] */ R"( vdisplay [-noupdate|-update] [-mutable] [-neutral] - [-trsfPers {zoom|rotate|zoomRotate|trihedron|none}=none] + [-trsfPers {zoom|rotate|zoomRotate|trihedron|axial|zoomaxial|none}=none] [-trsfPersPos X Y [Z]] [-3d] [-2d|-trihedron [{top|bottom|left|right|topLeft |topRight|bottomLeft|bottomRight} diff --git a/tests/v3d/manipulator/bug33514 b/tests/v3d/manipulator/bug33514 new file mode 100644 index 0000000000..60a2ecf420 --- /dev/null +++ b/tests/v3d/manipulator/bug33514 @@ -0,0 +1,53 @@ +puts "========" +puts "0033514: Visualization - Scaled view twists zoom persistence objects" +puts "========" +puts "" + +pload MODELING VISUALIZATION +vinit +box b 10 10 10 +vdisplay b +vfit +vsetdispmode 1 +vmanipulator vm -attach b +vscale 1 3 10 +vviewparams -scale 6.28866 -proj 0.57735 -0.57735 0.57735 -up -0.408248 0.408248 0.816497 -at 0 10 30 + + +set color_1 [vreadpixel 235 170 -rgb -name] +set color_2 [vreadpixel 223 155 -rgb -name] +set color_3 [vreadpixel 235 155 -rgb -name] + +if {$color_1 != "RED3"} { + puts "ERROR: trihedron does not maintain position" + puts " additional investigation is needed" + puts " expected color is: RED3" + puts " current color is: $color_1" +} + +if {$color_2 != "BLUE3"} { + puts "ERROR: trihedron does not maintain position" + puts " additional investigation is needed" + puts " expected color is: BLUE3" + puts " current color is: $color_2" +} + +if {$color_3 != "GREEN3"} { + puts "ERROR: trihedron does not maintain position" + puts " additional investigation is needed" + puts " expected color is: GREEN3" + puts " current color is: $color_3" +} + +vdump $imagedir/${casename}.png + +vclear +box b 10 10 10 +vdisplay b +vfit +vsetdispmode 1 +vmanipulator vm -attach b -zoomable 1 +vscale 1 3 10 +vviewparams -scale 4.28866 -proj 0.57735 -0.57735 0.57735 -up -0.408248 0.408248 0.816497 -at 0 10 30 + +vdump $imagedir/${casename}_zoomable.png diff --git a/tests/v3d/trihedron/bug27832 b/tests/v3d/trihedron/bug27832 new file mode 100644 index 0000000000..e8ae56dc4f --- /dev/null +++ b/tests/v3d/trihedron/bug27832 @@ -0,0 +1,46 @@ +puts "========" +puts "0027832: Visualization - Scaled zbuffer trihedron" +puts "========" +puts "" + +pload MODELING VISUALIZATION +vinit +box b 10 10 10 +vdisplay b +vfit +vsetdispmode 1 +vzbufftrihedron -on +#draw initial picture of box without visual scale +vdump $imagedir/${casename}_unscaled.png + +#draw picture of box after visual scale +#and zoomed out +vscale 1 3 10 +vzoom 1.0 + +set color_1 [vreadpixel 55 360 -rgb -name] +set color_2 [vreadpixel 50 350 -rgb -name] +set color_3 [vreadpixel 55 355 -rgb -name] + +if {$color_1 != "RED3"} { + puts "ERROR: trihedron does not maintain position" + puts " additional investigation is needed" + puts " expected color is: RED3" + puts " current color is: $color_1" +} + +if {$color_2 != "BLUE3"} { + puts "ERROR: trihedron does not maintain position" + puts " additional investigation is needed" + puts " expected color is: BLUE3" + puts " current color is: $color_2" +} + +if {$color_3 != "GREEN3"} { + puts "ERROR: trihedron does not maintain position" + puts " additional investigation is needed" + puts " expected color is: GREEN3" + puts " current color is: $color_3" +} + +vdump $imagedir/${casename}_scaled.png