Files
ResInsight/ApplicationLibCode/UnitTests/CvfCameraCrashTriage-Test.cpp
T
Magne Sjaastad 63eaa1266d Address review feedback on crash-fix batch
- Camera::fitView/computeFitViewEyePosition: derive one corrected, non-parallel up vector and use it consistently for right, upNorm, planeTop and the final setFromLookAt(), instead of only repairing the right vector. Previously the degenerate (parallel dir/up) case still produced a singular view matrix because up itself was never corrected. Added a regression test exercising fitView() end-to-end (not just computeFitViewEyePosition()) that checks the resulting direction/up/right form a valid orthonormal basis.
- RimViewController::updateCameraLink/updateTimeStepLink: guard against ownerViewLinker()->masterView() being null (RimViewLinker::setMasterView(nullptr) is a supported state), not only against a null view linker.
- RicHistogramPlotTools: use RiaGuiApplication::isRunning() before calling RiaGuiApplication::instance(), since instance() itself asserts when there is no running GUI application.
- RimDockWindowController::updateViewerWidget: create the view widget before the dock widget, so a failed view-widget creation does not leave a dock widget allocated without a dock manager (which deleteDockWidget() cannot clean up).
- RimStimPlanModelCalculator::calculateFormation: avoid continue via a small lambda, and reject double values outside the range of int before the static_cast to avoid undefined behavior.
2026-10-05 19:56:10 +02:00

72 lines
2.8 KiB
C++

#include "gtest/gtest.h"
#include "cvfBoundingBox.h"
#include "cvfCamera.h"
using namespace cvf;
//--------------------------------------------------------------------------------------------------
/// computeFitViewEyePosition() used to assert/abort (CVF_ASSERT in Plane::distanceToOrigin) when
/// the view direction and up vector are parallel: dir^up then becomes a zero vector, producing an
/// invalid (zero-normal) plane used internally. Reproduces the crash reported from
/// caf::Viewer::zoomAll() with a degenerate camera orientation.
//--------------------------------------------------------------------------------------------------
TEST( CvfCameraCrashTriageTest, FitViewWithParallelDirAndUpDoesNotCrash )
{
Camera c;
BoundingBox bb;
bb.add( Vec3d( 0, 0, 0 ) );
bb.add( Vec3d( 1, 1, 1 ) );
Vec3d inViewDir( 0, 0, 1 );
Vec3d inUp( 0, 0, 1 );
double coverageFactor = 0.9;
Vec3d eye = Camera::computeFitViewEyePosition( bb, inViewDir, inUp, coverageFactor, c.fieldOfViewYDeg(), 1.0 );
EXPECT_FALSE( eye.isUndefined() );
}
//--------------------------------------------------------------------------------------------------
/// fitView() must also produce a valid, non-singular camera orientation when dir and up are
/// parallel: it uses the (uncorrected) up vector both for setFromLookAt() and internally in
/// computeFitViewEyePosition()/createLookAtMatrix(), so the whole up vector derivation must be
/// consistent, not only the right vector used to compute the eye position.
//--------------------------------------------------------------------------------------------------
TEST( CvfCameraCrashTriageTest, FitViewWithParallelDirAndUpProducesValidViewMatrix )
{
Camera c;
c.setViewport( 0, 0, 100, 100 );
BoundingBox bb;
bb.add( Vec3d( 0, 0, 0 ) );
bb.add( Vec3d( 1, 1, 1 ) );
Vec3d inViewDir( 0, 0, 1 );
Vec3d inUp( 0, 0, 1 );
double coverageFactor = 0.9;
c.fitView( bb, inViewDir, inUp, coverageFactor );
Vec3d eye;
Vec3d vrp;
Vec3d up;
c.toLookAt( &eye, &vrp, &up );
EXPECT_FALSE( eye.isUndefined() );
EXPECT_FALSE( c.direction().isUndefined() );
EXPECT_FALSE( c.up().isUndefined() );
EXPECT_FALSE( c.right().isUndefined() );
// direction, up and right should form a valid, mutually orthogonal basis (within floating point
// tolerance). If the up vector correction is not applied consistently, the derived up/right
// vectors from the (singular) view matrix will be degenerate (zero length or not orthogonal).
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 );
EXPECT_NEAR( c.direction() * c.up(), 0.0, 1e-6 );
EXPECT_NEAR( c.direction() * c.right(), 0.0, 1e-6 );
EXPECT_NEAR( c.up() * c.right(), 0.0, 1e-6 );
}