Revert "Revert "Fix more tests""

This reverts commit 26c65500a3f606c19396eb9adbd4c64c9633b7cb.
This commit is contained in:
Nyall Dawson 2025-02-28 07:41:47 +10:00
parent 2c43f91a93
commit 9efa2da3db
5 changed files with 50 additions and 20 deletions

View File

@ -59,8 +59,12 @@ typedef Qt3DCore::QBuffer Qt3DQBuffer;
// declared here as Qgs3DTypes has no cpp file
const char *Qgs3DTypes::PROP_NAME_3D_RENDERER_FLAG = "PROP_NAME_3D_RENDERER_FLAG";
static void waitForFrame( Qgs3DMapScene *scene )
void Qgs3DUtils::waitForFrame( QgsAbstract3DEngine &engine, Qgs3DMapScene *scene )
{
// Set policy to always render frame, so we don't wait forever.
Qt3DRender::QRenderSettings::RenderPolicy oldPolicy = engine.renderSettings()->renderPolicy();
engine.renderSettings()->setRenderPolicy( Qt3DRender::QRenderSettings::RenderPolicy::Always );
// Wait for at least one frame to render
Qt3DLogic::QFrameAction *frameAction = new Qt3DLogic::QFrameAction();
scene->addComponent( frameAction );
@ -68,6 +72,8 @@ static void waitForFrame( Qgs3DMapScene *scene )
QObject::connect( frameAction, &Qt3DLogic::QFrameAction::triggered, &evLoop, &QEventLoop::quit );
evLoop.exec();
scene->removeComponent( frameAction );
engine.renderSettings()->setRenderPolicy( oldPolicy );
}
QImage Qgs3DUtils::captureSceneImage( QgsAbstract3DEngine &engine, Qgs3DMapScene *scene )
@ -78,7 +84,7 @@ QImage Qgs3DUtils::captureSceneImage( QgsAbstract3DEngine &engine, Qgs3DMapScene
// We need to change render policy to RenderPolicy::Always, since otherwise render capture node won't work
engine.renderSettings()->setRenderPolicy( Qt3DRender::QRenderSettings::RenderPolicy::Always );
waitForFrame( scene );
waitForFrame( engine, scene );
auto saveImageFcn = [&evLoop, &resImage]( const QImage &img ) {
resImage = img;
@ -124,8 +130,6 @@ QImage Qgs3DUtils::captureSceneDepthBuffer( QgsAbstract3DEngine &engine, Qgs3DMa
// We need to change render policy to RenderPolicy::Always, since otherwise render capture node won't work
engine.renderSettings()->setRenderPolicy( Qt3DRender::QRenderSettings::RenderPolicy::Always );
waitForFrame( scene );
auto requestImageFcn = [&engine, scene] {
if ( scene->sceneState() == Qgs3DMapScene::Ready )
{
@ -142,6 +146,8 @@ QImage Qgs3DUtils::captureSceneDepthBuffer( QgsAbstract3DEngine &engine, Qgs3DMa
QMetaObject::Connection conn1 = QObject::connect( &engine, &QgsAbstract3DEngine::depthBufferCaptured, saveImageFcn );
QMetaObject::Connection conn2;
// Make sure once-per-frame functions run
waitForFrame( engine, scene );
if ( scene->sceneState() == Qgs3DMapScene::Ready )
{
requestImageFcn();

View File

@ -65,6 +65,12 @@ class _3D_EXPORT Qgs3DUtils
*/
static QImage captureSceneImage( QgsAbstract3DEngine &engine, Qgs3DMapScene *scene );
/**
* Waits for a frame to be rendered. Useful to trigger once-per-frame updates
* \since QGIS 3.42
*/
static void waitForFrame( QgsAbstract3DEngine &engine, Qgs3DMapScene *scene );
/**
* Captures the depth buffer of the current 3D scene of a 3D engine. The function waits
* until the scene is not fully loaded/updated before capturing the image.

View File

@ -572,6 +572,7 @@ void QgsCameraController::onWheel( Qt3DInput::QWheelEvent *wheel )
if ( mCurrentOperation != MouseOperation::ZoomWheel )
{
setMouseParameters( MouseOperation::ZoomWheel );
// The actual zooming will happen after we get a new depth buffer
}
else
{

View File

@ -52,6 +52,8 @@ class TestQgs3DCameraController : public QgsTest
void testRotationCenterRotationCameraRotationCenter();
private:
void waitForNearPlane( QgsOffscreen3DEngine &engine, Qgs3DMapScene *scene, float atLeast ); //#spellok
QgsRasterLayer *mLayerRgb = nullptr;
QgsVectorLayer *mLayerBuildings = nullptr;
};
@ -455,14 +457,13 @@ void TestQgs3DCameraController::testRotationCenterZoomWheelRotationCenter()
// look from the top
scene->cameraController()->setLookingAtPoint( QgsVector3D( 0, 0, 0 ), 2500, 0, 0 );
waitForNearPlane( engine, scene, 1000 );
QVector3D initialCamViewCenter = scene->cameraController()->camera()->viewCenter();
QVector3D initialCamPosition = scene->cameraController()->camera()->position();
float initialPitch = scene->cameraController()->pitch();
float initialYaw = scene->cameraController()->yaw();
// this call is not used but ensures to synchronize the scene
Qgs3DUtils::captureSceneImage( engine, scene );
QMouseEvent mousePressEvent( QEvent::MouseButtonPress, midPos, Qt::LeftButton, Qt::LeftButton, Qt::ShiftModifier );
scene->cameraController()->onMousePressed( new Qt3DInput::QMouseEvent( mousePressEvent ) );
@ -522,9 +523,9 @@ void TestQgs3DCameraController::testRotationCenterZoomWheelRotationCenter()
depthImage = Qgs3DUtils::captureSceneDepthBuffer( engine, scene );
scene->cameraController()->depthBufferCaptured( depthImage );
QGSCOMPARENEARVECTOR3D( scene->cameraController()->mZoomPoint, QVector3D( 283.2, -923.1, -27.0 ), 1.5 );
QGSCOMPARENEARVECTOR3D( scene->cameraController()->cameraPose().centerPoint(), QVector3D( 99.4, -319.9, -8.8 ), 2.0 );
QGSCOMPARENEAR( scene->cameraController()->cameraPose().distanceFromCenterPoint(), 1631.9, 2.0 );
QGSCOMPARENEARVECTOR3D( scene->cameraController()->mZoomPoint, QVector3D( 312.936, -950.772, -125.381 ), 3.0 );
QGSCOMPARENEARVECTOR3D( scene->cameraController()->cameraPose().centerPoint(), QVector3D( 109.8, -329.4, -43.3 ), 3.0 );
QGSCOMPARENEAR( scene->cameraController()->cameraPose().distanceFromCenterPoint(), 1631.9, 3.0 );
QCOMPARE( scene->cameraController()->pitch(), initialPitch );
QCOMPARE( scene->cameraController()->yaw(), initialYaw );
QCOMPARE( scene->cameraController()->mCumulatedWheelY, 0 );
@ -540,6 +541,7 @@ void TestQgs3DCameraController::testRotationCenterZoomWheelRotationCenter()
initialPitch = scene->cameraController()->pitch();
initialYaw = scene->cameraController()->yaw();
Qgs3DUtils::waitForFrame( engine, scene );
// the first mouse event only updates the mouse position
// the second one will update the camera
QMouseEvent mouseMoveEvent3( QEvent::MouseMove, midPos + movement1 + movement2, Qt::LeftButton, Qt::LeftButton, Qt::ShiftModifier );
@ -558,9 +560,9 @@ void TestQgs3DCameraController::testRotationCenterZoomWheelRotationCenter()
QCOMPARE( scene->cameraController()->mCurrentOperation, QgsCameraController::MouseOperation::RotationCenter );
diffViewCenter = scene->cameraController()->camera()->viewCenter() - initialCamViewCenter;
QGSCOMPARENEARVECTOR3D( diffViewCenter, QVector3D( 25.9, 7.1, 5.2 ), 1.0 );
QGSCOMPARENEARVECTOR3D( diffViewCenter, QVector3D( 26.9, 7.3, 5.4 ), 2.0 );
diffPosition = scene->cameraController()->camera()->position() - initialCamPosition;
QGSCOMPARENEARVECTOR3D( diffPosition, QVector3D( -44.3, -9.1, -11.7 ), 1.0 );
QGSCOMPARENEARVECTOR3D( diffPosition, QVector3D( -43.2, -9.1, -11.1 ), 1.0 );
diffPitch = scene->cameraController()->pitch() - initialPitch;
diffYaw = scene->cameraController()->yaw() - initialYaw;
QGSCOMPARENEAR( diffPitch, 2.5, 0.1 );
@ -598,14 +600,13 @@ void TestQgs3DCameraController::testTranslateRotationCenterTranslate()
// look from the top
scene->cameraController()->setLookingAtPoint( QgsVector3D( 0, 0, 0 ), 2500, 0, 0 );
waitForNearPlane( engine, scene, 1000 );
QVector3D initialCamViewCenter = scene->cameraController()->camera()->viewCenter();
QVector3D initialCamPosition = scene->cameraController()->camera()->position();
float initialPitch = scene->cameraController()->pitch();
float initialYaw = scene->cameraController()->yaw();
// this call is not used but ensures to synchronize the scene
Qgs3DUtils::captureSceneImage( engine, scene );
//
// 1. Translate
//
@ -751,14 +752,12 @@ void TestQgs3DCameraController::testTranslateZoomWheelTranslate()
// look from the top
scene->cameraController()->setLookingAtPoint( QgsVector3D( 0, 0, 0 ), 2500, 0, 0 );
waitForNearPlane( engine, scene, 1000 );
QVector3D initialCamViewCenter = scene->cameraController()->camera()->viewCenter();
QVector3D initialCamPosition = scene->cameraController()->camera()->position();
float initialPitch = scene->cameraController()->pitch();
float initialYaw = scene->cameraController()->yaw();
// this call is not used but ensures to synchronize the scene
Qgs3DUtils::captureSceneImage( engine, scene );
//
// 1. Translate
//
@ -857,9 +856,9 @@ void TestQgs3DCameraController::testTranslateZoomWheelTranslate()
QCOMPARE( scene->cameraController()->mCurrentOperation, QgsCameraController::MouseOperation::Translation );
diffViewCenter = scene->cameraController()->camera()->viewCenter() - initialCamViewCenter;
QGSCOMPARENEARVECTOR3D( diffViewCenter, QVector3D( -11.3, 11.3, 0.0 ), 1.0 );
QGSCOMPARENEARVECTOR3D( diffViewCenter, QVector3D( -17.2, 17.2, 0.0 ), 1.0 );
diffPosition = scene->cameraController()->camera()->position() - initialCamPosition;
QGSCOMPARENEARVECTOR3D( diffPosition, QVector3D( -11.3, 11.3, 0.0 ), 1.0 );
QGSCOMPARENEARVECTOR3D( diffPosition, QVector3D( -17.2, 17.2, 0.0 ), 1.0 );
QCOMPARE( scene->cameraController()->pitch(), initialPitch );
QCOMPARE( scene->cameraController()->yaw(), initialYaw );
@ -1173,5 +1172,20 @@ void TestQgs3DCameraController::testRotationCenterRotationCameraRotationCenter()
mapSettings->setLayers( {} );
}
void TestQgs3DCameraController::waitForNearPlane( QgsOffscreen3DEngine &engine, Qgs3DMapScene *scene, float atLeast ) //#spellok
{
// XXX: Sometimes the near/far planes aren't calculated correctly, so they're
// left at the too-deep default. This causes the rest of the test to fail in
// weird ways every once in a while, so loop until we get good values.
do
{
// Force recalcualtion of near/far planes.
scene->cameraController()->mCameraChanged = true;
// this call is not used but ensures to synchronize the scene
Qgs3DUtils::captureSceneImage( engine, scene );
} while ( scene->cameraController()->camera()->nearPlane() < atLeast ); //#spellok
}
QGSTEST_MAIN( TestQgs3DCameraController )
#include "testqgs3dcameracontroller.moc"

View File

@ -2118,6 +2118,7 @@ void TestQgs3DRendering::testDepthBuffer()
QGSVERIFYIMAGECHECK( "depth_wheel_action_1", "depth_wheel_action_1", grayImage, QString(), 5, QSize( 0, 0 ), 2 );
scene->cameraController()->depthBufferCaptured( depthImage );
Qgs3DUtils::waitForFrame( engine, scene );
QGSCOMPARENEARVECTOR3D( scene->cameraController()->mZoomPoint, QVector3D( -32.7, -185.5, 224.6 ), 1.0 );
QGSCOMPARENEARVECTOR3D( scene->cameraController()->cameraPose().centerPoint(), QVector3D( -6.8, -38.6, 46.7 ), 1.0 );
@ -2135,6 +2136,7 @@ void TestQgs3DRendering::testDepthBuffer()
QGSVERIFYIMAGECHECK( "depth_wheel_action_2", "depth_wheel_action_2", grayImage, QString(), 5, QSize( 0, 0 ), 2 );
scene->cameraController()->depthBufferCaptured( depthImage );
Qgs3DUtils::waitForFrame( engine, scene );
QGSCOMPARENEARVECTOR3D( scene->cameraController()->mZoomPoint, QVector3D( -32.5, -184.7, 223.5 ), 1.0 );
QGSCOMPARENEARVECTOR3D( scene->cameraController()->cameraPose().centerPoint(), QVector3D( -12.1, -69.0, 83.5 ), 1.0 );
@ -2152,6 +2154,7 @@ void TestQgs3DRendering::testDepthBuffer()
QGSVERIFYIMAGECHECK( "depth_wheel_action_3", "depth_wheel_action_3", grayImage, QString(), 5, QSize( 0, 0 ), 2 );
scene->cameraController()->depthBufferCaptured( depthImage );
Qgs3DUtils::waitForFrame( engine, scene );
QGSCOMPARENEARVECTOR3D( scene->cameraController()->mZoomPoint, QVector3D( -32.4, -184.1, 222.8 ), 1.0 );
QGSCOMPARENEARVECTOR3D( scene->cameraController()->cameraPose().centerPoint(), QVector3D( -29.0, -164.9, 199.6 ), 1.0 );