0029837: Visualization, Graphic3d_Camera - Fit All operation works incorrectly on...
authorkgv <kgv@opencascade.com>
Mon, 29 Jul 2019 00:21:28 +0000 (03:21 +0300)
committerbugmaster <bugmaster@opencascade.com>
Tue, 30 Jul 2019 16:34:49 +0000 (19:34 +0300)
Graphic3d_Camera has been revised to store camera Direction from Eye explicitly
and Distance to Center instead of auxiliary Center point.

This allows setting camera Distance to 0 (for flat objects) without side effects
like broken FitAll, wobbling on rotating.

src/AIS/AIS_ViewController.cxx
src/AIS/AIS_ViewController.hxx
src/Graphic3d/Graphic3d_Camera.cxx
src/Graphic3d/Graphic3d_Camera.hxx
src/Graphic3d/Graphic3d_TransformPers.hxx
src/V3d/V3d_View.cxx
src/V3d/V3d_View.hxx
tests/bugs/vis/bug29837 [new file with mode: 0644]

index 61aaac5..0e2ce3a 100644 (file)
@@ -1453,6 +1453,7 @@ void AIS_ViewController::handleOrbitRotation (const Handle(V3d_View)& theView,
 
     myRotatePnt3d      = thePnt;
     myCamStartOpUp     = aCam->Up();
+    myCamStartOpDir    = aCam->Direction();
     myCamStartOpEye    = aCam->Eye();
     myCamStartOpCenter = aCam->Center();
 
@@ -1493,8 +1494,9 @@ void AIS_ViewController::handleOrbitRotation (const Handle(V3d_View)& theView,
 
     const gp_Dir aNewUp = gp::DZ().Transformed (aTrsfRot);
     aCam->SetUp (aNewUp);
-    aCam->SetCenter(myRotatePnt3d.XYZ() + myCamStartOpToCenter.Transformed (aTrsfRot).XYZ());
-    aCam->SetEye   (myRotatePnt3d.XYZ() + myCamStartOpToEye   .Transformed (aTrsfRot).XYZ());
+    aCam->SetEyeAndCenter (myRotatePnt3d.XYZ() + myCamStartOpToEye   .Transformed (aTrsfRot).XYZ(),
+                           myRotatePnt3d.XYZ() + myCamStartOpToCenter.Transformed (aTrsfRot).XYZ());
+
     aCam->OrthogonalizeUp();
   }
   else
@@ -1504,9 +1506,9 @@ void AIS_ViewController::handleOrbitRotation (const Handle(V3d_View)& theView,
     //theView->Rotate (aDX, aDY, aDZ, myRotatePnt3d.X(), myRotatePnt3d.Y(), myRotatePnt3d.Z(), false);
 
     // restore previous camera state
-    aCam->SetUp     (myCamStartOpUp);
-    aCam->SetEye    (myCamStartOpEye);
-    aCam->SetCenter (myCamStartOpCenter);
+    aCam->SetEyeAndCenter (myCamStartOpEye, myCamStartOpCenter);
+    aCam->SetUp (myCamStartOpUp);
+    aCam->SetDirectionFromEye (myCamStartOpDir);
 
     Graphic3d_Vec2d aWinXY;
     theView->Size (aWinXY.x(), aWinXY.y());
@@ -1599,11 +1601,10 @@ void AIS_ViewController::handleViewRotation (const Handle(V3d_View)& theView,
   gp_Trsf aTrsfRot;
   aTrsfRot.SetRotation (aRot);
 
-  const double aDist   = aCam->Distance();
   const gp_Dir aNewUp  = gp::DZ().Transformed (aTrsfRot);
   const gp_Dir aNewDir = gp::DX().Transformed (aTrsfRot);
-  aCam->SetUp     (aNewUp);
-  aCam->SetCenter (aCam->Eye().Translated (gp_Vec (aNewDir) * aDist));
+  aCam->SetUp (aNewUp);
+  aCam->SetDirectionFromEye (aNewDir);
   aCam->OrthogonalizeUp();
   theView->Invalidate();
 }
index 01e1f51..7c566b2 100644 (file)
@@ -672,6 +672,7 @@ protected: //! @name rotation/panning transient state variables
   gp_Pnt              myPanPnt3d;                 //!< active panning anchor point
   gp_Pnt              myRotatePnt3d;              //!< active rotation center of gravity
   gp_Dir              myCamStartOpUp;             //!< camera Up    direction at the beginning of rotation
+  gp_Dir              myCamStartOpDir;            //!< camera View  direction at the beginning of rotation
   gp_Pnt              myCamStartOpEye;            //!< camera Eye    position at the beginning of rotation
   gp_Pnt              myCamStartOpCenter;         //!< camera Center position at the beginning of rotation
   gp_Vec              myCamStartOpToCenter;       //!< vector from rotation gravity point to camera Center at the beginning of rotation
index a473094..916d080 100644 (file)
@@ -39,9 +39,6 @@ namespace
   // atomic state counter
   static volatile Standard_Integer THE_STATE_COUNTER = 0;
 
-  // minimum camera distance
-  static const Standard_Real MIN_DISTANCE = Pow (0.1, ShortRealDigits() - 2);
-
   // z-range tolerance compatible with for floating point.
   static Standard_Real zEpsilon()
   {
@@ -64,7 +61,7 @@ namespace
   //! Convert camera definition to Ax3
   gp_Ax3 cameraToAx3 (const Graphic3d_Camera& theCamera)
   {
-    const gp_Dir aBackDir(gp_Vec(theCamera.Center(), theCamera.Eye()));
+    const gp_Dir aBackDir = -theCamera.Direction();
     const gp_Dir anXAxis (theCamera.Up().Crossed (aBackDir));
     const gp_Dir anYAxis (aBackDir      .Crossed (anXAxis));
     const gp_Dir aZAxis  (anXAxis       .Crossed (anYAxis));
@@ -78,8 +75,9 @@ namespace
 // =======================================================================
 Graphic3d_Camera::Graphic3d_Camera()
 : myUp (0.0, 1.0, 0.0),
+  myDirection (0.0, 0.0, 1.0),
   myEye (0.0, 0.0, -1500.0),
-  myCenter (0.0, 0.0, 0.0),
+  myDistance (1500.0),
   myAxialScale (1.0, 1.0, 1.0),
   myProjType (Projection_Orthographic),
   myFOVy (45.0),
@@ -104,8 +102,9 @@ Graphic3d_Camera::Graphic3d_Camera()
 // =======================================================================
 Graphic3d_Camera::Graphic3d_Camera (const Handle(Graphic3d_Camera)& theOther)
 : myUp (0.0, 1.0, 0.0),
+  myDirection (0.0, 0.0, 1.0),
   myEye (0.0, 0.0, -1500.0),
-  myCenter (0.0, 0.0, 0.0),
+  myDistance (1500.0),
   myAxialScale (1.0, 1.0, 1.0),
   myProjType (Projection_Orthographic),
   myFOVy (45.0),
@@ -146,9 +145,17 @@ void Graphic3d_Camera::CopyMappingData (const Handle(Graphic3d_Camera)& theOther
 // =======================================================================
 void Graphic3d_Camera::CopyOrientationData (const Handle(Graphic3d_Camera)& theOtherCamera)
 {
-  SetUp         (theOtherCamera->Up());
-  SetEye        (theOtherCamera->Eye());
-  SetCenter     (theOtherCamera->Center());
+  if (!myEye.IsEqual (theOtherCamera->Eye(), 0.0)
+   || !myUp.IsEqual (theOtherCamera->Up(), 0.0)
+   || !myDirection.IsEqual (theOtherCamera->Direction(), 0.0)
+   ||  myDistance != theOtherCamera->Distance())
+  {
+    myEye = theOtherCamera->Eye();
+    myUp  = theOtherCamera->Up();
+    myDirection = theOtherCamera->Direction();
+    myDistance = theOtherCamera->Distance();
+    InvalidateOrientation();
+  }
   SetAxialScale (theOtherCamera->AxialScale());
 }
 
@@ -163,6 +170,43 @@ void Graphic3d_Camera::Copy (const Handle(Graphic3d_Camera)& theOther)
 }
 
 // =======================================================================
+// function : MoveEyeTo
+// purpose  :
+// =======================================================================
+void Graphic3d_Camera::MoveEyeTo (const gp_Pnt& theEye)
+{
+  if (myEye.IsEqual (theEye, 0.0))
+  {
+    return;
+  }
+
+  myEye = theEye;
+  InvalidateOrientation();
+}
+
+// =======================================================================
+// function : SetEyeAndCenter
+// purpose  :
+// =======================================================================
+void Graphic3d_Camera::SetEyeAndCenter (const gp_Pnt& theEye,
+                                        const gp_Pnt& theCenter)
+{
+  if (Eye()   .IsEqual (theEye,    0.0)
+   && Center().IsEqual (theCenter, 0.0))
+  {
+    return;
+  }
+
+  myEye = theEye;
+  myDistance = theEye.Distance (theCenter);
+  if (myDistance > gp::Resolution())
+  {
+    myDirection = gp_Dir (theCenter.XYZ() - theEye.XYZ());
+  }
+  InvalidateOrientation();
+}
+
+// =======================================================================
 // function : SetEye
 // purpose  :
 // =======================================================================
@@ -173,7 +217,13 @@ void Graphic3d_Camera::SetEye (const gp_Pnt& theEye)
     return;
   }
 
+  const gp_Pnt aCenter = Center();
   myEye = theEye;
+  myDistance = myEye.Distance (aCenter);
+  if (myDistance > gp::Resolution())
+  {
+    myDirection = gp_Dir (aCenter.XYZ() - myEye.XYZ());
+  }
   InvalidateOrientation();
 }
 
@@ -183,12 +233,17 @@ void Graphic3d_Camera::SetEye (const gp_Pnt& theEye)
 // =======================================================================
 void Graphic3d_Camera::SetCenter (const gp_Pnt& theCenter)
 {
-  if (Center().IsEqual (theCenter, 0.0))
+  const Standard_Real aDistance = myEye.Distance (theCenter);
+  if (myDistance == aDistance)
   {
     return;
   }
 
-  myCenter = theCenter;
+  myDistance = aDistance;
+  if (myDistance > gp::Resolution())
+  {
+    myDirection = gp_Dir (theCenter.XYZ() - myEye.XYZ());
+  }
   InvalidateOrientation();
 }
 
@@ -228,26 +283,30 @@ void Graphic3d_Camera::SetAxialScale (const gp_XYZ& theAxialScale)
 // =======================================================================
 void Graphic3d_Camera::SetDistance (const Standard_Real theDistance)
 {
-  if (Distance() == theDistance)
+  if (myDistance == theDistance)
   {
     return;
   }
 
-  gp_Vec aCenter2Eye (Direction());
-  aCenter2Eye.Reverse();
-
-  // Camera should have non-zero distance.
-  aCenter2Eye.Scale (Max (theDistance, MIN_DISTANCE));
-  SetEye (Center().Translated (aCenter2Eye));
+  const gp_Pnt aCenter = Center();
+  myDistance = theDistance;
+  myEye = aCenter.XYZ() - myDirection.XYZ() * myDistance;
+  InvalidateOrientation();
 }
 
 // =======================================================================
-// function : Distance
+// function : SetDirectionFromEye
 // purpose  :
 // =======================================================================
-Standard_Real Graphic3d_Camera::Distance() const
+void Graphic3d_Camera::SetDirectionFromEye (const gp_Dir& theDir)
 {
-  return myEye.Distance (myCenter);
+  if (myDirection.IsEqual (theDir, 0.0))
+  {
+    return;
+  }
+
+  myDirection = theDir;
+  InvalidateOrientation();
 }
 
 // =======================================================================
@@ -256,24 +315,15 @@ Standard_Real Graphic3d_Camera::Distance() const
 // =======================================================================
 void Graphic3d_Camera::SetDirection (const gp_Dir& theDir)
 {
-  if (Direction().IsEqual (theDir, 0.0))
+  if (myDirection.IsEqual (theDir, 0.0))
   {
     return;
   }
 
-  gp_Vec aScaledDir (theDir);
-  aScaledDir.Scale (Distance());
-  aScaledDir.Reverse();
-  SetEye (Center().Translated (aScaledDir));
-}
-
-// =======================================================================
-// function : Direction
-// purpose  :
-// =======================================================================
-gp_Dir Graphic3d_Camera::Direction() const
-{
-  return gp_Dir (gp_Vec (myEye, myCenter));
+  const gp_Pnt aCenter = Center();
+  myDirection = theDir;
+  myEye = aCenter.XYZ() - theDir.XYZ() * myDistance;
+  InvalidateOrientation();
 }
 
 // =======================================================================
@@ -500,9 +550,10 @@ void Graphic3d_Camera::Transform (const gp_Trsf& theTrsf)
     return;
   }
 
-  SetUp     (myUp.Transformed (theTrsf));
-  SetEye    (myEye.Transformed (theTrsf));
-  SetCenter (myCenter.Transformed (theTrsf));
+  myUp .Transform (theTrsf);
+  myDirection.Transform (theTrsf);
+  myEye.Transform (theTrsf);
+  InvalidateOrientation();
 }
 
 // =======================================================================
@@ -953,9 +1004,9 @@ Graphic3d_Camera::TransformMatrices<Elem_t>&
                                   static_cast<Elem_t> (myEye.Y()),
                                   static_cast<Elem_t> (myEye.Z()));
 
-  NCollection_Vec3<Elem_t> aCenter (static_cast<Elem_t> (myCenter.X()),
-                                    static_cast<Elem_t> (myCenter.Y()),
-                                    static_cast<Elem_t> (myCenter.Z()));
+  NCollection_Vec3<Elem_t> aViewDir (static_cast<Elem_t> (myDirection.X()),
+                                     static_cast<Elem_t> (myDirection.Y()),
+                                     static_cast<Elem_t> (myDirection.Z()));
 
   NCollection_Vec3<Elem_t> anUp (static_cast<Elem_t> (myUp.X()),
                                  static_cast<Elem_t> (myUp.Y()),
@@ -965,7 +1016,7 @@ Graphic3d_Camera::TransformMatrices<Elem_t>&
                                          static_cast<Elem_t> (myAxialScale.Y()),
                                          static_cast<Elem_t> (myAxialScale.Z()));
 
-  LookOrientation (anEye, aCenter, anUp, anAxialScale, theMatrices.Orientation);
+  LookOrientation (anEye, aViewDir, anUp, anAxialScale, theMatrices.Orientation);
 
   return theMatrices; // for inline accessors
 }
@@ -1106,12 +1157,12 @@ void Graphic3d_Camera::StereoEyeProj (const Elem_t theLeft,
 // =======================================================================
 template <typename Elem_t>
 void Graphic3d_Camera::LookOrientation (const NCollection_Vec3<Elem_t>& theEye,
-                                        const NCollection_Vec3<Elem_t>& theLookAt,
+                                        const NCollection_Vec3<Elem_t>& theFwdDir,
                                         const NCollection_Vec3<Elem_t>& theUpDir,
                                         const NCollection_Vec3<Elem_t>& theAxialScale,
                                         NCollection_Mat4<Elem_t>& theOutMx)
 {
-  NCollection_Vec3<Elem_t> aForward = theLookAt - theEye;
+  NCollection_Vec3<Elem_t> aForward = theFwdDir;
   aForward.Normalize();
 
   // side = forward x up
@@ -1219,7 +1270,9 @@ bool Graphic3d_Camera::ZFitAll (const Standard_Real theScaleFactor,
     Standard_Real aDistance = aCamPln.Distance (aMeasurePnt);
 
     // Check if the camera is intruded into the scene.
-    if (aCamDir.IsOpposite (gp_Vec (aCamEye, aMeasurePnt), M_PI * 0.5))
+    gp_Vec aVecToMeasurePnt (aCamEye, aMeasurePnt);
+    if (aVecToMeasurePnt.Magnitude() > gp::Resolution()
+     && aCamDir.IsOpposite (aVecToMeasurePnt, M_PI * 0.5))
     {
       aDistance *= -1;
     }
@@ -1310,6 +1363,10 @@ bool Graphic3d_Camera::ZFitAll (const Standard_Real theScaleFactor,
     {
       // Clip zNear according to the minimum value matching the quality.
       aZNear = aZNearMin;
+      if (aZFar < aZNear)
+      {
+        aZFar = aZNear;
+      }
     }
     else
     {
@@ -1325,10 +1382,12 @@ bool Graphic3d_Camera::ZFitAll (const Standard_Real theScaleFactor,
     {
       aZNear = zEpsilon();
     }
+    Standard_ASSERT_RAISE (aZFar > aZNear, "ZFar should be greater than ZNear");
   }
 
   theZNear = aZNear;
   theZFar  = aZFar;
+  Standard_ASSERT_RAISE (aZFar > aZNear, "ZFar should be greater than ZNear");
   return true;
 }
 
@@ -1400,8 +1459,7 @@ Standard_EXPORT void NCollection_Lerp<Handle(Graphic3d_Camera)>::Interpolate (co
     aCenter = anAnchor + aDirEyeToCenter.XYZ() * aDistEyeCenter * aKc;
     anEye   = anAnchor - aDirEyeToCenter.XYZ() * aDistEyeCenter * (1.0 - aKc);
 
-    theCamera->SetCenter (aCenter);
-    theCamera->SetEye    (anEye);
+    theCamera->SetEyeAndCenter (anEye, aCenter);
   }
 
   // apply scaling
index f532763..62fc9f7 100644 (file)
@@ -155,30 +155,28 @@ public:
 //! @name Public camera properties
 public:
 
-  //! Sets camera Eye position.
-  //! @param theEye [in] the location of camera's Eye.
-  Standard_EXPORT void SetEye (const gp_Pnt& theEye);
+  //! Get camera look direction.
+  //! @return camera look direction.
+  const gp_Dir& Direction() const { return myDirection; }
 
-  //! Get camera Eye position.
-  //! @return camera eye location.
-  const gp_Pnt& Eye() const
-  {
-    return myEye;
-  }
+  //! Sets camera look direction preserving the current Eye() position.
+  //! WARNING! This method does NOT verify that the current Up() vector is orthogonal to the new Direction.
+  //! @param theDir [in] the direction.
+  Standard_EXPORT void SetDirectionFromEye (const gp_Dir& theDir);
 
-  //! Sets Center of the camera.
-  //! @param theCenter [in] the point where the camera looks at.
-  Standard_EXPORT void SetCenter (const gp_Pnt& theCenter);
+  //! Sets camera look direction and computes the new Eye position relative to current Center.
+  //! WARNING! This method does NOT verify that the current Up() vector is orthogonal to the new Direction.
+  //! @param theDir [in] the direction.
+  Standard_EXPORT void SetDirection (const gp_Dir& theDir);
 
-  //! Get Center of the camera.
-  //! @return the point where the camera looks at.
-  const gp_Pnt& Center() const
-  {
-    return myCenter;
-  }
+  //! Get camera Up direction vector.
+  //! @return Camera's Up direction vector.
+  const gp_Dir& Up() const { return myUp; }
 
   //! Sets camera Up direction vector, orthogonal to camera direction.
+  //! WARNING! This method does NOT verify that the new Up vector is orthogonal to the current Direction().
   //! @param theUp [in] the Up direction vector.
+  //! @sa OrthogonalizeUp().
   Standard_EXPORT void SetUp (const gp_Dir& theUp);
 
   //! Orthogonalize up direction vector.
@@ -187,39 +185,54 @@ public:
   //! Return a copy of orthogonalized up direction vector.
   Standard_EXPORT gp_Dir OrthogonalizedUp() const;
 
-  //! Get camera Up direction vector.
-  //! @return Camera's Up direction vector.
-  const gp_Dir& Up() const
-  {
-    return myUp;
-  }
+  //! Get camera Eye position.
+  //! @return camera eye location.
+  const gp_Pnt& Eye() const { return myEye; }
 
-  //! Set camera axial scale.
-  //! @param theAxialScale [in] the axial scale vector.
-  Standard_EXPORT void SetAxialScale (const gp_XYZ& theAxialScale);
+  //! Sets camera Eye position.
+  //! Unlike SetEye(), this method only changes Eye point and preserves camera direction.
+  //! @param theEye [in] the location of camera's Eye.
+  //! @sa SetEye()
+  Standard_EXPORT void MoveEyeTo (const gp_Pnt& theEye);
 
-  //! Get camera axial scale.
-  //! @return Camera's axial scale.
-  const gp_XYZ& AxialScale() const
+  //! Sets camera Eye and Center positions.
+  //! @param theEye    [in] the location of camera's Eye
+  //! @param theCenter [in] the location of camera's Center
+  Standard_EXPORT void SetEyeAndCenter (const gp_Pnt& theEye,
+                                        const gp_Pnt& theCenter);
+
+  //! Sets camera Eye position.
+  //! WARNING! For backward compatibility reasons, this method also changes view direction,
+  //! so that the new direction is computed from new Eye position to old Center position.
+  //! @param theEye [in] the location of camera's Eye.
+  //! @sa MoveEyeTo(), SetEyeAndCenter()
+  Standard_EXPORT void SetEye (const gp_Pnt& theEye);
+
+  //! Get Center of the camera, e.g. the point where camera looks at.
+  //! This point is computed as Eye() translated along Direction() at Distance().
+  //! @return the point where the camera looks at.
+  gp_Pnt Center() const
   {
-    return myAxialScale;
+    return myEye.XYZ() + myDirection.XYZ() * myDistance;
   }
 
-  //! Set distance of Eye from camera Center.
-  //! @param theDistance [in] the distance.
-  Standard_EXPORT void SetDistance (const Standard_Real theDistance);
+  //! Sets Center of the camera, e.g. the point where camera looks at.
+  //! This methods changes camera direction, so that the new direction is computed
+  //! from current Eye position to specified Center position.
+  //! @param theCenter [in] the point where the camera looks at.
+  Standard_EXPORT void SetCenter (const gp_Pnt& theCenter);
 
   //! Get distance of Eye from camera Center.
   //! @return the distance.
-  Standard_EXPORT Standard_Real Distance() const;
+  Standard_Real Distance() const { return myDistance; }
 
-  //! Sets camera look direction.
-  //! @param theDir [in] the direction.
-  Standard_EXPORT void SetDirection (const gp_Dir& theDir);
+  //! Set distance of Eye from camera Center.
+  //! @param theDistance [in] the distance.
+  Standard_EXPORT void SetDistance (const Standard_Real theDistance);
 
-  //! Get camera look direction.
-  //! @return camera look direction.
-  Standard_EXPORT gp_Dir Direction() const;
+  //! Get camera scale.
+  //! @return camera scale factor.
+  Standard_EXPORT Standard_Real Scale() const;
 
   //! Sets camera scale. For orthographic projection the scale factor
   //! corresponds to parallel scale of view mapping  (i.e. size
@@ -231,9 +244,13 @@ public:
   //! @param theScale [in] the scale factor.
   Standard_EXPORT void SetScale (const Standard_Real theScale);
 
-  //! Get camera scale.
-  //! @return camera scale factor.
-  Standard_EXPORT Standard_Real Scale() const;
+  //! Get camera axial scale.
+  //! @return Camera's axial scale.
+  const gp_XYZ& AxialScale() const { return myAxialScale; }
+
+  //! Set camera axial scale.
+  //! @param theAxialScale [in] the axial scale vector.
+  Standard_EXPORT void SetAxialScale (const gp_XYZ& theAxialScale);
 
   //! Change camera projection type.
   //! When switching to perspective projection from orthographic one,
@@ -619,14 +636,14 @@ private:
   //! Reference point differs for perspective and ortho modes 
   //! (made for compatibility, to be improved..).
   //! @param theEye [in] the eye coordinates in 3D space.
-  //! @param theLookAt [in] the point the camera looks at.
+  //! @param theFwdDir [in] view direction
   //! @param theUpDir [in] the up direction vector.
   //! @param theAxialScale [in] the axial scale vector.
   //! @param theOutMx [in/out] the orientation matrix.
   template <typename Elem_t>
   static void
     LookOrientation (const NCollection_Vec3<Elem_t>& theEye,
-                     const NCollection_Vec3<Elem_t>& theLookAt,
+                     const NCollection_Vec3<Elem_t>& theFwdDir,
                      const NCollection_Vec3<Elem_t>& theUpDir,
                      const NCollection_Vec3<Elem_t>& theAxialScale,
                      NCollection_Mat4<Elem_t>&       theOutMx);
@@ -654,9 +671,10 @@ public:
 
 private:
 
-  gp_Dir myUp;     //!< Camera up direction vector.
-  gp_Pnt myEye;    //!< Camera eye position.
-  gp_Pnt myCenter; //!< Camera center.
+  gp_Dir        myUp;       //!< Camera up direction vector
+  gp_Dir        myDirection;//!< Camera view direction (from eye)
+  gp_Pnt        myEye;      //!< Camera eye position
+  Standard_Real myDistance; //!< distance from Eye to Center
 
   gp_XYZ myAxialScale; //!< World axial scale.
 
index 7ad65a0..cdc832a 100644 (file)
@@ -349,7 +349,7 @@ void Graphic3d_TransformPers::Apply (const Handle(Graphic3d_Camera)& theCamera,
     // scale factor to pixels
     const gp_XYZ aViewDim = theCamera->ViewDimensions (aFocus);
     const Standard_Real aScale = Abs(aViewDim.Y()) / Standard_Real(aVPSizeY);
-    const gp_Dir aForward (theCamera->Center().XYZ() - theCamera->Eye().XYZ());
+    const gp_Dir aForward = theCamera->Direction();
     gp_XYZ aCenter = theCamera->Center().XYZ() + aForward.XYZ() * (aFocus - theCamera->Distance());
     if ((myParams.Params2d.Corner & (Aspect_TOTP_LEFT | Aspect_TOTP_RIGHT)) != 0)
     {
index 61ae63b..c46590a 100644 (file)
@@ -609,16 +609,17 @@ void V3d_View::Rotate (const Standard_Real ax,
   if (Start)
   {
     myCamStartOpUp     = aCamera->Up();
+    myCamStartOpDir    = aCamera->Direction();
     myCamStartOpEye    = aCamera->Eye();
     myCamStartOpCenter = aCamera->Center();
   }
 
-  aCamera->SetUp     (myCamStartOpUp);
-  aCamera->SetEye    (myCamStartOpEye);
-  aCamera->SetCenter (myCamStartOpCenter);
+  aCamera->SetUp (myCamStartOpUp);
+  aCamera->SetEyeAndCenter (myCamStartOpEye, myCamStartOpCenter);
+  aCamera->SetDirectionFromEye (myCamStartOpDir);
 
   // rotate camera around 3 initial axes
-  gp_Dir aBackDir (gp_Vec (myCamStartOpCenter, myCamStartOpEye));
+  gp_Dir aBackDir = -myCamStartOpDir;
   gp_Dir aXAxis (myCamStartOpUp.Crossed (aBackDir));
   gp_Dir aYAxis (aBackDir.Crossed (aXAxis));
   gp_Dir aZAxis (aXAxis.Crossed (aYAxis));
@@ -663,15 +664,16 @@ void V3d_View::Rotate(const Standard_Real ax, const Standard_Real ay, const Stan
   {
     myGravityReferencePoint.SetCoord (X, Y, Z);
     myCamStartOpUp     = aCamera->Up();
+    myCamStartOpDir    = aCamera->Direction();
     myCamStartOpEye    = aCamera->Eye();
     myCamStartOpCenter = aCamera->Center();
   }
 
   const Graphic3d_Vertex& aVref = myGravityReferencePoint;
 
-  aCamera->SetUp     (myCamStartOpUp);
-  aCamera->SetEye    (myCamStartOpEye);
-  aCamera->SetCenter (myCamStartOpCenter);
+  aCamera->SetUp (myCamStartOpUp);
+  aCamera->SetEyeAndCenter (myCamStartOpEye, myCamStartOpCenter);
+  aCamera->SetDirectionFromEye (myCamStartOpDir);
 
   // rotate camera around 3 initial axes
   gp_Pnt aRCenter (aVref.X(), aVref.Y(), aVref.Z());
@@ -732,26 +734,22 @@ void V3d_View::Rotate (const V3d_TypeOfAxe theAxe, const Standard_Real theAngle,
   {
     myGravityReferencePoint.SetCoord (theX, theY, theZ);
     myCamStartOpUp     = aCamera->Up();
+    myCamStartOpDir    = aCamera->Direction();
     myCamStartOpEye    = aCamera->Eye();
     myCamStartOpCenter = aCamera->Center();
-
     switch (theAxe)
     {
       case V3d_X: myViewAxis = gp::DX(); break;
       case V3d_Y: myViewAxis = gp::DY(); break;
       case V3d_Z: myViewAxis = gp::DZ(); break;
     }
-
-    myCamStartOpUp     = aCamera->Up();
-    myCamStartOpEye    = aCamera->Eye();
-    myCamStartOpCenter = aCamera->Center();
   }
 
   const Graphic3d_Vertex& aVref = myGravityReferencePoint;
 
-  aCamera->SetUp     (myCamStartOpUp);
-  aCamera->SetEye    (myCamStartOpEye);
-  aCamera->SetCenter (myCamStartOpCenter);
+  aCamera->SetUp (myCamStartOpUp);
+  aCamera->SetEyeAndCenter (myCamStartOpEye, myCamStartOpCenter);
+  aCamera->SetDirectionFromEye (myCamStartOpDir);
 
   // rotate camera around passed axis
   gp_Trsf aRotation;
@@ -782,15 +780,17 @@ void V3d_View::Rotate(const Standard_Real angle, const Standard_Boolean Start)
 
   Handle(Graphic3d_Camera) aCamera = Camera();
 
-  if( Start ) {
+  if (Start)
+  {
     myCamStartOpUp     = aCamera->Up();
+    myCamStartOpDir    = aCamera->Direction();
     myCamStartOpEye    = aCamera->Eye();
     myCamStartOpCenter = aCamera->Center();
   }
 
-  aCamera->SetUp     (myCamStartOpUp);
-  aCamera->SetEye    (myCamStartOpEye);
-  aCamera->SetCenter (myCamStartOpCenter);
+  aCamera->SetUp (myCamStartOpUp);
+  aCamera->SetEyeAndCenter (myCamStartOpEye, myCamStartOpCenter);
+  aCamera->SetDirectionFromEye (myCamStartOpDir);
 
   gp_Trsf aRotation;
   gp_Pnt aRCenter (myDefaultViewPoint);
@@ -823,15 +823,17 @@ void V3d_View::Turn(const Standard_Real ax, const Standard_Real ay, const Standa
 
   Handle(Graphic3d_Camera) aCamera = Camera();
 
-  if( Start ) {
+  if (Start)
+  {
     myCamStartOpUp     = aCamera->Up();
+    myCamStartOpDir    = aCamera->Direction();
     myCamStartOpEye    = aCamera->Eye();
     myCamStartOpCenter = aCamera->Center();
   }
 
-  aCamera->SetUp     (myCamStartOpUp);
-  aCamera->SetEye    (myCamStartOpEye);
-  aCamera->SetCenter (myCamStartOpCenter);
+  aCamera->SetUp (myCamStartOpUp);
+  aCamera->SetEyeAndCenter (myCamStartOpEye, myCamStartOpCenter);
+  aCamera->SetDirectionFromEye (myCamStartOpDir);
 
   // rotate camera around 3 initial axes
   gp_Pnt aRCenter = aCamera->Eye();
@@ -886,15 +888,17 @@ void V3d_View::Turn(const Standard_Real angle, const Standard_Boolean Start)
 
   Handle(Graphic3d_Camera) aCamera = Camera();
 
-  if( Start ) {
+  if (Start)
+  {
     myCamStartOpUp     = aCamera->Up();
+    myCamStartOpDir    = aCamera->Direction();
     myCamStartOpEye    = aCamera->Eye();
     myCamStartOpCenter = aCamera->Center();
   }
 
-  aCamera->SetUp     (myCamStartOpUp);
-  aCamera->SetEye    (myCamStartOpEye);
-  aCamera->SetCenter (myCamStartOpCenter);
+  aCamera->SetUp (myCamStartOpUp);
+  aCamera->SetEyeAndCenter (myCamStartOpEye, myCamStartOpCenter);
+  aCamera->SetDirectionFromEye (myCamStartOpDir);
 
   gp_Trsf aRotation;
   gp_Pnt aRCenter = aCamera->Eye();
@@ -1054,8 +1058,10 @@ void V3d_View::SetProj (const V3d_TypeOfOrientation theOrientation,
   const Handle(Graphic3d_Camera)& aCamera = Camera();
   const gp_Pnt anOriginVCS = aCamera->ConvertWorld2View (gp::Origin());
 
-  aCamera->SetCenter (gp_Pnt (0, 0, 0));
-  aCamera->SetDirection (gp_Dir (aBck.X(), aBck.Y(), aBck.Z()).Reversed());
+  const Standard_Real aNewDist = aCamera->Eye().Distance (gp_Pnt (0, 0, 0));
+  aCamera->SetEyeAndCenter (gp_XYZ (0, 0, 0) + aBck.XYZ() * aNewDist,
+                            gp_XYZ (0, 0, 0));
+  aCamera->SetDirectionFromEye (-aBck);
   aCamera->SetUp (gp_Dir (anUp.x(), anUp.y(), anUp.z()));
   aCamera->OrthogonalizeUp();
 
@@ -2343,6 +2349,7 @@ void V3d_View::Panning (const Standard_Real theDXv,
 
   if (theToStart)
   {
+    myCamStartOpDir    = aCamera->Direction();
     myCamStartOpEye    = aCamera->Eye();
     myCamStartOpCenter = aCamera->Center();
   }
@@ -2351,8 +2358,8 @@ void V3d_View::Panning (const Standard_Real theDXv,
 
   gp_Pnt aViewDims = aCamera->ViewDimensions();
 
-  aCamera->SetEye (myCamStartOpEye);
-  aCamera->SetCenter (myCamStartOpCenter);
+  aCamera->SetEyeAndCenter (myCamStartOpEye, myCamStartOpCenter);
+  aCamera->SetDirectionFromEye (myCamStartOpDir);
   Translate (aCamera, -theDXv, -theDYv);
   Scale (aCamera, aViewDims.X() / theZoomFactor, aViewDims.Y() / theZoomFactor);
 
index c27d6f8..e6a1dd5 100644 (file)
@@ -995,6 +995,7 @@ protected:
   Standard_Real myOldMouseX;
   Standard_Real myOldMouseY;
   gp_Dir myCamStartOpUp;
+  gp_Dir myCamStartOpDir;
   gp_Pnt myCamStartOpEye;
   Standard_Real myCamStartOpBnd[6];
   gp_Pnt myCamStartOpCenter;
diff --git a/tests/bugs/vis/bug29837 b/tests/bugs/vis/bug29837
new file mode 100644 (file)
index 0000000..01019a5
--- /dev/null
@@ -0,0 +1,20 @@
+puts "============"
+puts "0029837: Visualization, Graphic3d_Camera - Fit All operation works incorrectly on flat object"
+puts "============"
+puts ""
+
+pload VISUALIZATION
+vclear
+vinit View1
+vtop
+vpoint p1   0 0 4000
+vpoint p2 200 0 4000
+vaspects p1 -setColor RED
+vaspects p2 -setColor GREEN
+vaspects p1 p2 -setMarkerType . -setMarkerSize 20
+vsegment s p1 p2
+vfit
+if { [vreadpixel   5 200 -rgb -name] != "RED"   } { puts "Error: p1 not found" }
+if { [vreadpixel 402 200 -rgb -name] != "GREEN" } { puts "Error: p2 not found" }
+
+vdump $::imagedir/${::casename}.png