From 10684e906ddc0aff52d12749dfef2dbd3fbcd7a4 Mon Sep 17 00:00:00 2001 From: duv Date: Thu, 16 Jul 2015 16:00:24 +0300 Subject: [PATCH] Temporarily disable patch 25760. Conflicts: src/Graphic3d/Graphic3d_Camera.cxx --- src/Graphic3d/Graphic3d_Camera.cxx | 214 +++++++++++------------------ 1 file changed, 80 insertions(+), 134 deletions(-) diff --git a/src/Graphic3d/Graphic3d_Camera.cxx b/src/Graphic3d/Graphic3d_Camera.cxx index 7b38769e67..1f740b08ab 100644 --- a/src/Graphic3d/Graphic3d_Camera.cxx +++ b/src/Graphic3d/Graphic3d_Camera.cxx @@ -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 aZNear = static_cast (myZNear); Elem_t aZFar = static_cast (myZFar); Elem_t anAspect = static_cast (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 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::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); -- 2.39.5