ObjectPicker doesn't work for a dynamically created entity if there isn't already another entity with ObjectPicker
Asked Answered
W

0

6

I have a Scene3D where I dynamically add an entity which has an ObjectPicker, via this helper class' Scene3DViewHelper::addCuboid() slot:

scene3dviewhelper.h:

#ifndef SCENE3DVIEWHELPER_H
#define SCENE3DVIEWHELPER_H

#include <Qt3DCore/QEntity>

class Scene3DViewHelper : public QObject
{
    Q_OBJECT
public:
    Q_PROPERTY(Qt3DCore::QEntity * rootEntity READ rootEntity WRITE setRootEntity NOTIFY rootEntityChanged)

    explicit Scene3DViewHelper(QObject *parent = nullptr);

    Qt3DCore::QEntity * rootEntity() const;

public slots:
    void setRootEntity(Qt3DCore::QEntity *rootEntity);
    void addCuboid();

signals:
    void rootEntityChanged(Qt3DCore::QEntity *rootEntity);

private:
    Qt3DCore::QEntity *rootEntity_;
};

#endif // SCENE3DVIEWHELPER_H

scene3dviewhelper.cpp:

#include "scene3dviewhelper.h"
#include <Qt3DCore>
#include <Qt3DRender>
#include <Qt3DExtras>

Scene3DViewHelper::Scene3DViewHelper(QObject *parent) : QObject(parent) {}

Qt3DCore::QEntity * Scene3DViewHelper::rootEntity() const { return rootEntity_; }

void Scene3DViewHelper::setRootEntity(Qt3DCore::QEntity *rootEntity)
{
    auto old = rootEntity_;
    rootEntity_ = rootEntity;
    if(rootEntity_ != old) emit rootEntityChanged(rootEntity);
}

void Scene3DViewHelper::addCuboid()
{
    if(!rootEntity_) return;
    auto cuboidEntity = new Qt3DCore::QEntity(rootEntity_);
    auto mat = new Qt3DExtras::QPhongMaterial(cuboidEntity);
    mat->setDiffuse(QColor(217, 217, 255));
    auto t = new Qt3DCore::QTransform(cuboidEntity);
    auto mesh = new Qt3DExtras::QCuboidMesh(cuboidEntity);
    auto picker = new Qt3DRender::QObjectPicker(cuboidEntity);
    connect(picker, &Qt3DRender::QObjectPicker::clicked, [=] {
        qDebug() << "clicked entity" << cuboidEntity;
    });
    mesh->setXExtent(1);
    mesh->setYExtent(1);
    mesh->setZExtent(1);
    cuboidEntity->addComponent(mat);
    cuboidEntity->addComponent(t);
    cuboidEntity->addComponent(mesh);
    cuboidEntity->addComponent(picker);
}

Scene3DView.qml:

import QtQuick.Scene3D 2.0
import Qt3D.Core 2.0
import Qt3D.Render 2.14
import Qt3D.Input 2.0
import Qt3D.Logic 2.0
import Qt3D.Extras 2.0

import Qt3DUtils 1.0

Scene3D {
    id: scene3d
    aspects: ["render", "logic", "input"]
    hoverEnabled: true // needed for ObjectPickers to handle hover events
    property alias helper: helper
    
    data: Scene3DViewHelper {
        id: helper
        rootEntity: rootEntity
    }

    entity: Entity {
        id: rootEntity
        components: [
            RenderSettings {
                ForwardRenderer {
                    id: forwardRenderer
                    camera: mainCamera
                }
                pickingSettings.pickMethod: PickingSettings.TrianglePicking
                pickingSettings.pickResultMode: PickingSettings.AllPicks
                pickingSettings.faceOrientationPickingMode: PickingSettings.FrontAndBackFace
            },
            InputSettings {}
        ]
    
        Camera {
            id: mainCamera
            projectionType: CameraLens.PerspectiveProjection
            fieldOfView: 45
            aspectRatio: 16/9
            nearPlane : 0.1
            farPlane : 1000.0
            position: Qt.vector3d(0.0, 0.0, -4.0)
            upVector: Qt.vector3d(0.0, 1.0, 0.0)
            viewCenter: Qt.vector3d(0.0, 0.5, 0.0)
        }

        /*Entity {
            id: cuboid0
            components: [
                CuboidMesh {
                    xExtent: 1
                    yExtent: 1
                    zExtent: 1
                },
                Transform {
                    translation.x: -1.5
                },
                PhongMaterial {
                    diffuse: Qt.rgba(0.85, 0.85, 1, 1)
                },
                ObjectPicker {
                    onClicked: console.log("clicked entity", cuboid0)
                }
            ]
        }*/
    }
}

main.qml:

import QtQuick.Window 2.13 as QtQuick
    
ApplicationWindow {
    id: mainWindow
    visible: true
    width: 1000
    height: 700

    MainMenu {
        onAddCuboid: scene3d.helper.addCuboid()
    }

    Scene3DView {
        id: scene3d
        anchors.fill: parent
    }
}

main.cpp:

#include <QApplication>
#include <QQmlApplicationEngine>

#include "scene3dviewhelper.h"

int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    QApplication app(argc, argv);
    qmlRegisterType<Scene3DViewHelper>("Qt3DUtils", 1, 0, "Scene3DViewHelper");
    const QUrl mainUrl(QStringLiteral("qrc:/main.qml"));
    QQmlApplicationEngine engine;
    QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                     &app, [&](QObject *obj, const QUrl &objUrl) {
        if(!obj && mainUrl == objUrl)
            QCoreApplication::exit(-1);
    }, Qt::QueuedConnection);
    engine.load(mainUrl);
    return app.exec();
}

The problem is that the ObjectPicker doesn't work: I'm supposed to see the "clicked entity Qt3DCore::QEntity(0x7fa19f005300)" message on the console when I click the cuboid, but I don't see it.

If I uncomment the cuboid0 entity, then picking works both for the cuboid0 entity and for the dynamically created cuboid:

qml: clicked entity Qt3DCore::Quick::Quick3DEntity(0x7fa0d7c025e0)

clicked entity Qt3DCore::QEntity(0x7fa0d6527f10)

What does creating the Entity in QML do that I don't do in void Scene3DViewHelper::addCuboid()?

Williford answered 3/3, 2020 at 14:19 Comment(7)
Does it happen for pressed signal too? Using connect(picker, &Qt3DRender::QObjectPicker::pressed, ...);Autolycus
Yes, also pressed is not received if the static (cuboid0) entity is not present. Strangely, if cuboid0 is present, pressed is received twice on the dynamically created entity.Williford
Another interesting fact is that is enough to add cuboid0 with enabled: false, and picking will work on the dynamically created entity.Williford
What's the Qt version you are using - 5.14.1? Can you try to build against 5.13.2? Does that change behaviour? I was facing something similar like bugreports.qt.io/browse/QTBUG-82269 but did not nail it down to the exact reason.Coptic
I think @Coptic is right. Try Qt LTS versions like 5.12.7 and see if behavior is the same.Autolycus
Right. I tried with 5.12.5 and it does not happen.Williford
Removing hoverEnabled: true makes the issue go awayWilliford

© 2022 - 2024 — McMap. All rights reserved.