-1

On my rootEntity I have 2 entities (parents) which are composed of multiple entities (child). I'd like to have one QObjectPicker but working only for some entities.

For the moment I have my QObjectPicker that I add to the rootEntity and that detect picking for all my entities on screen (it detect child when I click on it). But I want that some of the child become not pickable.

My first idea was to share the QObjectPicker for all the entities that require it (for all the child that need to be pickable). But a QObjectPicker is not a sharable object. Is there a way to do what I want?

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

Edit 1 :

I tried to use the QNoPicking class in my framegraph like suggested by Florian Blume. But I can't find a way to make it work.

here is an example:

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 class

#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, 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, 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, [this](Qt3DRender::QPickEvent* event) {
        qDebug() << "clicked";
    });
}

Even without the renderStateSet set as QLayerFilter's parent and with different parent I can't make it work... either everything is pickable, either there is only the pickable entity that are displayed (or the opposite)

I even tried with 2 pickerLayer, but I can't get it work

Any idea?

Jason Aller
  • 3,541
  • 28
  • 38
  • 38
Romain
  • 44
  • 6
  • 1
    It's difficult to tell from your example what you're doing wrong. Please provide a [minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example). – Florian Blume Nov 24 '20 at 15:51

1 Answers1

0

You can use the QNoPicking class in your framegraph together with a layer filter and a layer which you add to the entity you want to prevent the QObjectPicker from picking.

Florian Blume
  • 3,237
  • 17
  • 37
  • I understand it would be something like this right : Qt3DRender::QLayerFilter * pickingFilter = new Qt3DRender::QLayerFilter(cameraSelector); pickingFilter->addLayer(this->pickingLayer); Qt3DRender::QNoPicking * noPicking = new Qt3DRender::QNoPicking(pickingFilter); – Romain Nov 09 '20 at 15:02
  • Yes exactly and then you have to add the pickingFilter layer to the objects you don't want to pick. The `QNoPicking` node should be a leaf node I guess because you don't want different framegraph branches for picked and non-picked objects. – Florian Blume Nov 09 '20 at 15:10
  • Hey ! I just edit my post because i can't make it work. If you have some times :) – Romain Nov 24 '20 at 11:48