aPntsToMeasure.Append (gp_Pnt (aGraphicBB[3], aGraphicBB[4], aGraphicBB[2]));
aPntsToMeasure.Append (gp_Pnt (aGraphicBB[3], aGraphicBB[4], aGraphicBB[5]));
- if (!theMinMax.IsVoid() && !theMinMax.IsWhole())
+ Standard_Boolean isFiniteMinMax = !theMinMax.IsVoid() && !theMinMax.IsWhole();
+
+ if (isFiniteMinMax)
{
Standard_Real aMinMax[6];
theMinMax.Get (aMinMax[0], aMinMax[1], aMinMax[2], aMinMax[3], aMinMax[4], aMinMax[5]);
gp_Pnt aCamEye = myEye;
gp_Pln aCamPln (aCamEye, aCamDir);
- Standard_Real aModelMinDist = RealLast();
- Standard_Real aModelMaxDist = RealFirst();
- Standard_Real aGraphicMinDist = RealLast();
- Standard_Real aGraphicMaxDist = RealFirst();
+ Standard_Real aModelMinDist = RealLast();
+ Standard_Real aModelMaxDist = RealFirst();
+ Standard_Real aGraphMinDist = RealLast();
+ Standard_Real aGraphMaxDist = RealFirst();
const gp_XYZ& anAxialScale = myAxialScale;
}
// The first eight points are from theGraphicBB, the last eight points are from theMinMax (can be absent).
- Standard_Real& aChangeMinDist = aCounter >= 8 ? aModelMinDist : aGraphicMinDist;
- Standard_Real& aChangeMaxDist = aCounter >= 8 ? aModelMaxDist : aGraphicMaxDist;
+ Standard_Real& aChangeMinDist = aCounter >= 8 ? aModelMinDist : aGraphMinDist;
+ Standard_Real& aChangeMaxDist = aCounter >= 8 ? aModelMaxDist : aGraphMaxDist;
aChangeMinDist = Min (aDistance, aChangeMinDist);
aChangeMaxDist = Max (aDistance, aChangeMaxDist);
aCounter++;
}
// Compute depth of bounding box center.
- Standard_Real aMidDepth = (aGraphicMinDist + aGraphicMaxDist) * 0.5;
- Standard_Real aHalfDepth = (aGraphicMaxDist - aGraphicMinDist) * 0.5;
+ Standard_Real aMidDepth = (aGraphMinDist + aGraphMaxDist) * 0.5;
+ Standard_Real aHalfDepth = (aGraphMaxDist - aGraphMinDist) * 0.5;
// Compute enlarged or shrank near and far z ranges.
Standard_Real aZNear = aMidDepth - aHalfDepth * theScaleFactor;
SetZRange (DEFAULT_ZNEAR, DEFAULT_ZFAR);
return;
}
-
- // For better perspective the zNear value should not be less than zEpsilon (zFar).
- // If zNear computed by graphical boundaries do not meet the rule (e.g. it is negative
- // when computing it for grid) it could be increased up to minimum depth computed by
- // application min max values. This means that z-fit can sacrifice presentation of
- // non primary application graphical objects in favor of better perspective projection;
- if (aZNear < zEpsilon (aZFar))
- {
- // Otherwise it should be increased up to zEpsilon (1.0) to avoid clipping of primary
- // graphical objects.
- if (aModelMinDist < zEpsilon (aZFar))
- {
- aMidDepth = (aModelMinDist + aModelMaxDist) * 0.5;
- aHalfDepth = (aModelMinDist - aModelMaxDist) * 0.5;
- aZNear = Max (zEpsilon(), aMidDepth - aHalfDepth * theScaleFactor);
- }
- else
- {
- aZNear = zEpsilon (aZFar);
- }
- }
}
//
if (!IsOrthographic())
{
- // Compensate zNear, zFar conversion errors for perspective projection.
- aZNear -= aZFar * zEpsilon (aZNear) / (aZFar - zEpsilon (aZNear));
- aZFar += zEpsilon (aZFar);
+ // For perspective projection, the value of z in normalized device coordinates is non-linear
+ // function of eye z coordinate. For fixed-point depth representation resolution of z in
+ // model-view space will grow towards zFar plane and its scale depends mostly on how far is zNear
+ // against camera's eye. The purpose of the code below is to select most appropriate zNear distance
+ // to balance between clipping (less zNear, more chances to observe closely small models without clipping)
+ // and resolution of depth. A well applicable criteria to this is a ratio between resolution of z at center
+ // of model boundaries and the distance to that center point. The ratio is chosen empirically and validated
+ // by tests database. It is considered to be ~0.001 (0.1%) for 24 bit depth buffer, for less depth bitness
+ // the zNear will be placed similarly giving lower resolution.
+ // Approximation of the formula for respectively large z range is:
+ // zNear = [z * (1 + k) / (k * c)],
+ // where:
+ // z - distance to center of model boundaries;
+ // k - chosen ratio, c - capacity of depth buffer;
+ // k = 0.001, k * c = 1677.216, (1 + k) / (k * c) ~ 5.97E-4
+ //
+ // The function uses center of model boundaries computed from "theMinMax" boundaries (instead of using real
+ // graphical boundaries of all displayed objects). That means that it can sacrifice resolution of presentation
+ // of non primary ("infinite") application graphical objects in favor of better perspective projection of the
+ // small applicative objects measured with "theMinMax" values.
+ Standard_Real aZRange = isFiniteMinMax ? aModelMaxDist - aModelMinDist : aGraphMaxDist - aGraphMinDist;
+ Standard_Real aZMin = isFiniteMinMax ? aModelMinDist : aGraphMinDist;
+ Standard_Real aZ = aZMin < 0 ? aZRange / 2.0 : aZRange / 2.0 + aZMin;
+ Standard_Real aZNearMin = aZ * 5.97E-4;
+ if (aZNear < aZNearMin)
+ {
+ // Clip zNear according to the minimum value matching the quality.
+ aZNear = aZNearMin;
+ }
+ else
+ {
+ // Compensate zNear conversion errors for perspective projection.
+ aZNear -= aZFar * zEpsilon (aZNear) / (aZFar - zEpsilon (aZNear));
+ }
+
+ // Compensate zFar conversion errors for perspective projection.
+ aZFar += zEpsilon (aZFar);
// Ensure that after all the zNear is not a negative value.
if (aZNear < zEpsilon())
--- /dev/null
+puts "========"
+puts "OCC26401"
+puts "========"
+puts ""
+###########################################################################################
+# Visualization - small boxes in front of big one disappear in perspective view
+###########################################################################################
+
+# Boxes {1 x 1 x 1}
+box b0 0 0 0 1 1 1
+box b1 -1 0 0 1 1 1
+box b2 1 0 0 1 1 1
+box b3 0 1 0 1 1 1
+box b4 -1 1 0 1 1 1
+box b5 1 1 0 1 1 1
+
+vinit View1
+vclear
+vaxo
+vsetdispmode 1
+vcamera -persp
+vdisplay b0 b1 b2 b3 b4 b5
+vsetcolor b1 b2 GREEN
+vsetcolor b4 b5 RED
+vsetcolor b3 GRAY55
+vfit
+vautozfit
+vzrange
+vtrihedron t
+
+set color "[vreadpixel 230 230 rgb]"
+if { [lindex $color 0] == 0 &&
+ [lindex $color 1] == 0 &&
+ [lindex $color 2] == 0 } {
+ puts "Error : Boxes disappear."
+}
+
+vdump $imagedir/${casename}_1.png
+
+# Boxes {0.01 x 0.01 x 0.01}
+box b0 0.00 0.00 0.00 0.01 0.01 0.01
+box b1 -0.01 0.00 0.00 0.01 0.01 0.01
+box b2 0.01 0.00 0.00 0.01 0.01 0.01
+box b3 0.00 0.01 0.00 0.01 0.01 0.01
+box b4 -0.01 0.01 0.00 0.01 0.01 0.01
+box b5 0.01 0.01 0.00 0.01 0.01 0.01
+
+vinit View2
+vclear
+vaxo
+vsetdispmode 1
+vcamera -persp
+vdisplay b0 b1 b2 b3 b4 b5
+vsetcolor b1 b2 GREEN
+vsetcolor b4 b5 RED
+vsetcolor b3 GRAY55
+vfit
+vautozfit
+vzrange
+vtrihedron t
+
+set color "[vreadpixel 230 230 rgb]"
+if { [lindex $color 0] == 0 &&
+ [lindex $color 1] == 0 &&
+ [lindex $color 2] == 0 } {
+ puts "Error : Boxes disappear."
+}
+
+vdump $imagedir/${casename}_2.png