]> OCCT Git - occt-copy.git/commitdiff
Temporarily disable patch 25760.
authorduv <duv@opencascade.com>
Thu, 16 Jul 2015 13:00:24 +0000 (16:00 +0300)
committeromy <omy@opencascade.com>
Mon, 31 Aug 2015 11:12:01 +0000 (14:12 +0300)
Conflicts:
src/Graphic3d/Graphic3d_Camera.cxx

src/Graphic3d/Graphic3d_Camera.cxx

index 7b38769e6711fb21fb7af33ae9f76292380e772d..1f740b08abc83dfb0d68c7e6fab6fec1700b3e74 100644 (file)
@@ -40,24 +40,6 @@ namespace
 
   // 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()
-  {
-    return FLT_EPSILON;
-  }
-
-  // relative z-range tolerance compatible with for floating point.
-  static Standard_Real zEpsilon (const Standard_Real theValue)
-  {
-    if (theValue == 0)
-    {
-      return FLT_EPSILON;
-    }
-    Standard_Real aLogRadix = Log10 (Abs (theValue)) / Log10 (FLT_RADIX);
-    Standard_Real aExp = Floor (aLogRadix);
-    return FLT_EPSILON * Pow (FLT_RADIX, aExp);
-  };
 };
 
 // =======================================================================
@@ -567,18 +549,8 @@ gp_Pnt Graphic3d_Camera::ConvertView2World (const gp_Pnt& thePnt) const
 gp_XYZ Graphic3d_Camera::ViewDimensions() const
 {
   // view plane dimensions
-  Standard_Real aSize = IsOrthographic() ? myScale : (2.0 * Distance() * Tan (DTR_HALF * myFOVy));
-  Standard_Real aSizeX, aSizeY;
-  if (myAspect > 1.0)
-  {
-    aSizeX = aSize * myAspect;
-    aSizeY = aSize;
-  }
-  else
-  {
-    aSizeX = aSize;
-    aSizeY = aSize / myAspect;
-  }
+  Standard_Real aSizeY = IsOrthographic() ? myScale : (2.0 * Distance() * Tan (DTR_HALF * myFOVy));
+  Standard_Real aSizeX = myAspect * aSizeY;
 
   // and frustum depth
   return gp_XYZ (aSizeX, aSizeY, myZFar - myZNear);
@@ -726,28 +698,18 @@ 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 aDXHalf = 0.0, aDYHalf = 0.0;
+  Elem_t 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;
@@ -1021,20 +983,47 @@ void Graphic3d_Camera::ZFitAll (const Standard_Real theScaleFactor, const Bnd_Bo
 {
   Standard_ASSERT_RAISE (theScaleFactor > 0.0, "Zero or negative scale factor is not allowed.");
 
-  // Method changes zNear and zFar parameters of camera so as to fit graphical structures
-  // by their graphical boundaries. It precisely fits min max boundaries of primary application
-  // objects (second argument), while it can sacrifice the real graphical boundaries of the
-  // scene with infinite or helper objects (third argument) for the sake of perspective projection.
+  // 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.
+
   if (theGraphicBB.IsVoid())
   {
-    SetZRange (DEFAULT_ZNEAR, DEFAULT_ZFAR);
+    // 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 = 1.0 / Pow (10.0, ShortRealDigits() - 1);
+
+    Standard_Real aZFar  = Distance() * 3.0;
+    Standard_Real aZNear = 0.0;
+
+    if (!IsOrthographic())
+    {
+      if (aZFar < aPrecision)
+      {
+        // Invalid case when both values are negative
+        aZNear = aPrecision;
+        aZFar  = aPrecision * 2.0;
+      }
+      else if (aZNear < Abs (aZFar) * aPrecision)
+      {
+        // Z is less than 0.0, try to fix it using any appropriate z-scale
+        aZNear = Abs (aZFar) * aPrecision;
+      }
+    }
+
+    SetZRange (aZNear, aZFar);
     return;
   }
 
-  // Measure depth of boundary points from camera eye.
+  // Measure depth of boundary points from camera eye
   NCollection_Sequence<gp_Pnt> aPntsToMeasure;
 
-  Standard_Real aGraphicBB[6];
+  Standard_Real aGraphicBB[6]; // real graphical boundaries (not accounting infinite flag).
   theGraphicBB.Get (aGraphicBB[0], aGraphicBB[1], aGraphicBB[2], aGraphicBB[3], aGraphicBB[4], aGraphicBB[5]);
 
   aPntsToMeasure.Append (gp_Pnt (aGraphicBB[0], aGraphicBB[1], aGraphicBB[2]));
@@ -1050,7 +1039,7 @@ void Graphic3d_Camera::ZFitAll (const Standard_Real theScaleFactor, const Bnd_Bo
 
   if (isFiniteMinMax)
   {
-    Standard_Real aMinMax[6];
+    Standard_Real aMinMax[6]; // applicative min max boundaries
     theMinMax.Get (aMinMax[0], aMinMax[1], aMinMax[2], aMinMax[3], aMinMax[4], aMinMax[5]);
 
     aPntsToMeasure.Append (gp_Pnt (aMinMax[0], aMinMax[1], aMinMax[2]));
@@ -1063,7 +1052,7 @@ void Graphic3d_Camera::ZFitAll (const Standard_Real theScaleFactor, const Bnd_Bo
     aPntsToMeasure.Append (gp_Pnt (aMinMax[3], aMinMax[4], aMinMax[5]));
   }
 
-  // Camera eye plane.
+  // Camera eye plane
   gp_Dir aCamDir = Direction();
   gp_Pnt aCamEye = myEye;
   gp_Pln aCamPln (aCamEye, aCamDir);
@@ -1075,7 +1064,7 @@ void Graphic3d_Camera::ZFitAll (const Standard_Real theScaleFactor, const Bnd_Bo
 
   const gp_XYZ& anAxialScale = myAxialScale;
 
-  // Get minimum and maximum distances to the eye plane.
+  // Get minimum and maximum distances to the eye plane
   Standard_Integer aCounter = 0;
   NCollection_Sequence<gp_Pnt>::Iterator aPntIt(aPntsToMeasure);
   for (; aPntIt.More(); aPntIt.Next())
@@ -1088,13 +1077,14 @@ void Graphic3d_Camera::ZFitAll (const Standard_Real theScaleFactor, const Bnd_Bo
 
     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))
     {
       aDistance *= -1;
     }
 
-    // The first eight points are from theGraphicBB, the last eight points are from theMinMax (can be absent).
+    // the first eight points are from theGraphicBB, the last eight points are from theMinMax
+    // (they can be absent).
     Standard_Real& aChangeMinDist = aCounter >= 8 ? aModelMinDist : aGraphMinDist;
     Standard_Real& aChangeMaxDist = aCounter >= 8 ? aModelMaxDist : aGraphMaxDist;
     aChangeMinDist = Min (aDistance, aChangeMinDist);
@@ -1102,98 +1092,54 @@ void Graphic3d_Camera::ZFitAll (const Standard_Real theScaleFactor, const Bnd_Bo
     aCounter++;
   }
 
-  // Compute depth of bounding box center.
+  // Compute depth of bounding box center
   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;
-  Standard_Real aZFar   = aMidDepth + aHalfDepth * theScaleFactor;
+  // 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);
 
-  if (!IsOrthographic())
-  {
-    // Everything is behind the perspective camera.
-    if (aZFar < zEpsilon())
-    {
-      SetZRange (DEFAULT_ZNEAR, DEFAULT_ZFAR);
-      return;
-    }
-  }
-
-  //
-  // Consider clipping errors due to double to single precision floating-point conversion.
-  //
-
-  // Model to view transformation performs translation of points against eye position
-  // in three dimensions. Both point coordinate and eye position values are converted from
-  // double to single precision floating point numbers producing conversion errors. 
-  // Epsilon (Mod) * 3.0 should safely compensate precision error for z coordinate after
-  // translation assuming that the:
-  // Epsilon (Eye.Mod()) * 3.0 > Epsilon (Eye.X()) + Epsilon (Eye.Y()) + Epsilon (Eye.Z()).
-  Standard_Real aEyeConf = 3.0 * zEpsilon (myEye.XYZ().Modulus());
-
-  // Model to view transformation performs rotation of points according to view direction.
-  // New z coordinate is computed as a multiplication of point's x, y, z coordinates by the
-  // "forward" direction vector's x, y, z coordinates. Both point's and "z" direction vector's
-  // values are converted from double to single precision floating point numbers producing
-  // conversion errors.
-  // Epsilon (Mod) * 6.0 should safely compensate the precision errors for the multiplication
-  // of point coordinates by direction vector.
-  gp_Pnt aGraphicMin = theGraphicBB.CornerMin();
-  gp_Pnt aGraphicMax = theGraphicBB.CornerMax();
-
-  Standard_Real aModelConf = 6.0 * zEpsilon (aGraphicMin.XYZ().Modulus()) +
-                             6.0 * zEpsilon (aGraphicMax.XYZ().Modulus());
-
-  // Compensate floating point conversion errors by increasing zNear, zFar to avoid clipping.
-  aZNear -= zEpsilon (aZNear) + aEyeConf + aModelConf;
-  aZFar  += zEpsilon (aZFar)  + aEyeConf + aModelConf;
+  // 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 (!IsOrthographic())
   {
-    // 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)
+    if (aZFar >= aPrecision)
     {
-      // Clip zNear according to the minimum value matching the quality.
-      aZNear = aZNearMin;
+      // 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
+    else // aZFar < aPrecision - Invalid case when both ZNear and ZFar are negative
     {
-      // Compensate zNear conversion errors for perspective projection.
-      aZNear -= aZFar * zEpsilon (aZNear) / (aZFar - zEpsilon (aZNear));
+      aZNear = aPrecision;
+      aZFar  = aPrecision * 2.0;
     }
+  }
 
-    // Compensate zFar conversion errors for perspective projection.
-    aZFar += zEpsilon (aZFar);
-
-    // Ensure that after all the zNear is not a negative value.
-    if (aZNear < zEpsilon())
-    {
-      aZNear = zEpsilon();
-    }
+  // If range is too small
+  if (aZFar < (aZNear + Abs (aZFar) * aPrecision))
+  {
+    aZFar = aZNear + Abs (aZFar) * aPrecision;
   }
 
   SetZRange (aZNear, aZFar);