Qt3D: QObjectPicker test not working as expected



  • Hi,

    I'm trying to make picking work with a simple C++ widget application, using QtCreator 4.2.1 and Qt 5.8.0

    The example creates two spheres, a green one at 0,0,0 and a red one at -20, 0, 0

    No matter where I click in the 3D space, the green one is hit by the picker ray, no matter what.

    However, if I rotate the scene so that the red sphere is exactly in front of the green sphere, the ray hits the red one. Again, no matter what or where I click.

    Basically, it seems that the ray always goes from the camera to origo (0,0,0) regardless of where I click with the mouse.

    Any tips out there on what I'm forgetting, or doing wrong?

    Here is the .cpp file of the example:

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    
    #include <Qt3DCore/QEntity>
    #include <Qt3DRender/QCamera>
    #include <Qt3DRender/QCameraLens>
    #include <Qt3DRender/QRenderSettings>
    #include <Qt3DRender/QObjectPicker>
    #include <Qt3DExtras/QForwardRenderer>
    #include <Qt3DExtras/Qt3DWindow>
    #include <Qt3DExtras/QOrbitCameraController>
    #include <Qt3DExtras/QSphereMesh>
    #include <Qt3DCore/QTransform>
    #include <Qt3DExtras/QPhongMaterial>
    
    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
    
    
        Qt3DExtras::Qt3DWindow *mView = new Qt3DExtras::Qt3DWindow();
        QWidget *mContainerScene = QWidget::createWindowContainer(mView, this);
        ui->layoutScene->addWidget(mContainerScene);
    
        Qt3DRender::QCamera *mCamera = mView->camera();
        mCamera->setProjectionType(Qt3DRender::QCameraLens::PerspectiveProjection);
        //mCamera->setAspectRatio(mView->width() / mView->height());
        mCamera->setAspectRatio(16.0f / 9.0f);
        mCamera->setFieldOfView(45.0f);
        mCamera->setUpVector(QVector3D(0.0f, 1.0f, 0.0f));
        mCamera->setPosition(QVector3D(0.0f, 20.0f, 80.0f));
        mCamera->setViewCenter(QVector3D(0.0f, 0.0f, 0.0f));
        mCamera->setNearPlane(0.01f);
        mCamera->setFarPlane(100000.0f);
    
        mView->defaultFrameGraph()->setClearColor(QColor(0, 0, 0));
    
        Qt3DRender::QRenderSettings *mRenderSettings = new Qt3DRender::QRenderSettings();
        mRenderSettings->pickingSettings()->setPickMethod(Qt3DRender::QPickingSettings::TrianglePicking);
        mRenderSettings->pickingSettings()->setPickResultMode(Qt3DRender::QPickingSettings::NearestPick);
        mRenderSettings->setActiveFrameGraph(mView->defaultFrameGraph());
    
        Qt3DCore::QEntity *mSceneEntity = new Qt3DCore::QEntity();
        mSceneEntity->addComponent(mRenderSettings);
        mSceneEntity->setObjectName(QStringLiteral("scene entity"));
    
        Qt3DExtras::QOrbitCameraController *mCameraController =
                new Qt3DExtras::QOrbitCameraController(mSceneEntity);
        mCameraController->setLinearSpeed(50.0f);
        mCameraController->setLookSpeed(180.0f);
        mCameraController->setCamera(mCamera);
    
        // Create entity 1
        Qt3DCore::QEntity *entity1 = new Qt3DCore::QEntity(mSceneEntity);
        entity1->setObjectName("entity 1");
    
        Qt3DExtras::QSphereMesh *mMesh1 = new Qt3DExtras::QSphereMesh(entity1);
        mMesh1->setRadius(1.0f);
        entity1->addComponent(mMesh1);
    
        Qt3DCore::QTransform *mTransform1 = new Qt3DCore::QTransform(entity1);
        mTransform1->setTranslation(QVector3D(0, 0, 0));
        mTransform1->setScale(1);
        mTransform1->setScale3D(QVector3D(1, 1, 1));
        entity1->addComponent(mTransform1);
    
        Qt3DExtras::QPhongMaterial *mMaterial1 = new Qt3DExtras::QPhongMaterial(entity1);
        QColor color(0, 255, 0);
        mMaterial1->setDiffuse(color);
        mMaterial1->setSpecular(color);
        mMaterial1->setAmbient(color);
        mMaterial1->setShininess(5.0f);
        entity1->addComponent(mMaterial1);
    
        Qt3DRender::QObjectPicker *picker1 = new Qt3DRender::QObjectPicker(entity1);
        picker1->setHoverEnabled(false);
        picker1->setEnabled(true);
        QObject::connect(picker1, &Qt3DRender::QObjectPicker::pressed, this, &MainWindow::onPicked);
        entity1->addComponent(picker1);
    
        // Create entity 2
        Qt3DCore::QEntity *entity2 = new Qt3DCore::QEntity(mSceneEntity);
        entity2->setObjectName("entity 2");
    
        Qt3DExtras::QSphereMesh *mMesh2 = new Qt3DExtras::QSphereMesh(entity2);
        mMesh2->setRadius(1.0f);
        entity2->addComponent(mMesh2);
    
        Qt3DCore::QTransform *mTransform2 = new Qt3DCore::QTransform(entity2);
        mTransform2->setTranslation(QVector3D(-20, 0, 0));
        mTransform2->setScale(1);
        mTransform2->setScale3D(QVector3D(1, 1, 1));
        entity2->addComponent(mTransform2);
    
        Qt3DExtras::QPhongMaterial *mMaterial2 = new Qt3DExtras::QPhongMaterial(entity2);
        QColor color2(255, 0, 0);
        mMaterial2->setDiffuse(color2);
        mMaterial2->setSpecular(color2);
        mMaterial2->setAmbient(color2);
        mMaterial2->setShininess(5.0f);
        entity2->addComponent(mMaterial2);
    
        Qt3DRender::QObjectPicker *picker2 = new Qt3DRender::QObjectPicker(entity2);
        picker2->setHoverEnabled(false);
        picker2->setEnabled(true);
        QObject::connect(picker2, &Qt3DRender::QObjectPicker::pressed, this, &MainWindow::onPicked);
        entity2->addComponent(picker2);
    
        mView->setRootEntity(mSceneEntity);
        mView->show();
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    
    void MainWindow::onPicked(Qt3DRender::QPickEvent *evt)
    {
        Qt3DCore::QEntity *entity = qobject_cast<Qt3DCore::QEntity*>(sender()->parent());
        qDebug() << "Picked " << entity->objectName();
    }
    


  • Not sure what is going on here but not creating a RenderSetting and not setting the camera aspect ratio and FOW solved the issue.
    By creating a custom RenderSettings I may have ended up with a orthogonal projection or something.

    Here is a working example:

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    
    #include <Qt3DCore/QEntity>
    #include <Qt3DRender/QCamera>
    #include <Qt3DRender/QCameraLens>
    #include <Qt3DRender/QObjectPicker>
    #include <Qt3DExtras/QForwardRenderer>
    #include <Qt3DExtras/Qt3DWindow>
    #include <Qt3DExtras/QOrbitCameraController>
    #include <Qt3DExtras/QSphereMesh>
    #include <Qt3DCore/QTransform>
    #include <Qt3DExtras/QPhongMaterial>
    
    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
    
        Qt3DExtras::Qt3DWindow *view = new Qt3DExtras::Qt3DWindow();
        QWidget *containerScene = QWidget::createWindowContainer(view, this);
        ui->layoutScene->addWidget(containerScene);
    
        Qt3DRender::QCamera *camera = view->camera();
        camera->setProjectionType(Qt3DRender::QCameraLens::PerspectiveProjection);
        camera->setUpVector(QVector3D(0.0f, 1.0f, 0.0f));
        camera->setPosition(QVector3D(0.0f, 20.0f, 80.0f));
        camera->setViewCenter(QVector3D(0.0f, 0.0f, 0.0f));
    
        view->defaultFrameGraph()->setClearColor(QColor(0, 0, 0));
    
        Qt3DCore::QEntity *sceneEntity = new Qt3DCore::QEntity();
    
        Qt3DExtras::QOrbitCameraController *cameraController =
                new Qt3DExtras::QOrbitCameraController(sceneEntity);
        cameraController->setLinearSpeed(50.0f);
        cameraController->setLookSpeed(180.0f);
        cameraController->setCamera(camera);
    
        // Create entity 1
        Qt3DCore::QEntity *entity1 = new Qt3DCore::QEntity(sceneEntity);
        entity1->setObjectName("entity 1");
    
        Qt3DExtras::QSphereMesh *mesh1 = new Qt3DExtras::QSphereMesh(entity1);
        mesh1->setRadius(1.0f);
        entity1->addComponent(mesh1);
    
        Qt3DCore::QTransform *transform1 = new Qt3DCore::QTransform(entity1);
        transform1->setTranslation(QVector3D(0, 0, 0));
        transform1->setScale(1);
        transform1->setScale3D(QVector3D(1, 1, 1));
        entity1->addComponent(transform1);
    
        Qt3DExtras::QPhongMaterial *material1 = new Qt3DExtras::QPhongMaterial(entity1);
        QColor color(0, 255, 0);
        material1->setDiffuse(color);
        material1->setSpecular(color);
        material1->setAmbient(color);
        material1->setShininess(5.0f);
        entity1->addComponent(material1);
    
        Qt3DRender::QObjectPicker *picker1 = new Qt3DRender::QObjectPicker(entity1);
        picker1->setHoverEnabled(false);
        picker1->setEnabled(true);
        QObject::connect(picker1, &Qt3DRender::QObjectPicker::pressed, this, &MainWindow::onPicked);
        entity1->addComponent(picker1);
    
        // Create entity 2
        Qt3DCore::QEntity *entity2 = new Qt3DCore::QEntity(sceneEntity);
        entity2->setObjectName("entity 2");
    
        Qt3DExtras::QSphereMesh *mesh2 = new Qt3DExtras::QSphereMesh(entity2);
        mesh2->setRadius(1.0f);
        entity2->addComponent(mesh2);
    
        Qt3DCore::QTransform *transform2 = new Qt3DCore::QTransform(entity2);
        transform2->setTranslation(QVector3D(-20, 0, 0));
        transform2->setScale(1);
        transform2->setScale3D(QVector3D(1, 1, 1));
        entity2->addComponent(transform2);
    
        Qt3DExtras::QPhongMaterial *material2 = new Qt3DExtras::QPhongMaterial(entity2);
        QColor color2(255, 0, 0);
        material2->setDiffuse(color2);
        material2->setSpecular(color2);
        material2->setAmbient(color2);
        material2->setShininess(5.0f);
        entity2->addComponent(material2);
    
        Qt3DRender::QObjectPicker *picker2 = new Qt3DRender::QObjectPicker(entity2);
        picker2->setHoverEnabled(false);
        picker2->setEnabled(true);
        QObject::connect(picker2, &Qt3DRender::QObjectPicker::pressed, this, &MainWindow::onPicked);
        entity2->addComponent(picker2);
    
        view->setRootEntity(sceneEntity);
        view->show();
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    
    void MainWindow::onPicked(Qt3DRender::QPickEvent *evt)
    {
        Qt3DCore::QEntity *entity = qobject_cast<Qt3DCore::QEntity*>(sender()->parent());
        qDebug() << "Picked " << entity->objectName();
    }
    
    

Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.