mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-04-04 18:06:22 +03:00
0026082: When view is resized horizontally the visualization is not scaled
This commit is contained in:
parent
7e59624d86
commit
ab1c121bb9
@ -694,18 +694,28 @@ Graphic3d_Camera::TransformMatrices<Elem_t>&
|
||||
Elem_t aZNear = static_cast<Elem_t> (myZNear);
|
||||
Elem_t aZFar = static_cast<Elem_t> (myZFar);
|
||||
Elem_t anAspect = static_cast<Elem_t> (myAspect);
|
||||
Elem_t aDYHalf = 0.0;
|
||||
Elem_t aDXHalf = 0.0, aDYHalf = 0.0;
|
||||
if (IsOrthographic())
|
||||
{
|
||||
aDXHalf = aScale * Elem_t (0.5);
|
||||
aDYHalf = aScale * Elem_t (0.5);
|
||||
}
|
||||
else
|
||||
{
|
||||
aDXHalf = aZNear * Elem_t (Tan (DTR_HALF * myFOVy));
|
||||
aDYHalf = aZNear * Elem_t (Tan (DTR_HALF * myFOVy));
|
||||
}
|
||||
|
||||
if (anAspect > 1.0)
|
||||
{
|
||||
aDXHalf *= anAspect;
|
||||
}
|
||||
else
|
||||
{
|
||||
aDYHalf /= anAspect;
|
||||
}
|
||||
|
||||
// sets right of frustum based on aspect ratio
|
||||
Elem_t aDXHalf = anAspect * aDYHalf;
|
||||
Elem_t aLeft = -aDXHalf;
|
||||
Elem_t aRight = aDXHalf;
|
||||
Elem_t aBot = -aDYHalf;
|
||||
|
@ -77,6 +77,8 @@ To solve the problem (for lack of a better solution) I make 2 passes.
|
||||
#include <Standard_ErrorHandler.hxx>
|
||||
#include <Standard_DivideByZero.hxx>
|
||||
|
||||
#include <NCollection_Array1.hxx>
|
||||
|
||||
#include <Visual3d_ViewManager.hxx>
|
||||
#include <Visual3d_Light.hxx>
|
||||
#include <Visual3d_Layer.hxx>
|
||||
@ -1579,7 +1581,7 @@ void V3d_View::WindowFit (const Standard_Integer theMinXp,
|
||||
|
||||
if (!myCamera->IsOrthographic())
|
||||
{
|
||||
// normalize view coordiantes
|
||||
// normalize view coordinates
|
||||
Standard_Integer aWinWidth, aWinHeight;
|
||||
MyWindow->Size (aWinWidth, aWinHeight);
|
||||
|
||||
@ -2993,36 +2995,41 @@ Standard_Boolean V3d_View::FitMinMax (const Handle(Graphic3d_Camera)& theCamera,
|
||||
// option is to perform frustum plane adjustment algorithm in view camera space,
|
||||
// which will lead to a number of additional world-view space conversions and
|
||||
// loosing precision as well.
|
||||
gp_Pnt aMinCorner = theBox.CornerMin();
|
||||
gp_Pnt aMaxCorner = theBox.CornerMax();
|
||||
Standard_Real aXmin = aMinCorner.X() * theCamera->AxialScale().X();
|
||||
Standard_Real aXmax = aMaxCorner.X() * theCamera->AxialScale().X();
|
||||
Standard_Real aYmin = aMinCorner.Y() * theCamera->AxialScale().Y();
|
||||
Standard_Real aYmax = aMaxCorner.Y() * theCamera->AxialScale().Y();
|
||||
Standard_Real aZmin = aMinCorner.Z() * theCamera->AxialScale().Z();
|
||||
Standard_Real aZmax = aMaxCorner.Z() * theCamera->AxialScale().Z();
|
||||
gp_Pnt aBndMin = theBox.CornerMin().XYZ().Multiplied (theCamera->AxialScale());
|
||||
gp_Pnt aBndMax = theBox.CornerMax().XYZ().Multiplied (theCamera->AxialScale());
|
||||
|
||||
Bnd_Box aBBox;
|
||||
aBBox.Update (aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
|
||||
if (aBBox.IsThin (RealEpsilon()))
|
||||
if (aBndMax.IsEqual (aBndMin, RealEpsilon()))
|
||||
{
|
||||
return Standard_False; // nothing to fit all
|
||||
}
|
||||
|
||||
gp_Pnt aBBCenter ((aXmin + aXmax) * 0.5, (aYmin + aYmax) * 0.5, (aZmin + aZmax) * 0.5);
|
||||
|
||||
gp_Pln aFrustumLeft;
|
||||
gp_Pln aFrustumRight;
|
||||
gp_Pln aFrustumBottom;
|
||||
gp_Pln aFrustumTop;
|
||||
gp_Pln aFrustumNear;
|
||||
gp_Pln aFrustumFar;
|
||||
theCamera->Frustum (aFrustumLeft, aFrustumRight, aFrustumBottom, aFrustumTop, aFrustumNear, aFrustumFar);
|
||||
// Prepare camera frustum planes.
|
||||
NCollection_Array1<gp_Pln> aFrustumPlane (1, 6);
|
||||
theCamera->Frustum (aFrustumPlane.ChangeValue (1),
|
||||
aFrustumPlane.ChangeValue (2),
|
||||
aFrustumPlane.ChangeValue (3),
|
||||
aFrustumPlane.ChangeValue (4),
|
||||
aFrustumPlane.ChangeValue (5),
|
||||
aFrustumPlane.ChangeValue (6));
|
||||
|
||||
// Prepare camera up, side, direction vectors.
|
||||
gp_Dir aCamUp = theCamera->OrthogonalizedUp();
|
||||
gp_Dir aCamDir = theCamera->Direction();
|
||||
gp_Dir aCamSide = aCamDir ^ aCamUp;
|
||||
|
||||
// Prepare scene bounding box parameters.
|
||||
gp_Pnt aBndCenter = (aBndMin.XYZ() + aBndMax.XYZ()) / 2.0;
|
||||
|
||||
NCollection_Array1<gp_Pnt> aBndCorner (1, 8);
|
||||
aBndCorner.ChangeValue (1) = gp_Pnt (aBndMin.X(), aBndMin.Y(), aBndMin.Z());
|
||||
aBndCorner.ChangeValue (2) = gp_Pnt (aBndMin.X(), aBndMin.Y(), aBndMax.Z());
|
||||
aBndCorner.ChangeValue (3) = gp_Pnt (aBndMin.X(), aBndMax.Y(), aBndMin.Z());
|
||||
aBndCorner.ChangeValue (4) = gp_Pnt (aBndMin.X(), aBndMax.Y(), aBndMax.Z());
|
||||
aBndCorner.ChangeValue (5) = gp_Pnt (aBndMax.X(), aBndMin.Y(), aBndMin.Z());
|
||||
aBndCorner.ChangeValue (6) = gp_Pnt (aBndMax.X(), aBndMin.Y(), aBndMax.Z());
|
||||
aBndCorner.ChangeValue (7) = gp_Pnt (aBndMax.X(), aBndMax.Y(), aBndMin.Z());
|
||||
aBndCorner.ChangeValue (8) = gp_Pnt (aBndMax.X(), aBndMax.Y(), aBndMax.Z());
|
||||
|
||||
// Perspective-correct camera projection vector, matching the bounding box is determined geometrically.
|
||||
// Knowing the initial shape of a frustum it is possible to match it to a bounding box.
|
||||
// Then, knowing the relation of camera projection vector to the frustum shape it is possible to
|
||||
@ -3039,30 +3046,33 @@ Standard_Boolean V3d_View::FitMinMax (const Handle(Graphic3d_Camera)& theCamera,
|
||||
// 3) Determine new camera projection vector using the normalized asymmetry.
|
||||
// 4) Determine new zooming in view space.
|
||||
|
||||
// Determine normalized projection asymmetry (if any).
|
||||
// 1. Determine normalized projection asymmetry (if any).
|
||||
Standard_Real anAssymX = Tan ( aCamSide.Angle (aFrustumPlane (1).Axis().Direction()))
|
||||
- Tan (-aCamSide.Angle (aFrustumPlane (2).Axis().Direction()));
|
||||
Standard_Real anAssymY = Tan ( aCamUp.Angle (aFrustumPlane (3).Axis().Direction()))
|
||||
- Tan (-aCamUp.Angle (aFrustumPlane (4).Axis().Direction()));
|
||||
|
||||
Standard_Real anAssymX = Tan ( aCamSide.Angle (aFrustumLeft.Axis().Direction()))
|
||||
- Tan (-aCamSide.Angle (aFrustumRight.Axis().Direction()));
|
||||
Standard_Real anAssymY = Tan ( aCamUp.Angle (aFrustumBottom.Axis().Direction()))
|
||||
- Tan (-aCamUp.Angle (aFrustumTop.Axis().Direction()));
|
||||
// 2. Determine how far should be the frustum planes placed from center
|
||||
// of bounding box, in order to match the bounding box closely.
|
||||
NCollection_Array1<Standard_Real> aFitDistance (1, 6);
|
||||
aFitDistance.ChangeValue (1) = 0.0;
|
||||
aFitDistance.ChangeValue (2) = 0.0;
|
||||
aFitDistance.ChangeValue (3) = 0.0;
|
||||
aFitDistance.ChangeValue (4) = 0.0;
|
||||
aFitDistance.ChangeValue (5) = 0.0;
|
||||
aFitDistance.ChangeValue (6) = 0.0;
|
||||
|
||||
// Determine how far should be the frustum planes placed from center
|
||||
// of bounding box, in order to match the bounding box closely.
|
||||
gp_Pln aMatchSide[6] = {aFrustumLeft, aFrustumRight, aFrustumBottom, aFrustumTop, aFrustumNear, aFrustumFar};
|
||||
Standard_Real aMatchDistance[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
|
||||
for (Standard_Integer anIt = 0; anIt < 6; ++anIt)
|
||||
for (Standard_Integer anI = aFrustumPlane.Lower(); anI <= aFrustumPlane.Upper(); ++anI)
|
||||
{
|
||||
const gp_Dir& aPlaneN = aMatchSide[anIt].Axis().Direction();
|
||||
// Measure distances from center of bounding box to its corners towards the frustum plane.
|
||||
const gp_Dir& aPlaneN = aFrustumPlane.ChangeValue (anI).Axis().Direction();
|
||||
|
||||
gp_Trsf aPlaneTrsf;
|
||||
aPlaneTrsf.SetTransformation (gp_Ax3(), gp_Ax3 (aBBCenter, aPlaneN));
|
||||
Bnd_Box aRelativeBBox = aBBox.Transformed (aPlaneTrsf);
|
||||
Standard_Real& aFitDist = aFitDistance.ChangeValue (anI);
|
||||
|
||||
Standard_Real aDummy = 0.0;
|
||||
Standard_Real aZmin = 0.0;
|
||||
Standard_Real aZmax = 0.0;
|
||||
aRelativeBBox.Get (aDummy, aDummy, aZmin, aDummy, aDummy, aZmax);
|
||||
aMatchDistance[anIt] = -aZmin;
|
||||
for (Standard_Integer aJ = aBndCorner.Lower(); aJ <= aBndCorner.Upper(); ++aJ)
|
||||
{
|
||||
aFitDist = Max (aFitDist, gp_Vec (aBndCenter, aBndCorner (aJ)).Dot (aPlaneN));
|
||||
}
|
||||
}
|
||||
// The center of camera is placed on the same line with center of bounding box.
|
||||
// The view plane section crosses the bounding box at its center.
|
||||
@ -3080,32 +3090,31 @@ Standard_Boolean V3d_View::FitMinMax (const Handle(Graphic3d_Camera)& theCamera,
|
||||
// \//
|
||||
// //
|
||||
// (frustum plane)
|
||||
aFitDistance.ChangeValue (1) *= Sqrt(1 + Pow (Tan ( aCamSide.Angle (aFrustumPlane (1).Axis().Direction())), 2.0));
|
||||
aFitDistance.ChangeValue (2) *= Sqrt(1 + Pow (Tan (-aCamSide.Angle (aFrustumPlane (2).Axis().Direction())), 2.0));
|
||||
aFitDistance.ChangeValue (3) *= Sqrt(1 + Pow (Tan ( aCamUp.Angle (aFrustumPlane (3).Axis().Direction())), 2.0));
|
||||
aFitDistance.ChangeValue (4) *= Sqrt(1 + Pow (Tan (-aCamUp.Angle (aFrustumPlane (4).Axis().Direction())), 2.0));
|
||||
aFitDistance.ChangeValue (5) *= Sqrt(1 + Pow (Tan ( aCamDir.Angle (aFrustumPlane (5).Axis().Direction())), 2.0));
|
||||
aFitDistance.ChangeValue (6) *= Sqrt(1 + Pow (Tan (-aCamDir.Angle (aFrustumPlane (6).Axis().Direction())), 2.0));
|
||||
|
||||
aMatchDistance[0] *= Sqrt(1 + Pow (Tan ( aCamSide.Angle (aFrustumLeft.Axis().Direction())), 2.0));
|
||||
aMatchDistance[1] *= Sqrt(1 + Pow (Tan (-aCamSide.Angle (aFrustumRight.Axis().Direction())), 2.0));
|
||||
aMatchDistance[2] *= Sqrt(1 + Pow (Tan ( aCamUp.Angle (aFrustumBottom.Axis().Direction())), 2.0));
|
||||
aMatchDistance[3] *= Sqrt(1 + Pow (Tan (-aCamUp.Angle (aFrustumTop.Axis().Direction())), 2.0));
|
||||
aMatchDistance[4] *= Sqrt(1 + Pow (Tan ( aCamDir.Angle (aFrustumNear.Axis().Direction())), 2.0));
|
||||
aMatchDistance[5] *= Sqrt(1 + Pow (Tan (-aCamDir.Angle (aFrustumFar.Axis().Direction())), 2.0));
|
||||
Standard_Real aViewSizeXv = aFitDistance (1) + aFitDistance (2);
|
||||
Standard_Real aViewSizeYv = aFitDistance (3) + aFitDistance (4);
|
||||
Standard_Real aViewSizeZv = aFitDistance (5) + aFitDistance (6);
|
||||
|
||||
Standard_Real aViewSizeXv = aMatchDistance[0] + aMatchDistance[1];
|
||||
Standard_Real aViewSizeYv = aMatchDistance[2] + aMatchDistance[3];
|
||||
Standard_Real aViewSizeZv = aMatchDistance[4] + aMatchDistance[5];
|
||||
|
||||
// Place center of camera on the same line with center of bounding
|
||||
// box applying corresponding projection asymmetry (if any).
|
||||
// 3. Place center of camera on the same line with center of bounding
|
||||
// box applying corresponding projection asymmetry (if any).
|
||||
Standard_Real anAssymXv = anAssymX * aViewSizeXv * 0.5;
|
||||
Standard_Real anAssymYv = anAssymY * aViewSizeYv * 0.5;
|
||||
Standard_Real anOffsetXv = (aMatchDistance[1] - aMatchDistance[0]) * 0.5 + anAssymXv;
|
||||
Standard_Real anOffsetYv = (aMatchDistance[3] - aMatchDistance[2]) * 0.5 + anAssymYv;
|
||||
Standard_Real anOffsetXv = (aFitDistance (2) - aFitDistance (1)) * 0.5 + anAssymXv;
|
||||
Standard_Real anOffsetYv = (aFitDistance (4) - aFitDistance (3)) * 0.5 + anAssymYv;
|
||||
gp_Vec aTranslateSide = gp_Vec (aCamSide) * anOffsetXv;
|
||||
gp_Vec aTranslateUp = gp_Vec (aCamUp) * anOffsetYv;
|
||||
gp_Pnt aNewCenter = aBBCenter.Translated (aTranslateSide).Translated (aTranslateUp);
|
||||
gp_Pnt aCamNewCenter = aBndCenter.Translated (aTranslateSide).Translated (aTranslateUp);
|
||||
|
||||
gp_Trsf aCenterTrsf;
|
||||
aCenterTrsf.SetTranslation (theCamera->Center(), aNewCenter);
|
||||
aCenterTrsf.SetTranslation (theCamera->Center(), aCamNewCenter);
|
||||
theCamera->Transform (aCenterTrsf);
|
||||
theCamera->SetDistance (aMatchDistance[5] + aMatchDistance[4]);
|
||||
theCamera->SetDistance (aFitDistance (6) + aFitDistance (5));
|
||||
|
||||
// Bounding box collapses to a point or thin line going in depth of the screen
|
||||
if (aViewSizeXv < theResolution && aViewSizeYv < theResolution)
|
||||
@ -3135,8 +3144,14 @@ void V3d_View::Scale (const Handle(Graphic3d_Camera)& theCamera,
|
||||
const Standard_Real theSizeYv) const
|
||||
{
|
||||
Standard_Real anAspect = theCamera->Aspect();
|
||||
Standard_Real aMaxSize = Max (theSizeXv / anAspect, theSizeYv);
|
||||
theCamera->SetScale (aMaxSize);
|
||||
if (anAspect > 1.0)
|
||||
{
|
||||
theCamera->SetScale (Max (theSizeXv / anAspect, theSizeYv));
|
||||
}
|
||||
else
|
||||
{
|
||||
theCamera->SetScale (Max (theSizeXv, theSizeYv * anAspect));
|
||||
}
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
|
48
tests/bugs/vis/bug26082
Normal file
48
tests/bugs/vis/bug26082
Normal file
@ -0,0 +1,48 @@
|
||||
puts "============"
|
||||
puts "CR26082"
|
||||
puts "============"
|
||||
puts ""
|
||||
|
||||
#########################################################################
|
||||
puts "When view is resized horizontally the viusaliziation is not scaled"
|
||||
#########################################################################
|
||||
|
||||
set cursor_1 { 288 53 }
|
||||
set cursor_2 { 53 127 }
|
||||
set cursor_3 { 122 154 }
|
||||
|
||||
set viewparams { -scale 606.309 \
|
||||
-proj 0.577 -0.577 0.577 \
|
||||
-up -0.408 0.408 0.816 \
|
||||
-at 0.5 0.5 0.5
|
||||
-eye 1.5 -0.5 1.5 }
|
||||
|
||||
pload VISUALIZATION MODELING
|
||||
|
||||
box b 1 1 1
|
||||
|
||||
vinit View1 w=400 h=400
|
||||
vinit View2 w=200 h=400
|
||||
vinit View3 w=400 h=200
|
||||
vclear
|
||||
vaxo
|
||||
|
||||
vdisplay b
|
||||
|
||||
vactivate View1
|
||||
vviewparams {*}$viewparams
|
||||
vmoveto {*}$cursor_1
|
||||
checkcolor {*}$cursor_1 0 1 1
|
||||
vdump ${imagedir}/${casename}_1.png
|
||||
|
||||
vactivate View2
|
||||
vviewparams {*}$viewparams
|
||||
vmoveto {*}$cursor_2
|
||||
checkcolor {*}$cursor_2 0 1 1
|
||||
vdump ${imagedir}/${casename}_2.png
|
||||
|
||||
vactivate View3
|
||||
vviewparams {*}$viewparams
|
||||
vmoveto {*}$cursor_3
|
||||
checkcolor {*}$cursor_3 0 1 1
|
||||
vdump ${imagedir}/${casename}_3.png
|
Loading…
x
Reference in New Issue
Block a user