1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-08-09 13:22:24 +03:00

0024996: Visualization - newly displayed objects are clipped until first

camera movement

AutoZFit operation now may be applied on Visual3d_View level.
Visual3d_View tracks Graphic3d_Structure updates and call AutoZFit within
Visual3d_View::Redraw if necessary.
In order to get AutoZFit functionality on Visual3d_View level ZfitAll
method moved from V3d_View into Graphic3d_Camera. AutoZFit method and
AutoZFitMode flag now part of Visual3d_View.

Test case for issue CR24996
This commit is contained in:
duv
2014-07-17 13:46:53 +04:00
committed by bugmaster
parent 9dba391d4c
commit 6bc6a6fc07
11 changed files with 480 additions and 339 deletions

View File

@@ -244,6 +244,16 @@ is
---Level: Public
---Purpose: Updates the lights of the view. The view is redrawn.
AutoZFit (me : mutable);
---Level: Public
---Purpose: If automatic z-range fitting is turned on, adjusts Z-min and Z-max
-- projection volume planes with call to ZFitAll.
ZFitAll (me : mutable; theScaleFactor : Real from Standard = 1.0);
---Level: Public
---Purpose: Change Z-min and Z-max planes of projection volume to match the
-- displayed objects.
--------------------------------------------------------
---Category: Methods to modify the Attributes of the view
--------------------------------------------------------
@@ -413,28 +423,6 @@ is
returns Boolean from Standard;
---Purpose: sets the immediate update mode and returns the previous one.
SetAutoZFitMode (me : mutable;
theIsOn : Boolean;
theScaleFactor : Real from Standard = 1.0);
---Level: public
---Purpose: Sets the automatic z-fit mode and its parameters.
-- The auto z-fit has extra parameters which can controlled from application level
-- to ensure that the size of viewing volume will be sufficiently large to cover
-- the depth of unmanaged objects, for example, transformation persistent ones.
-- @param theScaleFactor [in] the scale factor for Z-range.
-- The range between Z-min, Z-max projection volume planes
-- evaluated by z fitting method will be scaled using this coefficient.
-- Program error exception is thrown if negative or zero value
-- is passed.
AutoZFitMode (me) returns Boolean;
---Level: public
---Purpose: returns TRUE if automatic z-fit mode is turned on.
AutoZFitScaleFactor (me) returns Real from Standard;
---Level: public
---Purpose: returns scale factor parameter of automatic z-fit mode.
---------------------------------------------------
-- Triedron methods
---------------------------------------------------
@@ -919,24 +907,6 @@ is
-- @param theMargin [in] the margin coefficient for view borders.
-- @param theToUpdate [in] flag to perform view update.
ZFitAll (me : mutable; theScaleFactor : Real from Standard = 1.0);
---Level: Public
---Purpose: Change Z-min and Z-max planes of projection volume to match the
-- displayed objects. The methods ensures that view volume will
-- be close by depth range to the displayed objects. Fitting assumes that
-- for orthogonal projection the view volume contains the displayed objects
-- completely. For zoomed perspective view, the view volume is adjusted such
-- that it contains the objects or their parts, located in front of the camera.
-- @param theScaleFactor [in] the scale factor for Z-range.
-- The range between Z-min, Z-max projection volume planes
-- evaluated by z fitting method will be scaled using this coefficient.
-- Program error exception is thrown if negative or zero value is passed.
AutoZFit (me : mutable);
---Level: Public
---Purpose: If automatic z-range fitting is turned on, adjusts Z-min and Z-max
-- projection volume planes with call to ZFitAll.
DepthFitAll( me : mutable ; Aspect : Coefficient = 0.01;
Margin : Coefficient = 0.01 );
---Level: Public
@@ -1693,8 +1663,6 @@ fields
myViewAxis : Vector from Graphic3d;
myGravityReferencePoint : Vertex from Graphic3d;
myCamProjectionShift : Pnt from gp;
myAutoZFitIsOn : Boolean from Standard;
myAutoZFitScaleFactor : Real from Standard;
friends

View File

@@ -165,9 +165,7 @@ V3d_View::V3d_View(const Handle(V3d_Viewer)& VM, const V3d_TypeOfView Type ) :
MyViewContext (),
myActiveLightsIterator(),
SwitchSetFront(Standard_False),
MyTrsf (1, 4, 1, 4),
myAutoZFitIsOn (Standard_True),
myAutoZFitScaleFactor (1.0)
MyTrsf (1, 4, 1, 4)
{
myImmediateUpdate = Standard_False;
MyView = new Visual3d_View(MyViewer->Viewer());
@@ -287,8 +285,7 @@ V3d_View::V3d_View(const Handle(V3d_Viewer)& theVM,const Handle(V3d_View)& theVi
MyViewContext = aFromView->Context() ;
SetCamera (new Graphic3d_Camera (theView->Camera()));
myAutoZFitIsOn = theView->AutoZFitMode();
myAutoZFitScaleFactor = theView->AutoZFitScaleFactor();
View()->SetAutoZFitMode (theView->View()->AutoZFitMode(), theView->View()->AutoZFitScaleFactor());
MyBackground = aFromView->Background() ;
MyGradientBackground = aFromView->GradientBackground();
@@ -396,7 +393,7 @@ void V3d_View::Remove() const
//=============================================================================
void V3d_View::Update() const
{
if( MyView->IsDefined() ) MyView->Update() ;
if( MyView->IsDefined() ) MyView->Update (Aspect_TOU_ASAP) ;
}
//=============================================================================
@@ -432,6 +429,24 @@ void V3d_View::Invalidate() const
}
}
//=============================================================================
//function : AutoZFit
//purpose :
//=============================================================================
void V3d_View::AutoZFit()
{
View()->AutoZFit();
}
//=============================================================================
//function : ZFitAll
//purpose :
//=============================================================================
void V3d_View::ZFitAll (const Standard_Real theScaleFactor)
{
View()->ZFitAll (theScaleFactor);
}
//=============================================================================
//function : Redraw
//purpose :
@@ -676,7 +691,7 @@ void V3d_View::SetFront()
myCamera->SetDirection (gp_Dir (vx, vy, vz).Reversed());
myCamera->SetUp (gp_Dir (xu, yu, zu));
AutoZFit();
View()->AutoZFit();
SwitchSetFront = !SwitchSetFront;
@@ -730,7 +745,7 @@ void V3d_View::Rotate (const Standard_Real ax,
myCamera->Transform (aTrsf);
AutoZFit();
View()->AutoZFit();
ImmediateUpdate();
}
@@ -785,7 +800,7 @@ void V3d_View::Rotate(const Standard_Real ax, const Standard_Real ay, const Stan
myCamera->Transform (aTrsf);
AutoZFit();
View()->AutoZFit();
ImmediateUpdate();
}
@@ -861,7 +876,7 @@ void V3d_View::Rotate(const V3d_TypeOfAxe Axe, const Standard_Real angle,
aRotation.SetRotation (gp_Ax1 (aRCenter, aRAxis), Angle);
myCamera->Transform (aRotation);
AutoZFit();
View()->AutoZFit();
ImmediateUpdate();
}
@@ -896,7 +911,7 @@ void V3d_View::Rotate(const Standard_Real angle, const Standard_Boolean Start)
aRotation.SetRotation (gp_Ax1 (aRCenter, aRAxis), Angle);
myCamera->Transform (aRotation);
AutoZFit();
View()->AutoZFit();
ImmediateUpdate();
}
@@ -944,7 +959,7 @@ void V3d_View::Turn(const Standard_Real ax, const Standard_Real ay, const Standa
myCamera->Transform (aTrsf);
AutoZFit();
View()->AutoZFit();
ImmediateUpdate();
}
@@ -997,7 +1012,7 @@ void V3d_View::Turn(const Standard_Real angle, const Standard_Boolean Start)
aRotation.SetRotation (gp_Ax1 (aRCenter, aRAxis), Angle);
myCamera->Transform (aRotation);
AutoZFit();
View()->AutoZFit();
ImmediateUpdate();
}
@@ -1046,40 +1061,11 @@ void V3d_View::SetTwist(const Standard_Real angle)
myCamera->SetUp (gp_Dir (myYscreenAxisX, myYscreenAxisY, myYscreenAxisZ));
myCamera->Transform (aTrsf);
AutoZFit();
View()->AutoZFit();
ImmediateUpdate();
}
//=============================================================================
//function : SetAutoZFitMode
//purpose :
//=============================================================================
void V3d_View::SetAutoZFitMode (const Standard_Boolean theIsOn, const Standard_Real theScaleFactor)
{
Standard_ASSERT_RAISE (theScaleFactor > 0.0, "Zero or negative scale factor is not allowed.");
myAutoZFitScaleFactor = theScaleFactor;
myAutoZFitIsOn = theIsOn;
}
//=============================================================================
//function : AutoZFitMode
//purpose :
//=============================================================================
Standard_Boolean V3d_View::AutoZFitMode() const
{
return myAutoZFitIsOn;
}
//=============================================================================
//function : AutoZFitScaleFactor
//purpose :
//=============================================================================
Standard_Real V3d_View::AutoZFitScaleFactor () const
{
return myAutoZFitScaleFactor;
}
//=============================================================================
//function : SetEye
//purpose :
@@ -1093,7 +1079,7 @@ void V3d_View::SetEye(const Standard_Real X,const Standard_Real Y,const Standard
myCamera->SetEye (gp_Pnt (X, Y, Z));
SetTwist (aTwistBefore);
AutoZFit();
View()->AutoZFit();
SetImmediateUpdate (wasUpdateEnabled);
@@ -1123,7 +1109,7 @@ void V3d_View::SetDepth(const Standard_Real Depth)
myCamera->SetCenter (aCameraCenter);
}
AutoZFit();
View()->AutoZFit();
ImmediateUpdate();
}
@@ -1148,7 +1134,7 @@ void V3d_View::SetProj( const Standard_Real Vx,const Standard_Real Vy, const Sta
SetTwist(aTwistBefore);
}
AutoZFit();
View()->AutoZFit();
SetImmediateUpdate (wasUpdateEnabled);
@@ -1190,7 +1176,7 @@ void V3d_View::SetProj( const V3d_TypeOfOrientation Orientation )
Panning (aPanX, aPanY);
AutoZFit();
View()->AutoZFit();
ImmediateUpdate();
}
@@ -1209,7 +1195,7 @@ void V3d_View::SetAt(const Standard_Real X,const Standard_Real Y,const Standard_
SetTwist (aTwistBefore);
AutoZFit();
View()->AutoZFit();
SetImmediateUpdate (wasUpdateEnabled);
@@ -1253,7 +1239,7 @@ void V3d_View::SetUp(const Standard_Real Vx,const Standard_Real Vy,const Standar
myCamera->SetUp (gp_Dir (myYscreenAxisX, myYscreenAxisY, myYscreenAxisZ));
AutoZFit();
View()->AutoZFit();
ImmediateUpdate();
}
@@ -1296,7 +1282,7 @@ void V3d_View::SetUp( const V3d_TypeOfOrientation Orientation )
myCamera->SetUp (gp_Dir (myYscreenAxisX, myYscreenAxisY, myYscreenAxisZ));
AutoZFit();
View()->AutoZFit();
ImmediateUpdate();
}
@@ -1336,7 +1322,7 @@ void V3d_View::Reset( const Standard_Boolean update )
myCamera->CopyMappingData (aDefaultCamera);
myCamera->CopyOrientationData (aDefaultCamera);
AutoZFit();
View()->AutoZFit();
}
SwitchSetFront = Standard_False;
@@ -1368,7 +1354,7 @@ void V3d_View::SetSize (const Standard_Real theSize)
myCamera->SetScale (myCamera->Aspect() >= 1.0 ? theSize / myCamera->Aspect() : theSize);
AutoZFit();
View()->AutoZFit();
ImmediateUpdate();
}
@@ -1471,7 +1457,7 @@ void V3d_View::SetZoom(const Standard_Real Coef,const Standard_Boolean Start)
myCamera->SetEye (myCamStartOpEye);
myCamera->SetCenter (myCamStartOpCenter);
myCamera->SetScale (myCamera->Scale() / Coef);
AutoZFit();
View()->AutoZFit();
ImmediateUpdate();
}
@@ -1498,7 +1484,7 @@ void V3d_View::SetScale( const Standard_Real Coef )
myCamera->SetScale (myCamera->Scale() / Coef);
}
AutoZFit();
View()->AutoZFit();
ImmediateUpdate();
}
@@ -1512,7 +1498,7 @@ void V3d_View::SetAxialScale( const Standard_Real Sx, const Standard_Real Sy, co
V3d_BadValue_Raise_if( Sx <= 0. || Sy <= 0. || Sz <= 0.,"V3d_View::SetAxialScale, bad coefficient");
myCamera->SetAxialScale (gp_XYZ (Sx, Sy, Sz));
AutoZFit();
View()->AutoZFit();
}
//=============================================================================
@@ -1538,7 +1524,7 @@ void V3d_View::FitAll (const Standard_Real theMargin, const Standard_Boolean the
return;
}
AutoZFit();
View()->AutoZFit();
if (myImmediateUpdate || theToUpdate)
{
@@ -1546,173 +1532,6 @@ void V3d_View::FitAll (const Standard_Real theMargin, const Standard_Boolean the
}
}
//=============================================================================
//function : AutoZFit
//purpose :
//=============================================================================
void V3d_View::AutoZFit()
{
if (!AutoZFitMode())
{
return;
}
ZFitAll (myAutoZFitScaleFactor);
}
//=============================================================================
//function : ZFitAll
//purpose :
//=============================================================================
void V3d_View::ZFitAll (const Standard_Real theScaleFactor)
{
Standard_ASSERT_RAISE (theScaleFactor > 0.0, "Zero or negative scale factor is not allowed.");
// Method changes ZNear and ZFar planes of camera so as to fit the graphical structures
// by their real boundaries (computed ignoring infinite flag) into the viewing volume.
// In addition to the graphical boundaries, the usual min max used for fitting perspective
// camera. To avoid numeric errors for perspective camera the negative ZNear values are
// fixed using tolerance distance, relative to boundaries size. The tolerance distance
// should be computed using information on boundaries of primary application actors,
// (e.g. representing the displayed model) - to ensure that they are not unreasonably clipped.
Standard_Real aMinMax[6]; // applicative min max boundaries
View()->MinMaxValues (aMinMax[0], aMinMax[1], aMinMax[2],
aMinMax[3], aMinMax[4], aMinMax[5],
Standard_False);
Standard_Real aGraphicBB[6]; // real graphical boundaries (not accounting infinite flag).
View()->MinMaxValues (aGraphicBB[0], aGraphicBB[1], aGraphicBB[2],
aGraphicBB[3], aGraphicBB[4], aGraphicBB[5],
Standard_True);
// Check if anything can be adjusted
Standard_Real aLim = (ShortRealLast() - 1.0);
if (Abs (aGraphicBB[0]) > aLim || Abs (aGraphicBB[1]) > aLim || Abs (aGraphicBB[2]) > aLim ||
Abs (aGraphicBB[3]) > aLim || Abs (aGraphicBB[4]) > aLim || Abs (aGraphicBB[5]) > aLim)
{
SetZSize (0.0);
ImmediateUpdate();
return;
}
// Measure depth of boundary points from camera eye
gp_Pnt aPntsToMeasure[16] =
{
gp_Pnt (aMinMax[0], aMinMax[1], aMinMax[2]),
gp_Pnt (aMinMax[0], aMinMax[1], aMinMax[5]),
gp_Pnt (aMinMax[0], aMinMax[4], aMinMax[2]),
gp_Pnt (aMinMax[0], aMinMax[4], aMinMax[5]),
gp_Pnt (aMinMax[3], aMinMax[1], aMinMax[2]),
gp_Pnt (aMinMax[3], aMinMax[1], aMinMax[5]),
gp_Pnt (aMinMax[3], aMinMax[4], aMinMax[2]),
gp_Pnt (aMinMax[3], aMinMax[4], aMinMax[5]),
gp_Pnt (aGraphicBB[0], aGraphicBB[1], aGraphicBB[2]),
gp_Pnt (aGraphicBB[0], aGraphicBB[1], aGraphicBB[5]),
gp_Pnt (aGraphicBB[0], aGraphicBB[4], aGraphicBB[2]),
gp_Pnt (aGraphicBB[0], aGraphicBB[4], aGraphicBB[5]),
gp_Pnt (aGraphicBB[3], aGraphicBB[1], aGraphicBB[2]),
gp_Pnt (aGraphicBB[3], aGraphicBB[1], aGraphicBB[5]),
gp_Pnt (aGraphicBB[3], aGraphicBB[4], aGraphicBB[2]),
gp_Pnt (aGraphicBB[3], aGraphicBB[4], aGraphicBB[5])
};
// Camera eye plane
gp_Dir aCamDir = myCamera->Direction();
gp_Pnt aCamEye = myCamera->Eye();
gp_Pln aCamPln (aCamEye, aCamDir);
Standard_Real aModelMinDist = RealLast();
Standard_Real aModelMaxDist = RealFirst();
Standard_Real aGraphicMinDist = RealLast();
Standard_Real aGraphicMaxDist = RealFirst();
const gp_XYZ& anAxialScale = myCamera->AxialScale();
// Get minimum and maximum distances to the eye plane
for (Standard_Integer aPntIt = 0; aPntIt < 16; ++aPntIt)
{
gp_Pnt aMeasurePnt = aPntsToMeasure[aPntIt];
if (Abs (aMeasurePnt.X()) > aLim || Abs (aMeasurePnt.Y()) > aLim || Abs (aMeasurePnt.Z()) > aLim)
{
continue;
}
aMeasurePnt = gp_Pnt (aMeasurePnt.X() * anAxialScale.X(),
aMeasurePnt.Y() * anAxialScale.Y(),
aMeasurePnt.Z() * anAxialScale.Z());
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))
{
aDistance *= -1;
}
Standard_Real& aChangeMinDist = aPntIt >= 8 ? aGraphicMinDist : aModelMinDist;
Standard_Real& aChangeMaxDist = aPntIt >= 8 ? aGraphicMaxDist : aModelMaxDist;
aChangeMinDist = Min (aDistance, aChangeMinDist);
aChangeMaxDist = Max (aDistance, aChangeMaxDist);
}
// Compute depth of bounding box center
Standard_Real aMidDepth = (aGraphicMinDist + aGraphicMaxDist) * 0.5;
Standard_Real aHalfDepth = (aGraphicMaxDist - aGraphicMinDist) * 0.5;
// ShortReal precision factor used to add meaningful tolerance to
// ZNear, ZFar values in order to avoid equality after type conversion
// to ShortReal matrices type.
const Standard_Real aPrecision = Pow (0.1, ShortRealDigits() - 2);
// Compute enlarged or shrank near and far z ranges
Standard_Real aZNear = aMidDepth - aHalfDepth * theScaleFactor;
Standard_Real aZFar = aMidDepth + aHalfDepth * theScaleFactor;
aZNear -= aPrecision * 0.5;
aZFar += aPrecision * 0.5;
if (!myCamera->IsOrthographic())
{
if (aZFar >= aPrecision)
{
// To avoid numeric errors... (See comments in the beginning of the method).
// Choose between model distance and graphical distance, as the model boundaries
// might be infinite if all structures have infinite flag.
const Standard_Real aGraphicDepth = aGraphicMaxDist >= aGraphicMinDist
? aGraphicMaxDist - aGraphicMinDist : RealLast();
const Standard_Real aModelDepth = aModelMaxDist >= aModelMinDist
? aModelMaxDist - aModelMinDist : RealLast();
const Standard_Real aMinDepth = Min (aModelDepth, aGraphicDepth);
const Standard_Real aZTolerance =
Max (Abs (aMinDepth) * aPrecision, aPrecision);
if (aZNear < aZTolerance)
{
aZNear = aZTolerance;
}
}
else // aZFar < aPrecision - Invalid case when both ZNear and ZFar are negative
{
aZNear = aPrecision;
aZFar = aPrecision * 2.0;
}
}
// If range is too small
if (aZFar < (aZNear + Abs (aZFar) * aPrecision))
{
aZFar = aZNear + Abs (aZFar) * aPrecision;
}
myCamera->SetZRange (aZNear, aZFar);
ImmediateUpdate();
}
//=============================================================================
//function : DepthFitAll
//purpose :
@@ -1858,7 +1677,7 @@ void V3d_View::WindowFit (const Standard_Integer theMinXp,
Translate (myCamera, aPanVec.X(), -aPanVec.Y());
Scale (myCamera, aUSize, aVSize);
AutoZFit();
View()->AutoZFit();
}
else
{
@@ -2811,7 +2630,7 @@ void V3d_View::ZoomAtPoint (const Standard_Integer theMouseStartX,
myCamera->SetScale (myCamera->Scale() / aCoef);
Translate (myCamera, aZoomAtPointXv - aDxv, aZoomAtPointYv - aDyv);
AutoZFit();
View()->AutoZFit();
SetImmediateUpdate (wasUpdateEnabled);
@@ -2867,7 +2686,7 @@ void V3d_View::FitAll(const Handle(Aspect_Window)& aWindow,
myCamera->SetAspect (aWinAspect);
Translate (myCamera, (Xmin + Xmax) * 0.5, (Ymin + Ymax) * 0.5);
Scale (myCamera, aFitSizeU, aFitSizeV);
AutoZFit();
View()->AutoZFit();
ImmediateUpdate();
}
@@ -3104,7 +2923,7 @@ Standard_Boolean V3d_View::ToPixMap (Image_PixMap& theImage,
const Standard_Boolean toAutoUpdate = myImmediateUpdate;
myImmediateUpdate = Standard_False;
AutoZFit();
View()->AutoZFit();
myImmediateUpdate = toAutoUpdate;
if (theToKeepAspect)

View File

@@ -68,7 +68,7 @@ void V3d_View::Move(const Standard_Real Dx, const Standard_Real Dy, const Standa
+ Dz * gp_Pnt (ZX, ZY, ZZ).XYZ()
);
AutoZFit();
View()->AutoZFit();
ImmediateUpdate();
}
@@ -86,7 +86,7 @@ void V3d_View::Move(const Standard_Real Length, const Standard_Boolean Start) {
myCamera->SetEye (myCamera->Eye().XYZ() + Length * gp_Pnt (Vx, Vy, Vz).XYZ());
AutoZFit();
View()->AutoZFit();
ImmediateUpdate();
}
@@ -142,7 +142,7 @@ void V3d_View::Translate(const Standard_Real Dx, const Standard_Real Dy, const S
- Dz * gp_Pnt (ZX, ZY, ZZ).XYZ()
);
AutoZFit();
View()->AutoZFit();
ImmediateUpdate();
}
@@ -190,7 +190,7 @@ void V3d_View::Translate(const Standard_Real theLength, const Standard_Boolean t
gp_Pnt aNewCenter (myCamStartOpCenter.XYZ() - gp_Pnt (aVx, aVy, aVz).XYZ() * theLength);
myCamera->SetCenter (aNewCenter);
AutoZFit();
View()->AutoZFit();
ImmediateUpdate();
}