1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-10 18:51:21 +03:00

0029837: Visualization, Graphic3d_Camera - Fit All operation works incorrectly on flat object

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.
This commit is contained in:
kgv 2019-07-29 03:21:28 +03:00 committed by bugmaster
parent e36ee9677a
commit 607e5e62e7
8 changed files with 243 additions and 137 deletions

View File

@ -1453,6 +1453,7 @@ void AIS_ViewController::handleOrbitRotation (const Handle(V3d_View)& theView,
myRotatePnt3d = thePnt; myRotatePnt3d = thePnt;
myCamStartOpUp = aCam->Up(); myCamStartOpUp = aCam->Up();
myCamStartOpDir = aCam->Direction();
myCamStartOpEye = aCam->Eye(); myCamStartOpEye = aCam->Eye();
myCamStartOpCenter = aCam->Center(); myCamStartOpCenter = aCam->Center();
@ -1493,8 +1494,9 @@ void AIS_ViewController::handleOrbitRotation (const Handle(V3d_View)& theView,
const gp_Dir aNewUp = gp::DZ().Transformed (aTrsfRot); const gp_Dir aNewUp = gp::DZ().Transformed (aTrsfRot);
aCam->SetUp (aNewUp); aCam->SetUp (aNewUp);
aCam->SetCenter(myRotatePnt3d.XYZ() + myCamStartOpToCenter.Transformed (aTrsfRot).XYZ()); aCam->SetEyeAndCenter (myRotatePnt3d.XYZ() + myCamStartOpToEye .Transformed (aTrsfRot).XYZ(),
aCam->SetEye (myRotatePnt3d.XYZ() + myCamStartOpToEye .Transformed (aTrsfRot).XYZ()); myRotatePnt3d.XYZ() + myCamStartOpToCenter.Transformed (aTrsfRot).XYZ());
aCam->OrthogonalizeUp(); aCam->OrthogonalizeUp();
} }
else 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); //theView->Rotate (aDX, aDY, aDZ, myRotatePnt3d.X(), myRotatePnt3d.Y(), myRotatePnt3d.Z(), false);
// restore previous camera state // restore previous camera state
aCam->SetUp (myCamStartOpUp); aCam->SetEyeAndCenter (myCamStartOpEye, myCamStartOpCenter);
aCam->SetEye (myCamStartOpEye); aCam->SetUp (myCamStartOpUp);
aCam->SetCenter (myCamStartOpCenter); aCam->SetDirectionFromEye (myCamStartOpDir);
Graphic3d_Vec2d aWinXY; Graphic3d_Vec2d aWinXY;
theView->Size (aWinXY.x(), aWinXY.y()); theView->Size (aWinXY.x(), aWinXY.y());
@ -1599,11 +1601,10 @@ void AIS_ViewController::handleViewRotation (const Handle(V3d_View)& theView,
gp_Trsf aTrsfRot; gp_Trsf aTrsfRot;
aTrsfRot.SetRotation (aRot); aTrsfRot.SetRotation (aRot);
const double aDist = aCam->Distance();
const gp_Dir aNewUp = gp::DZ().Transformed (aTrsfRot); const gp_Dir aNewUp = gp::DZ().Transformed (aTrsfRot);
const gp_Dir aNewDir = gp::DX().Transformed (aTrsfRot); const gp_Dir aNewDir = gp::DX().Transformed (aTrsfRot);
aCam->SetUp (aNewUp); aCam->SetUp (aNewUp);
aCam->SetCenter (aCam->Eye().Translated (gp_Vec (aNewDir) * aDist)); aCam->SetDirectionFromEye (aNewDir);
aCam->OrthogonalizeUp(); aCam->OrthogonalizeUp();
theView->Invalidate(); theView->Invalidate();
} }

View File

@ -672,6 +672,7 @@ protected: //! @name rotation/panning transient state variables
gp_Pnt myPanPnt3d; //!< active panning anchor point gp_Pnt myPanPnt3d; //!< active panning anchor point
gp_Pnt myRotatePnt3d; //!< active rotation center of gravity gp_Pnt myRotatePnt3d; //!< active rotation center of gravity
gp_Dir myCamStartOpUp; //!< camera Up direction at the beginning of rotation 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 myCamStartOpEye; //!< camera Eye position at the beginning of rotation
gp_Pnt myCamStartOpCenter; //!< camera Center 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 gp_Vec myCamStartOpToCenter; //!< vector from rotation gravity point to camera Center at the beginning of rotation

View File

@ -39,9 +39,6 @@ namespace
// atomic state counter // atomic state counter
static volatile Standard_Integer THE_STATE_COUNTER = 0; 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. // z-range tolerance compatible with for floating point.
static Standard_Real zEpsilon() static Standard_Real zEpsilon()
{ {
@ -64,7 +61,7 @@ namespace
//! Convert camera definition to Ax3 //! Convert camera definition to Ax3
gp_Ax3 cameraToAx3 (const Graphic3d_Camera& theCamera) 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 anXAxis (theCamera.Up().Crossed (aBackDir));
const gp_Dir anYAxis (aBackDir .Crossed (anXAxis)); const gp_Dir anYAxis (aBackDir .Crossed (anXAxis));
const gp_Dir aZAxis (anXAxis .Crossed (anYAxis)); const gp_Dir aZAxis (anXAxis .Crossed (anYAxis));
@ -78,8 +75,9 @@ namespace
// ======================================================================= // =======================================================================
Graphic3d_Camera::Graphic3d_Camera() Graphic3d_Camera::Graphic3d_Camera()
: myUp (0.0, 1.0, 0.0), : myUp (0.0, 1.0, 0.0),
myDirection (0.0, 0.0, 1.0),
myEye (0.0, 0.0, -1500.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), myAxialScale (1.0, 1.0, 1.0),
myProjType (Projection_Orthographic), myProjType (Projection_Orthographic),
myFOVy (45.0), myFOVy (45.0),
@ -104,8 +102,9 @@ Graphic3d_Camera::Graphic3d_Camera()
// ======================================================================= // =======================================================================
Graphic3d_Camera::Graphic3d_Camera (const Handle(Graphic3d_Camera)& theOther) Graphic3d_Camera::Graphic3d_Camera (const Handle(Graphic3d_Camera)& theOther)
: myUp (0.0, 1.0, 0.0), : myUp (0.0, 1.0, 0.0),
myDirection (0.0, 0.0, 1.0),
myEye (0.0, 0.0, -1500.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), myAxialScale (1.0, 1.0, 1.0),
myProjType (Projection_Orthographic), myProjType (Projection_Orthographic),
myFOVy (45.0), 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) void Graphic3d_Camera::CopyOrientationData (const Handle(Graphic3d_Camera)& theOtherCamera)
{ {
SetUp (theOtherCamera->Up()); if (!myEye.IsEqual (theOtherCamera->Eye(), 0.0)
SetEye (theOtherCamera->Eye()); || !myUp.IsEqual (theOtherCamera->Up(), 0.0)
SetCenter (theOtherCamera->Center()); || !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()); SetAxialScale (theOtherCamera->AxialScale());
} }
@ -162,6 +169,43 @@ void Graphic3d_Camera::Copy (const Handle(Graphic3d_Camera)& theOther)
CopyOrientationData (theOther); CopyOrientationData (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 // function : SetEye
// purpose : // purpose :
@ -173,7 +217,13 @@ void Graphic3d_Camera::SetEye (const gp_Pnt& theEye)
return; return;
} }
const gp_Pnt aCenter = Center();
myEye = theEye; myEye = theEye;
myDistance = myEye.Distance (aCenter);
if (myDistance > gp::Resolution())
{
myDirection = gp_Dir (aCenter.XYZ() - myEye.XYZ());
}
InvalidateOrientation(); InvalidateOrientation();
} }
@ -183,12 +233,17 @@ void Graphic3d_Camera::SetEye (const gp_Pnt& theEye)
// ======================================================================= // =======================================================================
void Graphic3d_Camera::SetCenter (const gp_Pnt& theCenter) 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; return;
} }
myCenter = theCenter; myDistance = aDistance;
if (myDistance > gp::Resolution())
{
myDirection = gp_Dir (theCenter.XYZ() - myEye.XYZ());
}
InvalidateOrientation(); InvalidateOrientation();
} }
@ -228,26 +283,30 @@ void Graphic3d_Camera::SetAxialScale (const gp_XYZ& theAxialScale)
// ======================================================================= // =======================================================================
void Graphic3d_Camera::SetDistance (const Standard_Real theDistance) void Graphic3d_Camera::SetDistance (const Standard_Real theDistance)
{ {
if (Distance() == theDistance) if (myDistance == theDistance)
{ {
return; return;
} }
gp_Vec aCenter2Eye (Direction()); const gp_Pnt aCenter = Center();
aCenter2Eye.Reverse(); myDistance = theDistance;
myEye = aCenter.XYZ() - myDirection.XYZ() * myDistance;
// Camera should have non-zero distance. InvalidateOrientation();
aCenter2Eye.Scale (Max (theDistance, MIN_DISTANCE));
SetEye (Center().Translated (aCenter2Eye));
} }
// ======================================================================= // =======================================================================
// function : Distance // function : SetDirectionFromEye
// purpose : // 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) void Graphic3d_Camera::SetDirection (const gp_Dir& theDir)
{ {
if (Direction().IsEqual (theDir, 0.0)) if (myDirection.IsEqual (theDir, 0.0))
{ {
return; return;
} }
gp_Vec aScaledDir (theDir); const gp_Pnt aCenter = Center();
aScaledDir.Scale (Distance()); myDirection = theDir;
aScaledDir.Reverse(); myEye = aCenter.XYZ() - theDir.XYZ() * myDistance;
SetEye (Center().Translated (aScaledDir)); InvalidateOrientation();
}
// =======================================================================
// function : Direction
// purpose :
// =======================================================================
gp_Dir Graphic3d_Camera::Direction() const
{
return gp_Dir (gp_Vec (myEye, myCenter));
} }
// ======================================================================= // =======================================================================
@ -500,9 +550,10 @@ void Graphic3d_Camera::Transform (const gp_Trsf& theTrsf)
return; return;
} }
SetUp (myUp.Transformed (theTrsf)); myUp .Transform (theTrsf);
SetEye (myEye.Transformed (theTrsf)); myDirection.Transform (theTrsf);
SetCenter (myCenter.Transformed (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.Y()),
static_cast<Elem_t> (myEye.Z())); static_cast<Elem_t> (myEye.Z()));
NCollection_Vec3<Elem_t> aCenter (static_cast<Elem_t> (myCenter.X()), NCollection_Vec3<Elem_t> aViewDir (static_cast<Elem_t> (myDirection.X()),
static_cast<Elem_t> (myCenter.Y()), static_cast<Elem_t> (myDirection.Y()),
static_cast<Elem_t> (myCenter.Z())); static_cast<Elem_t> (myDirection.Z()));
NCollection_Vec3<Elem_t> anUp (static_cast<Elem_t> (myUp.X()), NCollection_Vec3<Elem_t> anUp (static_cast<Elem_t> (myUp.X()),
static_cast<Elem_t> (myUp.Y()), 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.Y()),
static_cast<Elem_t> (myAxialScale.Z())); 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 return theMatrices; // for inline accessors
} }
@ -1106,12 +1157,12 @@ void Graphic3d_Camera::StereoEyeProj (const Elem_t theLeft,
// ======================================================================= // =======================================================================
template <typename Elem_t> template <typename Elem_t>
void Graphic3d_Camera::LookOrientation (const NCollection_Vec3<Elem_t>& theEye, 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>& theUpDir,
const NCollection_Vec3<Elem_t>& theAxialScale, const NCollection_Vec3<Elem_t>& theAxialScale,
NCollection_Mat4<Elem_t>& theOutMx) NCollection_Mat4<Elem_t>& theOutMx)
{ {
NCollection_Vec3<Elem_t> aForward = theLookAt - theEye; NCollection_Vec3<Elem_t> aForward = theFwdDir;
aForward.Normalize(); aForward.Normalize();
// side = forward x up // side = forward x up
@ -1219,7 +1270,9 @@ bool Graphic3d_Camera::ZFitAll (const Standard_Real theScaleFactor,
Standard_Real aDistance = aCamPln.Distance (aMeasurePnt); Standard_Real aDistance = aCamPln.Distance (aMeasurePnt);
// Check if the camera is intruded into the scene. // 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; aDistance *= -1;
} }
@ -1310,6 +1363,10 @@ bool Graphic3d_Camera::ZFitAll (const Standard_Real theScaleFactor,
{ {
// Clip zNear according to the minimum value matching the quality. // Clip zNear according to the minimum value matching the quality.
aZNear = aZNearMin; aZNear = aZNearMin;
if (aZFar < aZNear)
{
aZFar = aZNear;
}
} }
else else
{ {
@ -1325,10 +1382,12 @@ bool Graphic3d_Camera::ZFitAll (const Standard_Real theScaleFactor,
{ {
aZNear = zEpsilon(); aZNear = zEpsilon();
} }
Standard_ASSERT_RAISE (aZFar > aZNear, "ZFar should be greater than ZNear");
} }
theZNear = aZNear; theZNear = aZNear;
theZFar = aZFar; theZFar = aZFar;
Standard_ASSERT_RAISE (aZFar > aZNear, "ZFar should be greater than ZNear");
return true; return true;
} }
@ -1400,8 +1459,7 @@ Standard_EXPORT void NCollection_Lerp<Handle(Graphic3d_Camera)>::Interpolate (co
aCenter = anAnchor + aDirEyeToCenter.XYZ() * aDistEyeCenter * aKc; aCenter = anAnchor + aDirEyeToCenter.XYZ() * aDistEyeCenter * aKc;
anEye = anAnchor - aDirEyeToCenter.XYZ() * aDistEyeCenter * (1.0 - aKc); anEye = anAnchor - aDirEyeToCenter.XYZ() * aDistEyeCenter * (1.0 - aKc);
theCamera->SetCenter (aCenter); theCamera->SetEyeAndCenter (anEye, aCenter);
theCamera->SetEye (anEye);
} }
// apply scaling // apply scaling

View File

@ -155,30 +155,28 @@ public:
//! @name Public camera properties //! @name Public camera properties
public: public:
//! Sets camera Eye position. //! Get camera look direction.
//! @param theEye [in] the location of camera's Eye. //! @return camera look direction.
Standard_EXPORT void SetEye (const gp_Pnt& theEye); const gp_Dir& Direction() const { return myDirection; }
//! Get camera Eye position. //! Sets camera look direction preserving the current Eye() position.
//! @return camera eye location. //! WARNING! This method does NOT verify that the current Up() vector is orthogonal to the new Direction.
const gp_Pnt& Eye() const //! @param theDir [in] the direction.
{ Standard_EXPORT void SetDirectionFromEye (const gp_Dir& theDir);
return myEye;
}
//! Sets Center of the camera. //! Sets camera look direction and computes the new Eye position relative to current Center.
//! @param theCenter [in] the point where the camera looks at. //! WARNING! This method does NOT verify that the current Up() vector is orthogonal to the new Direction.
Standard_EXPORT void SetCenter (const gp_Pnt& theCenter); //! @param theDir [in] the direction.
Standard_EXPORT void SetDirection (const gp_Dir& theDir);
//! Get Center of the camera. //! Get camera Up direction vector.
//! @return the point where the camera looks at. //! @return Camera's Up direction vector.
const gp_Pnt& Center() const const gp_Dir& Up() const { return myUp; }
{
return myCenter;
}
//! Sets camera Up direction vector, orthogonal to camera direction. //! 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. //! @param theUp [in] the Up direction vector.
//! @sa OrthogonalizeUp().
Standard_EXPORT void SetUp (const gp_Dir& theUp); Standard_EXPORT void SetUp (const gp_Dir& theUp);
//! Orthogonalize up direction vector. //! Orthogonalize up direction vector.
@ -187,39 +185,54 @@ public:
//! Return a copy of orthogonalized up direction vector. //! Return a copy of orthogonalized up direction vector.
Standard_EXPORT gp_Dir OrthogonalizedUp() const; Standard_EXPORT gp_Dir OrthogonalizedUp() const;
//! Get camera Up direction vector. //! Get camera Eye position.
//! @return Camera's Up direction vector. //! @return camera eye location.
const gp_Dir& Up() const const gp_Pnt& Eye() const { return myEye; }
//! 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);
//! 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 myUp; return myEye.XYZ() + myDirection.XYZ() * myDistance;
} }
//! Set camera axial scale. //! Sets Center of the camera, e.g. the point where camera looks at.
//! @param theAxialScale [in] the axial scale vector. //! This methods changes camera direction, so that the new direction is computed
Standard_EXPORT void SetAxialScale (const gp_XYZ& theAxialScale); //! 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 camera axial scale. //! Get distance of Eye from camera Center.
//! @return Camera's axial scale. //! @return the distance.
const gp_XYZ& AxialScale() const Standard_Real Distance() const { return myDistance; }
{
return myAxialScale;
}
//! Set distance of Eye from camera Center. //! Set distance of Eye from camera Center.
//! @param theDistance [in] the distance. //! @param theDistance [in] the distance.
Standard_EXPORT void SetDistance (const Standard_Real theDistance); Standard_EXPORT void SetDistance (const Standard_Real theDistance);
//! Get distance of Eye from camera Center. //! Get camera scale.
//! @return the distance. //! @return camera scale factor.
Standard_EXPORT Standard_Real Distance() const; Standard_EXPORT Standard_Real Scale() const;
//! Sets camera look direction.
//! @param theDir [in] the direction.
Standard_EXPORT void SetDirection (const gp_Dir& theDir);
//! Get camera look direction.
//! @return camera look direction.
Standard_EXPORT gp_Dir Direction() const;
//! Sets camera scale. For orthographic projection the scale factor //! Sets camera scale. For orthographic projection the scale factor
//! corresponds to parallel scale of view mapping (i.e. size //! corresponds to parallel scale of view mapping (i.e. size
@ -231,9 +244,13 @@ public:
//! @param theScale [in] the scale factor. //! @param theScale [in] the scale factor.
Standard_EXPORT void SetScale (const Standard_Real theScale); Standard_EXPORT void SetScale (const Standard_Real theScale);
//! Get camera scale. //! Get camera axial scale.
//! @return camera scale factor. //! @return Camera's axial scale.
Standard_EXPORT Standard_Real Scale() const; 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. //! Change camera projection type.
//! When switching to perspective projection from orthographic one, //! When switching to perspective projection from orthographic one,
@ -619,14 +636,14 @@ private:
//! Reference point differs for perspective and ortho modes //! Reference point differs for perspective and ortho modes
//! (made for compatibility, to be improved..). //! (made for compatibility, to be improved..).
//! @param theEye [in] the eye coordinates in 3D space. //! @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 theUpDir [in] the up direction vector.
//! @param theAxialScale [in] the axial scale vector. //! @param theAxialScale [in] the axial scale vector.
//! @param theOutMx [in/out] the orientation matrix. //! @param theOutMx [in/out] the orientation matrix.
template <typename Elem_t> template <typename Elem_t>
static void static void
LookOrientation (const NCollection_Vec3<Elem_t>& theEye, 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>& theUpDir,
const NCollection_Vec3<Elem_t>& theAxialScale, const NCollection_Vec3<Elem_t>& theAxialScale,
NCollection_Mat4<Elem_t>& theOutMx); NCollection_Mat4<Elem_t>& theOutMx);
@ -654,9 +671,10 @@ public:
private: private:
gp_Dir myUp; //!< Camera up direction vector. gp_Dir myUp; //!< Camera up direction vector
gp_Pnt myEye; //!< Camera eye position. gp_Dir myDirection;//!< Camera view direction (from eye)
gp_Pnt myCenter; //!< Camera center. gp_Pnt myEye; //!< Camera eye position
Standard_Real myDistance; //!< distance from Eye to Center
gp_XYZ myAxialScale; //!< World axial scale. gp_XYZ myAxialScale; //!< World axial scale.

View File

@ -349,7 +349,7 @@ void Graphic3d_TransformPers::Apply (const Handle(Graphic3d_Camera)& theCamera,
// scale factor to pixels // scale factor to pixels
const gp_XYZ aViewDim = theCamera->ViewDimensions (aFocus); const gp_XYZ aViewDim = theCamera->ViewDimensions (aFocus);
const Standard_Real aScale = Abs(aViewDim.Y()) / Standard_Real(aVPSizeY); 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()); gp_XYZ aCenter = theCamera->Center().XYZ() + aForward.XYZ() * (aFocus - theCamera->Distance());
if ((myParams.Params2d.Corner & (Aspect_TOTP_LEFT | Aspect_TOTP_RIGHT)) != 0) if ((myParams.Params2d.Corner & (Aspect_TOTP_LEFT | Aspect_TOTP_RIGHT)) != 0)
{ {

View File

@ -609,16 +609,17 @@ void V3d_View::Rotate (const Standard_Real ax,
if (Start) if (Start)
{ {
myCamStartOpUp = aCamera->Up(); myCamStartOpUp = aCamera->Up();
myCamStartOpDir = aCamera->Direction();
myCamStartOpEye = aCamera->Eye(); myCamStartOpEye = aCamera->Eye();
myCamStartOpCenter = aCamera->Center(); myCamStartOpCenter = aCamera->Center();
} }
aCamera->SetUp (myCamStartOpUp); aCamera->SetUp (myCamStartOpUp);
aCamera->SetEye (myCamStartOpEye); aCamera->SetEyeAndCenter (myCamStartOpEye, myCamStartOpCenter);
aCamera->SetCenter (myCamStartOpCenter); aCamera->SetDirectionFromEye (myCamStartOpDir);
// rotate camera around 3 initial axes // 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 aXAxis (myCamStartOpUp.Crossed (aBackDir));
gp_Dir aYAxis (aBackDir.Crossed (aXAxis)); gp_Dir aYAxis (aBackDir.Crossed (aXAxis));
gp_Dir aZAxis (aXAxis.Crossed (aYAxis)); 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); myGravityReferencePoint.SetCoord (X, Y, Z);
myCamStartOpUp = aCamera->Up(); myCamStartOpUp = aCamera->Up();
myCamStartOpDir = aCamera->Direction();
myCamStartOpEye = aCamera->Eye(); myCamStartOpEye = aCamera->Eye();
myCamStartOpCenter = aCamera->Center(); myCamStartOpCenter = aCamera->Center();
} }
const Graphic3d_Vertex& aVref = myGravityReferencePoint; const Graphic3d_Vertex& aVref = myGravityReferencePoint;
aCamera->SetUp (myCamStartOpUp); aCamera->SetUp (myCamStartOpUp);
aCamera->SetEye (myCamStartOpEye); aCamera->SetEyeAndCenter (myCamStartOpEye, myCamStartOpCenter);
aCamera->SetCenter (myCamStartOpCenter); aCamera->SetDirectionFromEye (myCamStartOpDir);
// rotate camera around 3 initial axes // rotate camera around 3 initial axes
gp_Pnt aRCenter (aVref.X(), aVref.Y(), aVref.Z()); 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); myGravityReferencePoint.SetCoord (theX, theY, theZ);
myCamStartOpUp = aCamera->Up(); myCamStartOpUp = aCamera->Up();
myCamStartOpDir = aCamera->Direction();
myCamStartOpEye = aCamera->Eye(); myCamStartOpEye = aCamera->Eye();
myCamStartOpCenter = aCamera->Center(); myCamStartOpCenter = aCamera->Center();
switch (theAxe) switch (theAxe)
{ {
case V3d_X: myViewAxis = gp::DX(); break; case V3d_X: myViewAxis = gp::DX(); break;
case V3d_Y: myViewAxis = gp::DY(); break; case V3d_Y: myViewAxis = gp::DY(); break;
case V3d_Z: myViewAxis = gp::DZ(); break; case V3d_Z: myViewAxis = gp::DZ(); break;
} }
myCamStartOpUp = aCamera->Up();
myCamStartOpEye = aCamera->Eye();
myCamStartOpCenter = aCamera->Center();
} }
const Graphic3d_Vertex& aVref = myGravityReferencePoint; const Graphic3d_Vertex& aVref = myGravityReferencePoint;
aCamera->SetUp (myCamStartOpUp); aCamera->SetUp (myCamStartOpUp);
aCamera->SetEye (myCamStartOpEye); aCamera->SetEyeAndCenter (myCamStartOpEye, myCamStartOpCenter);
aCamera->SetCenter (myCamStartOpCenter); aCamera->SetDirectionFromEye (myCamStartOpDir);
// rotate camera around passed axis // rotate camera around passed axis
gp_Trsf aRotation; gp_Trsf aRotation;
@ -782,15 +780,17 @@ void V3d_View::Rotate(const Standard_Real angle, const Standard_Boolean Start)
Handle(Graphic3d_Camera) aCamera = Camera(); Handle(Graphic3d_Camera) aCamera = Camera();
if( Start ) { if (Start)
{
myCamStartOpUp = aCamera->Up(); myCamStartOpUp = aCamera->Up();
myCamStartOpDir = aCamera->Direction();
myCamStartOpEye = aCamera->Eye(); myCamStartOpEye = aCamera->Eye();
myCamStartOpCenter = aCamera->Center(); myCamStartOpCenter = aCamera->Center();
} }
aCamera->SetUp (myCamStartOpUp); aCamera->SetUp (myCamStartOpUp);
aCamera->SetEye (myCamStartOpEye); aCamera->SetEyeAndCenter (myCamStartOpEye, myCamStartOpCenter);
aCamera->SetCenter (myCamStartOpCenter); aCamera->SetDirectionFromEye (myCamStartOpDir);
gp_Trsf aRotation; gp_Trsf aRotation;
gp_Pnt aRCenter (myDefaultViewPoint); 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(); Handle(Graphic3d_Camera) aCamera = Camera();
if( Start ) { if (Start)
{
myCamStartOpUp = aCamera->Up(); myCamStartOpUp = aCamera->Up();
myCamStartOpDir = aCamera->Direction();
myCamStartOpEye = aCamera->Eye(); myCamStartOpEye = aCamera->Eye();
myCamStartOpCenter = aCamera->Center(); myCamStartOpCenter = aCamera->Center();
} }
aCamera->SetUp (myCamStartOpUp); aCamera->SetUp (myCamStartOpUp);
aCamera->SetEye (myCamStartOpEye); aCamera->SetEyeAndCenter (myCamStartOpEye, myCamStartOpCenter);
aCamera->SetCenter (myCamStartOpCenter); aCamera->SetDirectionFromEye (myCamStartOpDir);
// rotate camera around 3 initial axes // rotate camera around 3 initial axes
gp_Pnt aRCenter = aCamera->Eye(); 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(); Handle(Graphic3d_Camera) aCamera = Camera();
if( Start ) { if (Start)
{
myCamStartOpUp = aCamera->Up(); myCamStartOpUp = aCamera->Up();
myCamStartOpDir = aCamera->Direction();
myCamStartOpEye = aCamera->Eye(); myCamStartOpEye = aCamera->Eye();
myCamStartOpCenter = aCamera->Center(); myCamStartOpCenter = aCamera->Center();
} }
aCamera->SetUp (myCamStartOpUp); aCamera->SetUp (myCamStartOpUp);
aCamera->SetEye (myCamStartOpEye); aCamera->SetEyeAndCenter (myCamStartOpEye, myCamStartOpCenter);
aCamera->SetCenter (myCamStartOpCenter); aCamera->SetDirectionFromEye (myCamStartOpDir);
gp_Trsf aRotation; gp_Trsf aRotation;
gp_Pnt aRCenter = aCamera->Eye(); gp_Pnt aRCenter = aCamera->Eye();
@ -1054,8 +1058,10 @@ void V3d_View::SetProj (const V3d_TypeOfOrientation theOrientation,
const Handle(Graphic3d_Camera)& aCamera = Camera(); const Handle(Graphic3d_Camera)& aCamera = Camera();
const gp_Pnt anOriginVCS = aCamera->ConvertWorld2View (gp::Origin()); const gp_Pnt anOriginVCS = aCamera->ConvertWorld2View (gp::Origin());
aCamera->SetCenter (gp_Pnt (0, 0, 0)); const Standard_Real aNewDist = aCamera->Eye().Distance (gp_Pnt (0, 0, 0));
aCamera->SetDirection (gp_Dir (aBck.X(), aBck.Y(), aBck.Z()).Reversed()); 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->SetUp (gp_Dir (anUp.x(), anUp.y(), anUp.z()));
aCamera->OrthogonalizeUp(); aCamera->OrthogonalizeUp();
@ -2343,6 +2349,7 @@ void V3d_View::Panning (const Standard_Real theDXv,
if (theToStart) if (theToStart)
{ {
myCamStartOpDir = aCamera->Direction();
myCamStartOpEye = aCamera->Eye(); myCamStartOpEye = aCamera->Eye();
myCamStartOpCenter = aCamera->Center(); myCamStartOpCenter = aCamera->Center();
} }
@ -2351,8 +2358,8 @@ void V3d_View::Panning (const Standard_Real theDXv,
gp_Pnt aViewDims = aCamera->ViewDimensions(); gp_Pnt aViewDims = aCamera->ViewDimensions();
aCamera->SetEye (myCamStartOpEye); aCamera->SetEyeAndCenter (myCamStartOpEye, myCamStartOpCenter);
aCamera->SetCenter (myCamStartOpCenter); aCamera->SetDirectionFromEye (myCamStartOpDir);
Translate (aCamera, -theDXv, -theDYv); Translate (aCamera, -theDXv, -theDYv);
Scale (aCamera, aViewDims.X() / theZoomFactor, aViewDims.Y() / theZoomFactor); Scale (aCamera, aViewDims.X() / theZoomFactor, aViewDims.Y() / theZoomFactor);

View File

@ -995,6 +995,7 @@ protected:
Standard_Real myOldMouseX; Standard_Real myOldMouseX;
Standard_Real myOldMouseY; Standard_Real myOldMouseY;
gp_Dir myCamStartOpUp; gp_Dir myCamStartOpUp;
gp_Dir myCamStartOpDir;
gp_Pnt myCamStartOpEye; gp_Pnt myCamStartOpEye;
Standard_Real myCamStartOpBnd[6]; Standard_Real myCamStartOpBnd[6];
gp_Pnt myCamStartOpCenter; gp_Pnt myCamStartOpCenter;

20
tests/bugs/vis/bug29837 Normal file
View File

@ -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