Qt3D-禁用确定实体为可拾取对象将QObjectPicker设置为rootEntity

问题描述

在我的rootEntity上,我有2个实体(父级),由多个实体(子级)组成。 我想拥有一个QObjectPicker,但仅适用于某些实体。

目前,我有我的QObjectPicker,我将其添加到rootEntity并检测屏幕上所有实体的拾取情况(当我单击它时,它会检测子对象)。但是我希望其中的一些孩子变得不能被拣选。

我的第一个想法是为所有需要它的实体(对于所有需要选择的子对象)共享QObjectPicker。但是QObjectPicker不是可共享的对象。 有什么方法可以做我想要的吗?

-RootEntity
--ParentX
--- ChildX1
--- ChildX2
--ParentY
--- ChildY1
--- ChildY2

编辑1:

我尝试像Florian Blume建议的那样在我的框架图中使用Qnopicking类。 但是我找不到一种使它起作用的方法

这是一个示例:

QtPicking.h

#pragma once

#include <QtWidgets/QMainWindow>
#include "ui_QtPicking.h"

#include <QApplication>

#include <Qt3DExtras/Qt3DWindow>
#include <Qt3DRender/qframeGraphNode>
#include <Qt3DRender/QClearBuffers>
#include <Qt3DRender/QRenderSettings>
#include <Qt3DRender/QRenderSurfaceSelector>
#include <Qt3DRender/QRenderStateSet>
#include <Qt3DRender/QCullFace>
#include <Qt3DRender/QCameraSelector>
#include <Qt3DRender/QCamera>
#include <Qt3DRender/QDepthTest>
#include <Qt3DRender/QViewport>
#include <Qt3DRender/QPointSize>
#include <Qt3DRender/Qlinewidth>
#include <Qt3DRender/qframeGraphNode>
#include <Qt3DRender/QTechniqueFilter>
#include <Qt3DRender/QLayer>
#include <Qt3DRender/QLayerFilter>
#include <Qt3DRender/Qnopicking>
#include <Qt3DExtras/QSphereMesh>
#include <Qt3DCore/QTransform>
#include <Qt3DExtras/QphongMaterial>
#include <Qt3DCore/QEntity>
#include <Qt3DRender/QObjectPicker>
#include <Qt3DRender/QPickEvent>
#include <Qt3DExtras/QOrbitCameraController>

class QtPicking : public QMainWindow
{
    Q_OBJECT

public:
    QtPicking(QWidget *parent = Q_NULLPTR);

    void loadScene(Qt3DCore::QEntity * rootEntity,Qt3DRender::QLayer * nopickingLayer);

private:
    Ui::QtPickingClass ui;
};

QtPicking.cpp类

#include "QtPicking.h"

QtPicking::QtPicking(QWidget *parent)
    : QMainWindow(parent)
{
    ui.setupUi(this);

    //Qt3DWindow
    Qt3DExtras::Qt3DWindow * viewer3D = new Qt3DExtras::Qt3DWindow();
    Qt3DCore::QEntity * rootEntity = new Qt3DCore::QEntity();

    viewer3D->setRootEntity(rootEntity);
    viewer3D->setFlags(Qt::Widget);

    //insert qt3dwindow inside gui
    QWidget * WidgetViewer = QWidget::createWindowContainer(viewer3D,this,Qt::Widget);
    this->ui.layout->addWidget(WidgetViewer);

    //layer no picking
    Qt3DRender::QLayer* nopickingLayer = new Qt3DRender::QLayer();



    //************************** SETTING THE FRAMEGRAPH
    //camera
    Qt3DRender::QCamera* camera = viewer3D->camera();
    camera->setPosition(QVector3D(10,5,5));
    camera->setViewCenter(QVector3D(0,0));
    camera->setParent(rootEntity);

    Qt3DExtras::QOrbitCameraController* manipulator = new Qt3DExtras::QOrbitCameraController(rootEntity);
    manipulator->setLinearSpeed(50.f);
    manipulator->setLookSpeed(180.f);
    manipulator->setCamera(camera);

    //render settings
    Qt3DRender::QRenderSurfaceSelector* surfaceSelector = new Qt3DRender::QRenderSurfaceSelector();
    surfaceSelector->setSurface(viewer3D);

    Qt3DRender::QViewport* viewport = new Qt3DRender::QViewport(surfaceSelector);
    viewport->setnormalizedRect(QRectF(0,1.0,1.0));

    Qt3DRender::QCameraSelector* cameraSelector = new Qt3DRender::QCameraSelector(viewport);
    cameraSelector->setCamera(camera);

    Qt3DRender::QClearBuffers* clearBuffers = new Qt3DRender::QClearBuffers(cameraSelector);
    clearBuffers->setBuffers(Qt3DRender::QClearBuffers::ColorDepthBuffer);
    clearBuffers->setClearColor(Qt::white);

    //renderstate
    Qt3DRender::QRenderStateSet* renderStateSet = new Qt3DRender::QRenderStateSet(cameraSelector);

    //culling => surface
    Qt3DRender::QCullFace* cullFace = new Qt3DRender::QCullFace(renderStateSet);
    cullFace->setMode(Qt3DRender::QCullFace::NoCulling);
    renderStateSet->addRenderState(cullFace);

    //taille des points
    Qt3DRender::QPointSize* pointsize = new Qt3DRender::QPointSize(renderStateSet);
    pointsize->setSizeMode(Qt3DRender::QPointSize::Fixed);
    pointsize->setValue(2);
    renderStateSet->addRenderState(pointsize);

    Qt3DRender::QDepthTest* depthTest = new Qt3DRender::QDepthTest(renderStateSet);
    depthTest->setDepthFunction(Qt3DRender::QDepthTest::LessOrEqual);
    renderStateSet->addRenderState(depthTest);

    Qt3DRender::QLayerFilter* pickingFilter = new Qt3DRender::QLayerFilter(cameraSelector);
    pickingFilter->addLayer(nopickingLayer);

    Qt3DRender::Qnopicking* nopicking = new Qt3DRender::Qnopicking(pickingFilter);

    viewer3D->setActiveFrameGraph(surfaceSelector);


    //load scene
    loadScene(rootEntity,nopickingLayer);

}

/*  Load a scene with 1 parent entity and 2 child   
 *  The parent hold the picker. 
 *  One of the entity must be pickable and the other no. => using layerfilter
 */
void QtPicking::loadScene(Qt3DCore::QEntity* rootEntity,Qt3DRender::QLayer* nopickingLayer)
{
    //scene
    Qt3DExtras::QphongMaterial* material = new Qt3DExtras::QphongMaterial(rootEntity);
    material->setAmbient(Qt::black);

    Qt3DCore::QEntity* parentEntity = new Qt3DCore::QEntity(rootEntity);

    //first child => must be pickable
    Qt3DCore::QEntity* child1 = new Qt3DCore::QEntity(parentEntity);
    Qt3DExtras::QSphereMesh* child1Mesh = new Qt3DExtras::QSphereMesh;
    child1Mesh->seTradius(1);
    Qt3DCore::QTransform* child1Transform = new Qt3DCore::QTransform();
    child1Transform->setTranslation(QVector3D(2,2,2));
    child1->addComponent(child1Mesh);
    child1->addComponent(child1Transform);
    child1->addComponent(material);

    //second child => must NOT be pickable
    Qt3DCore::QEntity* child2 = new Qt3DCore::QEntity(parentEntity);
    Qt3DExtras::QSphereMesh* child2Mesh = new Qt3DExtras::QSphereMesh;
    child2Mesh->seTradius(2);
    child2->addComponent(child2Mesh);
    child2->addComponent(material);
    child2->addComponent(nopickingLayer);

    Qt3DRender::QObjectPicker* picker = new Qt3DRender::QObjectPicker();
    picker->setEnabled(true);
    parentEntity->addComponent(picker);

    connect(picker,&Qt3DRender::QObjectPicker::clicked,[this](Qt3DRender::QPickEvent* event) {
        qDebug() << "clicked";
    });
}

即使没有将renderStateSet设置为QLayerFilter的父级,并且将父级与其他父级设置为不同,我也无法使其正常工作... 要么一切都是可拣选的,要么只显示了可拣选实体(或相反)

我什至尝试了2个pickerLayer,但无法正常工作

有什么主意吗?

解决方法

您可以在框架图中使用QNoPicking类,并在要阻止QObjectPicker选取的实体上添加图层过滤器和图层。