mirror of
https://github.com/OPM/ResInsight.git
synced 2026-10-24 14:17:52 -05:00
Fix crash in Camera::computeFitViewEyePosition with zero view direction
Zoom All could pass a zero view direction (eye equal to view reference point). The up vector then also became zero, giving a plane with a zero normal and an assert in Plane::distanceToOrigin. Fall back to the Y axis when the direction is zero or undefined. Follow-up to the parallel dir/up fix in #14849. Call stack: [5] cvf::AssertHandlerConsole::handleAssert(char const*, int, char const*, char const*) at cvfAssert.cpp:125 [6] cvf::Plane::distanceToOrigin() const at cvfPlane.cpp:313 [7] cvf::Camera::computeFitViewEyePosition(cvf::BoundingBox const&, cvf::Vector3<double> const&, cvf::Vector3<double> const&, double, double, double) at cvfCamera.cpp:361 [8] caf::Viewer::zoomAll() at cafViewer.cpp:992 [9] caf::CmdFeature::actionTriggered(bool) at cafCmdFeature.cpp:176
This commit is contained in:
1 parent
72df8a69f5
commit
d8dc1c051f
2 files changed
+60
-2
No files matched your search
@@ -85,3 +85,44 @@ TEST( CvfCameraCrashTriageTest, FitViewWithParallelDirAndUpProducesValidViewMatr
|
||||
EXPECT_NEAR( c.direction() * c.right(), 0.0, 1e-6 );
|
||||
EXPECT_NEAR( c.up() * c.right(), 0.0, 1e-6 );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// A zero view direction (eye == view reference point, as in caf::Viewer::zoomAll()) gave a zero up
|
||||
/// vector and a zero-normal plane, which asserted in Plane::distanceToOrigin().
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
TEST( CvfCameraCrashTriageTest, FitViewEyePositionWithZeroDirDoesNotCrash )
|
||||
{
|
||||
Camera c;
|
||||
|
||||
BoundingBox bb;
|
||||
bb.add( Vec3d( 0, 0, 0 ) );
|
||||
bb.add( Vec3d( 1, 1, 1 ) );
|
||||
|
||||
for ( const auto& dir : { Vec3d::ZERO, Vec3d::UNDEFINED } )
|
||||
{
|
||||
Vec3d eye = Camera::computeFitViewEyePosition( bb, dir, Vec3d( 0, 0, 1 ), 0.9, c.fieldOfViewYDeg(), 1.0 );
|
||||
|
||||
EXPECT_FALSE( eye.isUndefined() );
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// fitView() must derive the up vector from the same valid direction as the eye position
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
TEST( CvfCameraCrashTriageTest, FitViewWithZeroOrUndefinedDirProducesValidViewMatrix )
|
||||
{
|
||||
BoundingBox bb;
|
||||
bb.add( Vec3d( 0, 0, 0 ) );
|
||||
bb.add( Vec3d( 1, 1, 1 ) );
|
||||
|
||||
for ( const auto& dir : { Vec3d::ZERO, Vec3d::UNDEFINED } )
|
||||
{
|
||||
Camera c;
|
||||
c.setViewport( 0, 0, 100, 100 );
|
||||
c.fitView( bb, dir, Vec3d( 0, 0, 1 ), 0.9 );
|
||||
|
||||
EXPECT_NEAR( c.direction().length(), 1.0, 1e-6 );
|
||||
EXPECT_NEAR( c.up().length(), 1.0, 1e-6 );
|
||||
EXPECT_NEAR( c.right().length(), 1.0, 1e-6 );
|
||||
}
|
||||
}
|
||||
@@ -43,10 +43,23 @@
|
||||
#include "cvfBoundingBox.h"
|
||||
#include "cvfGeometryUtils.h"
|
||||
|
||||
#include <limits>
|
||||
|
||||
namespace cvf {
|
||||
|
||||
namespace {
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// A zero, undefined or non-finite view direction cannot define a view; fall back to looking along the Y axis
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
Vec3d validViewDirection(const Vec3d& dir)
|
||||
{
|
||||
const double length = dir.length();
|
||||
if (!dir.isUndefined() && length > 0.0 && length < std::numeric_limits<double>::max()) return dir;
|
||||
|
||||
return Vec3d::Y_AXIS;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Returns an up vector guaranteed to be non-parallel to dir. If the passed up vector is already
|
||||
/// non-parallel to dir, it is returned unchanged. Otherwise a corrected, orthogonal up vector is
|
||||
@@ -310,8 +323,10 @@ void Camera::setProjectionAsPixelExact2D()
|
||||
/// the view to. The relativeDistance parameter specifies the distance from the camera to the
|
||||
/// center of the bounding box
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void Camera::fitView(const BoundingBox& boundingBox, const Vec3d& dir, const Vec3d& up, double coverageFactor)
|
||||
void Camera::fitView(const BoundingBox& boundingBox, const Vec3d& dirIn, const Vec3d& up, double coverageFactor)
|
||||
{
|
||||
const cvf::Vec3d dir = validViewDirection(dirIn);
|
||||
|
||||
// dir and up may be parallel (degenerate camera orientation); derive a corrected, non-parallel
|
||||
// up vector so both the eye computation and the final look-at matrix use a consistent basis.
|
||||
cvf::Vec3d correctedUp = nonParallelUpVector(dir, up);
|
||||
@@ -327,8 +342,10 @@ void Camera::fitView(const BoundingBox& boundingBox, const Vec3d& dir, const Vec
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
Vec3d Camera::computeFitViewEyePosition(const BoundingBox& boundingBox, const Vec3d& dir, const Vec3d& up, double coverageFactor, double fieldOfViewYDeg, double aspectRatio)
|
||||
Vec3d Camera::computeFitViewEyePosition(const BoundingBox& boundingBox, const Vec3d& dirIn, const Vec3d& up, double coverageFactor, double fieldOfViewYDeg, double aspectRatio)
|
||||
{
|
||||
const cvf::Vec3d dir = validViewDirection(dirIn);
|
||||
|
||||
cvf::Vec3d corners[8];
|
||||
boundingBox.cornerVertices(corners);
|
||||
|
||||
|
||||
Reference in new issue
Block a user