首页 > 解决方案 > 如果还没有另一个具有 ObjectPicker 的实体,则 ObjectPicker 不适用于动态创建的实体

问题描述

我有一个我通过这个助手类的插槽Scene3D动态添加一个实体的地方:ObjectPickerScene3DViewHelper::addCuboid()

场景3dviewhelper.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
    }
}

主.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();
}

问题是它ObjectPicker不起作用:当我单击长方体时,我应该在控制台上看到“单击的实体 Qt3DCore::QEntity(0x7fa19f005300)”消息,但我没有看到它。

如果我取消对cuboid0实体的注释,则选取对cuboid0实体和动态创建的长方体都有效:

qml: 点击实体 Qt3DCore::Quick::Quick3DEntity(0x7fa0d7c025e0)

点击实体 Qt3DCore::QEntity(0x7fa0d6527f10)

在 QML 中创建实体有什么我没有做的void Scene3DViewHelper::addCuboid()

标签: qtqmlqt3d

解决方案


推荐阅读